[Orca-checkins] rev 107 - in trunk/orca: . config lib src docs packages packages/Storable-0.6 at 3 packages/Storable-0.6 at 3/t packages/Digest-MD5-2.07 packages/Digest-MD5-2.07/MD2 packages/Digest-MD5-2.07/MD2/t packages/Digest-MD5-2.07/t packages/Digest-MD5-2.07/hints packages/Digest-MD5-2.07/lib packages/Digest-MD5-2.07/lib/Digest packages/Digest-MD5-2.07/SHA1 packages/Digest-MD5-2.07/SHA1/t packages/Digest-MD5-2.07/SHA1/lib packages/Digest-MD5-2.07/examples packages/rrdtool-0.99.29.1 packages/rrdtool-0.99.29.1/src packages/rrdtool-0.99.29.1/contrib packages/rrdtool-0.99.29.1/contrib/log2rrd packages/rrdtool-0.99.29.1/contrib/trytime packages/rrdtool-0.99.29.1/perl-piped packages/rrdtool-0.99.29.1/perl-piped/t packages/rrdtool-0.99.29.1/perl-piped/examples packages/rrdtool-0.99.29.1/doc packages/rrdtool-0.99.29.1/perl-shared packages/rrdtool-0.99.29.1/perl-shared/t packages/rrdtool-0.99.29.1/perl-shared/examples packages/rrdtool-0.99.29.1/gd1.2 packages/Math-Interpolate-1.02 packages/Math-Interpolate-1.02/t packages/Math-Interpolate-1.02/lib packages/Math-Interpolate-1.02/lib/Math
blair at orcaware.com
blair at orcaware.com
Sat Jul 13 18:47:03 PDT 2002
Author: blair
Date: Fri, 28 Jun 2002 21:58:34 -0700
New Revision: 107
Added:
trunk/orca/NEWS
trunk/orca/config/check_for_perl_mod
trunk/orca/packages/
trunk/orca/packages/Digest-MD5-2.07/
trunk/orca/packages/Digest-MD5-2.07/Changes
trunk/orca/packages/Digest-MD5-2.07/MANIFEST
trunk/orca/packages/Digest-MD5-2.07/MD2/
trunk/orca/packages/Digest-MD5-2.07/MD2/MD2.pm
trunk/orca/packages/Digest-MD5-2.07/MD2/MD2.xs
trunk/orca/packages/Digest-MD5-2.07/MD2/Makefile.PL
trunk/orca/packages/Digest-MD5-2.07/MD2/rfc1319.txt
trunk/orca/packages/Digest-MD5-2.07/MD2/t/
trunk/orca/packages/Digest-MD5-2.07/MD2/t/md2.t
trunk/orca/packages/Digest-MD5-2.07/MD2/typemap
trunk/orca/packages/Digest-MD5-2.07/MD5.pm
trunk/orca/packages/Digest-MD5-2.07/MD5.xs
trunk/orca/packages/Digest-MD5-2.07/Makefile.PL
trunk/orca/packages/Digest-MD5-2.07/README
trunk/orca/packages/Digest-MD5-2.07/SHA1/
trunk/orca/packages/Digest-MD5-2.07/SHA1/Makefile.PL
trunk/orca/packages/Digest-MD5-2.07/SHA1/SHA1.pm
trunk/orca/packages/Digest-MD5-2.07/SHA1/SHA1.xs
trunk/orca/packages/Digest-MD5-2.07/SHA1/lib/
trunk/orca/packages/Digest-MD5-2.07/SHA1/lib/SHA.pm
trunk/orca/packages/Digest-MD5-2.07/SHA1/t/
trunk/orca/packages/Digest-MD5-2.07/SHA1/t/sha.t
trunk/orca/packages/Digest-MD5-2.07/SHA1/t/sha1.t
trunk/orca/packages/Digest-MD5-2.07/SHA1/typemap
trunk/orca/packages/Digest-MD5-2.07/examples/
trunk/orca/packages/Digest-MD5-2.07/examples/mddriver.pl
trunk/orca/packages/Digest-MD5-2.07/examples/twdigest.pl
trunk/orca/packages/Digest-MD5-2.07/hints/
trunk/orca/packages/Digest-MD5-2.07/hints/dec_osf.pl
trunk/orca/packages/Digest-MD5-2.07/hints/irix_6.pl
trunk/orca/packages/Digest-MD5-2.07/lib/
trunk/orca/packages/Digest-MD5-2.07/lib/Digest.pm
trunk/orca/packages/Digest-MD5-2.07/lib/Digest/
trunk/orca/packages/Digest-MD5-2.07/lib/Digest/HMAC.pm
trunk/orca/packages/Digest-MD5-2.07/lib/Digest/HMAC_MD5.pm
trunk/orca/packages/Digest-MD5-2.07/lib/Digest/HMAC_SHA1.pm
trunk/orca/packages/Digest-MD5-2.07/lib/MD5.pm
trunk/orca/packages/Digest-MD5-2.07/rfc1321.txt
trunk/orca/packages/Digest-MD5-2.07/rfc2104.txt
trunk/orca/packages/Digest-MD5-2.07/t/
trunk/orca/packages/Digest-MD5-2.07/t/digest.t
trunk/orca/packages/Digest-MD5-2.07/t/files.t
trunk/orca/packages/Digest-MD5-2.07/t/md5-aaa.t
trunk/orca/packages/Digest-MD5-2.07/t/md5.t
trunk/orca/packages/Digest-MD5-2.07/t/rfc2202.t
trunk/orca/packages/Digest-MD5-2.07/typemap
trunk/orca/packages/Makefile.in
trunk/orca/packages/Math-Interpolate-1.02/
trunk/orca/packages/Math-Interpolate-1.02/CHANGES
trunk/orca/packages/Math-Interpolate-1.02/MANIFEST
trunk/orca/packages/Math-Interpolate-1.02/Makefile.PL
trunk/orca/packages/Math-Interpolate-1.02/README
trunk/orca/packages/Math-Interpolate-1.02/lib/
trunk/orca/packages/Math-Interpolate-1.02/lib/Math/
trunk/orca/packages/Math-Interpolate-1.02/lib/Math/Interpolate.pm
trunk/orca/packages/Math-Interpolate-1.02/lib/Math/IntervalSearch.pm
trunk/orca/packages/Math-Interpolate-1.02/t/
trunk/orca/packages/Math-Interpolate-1.02/t/01interval.t
trunk/orca/packages/Math-Interpolate-1.02/t/02interp.t
trunk/orca/packages/Storable-0.6 at 3/
trunk/orca/packages/Storable-0.6 at 3/ChangeLog
trunk/orca/packages/Storable-0.6 at 3/MANIFEST
trunk/orca/packages/Storable-0.6 at 3/Makefile.PL
trunk/orca/packages/Storable-0.6 at 3/README
trunk/orca/packages/Storable-0.6 at 3/Storable.pm
trunk/orca/packages/Storable-0.6 at 3/Storable.xs
trunk/orca/packages/Storable-0.6 at 3/patchlevel.h
trunk/orca/packages/Storable-0.6 at 3/t/
trunk/orca/packages/Storable-0.6 at 3/t/canonical.t
trunk/orca/packages/Storable-0.6 at 3/t/dclone.t
trunk/orca/packages/Storable-0.6 at 3/t/dump.pl
trunk/orca/packages/Storable-0.6 at 3/t/forgive.t
trunk/orca/packages/Storable-0.6 at 3/t/freeze.t
trunk/orca/packages/Storable-0.6 at 3/t/retrieve.t
trunk/orca/packages/Storable-0.6 at 3/t/store.t
trunk/orca/packages/Storable-0.6 at 3/t/tied.t
trunk/orca/packages/rrdtool-0.99.29.1/
trunk/orca/packages/rrdtool-0.99.29.1/CHANGES
trunk/orca/packages/rrdtool-0.99.29.1/CONTRIBUTORS
trunk/orca/packages/rrdtool-0.99.29.1/COPYING
trunk/orca/packages/rrdtool-0.99.29.1/COPYRIGHT
trunk/orca/packages/rrdtool-0.99.29.1/MANIFEST
trunk/orca/packages/rrdtool-0.99.29.1/Makefile.dist
trunk/orca/packages/rrdtool-0.99.29.1/Makefile.in
trunk/orca/packages/rrdtool-0.99.29.1/README
trunk/orca/packages/rrdtool-0.99.29.1/TODO
trunk/orca/packages/rrdtool-0.99.29.1/config.h.in
trunk/orca/packages/rrdtool-0.99.29.1/configure
trunk/orca/packages/rrdtool-0.99.29.1/configure.in
trunk/orca/packages/rrdtool-0.99.29.1/contrib/
trunk/orca/packages/rrdtool-0.99.29.1/contrib/README
trunk/orca/packages/rrdtool-0.99.29.1/contrib/log2rrd/
trunk/orca/packages/rrdtool-0.99.29.1/contrib/log2rrd/README
trunk/orca/packages/rrdtool-0.99.29.1/contrib/log2rrd/log2rrd.pl
trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/
trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/Makefile
trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/README
trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/trytime.c
trunk/orca/packages/rrdtool-0.99.29.1/doc/
trunk/orca/packages/rrdtool-0.99.29.1/doc/GNUmakefile.in
trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDp.3
trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDp.html
trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDs.3
trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDs.html
trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.1
trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.html
trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.pod
trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.txt
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.1
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.html
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.pod
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.txt
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.1
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.html
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.pod
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.txt
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.1
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.html
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.pod
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.txt
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.1
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.html
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.pod
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.txt
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdintro.pod
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.1
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.html
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.pod
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.txt
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.1
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.html
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.pod
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.txt
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.1
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.html
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.pod
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.txt
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.1
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.html
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.pod
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.txt
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.1
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.html
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.pod
trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.txt
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/Makefile.in
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/README
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/demoin.gif
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.c
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.dsp
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.dsw
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.h
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gddemo.c
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontg.c
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontg.h
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontl.c
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontl.h
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontmb.c
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontmb.h
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfonts.c
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfonts.h
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontt.c
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontt.h
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/giftogd.c
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/index.html
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/mathmake.c
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/mtables.c
trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/webgif.c
trunk/orca/packages/rrdtool-0.99.29.1/install-sh
trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/
trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/MANIFEST
trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/Makefile.PL
trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/README
trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/RRDp.pm
trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/examples/
trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/examples/piped-demo.pl.in
trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/t/
trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/t/base.t
trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/
trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/MANIFEST
trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/Makefile.PL
trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/README
trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/RRDs.pm
trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/RRDs.xs
trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/examples/
trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/examples/shared-demo.pl.in
trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/t/
trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/t/base.t
trunk/orca/packages/rrdtool-0.99.29.1/src/
trunk/orca/packages/rrdtool-0.99.29.1/src/Makefile.in
trunk/orca/packages/rrdtool-0.99.29.1/src/getopt.c
trunk/orca/packages/rrdtool-0.99.29.1/src/getopt.h
trunk/orca/packages/rrdtool-0.99.29.1/src/getopt1.c
trunk/orca/packages/rrdtool-0.99.29.1/src/ntconfig.h
trunk/orca/packages/rrdtool-0.99.29.1/src/parsetime.c
trunk/orca/packages/rrdtool-0.99.29.1/src/parsetime.h
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd.dsp
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd.dsw
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_create.c
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_diff.c
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_dump.c
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_error.c
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_fetch.c
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_format.c
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_format.h
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_graph.c
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_last.c
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_open.c
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_tool.c
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_tool.h
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_tune.c
trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_update.c
trunk/orca/packages/rrdtool-0.99.29.1/src/rrdtool.dsp
trunk/orca/packages/rrdtool-0.99.29.1/src/rrdtool.dsw
trunk/orca/src/migrate_to_orcallator.pl
Modified:
trunk/orca/CHANGES
trunk/orca/INSTALL
trunk/orca/Makefile.in
trunk/orca/README
trunk/orca/TODO
trunk/orca/config/PerlHead1.in
trunk/orca/config/PerlHead2.in
trunk/orca/config/acinclude.m4
trunk/orca/configure
trunk/orca/configure.in
trunk/orca/docs/ARCHITECTURE
trunk/orca/lib/Makefile.in
trunk/orca/lib/orcallator.cfg.in
trunk/orca/lib/orcallator.se
trunk/orca/lib/time_gets.cfg
trunk/orca/src/Makefile.in
trunk/orca/src/orca.pl
trunk/orca/src/orcallator_column.pl
trunk/orca/src/orcallator_running.pl.in
trunk/orca/src/restart_orcallator.sh.in
trunk/orca/src/start_orcallator.sh.in
trunk/orca/src/stop_orcallator.sh.in
Log:
Load orca-0.21 into trunk/orca.
Modified: trunk/orca/configure
==============================================================================
--- trunk/orca/configure (original)
+++ trunk/orca/configure Sat Jul 13 18:45:50 2002
@@ -12,17 +12,17 @@
ac_default_prefix=/usr/local
# Any additions from configure.in:
ac_help="$ac_help
- --with-rrd-dir=DIR directory were the RRD data files are stored"
+ --with-rrd-dir=DIR directory were the RRD data files are stored"
ac_help="$ac_help
- --with-html-dir=DIR location of the root output HTML directory"
+ --with-html-dir=DIR location of the root output HTML directory"
ac_help="$ac_help
- --with-perc-dir=DIR directory were percollator output is stored"
+ --with-orcallator-dir=DIR directory were orcallator output is stored"
ac_help="$ac_help
- --with-ncsa-log=FILE location of the NCSA style web server access log"
+ --with-ncsa-log=FILE location of the NCSA style web server access log"
ac_help="$ac_help
- --with-proxy-log=FILE location of the proxy NCSA style web server access log"
+ --with-proxy-log=FILE location of the proxy NCSA web server access log"
ac_help="$ac_help
- --with-squid-log=FILE location of the Squid file"
+ --with-squid-log=FILE location of the Squid file log file"
# Initialize some variables set by options.
# The variables have the same names as the options, with
@@ -642,10 +642,26 @@
program_prefix=${target_alias}-
+# Remember the command line arguments to configure for use when
+# configure is run again.
+CONFIGURE_COMMAND_LINE=${1+"$@"}
+
+
+# Define the directories containing packages that Orca makes use of here.
+# The path packages gets added where necessary.
+DIGEST_MD5_DIR=Digest-MD5-2.07
+MATH_INTERPOLATE_DIR=Math-Interpolate-1.02
+RRDTOOL_DIR=rrdtool-0.99.29.1
+STORABLE_DIR=Storable-0.6 at 3
+
+
+
+
+
# Minimum Autoconf version required.
-# Define the directories where the source percollator and RRD data files
+# Define the directories where the source orcallator and RRD data files
# will be installed.
# Check whether --with-rrd-dir or --without-rrd-dir was given.
if test "${with_rrd_dir+set}" = set; then
@@ -690,27 +706,27 @@
-# Check whether --with-perc-dir or --without-perc-dir was given.
-if test "${with_perc_dir+set}" = set; then
- withval="$with_perc_dir"
+# Check whether --with-orcallator-dir or --without-orcallator-dir was given.
+if test "${with_orcallator_dir+set}" = set; then
+ withval="$with_orcallator_dir"
case "$withval" in
"" | y | ye | yes | n | no)
- { echo "configure: error: *** You must supply an argument to the --with-perc-dir option." 1>&2; exit 1; }
+ { echo "configure: error: *** You must supply an argument to the --with-orcallator-dir option." 1>&2; exit 1; }
;;
- *) PERCOLLATOR_DIR="$withval"
+ *) ORCALLATOR_DIR="$withval"
;;
esac
else
- : ${PERCOLLATOR_DIR=$localstatedir/orca/percollator}
+ : ${ORCALLATOR_DIR=$localstatedir/orca/orcallator}
fi
-PERCOLLATOR_DIR=`(
+ORCALLATOR_DIR=`(
test "x$prefix" = xNONE && prefix=$ac_default_prefix
test "x$exec_prefix" = xNONE && exec_prefix=${prefix}
- eval echo "$PERCOLLATOR_DIR"
+ eval echo "$ORCALLATOR_DIR"
)`
@@ -782,6 +798,258 @@
+# To get a default CFLAGS for this build, check for a C compiler. This
+# is also needed to be ready to compile any Perl modules.
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:807: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:837: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:888: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:920: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 931 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:936: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:962: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:967: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:976: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:995: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:1028: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
if test "$program_transform_name" = s,x,x,; then
program_transform_name=
else
@@ -806,7 +1074,7 @@
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:810: checking for $ac_word" >&5
+echo "configure:1078: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_AWK'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -844,7 +1112,7 @@
# Extract the first word of "cut", so it can be a program name with args.
set dummy cut; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:848: checking for $ac_word" >&5
+echo "configure:1116: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_CUT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -880,7 +1148,7 @@
# Extract the first word of "expr", so it can be a program name with args.
set dummy expr; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:884: checking for $ac_word" >&5
+echo "configure:1152: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_EXPR'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -916,7 +1184,7 @@
# Extract the first word of "se", so it can be a program name with args.
set dummy se; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:920: checking for $ac_word" >&5
+echo "configure:1188: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_SE'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -951,7 +1219,7 @@
# Extract the first word of "uname", so it can be a program name with args.
set dummy uname; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:955: checking for $ac_word" >&5
+echo "configure:1223: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_UNAME'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -985,13 +1253,15 @@
fi
-# Include the file that defined BORP_PERL_RUN.
+# Include the file that defines BORP_PERL_RUN.
+
+
# Extract the first word of "perl", so it can be a program name with args.
set dummy perl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:995: checking for $ac_word" >&5
+echo "configure:1265: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1024,11 +1294,12 @@
echo "$ac_t""no" 1>&6
fi
-if test "x$PERL" != "xNOT_FOUND"; then
- PERL="$PERL -w"
+if test "x$PERL" = "xNOT_FOUND"; then
+ { echo "configure: error: *** Perl not found. Please install Perl. See INSTALL how to do this." 1>&2; exit 1; }
+else
echo $ac_n "checking if '$PERL' will run Perl scripts""... $ac_c" 1>&6
-echo "configure:1032: checking if '$PERL' will run Perl scripts" >&5
+echo "configure:1303: checking if '$PERL' will run Perl scripts" >&5
rm -f conftest.BZ
cat > conftest.BZ <<EOF
#!$PERL
@@ -1045,12 +1316,112 @@
fi
rm -f conftest.BZ
-else
- PERLHEAD=PerlHead2
fi
PERL_HEAD="../config/$PERL_HEAD"
+# Check for necessary Perl modules.
+
+ echo $ac_n "checking if Perl module Digest::MD5 version 2.00 is installed""... $ac_c" 1>&6
+echo "configure:1327: checking if Perl module Digest::MD5 version 2.00 is installed" >&5
+ if $PERL ./config/check_for_perl_mod Digest::MD5 2.00; then
+ borp_cv_perl_digest_md5=yes
+
+ else
+ borp_cv_perl_digest_md5=no
+
+ fi
+ echo "$ac_t""$borp_cv_perl_digest_md5" 1>&6
+
+if test "$borp_cv_perl_digest_md5" = no; then
+ MAKE_DIGEST_MD5=make_digest_md5
+ TEST_DIGEST_MD5=test_digest_md5
+ INSTALL_DIGEST_MD5=install_digest_md5
+ CLEAN_DIGEST_MD5=clean_digest_md5
+ DISTCLEAN_DIGEST_MD5=distclean_digest_md5
+fi
+
+
+
+
+
+
+
+ echo $ac_n "checking if Perl module Math::Interpolate version 1.00 is installed""... $ac_c" 1>&6
+echo "configure:1352: checking if Perl module Math::Interpolate version 1.00 is installed" >&5
+ if $PERL ./config/check_for_perl_mod Math::Interpolate 1.00; then
+ borp_cv_perl_math_interpolate=yes
+
+ else
+ borp_cv_perl_math_interpolate=no
+
+ fi
+ echo "$ac_t""$borp_cv_perl_math_interpolate" 1>&6
+
+if test "$borp_cv_perl_math_interpolate" = no; then
+ MAKE_MATH_INTERPOLATE=make_math_interpolate
+ TEST_MATH_INTERPOLATE=test_math_interpolate
+ INSTALL_MATH_INTERPOLATE=install_math_interpolate
+ CLEAN_MATH_INTERPOLATE=clean_math_interpolate
+ DISTCLEAN_MATH_INTERPOLATE=distclean_math_interpolate
+fi
+
+
+
+
+
+
+
+ echo $ac_n "checking if Perl module RRDs version 0.99029 is installed""... $ac_c" 1>&6
+echo "configure:1377: checking if Perl module RRDs version 0.99029 is installed" >&5
+ if $PERL ./config/check_for_perl_mod RRDs 0.99029; then
+ borp_cv_perl_rdds=yes
+
+ else
+ borp_cv_perl_rdds=no
+
+ fi
+ echo "$ac_t""$borp_cv_perl_rdds" 1>&6
+
+if test "$borp_cv_perl_rdds" = no; then
+ MAKE_RRDTOOL=make_rrdtool
+ TEST_RRDTOOL=test_rrdtool
+ INSTALL_RRDTOOL=install_rrdtool
+ CLEAN_RRDTOOL=clean_rrdtool
+ DISTCLEAN_RRDTOOL=distclean_rrdtool
+fi
+
+
+
+
+
+
+
+ echo $ac_n "checking if Perl module Storable version 0.603 is installed""... $ac_c" 1>&6
+echo "configure:1402: checking if Perl module Storable version 0.603 is installed" >&5
+ if $PERL ./config/check_for_perl_mod Storable 0.603; then
+ borp_cv_perl_storable=yes
+
+ else
+ borp_cv_perl_storable=no
+
+ fi
+ echo "$ac_t""$borp_cv_perl_storable" 1>&6
+
+if test "$borp_cv_perl_storable" = no; then
+ MAKE_STORABLE=make_storable
+ TEST_STORABLE=test_storable
+ INSTALL_STORABLE=install_storable
+ CLEAN_STORABLE=clean_storable
+ DISTCLEAN_STORABLE=distclean_storable
+fi
+
+
+
+
+
+
+
# Define the INSTALL and MKDIR variables to point to the scripts in
# the config directory.
INSTALL="../config/install-sh -c"
@@ -1176,12 +1547,13 @@
trap 'rm -fr `echo "config/PerlHead1
config/PerlHead2
- src/percol_running.pl
- src/restart_percol.sh
- src/start_percol.sh
- src/stop_percol.sh
+ packages/Makefile
+ src/orcallator_running.pl
+ src/restart_orcallator.sh
+ src/start_orcallator.sh
+ src/stop_orcallator.sh
src/Makefile
- lib/percollator.cfg
+ lib/orcallator.cfg
lib/Makefile
docs/Makefile
Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
@@ -1231,11 +1603,18 @@
s%@build_cpu@%$build_cpu%g
s%@build_vendor@%$build_vendor%g
s%@build_os@%$build_os%g
+s%@CONFIGURE_COMMAND_LINE@%$CONFIGURE_COMMAND_LINE%g
+s%@DIGEST_MD5_DIR@%$DIGEST_MD5_DIR%g
+s%@MATH_INTERPOLATE_DIR@%$MATH_INTERPOLATE_DIR%g
+s%@RRDTOOL_DIR@%$RRDTOOL_DIR%g
+s%@STORABLE_DIR@%$STORABLE_DIR%g
s%@RRD_DIR@%$RRD_DIR%g
s%@HTML_DIR@%$HTML_DIR%g
-s%@PERCOLLATOR_DIR@%$PERCOLLATOR_DIR%g
+s%@ORCALLATOR_DIR@%$ORCALLATOR_DIR%g
s%@WATCH_HTTPD@%$WATCH_HTTPD%g
s%@WEB_LOG@%$WEB_LOG%g
+s%@CC@%$CC%g
+s%@SET_MAKE@%$SET_MAKE%g
s%@AWK@%$AWK%g
s%@CUT@%$CUT%g
s%@EXPR@%$EXPR%g
@@ -1243,6 +1622,26 @@
s%@UNAME@%$UNAME%g
s%@PERL@%$PERL%g
s%@PERL_HEAD@%$PERL_HEAD%g
+s%@MAKE_DIGEST_MD5@%$MAKE_DIGEST_MD5%g
+s%@TEST_DIGEST_MD5@%$TEST_DIGEST_MD5%g
+s%@INSTALL_DIGEST_MD5@%$INSTALL_DIGEST_MD5%g
+s%@CLEAN_DIGEST_MD5@%$CLEAN_DIGEST_MD5%g
+s%@DISTCLEAN_DIGEST_MD5@%$DISTCLEAN_DIGEST_MD5%g
+s%@MAKE_MATH_INTERPOLATE@%$MAKE_MATH_INTERPOLATE%g
+s%@TEST_MATH_INTERPOLATE@%$TEST_MATH_INTERPOLATE%g
+s%@INSTALL_MATH_INTERPOLATE@%$INSTALL_MATH_INTERPOLATE%g
+s%@CLEAN_MATH_INTERPOLATE@%$CLEAN_MATH_INTERPOLATE%g
+s%@DISTCLEAN_MATH_INTERPOLATE@%$DISTCLEAN_MATH_INTERPOLATE%g
+s%@MAKE_RRDTOOL@%$MAKE_RRDTOOL%g
+s%@TEST_RRDTOOL@%$TEST_RRDTOOL%g
+s%@INSTALL_RRDTOOL@%$INSTALL_RRDTOOL%g
+s%@CLEAN_RRDTOOL@%$CLEAN_RRDTOOL%g
+s%@DISTCLEAN_RRDTOOL@%$DISTCLEAN_RRDTOOL%g
+s%@MAKE_STORABLE@%$MAKE_STORABLE%g
+s%@TEST_STORABLE@%$TEST_STORABLE%g
+s%@INSTALL_STORABLE@%$INSTALL_STORABLE%g
+s%@CLEAN_STORABLE@%$CLEAN_STORABLE%g
+s%@DISTCLEAN_STORABLE@%$DISTCLEAN_STORABLE%g
s%@INSTALL@%$INSTALL%g
s%@MKDIR@%$MKDIR%g
@@ -1288,12 +1687,13 @@
CONFIG_FILES=\${CONFIG_FILES-"config/PerlHead1
config/PerlHead2
- src/percol_running.pl
- src/restart_percol.sh
- src/start_percol.sh
- src/stop_percol.sh
+ packages/Makefile
+ src/orcallator_running.pl
+ src/restart_orcallator.sh
+ src/start_orcallator.sh
+ src/stop_orcallator.sh
src/Makefile
- lib/percollator.cfg
+ lib/orcallator.cfg
lib/Makefile
docs/Makefile
Makefile"}
@@ -1363,6 +1763,15 @@
test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+if test "$borp_cv_perl_rdds" != "yes"; then
+ echo ""
+ echo "Running configure in packages/$RRDTOOL_DIR to create RRDtool and RRDs.pm."
+ echo ""
+ echo "(cd packages/$RRDTOOL_DIR; ./configure $CONFIGURE_COMMAND_LINE --cache-file=../../config.cache)"
+ echo ""
+ (cd packages/$RRDTOOL_DIR; ./configure $CONFIGURE_COMMAND_LINE --cache-file=../../config.cache)
+fi
+
if test -z "$WEB_LOG"; then
echo "configure: warning: *** Unless you use a --with-*-log option you will not gather WWW log data." 1>&2
fi
Modified: trunk/orca/Makefile.in
==============================================================================
--- trunk/orca/Makefile.in (original)
+++ trunk/orca/Makefile.in Sat Jul 13 18:45:51 2002
@@ -1,32 +1,50 @@
-SUBDIRS = lib src docs
+ at SET_MAKE@
+
+SUBDIRS = packages lib src docs
PREFIX = @prefix@
-PERCOLLATOR_DIR = @PERCOLLATOR_DIR@
+ORCALLATOR_DIR = @ORCALLATOR_DIR@
RRD_DIR = @RRD_DIR@
+CFLAGS = @CFLAGS@
-all: configure
- @for dir in $(SUBDIRS); do \
- echo "cd $$dir; $(MAKE)"; \
- (cd $$dir; $(MAKE)); \
+all: configure Makefile
+ @for dir in $(SUBDIRS); do \
+ echo "cd $$dir && $(MAKE) CFLAGS=$(CFLAGS)"; \
+ (cd $$dir && $(MAKE) CFLAGS="$(CFLAGS)"); \
done
+test:
+ (cd packages; $(MAKE) CFLAGS="$(CFLAGS)" test)
+
+migrate:
+ (cd src; $(MAKE) migrate)
+
install:
- ./config/mkinstalldirs $(PERCOLLATOR_DIR)
+ ./config/mkinstalldirs $(ORCALLATOR_DIR)
./config/mkinstalldirs $(RRD_DIR)
@for dir in $(SUBDIRS); do \
- echo "cd $$dir; $(MAKE) install"; \
- (cd $$dir; $(MAKE) install); \
+ echo "cd $$dir && $(MAKE) install"; \
+ (cd $$dir && $(MAKE) install); \
done
+modules:
+ (cd packages && $(MAKE) CFLAGS="$(CFLAGS)" modules)
+
+test_modules:
+ (cd packages && $(MAKE) CFLAGS="$(CFLAGS)" test_modules)
+
+install_modules:
+ (cd packages && $(MAKE) CFLAGS="$(CFLAGS)" install_modules)
+
clean:
@for dir in $(SUBDIRS); do \
- echo "cd $$dir; $(MAKE) clean"; \
- (cd $$dir; $(MAKE) clean); \
+ echo "cd $$dir && $(MAKE) clean"; \
+ (cd $$dir && $(MAKE) clean); \
done
distclean:
@for dir in $(SUBDIRS); do \
- echo "cd $$dir; $(MAKE) distclean"; \
- (cd $$dir; $(MAKE) distclean); \
+ echo "cd $$dir && $(MAKE) distclean"; \
+ (cd $$dir && $(MAKE) distclean); \
done
$(RM) config/PerlHead1 config/PerlHead2
$(RM) config.cache config.log config.status Makefile
@@ -34,3 +52,6 @@
configure: configure.in
autoconf
./config.status
+
+Makefile: Makefile.in
+ ./config.status
Modified: trunk/orca/TODO
==============================================================================
--- trunk/orca/TODO (original)
+++ trunk/orca/TODO Sat Jul 13 18:45:51 2002
@@ -2,7 +2,7 @@
Come up with a better error scheme than using warn() for some
errors and the email warn for others.
Do something better if the number of columns changes in a single
- percollator file.
+ orcallator file.
Have a scheme were at any point of time a data file may add or
change the number of columns of data and column names.
Lock file.
@@ -13,7 +13,7 @@
Make plots from multiple files sets: delete source files_key and put
it into data.
Update HTML files if a new file is found with a new group.
- Update percollator.cfg.in for caching and proxy stuff.
+ Update orcallator.cfg.in for caching and proxy stuff.
-percollator.se:
+orcallator.se:
Better documentation.
Added: trunk/orca/config/check_for_perl_mod
==============================================================================
--- trunk/orca/config/check_for_perl_mod (original)
+++ trunk/orca/config/check_for_perl_mod Sat Jul 13 18:45:51 2002
@@ -0,0 +1,31 @@
+use strict;
+
+my $verbose = 0;
+
+# Subroutine to check for installed modules.
+sub check_version
+{
+ my ($pkg, $wanted) = @_;
+
+ local($|) = 1;
+ print "Checking for $pkg..." if $verbose;
+
+ eval { my $p; ($p = $pkg . ".pm") =~ s#::#/#g; require $p; };
+
+ no strict 'refs';
+
+ my $vstr = ${"${pkg}::VERSION"} ? "found v" . ${"${pkg}::VERSION"}
+ : "not found";
+ my $vnum = ${"${pkg}::VERSION"} || 0;
+
+ if ($verbose) {
+ print $vnum >= $wanted ? "ok\n" : " " . $vstr . "\n";
+ }
+
+ $vnum >= $wanted;
+}
+
+die "usage: $0 package_name version" unless @ARGV == 2;
+
+# Return 0 if the necessary version was found, 1 otherwise.
+exit(!check_version(@ARGV));
Modified: trunk/orca/config/acinclude.m4
==============================================================================
--- trunk/orca/config/acinclude.m4 (original)
+++ trunk/orca/config/acinclude.m4 Sat Jul 13 18:45:51 2002
@@ -1,3 +1,21 @@
+dnl Check if the requested modules are install in this perl module.
+dnl Do not cache this result, since the user may easy install the
+dnl modules and rerun configure. We do not want to remember if
+dnl the module is not installed.
+dnl BORP_PERL_MODULE(DEFINE, PATH_TO_PERL, MODULE_NAME, MODULE_VERSION,
+dnl [ACTION_IF_FOUND, [ACTION_IF_NOT_FOUND]]
+AC_DEFUN(BORP_PERL_MODULE, [
+ AC_MSG_CHECKING([if Perl module $3 version $4 is installed])
+ if $2 ./config/check_for_perl_mod $3 $4; then
+ $1=yes
+ ifelse([$5], , , [$5])
+ else
+ $1=no
+ ifelse([$6], , , [$6])
+ fi
+ AC_MSG_RESULT([$]$1)
+])
+
dnl Check if the whole path to Perl can be placed on the #! line
dnl of a shell script. Some systems have length restrictions
dnl so some paths to programs may be too long.
Modified: trunk/orca/config/PerlHead1.in
==============================================================================
--- trunk/orca/config/PerlHead1.in (original)
+++ trunk/orca/config/PerlHead1.in Sat Jul 13 18:45:51 2002
@@ -1,4 +1,4 @@
-#!@PERL@ # -*- perl -*-
+#!@PERL@ -w # -*- perl -*-
require 5.005;
Modified: trunk/orca/config/PerlHead2.in
==============================================================================
--- trunk/orca/config/PerlHead2.in (original)
+++ trunk/orca/config/PerlHead2.in Sat Jul 13 18:45:51 2002
@@ -1,8 +1,8 @@
#!/bin/sh -- # -*- perl -*- -w
# Catch for sh/csh on systems without #! ability.
-eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
-& eval 'exec perl -S $0 $argv:q'
+eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}'
+& eval 'exec perl -w -S $0 $argv:q'
if 0;
require 5.005;
Modified: trunk/orca/configure.in
==============================================================================
--- trunk/orca/configure.in (original)
+++ trunk/orca/configure.in Sat Jul 13 18:45:51 2002
@@ -5,13 +5,29 @@
AC_CONFIG_AUX_DIR(config)
AC_CANONICAL_SYSTEM
+# Remember the command line arguments to configure for use when
+# configure is run again.
+CONFIGURE_COMMAND_LINE=${1+"$@"}
+AC_SUBST(CONFIGURE_COMMAND_LINE)
+
+# Define the directories containing packages that Orca makes use of here.
+# The path packages gets added where necessary.
+DIGEST_MD5_DIR=Digest-MD5-2.07
+MATH_INTERPOLATE_DIR=Math-Interpolate-1.02
+RRDTOOL_DIR=rrdtool-0.99.29.1
+STORABLE_DIR=Storable-0.6 at 3
+AC_SUBST(DIGEST_MD5_DIR)
+AC_SUBST(MATH_INTERPOLATE_DIR)
+AC_SUBST(RRDTOOL_DIR)
+AC_SUBST(STORABLE_DIR)
+
# Minimum Autoconf version required.
AC_PREREQ(2.13)
-# Define the directories where the source percollator and RRD data files
+# Define the directories where the source orcallator and RRD data files
# will be installed.
AC_ARG_WITH(rrd-dir,
- [ --with-rrd-dir=DIR directory were the RRD data files are stored],
+ [ --with-rrd-dir=DIR directory were the RRD data files are stored],
[
case "$withval" in
"" | y | ye | yes | n | no)
@@ -31,7 +47,7 @@
AC_SUBST(RRD_DIR)
AC_ARG_WITH(html-dir,
- [ --with-html-dir=DIR location of the root output HTML directory],
+ [ --with-html-dir=DIR location of the root output HTML directory],
[
case "$withval" in
"" | y | ye | yes | n | no)
@@ -45,30 +61,30 @@
)
AC_SUBST(HTML_DIR)
-AC_ARG_WITH(perc-dir,
- [ --with-perc-dir=DIR directory were percollator output is stored],
+AC_ARG_WITH(orcallator-dir,
+ [ --with-orcallator-dir=DIR directory were orcallator output is stored],
[
case "$withval" in
"" | y | ye | yes | n | no)
- AC_MSG_ERROR([*** You must supply an argument to the --with-perc-dir option.])
+ AC_MSG_ERROR([*** You must supply an argument to the --with-orcallator-dir option.])
;;
- *) PERCOLLATOR_DIR="$withval"
+ *) ORCALLATOR_DIR="$withval"
;;
esac
],
- : ${PERCOLLATOR_DIR=$localstatedir/orca/percollator}
+ : ${ORCALLATOR_DIR=$localstatedir/orca/orcallator}
)
-PERCOLLATOR_DIR=`(
+ORCALLATOR_DIR=`(
test "x$prefix" = xNONE && prefix=$ac_default_prefix
test "x$exec_prefix" = xNONE && exec_prefix=${prefix}
- eval echo "$PERCOLLATOR_DIR"
+ eval echo "$ORCALLATOR_DIR"
)`
-AC_SUBST(PERCOLLATOR_DIR)
+AC_SUBST(ORCALLATOR_DIR)
WATCH_HTTPD=
NCSA_LOG=
AC_ARG_WITH(ncsa-log,
- [ --with-ncsa-log=FILE location of the NCSA style web server access log],
+ [ --with-ncsa-log=FILE location of the NCSA style web server access log],
[
case "$withval" in
"" | y | ye | yes | n | no)
@@ -84,7 +100,7 @@
PROXY_LOG=
AC_ARG_WITH(proxy-log,
- [ --with-proxy-log=FILE location of the proxy NCSA style web server access log],
+ [ --with-proxy-log=FILE location of the proxy NCSA web server access log],
[
if test "$NCSA_LOG"; then
AC_MSG_ERROR([*** You cannot use both --with-ncsa-log and --with-proxy-log.])
@@ -102,7 +118,7 @@
)
AC_ARG_WITH(squid-log,
- [ --with-squid-log=FILE location of the Squid file],
+ [ --with-squid-log=FILE location of the Squid file log file],
[
if test "$NCSA_LOG"; then
AC_MSG_ERROR([*** You cannot use both --with-ncsa-log and --with-squid-log.])
@@ -124,6 +140,11 @@
AC_SUBST(WATCH_HTTPD)
AC_SUBST(WEB_LOG)
+# To get a default CFLAGS for this build, check for a C compiler. This
+# is also needed to be ready to compile any Perl modules.
+AC_PROG_CC
+
+AC_PROG_MAKE_SET
AC_ARG_PROGRAM
AC_PATH_PROGS(AWK,mawk gawk nawk awk)
AC_PATH_PROG(CUT, cut, cut)
@@ -131,18 +152,75 @@
AC_PATH_PROG(SE, se,,/opt/RICHPse/bin:$PATH)
AC_PATH_PROG(UNAME, uname, uname)
-# Include the file that defined BORP_PERL_RUN.
+# Include the file that defines BORP_PERL_RUN.
sinclude(config/acinclude.m4)
AC_PATH_PROG(PERL, perl, NOT_FOUND)
-if test "x$PERL" != "xNOT_FOUND"; then
- PERL="$PERL -w"
- BORP_PERL_RUN($PERL, PERL_HEAD=PerlHead1, PERL_HEAD=PerlHead2)
+if test "x$PERL" = "xNOT_FOUND"; then
+ AC_MSG_ERROR([*** Perl not found. Please install Perl. See INSTALL how to do this.])
else
- PERLHEAD=PerlHead2
+ BORP_PERL_RUN($PERL, PERL_HEAD=PerlHead1, PERL_HEAD=PerlHead2)
fi
PERL_HEAD="../config/$PERL_HEAD"
AC_SUBST(PERL_HEAD)
+# Check for necessary Perl modules.
+BORP_PERL_MODULE(borp_cv_perl_digest_md5, $PERL, Digest::MD5, 2.00)
+if test "$borp_cv_perl_digest_md5" = no; then
+ MAKE_DIGEST_MD5=make_digest_md5
+ TEST_DIGEST_MD5=test_digest_md5
+ INSTALL_DIGEST_MD5=install_digest_md5
+ CLEAN_DIGEST_MD5=clean_digest_md5
+ DISTCLEAN_DIGEST_MD5=distclean_digest_md5
+fi
+AC_SUBST(MAKE_DIGEST_MD5)
+AC_SUBST(TEST_DIGEST_MD5)
+AC_SUBST(INSTALL_DIGEST_MD5)
+AC_SUBST(CLEAN_DIGEST_MD5)
+AC_SUBST(DISTCLEAN_DIGEST_MD5)
+
+BORP_PERL_MODULE(borp_cv_perl_math_interpolate, $PERL, Math::Interpolate, 1.00)
+if test "$borp_cv_perl_math_interpolate" = no; then
+ MAKE_MATH_INTERPOLATE=make_math_interpolate
+ TEST_MATH_INTERPOLATE=test_math_interpolate
+ INSTALL_MATH_INTERPOLATE=install_math_interpolate
+ CLEAN_MATH_INTERPOLATE=clean_math_interpolate
+ DISTCLEAN_MATH_INTERPOLATE=distclean_math_interpolate
+fi
+AC_SUBST(MAKE_MATH_INTERPOLATE)
+AC_SUBST(TEST_MATH_INTERPOLATE)
+AC_SUBST(INSTALL_MATH_INTERPOLATE)
+AC_SUBST(CLEAN_MATH_INTERPOLATE)
+AC_SUBST(DISTCLEAN_MATH_INTERPOLATE)
+
+BORP_PERL_MODULE(borp_cv_perl_rdds, $PERL, RRDs, 0.99029)
+if test "$borp_cv_perl_rdds" = no; then
+ MAKE_RRDTOOL=make_rrdtool
+ TEST_RRDTOOL=test_rrdtool
+ INSTALL_RRDTOOL=install_rrdtool
+ CLEAN_RRDTOOL=clean_rrdtool
+ DISTCLEAN_RRDTOOL=distclean_rrdtool
+fi
+AC_SUBST(MAKE_RRDTOOL)
+AC_SUBST(TEST_RRDTOOL)
+AC_SUBST(INSTALL_RRDTOOL)
+AC_SUBST(CLEAN_RRDTOOL)
+AC_SUBST(DISTCLEAN_RRDTOOL)
+
+BORP_PERL_MODULE(borp_cv_perl_storable, $PERL, Storable, 0.603)
+if test "$borp_cv_perl_storable" = no; then
+ MAKE_STORABLE=make_storable
+ TEST_STORABLE=test_storable
+ INSTALL_STORABLE=install_storable
+ CLEAN_STORABLE=clean_storable
+ DISTCLEAN_STORABLE=distclean_storable
+fi
+AC_SUBST(MAKE_STORABLE)
+AC_SUBST(TEST_STORABLE)
+AC_SUBST(INSTALL_STORABLE)
+AC_SUBST(CLEAN_STORABLE)
+AC_SUBST(DISTCLEAN_STORABLE)
+
+
# Define the INSTALL and MKDIR variables to point to the scripts in
# the config directory.
INSTALL="../config/install-sh -c"
@@ -156,16 +234,26 @@
#--------------------------------------------------------------------
AC_OUTPUT(config/PerlHead1
config/PerlHead2
- src/percol_running.pl
- src/restart_percol.sh
- src/start_percol.sh
- src/stop_percol.sh
+ packages/Makefile
+ src/orcallator_running.pl
+ src/restart_orcallator.sh
+ src/start_orcallator.sh
+ src/stop_orcallator.sh
src/Makefile
- lib/percollator.cfg
+ lib/orcallator.cfg
lib/Makefile
docs/Makefile
Makefile)
+if test "$borp_cv_perl_rdds" != "yes"; then
+ echo ""
+ echo "Running configure in packages/$RRDTOOL_DIR to create RRDtool and RRDs.pm."
+ echo ""
+ echo "(cd packages/$RRDTOOL_DIR; ./configure $CONFIGURE_COMMAND_LINE --cache-file=../../config.cache)"
+ echo ""
+ (cd packages/$RRDTOOL_DIR; ./configure $CONFIGURE_COMMAND_LINE --cache-file=../../config.cache)
+fi
+
if test -z "$WEB_LOG"; then
AC_MSG_WARN([*** Unless you use a --with-*-log option you will not gather WWW log data.])
fi
Modified: trunk/orca/lib/Makefile.in
==============================================================================
--- trunk/orca/lib/Makefile.in (original)
+++ trunk/orca/lib/Makefile.in Sat Jul 13 18:45:51 2002
@@ -1,13 +1,16 @@
+ at SET_MAKE@
+
prefix = @prefix@
exec_prefix = @exec_prefix@
libdir = @libdir@
MKDIR = @MKDIR@
INSTALL = @INSTALL@
-all: percollator.cfg orca.gif.hex rrdtool.gif.hex
+all: orcallator.cfg orca.gif.hex rrdtool.gif.hex
-percollator.cfg: percollator.cfg.in
- cd ..; ./config.status
+orcallator.cfg: orcallator.cfg.in
+ (cd ..; ./config.status)
+ $(MAKE)
# Create a hex file representation of orca.gif that can be stored inside
# orca.pl.
@@ -21,12 +24,12 @@
install: all
$(MKDIR) $(libdir)
- -cp -p $(libdir)/percollator.cfg $(libdir)/percollator.cfg.`date +%Y-%m-%d-%H:%M:%S`
- $(INSTALL) -m 0644 percollator.cfg $(libdir)
- $(INSTALL) -m 0644 percollator.se $(libdir)
+ -cp -p $(libdir)/orcallator.cfg $(libdir)/orcallator.cfg.`date +%Y-%m-%d-%H:%M:%S`
+ $(INSTALL) -m 0644 orcallator.cfg $(libdir)
+ $(INSTALL) -m 0644 orcallator.se $(libdir)
clean:
- $(RM) percollator.cfg
+ $(RM) orcallator.cfg
distclean: clean
$(RM) Makefile
Modified: trunk/orca/lib/orcallator.cfg.in
==============================================================================
--- trunk/orca/lib/orcallator.cfg.in (original)
+++ trunk/orca/lib/orcallator.cfg.in Sat Jul 13 18:45:51 2002
@@ -1,13 +1,13 @@
-# Orca configuration file for Percollator files.
+# Orca configuration file for orcallator files.
-base_dir @RRD_DIR@/percollator
+base_dir @RRD_DIR@/orcallator
state_file orca.state
html_dir @HTML_DIR@
expire_gifs 1
# Find files at the following times:
-# 0:10 to pick up new percollator files for the new day.
-# 1:00 to pick up late comer percollator files for the new day.
+# 0:10 to pick up new orcallator files for the new day.
+# 1:00 to pick up late comer orcallator files for the new day.
# 6:00 to pick up new files before the working day.
# 12:00 to pick up new files during the working day.
# 19:00 to pick up new files after the working day.
@@ -22,8 +22,8 @@
# This defines where the find the source data files and the format of those
# files.
-files percol {
-find_files @PERCOLLATOR_DIR@/(.*)/percol-\d{4}-\d{2}-\d{2}
+files orcallator {
+find_files @ORCALLATOR_DIR@/(.*)/(?:(?:orcallator)|(?:percol))-\d{4}-\d{2}-\d{2}
column_description first_line
date_source column_name timestamp
date_format %s
@@ -60,7 +60,7 @@
plot {
title %g Average # Processes in Run Queue
-source percol
+source orcallator
data 1runq
data 5runq
data 15runq
@@ -74,7 +74,7 @@
plot {
title %g System Load
-source percol
+source orcallator
data 1load
data 5load
data 15load
@@ -88,7 +88,7 @@
plot {
title %g Number of System & Httpd Processes
-source percol
+source orcallator
data #proc
data #httpds
line_type line1
@@ -102,7 +102,7 @@
plot {
title %g CPU Usage
-source percol
+source orcallator
data usr%
data sys%
data 100 - usr% - sys%
@@ -122,7 +122,7 @@
plot {
title %g Web Server Hit Rate
-source percol
+source orcallator
data httpop/s
data http/p5s
legend 5 min average hits/s
@@ -134,7 +134,7 @@
plot {
title %g Web Server File Size
-source percol
+source orcallator
data %to1KB
data %to10KB
data %to100KB
@@ -160,7 +160,7 @@
plot {
title %g Web Server Data Transfer Rate
-source percol
+source orcallator
data httpb/s
legend Bytes/s
y_legend Bytes/s
@@ -169,7 +169,7 @@
plot {
title %g Web Server HTTP Error Rate
-source percol
+source orcallator
data htErr/s
legend HTTP Errors/s
y_legend Errors/s
@@ -178,7 +178,7 @@
plot {
title %g Bits Per Second: be0
-source percol
+source orcallator
data 1024 * 8 * be0InKB/s
data 1024 * 8 * be0OuKB/s
line_type area
@@ -191,8 +191,22 @@
}
plot {
+title %g Bits Per Second: elxl0
+source orcallator
+data 1024 * 8 * elxl0InKB/s
+data 1024 * 8 * elxl0OuKB/s
+line_type area
+legend Input
+legend Output
+y_legend bits/s
+data_min 0
+data_max 100000000
+optional
+}
+
+plot {
title %g Bits Per Second: hme0
-source percol
+source orcallator
data 1024 * 8 * hme0InKB/s
data 1024 * 8 * hme0OuKB/s
line_type area
@@ -206,7 +220,7 @@
plot {
title %g Bits Per Second: hme1
-source percol
+source orcallator
data 1024 * 8 * hme1InKB/s
data 1024 * 8 * hme1OuKB/s
line_type area
@@ -220,7 +234,7 @@
plot {
title %g Bits Per Second: hme2
-source percol
+source orcallator
data 1024 * 8 * hme2InKB/s
data 1024 * 8 * hme2OuKB/s
line_type area
@@ -234,7 +248,7 @@
plot {
title %g Bits Per Second: le0
-source percol
+source orcallator
data 1024 * 8 * le0InKB/s
data 1024 * 8 * le0OuKB/s
line_type area
@@ -248,7 +262,7 @@
plot {
title %g Bits Per Second: le1
-source percol
+source orcallator
data 1024 * 8 * le1InKB/s
data 1024 * 8 * le1OuKB/s
line_type area
@@ -262,7 +276,7 @@
plot {
title %g Packets Per Second: $1
-source percol
+source orcallator
data (.*\d)Ipkt/s
data $1Opkt/s
line_type area
@@ -276,7 +290,7 @@
plot {
title %g Errors Per Second: $1
-source percol
+source orcallator
data (.*\d)IErr/s
data $1OErr/s
line_type area
@@ -289,7 +303,7 @@
plot {
title %g Ethernet Nocanput Rate
-source percol
+source orcallator
data (.*\d)NoCP/s
legend $1
y_legend Nocanput/s
@@ -299,7 +313,7 @@
plot {
title %g Ethernet Deferred Packet Rate
-source percol
+source orcallator
data (.*\d)Defr/s
legend $1
y_legend Defers/s
@@ -309,7 +323,7 @@
plot {
title %g Ethernet Collisions
-source percol
+source orcallator
data (.*\d)Coll%
legend $1
y_legend Percent
@@ -320,7 +334,7 @@
plot {
title %g TCP Bits Per Second
-source percol
+source orcallator
data 1024 * 8 * tcp_InKB/s
data 1024 * 8 * tcp_OuKB/s
line_type area
@@ -333,7 +347,7 @@
plot {
title %g TCP Segments Per Second
-source percol
+source orcallator
data tcp_Iseg/s
data tcp_Oseg/s
line_type area
@@ -346,7 +360,7 @@
plot {
title %g TCP Retransmission & Duplicate Received Percentage
-source percol
+source orcallator
data tcp_Ret%
data tcp_Dup%
legend Retransmission
@@ -358,7 +372,7 @@
plot {
title %g TCP New Connection Rate
-source percol
+source orcallator
data tcp_Icn/s
data tcp_Ocn/s
legend Input - Passive
@@ -370,7 +384,7 @@
plot {
title %g TCP Number Open Connections
-source percol
+source orcallator
data tcp_estb
legend # Open Connections
y_legend Number Open TCP Connections
@@ -380,7 +394,7 @@
plot {
title %g TCP Reset Rate
-source percol
+source orcallator
data tcp_Rst/s
legend Number TCP Resets/s
y_legend Resets/s
@@ -389,7 +403,7 @@
plot {
title %g TCP Attempt Fail Rate
-source percol
+source orcallator
data tcp_Atf/s
legend TCP Attempt Fails/s
y_legend Atf/s
@@ -398,7 +412,7 @@
plot {
title %g TCP Listen Drop Rate
-source percol
+source orcallator
data tcp_Ldrp/s
data tcp_LdQ0/s
data tcp_HOdp/s
@@ -410,7 +424,7 @@
plot {
title %g Sleeps on Mutex Rate
-source percol
+source orcallator
data smtx
data smtx/cpu
legend Sleeps on mutex
@@ -421,7 +435,7 @@
plot {
title %g NFS Call Rate
-source percol
+source orcallator
data nfs_call/s
legend NFS Calls/s
y_legend Calls/s
@@ -430,7 +444,7 @@
plot {
title %g NFS Timeouts & Bad Transmits Rate
-source percol
+source orcallator
data nfs_timo/s
data nfs_badx/s
legend NFS Timeouts
@@ -441,7 +455,7 @@
plot {
title %g Peak & Mean Disk Busy
-source percol
+source orcallator
data disk_peak
data disk_mean
line_type line1
@@ -454,7 +468,7 @@
plot {
title %g Cache Hit Percentages
-source percol
+source orcallator
data dnlc_hit%
data inod_hit%
legend DNLC
@@ -466,7 +480,7 @@
plot {
title %g Cache Reference Rate
-source percol
+source orcallator
data dnlc_ref/s
data inod_ref/s
line_type line1
@@ -479,7 +493,7 @@
plot {
title %g Inode Steal Rate
-source percol
+source orcallator
data inod_stl/s
legend Inode w/page steals/s
y_legend Steals/s
@@ -488,7 +502,7 @@
plot {
title %g Available Swap Space
-source percol
+source orcallator
data 1024 * swap_avail
legend Available Swap Space
y_legend Bytes
@@ -497,7 +511,7 @@
plot {
title %g Page Residence Time
-source percol
+source orcallator
data page_rstim
legend Page Residence Time
y_legend Seconds
@@ -506,7 +520,7 @@
plot {
title %g Page Usage
-source percol
+source orcallator
data pp_kernel
data free_pages
data pagestotl - pp_kernel - free_pages
@@ -529,7 +543,7 @@
plot {
title %g Pages Locked & IO
-source percol
+source orcallator
data pageslock
data pagesio
legend Locked
Modified: trunk/orca/lib/orcallator.se
==============================================================================
--- trunk/orca/lib/orcallator.se (original)
+++ trunk/orca/lib/orcallator.se Sat Jul 13 18:45:52 2002
@@ -1,5 +1,5 @@
//
-// Percollator.se, a log generating performance monitor.
+// Orcallator.se, a log generating performance monitor.
//
// This program logs many different system quantities to a log file
// for later processing.
@@ -8,11 +8,14 @@
//
// Portions copied from percollator.se written by Adrian Cockroft.
//
+// Version 1.7: Mar 25, 1999 Speed up by 20% and simplify count_proc.
+// Version 1.6: Feb 23, 1999 Print pvm.user_time and system_time correctly.
+// Version 1.5: Feb 23, 1999 Always write header to a new file.
// Version 1.4: Feb 19, 1999 Handle missing HTTP/1.x in access log.
// Version 1.3: Feb 18, 1999 On busy machines httpops5 will be enlarged.
// Version 1.2: Feb 18, 1999 Output data on integral multiples of interval.
// Version 1.1: Feb 18, 1999 Integrate Squid log processing from SE 3.1.
-// Version 1.0: Sep 9, 1998 Initial version.
+// Version 1.0: Sep 9, 1998 Initial version.
//
// The default sampling interval in seconds.
@@ -34,9 +37,6 @@
#define WATCH_PAGES
#endif
-// The ioctl version of the psinfo structure is needed.
-#define PSINFO_IOCTL
-
#include <stdio.se>
#include <stdlib.se>
#include <unistd.se>
@@ -55,7 +55,6 @@
#include <tcp_rules.se>
#ifdef WATCH_HTTPD
-#include <fcntl.se>
#include <proc.se>
#include <stat.se>
#endif
@@ -200,7 +199,6 @@
starts new logfile each day
*/
ulong checkoutput(tm_t now) {
- int exists;
string outdir = getenv("OUTDIR");
string outname;
ulong ofile;
@@ -225,16 +223,13 @@
}
strftime(tm_buf, sizeof(tm_buf), "%Y-%m-%d", now);
outname = sprintf("%s/percol-%s", outdir, tm_buf);
- exists = access(outname, F_OK); /* see if file already exists */
ofile = fopen(outname, "a"); /* open for append either way */
if (ofile == 0) {
perror("can't open output logfile");
exit(1);
}
- /* if didn't exist write header */
- if (exists == -1) {
- print_columns(ofile, col_comment);
- }
+ // Always write header.
+ print_columns(ofile, col_comment);
then = now;
}
return ofile;
@@ -266,7 +261,7 @@
fprintf(stderr, "%s can use the following environmental variables:\n", program_name);
fprintf(stderr, " setenv WEB_LOG /ns-home/httpd-80/logs/access - location of web server log\n");
fprintf(stderr, " setenv GATEWAY some.where.com - special address to monitor\n");
- fprintf(stderr, " setenv OUTDIR /ns-home/docs/percollator/logs - default stdout\n");
+ fprintf(stderr, " setenv OUTDIR /ns-home/docs/orcallator/logs - default stdout\n");
fprintf(stderr, " setenv SEARCHURL srch.cgi - match for search scripts, default is search.cgi\n");
fprintf(stderr, "Defines:\n");
fprintf(stderr, " -DWATCH_HTTPD watch httpd access log\n");
@@ -511,8 +506,8 @@
// In SE 3.0 user_time and system_time are int and in SE 3.1 they are
// double, so cast everything to double using + 0.0.
- put_output("usr%", sprintf("%4.0f", pvm.user_time + 0.0));
- put_output("sys%", sprintf("%4.0f", pvm.system_time + 0.0));
+ put_output(" usr%", sprintf("%5.1f", pvm.user_time + 0.0));
+ put_output(" sys%", sprintf("%5.1f", pvm.system_time + 0.0));
put_output(" 1load", sprintf("%6.2f", tmp_kstat_misc.avenrun_1min/256.0));
put_output(" 5load", sprintf("%6.2f", tmp_kstat_misc.avenrun_5min/256.0));
put_output("15load", sprintf("%6.2f", tmp_kstat_misc.avenrun_15min/256.0));
@@ -1003,83 +998,23 @@
#endif
}
-long count_proc(string name)
+int count_proc(string name)
{
- ulong directory_pointer;
- ulong directory_entry;
- dirent_t directory_data;
- int process_number;
- char process_name[64];
- long num_proc;
- int process_fd;
- int err;
-#if MINOR_VERSION < 60
- prpsinfo_t ps[1]; // format for ioctl
-#else
- psinfo_t ps[1]; // format changes when read used
- ulong pps = 0;
-
- if (pps == 0) {
- pps = malloc(sizeof(ps));
- }
-#endif
-
- directory_pointer = opendir("/proc");
- if (directory_pointer == 0) {
- fprintf(stderr, "%s: cannot open /proc for reading.\n", program_name);
- return 0;
- }
-
- rewinddir(directory_pointer);
-
- num_proc = 0;
+ int count;
+ prpsinfo_t p;
- // Go through all processes.
- directory_entry = readdir(directory_pointer);
- for (; directory_entry != NULL; ) {
- struct_fill(directory_data, directory_entry);
- directory_entry = readdir(directory_pointer);
-
- process_number = atoi(directory_data.d_name);
-#if MINOR_VERSION < 60
- process_name = sprintf("/proc/%d", process_number);
-#else
- process_name = sprintf("/proc/%d/psinfo", process_number);
-#endif
- process_fd = open(process_name, O_RDONLY, 0);
- if (process_fd == -1) {
- continue;
- }
-
-#if MINOR_VERSION < 60
- // Read the process info and accumulate errors.
- err += ioctl(process_fd, PIOCPSINFO, ps);
- if (err != 0) {
-#else
- err += read(process_fd, pps, sizeof(ps));
- struct_fill(ps, pps);
- if (err == 0) {
-#endif
-
- // Process went away since the directory was opened.
- close(process_fd);
- continue;
- }
-
- close(process_fd);
- if (ps[0].pr_fname =~ name) {
- ++num_proc;
+ count = 0;
+ for (p=first_proc(); p.pr_pid != -1; p=next_proc()) {
+ if (p.pr_fname =~ name) {
+ count++;
}
}
-
- closedir(directory_pointer);
-
- return num_proc;
+ return count;
}
put_httpd()
{
- put_output("#httpds", sprintf("%7ld", count_proc("httpd")));
+ put_output("#httpds", sprintf("%7d", count_proc("httpd")));
put_output("httpop/s", sprintf("%8.2f", httpops/log_interval));
put_output("http/p5s", sprintf("%8.2f", httpops5));
put_output("cndget/s", sprintf("%8.2f", httpop_condgets/log_interval));
Modified: trunk/orca/lib/time_gets.cfg
==============================================================================
--- trunk/orca/lib/time_gets.cfg (original)
+++ trunk/orca/lib/time_gets.cfg Sat Jul 13 18:45:53 2002
@@ -6,8 +6,8 @@
expire_gifs 1
# Find files at the following times:
-# 0:10 to pick up new percollator files for the new day.
-# 1:00 to pick up late comer percollator files for the new day.
+# 0:10 to pick up new orcallator files for the new day.
+# 1:00 to pick up late comer orcallator files for the new day.
# 6:00 to pick up new files before the working day.
# 12:00 to pick up new files during the working day.
# 19:00 to pick up new files after the working day.
@@ -57,484 +57,3 @@
<font face="Arial,Helvetica">
These plots brought to you by your local system administrator.
</font>
-
-plot {
-title %g Average # Processes in Run Queue
-source percol
-data 1runq
-data 5runq
-data 15runq
-legend 1 Minute Average
-legend 5 Minute Average
-legend 15 Minute Average
-y_legend # Processes
-data_min 0
-data_max 100
-}
-
-plot {
-title %g System Load
-source percol
-data 1load
-data 5load
-data 15load
-legend 1 Minute Average
-legend 5 Minute Average
-legend 15 Minute Average
-y_legend Load
-data_min 0
-data_max 200
-}
-
-plot {
-title %g Number of System & Httpd Processes
-source percol
-data #proc
-data #httpds
-line_type line1
-line_type area
-legend System total
-legend Number httpds
-y_legend # Processes
-data_min 0
-data_max 10000
-}
-
-plot {
-title %g CPU Usage
-source percol
-data usr%
-data sys%
-data 100 - usr% - sys%
-legend User
-legend System
-legend Idle
-line_type area
-line_type stack
-line_type stack
-y_legend Percent
-data_min 0
-data_max 100
-plot_min 0
-plot_max 100
-rigid_min_max 1
-}
-
-plot {
-title %g Web Server Hit Rate
-source percol
-data httpop/s
-data http/p5s
-legend 5 minute average hits/s
-legend Peak 5 second interval hits/s
-y_legend Hits/second
-data_min 0
-optional
-}
-
-plot {
-title %g Web Server File Size
-source percol
-data %to1KB
-data %to10KB
-data %to100KB
-data %to1MB
-data %over1MB
-line_type area
-line_type stack
-line_type stack
-line_type stack
-line_type stack
-legend 0 - 1 KB
-legend 1 - 10 KB
-legend 10 - 100 KB
-legend 100 - 1000 KB
-legend Greater than 1 MB
-y_legend Percent
-data_min 0
-data_max 100
-plot_min 0
-plot_max 100
-rigid_min_max 1
-}
-
-plot {
-title %g Web Server Data Transfer Rate
-source percol
-data httpb/s
-legend Bytes/s
-y_legend Bytes/s
-data_min 0
-}
-
-plot {
-title %g Web Server HTTP Error Rate
-source percol
-data htErr/s
-legend HTTP Errors/s
-y_legend Errors/s
-data_min 0
-}
-
-plot {
-title %g Bits Per Second: be0
-source percol
-data 1024 * 8 * be0InKB/s
-data 1024 * 8 * be0OuKB/s
-line_type area
-legend Input
-legend Output
-y_legend bits/s
-data_min 0
-data_max 100000000
-optional
-}
-
-plot {
-title %g Bits Per Second: hme0
-source percol
-data 1024 * 8 * hme0InKB/s
-data 1024 * 8 * hme0OuKB/s
-line_type area
-legend Input
-legend Output
-y_legend bits/s
-data_min 0
-data_max 100000000
-optional
-}
-
-plot {
-title %g Bits Per Second: hme1
-source percol
-data 1024 * 8 * hme1InKB/s
-data 1024 * 8 * hme1OuKB/s
-line_type area
-legend Input
-legend Output
-y_legend bits/s
-data_min 0
-data_max 100000000
-optional
-}
-
-plot {
-title %g Bits Per Second: hme2
-source percol
-data 1024 * 8 * hme2InKB/s
-data 1024 * 8 * hme2OuKB/s
-line_type area
-legend Input
-legend Output
-y_legend bits/s
-data_min 0
-data_max 100000000
-optional
-}
-
-plot {
-title %g Bits Per Second: le0
-source percol
-data 1024 * 8 * le0InKB/s
-data 1024 * 8 * le0OuKB/s
-line_type area
-legend Input
-legend Output
-y_legend bits/s
-data_min 0
-data_max 10000000
-optional
-}
-
-plot {
-title %g Bits Per Second: le1
-source percol
-data 1024 * 8 * le1InKB/s
-data 1024 * 8 * le1OuKB/s
-line_type area
-legend Input
-legend Output
-y_legend bits/s
-data_min 0
-data_max 10000000
-optional
-}
-
-plot {
-title %g Packets Per Second: $1
-source percol
-data (.*\d)Ipkt/s
-data $1Opkt/s
-line_type area
-legend Input
-legend Output
-y_legend Packets/s
-data_min 0
-data_max 100000
-flush_regexps 1
-}
-
-plot {
-title %g Errors Per Second: $1
-source percol
-data (.*\d)IErr/s
-data $1OErr/s
-line_type area
-legend Input
-legend Output
-y_legend Errors/s
-data_min 0
-flush_regexps 1
-}
-
-plot {
-title %g Ethernet Nocanput Rate
-source percol
-data (.*\d)NoCP/s
-legend $1
-y_legend Nocanput/s
-data_min 0
-flush_regexps 1
-}
-
-plot {
-title %g Ethernet Deferred Packet Rate
-source percol
-data (.*\d)Defr/s
-legend $1
-y_legend Defers/s
-data_min 0
-flush_regexps 1
-}
-
-plot {
-title %g Ethernet Collisions
-source percol
-data (.*\d)Coll%
-legend $1
-y_legend Percent
-data_min 0
-data_max 200
-flush_regexps 1
-}
-
-plot {
-title %g TCP Bits Per Second
-source percol
-data 1024 * 8 * tcp_InKB/s
-data 1024 * 8 * tcp_OuKB/s
-line_type area
-legend Input
-legend Output
-y_legend bits/s
-data_min 0
-data_max 1000000000
-}
-
-plot {
-title %g TCP Segments Per Second
-source percol
-data tcp_Iseg/s
-data tcp_Oseg/s
-line_type area
-legend Input
-legend Output
-y_legend Segments/s
-data_min 0
-data_max 20000
-}
-
-plot {
-title %g TCP Retransmission & Duplicate Received Percentage
-source percol
-data tcp_Ret%
-data tcp_Dup%
-legend Retransmission
-legend Duplicate Received
-y_legend Percent
-data_min 0
-data_max 200
-}
-
-plot {
-title %g TCP New Connection Rate
-source percol
-data tcp_Icn/s
-data tcp_Ocn/s
-legend Input - Passive
-legend Output - Active
-y_legend Connections/s
-data_min 0
-data_max 10000
-}
-
-plot {
-title %g TCP Number Open Connections
-source percol
-data tcp_estb
-legend Number Open TCP Connections
-y_legend Number Open Connections
-data_min 0
-data_max 50000
-}
-
-plot {
-title %g TCP Reset Rate
-source percol
-data tcp_Rst/s
-legend Number TCP Resets/s
-y_legend Resets/s
-data_min 0
-}
-
-plot {
-title %g TCP Attempt Fail Rate
-source percol
-data tcp_Atf/s
-legend TCP Attempt Fails/s
-y_legend Atf/s
-data_min 0
-}
-
-plot {
-title %g TCP Listen Drop Rate
-source percol
-data tcp_Ldrp/s
-data tcp_LdQ0/s
-data tcp_HOdp/s
-legend TCP Listen Drops
-legend TCP Listen Drop Q0
-legend TCP Half Open Drops
-data_min 0
-}
-
-plot {
-title %g Sleeps on Mutex Rate
-source percol
-data smtx
-data smtx/cpu
-legend Sleeps on mutex
-legend Sleeps on mutex/cpu
-y_legend Smtx/s
-data_min 0
-}
-
-plot {
-title %g NFS Call Rate
-source percol
-data nfs_call/s
-legend NFS Calls/s
-y_legend Calls/s
-data_min 0
-}
-
-plot {
-title %g NFS Timeouts & Bad Transmits Rate
-source percol
-data nfs_timo/s
-data nfs_badx/s
-legend NFS Timeouts
-legend Bad Transmits
-y_legend Count/s
-data_min 0
-}
-
-plot {
-title %g Peak & Mean Disk Busy
-source percol
-data disk_peak
-data disk_mean
-line_type line1
-line_type area
-legend Peak Disk Busy
-legend Mean Disk Busy
-y_legend Disk Busy Measure
-data_min 0
-}
-
-plot {
-title %g Cache Hit Percentages
-source percol
-data dnlc_hit%
-data inod_hit%
-legend DNLC
-legend Inode Cache
-y_legend Percent
-data_min 0
-data_max 100
-}
-
-plot {
-title %g Cache Reference Rate
-source percol
-data dnlc_ref/s
-data inod_ref/s
-line_type line1
-line_type area
-legend DNLC
-legend Inode Cache
-y_legend References/s
-data_min 0
-}
-
-plot {
-title %g Inode Steal Rate
-source percol
-data inod_stl/s
-legend Inode w/page steal rate
-y_legend Steals/s
-data_min 0
-}
-
-plot {
-title %g Available Swap Space
-source percol
-data 1024 * swap_avail
-legend Available Swap Space
-y_legend Bytes
-data_min 0
-}
-
-plot {
-title %g Page Residence Time
-source percol
-data page_rstim
-legend Page Residence Time
-y_legend Seconds
-data_min 0
-}
-
-plot {
-title %g Page Usage
-source percol
-data pp_kernel
-data free_pages
-data pagestotl - pp_kernel - free_pages
-data pagestotl
-line_type area
-line_type stack
-line_type stack
-line_type line2
-legend Kernel
-legend Free List
-legend Other
-legend System Total
-y_legend Number of Pages
-data_min 0
-plot_min 0
-color 00ff00
-color ff0000
-color 0000ff
-}
-
-plot {
-title %g Pages Locked & IO
-source percol
-data pageslock
-data pagesio
-legend Locked
-legend IO
-y_legend Number of Pages
-data_min 0
-plot_min 0
-}
Modified: trunk/orca/INSTALL
==============================================================================
--- trunk/orca/INSTALL (original)
+++ trunk/orca/INSTALL Sat Jul 13 18:45:53 2002
@@ -1,92 +1,58 @@
Outline:
-1) Install Perl 5.005_02.
-2) Install necessary Perl modules.
- a) Install Math::IntervalSearch version 1.00 or greater.
- b) Install Digest::MD5 version 2.00 or greater.
- c) Install RRDs version 0.99.6 or greater.
-3) Decide where Orca's binaries, RRD, HTML, and percollator directories
- will reside. Make sure performance concerns are handled.
-4) Configure Orca.
-5) Install Orca.
-6) [Optional] Install percollator.
- a) Install the SE toolkit.
- b) Apply a patch to the SE 3.0 toolkit.
- c) Examine Orca/percollator programs.
- d) Run start_percol on all systems.
- e) Edit percollator.cfg.
- f) Run Orca.
-1) Install Perl 5.005_02.
+1) Install Perl 5.005_0[23].
- I have used only version version 5.005_02 of Perl with Orca.
- Because Orca makes very heavy use of references, it may or may not
- work with older versions of Perl. I welcome feedback if Orca works
- with older Perls.
-
- This step is too large to go into here. The bottom line is to
- follow the instructions at
+2) Decide where Orca's binaries, RRD, HTML, and orcallator directories
+ will reside. Make sure performance concerns are handled.
- http://language.perl.com/info/software.html
+3) Configure Orca.
-2) Install necessary Perl modules.
+4) Make, test and install necessary Perl modules.
+ b) Install Digest::MD5 version 2.00 or greater.
a) Install Math::IntervalSearch version 1.00 or greater.
+ c) Install RRDs version 0.99.29 or greater.
+ d) Install Storable 0.603 or greater.
- Download Math::IntervalSearch from either:
+5) Make Orca.
- ftp://ftp.gps.caltech.edu/pub/blair/Perl/Math-Interpolate-1.01.tar.gz
- http://www.perl.com/CPAN/authors/id/B/BZ/BZAJAC/Math-Interpolate-1.01.tar.gz
+6) Install Orca.
- % gunzip -c Math-Interpolate-1.01.tar.gz | tar xvf -
- % cd Math-Interpolate-1.01
- % perl Makefile.PL
- % make
- % make test
- % make install
+7) [Optional] Install orcallator.
+ a) If required, rename all percollator, percol and perc filenames to
+ orcallator.
+ b) Install the SE toolkit.
+ c) Apply a patch to the SE 3.0 toolkit.
+ d) Examine Orca/orcallator programs.
+ e) Run start_orcallator on all systems.
+ f) Edit orcallator.cfg.
+ g) Run Orca.
- b) Install Digest::MD5 version 2.00 or greater.
- Download Digest::MD5 from:
- http://www.perl.com/CPAN/authors/id/GAAS/Digest-MD5-2.02.tar.gz
- % gunzip -c Digest-MD5-2.02.tar.gz | tar xvf -
- % cd Digest-MD5-2.02
- % perl Makefile.PL
- % make
- % make test
- % make install
+1) Install Perl 5.005_0[23].
- c) Install RRDs version 0.99.6 or greater.
+ I have used only version 5.005_0[23] of Perl with Orca. Because Orca
+ makes very heavy use of references, it may or may not work with older
+ versions of Perl. I welcome feedback if Orca works with older Perls.
- Download RRDs from:
+ This step is too large to go into here. The bottom line is to follow
+ the instructions at
- http://ee-staff.ethz.ch/~oetiker/webtools/rrdtool/pub/
-
- % gunzip -c rrdtool-?.??.?.tar.gz | tar xvf -
- % cd rrdtool-?.??.?
- % sh configure --verbose
- % make [ To optimize: make CFLAGS=-O ]
- % cd perl-shared
- % perl Makefile.PL
- % make [ To optimize: make OPTIMIZE=-O ]
- % make test
- % make install
-
- For large installations, I recommend that RRD be compiled with
- optimization turned on.
+ http://language.perl.com/info/software.html
-3) Decide where Orca's binaries, RRD, HTML, and percollator directories
+2) Decide where Orca's binaries, RRD, HTML, and orcallator directories
will reside. Make sure performance concerns are handled.
First choose the location where Orca will be installed. By default,
Orca will install into the following structure:
- $prefix Prefix, set with --prefix=
- $prefix/bin Binaries, set with --bindir=
- $prefix/lib Libraries, set with --libdir=
- $prefix/man Manual pages, set with --mandir=
- $prefix/var/orca/rrd RRD directory, set with --with-rrd-dir
- $prefix/var/orca/percollator Percollator directory, set with --with-perc-dir
+ $prefix Prefix, set with --prefix=
+ $prefix/bin Binaries, set with --bindir=
+ $prefix/lib Libraries, set with --libdir=
+ $prefix/man Manual pages, set with --mandir=
+ $prefix/var/orca/rrd RRD directory, set with --with-rrd-dir
+ $prefix/var/orca/orcallator Orcallator directory, set with --with-orcallator-dir
By default $prefix is set to /usr/local. The -- arguments shown
above should be given to the configure script described below which
@@ -102,37 +68,37 @@
concerns it is more important this directory be locally stored than
HTML directory where the resulting HTML and GIF files are written.
- If you are going to use the percollator Orca addon to monitor your
+ If you are going to use the orcallator Orca addon to monitor your
Sun Solaris systems, then you will in addition need to decide where
- to have percollator store its data files. By default, these data
+ to have orcallator store its data files. By default, these data
files are written to once every 5 minutes, so IO is not an issue.
- The issue here is that percollator needs to run as root and all of
- the percollator output files from all your hosts need to be written
+ The issue here is that orcallator needs to run as root and all of
+ the orcallator output files from all your hosts need to be written
into the same NFS shared directory that Orca can read. It is not too
- important that the directory that percollator writes into be mounted
+ important that the directory that orcallator writes into be mounted
locally on the machine that Orca will run on, since Orca will only
read each file every five minutes.
- If you are running percollator on a system running a web, proxy,
- or Squid server, you can have percollator watch the logs generated
- by these programs. In this case, note the location of the log file
- for the configure script.
+ If you are running orcallator on a system running a web, proxy, or
+ Squid server, you can have orcallator watch the logs generated by
+ these programs. In this case, note the location of the log file for
+ the configure script.
-4) Configure Orca.
+3) Configure Orca.
Now that you have decided where the RRD, HTML, and optionally the
- percollator data files and the web server access logs, are located,
+ orcallator data files and the web server access logs, are located,
run the configure script with the following arguments:
% ./configure --prefix=ORCA_PREFIX_DIRECTORY \
--with-rrd-dir=RRD_DIR_LOCATION \
--with-html-dir=HTML_DIR_LOCATION \
- --with-perc-dir=PERCOLLATOR_DIR_LOCATION \
+ --with-orcallator-dir=ORCALLATOR_DIR_LOCATION \
--with-TYPE-log=LOG_LOCATION
If you choose nothing else, the --with-html-dir must always be used.
- If you use a web, proxy, or Squid server, you can have percollator
+ If you use a web, proxy, or Squid server, you can have orcallator
gather statistics from the log file. Use this table to decide which
configure option to use:
@@ -145,16 +111,126 @@
Configure will let you use only one of these --with-TYPE-log options.
The configure script will find where your version of Perl and some
- other assorted programs are located.
+ other assorted programs are located. It will also determine if you
+ have the necessary Perl modules to run Orca. If it does not find
+ the required modules, the modules that are included with the Orca
+ distribution will be built.
+
+4) Make, test and install necessary Perl modules.
+
+ Orca requires the following modules at the specified version number:
+
+ Name Required Version Included With Orca
+ -----------------------------------------------------------------------
+ Digest::MD5 version 2.00 or greater 2.07
+ Math::IntervalSearch 1.00 or greater 1.02
+ RRDs version 0.99.29 or greater 0.99.29
+ Storable 0.603 or greater 0.603
+
+ All four of these modules are included with the Orca distribution
+ in the packages directory. When you configured Orca in step 3),
+ configure should have determined if you need any of these modules
+ installed in the version of Perl that configure found. configure will
+ then modify the packages/Makefile file to only build those modules
+ that need to be installed.
+
+ All of the modules except for Math::IntervalSearch require a compiler
+ and generate shared libraries by default.
+
+ To make these modules run the following command:
+
+ % make modules [ To optimize: make modules CFLAGS=-O ]
-5) Install Orca.
+ To test if the modules are working properly, run the following command:
- Now run make and make install:
+ % make test_modules
+
+ To automatically install these modules into Perl run the following
+ command:
+
+ % make install_modules
+
+ If you want newer version of these modules, get them from the following
+ locations:
+
+ Math::IntervalSearch
+
+ ftp://ftp.gps.caltech.edu/pub/blair/Perl/Math-Interpolate-1.02.tar.gz
+ http://www.perl.com/CPAN/authors/id/B/BZ/BZAJAC/Math-Interpolate-1.02.tar.gz
+
+ % gunzip -c Math-Interpolate-1.02.tar.gz | tar xvf -
+ % cd Math-Interpolate-1.02
+ % perl Makefile.PL
+ % make
+ % make test
+ % make install
+
+ Digest::MD5
+
+ http://www.perl.com/CPAN/authors/id/GAAS/Digest-MD5-2.07.tar.gz
+
+ % gunzip -c Digest-MD5-2.07.tar.gz | tar xvf -
+ % cd Digest-MD5-2.07
+ % perl Makefile.PL
+ % make
+ % make test
+ % make install
+
+ RRDs
+
+ http://ee-staff.ethz.ch/~oetiker/webtools/rrdtool/pub/
+
+ RRDs is the Perl module that comes with RRDtool, a package written
+ by Tobias Oetiker. RRDtool contains a copy of the gd1.2 library
+ and is installed automatically into the RRDtool shared library that
+ is used by the RRDs Perl module. While gd1.3 exists, according
+ to its README file it generates larger GIFs. I see no reason to
+ link RRDtool with gd1.3.
+
+ % gunzip -c rrdtool-?.??.??.tar.gz | tar xvf -
+ % cd rrdtool-?.??.??
+ % sh configure --verbose
+ % make [ To optimize: make CFLAGS=-O ]
+ % cd perl-shared
+ % make test
+ % make install
+
+ For large installations, I recommend that RRDs be compiled with
+ optimization turned on.
+
+5) Make Orca.
+
+ Build Orca by running the following command:
% make
+
+6) Install Orca.
+
+ Between version 0.20 and 0.21 of Orca, a major name change occurred in
+ all of the installed and generated files. Any filenames containing
+ percollator, percol, and perc had the name orcallator substituted in
+ place. Percollator.se has been renamed to orcallator.se and its output
+ files are now named orcallator. The default percollator.cfg has been
+ renamed to orcallator.cfg and the version of orcallator.cfg included
+ here now looks for data filenames of the form orcallator-1999-05-08
+ and percol-1999-05-8. If you are running an Orca installation 0.20 or
+ older and want to rename all of the files and directories in your Orca
+ installation to the new scheme, then kill any running percollator.se's
+ and Orca processes. Then run
+
+ % make migrate
+
+ This will look through the all of the directories that Orca will
+ install into and use (namely the $prefix, $exec_prefix, $bindir,
+ $libdir, $ORCALLATOR_DIR, and $RRD_DIR directories) and perform any
+ necessary file renaming. Filenamess containing the word percent will
+ not have be modified to contain the word orcallatorent.
+
+ Now run the following command to install Orca:
+
% make install
-6) [Optional] Install percollator.
+7) [Optional] Install orcallator.
a) Install the SE toolkit.
Perform the installation instructions as listed on the web page
@@ -173,7 +249,7 @@
% cd /opt/RICHPse
% patch -s < THIS_DIR/patches/p_netstat_class.se.diff
- c) Examine Orca/percollator programs.
+ c) Examine Orca/orcallator programs.
Orca's installation scripts also installs several programs and
configuration files necessary to have Orca monitor many different
@@ -181,29 +257,33 @@
The following tools are installed in the $prefix/bin directory:
- start_percol - start percollator on a system
- stop_precol - stop percollator on a system
- restart_percol - restart percollator on a system
- percol_column - print selected columns from percollator output
- percol_running - run to see if any percollators are not running
+ start_orcallator - start orcallator on a system
+ stop_precol - stop orcallator on a system
+ restart_orcallator - restart orcallator on a system
+ orcallator_column - print selected columns from orcallator output
+ orcallator_running - run to see if any orcallators are not running
- d) Run start_percol on all systems.
+ d) Run start_orcallator on all systems.
Log in as root on all the systems you want to watch and run:
- % $prefix/bin/start_percol
+ % $prefix/bin/start_orcallator
+
+ Orcallator will not generate an output data file until the first
+ update interval, which will be between 2.5 to 7.5 minutes after
+ orcallator is started.
- e) Edit percollator.cfg.
+ e) Edit orcallator.cfg.
- You need to edit the installed percollator.cfg file and remove
+ You need to edit the installed orcallator.cfg file and remove
all unneeded references. In particular, you'll want to change
warn_email, which is the email address that receives emails when
- percollator generated files are out of date, which may signify a
- percollator program that has died and is no longer gathering data.
+ orcallator generated files are out of date, which may signify a
+ orcallator program that has died and is no longer gathering data.
f) Run Orca.
Log into the system that will run Orca and run the command:
% cd $prefix
- % ./bin/orca -v lib/percollator.cfg
+ % ./bin/orca -v lib/orcallator.cfg
Modified: trunk/orca/src/orcallator_running.pl.in
==============================================================================
--- trunk/orca/src/orcallator_running.pl.in (original)
+++ trunk/orca/src/orcallator_running.pl.in Sat Jul 13 18:45:53 2002
@@ -1,4 +1,4 @@
-# not_running: warn if percollator files are not up to date.
+# orcallator_running: warn if orcallator files are not up to date.
#
# Copyright (C) 1998, 1999 Blair Zajac and GeoCities, Inc.
Modified: trunk/orca/src/Makefile.in
==============================================================================
--- trunk/orca/src/Makefile.in (original)
+++ trunk/orca/src/Makefile.in Sat Jul 13 18:45:53 2002
@@ -1,14 +1,18 @@
+ at SET_MAKE@
+
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
MKDIR = @MKDIR@
INSTALL = @INSTALL@
PERL_HEAD = @PERL_HEAD@
-PERL_SCRIPTS = percol_running orca percol_column
-SHELL_SCRIPTS = restart_percol stop_percol start_percol
+ORCALLATOR_DIR = @ORCALLATOR_DIR@
+RRD_DIR = @RRD_DIR@
+PERL_SCRIPTS = orcallator_running orca orcallator_column
+SHELL_SCRIPTS = restart_orcallator stop_orcallator start_orcallator
TARGETS = $(PERL_SCRIPTS) $(SHELL_SCRIPTS)
-all: $(TARGETS)
+all: $(TARGETS) migrate_to_orcallator
install: all
$(MKDIR) $(bindir)
@@ -17,11 +21,14 @@
$(INSTALL) $$file $(bindir); \
done
+migrate: migrate_to_orcallator
+ ./migrate_to_orcallator $(prefix) $(exec_prefix) $(bindir) $(libdir) $(ORCALLATOR_DIR) $(RRD_DIR)
+
clean:
$(RM) $(TARGETS)
distclean: clean
- $(RM) *.sh percol_running.pl Makefile
+ $(RM) *.sh orcallator_running.pl Makefile
.SUFFIXES: .pl .sh
@@ -33,5 +40,22 @@
cp $< $@
chmod 0755 $@
-percol_running.pl: percol_running.pl.in
- cd ..; ./config.status
+Makefile: Makefile.in
+ (cd ..; ./config.status)
+ $(MAKE)
+
+orcallator_running.pl: orcallator_running.pl.in
+ (cd ..; ./config.status)
+ $(MAKE)
+
+restart_orcallator.sh: restart_orcallator.sh.in
+ (cd ..; ./config.status)
+ $(MAKE)
+
+start_orcallator.sh: start_orcallator.sh.in
+ (cd ..; ./config.status)
+ $(MAKE)
+
+stop_orcallator.sh: stop_orcallator.sh.in
+ (cd ..; ./config.status)
+ $(MAKE)
Modified: trunk/orca/src/restart_orcallator.sh.in
==============================================================================
--- trunk/orca/src/restart_orcallator.sh.in (original)
+++ trunk/orca/src/restart_orcallator.sh.in Sat Jul 13 18:45:53 2002
@@ -1,12 +1,12 @@
#!/bin/sh
-# This stops and restarts percollator.se.
+# This stops and restarts orcallator.se.
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
-# Kill any running percollators.
-$bindir/stop_percol
+# Kill any running orcallators.
+$bindir/stop_orcallator
-# Start the percollator.
-$bindir/start_percol
+# Start the orcallator.
+$bindir/start_orcallator
Modified: trunk/orca/src/stop_orcallator.sh.in
==============================================================================
--- trunk/orca/src/stop_orcallator.sh.in (original)
+++ trunk/orca/src/stop_orcallator.sh.in Sat Jul 13 18:45:53 2002
@@ -2,17 +2,17 @@
AWK=@AWK@
-# Kill any running percollators.
-pids=`/usr/ucb/ps auxww | $AWK '/percollator.se/ && !/awk/ {print $2}'`
+# Kill any running orcallators.
+pids=`/usr/ucb/ps auxww | $AWK '/orcallator.se/ && !/awk/ {print $2}'`
if test "$pids" != ""; then
echo "Killing pids $pids."
kill -HUP $pids
sleep 1
- pids=`/usr/ucb/ps auxww | $AWK '/percollator.se/ && !/awk/ {print $2}'`
+ pids=`/usr/ucb/ps auxww | $AWK '/orcallator.se/ && !/awk/ {print $2}'`
if test "$pids" != ""; then
kill -TERM $pids
sleep 1
- pids=`/usr/ucb/ps auxww | $AWK '/percollator.se/ && !/awk/ {print $2}'`
+ pids=`/usr/ucb/ps auxww | $AWK '/orcallator.se/ && !/awk/ {print $2}'`
if test "$pids" != ""; then
kill -9 $pids
sleep 1
Added: trunk/orca/src/migrate_to_orcallator.pl
==============================================================================
--- trunk/orca/src/migrate_to_orcallator.pl (original)
+++ trunk/orca/src/migrate_to_orcallator.pl Sat Jul 13 18:45:53 2002
@@ -0,0 +1,34 @@
+# migrate_to_orcallator: migrate from a percollator named installation to
+# an orcallator named install.
+#
+# Copyright (C) 1999 Blair Zajac and GeoCities, Inc.
+
+use strict;
+use File::Find;
+
+$| = 1;
+
+# Take a list of directories and rename every file in the directory using
+# the following translation in the following order:
+# percollator -> orcallator
+# percol -> orcallator
+# perc -> orcallator
+# Protect the word percent from this conversion.
+foreach my $dir (@ARGV) {
+ finddepth(\&rename, $dir) if -d $dir;
+}
+
+sub rename {
+ my $old_name = $_;
+ my $new_name = $_;
+ $new_name =~ s/percent/\200/g;
+ $new_name =~ s/percollator/orcallator/g;
+ $new_name =~ s/percol/orcallator/g;
+ $new_name =~ s/perc/orcallator/g;
+ $new_name =~ s/\200/percent/g;
+ if ($old_name ne $new_name) {
+ print "Renaming $File::Find::dir/$old_name\n";
+ rename("$File::Find::dir/$old_name", "$File::Find::dir/$new_name") or
+ warn "$0: cannot rename `$File::Find::dir/$old_name': $!\n";
+ }
+}
Modified: trunk/orca/src/orcallator_column.pl
==============================================================================
--- trunk/orca/src/orcallator_column.pl (original)
+++ trunk/orca/src/orcallator_column.pl Sat Jul 13 18:45:53 2002
@@ -1,4 +1,4 @@
-# percol_column: display selected columns from percollator output.
+# orcallator_column: display selected columns from orcallator output.
#
# Copyright (C) 1998, 1999 Blair Zajac and GeoCities, Inc.
Modified: trunk/orca/src/start_orcallator.sh.in
==============================================================================
--- trunk/orca/src/start_orcallator.sh.in (original)
+++ trunk/orca/src/start_orcallator.sh.in Sat Jul 13 18:45:53 2002
@@ -1,6 +1,6 @@
#!/bin/sh
-# This script runs percollator.se with the proper options for your site.
+# This script runs orcallator.se with the proper options for your site.
# Define program locations that will be needed.
prefix=@prefix@
@@ -25,8 +25,8 @@
# Export the environmental variables.
export OUTDIR WEB_LOG
-# Check if percollator is already running.
-pids=`/usr/ucb/ps auxww | $AWK '/percollator.se/ && !/awk/ {print $2}'`
+# Check if orcallator is already running.
+pids=`/usr/ucb/ps auxww | $AWK '/orcallator.se/ && !/awk/ {print $2}'`
if test "$pids" != ""; then
echo "Percollator already running. Exiting."
exit 1
@@ -53,11 +53,11 @@
# Now start the logging.
echo "Starting logging"
-$SE $LE_PATCH -DWATCH_OS $WATCH_HTTPD $libdir/percollator.se &
+$SE $LE_PATCH -DWATCH_OS $WATCH_HTTPD $libdir/orcallator.se &
-# Write the PID of percollator to a file to make killing easier.
+# Write the PID of orcallator to a file to make killing easier.
pid=$!
-echo $pid > $OUTDIR/percollator.pid
+echo $pid > $OUTDIR/orcallator.pid
-# Sleep for a couple of seconds to allow any percollator warnings to appear.
+# Sleep for a couple of seconds to allow any orcallator warnings to appear.
sleep 5
Modified: trunk/orca/src/orca.pl
==============================================================================
--- trunk/orca/src/orca.pl (original)
+++ trunk/orca/src/orca.pl Sat Jul 13 18:45:53 2002
@@ -17,13 +17,13 @@
# This is the version of Orca.
use vars qw($VERSION);
-$VERSION = '0.20';
+$VERSION = '0.21';
# This is the version number used in creating the DS names in RRDs.
-# This should be updated any time a new version of Orca needs some
-# new content in its RRD files. The DS name is a concatentation of
-# the string Orca with this string of digits.
-my $ORCA_RRD_VERSION = 19990215;
+# This should be updated any time a new version of Orca needs some new
+# content in its RRD files. The DS name is a concatentation of the
+# string Orca with this string of digits.
+my $ORCA_RRD_VERSION = 19990222;
# The number of seconds in one day.
my $day_seconds = 24*60*60;
@@ -31,19 +31,20 @@
# These define the different RRAs to create, how far back in time they
# go, how many primary data points go into a consolidated data point,
# and the default how to create RRAs. The first array holds the names
-# of the different plot types to create. The second array holds the number of
-# 300 intervals are used to create a consolidated data point. The third
-# array is the number of consolidated data points held in the RRA. The
-# first one is every 5 minutes for 200 hours, the second is every 30 minutes
-# for 31 days, the third is every 2 hours for 100 days, and the last is
-# every day for 3 years. The last array holds the number of days back in
-# time to plot in the GIF. Be careful to not increase this so much that the
-# number of data points to plot are greater than the number of pixels
-# available for the GIF, otherwise there will be a 30% slowdown due to
-# a reduction calculation to resample the data to the lower resolution for
-# the plot. For example, with 40 days of 2 hour data, there are 480 data
-# points. For no slowdown to occur, the GIF should be atleast 480 pixels
-# wide.
+# of the different plot types to create. The second array holds the
+# number of 300 intervals are used to create a consolidated data
+# point. The third array is the number of consolidated data points
+# held in the RRA. The first one is every 5 minutes for 200 hours, the
+# second is every 30 minutes for 31 days, the third is every 2 hours
+# for 100 days, and the last is every day for 3 years. The last array
+# holds the number of days back in time to plot in the GIF. Be
+# careful to not increase this so much that the number of data points
+# to plot are greater than the number of pixels available for the GIF,
+# otherwise there will be a 30% slowdown due to a reduction
+# calculation to resample the data to the lower resolution for the
+# plot. For example, with 40 days of 2 hour data, there are 480 data
+# points. For no slowdown to occur, the GIF should be atleast 480
+# pixels wide.
my @rra_plot_type = qw(daily weekly monthly yearly);
my @rra_pdp_count = ( 1, 6, 24, 288);
my @rra_row_count = ( 2400, 1488, 1200, 1098);
@@ -106,20 +107,18 @@
<table cellpadding=0 border=0>
<tr>
<td width=350 valign=center>
- <a href="http://www.geocities.com/ResearchTriangle/Thinktank/4996/">
- <img width=186 height=45 border=0 src="orca.gif" alt="Orca Home Page" >
- </a>
+ <a href="http://www.geocities.com/~bzking/">
+ <img width=186 height=45 border=0 src="orca.gif" alt="Orca Home Page"></a>
<br>
- <font FACE="Arial,Helvetica" SIZE=2>
+ <font FACE="Arial,Helvetica" size=2>
Orca-$::VERSION by
- <a href="http://www.geocities.com/ResearchTriangle/Thinktank/4996/">Blair Zajac</a>
+ <a href="http://www.geocities.com/~bzking/">Blair Zajac</a>
<a href="mailto:bzajac\@geostaff.com">bzajac\@geostaff.com</a>.
</font>
</td>
<td width=120 valign=center>
<a href="http://ee-staff.ethz.ch/~oetiker/webtools/rrdtool">
- <img width=120 height=34 border=0 src="rrdtool.gif" alt="RRDTool Home Page">
- </a>
+ <img width=120 height=34 border=0 src="rrdtool.gif" alt="RRDTool Home Page"></a>
</td>
</tr>
</table>
@@ -140,9 +139,9 @@
confess "$0: Orca::OpenFileHash::new passed wrong number of arguments.\n";
}
- my $class = shift;
+ my ($class, $max_elements) = @_;
- bless {_max_elements => shift,
+ bless {_max_elements => $max_elements,
_hash => {},
_weights => {},
_filenos => {},
@@ -173,8 +172,9 @@
sub add {
my ($self, $filename, $weight, $fd) = @_;
- # If there is an open file descriptor for this filename, then force it to
- # close. Then make space for the new file descriptor in the cache.
+ # If there is an open file descriptor for this filename, then force
+ # it to close. Then make space for the new file descriptor in the
+ # cache.
$self->close($filename);
$self->_close_extra($self->{_max_elements} - 1);
@@ -319,8 +319,8 @@
$self->{_buffer}{$filename} .= $buffer;
}
- # Find the first \n and return all the characters up to and including
- # that point.
+ # Find the first \n and return all the characters up to and
+ # including that point.
$pos = index($self->{_buffer}{$filename}, "\n");
my $line = '';
if ($pos != -1) {
@@ -340,8 +340,8 @@
package main;
-# Set up a cache of 150 open file descriptors. This leaves 255-150-3 = 102
-# file descriptors for other use in the program.
+# Set up a cache of 150 open file descriptors. This leaves 255-150-3
+# = 102 file descriptors for other use in the program.
use vars qw($open_file_cache);
$open_file_cache = Orca::OpenFileHash->new(150) unless $open_file_cache;
@@ -354,8 +354,8 @@
confess "$0: Orca::DataFile::new passed wrong number of arguments.\n";
}
- my $class = shift;
- my $filename = shift;
+ my ($class, $filename) = @_;
+
confess "$0: filename not passed to $class.\n" unless $filename;
my $self = bless {_filename => $filename,
_last_stat_time => -1,
@@ -391,10 +391,11 @@
sub update_stat {
my $self = shift;
- # Only update the stat if the previous stat occured more than one second
- # ago. This is used when this function is called immediately after the
- # object has been constructed and when we don't want to call two stat's
- # immediately. The tradeoff is to call time() instead.
+ # Only update the stat if the previous stat occured more than one
+ # second ago. This is used when this function is called immediately
+ # after the object has been constructed and when we don't want to
+ # call two stat's immediately. The tradeoff is to call time()
+ # instead.
my $time = time;
if ($time > $self->{_last_stat_time} + 1) {
my @stat = stat($self->{_filename});
@@ -445,7 +446,7 @@
package Orca::GIFFile;
-use RRDs 0.99011;
+use RRDs 0.99029;
use Carp;
sub new {
@@ -499,14 +500,16 @@
_my_rrd_list => [ &::unique(@$my_rrds_ref) ],
_plot_ref => $plot_ref,
_interval => int($config_files->{$files_key}{interval}+0.5),
- _expire => $config_options->{expire_gifs}
+ _expire => $config_options->{expire_gifs},
+ _gif_height => 0,
+ _gif_width => 0
}, $class;
# If the GIF already exists, then use its last modification time to
# calculate when it was last updated. If the file modification time
# is newer than the timestamp of the last data point entered, then
- # assume that the GIF needs to be recreated. This data will cause the
- # GIF to be created if the GIF does not exist.
+ # assume that the GIF needs to be recreated. This data will cause
+ # the GIF to be created if the GIF does not exist.
my $plot_end_time = $self->plot_end_time;
foreach my $plot_type (@rra_plot_type) {
$self->{"_${plot_type}_update_time"} = -1;
@@ -527,20 +530,32 @@
$self;
}
-sub rrds {
- @{$_[0]->{_my_rrd_list}};
+sub files_key {
+ $_[0]->{_files_key};
}
-sub plot_ref {
- $_[0]->{_plot_ref};
+sub gif_width {
+ $_[0]->{_gif_width};
}
-sub group {
- $_[0]->{_group};
+sub gif_height {
+ $_[0]->{_gif_height};
}
-sub files_key {
- $_[0]->{_files_key};
+# For this GIF return a string that can be used to size the image
+# properly in HTML. The output from this subroutine is either an
+# empty string or the size of the image.
+sub gif_img_src_size {
+ if ($_[0]->{_gif_height} and $_[0]->{_gif_width}) {
+ return "width=$_[0]->{_gif_width} height=$_[0]->{_gif_height}";
+ }
+ else {
+ return "";
+ }
+}
+
+sub group {
+ $_[0]->{_group};
}
sub name {
@@ -551,6 +566,14 @@
$_[0]->{_no_group_name};
}
+sub plot_ref {
+ $_[0]->{_plot_ref};
+}
+
+sub rrds {
+ @{$_[0]->{_my_rrd_list}};
+}
+
# Calculate the time of the last data point entered into the RRD that
# this gif will use.
sub plot_end_time {
@@ -584,17 +607,18 @@
sub _plot {
my ($self, $plot_type, $days_back, $rra_pdp_count) = @_;
- # Get the time stamp of the last data point entered into the RRDs that
- # are used to generate this GIF.
+ # Get the time stamp of the last data point entered into the RRDs
+ # that are used to generate this GIF.
my $plot_end_time = $self->plot_end_time;
- # Determine if the plot needs to be generated. First see if there has
- # been data flushed to the RRD that needs to be plotted. Otherwise,
- # see if the does not file exists or if the time corresponding to the
- # last data point is newer than the GIF. Take into account that a new
- # plot does not need to be generated until a primary data point has been
- # added. Primary data points are added after a data point falls into a
- # new bin, where the bin ends on multiples of the sampling iterval.
+ # Determine if the plot needs to be generated. First see if there
+ # has been data flushed to the RRD that needs to be plotted.
+ # Otherwise, see if the does not file exists or if the time
+ # corresponding to the last data point is newer than the GIF. Take
+ # into account that a new plot does not need to be generated until a
+ # primary data point has been added. Primary data points are added
+ # after a data point falls into a new bin, where the bin ends on
+ # multiples of the sampling iterval.
my $interval = $self->{_interval};
$rra_pdp_count = int($rra_pdp_count*300.0/$interval + 0.5);
$rra_pdp_count = 1 if $rra_pdp_count < 1;
@@ -609,7 +633,7 @@
my $group = $self->{_group};
my @options = (
'-e', $plot_end_time,
- '-v', $plot_ref->{y_legend},
+ '-v', ::replace_group_name($plot_ref->{y_legend}, $group),
'-t', ::replace_group_name($plot_ref->{title}, $group),
'-w', $plot_ref->{plot_width},
'-h', $plot_ref->{plot_height}
@@ -627,38 +651,62 @@
my $data_sources = @{$self->{_my_rrd_list}};
for (my $i=0; $i<$data_sources; ++$i) {
my $rrd_key = $self->{_my_rrd_list}[$i];
- my $rrd_filename = $self->{_all_rrd_ref}{$rrd_key}->filename;
- push(@options, "DEF:source$i=$rrd_filename:Orca$ORCA_RRD_VERSION:AVERAGE");
+ my $rrd = $self->{_all_rrd_ref}{$rrd_key};
+ my $rrd_filename = $rrd->filename;
+ my $rrd_version = $rrd->version;
+ push(@options, "DEF:average$i=$rrd_filename:Orca$rrd_version:AVERAGE");
}
+ my @legends;
+ my $max_legend_length = 0;
for (my $i=0; $i<$data_sources; ++$i) {
- my $legend = ::replace_group_name($plot_ref->{legend}[$i], $group);
- my $line_type = $plot_ref->{line_type}[$i];
- my $color = $plot_ref->{color}[$i];
- push(@options, "$line_type:source$i#$color:$legend");
+ my $legend = ::replace_group_name($plot_ref->{legend}[$i], $group);
+ my $line_type = $plot_ref->{line_type}[$i];
+ my $color = $plot_ref->{color}[$i];
+ push(@options, "$line_type:average$i#$color:$legend");
+ $legend =~ s:%:\200:g;
+ $legend =~ s:\200:%%:g;
+ my $legend_length = length($legend);
+ $max_legend_length = $legend_length if $legend_length > $max_legend_length;
+ push(@legends, $legend);
}
+
+ # Force a break between the plot legend and comments.
+ push(@options, 'COMMENT:\s',);
+
+ # Generate the legends containing the current, average, minimum, and
+ # maximum values on the plot.
for (my $i=0; $i<$data_sources; ++$i) {
- my $legend = ::replace_group_name($plot_ref->{legend}[$i], $group);
- $legend =~ s:%:\200:g;
- $legend =~ s:\200:%%:g;
- push(@options, "GPRINT:source$i:AVERAGE:Average $legend is %f",
- "GPRINT:source$i:LAST:Current $legend is %f");
- }
+ my $legend = $legends[$i];
+ $legend .= ' ' x ($max_legend_length - length($legend));
+ push(@options, "GPRINT:average$i:LAST:$legend Current\\: %f",
+ "GPRINT:average$i:AVERAGE:Average\\: %f",
+ "GPRINT:average$i:MIN:Min\\: %f",
+ "GPRINT:average$i:MAX:Max\\: %f\\l"
+ );
+ }
+ push(@options, 'COMMENT:\s',
+ 'COMMENT:Last data entered at ' .
+ localtime($plot_end_time) . '.');
my $gif_filename = "$self->{_gif_basename}-$plot_type.gif";
print " Creating `$gif_filename'.\n" if $opt_verbose > 1;
- my $graph_return = RRDs::graph $gif_filename,
- '-s', ($plot_end_time-$days_back*$day_seconds),
- @options;
+ my ($graph_return, $gif_width, $gif_height) =
+ RRDs::graph $gif_filename,
+ '-s', ($plot_end_time-$days_back*$day_seconds),
+ @options;
if (my $error = RRDs::error) {
warn "$0: warning: cannot create `$gif_filename': $error\n";
}
else {
$self->{$time_update_key} = $plot_end_time;
+ $self->{_gif_height} = $gif_height;
+ $self->{_gif_width} = $gif_width;
utime $plot_end_time, $plot_end_time, $gif_filename or
warn "$0: warning: cannot change mtime for `$gif_filename': $!\n";
- # Expire the GIF at the correct time using a META file if requested.
+ # Expire the GIF at the correct time using a META file if
+ # requested.
if ($self->{_expire}) {
if (open(META, "> $gif_filename.meta")) {
my $time =
@@ -678,11 +726,11 @@
}
sub _expire_string {
- my @gmtime = gmtime(shift);
- my ($wday) = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat')[$gmtime[6]];
+ my @gmtime = gmtime($_[0]);
+ my ($wday) = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat')[$gmtime[6]];
my ($month) = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep',
'Oct','Nov','Dec')[$gmtime[4]];
- my ($mday,$year,$hour,$min,$sec) = @gmtime[3,5,2,1,0];
+ my ($mday, $year, $hour, $min, $sec) = @gmtime[3,5,2,1,0];
if ($mday<10) {$mday = "0$mday";}
if ($hour<10) {$hour = "0$hour";}
if ($min<10) {$min = "0$min";}
@@ -712,6 +760,10 @@
$plot_ref,
$choose_data_sub) = @_;
+ unless (ref($choose_data_sub) eq 'CODE') {
+ confess "$0: Orca::RRDFile::new not passed a valid CODE ref for choosing data.\n";
+ }
+
# Remove any special characters from the unique name and do some
# replacements.
$name = &::strip_key_name($name);
@@ -736,10 +788,11 @@
$self->{_created_gifs} = {};
$self->{_plot_ref} = $plot_ref;
$self->{_interval} = int($config_files->{$files_key}{interval}+0.5);
+ $self->{_rrd_version} = $ORCA_RRD_VERSION;
- # See if the RRD file meets two requirements. The first is to see
- # if the last update time can be sucessfully read. The second is
- # to see if the RRD has an DS named "Orca$ORCA_RRD_VERSION". If
+ # See if the RRD file meets two requirements. The first is to see if
+ # the last update time can be sucessfully read. The second is to
+ # see if the RRD has an DS named "Orca$ORCA_RRD_VERSION". If
# neither one of these is true, then create a brand new RRD is
# created when data is first flushed to it.
$self->{_rrd_update_time} = -2;
@@ -760,12 +813,15 @@
close(RRDFILE) or
warn "$0: error in closing `$rrd_filename' for reading: $!\n";
- # Check the version number of file to the required version.
- if ($version eq $ORCA_RRD_VERSION) {
- $self->{_rrd_update_time} = $update_time;
- }
- elsif ($version) {
- warn "$0: old version $version RRD `$rrd_filename' found: will create new version $ORCA_RRD_VERSION file.\n";
+ # Compare the version number of file to the required version.
+ if (length($version)) {
+ if ($version >= $ORCA_RRD_VERSION) {
+ $self->{_rrd_update_time} = $update_time;
+ $self->{_rrd_version} = $version;
+ }
+ else {
+ warn "$0: old version $version RRD `$rrd_filename' found: will create new version $ORCA_RRD_VERSION file.\n";
+ }
}
else {
warn "$0: unknown version RRD `$rrd_filename' found: will create new version $ORCA_RRD_VERSION file.\n";
@@ -777,6 +833,10 @@
$self;
}
+sub version {
+ $_[0]->{_rrd_version};
+}
+
sub name {
$_[0]->{_name};
}
@@ -792,8 +852,7 @@
}
sub created_gifs {
- my $self = shift;
- values %{$self->{_created_gifs}};
+ values %{$_[0]->{_created_gifs}};
}
# Given a row of data from a source data file, take the required data
@@ -851,12 +910,12 @@
'-s', $interval,
$data_source);
- # Create the round robin archives. Take special care to not create two
- # RRA's with the same number of primary data points. This can happen
- # if the interval is equal to one of the consoldated intervals.
+ # Create the round robin archives. Take special care to not
+ # create two RRA's with the same number of primary data points.
+ # This can happen if the interval is equal to one of the
+ # consoldated intervals.
my $count = int($rra_row_count[0]*300.0/$interval + 0.5);
- my @one_pdp_option = ("RRA:AVERAGE:0.5:1:$count",
- "RRA:LAST:0.5:1:1");
+ my @one_pdp_option = ("RRA:AVERAGE:0.5:1:$count");
for (my $i=1; $i<@rra_pdp_count; ++$i) {
next if $interval > 300*$rra_pdp_count[$i];
@@ -865,8 +924,7 @@
push(@options, @one_pdp_option);
}
@one_pdp_option = ();
- push(@options, "RRA:AVERAGE:0.5:$rra_pdp_count:$rra_row_count[$i]",
- "RRA:LAST:0.5:$rra_pdp_count:1");
+ push(@options, "RRA:AVERAGE:0.5:$rra_pdp_count:$rra_row_count[$i]");
}
# Now do the actual creation.
@@ -900,7 +958,8 @@
return 0;
}
- # If there were no errors, then totally clear the hash to save memory.
+ # If there were no errors, then totally clear the hash to save
+ # memory.
delete $self->{_new_data};
$self->{_new_data} = {};
@@ -913,6 +972,7 @@
use Carp;
use Digest::MD5 qw(md5);
+use Storable 0.603 qw(dclone);
use vars qw(@ISA);
@ISA = qw(Orca::DataFile);
@@ -921,6 +981,20 @@
# return the correct data from the input file.
my %read_value_subs;
+# This is a static variable that lists all of the column names for a
+# particular files key.
+my %files_key_column_names;
+
+# This caches the reference to the array holding the column
+# descriptions for files that have their column descriptions in the
+# first line of the file.
+my %first_line_cache;
+
+# These are caches for the different objects that are used to add a
+# plot.
+my %all_rrds_cache;
+my %my_rrds_cache;
+
sub new {
unless (@_ == 10) {
confess "$0: Orca::SourceDataFile::new passed incorrect number of arguments.\n";
@@ -941,33 +1015,35 @@
$self->{_interval} = $interval;
$self->{_late_interval} = int(&$late_interval($interval) + 0.5);
$self->{_reopen} = $reopen;
- $self->{_column_description} = $column_description;
$self->{_date_source} = $date_source;
$self->{_date_format} = $date_format;
$self->{_warn_email} = $warn_email;
- $self->{_last_data_time} = -1;
- $self->{_last_read_time} = -1;
- $self->{_my_rrd_hash} = {};
+ $self->{_my_rrd_hash} = {};
$self->{_all_rrd_ref} = undef;
- $self->{_first_line} = 0;
+ $self->{_files_keys} = {};
+
+ $self->{_column_description} = $column_description;
+ $self->{_last_data_time} = -1;
+ $self->{_last_read_time} = -1;
+ $self->{_first_line} = 0;
$self->{_date_column_index} = undef;
- # There are three intervals associated with each file. The first is the
- # data update interval. This is the same interval used to generate the
- # RRDs. The second interval is the interval before the file is considered
- # late and is larger than the data update interval. This interval is
- # calculated by using the mathematical expression given in the
- # `late_interval' configuration option. If `late_interval' is not defined,
- # then it gets defaulted to the data update interval. The last interval is
- # the interval to use to tell the program when to attempt to read the file
- # next. Because it can take some time for the source files to be updated,
- # we don't want to read the file immediately after the data update interval
- # is done. For this reason, choose a read interval that is somewhere in
- # between the data source interval and the late interval. Use the
- # multiplicative average of the data update interval and the late interval
- # since the resulting value is closer to the data update interval. Ie:
- # (20 + 5)/2 = 12.5. Sqrt(20*5) = 10.
- #
+ # There are three intervals associated with each file. The first is
+ # the data update interval. This is the same interval used to
+ # generate the RRDs. The second interval is the interval before the
+ # file is considered late and is larger than the data update
+ # interval. This interval is calculated by using the mathematical
+ # expression given in the `late_interval' configuration option. If
+ # `late_interval' is not defined, then it gets defaulted to the data
+ # update interval. The last interval is the interval to use to tell
+ # the program when to attempt to read the file next. Because it can
+ # take some time for the source files to be updated, we don't want
+ # to read the file immediately after the data update interval is
+ # done. For this reason, choose a read interval that is somewhere
+ # in between the data source interval and the late interval. Use
+ # the multiplicative average of the data update interval and the
+ # late interval since the resulting value is closer to the data
+ # update interval. Ie: (20 + 5)/2 = 12.5. Sqrt(20*5) = 10.
my $read_interval = sqrt($self->{_interval}*$self->{_late_interval});
$self->{_read_interval} = int($read_interval + 0.5);
@@ -978,9 +1054,9 @@
}
}
- # Test if the file has been updated in the last _invterval number of
- # seconds. If so, then note it so we can see when the file is no longer
- # being updated.
+ # Test if the file has been updated in the last _interval number of
+ # seconds. If so, then note it so we can see when the file is no
+ # longer being updated.
$self->{_is_current} = $self->is_current;
return unless $self->get_column_names;
@@ -989,6 +1065,19 @@
$self;
}
+# For each files key store make a note of the column description names
+# that appear.
+sub add_files_keys {
+ my $self = shift;
+
+ foreach my $files_key (@_) {
+ $self->{_files_keys}{$files_key} = 1;
+ foreach my $description (@{$self->{_column_description}}) {
+ $files_key_column_names{$files_key}{$description} = 1;
+ }
+ }
+}
+
# Return 1 if the source data file is current or not. Alsot note the
# day that this test was performed. This lets the code ignore files
# that are not current because a new file was generated for the next
@@ -1001,16 +1090,17 @@
$self->last_stat_time <= $self->file_mtime + $self->{_late_interval};
}
-# This returns the time when the file should be next read. To calculate
-# the next read time, take into the account the time that it takes for
-# the file to be updated. In some sense, this is measured by the late
-# interval. Because we won't want to use the complete late interval,
-# take the multiplicative average instead of the summation average, since
-# the multiplicative average will result in an average closer to the smaller
-# of the two values. If the source file is current, then just add the
-# modified late interval to the last file modification time, otherwise
-# add the late interval to the last file stat time. Use the late interval
-# to watch old files so we don't spend as much time on them.
+# This returns the time when the file should be next read. To
+# calculate the next read time, take into the account the time that it
+# takes for the file to be updated. In some sense, this is measured
+# by the late interval. Because we won't want to use the complete
+# late interval, take the multiplicative average instead of the
+# summation average, since the multiplicative average will result in
+# an average closer to the smaller of the two values. If the source
+# file is current, then just add the modified late interval to the
+# last file modification time, otherwise add the late interval to the
+# last file stat time. Use the late interval to watch old files so we
+# don't spend as much time on them.
sub next_load_time {
my $self = shift;
@@ -1025,12 +1115,6 @@
}
}
-
-# This caches the reference to the array holding the column descriptions
-# for files that have their column descriptions in the first line of the
-# file.
-my %first_line_cache;
-
sub get_column_names {
my $self = shift;
@@ -1088,11 +1172,13 @@
$self;
}
-# These are caches for the different objects that are used to add a plot.
-my %all_rrds_cache;
-my %my_rrds_cache;
-
sub add_plots {
+ # Make sure that the user has called the add_files_keys method and
+ # inserted at least one key.
+ unless (keys %files_key_column_names) {
+ confess "$0: Orca::SourceDataFile::add_files_keys must be called before add_plots.\n";
+ }
+
unless (@_ == 8) {
confess "$0: Orca::SourceDataFile::add_plots passed wrong number of arguments.\n";
}
@@ -1106,10 +1192,17 @@
$rrd_data_files_ref,
$gif_files_ref) = @_;
- # See if we have already done all the work for a plot with this files_key,
- # group, and column description. Use an MD5 hash instead of a very long
- # key.
+ # See if we have already done all the work for a plot with this
+ # files_key, group, and column description. Use an MD5 hash instead
+ # of a very long key. Store into a hash the column names found in
+ # this file for this files key. Finally, create a hash keyed by
+ # column name with a value of the index into the column description
+ # array. for this files key.
my @column_description = @{$self->{_column_description}};
+ my %column_description;
+ for (my $i=0; $i<@column_description; ++$i) {
+ $column_description{$column_description[$i]} = $i;
+ }
my $plot_key = join("\200", $files_key, $group, @column_description);
my $cache_key = md5($plot_key);
if (defined $all_rrds_cache{$cache_key}) {
@@ -1125,20 +1218,20 @@
my $i = 0;
my $old_i = 0;
- # This is the main loop where we keep looking for plots to create until
- # all of the column descriptions have been compared against.
+ # This is the main loop where we keep looking for plots to create
+ # until all of the column descriptions have been compared against.
while ($handle_regexps or $i < @$config_plots) {
- # If we've reached an index value greater than the largest index in
- # the plots, then reset the index to the oldest regexp that still needs
- # to be completed.
+ # If we've reached an index value greater than the largest index
+ # in the plots, then reset the index to the oldest regexp that
+ # still needs to be completed.
if ($handle_regexps and $i >= @$config_plots) {
$i = $oldest_regexp_index;
}
my $plot = $config_plots->[$i];
- # Skip this plot if the files_key do not match. Increment the index
- # of the next plot to handle.
+ # Skip this plot if the files_key do not match. Increment the
+ # index of the next plot to handle.
if ($plot->{source} ne $files_key) {
if ($oldest_regexp_index == $i) {
$handle_regexps = 0;
@@ -1148,14 +1241,15 @@
next;
}
- # There are three cases to handle. The first is a single data source
- # with a single element that has a regular expression. In this case,
- # all of the columns are searched to match the regular expression. The
- # second case is two or more data sources and with one element in the
- # first data source that has a regular expression match. This may
- # generate more than one plot, while the first one will only generate
- # one plot. The final case to handle is when the previous two cases
- # are not true. The last column matched on is stored in @regexp_pos.
+ # There are three cases to handle. The first is a single data
+ # source with a single element that has a regular expression. In
+ # this case, all of the columns are searched to match the regular
+ # expression. The second case is two or more data sources and
+ # with one element in the first data source that has a regular
+ # expression match. This may generate more than one plot, while
+ # the first one will only generate one plot. The final case to
+ # handle is when the previous two cases are not true. The last
+ # column matched on is stored in @regexp_pos.
my $number_datas = @{$plot->{data}};
my $number_elements = @{$plot->{data}[0]};
my $has_regexp = $plot->{data}[0][0] =~ m:\(.+\):;
@@ -1174,30 +1268,29 @@
# In this case we're creating a whole new plot that will have as
# many data sources as their are columns that match the regular
- # expression. Start by making a deep copy of the plot. Be careful
- # not to make a deep copy of the creates reference, since it can
- # cause recursion in the Data::Dump.
+ # expression. Start by making a deep copy of the plot. Be
+ # careful not to make a deep copy of the creates reference,
+ # since it can cause recursion.
my $creates = delete $plot->{creates};
- my $d = Data::Dumper->Dump([$plot], [qw(plot)]);
- $plot->{creates} = $creates;
{
- local $SIG{__WARN__} = sub { die $_[0] };
- eval $d;
+ my $new_plot = dclone($plot);
+ $plot->{creates} = $creates;
+ $new_plot->{creates} = $creates;
+ $plot = $new_plot;
}
- die "$0: internal error: eval on\n $d\nOutput: $@\n" if $@;
# At this point we have a copy of plot. Now go through looking
- # for all the columns that match and create an additional data source
- # for each match.
+ # for all the columns that match and create an additional data
+ # source for each match.
my $regexp = $plot->{data}[0][0];
my $new_data_index = 0;
my $original_legend = $plot->{legend}[0];
- for (my $j=0; $j<@column_description; ++$j) {
- my $column_name = $column_description[$j];
+ foreach my $column_name (@column_description) {
my @matches = $column_name =~ /$regexp/;
next unless @matches;
$plot->{data}[$new_data_index] = [ $column_name ];
+
# Copy any items over that haven't been created for this new
# data source. Make sure that any new elements added to
# pcl_plot_append_elements show up here.
@@ -1266,9 +1359,9 @@
# Make a deep copy of the plot. In the string form of the plot
# replace all of the $1, $2, ... with what was matched in the
# first data source. The tricky one is to replace the regular
- # expression that did the match in the first place. Also, save a
- # copy of the creates array for this plot so it doesn't also get
- # dumped.
+ # expression that did the match in the first place. Also, save
+ # a copy of the creates array for this plot so it doesn't also
+ # get dumped.
my $creates = delete $plot->{creates};
my $d = Data::Dumper->Dump([$plot], [qw(plot)]);
$plot->{creates} = $creates;
@@ -1285,7 +1378,8 @@
}
die "$0: internal error: eval on\n $d\nOutput: $@\n" if $@;
- # Either increment the index or reset it to the oldest regexp index.
+ # Either increment the index or reset it to the oldest regexp
+ # index.
$old_i = $i;
$i = $plot->{flush_regexps} ? $oldest_regexp_index : $i + 1;
}
@@ -1294,110 +1388,126 @@
++$oldest_regexp_index unless $handle_regexps;
}
- # Convert the column names to an index into the @_ array. Make a copy
- # of the commands so that if we change anything, we're not changing the
- # original plot structure.
- my @column_commands;
- foreach my $command (@{$plot->{data}}) {
- push(@column_commands, [@$command]);
+ # Make a copy of the data's so that if we change anything, we're
+ # not changing the original plot structure. Look through each
+ # element of each data and look for names appearing in the column
+ # description array. If there is a match for this file, then
+ # convert the element to an index the @_ array where the data will
+ # be pulled from. If there is not a match, then see if the
+ # element matches a name from one of the other column names from
+ # the same files key. In this case the data argument for this
+ # file will not be used.
+ my @datas;
+ my $optional = $plot->{optional};
+ foreach my $one_data (@{$plot->{data}}) {
+ push(@datas, [@$one_data]);
}
my $match_any = 0;
- for (my $j=0; $j<@column_commands; $j++) {
- my $match_command = 0;
- for (my $k=0; $k<@{$column_commands[$j]}; ++$k) {
- my $element = $column_commands[$j][$k];
- for (my $l=0; $l<@column_description; ++$l) {
- if ($element eq $column_description[$l]) {
- $column_commands[$j][$k] = "\$_[$l]";
- $match_command = 1;
- }
+ for (my $j=0; $j<@datas; $j++) {
+ my $match_one_data = 0;
+ for (my $k=0; $k<@{$datas[$j]}; ++$k) {
+ my $element = $datas[$j][$k];
+ my $pos;
+ if (defined ($pos = $column_description{$element})) {
+ $datas[$j][$k] = "\$_[$pos]";
+ $match_one_data = 1;
+ }
+ elsif (defined $files_key_column_names{$files_key}{$element}) {
+ my $m = $old_i + 1;
+ warn "$0: $element in `data @{$plot->{data}[$j]}' in plot #$m not replaced since it is not in file `" . $self->filename . "'.\n" unless $optional;
+ $datas[$j] = undef;
+ last;
}
}
# If there were no substitutions, then warn about it.
- if (!$match_command and !$plot->{optional}) {
+ if (!$match_one_data and !$optional) {
my $m = $old_i + 1;
- warn "$0: warning: no substitutions performed for `@{$column_commands[$j]}' in plot #$m.\n";
+ warn "$0: warning: no substitutions performed for `data @{$plot->{data}[$j]}' in plot #$m in `" . $self->filename . "'.\n";
}
- $match_any = $match_any || $match_command;
+ $match_any = $match_any || $match_one_data;
}
- # Skip this plot if no matches were found and the the plot
- # is optional.
- next if (!$match_any and $plot->{optional});
+ # Skip this plot if no matches were found and the plot is
+ # optional.
+ next if (!$match_any and $optional);
# At this point we have a plot to create.
- # For each data source, create an executable subroutine that takes a
- # row of elements and returns the requested value. Also create an
- # unique Orca data file name for this plot and a name for this plot
- # that does not include the group.
+ # For each data source, create an executable subroutine that takes
+ # a row of elements and returns the requested value. Also create
+ # an unique Orca data file name for this plot and a name for this
+ # plot that does not include the group.
my @my_rrds;
my @no_group_name;
my @group_name;
- for (my $j=0; $j<@column_commands; ++$j) {
+ for (my $j=0; $j<@datas; ++$j) {
- my $expr = "sub {\n return @{$column_commands[$j]};\n}\n";
- my $expr_hash = md5($expr);
-
- my $choose_data_sub;
+ my $working_data = defined $datas[$j];
+ my $choose_data_sub = undef;
my $data_name = join('_', @{$plot->{data}[$j]});
- if (defined $read_value_subs{$expr_hash}) {
- $choose_data_sub = $read_value_subs{$expr_hash};
- }
- else {
- {
- local $SIG{__WARN__} = sub { die $_[0] };
- $choose_data_sub = eval $expr;
- }
- if ($@) {
- unless ($plot->{optional}) {
- my $m = $old_i + 1;
- warn "$0: warning: bad evaluation of commands for plot #$m.\nOutput: $@\n";
+
+ if ($working_data) {
+ my $expr = "sub {\n return @{$datas[$j]};\n}\n";
+ my $expr_hash = md5($expr);
+
+ unless (defined ($choose_data_sub = $read_value_subs{$expr_hash})) {
+ {
+ local $SIG{__WARN__} = sub { die $_[0] };
+ $choose_data_sub = eval $expr;
+ }
+ if ($@) {
+ unless ($optional) {
+ my $m = $old_i + 1;
+ warn "$0: warning: bad evaluation of commands for plot #$m `data @{$plot->{data}[$j]}'.\nOutput: $@\n";
+ }
+ $choose_data_sub = undef;
+ }
+ else {
+ $read_value_subs{$expr_hash} = $choose_data_sub;
}
- $choose_data_sub = sub { 0; };
- $data_name = 'ALL_ZEROS';
}
- $read_value_subs{$expr_hash} = $choose_data_sub;
}
my $name = "${files_key}_${group}_${data_name}";
push(@no_group_name, "${files_key}_${data_name}");
push(@group_name, $name);
- # Create a new RRD only if it doesn't already exist.
- unless (defined $rrd_data_files_ref->{$name}) {
- my $rrd_file = Orca::RRDFile->new($config_options,
- $config_files,
- $files_key,
- $group,
- $name,
- $plot,
- $choose_data_sub);
- $rrd_data_files_ref->{$name} = $rrd_file;
- }
- $self->{_all_rrd_ref} = $rrd_data_files_ref;
- $self->{_my_rrd_hash}{$name}++;
- push(@my_rrds, $name);
+ # Create a new RRD only if it doesn't already exist and if a
+ # valid get data subroutine is created.
+ if ($choose_data_sub) {
+ unless (defined $rrd_data_files_ref->{$name}) {
+ my $rrd_file = Orca::RRDFile->new($config_options,
+ $config_files,
+ $files_key,
+ $group,
+ $name,
+ $plot,
+ $choose_data_sub);
+ $rrd_data_files_ref->{$name} = $rrd_file;
+ }
+ $self->{_all_rrd_ref} = $rrd_data_files_ref;
+ $self->{_my_rrd_hash}{$name}++;
+ push(@my_rrds, $name);
+ }
}
# Generate a new plot for these data.
my $gif;
my $group_name = join(',', @group_name);
- if (defined $gif_files_ref->{hash}{$group_name}) {
- $gif = $gif_files_ref->{hash}{$group_name};
+ if (defined ($gif = $gif_files_ref->{hash}{$group_name})) {
$gif->add_rrds(@my_rrds);
}
else {
$gif = Orca::GIFFile->new($config_options,
- $config_files,
- $config_plots,
- $files_key,
- $group,
- join(',', @my_rrds),
- join(',', @no_group_name),
- $plot,
- $rrd_data_files_ref,
- \@my_rrds);
+ $config_files,
+ $config_plots,
+ $files_key,
+ $group,
+ join(',', @my_rrds),
+ join(',', @no_group_name),
+ $plot,
+ $rrd_data_files_ref,
+ \@my_rrds);
$gif_files_ref->{hash}{$group_name} = $gif;
push(@{$gif_files_ref->{list}}, $gif);
push(@{$config_plots->[$old_i]{creates}}, $gif);
@@ -1420,9 +1530,10 @@
my $filename = $self->filename;
- # Test to see if we should read the file. If the file has changed in
- # any way, then read it. If the file is now gone and we have an open
- # file descriptor for it, then read to the end of it and then close it.
+ # Test to see if we should read the file. If the file has changed
+ # in any way, then read it. If the file is now gone and we have an
+ # open file descriptor for it, then read to the end of it and then
+ # close it.
my $file_status = $self->status;
my $fd = $::open_file_cache->get_fd($filename);
my $load_data = $file_status != 0;
@@ -1436,9 +1547,9 @@
}
}
- # Test if the file was up to date and now is not. If so, then send a
- # message. Do not send a message if the file was current in the previous
- # day is now is not current today.
+ # Test if the file was up to date and now is not. If so, then send
+ # a message. Do not send a message if the file was current in the
+ # previous day is now is not current today.
my $old_is_current = $self->{_is_current};
my $old_is_current_day = $self->{_is_current_day};
my $current_day = (localtime($self->last_stat_time))[3];
@@ -1474,8 +1585,9 @@
return 0 unless $load_data;
- # Try to get a file descriptor to open the file. Skip the first line
- # if the first line is used for column descriptions.
+ # Try to get a file descriptor to open the file. Skip the first
+ # line if the first line is used for column descriptions.
+
my $opened_new_fd = !$fd;
unless ($fd) {
unless ($fd = $::open_file_cache->open($filename, $file_mtime)) {
@@ -1493,9 +1605,9 @@
while (my $line = <$fd>) {
my @line = split(' ', $line);
- # Skip this input line if 1) the file uses the first line to define the
- # column names, 2) the number of columns loaded is not equal to the
- # number of columns in the column description.
+ # Skip this input line if 1) the file uses the first line to
+ # define the column names, 2) the number of columns loaded is not
+ # equal to the number of columns in the column description.
if ($self->{_first_line} and @line != @{$self->{_column_description}}) {
warn "$0: number of columns in line $. of `$filename' does not match column description.\n";
next;
@@ -1504,9 +1616,10 @@
my $time = $use_file_mtime ? $self->file_mtime : $line[$date_column_index];
$last_data_time = $time if $time > $last_data_time;
- # If the file status from the source data file is greater than zero, then
- # it means the file has changed in some way, so we need to do updates for
- # all plots. Load the available data and push it to the plots.
+ # If the file status from the source data file is greater than
+ # zero, then it means the file has changed in some way, so we need
+ # to do updates for all plots. Load the available data and push
+ # it to the plots.
my $add = 0;
foreach my $rrd_key (keys %{$self->{_my_rrd_hash}}) {
my $result = $self->{_all_rrd_ref}{$rrd_key}->queue_data($time, @line);
@@ -1529,18 +1642,19 @@
$::open_file_cache->change_weight($filename, $file_mtime);
- # Now two special cases to handle. First, if the file was removed and
- # we had an open file descriptor to it, then close the file descriptor.
- # Second, if the file has a new device number or inode and we had a
- # already opened file descriptor to the file, then close the descriptor,
- # reopen it and read all the rest of the data. If neither of these
- # cases is true, then close the file if the file should be reopened
- # next time.
+ # Now two special cases to handle. First, if the file was removed
+ # and we had an open file descriptor to it, then close the file
+ # descriptor. Second, if the file has a new device number or inode
+ # and we had a already opened file descriptor to the file, then
+ # close the descriptor, reopen it and read all the rest of the data.
+ # If neither of these cases is true, then close the file if the file
+ # should be reopened next time.
if ($file_status == -1 or ($file_status == 2 and !$opened_new_fd)) {
$::open_file_cache->close($filename) or
warn "$0: warning: cannot close `$filename' for reading: $!\n";
if ($file_status != -1) {
- # Setting the last_read_time to -1 will force load_new_data to read it.
+ # Setting the last_read_time to -1 will force load_new_data to
+ # read it.
$self->{_last_read_time} = -1;
$number_added += $self->load_new_data;
}
@@ -1559,15 +1673,28 @@
package main;
+sub Usage {
+ die "usage: $0 [-o] [-v] config_file\n";
+}
+
while (@ARGV and $ARGV[0] =~ /^-\w/) {
my $arg = shift;
- ++$opt_verbose if $arg eq '-v';
- ++$opt_once_only if $arg eq '-o';
+ if ($arg eq '-o') {
+ ++$opt_once_only;
+ }
+ elsif ($arg eq '-v') {
+ ++$opt_verbose;
+ }
+ else {
+ Usage;
+ }
}
-die "usage: $0 [-o] [-v] config_file\n" unless @ARGV;
+Usage unless @ARGV;
-print "Orca Version $VERSION.\n" if $opt_verbose;
+if ($opt_verbose) {
+ print "Orca version $VERSION using RRDs version $RRDs::VERSION.\n";
+}
&main(@ARGV);
@@ -1662,13 +1789,13 @@
my $find_new_files = 1;
my $time_interval = get_time_interval($config_options->{find_times});
- # This hash holds the next time to load the data from all the files in
- # a particular group.
+ # This hash holds the next time to load the data from all the files
+ # in a particular group.
my %group_load_time;
for (;;) {
- # If Orca is being forced to find new files, then set up the variables
- # here. Determine the current time interval we're in.
+ # If Orca is being forced to find new files, then set up the
+ # variables here. Determine the current time interval we're in.
if ($force_find_files) {
$force_find_files = 0;
$find_new_files = 1;
@@ -1683,9 +1810,9 @@
scalar localtime, ".\n";
}
- # Get the list of files to watch and the plots that will be created.
- # If files have been previously found, then use those files in the
- # search for new ones.
+ # Get the list of files to watch and the plots that will be
+ # created. If files have been previously found, then use those
+ # files in the search for new ones.
$old_found_files_ref = $new_found_files_ref if $new_found_files_ref;
($found_new_files, $new_found_files_ref, $group_files_ref) =
&find_files($config_filename,
@@ -1697,8 +1824,8 @@
$rrd_data_files_ref,
$gif_files_ref);
- # Go through all of the groups and for each group and all of the files
- # in the group find the next load time in the future.
+ # Go through all of the groups and for each group and all of the
+ # files in the group find the next load time in the future.
undef %group_load_time;
foreach my $group (keys %$group_files_ref) {
my $group_load_time = 1e20;
@@ -1760,7 +1887,8 @@
$group_load_time{$group} = $group_load_time;
# Now that the source data files have been read, recalculate the
- # time to sleep to if the load time for this group is in the future.
+ # time to sleep to if the load time for this group is in the
+ # future.
if (time < $group_load_time) {
$sleep_till_time = $group_load_time unless $sleep_till_time;
$sleep_till_time = $group_load_time if $group_load_time < $sleep_till_time;
@@ -1769,11 +1897,11 @@
next unless $number_new_data_points;
$updated_source_files = 1;
- # Flush the data that has been loaded for each plot. To keep the
- # RRD that was just created in the system's cache, plot GIFs that
- # only depend on this RRD, since GIFs that depend upon two or more
- # RRDs will most likely be generated more than once and the other
- # required RRDs may not exist yet.
+ # Flush the data that has been loaded for each plot. To keep
+ # the RRD that was just created in the system's cache, plot GIFs
+ # that only depend on this RRD, since GIFs that depend upon two
+ # or more RRDs will most likely be generated more than once and
+ # the other required RRDs may not exist yet.
if ($opt_verbose) {
print "Flushing new data", $group ? " from $group" : "", ".\n";
}
@@ -1811,18 +1939,19 @@
# Return now if this loop is being run only once.
last if $opt_once_only;
- # Now decide if we need to find new files. If the time interval does
- # change, then find new files only if the new time interval is not -1,
- # which signifies that the time is before the first find_times.
+ # Now decide if we need to find new files. If the time interval
+ # does change, then find new files only if the new time interval
+ # is not -1, which signifies that the time is before the first
+ # find_times.
my $new_time_interval = get_time_interval($config_options->{find_times});
if ($time_interval != $new_time_interval) {
$find_new_files = 1 if $new_time_interval != -1;
$time_interval = $new_time_interval;
}
- # Sleep if the sleep_till_time has not passed. If sleep_till_time is
- # now defined, then loop immediately. Sleep at least one second if
- # we need to sleep at all.
+ # Sleep if the sleep_till_time has not passed. If sleep_till_time
+ # is now defined, then loop immediately. Sleep at least one
+ # second if we need to sleep at all.
if ($sleep_till_time) {
my $now = time;
if ($sleep_till_time > $now) {
@@ -1901,137 +2030,145 @@
}
$index_html->print("<hr>\n<font size=\"-2\">");
- # The first step is to create the HTML files for each different group.
- # This is only done if there is more than one group gathered from the
- # configuration and input data files. If there is more than one group
- # first list the different available groups and create for each group
- # an HTML file that contains HREFs to the GIFs for that group. Also
- # create an HTML file for the daily, weekly, monthly, and yearly GIFs.
+ # The first step is to create the HTML files for each different
+ # group. This is only done if there is more than one group gathered
+ # from the configuration and input data files. If there is more
+ # than one group first list the different available groups and
+ # create for each group an HTML file that contains HREFs to the GIFs
+ # for that group. Also create an HTML file for the daily, weekly,
+ # monthly, and yearly GIFs.
- # This variable sets the number of groups to place into a single row.
+ # This variable sets the number of groups to place into a single
+ # row.
my $table_number_columns = 9;
my @table_columns;
- # Go through each group.
- if (keys %$group_files_ref > 1) {
- $index_html->print("<h2>Available Targets</h2>\n\n<table>\n");
- foreach my $group (sort sort_group_names keys %$group_files_ref) {
-
- # Create the HTML code for the main index.html file.
- my $group_basename = strip_key_name($group);
- my $element = "<table border=2><tr><td><b>$group</b></td></tr>\n<tr><td>\n";
- foreach my $plot_type (@rra_plot_type) {
- $element .= "<a href=\"$group_basename-$plot_type.html\">";
- my $Plot_Type = Capatialize($plot_type);
- $element .= "$Plot_Type</a><br>\n";
- }
- $element .= "<a href=\"$group_basename-all.html\">All</a></td></tr>\n";
- $element .= "</table>\n\n";
-
- push(@table_columns, "<td>$element</td>");
- if (@table_columns == $table_number_columns) {
- $index_html->print("<tr valign=top>" . join('', @table_columns) . "</tr>\n");
- @table_columns = ();
- }
-
- # Create the daily, weekly, monthly, yearly, and all HTML files for
- # this group.
- my @html_files;
- foreach my $plot_type (@rra_plot_type, 'all') {
- my $href = "$group_basename-$plot_type.html";
- my $filename = "$html_dir/$href";
- my $Plot_Type = Capatialize($plot_type);
- my $fd = Orca::HTMLFile->new($filename,
- "$Plot_Type $group",
- $config_options->{html_page_header},
- $config_options->{html_page_footer});
- unless ($fd) {
- warn "$0: warning: cannot open `$filename' for writing: $!\n";
- next;
- }
- push (@html_files, {fd => $fd,
- href => $href,
- plot_type => $plot_type,
- Plot_Type => $Plot_Type});
- }
-
- # At the top of the daily, weekly, monthly, yearly, and all HTML files
- # add HREFs to the other date span HTML files in the same group
- my $href_html;
- foreach my $plot_type (@html_files) {
- $href_html .= "<a href=\"$plot_type->{href}\">" .
- "$plot_type->{Plot_Type} $group</a><br>\n";
+ # Go through each group. If there is only one group and that group
+ # does not have a name, then give the group the name Everything.
+ # However, only refer to the name Everything in naming HTML files
+ # and in HTML content. Use the original group name as a hash key.
+ my $number_groups = keys %$group_files_ref;
+ $index_html->print("<h2>Available Targets</h2>\n\n<table>\n");
+ foreach my $group (sort sort_group_names keys %$group_files_ref) {
+ my $html_group = ($number_groups == 1 and !$group) ? 'Everything' : $group;
+
+ # Create the HTML code for the main index.html file.
+ my $group_basename = strip_key_name($html_group);
+ my $element = "<table border=2><tr><td><b>$html_group</b></td></tr>\n<tr><td>\n";
+ foreach my $plot_type (@rra_plot_type) {
+ $element .= "<a href=\"$group_basename-$plot_type.html\">";
+ my $Plot_Type = Capatialize($plot_type);
+ $element .= "$Plot_Type</a><br>\n";
+ }
+ $element .= "<a href=\"$group_basename-all.html\">All</a></td></tr>\n";
+ $element .= "</table>\n\n";
+
+ push(@table_columns, "<td>$element</td>");
+ if (@table_columns == $table_number_columns) {
+ $index_html->print("<tr valign=top>" . join('', @table_columns) . "</tr>\n");
+ @table_columns = ();
+ }
+
+ # Create the daily, weekly, monthly, yearly, and all HTML files
+ # for this group.
+ my @html_files;
+ foreach my $plot_type (@rra_plot_type, 'all') {
+ my $href = "$group_basename-$plot_type.html";
+ my $filename = "$html_dir/$href";
+ my $Plot_Type = Capatialize($plot_type);
+ my $fd = Orca::HTMLFile->new($filename,
+ "$Plot_Type $html_group",
+ $config_options->{html_page_header},
+ $config_options->{html_page_footer});
+ unless ($fd) {
+ warn "$0: warning: cannot open `$filename' for writing: $!\n";
+ next;
+ }
+ push (@html_files, {fd => $fd,
+ href => $href,
+ plot_type => $plot_type,
+ Plot_Type => $Plot_Type});
+ }
+
+ # At the top of the daily, weekly, monthly, yearly, and all HTML
+ # files add HREFs to the other date span HTML files in the same
+ # group.
+ my $href_html;
+ foreach my $plot_type (@html_files) {
+ $href_html .= "<a href=\"$plot_type->{href}\">" .
+ "$plot_type->{Plot_Type} $group</a><br>\n";
+ }
+ foreach my $html_file (@html_files) {
+ $html_file->{fd}->print($href_html);
+ }
+
+ # Use only those GIFs now that have the same group name as the
+ # HTML files that are being created.
+ my @gifs = grep {$group eq $_->group} @{$gif_files_ref->{list}};
+ if (@gifs > 1) {
+ my $href_html = "<hr>";
+ for (my $i=0; $i<@gifs; ++$i) {
+ $href_html .= "<a href=\"#$i\">[" .
+ replace_group_name($gifs[$i]->plot_ref->{title}, '') .
+ "]</a><spacer size=10>\n";
}
foreach my $html_file (@html_files) {
$html_file->{fd}->print($href_html);
}
+ }
- # Use only those GIFs now that have the same group name as the HTML
- # files that are being created.
- my @gifs = grep {$group eq $_->group} @{$gif_files_ref->{list}};
- if (@gifs > 1) {
- my $href_html = "<hr>";
- for (my $i=0; $i<@gifs; ++$i) {
- $href_html .= "<a href=\"#$i\">[" .
- replace_group_name($gifs[$i]->plot_ref->{title}, '') .
- "]</a><spacer size=10>\n";
- }
- foreach my $html_file (@html_files) {
- $html_file->{fd}->print($href_html);
- }
- }
+ # Add the images to the HTML files.
+ for (my $i=0; $i<@gifs; ++$i) {
+ my $gif = $gifs[$i];
+ my $name = $gif->name;
+ my $title = replace_group_name($gif->plot_ref->{title}, $gif->group);
+ my $href = "href=\"" . strip_key_name($name) . ".html\"";
+ my $sub_dir = $config_files->{$gif->files_key}{sub_dir};
+ my $gif_size = $gif->gif_img_src_size;
- # Add the images to the HTML files.
- for (my $i=0; $i<@gifs; ++$i) {
- my $gif = $gifs[$i];
- my $name = $gif->name;
- my $title = replace_group_name($gif->plot_ref->{title}, $gif->group);
- my $href = "href=\"" . strip_key_name($name) . ".html\"";
- my $sub_dir = $config_files->{$gif->files_key}{sub_dir};
-
- foreach my $html_file (@html_files) {
- $html_file->{fd}->print("<hr>\n<h2><a ${href} name=\"$i\">$html_file->{Plot_Type} " .
- "$title</a></h2>\n");
- }
-
- # Put the proper GIFs into each HTML file. The all HTML file is
- # listed last and requires special handling.
- for (my $j=0; $j<@html_files-1; ++$j) {
- my $gif_filename = "$name-$html_files[$j]{plot_type}.gif";
- $gif_filename = "$group/$gif_filename" if $sub_dir;
- my $html = "<a $href><img src=\"$gif_filename\"" .
- "alt=\"$html_files[$j]{Plot_Type} $title\"></a>\n";
- $html_files[$j]{fd}->print($html);
- $html_files[-1]{fd}->print($html);
- }
+ foreach my $html_file (@html_files) {
+ $html_file->{fd}->print("<hr>\n<h2><a ${href} name=\"$i\">$html_file->{Plot_Type} " .
+ "$title</a></h2>\n");
}
- foreach my $html_file (@html_files) {
- $html_file->{fd}->print("<hr>\n");
+ # Put the proper GIFs into each HTML file. The all HTML file is
+ # listed last and requires special handling.
+ for (my $j=0; $j<@html_files-1; ++$j) {
+ my $gif_filename = "$name-$html_files[$j]{plot_type}.gif";
+ $gif_filename = "$group/$gif_filename" if $sub_dir;
+ my $html = "<a $href><img src=\"$gif_filename\" $gif_size " .
+ "alt=\"$html_files[$j]{Plot_Type} $title\"></a>\n";
+ $html_files[$j]{fd}->print($html);
+ $html_files[-1]{fd}->print($html);
}
}
- # If there are any remaining groups to display, do it now.
- if (@table_columns) {
- $index_html->print("<tr valign=top>" .
- join('', @table_columns) .
- "</tr>\n");
+ foreach my $html_file (@html_files) {
+ $html_file->{fd}->print("<hr>\n");
}
- $index_html->print("</table>\n\n\n<br>\n<hr>\n" .
- "<h2>Available Data Sets</h2>\n\n");
}
- # Here the different available plots are listed and the HTML files created
- # that contain the HREFs to the proper GIFs. The HTML files created here
- # HREF to the GIFs that are created for a single plot. There are several
- # steps to do here. First, get a list of the different plots. For each
- # different type of plot, create a list GIFs that show that plot. Use
- # the @gifs_by_type array to keep the ordering in the type of GIFs and
- # the %gifs_by_type to hold references to an array for each type of GIF.
+ # If there are any remaining groups to display, do it now.
+ if (@table_columns) {
+ $index_html->print("<tr valign=top>" .
+ join('', @table_columns) .
+ "</tr>\n");
+ }
+ $index_html->print("</table>\n\n\n<br>\n<hr>\n" .
+ "<h2>Available Data Sets</h2>\n\n");
+
+ # Here the different available plots are listed and the HTML files
+ # created that contain the HREFs to the proper GIFs. The HTML files
+ # created here HREF to the GIFs that are created for a single plot.
+ # There are several steps to do here. First, get a list of the
+ # different plots. For each different type of plot, create a list
+ # GIFs that show that plot. Use the @gifs_by_type array to keep the
+ # ordering in the type of GIFs and the %gifs_by_type to hold
+ # references to an array for each type of GIF.
$index_html->print("<table>\n");
- # This sets the number of plot types to place into a single row in the
- # main index.html.
+ # This sets the number of plot types to place into a single row in
+ # the main index.html.
$table_number_columns = 1;
@table_columns = ();
@@ -2040,13 +2177,14 @@
next unless @{$config_plots->[$i]{creates}};
- # Create an ordered list of GIFs sorted on the legend name for each
- # GIF. Remember, each GIF represented here actually represents the
- # set of daily, weekly, monthly, and yearly GIF files.
- # %gif_legend_no_group is a hash keyed by the GIF that contains the
- # legend with no group substitution for the GIF. The %legends hash
- # is keyed by the legend name with no group substitution and contains
- # a reference to an array of GIFs that have the same legend name.
+ # Create an ordered list of GIFs sorted on the legend name for
+ # each GIF. Remember, each GIF represented here actually
+ # represents the set of daily, weekly, monthly, and yearly GIF
+ # files. %gif_legend_no_group is a hash keyed by the GIF that
+ # contains the legend with no group substitution for the GIF. The
+ # %legends hash is keyed by the legend name with no group
+ # substitution and contains a reference to an array of GIFs that
+ # have the same legend name.
my %gif_legend_no_group;
my %same_legends_gif_list;
foreach my $gif (@{$config_plots->[$i]{creates}}) {
@@ -2060,8 +2198,8 @@
}
# Put together the correctly ordered list of GIFs using the array
- # references in the legends hash. Sort the GIFs using the
- # special sorting routine for group names.
+ # references in the legends hash. Sort the GIFs using the special
+ # sorting routine for group names.
my @gifs;
foreach my $legend_no_group (sort keys %same_legends_gif_list) {
@{$same_legends_gif_list{$legend_no_group}} =
@@ -2080,13 +2218,15 @@
my $no_group_name = strip_key_name($gif->no_group_name);
my $legend_no_group = $gif_legend_no_group{$gif};
- # If this is the first time that this legend has been seen in for
- # creating the proper HTML files, then create the new HTML files
- # and set up the top of them properly and place into the main
- # index.html the proper HREFs to these files.
+ # If this is the first time that this legend has been seen in
+ # for creating the proper HTML files, then create the new HTML
+ # files and set up the top of them properly and place into the
+ # main index.html the proper HREFs to these files.
unless (defined $legend_html_files{$legend_no_group}) {
- # Now create the HTML files for the daily, weekly, monthly, yearly,
- # and all plots. Use the legend name to create this list.
+
+ # Now create the HTML files for the daily, weekly, monthly,
+ # yearly, and all plots. Use the legend name to create this
+ # list.
$legend_html_files{$legend_no_group} = [];
foreach my $plot_type (@rra_plot_type, 'all') {
my $href = "$no_group_name-$plot_type.html";
@@ -2107,10 +2247,10 @@
Plot_Type => $Plot_Type});
}
- # For each of the daily, weekly, monthy, yearly and all HTML files
- # add at the top of the file HREFs to all of the daily, weekly,
- # monthly, yearly and all HTML files. Also add HREFs to the
- # different groups later on in the same HTML file.
+ # For each of the daily, weekly, monthy, yearly and all HTML
+ # files add at the top of the file HREFs to all of the daily,
+ # weekly, monthly, yearly and all HTML files. Also add HREFs
+ # to the different groups later on in the same HTML file.
my @legend_html_files = @{$legend_html_files{$legend_no_group}};
my $href_html;
foreach my $plot_type (@legend_html_files) {
@@ -2118,9 +2258,10 @@
"$plot_type->{Plot_Type} $legend_no_group</a><br>\n";
}
- # Add to the top of the file HREFs to all of the different groups in
- # the HTML file. This makes traversing the HTML page easier. Do
- # this if there are two or more groups in this HTML page.
+ # Add to the top of the file HREFs to all of the different
+ # groups in the HTML file. This makes traversing the HTML
+ # page easier. Do this if there are two or more groups in
+ # this HTML page.
if (@{$same_legends_gif_list{$legend_no_group}} > 1) {
$href_html .= "<hr>\n";
foreach my $legend_gif (@{$same_legends_gif_list{$legend_no_group}}) {
@@ -2146,10 +2287,11 @@
}
}
- # At this point the HTML files for this set of daily, weekly, monthly,
- # and yearly GIFs have been opened. Now create the summary HTML
- # file that contains only four GIF images, the daily, weekly, monthly,
- # and yearly GIFs for a particular plot for a particular group.
+ # At this point the HTML files for this set of daily, weekly,
+ # monthly, and yearly GIFs have been opened. Now create the
+ # summary HTML file that contains only four GIF images, the
+ # daily, weekly, monthly, and yearly GIFs for a particular plot
+ # for a particular group.
my $with_group_name = strip_key_name($gif->name);
my $legend_with_group = replace_group_name($gif->plot_ref->{title},
$gif->group);
@@ -2165,10 +2307,12 @@
my $sub_dir = $config_files->{$gif->files_key}{sub_dir};
my $gif_filename = $with_group_name;
$gif_filename = $gif->group . "/$gif_filename" if $sub_dir;
+ my $gif_size = $gif->gif_img_src_size;
foreach my $plot_type (@rra_plot_type) {
my $Plot_Type = Capatialize($plot_type);
$summarize_html->print("<hr>\n<h2>$Plot_Type $legend_with_group</h2>\n",
"<img src=\"$gif_filename-$plot_type.gif\"",
+ $gif_size,
"alt=\"$Plot_Type $legend_with_group\">\n");
}
@@ -2184,7 +2328,7 @@
my $Plot_Type = $legend_html_files[$i]{Plot_Type};
my $gif_filename = "$name-$legend_html_files[$i]{plot_type}.gif";
$gif_filename = "$group/$gif_filename" if $sub_dir;
- my $html = "<a $href><img src=\"$gif_filename\"" .
+ my $html = "<a $href><img src=\"$gif_filename\" $gif_size " .
"alt=\"$Plot_Type $group $legend_no_group\"></a>\n";
$legend_html_files[$i]{fd}->print("<hr>\n<h2><a ${href} name=\"$group\">$Plot_Type $group $legend_no_group</a></h2>\n");
$legend_html_files[$i]{fd}->print($html);
@@ -2202,7 +2346,8 @@
sub perl_glob {
my $regexp = shift;
- # The current directory tells where to open the directory for matching.
+ # The current directory tells where to open the directory for
+ # matching.
my $current_dir = @_ ? shift : '.';
# Remove all multiple /'s, since they will confuse perl_glob.
@@ -2212,32 +2357,37 @@
# regular expression and set the current directory to /.
$current_dir = '/' if $regexp =~ s:^/::;
- # Get the first file path element from the regular expression to match.
+ # Get the first file path element from the regular expression to
+ # match.
my @regexp_elements = split(m:/:, $regexp);
my $first_regexp = shift(@regexp_elements);
- # Find all of the files in the current directory that match the first
- # regular expression.
- opendir(GLOB_DIR, "$current_dir") or
- die "$0: error: cannot opendir `$current_dir': $!\n";
+ # Find all of the files in the current directory that match the
+ # first regular expression.
+ unless (opendir(GLOB_DIR, "$current_dir")) {
+ warn "$0: error: cannot opendir `$current_dir': $!\n";
+ return ();
+ }
my @matches = grep { /^$first_regexp$/ } readdir(GLOB_DIR);
closedir(GLOB_DIR) or
warn "$0: warning: cannot closedir `$current_dir': $!\n";
- # If we're in the last regular expression match, then just return the
- # matches with the current directory prepended.
+ # If the last path element is being used as the regular expression,
+ # then just return the list of matching files with the current
+ # directory prepended.
unless (@regexp_elements) {
- return map { "$current_dir/$_" } @matches;
+ return grep { -f } map { "$current_dir/$_" } @matches;
}
# Otherwise we need to look into the directories below the current
- # directory. Also create the next regular expression to use that
- # is made up of the remaining file path elements.
+ # directory. Also create the next regular expression to use that is
+ # made up of the remaining file path elements. Make sure not to
+ # process any directories named `..'.
my @results;
my $new_regexp = join('/', @regexp_elements);
- foreach my $new_dir (grep { -d "$current_dir/$_" } @matches) {
+ foreach my $new_dir (grep { $_ ne '..' and -d "$current_dir/$_" } @matches) {
my $new_current = "$current_dir/$new_dir";
$new_current =~ s:/{2,}:/:g;
push(@results, perl_glob($new_regexp, $new_current));
@@ -2267,8 +2417,8 @@
}
}
-# Replace any %g with the group and any %G's with a capitalized version of
-# the group in the title string with the group name.
+# Replace any %g with the group and any %G's with a capitalized
+# version of the group in the title string with the group name.
sub replace_group_name {
my ($title, $group) = @_;
@@ -2340,8 +2490,8 @@
next;
}
- # Calculate which group the file belongs in and create a hash listing
- # the filenames for each group.
+ # Calculate which group the file belongs in and create a hash
+ # listing the filenames for each group.
my %tmp_files_by_group;
my %tmp_group_by_file;
foreach my $filename (unique(@filenames)) {
@@ -2350,7 +2500,8 @@
foreach my $regexp (@{$config_files->{$files_key}{find_files}}) {
my @result = ($filename =~ $regexp);
if (@result) {
- # There there are no ()'s in the regexp, then change (1) to ().
+ # There there are no ()'s in the regexp, then change (1) to
+ # ().
@result = () if (@result == 1 and $result[0] eq '1');
# Remove any empty matches from @result.
$group = join('_', grep {length($_)} @result);
@@ -2378,33 +2529,48 @@
# Now for each file, create the Orca::SourceDataFile object that
# manages that file and the GIFs that get generated from the file.
- foreach my $filename (@filenames) {
- # Create the object that contains this file. Take care if the same
- # file is being used in another files group.
+ # Delete from the list of filenames those files that have
+ # successfully created Orca::SourceDataFile objects.
+ for (my $i=0; $i<@filenames;) {
+ my $filename = $filenames[$i];
+ # Create the object that contains this file. Take care if the
+ # same file is being used in another files group.
unless (defined $new_found_files_ref->{$filename}) {
if (defined $old_found_files_ref->{$filename}) {
$new_found_files_ref->{$filename} = $old_found_files_ref->{$filename};
}
else {
print " $filename\n" if $opt_verbose;
- my $data_file =
+ my $data_file =
Orca::SourceDataFile->new($filename,
- $config_files->{$files_key}{interval},
- $config_options->{late_interval},
- $config_files->{$files_key}{reopen},
- $config_files->{$files_key}{column_description},
- $config_files->{$files_key}{date_source},
- $config_files->{$files_key}{date_format},
- $config_options->{warn_email},
- $saved_source_file_state);
+ $config_files->{$files_key}{interval},
+ $config_options->{late_interval},
+ $config_files->{$files_key}{reopen},
+ $config_files->{$files_key}{column_description},
+ $config_files->{$files_key}{date_source},
+ $config_files->{$files_key}{date_format},
+ $config_options->{warn_email},
+ $saved_source_file_state);
unless ($data_file) {
warn "$0: warning: cannot process `$filename'.\n";
+ splice(@filenames, $i, 1);
next;
}
$new_found_files_ref->{$filename} = $data_file;
$found_new_files = 1;
}
}
+ ++$i;
+ }
+
+ # Register with each source data file the files keys that use it.
+ foreach my $filename (@filenames) {
+ $new_found_files_ref->{$filename}->add_files_keys($files_key);
+ }
+
+ # Go through each source data file and register the new plots to
+ # create.
+ foreach my $filename (@filenames) {
my $group = $tmp_group_by_file{$filename};
$new_found_files_ref->{$filename}->add_plots($config_options,
$config_files,
@@ -2446,14 +2612,15 @@
print "Loading state from `$state_file'.\n" if $opt_verbose;
- # Get the first line which contains the hash key name. Check that the
- # first field is _filename.
- # key names match what is stored in this script.
+ # Get the first line which contains the hash key name. Check that
+ # the first field is _filename.
my $line = <STATE>;
+ defined($line) or return \%state;
chomp($line);
my @keys = split(' ', $line);
unless ($keys[0] eq '_filename') {
warn "$0: warning: ignoring state file `$state_file': incorrect first field.\n";
+ return \%state;
}
while (<STATE>) {
@@ -2542,12 +2709,12 @@
'ff0000', # Red
'a020f0', # Magenta
'ffa500', # Orange
- 'a52a2a', #
- '00ffff'); #
+ 'a52a2a', # Brown
+ '00ffff'); # Cyan
}
- # If data_dir is not set, then use base_dir. Only die if both
- # are not set.
+ # If data_dir is not set, then use base_dir. Only die if both are
+ # not set.
unless (defined $config_options->{data_dir}) {
if (defined $config_options->{base_dir}) {
$config_options->{data_dir} = $config_options->{base_dir};
@@ -2636,17 +2803,17 @@
}
}
- # Optional files options will be set to '' here if they haven't been set
- # by the user.
+ # Optional files options will be set to '' here if they haven't
+ # been set by the user.
foreach my $option (@cc_optional_files) {
unless (defined $config_files->{$files_key}{$option}) {
$config_files->{$files_key}{$option} = '';
}
}
- # Check that the date_source is either column_name followed by a column
- # name or file_mtime for the file modification time. If a column_name
- # is used, then the date_format is required.
+ # Check that the date_source is either column_name followed by a
+ # column name or file_mtime for the file modification time. If a
+ # column_name is used, then the date_format is required.
my $date_source = $config_files->{$files_key}{date_source}[0];
if ($date_source eq 'column_name') {
unless (@{$config_files->{$files_key}{date_source}} == 2) {
@@ -2666,16 +2833,28 @@
# Check that we have a valid regular expression for find_files and
# get a unique list of them. Also to see if the find_files match
# contains any ()'s that will split the files into groups. If so,
- # then we will use subdirectories to create our structure.
+ # then we will use subdirectories to create our structure. If a
+ # find begins with \./, then remove it from the path. Be careful
+ # of a search on only \./. Also remove any /\./'s in the path.
+ # Searches on both of these are unnecessary, since they involve
+ # searching on a current directory. However, do not remove /./'s
+ # since this will match single character files and directories.
my $sub_dir = 0;
my %find_files;
- foreach my $watch (@{$config_files->{$files_key}{find_files}}) {
+ my $number_finds = @{$config_files->{$files_key}{find_files}};
+ for (my $i=0; $i<$number_finds; ++$i) {
+ my $orig_find = $config_files->{$files_key}{find_files}[$i];
+ my $find = $orig_find;
+ $find =~ s:^\\./::;
+ $find =~ s:/\\./:/:g;
+ $find = $orig_find unless $find;
+ $config_files->{$files_key}{find_files}[$i] = $find;
my $test_string = 'abcdefg';
local $SIG{__WARN__} = sub { die $_[0] };
- eval { $test_string =~ /$watch/ };
- die "$0: error: illegal regular expression in `find_files $watch' for `files $files_key' in `$config_filename':\n$@\n" if $@;
- $find_files{$watch}++;
- $sub_dir = 1 if $watch =~ m:\(.+\):;
+ eval { $test_string =~ /$find/ };
+ die "$0: error: illegal regular expression in `find_files $orig_find' for `files $files_key' in `$config_filename':\n$@\n" if $@;
+ $find_files{$find}++;
+ $sub_dir = 1 if $find =~ m:\(.+\):;
}
$config_files->{$files_key}{find_files} = [sort keys %find_files];
$config_files->{$files_key}{sub_dir} = $sub_dir || $config_options->{sub_dir};
@@ -2696,12 +2875,12 @@
}
}
- # Create an array for each plot that will have a list of GIFs that were
- # generated from this plot.
+ # Create an array for each plot that will have a list of GIFs that
+ # were generated from this plot.
$config_plots->[$i]{creates} = [];
- # Optional options will be set to '' here if they haven't been set by the
- # user.
+ # Optional options will be set to '' here if they haven't been set
+ # by the user.
foreach my $option (@cc_optional_plots) {
unless (defined $config_plots->[$i]{$option}) {
$config_plots->[$i]{$option} = '';
@@ -2712,7 +2891,8 @@
$config_plots->[$i]{plot_width} = 500 unless $config_plots->[$i]{plot_width};
$config_plots->[$i]{plot_height} = 125 unless $config_plots->[$i]{plot_height};
- # Set the plot minimum and maximum values to U unless they are set.
+ # Set the plot minimum and maximum values to U unless they are
+ # set.
unless (defined $config_plots->[$i]{data_min}) {
$config_plots->[$i]{data_min} = 'U';
}
@@ -2736,7 +2916,7 @@
$config_plots->[$i]{data_type} = 'DERIVE';
}
else {
- die "$0: error: `data_type $config_plots->[$i]{data_type}' for `plot' #$j in `$config_filename' must be gauge, counter, or absolute.\n";
+ die "$0: error: `data_type $config_plots->[$i]{data_type}' for `plot' #$j in `$config_filename' must be gauge, counter, derive, or absolute.\n";
}
}
else {
@@ -2792,14 +2972,14 @@
}
}
- # If the generic y_legend is not set, then set it equal to the first
- # legend.
+ # If the generic y_legend is not set, then set it equal to the
+ # first legend.
unless (defined $config_plots->[$i]{y_legend}) {
$config_plots->[$i]{y_legend} = $config_plots->[$i]{legend}[0];
}
- # If the title is not set, then set it equal to all of the legends with
- # the group name prepended.
+ # If the title is not set, then set it equal to all of the legends
+ # with the group name prepended.
unless (defined $config_plots->[$i]{title}) {
my $title = '%G ';
for (my $k=0; $k<$number_datas; ++$k) {
@@ -2843,13 +3023,14 @@
}
}
-# These are state variables for reading the config file. The $files_key
-# variable holds the name of the file parameter when a file configuration
-# is being defined. If $files_key is '', then the a file configuration is
-# not being read. $plot_index is a string that represents a number that
-# is used as an index into @plots. If the string is negative, including
-# -0, then the plot configuration is not being defined, otherwise it holds
-# the index into the @plots array the is being defined.
+# These are state variables for reading the config file. The
+# $files_key variable holds the name of the file parameter when a file
+# configuration is being defined. If $files_key is '', then the a
+# file configuration is not being read. $plot_index is a string that
+# represents a number that is used as an index into @plots. If the
+# string is negative, including -0, then the plot configuration is not
+# being defined, otherwise it holds the index into the @plots array
+# the is being defined.
my $pcl_files_key;
my $pcl_plot_index;
@@ -2930,8 +3111,9 @@
my @line = split(' ', $line);
my $key = lc(shift(@line));
- # Warn if there is no option and it requires an option. Turn on options
- # that do not require an option argument and do not supply one.
+ # Warn if there is no option and it requires an option. Turn on
+ # options that do not require an option argument and do not supply
+ # one.
if ($key ne '}') {
if (grep { $key eq $_} @pcl_no_arg_elements) {
push(@line, 1) unless @line;
@@ -2944,20 +3126,24 @@
}
}
- # Prepend the base_dir to paths that are not prepended by /.
+ # Clean up paths. Prepend the base_dir to paths that are not
+ # prepended by ^\\?\.{0,2}/, which matches /, ./, ../, and \./.
+ # Then, remove any //'s.
my $base_dir = defined $config_options->{base_dir} ?
$config_options->{base_dir} : '';
- if ( $base_dir and grep {$key eq $_} @pcl_filepath_elements) {
+ if (grep {$key eq $_} @pcl_filepath_elements) {
foreach my $path (@line) {
- $path = "$base_dir/$path" unless $path =~ m:^/:;
- $path =~ s:/{2,}:/:
+ if ($base_dir) {
+ $path = "$base_dir/$path" unless $path =~ m:^\\?\.{0,2}/:;
+ }
+ $path =~ s:/{2,}:/:g;
}
}
my $value = "@line";
- # Process the line differently if we're reading for a particular option.
- # This one is for files.
+ # Process the line differently if we're reading for a particular
+ # option. This one is for files.
if ($pcl_files_key) {
if ($key eq '}') {
$pcl_files_key = '';
@@ -3068,9 +3254,9 @@
my %files;
my @plots;
- # Load in all lines in the file and then process them. If a line begins
- # with whitespace, then append it to the previously read line and do
- # not process it.
+ # Load in all lines in the file and then process them. If a line
+ # begins with whitespace, then append it to the previously read line
+ # and do not process it.
my $complete_line = '';
my $line_number = 1;
while (<CONFIG>) {
@@ -3078,7 +3264,8 @@
# Skip lines that begin with #.
next if /^#/;
- # If the line begins with whitespace, then append it to the previous line.
+ # If the line begins with whitespace, then append it to the
+ # previous line.
if (/^\s+/) {
$complete_line .= " $_";
next;
@@ -3144,8 +3331,8 @@
* Can be run under cron or it can sleep itself waiting for file updates
based on when the file was last updated.
-Orca is based the the RRD tool by Tobias Oetiker. While it is similar to
-the other tools based on RRD, such as Cricket and MRTG, it is significantly
+Orca is based the RRD tool by Tobias Oetiker. While it is similar to the
+other tools based on RRD, such as Cricket and MRTG, it is significantly
different. To see these other tools, examine
http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html
@@ -3158,7 +3345,7 @@
A small static example of Orca is at
- http://www.geocities.com/ResearchTriangle/Thinktank/4996/orca-example/
+ http://www.geocities.com/~bzking/orca-example/
Please inform me of any other sites using Orca and I will include them
here.
@@ -3195,8 +3382,8 @@
The first step in using Orca is to set up a configuration file that
instructs Orca on what to do. The configuration file is based on a
key/value pair structure. The key name must start at the beginning of
-a line. Lines that begin with whitespace are concatenated onto the the
-last key's value. This is the same format as used by MRTG and Cricket.
+a line. Lines that begin with whitespace are concatenated onto the last
+key's value. This is the same format as used by MRTG and Cricket.
There are three main groups of options in a Orca confg: general options,
file specific options, and plot specific options. General options may
@@ -3281,7 +3468,7 @@
B<warn_email> takes a list of email addresses of people to email
when something goes wrong with either Orca or the input data files.
-Currently email messages are sent out the the following circumstances:
+Currently email messages are sent out the following circumstances:
1) When a file did exist and now is gone.
2) When a file was being updated regularly and then no longer is updated.
@@ -3657,7 +3844,7 @@
incrementing counters like the InOctets counter in a router. The
B<COUNTER> data source assumes that the counter never decreases, except
when a counter overflows. The update function takes the overflow into
-account. B<DERIVE> will store the the derivative of the line going from
+account. B<DERIVE> will store the derivative of the line going from
the last to the current value of the data source. This can be useful for
counters which do raise and fall, for example, to measure the rate of
people entering or leaving a room. B<DERIVE> does not test for overflow.
Modified: trunk/orca/docs/ARCHITECTURE
==============================================================================
--- trunk/orca/docs/ARCHITECTURE (original)
+++ trunk/orca/docs/ARCHITECTURE Sat Jul 13 18:45:53 2002
@@ -1,10 +1,10 @@
+This incomplete file describes Orca's internal design.
+
Orca::OpenFileHash
Orca::HTMLFile
Orca::DataFile
Orca::SourceDataFile
-This file describes Orca's internal design.
-
Orca makes use of several internal classes (objects). They are:
Orca::OpenFileHash
Modified: trunk/orca/CHANGES
==============================================================================
--- trunk/orca/CHANGES (original)
+++ trunk/orca/CHANGES Sat Jul 13 18:45:54 2002
@@ -1,5 +1,217 @@
+Mon May 17 16:26:17 PDT 1999
+
+ Release version 0.21.
+
+Mon May 17 15:07:33 PDT 1999
+
+ Correct a bug when a source data file cannot be loaded it should
+ not used to look up a Orca::SourceDataFile object.
+
+ Reformat all the comments in orca.pl.
+
+Thu May 13 10:47:41 PDT 1999
+
+ Orca used to delete RRD files if they had an $ORCA_RRD_VERSION
+ number newer then the required version number. Now use them.
+ Add code to remember the Orca RRD version number so that the
+ GIF creation code works properly with RRD files with a version
+ different than $ORCA_RRD_VERSION.
+
+ Thanks to a configure file and some data from from Eric Blaise
+ <Eric.Blaise at socgen.com>, Orca can now handle plots containing
+ columns of data that do not exist in all input source data files.
+
+ In add_plots, a linear search was used to convert column
+ description names appearing in data statements to an index into
+ the column_description array. Now use a hash table look up.
+
+Wed May 12 09:31:43 PDT 1999
+
+ Orca now cleans up all file paths in the input configuration file.
+ If more than one / are found in a row, they are replaced by one /.
+ The base_dir is only prepended to paths if the path does not
+ match ^\\?\.{0,2}/, which will match on /, ./, ../, and \./.
+
+ The paths used to find input files are now passed through
+ the following regular expressions: s:^\\./:: and s:/\\./:/:g.
+ These remove unneccessary searches through the current directory.
+
+ Perl_glob will only return found files and no other type.
+ It will also not follow any directories named `..'.
+
+ Include RRDtool 0.99.29.1 with Orca. This includes a Makefile
+ patch and does not include a new version of RRDs.pm or librrd.
+
+ In any Makefile.in's that run config.status, they used to run
+ a make from the top level directory. Now they only run a make
+ from the directory that required the running of config.status.
+
+Tue May 11 16:24:09 PDT 1999
+
+ In places where deep copies of data structures are made and no
+ s///'s are performed on the text form of data, use dclone that
+ comes with Storable instead of using Data::Dumper and eval.
+
+ Do not prepend base_dir to any paths if they begin with either
+ `/' or `./'.
+
+ Require and include RRDtool 0.99.29 with Orca.
+
+ Orca now includes the four Perl packages it depends upon:
+ Digest::MD5 2.07, Math::Interpolate 1.02, RRDtool 0.99.29,
+ and Storable 0.6 at 3.
+
+Mon May 10 10:46:36 PDT 1999
+
+ Update references to Digest::MD5 version 2.07 and require
+ RRDtool 0.99.28.
+
+Sat May 8 19:29:14 PDT 1999
+
+ Upgrade the instructions to mention Math::Interpolate 1.02
+ instead of Math::Interpolator 1.01.
+
+Thu May 6 13:58:06 PDT 1999
+
+ Orca does not normally display the daily, weekly, monthly,
+ yearly, and everything plots for all the different measurements
+ if there is only one group. However, it is nice to see all the
+ different measurement plots in one page for a single group, so if
+ now there is only one group, then an Everything group placed at
+ the top of the main index.html file for daily, weekly, monthly,
+ and yearly overviews.
+
+ Make a comment about using gd1.3 versus gd1.2 in INSTALL when
+ building RRDtool. Because RRDtool comes with gd1.2 and generates
+ smaller GIFs, a comment is made that there is no reason to move
+ to gd1.3. The bottom line is that gd1.2 is preferred.
+
+ Check if the state file is empty and do not complain if it is.
+
+ Add installation instructions that to install this version
+ of Orca over an older version, a make migrate command will
+ need to be run to renames all files and directories containing
+ percollator, percol, or perc to orcallator in any of the installed
+ Orca directories.
+
+ Update orcallator.cfg to look for filenames like
+ orcallator-1999-05-06 and percol-1999-05-06.
+
+Wed May 5 10:43:23 PDT 1999
+
+ Require RRDtool 0.99.27.
+
+Mon May 3 14:51:06 PDT 1999
+
+ Rename everything percollator, perc and percol to orcallator.
+
+Fri Apr 30 16:34:20 PDT 1999
+
+ Update to install Perl 5.005_03 instead of 5.005_02.
+
+Fri Apr 23 09:31:28 PDT 1999
+
+ Require RRDtool 0.99.25.
+
+Thu Apr 22 09:21:15 PDT 1999
+
+ Require RRDtool 0.99.24.
+
+Sat Apr 17 12:06:46 PDT 1999
+
+ Change all URLs from
+ http://www.geocities.com/ResearchTriangle/Thinktank/4996/
+ to
+ http://www.geocities.com/~bzking/
+
+Thu Apr 8 17:03:37 PDT 1999
+
+ Require RRDtool 0.99.23.
+
+Wed Mar 31 19:07:41 PST 1999
+
+ When perl_glob cannot open a directory, return an empty
+ array and warn instead of dying. Fix from J.R. Tietsort
+ <jrtietsort at micron.com>.
+
+ Require RRDtool 0.99.22 which contains a memory leak bug fix.
+
+Sat Mar 27 10:07:09 PST 1999
+
+ Update references to Digest::MD5 version 2.06 and require
+ RRDtool 0.99.21.
+
+Thu Mar 25 15:30:00 PST 1999
+
+ Speed up count_proc() in percollator.se by 20% using a patch
+ supplied by Rich Pettit <rpettit at resolute.com>.
+
+Sat Mar 6 11:50:57 PST 1999
+
+ Update references to Digest::MD5 version 2.04.
+
+Thu Mar 4 16:42:03 PST 1999
+
+ Require RRDtool 0.99.19.
+
+Mon Mar 1 11:01:01 PST 1999
+
+ Require RRDtool 0.99.18.
+
+Tue Feb 23 09:19:37 PST 1999
+
+ Require RRDtool 0.99.15.
+
+ Die if a unrecognized command line option is given to Orca.
+
+ Do group name substitution on the Y legend in GIFs.
+
+ Add another consolidation function, DERIVE, to an error message.
+
+ Change the user, system and idle colors in the CPU usage plot
+ as requested by Alain Swanson <amswanson at micron.com>.
+
+ Change the printing format of usr% and sys% from %4.0f to %5.1f
+ in percollator.se to work around a printing problem reported by
+ Alain Swanson <amswanson at micron.com>. In SE 3.1 this will now
+ display an extra non-zero digit of measured precision.
+
+ Always output the header information in percollator.se, even
+ if Orca cannot handle it yet, since the number of columns may
+ change if new hardware is added to the system.
+
+Mon Feb 22 10:23:21 PST 1999
+
+ Add GIF width and height tags to img src's using the returned
+ GIF size from RRDs::graph.
+
+ Add a space between the ending " for the img src="" and the
+ following alt="" in the generated HTML.
+
+ Require RRDtool 0.99.14.
+
+ Add x86 Ethernet device plotting to percollator.cfg.in.
+
+ Remove the LAST RRA from all Orca created RRAs since it is not
+ required to get the current value from an RRA. The current
+ value is obtained by using the LAST consolidation function on
+ the plotted data.
+
+Sun Feb 21 11:03:39 PST 1999
+
+ Make use of RRDtool 0.99.12's legend formatting.
+
+Sat Feb 20 20:13:01 PST 1999
+
+ Require RRDtool 0.99.12.
+
Fri Feb 19 11:55:50 PST 1999
+ Move some </a> tags to the end of the image they were referencing
+ to remove some Netscape glitches.
+
+ Minor spelling fix and addition to CHANGES file.
+
Version 0.20.
Have the Orca logo be a hyperlink to the Orca home page.
@@ -16,8 +228,12 @@
the interval. This is useful for RRD which expects data to be
measured on the interval.
+ Fix a bug in percollator.se where it was inflating the httpops5
+ number since it was not calculating the actual time interval
+ and instead assuming a 5 second interval.
+
Add Squid log processing to percollator.se courtesy of Adrian
- Cockroft of Sun Microsystems.
+ Cockcroft of Sun Microsystems.
Rename the configure --with options. If you want to watch NCSA
style access logs, use --with-ncsa-log. To watch NCSA style
Added: trunk/orca/NEWS
==============================================================================
--- trunk/orca/NEWS (original)
+++ trunk/orca/NEWS Sat Jul 13 18:45:54 2002
@@ -0,0 +1,45 @@
+New in version 0.21.
+ 1) Every file containing the words percollator, percol and perc has
+ been renamed to contain the word orcallator. A new make target named
+ migrate will change all filenames in an installed Orca directory to
+ the new names. This `make migrate' should only be run after killing
+ any running percollator.se's and Orca processes and before installing
+ this version of Orca.
+ 2) Orca now includes Digest::MD5 2.07, Math::Interpolate 1.02, RRDs
+ 0.99029, and Storable 0.603 in packages/ to make installation easier.
+ The configure script now determines if you have the requisite version
+ of these packages installed in your Perl and will modify the Makefiles
+ to build the necessary modules.
+ 3) Orca now displays the daily, weekly, monthly, yearly plots of all
+ measurements even if there is only one group. Orca used to not make
+ the web pages showing the different measurements all on one page if
+ there was only one group.
+ 4) Add GIF width and height tags to img src's using the returned GIF
+ size from RRDs::graph to speed with page rendering.
+ 5) Some minor HTML fixes to have the pages look cleaner for Netscape
+ browsers.
+ 6) Make use of RRDtool 0.99.12's legend formatting to clean up the GIF
+ legends and to store the minimum and maximum values of a data stream.
+ 7) Remove the LAST RRA from all Orca created RRAs since it is not
+ required to get the current value from an RRA. This requires
+ rebuilding all RRDs.
+ 8) Add x86 Ethernet device (elxl*) plotting to orcallator.cfg.in.
+ 9) Do group name substitution on the Y legend in GIFs.
+10) Orca used to delete RRD files even if they are created with new
+ versions or Orca. Now the RRD file is used if it is at least as
+ new as the version a particular version of Orca needs.
+11) Orca now dies if an unrecognized command line option is given.
+12) Speed up the count_proc() routine in orcallator.se by 20%.
+13) Perl_glob does not die if it cannot open a directory. It will
+ also not follow directories named .. if they happen to match
+ a regular expression. It also only returns files matching the
+ regular expressions.
+14) Change all references from
+ http://www.geocities.com/ResearchTriangle/Thinktank/4996/
+ to
+ http://www.geocities.com/~bzking/
+15) Speed up Orca by using Storable to do deep clones of objects
+ instead of using Data::Dumper and eval.
+16) Replace some linear search by a hash lookup to speed up Orca.
+17) Fix some bugs in orcallator.se.
+18) Clean up some error messages.
Modified: trunk/orca/README
==============================================================================
--- trunk/orca/README (original)
+++ trunk/orca/README Sat Jul 13 18:45:54 2002
@@ -1,4 +1,4 @@
-This package contains two main tools: Orca and percollator.se.
+This package contains two main tools: Orca and orcallator.se.
Orca
=====
@@ -32,7 +32,7 @@
An example of the output generated by Orca is located at:
-http://www.geocities.com/ResearchTriangle/Thinktank/4996/orca-example/
+http://www.geocities.com/~bzking/orca-example/
Orca is written completely in Perl. To install, configure and use
Orca read the INSTALL file. Some sample configuration files for
@@ -47,29 +47,29 @@
explain how the data files Orca uses are created, maintained, and
used to create the GIFs that Orca creates.
-percollator.se
+orcallator.se
==============
-The other tool in this package is an updated version of percollator.se
+The other tool in this package is an updated version of orcallator.se
written by Adrian Cockcroft. Percollator.se is a tool written for Solaris
SPARC and Solaris x86 that collects a large amount of system and web
server statistics and prints them into a file for later processing
-and plotting. For documentation on the original percollator.se tool,
+and plotting. For documentation on the original orcallator.se tool,
see the URL http://www.sunworld.com/swol-03-1996/swol-03-perf.html
-This version of percollator.se collects much more data than the original
+This version of orcallator.se collects much more data than the original
on Solaris systems. I have designed an Orca configuration file designed
-to read the output of this percollator. Sample output from this set up
+to read the output of this orcallator. Sample output from this set up
is displayed at
-http://www.geocities.com/ResearchTriangle/Thinktank/4996/orca-example/
+http://www.geocities.com/~bzking/orca-example/
AVAILABLE AT
============
These tools are available for download from
-http://www.geocities.com/ResearchTriangle/Thinktank/4996/
+http://www.geocities.com/~bzking/
MAILING LISTS
=============
Added: trunk/orca/packages/Storable-0.6 at 3/t/dump.pl
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/t/dump.pl (original)
+++ trunk/orca/packages/Storable-0.6 at 3/t/dump.pl Sat Jul 13 18:45:54 2002
@@ -0,0 +1,140 @@
+;# $Id: dump.pl,v 0.6 1998/06/04 16:08:27 ram Exp $
+;#
+;# Copyright (c) 1995-1998, Raphael Manfredi
+;#
+;# You may redistribute only under the terms of the Artistic License,
+;# as specified in the README file that comes with the distribution.
+;#
+;# $Log: dump.pl,v $
+;# Revision 0.6 1998/06/04 16:08:27 ram
+;# Baseline for first beta release.
+;#
+
+package dump;
+use Carp;
+
+%dump = (
+ 'SCALAR' => 'dump_scalar',
+ 'ARRAY' => 'dump_array',
+ 'HASH' => 'dump_hash',
+ 'REF' => 'dump_ref',
+);
+
+# Given an object, dump its transitive data closure
+sub main'dump {
+ my ($object) = @_;
+ croak "Not a reference!" unless ref($object);
+ local %dumped;
+ local %object;
+ local $count = 0;
+ local $dumped = '';
+ &recursive_dump($object, 1);
+ return $dumped;
+}
+
+# This is the root recursive dumping routine that may indirectly be
+# called by one of the routine it calls...
+# The link parameter is set to false when the reference passed to
+# the routine is an internal temporay variable, implying the object's
+# address is not to be dumped in the %dumped table since it's not a
+# user-visible object.
+sub recursive_dump {
+ my ($object, $link) = @_;
+
+ # Get something like SCALAR(0x...) or TYPE=SCALAR(0x...).
+ # Then extract the bless, ref and address parts of that string.
+
+ my $what = "$object"; # Stringify
+ my ($bless, $ref, $addr) = $what =~ /^(\w+)=(\w+)\((0x.*)\)$/;
+ ($ref, $addr) = $what =~ /^(\w+)\((0x.*)\)$/ unless $bless;
+
+ # Special case for references to references. When stringified,
+ # they appear as being scalars. However, ref() correctly pinpoints
+ # them as being references indirections. And that's it.
+
+ $ref = 'REF' if ref($object) eq 'REF';
+
+ # Make sure the object has not been already dumped before.
+ # We don't want to duplicate data. Retrieval will know how to
+ # relink from the previously seen object.
+
+ if ($link && $dumped{$addr}++) {
+ my $num = $object{$addr};
+ $dumped .= "OBJECT #$num seen\n";
+ return;
+ }
+
+ my $objcount = $count++;
+ $object{$addr} = $objcount;
+
+ # Call the appropriate dumping routine based on the reference type.
+ # If the referenced was blessed, we bless it once the object is dumped.
+ # The retrieval code will perform the same on the last object retrieved.
+
+ croak "Unknown simple type '$ref'" unless defined $dump{$ref};
+
+ &{$dump{$ref}}($object); # Dump object
+ &bless($bless) if $bless; # Mark it as blessed, if necessary
+
+ $dumped .= "OBJECT $objcount\n";
+}
+
+# Indicate that current object is blessed
+sub bless {
+ my ($class) = @_;
+ $dumped .= "BLESS $class\n";
+}
+
+# Dump single scalar
+sub dump_scalar {
+ my ($sref) = @_;
+ my $scalar = $$sref;
+ unless (defined $scalar) {
+ $dumped .= "UNDEF\n";
+ return;
+ }
+ my $len = length($scalar);
+ $dumped .= "SCALAR len=$len $scalar\n";
+}
+
+# Dump array
+sub dump_array {
+ my ($aref) = @_;
+ my $items = 0 + @{$aref};
+ $dumped .= "ARRAY items=$items\n";
+ foreach $item (@{$aref}) {
+ unless (defined $item) {
+ $dumped .= 'ITEM_UNDEF' . "\n";
+ next;
+ }
+ $dumped .= 'ITEM ';
+ &recursive_dump(\$item, 1);
+ }
+}
+
+# Dump hash table
+sub dump_hash {
+ my ($href) = @_;
+ my $items = scalar(keys %{$href});
+ $dumped .= "HASH items=$items\n";
+ foreach $key (sort keys %{$href}) {
+ $dumped .= 'KEY ';
+ &recursive_dump(\$key, undef);
+ unless (defined $href->{$key}) {
+ $dumped .= 'VALUE_UNDEF' . "\n";
+ next;
+ }
+ $dumped .= 'VALUE ';
+ &recursive_dump(\$href->{$key}, 1);
+ }
+}
+
+# Dump reference to reference
+sub dump_ref {
+ my ($rref) = @_;
+ my $deref = $$rref; # Follow reference to reference
+ $dumped .= 'REF ';
+ &recursive_dump($deref, 1); # $dref is a reference
+}
+
+1;
Added: trunk/orca/packages/Storable-0.6 at 3/t/freeze.t
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/t/freeze.t (original)
+++ trunk/orca/packages/Storable-0.6 at 3/t/freeze.t Sat Jul 13 18:45:54 2002
@@ -0,0 +1,111 @@
+#!./perl
+
+# $Id: freeze.t,v 0.6.1.1 1998/06/12 09:47:08 ram Exp $
+#
+# Copyright (c) 1995-1998, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic License,
+# as specified in the README file that comes with the distribution.
+#
+# $Log: freeze.t,v $
+# Revision 0.6.1.1 1998/06/12 09:47:08 ram
+# patch1: added test for the LVALUE bug workaround
+#
+# Revision 0.6 1998/06/04 16:08:31 ram
+# Baseline for first beta release.
+#
+
+require 't/dump.pl';
+
+use Storable qw(freeze nfreeze thaw);
+
+print "1..15\n";
+
+$a = 'toto';
+$b = \$a;
+$c = bless {}, CLASS;
+$c->{attribute} = $b;
+$d = {};
+$e = [];
+$d->{'a'} = $e;
+$e->[0] = $d;
+%a = ('key', 'value', 1, 0, $a, $b, 'cvar', \$c);
+ at a = ('first', undef, 3, -4, -3.14159, 456, 4.5, $d, \$d, \$e, $e,
+ $b, \$a, $a, $c, \$c, \%a);
+
+print "not " unless defined ($f1 = freeze(\@a));
+print "ok 1\n";
+
+$dumped = &dump(\@a);
+print "ok 2\n";
+
+$root = thaw($f1);
+print "not " unless defined $root;
+print "ok 3\n";
+
+$got = &dump($root);
+print "ok 4\n";
+
+print "not " unless $got eq $dumped;
+print "ok 5\n";
+
+package FOO; @ISA = qw(Storable);
+
+sub make {
+ my $self = bless {};
+ $self->{key} = \%main::a;
+ return $self;
+};
+
+package main;
+
+$foo = FOO->make;
+print "not " unless $f2 = $foo->freeze;
+print "ok 6\n";
+
+print "not " unless $f3 = $foo->nfreeze;
+print "ok 7\n";
+
+$root3 = thaw($f3);
+print "not " unless defined $root3;
+print "ok 8\n";
+
+print "not " unless &dump($foo) eq &dump($root3);
+print "ok 9\n";
+
+$root = thaw($f2);
+print "not " unless &dump($foo) eq &dump($root);
+print "ok 10\n";
+
+print "not " unless &dump($root3) eq &dump($root);
+print "ok 11\n";
+
+$other = freeze($root);
+print "not " unless length($other) == length($f2);
+print "ok 12\n";
+
+$root2 = thaw($other);
+print "not " unless &dump($root2) eq &dump($root);
+print "ok 13\n";
+
+$VAR1 = [
+ 'method',
+ 1,
+ 'prepare',
+ 'SELECT table_name, table_owner, num_rows FROM iitables
+ where table_owner != \'$ingres\' and table_owner != \'DBA\''
+];
+
+$x = nfreeze($VAR1);
+$VAR2 = thaw($x);
+print "not " unless $VAR2->[3] eq $VAR1->[3];
+print "ok 14\n";
+
+# Test the workaround for LVALUE bug in perl 5.004_04 -- from Gisle Aas
+sub foo { $_[0] = 1 }
+$foo = [];
+foo($foo->[1]);
+eval { freeze($foo) };
+print "not " if $@;
+print "ok 15\n";
+
Added: trunk/orca/packages/Storable-0.6 at 3/t/forgive.t
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/t/forgive.t (original)
+++ trunk/orca/packages/Storable-0.6 at 3/t/forgive.t Sat Jul 13 18:45:54 2002
@@ -0,0 +1,52 @@
+#!./perl
+
+# $Id: forgive.t,v 0.6 1998/06/04 16:08:38 ram Exp $
+#
+# Copyright (c) 1995-1998, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic License,
+# as specified in the README file that comes with the distribution.
+#
+# Original Author: Ulrich Pfeifer
+# (C) Copyright 1997, Universitat Dortmund, all rights reserved.
+#
+# $Log: forgive.t,v $
+# Revision 0.6 1998/06/04 16:08:38 ram
+# Baseline for first beta release.
+#
+
+use Storable qw(store retrieve);
+
+print "1..8\n";
+
+my $test = 1;
+my $bad = ['foo', sub { 1 }, 'bar'];
+my $result;
+
+eval {$result = store ($bad , 't/store')};
+print ((!defined $result)?"ok $test\n":"not ok $test\n"); $test++;
+print (($@ ne '')?"ok $test\n":"not ok $test\n"); $test++;
+
+$Storable::forgive_me=1;
+
+open(SAVEERR, ">&STDERR");
+open(STDERR, ">/dev/null") or
+ ( print SAVEERR "Unable to redirect STDERR: $!\n" and exit(1) );
+
+eval {$result = store ($bad , 't/store')};
+
+open(STDERR, ">&SAVEERR");
+
+print ((defined $result)?"ok $test\n":"not ok $test\n"); $test++;
+print (($@ eq '')?"ok $test\n":"not ok $test\n"); $test++;
+
+my $ret = retrieve('t/store');
+print ((defined $ret)?"ok $test\n":"not ok $test\n"); $test++;
+print (($ret->[0] eq 'foo')?"ok $test\n":"not ok $test\n"); $test++;
+print (($ret->[2] eq 'bar')?"ok $test\n":"not ok $test\n"); $test++;
+print ((ref $ret->[1] eq 'SCALAR')?"ok $test\n":"not ok $test\n"); $test++;
+
+
+END {
+ unlink 't/store';
+}
Added: trunk/orca/packages/Storable-0.6 at 3/t/dclone.t
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/t/dclone.t (original)
+++ trunk/orca/packages/Storable-0.6 at 3/t/dclone.t Sat Jul 13 18:45:54 2002
@@ -0,0 +1,57 @@
+#!./perl
+
+# $Id: dclone.t,v 0.6 1998/06/04 16:08:25 ram Exp $
+#
+# Copyright (c) 1995-1998, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic License,
+# as specified in the README file that comes with the distribution.
+#
+# $Log: dclone.t,v $
+# Revision 0.6 1998/06/04 16:08:25 ram
+# Baseline for first beta release.
+#
+
+require 't/dump.pl';
+
+use Storable qw(dclone);
+
+print "1..6\n";
+
+$a = 'toto';
+$b = \$a;
+$c = bless {}, CLASS;
+$c->{attribute} = 'attrval';
+%a = ('key', 'value', 1, 0, $a, $b, 'cvar', \$c);
+ at a = ('first', undef, 3, -4, -3.14159, 456, 4.5,
+ $b, \$a, $a, $c, \$c, \%a);
+
+print "not " unless defined ($aref = dclone(\@a));
+print "ok 1\n";
+
+$dumped = &dump(\@a);
+print "ok 2\n";
+
+$got = &dump($aref);
+print "ok 3\n";
+
+print "not " unless $got eq $dumped;
+print "ok 4\n";
+
+package FOO; @ISA = qw(Storable);
+
+sub make {
+ my $self = bless {};
+ $self->{key} = \%main::a;
+ return $self;
+};
+
+package main;
+
+$foo = FOO->make;
+print "not " unless defined($r = $foo->dclone);
+print "ok 5\n";
+
+print "not " unless &dump($foo) eq &dump($r);
+print "ok 6\n";
+
Added: trunk/orca/packages/Storable-0.6 at 3/t/retrieve.t
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/t/retrieve.t (original)
+++ trunk/orca/packages/Storable-0.6 at 3/t/retrieve.t Sat Jul 13 18:45:54 2002
@@ -0,0 +1,57 @@
+#!./perl
+
+# $Id: retrieve.t,v 0.6 1998/06/04 16:08:33 ram Exp $
+#
+# Copyright (c) 1995-1998, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic License,
+# as specified in the README file that comes with the distribution.
+#
+# $Log: retrieve.t,v $
+# Revision 0.6 1998/06/04 16:08:33 ram
+# Baseline for first beta release.
+#
+
+require 't/dump.pl';
+
+use Storable qw(store retrieve nstore);
+
+print "1..9\n";
+
+$a = 'toto';
+$b = \$a;
+$c = bless {}, CLASS;
+$c->{attribute} = 'attrval';
+%a = ('key', 'value', 1, 0, $a, $b, 'cvar', \$c);
+ at a = ('first', '', undef, 3, -4, -3.14159, 456, 4.5,
+ $b, \$a, $a, $c, \$c, \%a);
+
+print "not " unless defined store(\@a, 't/store');
+print "ok 1\n";
+print "not " unless defined nstore(\@a, 't/nstore');
+print "ok 2\n";
+
+$root = retrieve('t/store');
+print "not " unless defined $root;
+print "ok 3\n";
+
+$nroot = retrieve('t/nstore');
+print "not " unless defined $nroot;
+print "ok 4\n";
+
+$d1 = &dump($root);
+print "ok 5\n";
+$d2 = &dump($nroot);
+print "ok 6\n";
+
+print "not " unless $d1 eq $d2;
+print "ok 7\n";
+
+# Make sure empty string is defined at retrieval time
+print "not " unless defined $root->[1];
+print "ok 8\n";
+print "not " if length $root->[1];
+print "ok 9\n";
+
+unlink 't/store', 't/nstore';
+
Added: trunk/orca/packages/Storable-0.6 at 3/t/tied.t
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/t/tied.t (original)
+++ trunk/orca/packages/Storable-0.6 at 3/t/tied.t Sat Jul 13 18:45:54 2002
@@ -0,0 +1,177 @@
+#!./perl
+
+# $Id: tied.t,v 0.6 1998/06/04 16:08:40 ram Exp $
+#
+# Copyright (c) 1995-1998, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic License,
+# as specified in the README file that comes with the distribution.
+#
+# $Log: tied.t,v $
+# Revision 0.6 1998/06/04 16:08:40 ram
+# Baseline for first beta release.
+#
+
+require 't/dump.pl';
+
+use Storable qw(freeze thaw);
+
+print "1..15\n";
+
+($scalar_fetch, $array_fetch, $hash_fetch) = (0, 0, 0);
+
+package TIED_HASH;
+
+sub TIEHASH {
+ my $self = bless {}, shift;
+ return $self;
+}
+
+sub FETCH {
+ my $self = shift;
+ my ($key) = @_;
+ $main::hash_fetch++;
+ return $self->{$key};
+}
+
+sub STORE {
+ my $self = shift;
+ my ($key, $value) = @_;
+ $self->{$key} = $value;
+}
+
+sub FIRSTKEY {
+ my $self = shift;
+ scalar keys %{$self};
+ return each %{$self};
+}
+
+sub NEXTKEY {
+ my $self = shift;
+ return each %{$self};
+}
+
+package TIED_ARRAY;
+
+sub TIEARRAY {
+ my $self = bless [], shift;
+ return $self;
+}
+
+sub FETCH {
+ my $self = shift;
+ my ($idx) = @_;
+ $main::array_fetch++;
+ return $self->[$idx];
+}
+
+sub STORE {
+ my $self = shift;
+ my ($idx, $value) = @_;
+ $self->[$idx] = $value;
+}
+
+sub FETCHSIZE {
+ my $self = shift;
+ return @{$self};
+}
+
+package TIED_SCALAR;
+
+sub TIESCALAR {
+ my $scalar;
+ my $self = bless \$scalar, shift;
+ return $self;
+}
+
+sub FETCH {
+ my $self = shift;
+ $main::scalar_fetch++;
+ return $$self;
+}
+
+sub STORE {
+ my $self = shift;
+ my ($value) = @_;
+ $$self = $value;
+}
+
+package main;
+
+$a = 'toto';
+$b = \$a;
+
+$c = tie %hash, TIED_HASH;
+$d = tie @array, TIED_ARRAY;
+tie $scalar, TIED_SCALAR;
+
+#$scalar = 'foo';
+#$hash{'attribute'} = \$d;
+#$array[0] = $c;
+#$array[1] = \$scalar;
+
+### If I say
+### $hash{'attribute'} = $d;
+### below, then dump() incorectly dumps the hash value as a string the second
+### time it is reached. I have not investigated enough to tell whether it's
+### a bug in my dump() routine or in the Perl tieing mechanism.
+$scalar = 'foo';
+$hash{'attribute'} = 'plain value';
+$array[0] = \$scalar;
+$array[1] = $c;
+$array[2] = \@array;
+
+ at tied = (\$scalar, \@array, \%hash);
+%a = ('key', 'value', 1, 0, $a, $b, 'cvar', \$a, 'scalarref', \$scalar);
+ at a = ('first', 3, -4, -3.14159, 456, 4.5, $d, \$d,
+ $b, \$a, $a, $c, \$c, \%a, \@array, \%hash, \@tied);
+
+print "not " unless defined($f = freeze(\@a));
+print "ok 1\n";
+
+$dumped = &dump(\@a);
+print "ok 2\n";
+
+$root = thaw($f);
+print "not " unless defined $root;
+print "ok 3\n";
+
+$got = &dump($root);
+print "ok 4\n";
+
+### Used to see the manifestation of the bug documented above.
+### print "original: $dumped";
+### print "--------\n";
+### print "got: $got";
+### print "--------\n";
+
+print "not " unless $got eq $dumped;
+print "ok 5\n";
+
+$g = freeze($root);
+print "not " unless length($f) == length($g);
+print "ok 6\n";
+
+# Ensure the tied items in the retrieved image work
+ at old = ($scalar_fetch, $array_fetch, $hash_fetch);
+ at tied = ($tscalar, $tarray, $thash) = @{$root->[$#{$root}]};
+ at type = qw(SCALAR ARRAY HASH);
+
+print "not " unless tied $$tscalar;
+print "ok 7\n";
+print "not " unless tied @{$tarray};
+print "ok 8\n";
+print "not " unless tied %{$thash};
+print "ok 9\n";
+
+ at new = ($$tscalar, $tarray->[0], $thash->{'attribute'});
+ at new = ($scalar_fetch, $array_fetch, $hash_fetch);
+
+# Tests 10..15
+for ($i = 0; $i < @new; $i++) {
+ print "not " unless $new[$i] == $old[$i] + 1;
+ printf "ok %d\n", 10 + 2*$i; # Tests 10,12,14
+ print "not " unless ref $tied[$i] eq $type[$i];
+ printf "ok %d\n", 11 + 2*$i; # Tests 11,13,15
+}
+
Added: trunk/orca/packages/Storable-0.6 at 3/t/canonical.t
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/t/canonical.t (original)
+++ trunk/orca/packages/Storable-0.6 at 3/t/canonical.t Sat Jul 13 18:45:54 2002
@@ -0,0 +1,128 @@
+#!./perl
+
+# $Id: canonical.t,v 0.6 1998/06/04 16:08:24 ram Exp $
+#
+# Copyright (c) 1995-1998, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic License,
+# as specified in the README file that comes with the distribution.
+#
+# $Log: canonical.t,v $
+# Revision 0.6 1998/06/04 16:08:24 ram
+# Baseline for first beta release.
+#
+
+BEGIN { push @INC, "../blib" }
+
+use Storable qw(freeze thaw dclone);
+use vars qw($debugging $verbose);
+
+print "1..5\n";
+
+sub ok {
+ my($testno, $ok) = @_;
+ print "not " unless $ok;
+ print "ok $testno\n";
+}
+
+
+# Uncomment the folowing line to get a dump of the constructed data structure
+# (you may want to reduce the size of the hashes too)
+# $debugging = 1;
+
+$hashsize = 100;
+$maxhash2size = 100;
+$maxarraysize = 100;
+
+# Use MD5 if its available to make random string keys
+
+eval { require "MD5.pm" };
+$gotmd5 = !$@;
+
+# Use Data::Dumper if debugging and it is available to create an ASCII dump
+
+if ($debugging) {
+ eval { require "Data/Dumper.pm" };
+ $gotdd = !$@;
+}
+
+ at fixed_strings = ("January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December" );
+
+# Build some arbitrarily complex data structure starting with a top level hash
+# (deeper levels contain scalars, references to hashes or references to arrays);
+
+for (my $i = 0; $i < $hashsize; $i++) {
+ my($k) = int(rand(1_000_000));
+ $k = MD5->hexhash($k) if $gotmd5 and int(rand(2));
+ $a1{$k} = { key => "$k", value => $i };
+
+ # A third of the elements are references to further hashes
+
+ if (int(rand(1.5))) {
+ my($hash2) = {};
+ my($hash2size) = int(rand($maxhash2size));
+ while ($hash2size--) {
+ my($k2) = $k . $i . int(rand(100));
+ $hash2->{$k2} = $fixed_strings[rand(int(@fixed_strings))];
+ }
+ $a1{$k}->{value} = $hash2;
+ }
+
+ # A further third are references to arrays
+
+ elsif (int(rand(2))) {
+ my($arr_ref) = [];
+ my($arraysize) = int(rand($maxarraysize));
+ while ($arraysize--) {
+ push(@$arr_ref, $fixed_strings[rand(int(@fixed_strings))]);
+ }
+ $a1{$k}->{value} = $arr_ref;
+ }
+}
+
+
+print STDERR Data::Dumper::Dumper(\%a1) if ($verbose and $gotdd);
+
+
+# Copy the hash, element by element in order of the keys
+
+foreach $k (sort keys %a1) {
+ $a2{$k} = { key => "$k", value => $a1{$k}->{value} };
+}
+
+# Deep clone the hash
+
+$a3 = dclone(\%a1);
+
+# In canonical mode the frozen representation of each of the hashes
+# should be identical
+
+$Storable::canonical = 1;
+
+$x1 = freeze(\%a1);
+$x2 = freeze(\%a2);
+$x3 = freeze($a3);
+
+ok 1, (length($x1) > $hashsize); # sanity check
+ok 2, length($x1) == length($x2); # idem
+ok 3, $x1 eq $x2;
+ok 4, $x1 eq $x3;
+
+# In normal mode it is exceedingly unlikely that the frozen
+# representaions of all the hashes will be the same (normally the hash
+# elements are frozen in the order they are stored internally,
+# i.e. pseudo-randomly).
+
+$Storable::canonical = 0;
+
+$x1 = freeze(\%a1);
+$x2 = freeze(\%a2);
+$x3 = freeze($a3);
+
+
+# Two out of three the same may be a coincidence, all three the same
+# is much, much more unlikely. Still it could happen, so this test
+# may report a false negative.
+
+ok 5, ($x1 ne $x2) || ($x1 ne $x3);
Added: trunk/orca/packages/Storable-0.6 at 3/t/store.t
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/t/store.t (original)
+++ trunk/orca/packages/Storable-0.6 at 3/t/store.t Sat Jul 13 18:45:54 2002
@@ -0,0 +1,108 @@
+#!./perl
+
+# $Id: store.t,v 0.6 1998/06/04 16:08:35 ram Exp $
+#
+# Copyright (c) 1995-1998, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic License,
+# as specified in the README file that comes with the distribution.
+#
+# $Log: store.t,v $
+# Revision 0.6 1998/06/04 16:08:35 ram
+# Baseline for first beta release.
+#
+
+require 't/dump.pl';
+
+use Storable qw(store retrieve store_fd nstore_fd retrieve_fd);
+
+print "1..20\n";
+
+$a = 'toto';
+$b = \$a;
+$c = bless {}, CLASS;
+$c->{attribute} = 'attrval';
+%a = ('key', 'value', 1, 0, $a, $b, 'cvar', \$c);
+ at a = ('first', undef, 3, -4, -3.14159, 456, 4.5,
+ $b, \$a, $a, $c, \$c, \%a);
+
+print "not " unless defined store(\@a, 't/store');
+print "ok 1\n";
+
+$dumped = &dump(\@a);
+print "ok 2\n";
+
+$root = retrieve('t/store');
+print "not " unless defined $root;
+print "ok 3\n";
+
+$got = &dump($root);
+print "ok 4\n";
+
+print "not " unless $got eq $dumped;
+print "ok 5\n";
+
+unlink 'store';
+
+package FOO; @ISA = qw(Storable);
+
+sub make {
+ my $self = bless {};
+ $self->{key} = \%main::a;
+ return $self;
+};
+
+package main;
+
+$foo = FOO->make;
+print "not " unless $foo->store('t/store');
+print "ok 6\n";
+
+print "not " unless open(OUT, '>>t/store');
+print "ok 7\n";
+binmode OUT;
+
+print "not " unless defined store_fd(\@a, ::OUT);
+print "ok 8\n";
+print "not " unless defined nstore_fd($foo, ::OUT);
+print "ok 9\n";
+print "not " unless defined nstore_fd(\%a, ::OUT);
+print "ok 10\n";
+
+print "not " unless close(OUT);
+print "ok 11\n";
+
+print "not " unless open(OUT, 't/store');
+binmode OUT;
+
+$r = retrieve_fd(::OUT);
+print "not " unless defined $r;
+print "ok 12\n";
+print "not " unless &dump($foo) eq &dump($r);
+print "ok 13\n";
+
+$r = retrieve_fd(::OUT);
+print "not " unless defined $r;
+print "ok 14\n";
+print "not " unless &dump(\@a) eq &dump($r);
+print "ok 15\n";
+
+$r = retrieve_fd(main::OUT);
+print "not " unless defined $r;
+print "ok 16\n";
+print "not " unless &dump($foo) eq &dump($r);
+print "ok 17\n";
+
+$r = retrieve_fd(::OUT);
+print "not " unless defined $r;
+print "ok 18\n";
+print "not " unless &dump(\%a) eq &dump($r);
+print "ok 19\n";
+
+eval { $r = retrieve_fd(::OUT); };
+print "not " unless $@;
+print "ok 20\n";
+
+close OUT;
+unlink 't/store';
+
Added: trunk/orca/packages/Storable-0.6 at 3/Storable.xs
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/Storable.xs (original)
+++ trunk/orca/packages/Storable-0.6 at 3/Storable.xs Sat Jul 13 18:45:55 2002
@@ -0,0 +1,2515 @@
+/*
+ * Store and retrieve mechanism.
+ */
+
+/*
+ * $Id: Storable.xs,v 0.6.1.3 1998/07/03 11:36:09 ram Exp $
+ *
+ * Copyright (c) 1995-1998, Raphael Manfredi
+ *
+ * You may redistribute only under the terms of the Artistic License,
+ * as specified in the README file that comes with the distribution.
+ *
+ * $Log: Storable.xs,v $
+ * Revision 0.6.1.3 1998/07/03 11:36:09 ram
+ * patch3: fixed compatibility (wrt 0.5 at 9) for retrieval of blessed refs
+ * patch3: increased store() throughput significantly
+ *
+ * Revision 0.6.1.2 1998/06/22 09:00:04 ram
+ * patch2: adjust refcnt of tied objects after calling sv_magic()
+ *
+ * Revision 0.6.1.1 1998/06/12 09:46:48 ram
+ * patch1: added workaround for persistent LVALUE-ness in perl5.004
+ * patch1: now handles Perl immortal scalars explicitely
+ * patch1: retrieval of non-immortal undef cannot be shared
+ *
+ * Revision 0.6 1998/06/04 16:08:22 ram
+ * Baseline for first beta release.
+ *
+ */
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+/*#define DEBUGME /* Debug mode, turns assertions on as well */
+/*#define DASSERT /* Assertion mode */
+
+/*
+ * Pre PerlIO time when none of USE_PERLIO and PERLIO_IS_STDIO is defined
+ * Provide them with the necessary defines so they can build with pre-5.004.
+ */
+#ifndef USE_PERLIO
+#ifndef PERLIO_IS_STDIO
+#define PerlIO FILE
+#define PerlIO_getc(x) getc(x)
+#define PerlIO_putc(f,x) putc(x,f)
+#define PerlIO_read(x,y,z) fread(y,1,z,x)
+#define PerlIO_write(x,y,z) fwrite(y,1,z,x)
+#define PerlIO_stdoutf printf
+#endif /* PERLIO_IS_STDIO */
+#endif /* USE_PERLIO */
+
+/*
+ * Earlier versions of perl might be used, we can't assume they have the latest!
+ */
+#ifndef newRV_noinc
+#define newRV_noinc(sv) ((Sv = newRV(sv)), --SvREFCNT(SvRV(Sv)), Sv)
+#endif
+#ifndef HvSHAREKEYS_off
+#define HvSHAREKEYS_off(hv) /* Ignore */
+#endif
+
+#ifdef DEBUGME
+#ifndef DASSERT
+#define DASSERT
+#endif
+#define TRACEME(x) do { PerlIO_stdoutf x; PerlIO_stdoutf("\n"); } while (0)
+#else
+#define TRACEME(x)
+#endif
+
+#ifdef DASSERT
+#define ASSERT(x,y) do { \
+ if (!x) { PerlIO_stdoutf y; PerlIO_stdoutf("\n"); }} while (0)
+#else
+#define ASSERT(x,y)
+#endif
+
+/*
+ * Type markers.
+ */
+
+#define C(x) ((char) (x)) /* For markers with dynamic retrieval handling */
+
+#define SX_OBJECT C(0) /* Already stored object */
+#define SX_LSCALAR C(1) /* Scalar (string) forthcoming (length, data) */
+#define SX_ARRAY C(2) /* Array forthcominng (size, item list) */
+#define SX_HASH C(3) /* Hash forthcoming (size, key/value pair list) */
+#define SX_REF C(4) /* Reference to object forthcoming */
+#define SX_UNDEF C(5) /* Undefined scalar */
+#define SX_INTEGER C(6) /* Integer forthcoming */
+#define SX_DOUBLE C(7) /* Double forthcoming */
+#define SX_BYTE C(8) /* (signed) byte forthcoming */
+#define SX_NETINT C(9) /* Integer in network order forthcoming */
+#define SX_SCALAR C(10) /* Scalar (small) forthcoming (length, data) */
+#define SX_TIED_ARRAY C(11) /* Tied array forthcoming */
+#define SX_TIED_HASH C(12) /* Tied hash forthcoming */
+#define SX_TIED_SCALAR C(13) /* Tied scalar forthcoming */
+#define SX_SV_UNDEF C(14) /* Perl's immortal sv_undef */
+#define SX_SV_YES C(15) /* Perl's immortal sv_yes */
+#define SX_SV_NO C(16) /* Perl's immortal sv_no */
+#define SX_ERROR C(17) /* Error */
+
+/*
+ * Those are only used to retrieve "old" pre-0.6 binary images.
+ */
+#define SX_ITEM 'i' /* An array item introducer */
+#define SX_IT_UNDEF 'I' /* Undefined array item */
+#define SX_KEY 'k' /* An hash key introducer */
+#define SX_VALUE 'v' /* An hash value introducer */
+#define SX_VL_UNDEF 'V' /* Undefined hash value */
+
+/*
+ * Notification markers.
+ */
+
+#define SX_BLESS 'b' /* Object is blessed, class name length <255 */
+#define SX_LG_BLESS 'B' /* Object is blessed, class name length >255 */
+#define SX_STORED 'X' /* End of object */
+
+#define LG_BLESS 255 /* Large blessing classname length limit */
+#define LG_SCALAR 255 /* Large scalar length limit */
+
+/*
+ * The following structure is used for hash table key retrieval. Since, when
+ * retrieving objects, we'll be facing blessed hash references, it's best
+ * to pre-allocate that buffer once and resize it as the need arises, never
+ * freeing it (keys will be saved away someplace else anyway, so even large
+ * keys are not enough a motivation to reclaim that space).
+ *
+ * This structure is also used for memory store/retrieve operations which
+ * happen in a fixed place before being malloc'ed elsewhere if persistency
+ * is required. Hence the aptr pointer.
+ */
+struct extendable {
+ char *arena; /* Will hold hash key strings, resized as needed */
+ STRLEN asiz; /* Size of aforementionned buffer */
+ char *aptr; /* Arena pointer, for in-place read/write ops */
+ char *aend; /* First invalid address */
+};
+
+/*
+ * At store time:
+ * This hash table records the objects which have already been stored.
+ * Those are referred to as SX_OBJECT in the file, and their "tag" (i.e.
+ * an arbitrary sequence number) is used to identify them.
+ *
+ * At retrieve time:
+ * This array table records the objects which have already been retrieved,
+ * as seen by the tag determind by counting the objects themselves. The
+ * reference to that retrieved object is kept in the table, and is returned
+ * when an SX_OBJECT is found bearing that same tag.
+ */
+
+typedef unsigned long stag_t; /* Used by pre-0.6 binary format */
+
+/*
+ * XXX multi-threading needs context for the following variables...
+ */
+static HV *hseen; /* which objects have been seen, store time */
+static AV *aseen; /* which objects have been seen, retrieve time */
+static I32 tagnum; /* incremented at store time for each seen object */
+static int netorder = 0; /* true if network order used */
+static int forgive_me = -1; /* whether to be forgiving... */
+static int canonical; /* whether to store hashes sorted by key */
+struct extendable keybuf; /* for hash key retrieval */
+struct extendable membuf; /* for memory store/retrieve operations */
+
+/*
+ * key buffer handling
+ */
+#define kbuf keybuf.arena
+#define ksiz keybuf.asiz
+#define KBUFINIT() do { \
+ if (!kbuf) { \
+ TRACEME(("** allocating kbuf of 128 bytes")); \
+ New(10003, kbuf, 128, char); \
+ ksiz = 128; \
+ } \
+} while (0)
+#define KBUFCHK(x) do { \
+ if (x >= ksiz) { \
+ TRACEME(("** extending kbuf to %d bytes", x+1)); \
+ Renew(kbuf, x+1, char); \
+ ksiz = x+1; \
+ } \
+} while (0)
+
+/*
+ * memory buffer handling
+ */
+#define mbase membuf.arena
+#define msiz membuf.asiz
+#define mptr membuf.aptr
+#define mend membuf.aend
+#define MGROW (1 << 13)
+#define MMASK (MGROW - 1)
+
+#define round_mgrow(x) \
+ ((unsigned long) (((unsigned long) (x) + MMASK) & ~MMASK))
+#define trunc_int(x) \
+ ((unsigned long) ((unsigned long) (x) & ~(sizeof(int)-1)))
+#define int_aligned(x) \
+ ((unsigned long) (x) == trunc_int(x))
+
+#define MBUF_INIT(x) do { \
+ if (!mbase) { \
+ TRACEME(("** allocating mbase of %d bytes", MGROW)); \
+ New(10003, mbase, MGROW, char); \
+ msiz = MGROW; \
+ } \
+ mptr = mbase; \
+ if (x) \
+ mend = mbase + x; \
+ else \
+ mend = mbase + msiz; \
+} while (0)
+
+#define MBUF_SIZE() (mptr - mbase)
+
+/*
+ * Use SvPOKp(), because SvPOK() fails on tainted scalars.
+ * See store_scalar() for other usage of this workaround.
+ */
+#define MBUF_LOAD(v) do { \
+ if (!SvPOKp(v)) \
+ croak("Not a scalar string"); \
+ mptr = mbase = SvPV(v, msiz); \
+ mend = mbase + msiz; \
+} while (0)
+
+#define MBUF_XTEND(x) do { \
+ int nsz = (int) round_mgrow((x)+msiz); \
+ int offset = mptr - mbase; \
+ TRACEME(("** extending mbase to %d bytes", nsz)); \
+ Renew(mbase, nsz, char); \
+ msiz = nsz; \
+ mptr = mbase + offset; \
+ mend = mbase + nsz; \
+} while (0)
+
+#define MBUF_CHK(x) do { \
+ if ((mptr + (x)) > mend) \
+ MBUF_XTEND(x); \
+} while (0)
+
+#define MBUF_GETC(x) do { \
+ if (mptr < mend) \
+ x = (int) (unsigned char) *mptr++; \
+ else \
+ return (SV *) 0; \
+} while (0)
+
+#define MBUF_GETINT(x) do { \
+ if ((mptr + sizeof(int)) <= mend) { \
+ if (int_aligned(mptr)) \
+ x = *(int *) mptr; \
+ else \
+ memcpy(&x, mptr, sizeof(int)); \
+ mptr += sizeof(int); \
+ } else \
+ return (SV *) 0; \
+} while (0)
+
+#define MBUF_READ(x,s) do { \
+ if ((mptr + (s)) <= mend) { \
+ memcpy(x, mptr, s); \
+ mptr += s; \
+ } else \
+ return (SV *) 0; \
+} while (0)
+
+#define MBUF_SAFEREAD(x,s,z) do { \
+ if ((mptr + (s)) <= mend) { \
+ memcpy(x, mptr, s); \
+ mptr += s; \
+ } else { \
+ sv_free(z); \
+ return (SV *) 0; \
+ } \
+} while (0)
+
+#define MBUF_PUTC(c) do { \
+ if (mptr < mend) \
+ *mptr++ = (char) c; \
+ else { \
+ MBUF_XTEND(1); \
+ *mptr++ = (char) c; \
+ } \
+} while (0)
+
+#define MBUF_PUTINT(i) do { \
+ MBUF_CHK(sizeof(int)); \
+ if (int_aligned(mptr)) \
+ *(int *) mptr = i; \
+ else \
+ memcpy(mptr, &i, sizeof(int)); \
+ mptr += sizeof(int); \
+} while (0)
+
+#define MBUF_WRITE(x,s) do { \
+ MBUF_CHK(s); \
+ memcpy(mptr, x, s); \
+ mptr += s; \
+} while (0)
+
+
+#define mbuf membuf.arena
+#define msiz membuf.asiz
+
+#define svis_REF 0
+#define svis_SCALAR 1
+#define svis_ARRAY 2
+#define svis_HASH 3
+#define svis_TIED 4
+#define svis_OTHER 5
+
+/*
+ * Before 0.6, the magic string was "perl-store" (binary version number 0).
+ *
+ * Since 0.6 introduced many binary incompatibilities, the magic string has
+ * been changed to "pst0" to allow an old image to be properly retrieved by
+ * a newer Storable, but ensure a newer image cannot be retrieved with an
+ * older version.
+ */
+static char old_magicstr[] = "perl-store"; /* Magic number before 0.6 */
+static char magicstr[] = "pst0"; /* Used as a magic number */
+
+#define STORABLE_BINARY 1 /* Binary "version" number */
+
+/*
+ * Useful store shortcuts...
+ */
+#define PUTMARK(x) do { \
+ if (!f) \
+ MBUF_PUTC(x); \
+ else if (PerlIO_putc(f, x) == EOF) \
+ return -1; \
+ } while (0)
+
+#ifdef HAS_HTONL
+#define WLEN(x) do { \
+ if (netorder) { \
+ int y = (int) htonl(x); \
+ if (!f) \
+ MBUF_PUTINT(y); \
+ else if (PerlIO_write(f, &y, sizeof(y)) != sizeof(y)) \
+ return -1; \
+ } else { \
+ if (!f) \
+ MBUF_PUTINT(x); \
+ else if (PerlIO_write(f, &x, sizeof(x)) != sizeof(x)) \
+ return -1; \
+ } \
+} while (0)
+#else
+#define WLEN(x) do { \
+ if (!f) \
+ MBUF_PUTINT(x); \
+ else if (PerlIO_write(f, &x, sizeof(x)) != sizeof(x)) \
+ return -1; \
+ } while (0)
+#endif
+
+#define WRITE(x,y) do { \
+ if (!f) \
+ MBUF_WRITE(x,y); \
+ else if (PerlIO_write(f, x, y) != y) \
+ return -1; \
+ } while (0)
+
+#define STORE_SCALAR(pv, len) do { \
+ if (len < LG_SCALAR) { \
+ unsigned char clen = (unsigned char) len; \
+ PUTMARK(SX_SCALAR); \
+ PUTMARK(clen); \
+ if (len) \
+ WRITE(pv, len); \
+ } else { \
+ PUTMARK(SX_LSCALAR); \
+ WLEN(len); \
+ WRITE(pv, len); \
+ } \
+} while (0)
+
+/*
+ * Store undef in arrays and hashes without recusrsing through store().
+ */
+#define STORE_UNDEF() do { \
+ tagnum++; \
+ PUTMARK(SX_UNDEF); \
+ PUTMARK(SX_STORED); \
+} while (0)
+
+/*
+ * Useful retrieve shortcuts...
+ */
+
+#define GETCHAR() \
+ (f ? PerlIO_getc(f) : (mptr >= mend ? EOF : (int) *mptr++))
+
+#define GETMARK(x) do { \
+ if (!f) \
+ MBUF_GETC(x); \
+ else if ((x = PerlIO_getc(f)) == EOF) \
+ return (SV *) 0; \
+} while (0)
+
+#ifdef HAS_NTOHL
+#define RLEN(x) do { \
+ if (!f) \
+ MBUF_GETINT(x); \
+ else if (PerlIO_read(f, &x, sizeof(x)) != sizeof(x)) \
+ return (SV *) 0; \
+ if (netorder) \
+ x = (int) ntohl(x); \
+} while (0)
+#else
+#define RLEN(x) do { \
+ if (!f) \
+ MBUF_GETINT(x); \
+ else if (PerlIO_read(f, &x, sizeof(x)) != sizeof(x)) \
+ return (SV *) 0; \
+} while (0)
+#endif
+
+#define READ(x,y) do { \
+ if (!f) \
+ MBUF_READ(x, y); \
+ else if (PerlIO_read(f, x, y) != y) \
+ return (SV *) 0; \
+} while (0)
+
+#define SAFEREAD(x,y,z) do { \
+ if (!f) \
+ MBUF_SAFEREAD(x,y,z); \
+ else if (PerlIO_read(f, x, y) != y) { \
+ sv_free(z); \
+ return (SV *) 0; \
+ } \
+} while (0)
+
+/*
+ * This macro is used at retrieve time, to remember where object 'y', bearing a
+ * given tag 'tagnum', has been retrieved. Next time we see an SX_OBJECT marker,
+ * we'll therefore know where it has been retrieved and will be able to
+ * share the same reference, as in the original stored memory image.
+ */
+#define SEEN(y) do { \
+ if (!y) \
+ return (SV *) 0; \
+ if (av_store(aseen, tagnum++, SvREFCNT_inc(y)) == 0) \
+ return (SV *) 0; \
+ TRACEME(("aseen(#%d) = 0x%lx (refcnt=%d)", tagnum-1, \
+ (unsigned long) y, SvREFCNT(y)-1)); \
+ } while (0)
+
+static int store();
+static SV *retrieve();
+
+/*
+ * store_ref
+ *
+ * Store a reference.
+ * Layout is SX_REF <object>.
+ */
+static int store_ref(f, sv)
+PerlIO *f;
+SV *sv;
+{
+ TRACEME(("store_ref (0x%lx)", (unsigned long) sv));
+
+ PUTMARK(SX_REF);
+ sv = SvRV(sv);
+ return store(f, sv);
+}
+
+/*
+ * store_scalar
+ *
+ * Store a scalar.
+ *
+ * Layout is SX_LSCALAR <length> <data>, SX_SCALAR <lenght> <data> or SX_UNDEF.
+ * The <data> section is omitted if <length> is 0.
+ *
+ * If integer or double, the layout is SX_INTEGER <data> or SX_DOUBLE <data>.
+ * Small integers (within [-127, +127]) are stored as SX_BYTE <byte>.
+ */
+static int store_scalar(f, sv)
+PerlIO *f;
+SV *sv;
+{
+ IV iv;
+ char *pv;
+ STRLEN len;
+ U32 flags = SvFLAGS(sv); /* "cc -O" may put it in register */
+
+ TRACEME(("store_scalar (0x%lx)", (unsigned long) sv));
+
+ /*
+ * For efficiency, break the SV encapsulation by peaking at the flags
+ * directly without using the Perl macros to avoid dereferencing
+ * sv->sv_flags each time we wish to check the flags.
+ */
+
+ if (!(flags & SVf_OK)) { /* !SvOK(sv) */
+ if (sv == &sv_undef) {
+ TRACEME(("immortal undef"));
+ PUTMARK(SX_SV_UNDEF);
+ } else {
+ TRACEME(("undef"));
+ PUTMARK(SX_UNDEF);
+ }
+ return 0;
+ }
+
+ /*
+ * Always store the string representation of a scalar if it exists.
+ * Gisle Aas provided me with this test case, better than a long speach:
+ *
+ * perl -MDevel::Peek -le '$a="abc"; $a+0; Dump($a)'
+ * SV = PVNV(0x80c8520)
+ * REFCNT = 1
+ * FLAGS = (NOK,POK,pNOK,pPOK)
+ * IV = 0
+ * NV = 0
+ * PV = 0x80c83d0 "abc"\0
+ * CUR = 3
+ * LEN = 4
+ *
+ * Write SX_SCALAR, length, followed by the actual data.
+ *
+ * Otherwise, write an SX_BYTE, SX_INTEGER or an SX_DOUBLE as
+ * appropriate, followed by the actual (binary) data. A double
+ * is written as a string if network order, for portability.
+ *
+ * NOTE: instead of using SvNOK(sv), we test for SvNOKp(sv).
+ * The reason is that when the scalar value is tainted, the SvNOK(sv)
+ * value is false.
+ *
+ * The test for a read-only scalar with both POK and NOK set is meant
+ * to quickly detect &sv_yes and &sv_no without having to pay the address
+ * comparison for each scalar we store.
+ */
+
+#define SV_MAYBE_IMMORTAL (SVf_READONLY|SVf_POK|SVf_NOK)
+
+ if ((flags & SV_MAYBE_IMMORTAL) == SV_MAYBE_IMMORTAL) {
+ if (sv == &sv_yes) {
+ TRACEME(("immortal yes"));
+ PUTMARK(SX_SV_YES);
+ } else if (sv == &sv_no) {
+ TRACEME(("immortal no"));
+ PUTMARK(SX_SV_NO);
+ } else {
+ pv = SvPV(sv, len); /* We know it's SvPOK */
+ goto string; /* Share code below */
+ }
+ } else if (flags & SVp_POK) { /* SvPOKp(sv) => string */
+ pv = SvPV(sv, len);
+
+ /*
+ * Will come here from below with pv and len set if double & netorder,
+ * or from above if it was readonly, POK and NOK but neither &sv_yes
+ * nor &sv_no.
+ */
+ string:
+
+ STORE_SCALAR(pv, len);
+ TRACEME(("ok (scalar 0x%lx '%s', length = %d)",
+ (unsigned long) sv, SvPVX(sv), len));
+
+ } else if (flags & SVp_NOK) { /* SvNOKp(sv) => double */
+ double nv = SvNV(sv);
+
+ /*
+ * Watch for number being an integer in disguise.
+ */
+ if (nv == (double) (iv = I_V(nv))) {
+ TRACEME(("double %lf is actually integer %ld", nv, iv));
+ goto integer; /* Share code below */
+ }
+
+ if (netorder) {
+ TRACEME(("double %lf stored as string", nv));
+ pv = SvPV(sv, len);
+ goto string; /* Share code below */
+ }
+
+ PUTMARK(SX_DOUBLE);
+ WRITE(&nv, sizeof(nv));
+
+ TRACEME(("ok (double 0x%lx, value = %lf)", (unsigned long) sv, nv));
+
+ } else if (flags & SVp_IOK) { /* SvIOKp(sv) => integer */
+ iv = SvIV(sv);
+
+ /*
+ * Will come here from above with iv set if double is an integer.
+ */
+ integer:
+
+ /*
+ * Optimize small integers into a single byte, otherwise store as
+ * a real integer (converted into network order if they asked).
+ */
+
+ if (iv >= -128 && iv <= 127) {
+ unsigned char siv = (unsigned char) (iv + 128); /* [0,255] */
+ PUTMARK(SX_BYTE);
+ PUTMARK(siv);
+ TRACEME(("small integer stored as %d", siv));
+ } else if (netorder) {
+ int niv;
+#ifdef HAS_HTONL
+ niv = (int) htonl(iv);
+ TRACEME(("using network order"));
+#else
+ niv = (int) iv;
+ TRACEME(("as-is for network order"));
+#endif
+ PUTMARK(SX_NETINT);
+ WRITE(&niv, sizeof(niv));
+ } else {
+ PUTMARK(SX_INTEGER);
+ WRITE(&iv, sizeof(iv));
+ }
+
+ TRACEME(("ok (integer 0x%lx, value = %d)", (unsigned long) sv, iv));
+
+ } else
+ croak("Can't determine type of %s(0x%lx)", sv_reftype(sv, FALSE),
+ (unsigned long) sv);
+
+ return 0; /* Ok, no recursion on scalars */
+}
+
+/*
+ * store_array
+ *
+ * Store an array.
+ *
+ * Layout is SX_ARRAY <size> followed by each item, in increading index order.
+ * Each item is stored as <object>.
+ */
+static int store_array(f, av)
+PerlIO *f;
+AV *av;
+{
+ SV **sav;
+ I32 len = av_len(av) + 1;
+ I32 i;
+ int ret;
+
+ TRACEME(("store_array (0x%lx)", (unsigned long) av));
+
+ /*
+ * Signal array by emitting SX_ARRAY, followed by the array length.
+ */
+
+ PUTMARK(SX_ARRAY);
+ WLEN(len);
+ TRACEME(("size = %d", len));
+
+ /*
+ * Now store each item recursively.
+ */
+
+ for (i = 0; i < len; i++) {
+ sav = av_fetch(av, i, 0);
+ if (!sav) {
+ TRACEME(("(#%d) undef item", i));
+ STORE_UNDEF();
+ continue;
+ }
+ TRACEME(("(#%d) item", i));
+ if (ret = store(f, *sav))
+ return ret;
+ }
+
+ TRACEME(("ok (array)"));
+
+ return 0;
+}
+
+/*
+ * sortcmp
+ *
+ * Sort two SVs
+ * Borrowed from perl source file pp_ctl.c, where it is used by pp_sort.
+ */
+static int
+sortcmp(a, b)
+const void *a;
+const void *b;
+{
+ return sv_cmp(*(SV * const *) a, *(SV * const *) b);
+}
+
+
+/*
+ * store_hash
+ *
+ * Store an hash table.
+ *
+ * Layout is SX_HASH <size> followed by each key/value pair, in random order.
+ * Values are stored as <object>.
+ * Keys are stored as <length> <data>, the <data> section being omitted
+ * if length is 0.
+ */
+static int store_hash(f, hv)
+PerlIO *f;
+HV *hv;
+{
+ I32 len = HvKEYS(hv);
+ I32 i;
+ int ret = 0;
+ I32 riter;
+ HE *eiter;
+
+ TRACEME(("store_hash (0x%lx)", (unsigned long) hv));
+
+ /*
+ * Signal hash by emitting SX_HASH, followed by the table length.
+ */
+
+ PUTMARK(SX_HASH);
+ WLEN(len);
+ TRACEME(("size = %d", len));
+
+ /*
+ * Save possible iteration state via each() on that table.
+ */
+
+ riter = HvRITER(hv);
+ eiter = HvEITER(hv);
+ hv_iterinit(hv);
+
+ /*
+ * Now store each item recursively.
+ *
+ * If canonical is defined to some true value then store each
+ * key/value pair in sorted order otherwise the order is random.
+ *
+ * Fetch the value from perl only once per store() operation, and only
+ * when needed.
+ */
+
+ if (
+ canonical == 1 ||
+ (canonical < 0 && (canonical =
+ SvTRUE(perl_get_sv("Storable::canonical", TRUE)) ? 1 : 0))
+ ) {
+ /*
+ * Storing in order, sorted by key.
+ * Run through the hash, building up an array of keys in a
+ * mortal array, sort the array and then run through the
+ * array.
+ */
+
+ AV *av = newAV();
+
+ TRACEME(("using canonical order"));
+
+ for (i = 0; i < len; i++) {
+ HE *he = hv_iternext(hv);
+ SV *key = hv_iterkeysv(he);
+ av_push(av, key);
+ }
+
+ qsort((char *) AvARRAY(av), len, sizeof(SV *), sortcmp);
+
+ for (i = 0; i < len; i++) {
+ char *keyval;
+ I32 keylen;
+ SV *key = av_shift(av);
+ HE *he = hv_fetch_ent(hv, key, 0, 0);
+ SV *val = HeVAL(he);
+ if (val == 0)
+ return 1; /* Internal error, not I/O error */
+
+ /*
+ * Store value first, if defined.
+ */
+
+ if (!SvOK(val)) {
+ TRACEME(("undef value"));
+ STORE_UNDEF();
+ } else {
+ TRACEME(("(#%d) value 0x%lx", i, (unsigned long) val));
+ if (ret = store(f, val))
+ goto out;
+ }
+
+ /*
+ * Write key string.
+ * Keys are written after values to make sure retrieval
+ * can be optimal in terms of memory usage, where keys are
+ * read into a fixed unique buffer called kbuf.
+ * See retrieve_hash() for details.
+ */
+
+ keyval = hv_iterkey(he, &keylen);
+ TRACEME(("(#%d) key '%s'", i, keyval));
+ WLEN(keylen);
+ if (keylen)
+ WRITE(keyval, keylen);
+ }
+
+ /*
+ * Free up the temporary array
+ */
+
+ av_undef(av);
+ sv_free((SV *) av);
+
+ } else {
+
+ /*
+ * Storing in "random" order (in the order the keys are stored
+ * within the the hash). This is the default and will be faster!
+ */
+
+ for (i = 0; i < len; i++) {
+ char *key;
+ I32 len;
+ SV *val = hv_iternextsv(hv, &key, &len);
+
+ if (val == 0)
+ return 1; /* Internal error, not I/O error */
+
+ /*
+ * Store value first, if defined.
+ */
+
+ if (!SvOK(val)) {
+ TRACEME(("undef value"));
+ STORE_UNDEF();
+ } else {
+ TRACEME(("(#%d) value 0x%lx", i, (unsigned long) val));
+ if (ret = store(f, val))
+ goto out;
+ }
+
+ /*
+ * Write key string.
+ * Keys are written after values to make sure retrieval
+ * can be optimal in terms of memory usage, where keys are
+ * read into a fixed unique buffer called kbuf.
+ * See retrieve_hash() for details.
+ */
+
+ TRACEME(("(#%d) key '%s'", i, key));
+ WLEN(len);
+ if (len)
+ WRITE(key, len);
+ }
+ }
+
+ TRACEME(("ok (hash 0x%lx)", (unsigned long) hv));
+
+out:
+ HvRITER(hv) = riter; /* Restore hash iterator state */
+ HvEITER(hv) = eiter;
+
+ return ret;
+}
+
+/*
+ * store_tied
+ *
+ * When storing a tied object (be it a tied scalar, array or hash), we lay out
+ * a special mark, followed by the underlying tied object. For instance, when
+ * dealing with a tied hash, we store SX_TIED_HASH <hash object>, where
+ * <hash object> stands for the serialization of the tied hash.
+ */
+static int store_tied(f, sv)
+PerlIO *f;
+SV *sv;
+{
+ MAGIC *mg;
+ int ret = 0;
+ int svt = SvTYPE(sv);
+ char mtype = 'P';
+
+ TRACEME(("store_tied (0x%lx)", (unsigned long) sv));
+
+ /*
+ * We have a small run-time penalty here because we chose to factorise
+ * all tieds objects into the same routine, and not have a store_tied_hash,
+ * a store_tied_array, etc...
+ *
+ * Don't use a switch() statement, as most compilers don't optimize that
+ * well for 2/3 values. An if() else if() cascade is just fine. We put
+ * tied hashes first, as they are the most likely beasts.
+ */
+
+ if (svt == SVt_PVHV) {
+ TRACEME(("tied hash"));
+ PUTMARK(SX_TIED_HASH); /* Introduces tied hash */
+ } else if (svt == SVt_PVAV) {
+ TRACEME(("tied array"));
+ PUTMARK(SX_TIED_ARRAY); /* Introduces tied array */
+ } else {
+ TRACEME(("tied scalar"));
+ PUTMARK(SX_TIED_SCALAR); /* Introduces tied scalar */
+ mtype = 'q';
+ }
+
+ if (!(mg = mg_find(sv, mtype)))
+ croak("No magic '%c' found while storing tied %s", mtype,
+ (svt == SVt_PVHV) ? "hash" :
+ (svt == SVt_PVAV) ? "array" : "scalar");
+
+ /*
+ * The mg->mg_obj found by mg_find() above actually points to the
+ * underlying tied Perl object implementation. For instance, if the
+ * original SV was that of a tied array, then mg->mg_obj is an AV.
+ *
+ * Note that we store the Perl object as-is. We don't call its FETCH
+ * method along the way. At retrieval time, we won't call its STORE
+ * method either, but the tieing magic will be re-installed. In itself,
+ * that ensures that the tieing semantics are preserved since futher
+ * accesses on the retrieved object will indeed call the magic methods...
+ */
+
+ if (ret = store(f, mg->mg_obj))
+ return ret;
+
+ TRACEME(("ok (tied)"));
+
+ return 0;
+}
+
+/*
+ * store_other
+ *
+ * We don't know how to store the item we reached, so return an error condition.
+ * (it's probably a GLOB, some CODE reference, etc...)
+ *
+ * If they defined the `forgive_me' variable at the Perl level to some
+ * true value, then don't croak, just warn, and store a placeholder string
+ * instead.
+ */
+static int store_other(f, sv)
+PerlIO *f;
+SV *sv;
+{
+ STRLEN len;
+ static char buf[80];
+
+ TRACEME(("store_other"));
+
+ /*
+ * Fetch the value from perl only once per store() operation.
+ */
+
+ if (
+ forgive_me == 0 ||
+ (forgive_me < 0 && !(forgive_me =
+ SvTRUE(perl_get_sv("Storable::forgive_me", TRUE)) ? 1 : 0))
+ )
+ croak("Can't store %s items", sv_reftype(sv, FALSE));
+
+ warn("Can't store %s items", sv_reftype(sv, FALSE));
+
+ /*
+ * Store placeholder string as a scalar instead...
+ */
+
+ (void) sprintf(buf, "You lost %s(0x%lx)\0", sv_reftype(sv, FALSE),
+ (unsigned long) sv);
+
+ len = strlen(buf);
+ STORE_SCALAR(buf, len);
+ TRACEME(("ok (dummy \"%s\", length = %d)", buf, len));
+
+ return 0;
+}
+
+/*
+ * Dynamic dispatching table for SV store.
+ */
+static int (*sv_store[])() = {
+ store_ref, /* svis_REF */
+ store_scalar, /* svis_SCALAR */
+ store_array, /* svis_ARRAY */
+ store_hash, /* svis_HASH */
+ store_tied, /* svis_TIED */
+ store_other, /* svis_OTHER */
+};
+
+#define SV_STORE(x) (*sv_store[x])
+
+/*
+ * sv_type
+ *
+ * WARNING: partially duplicates Perl's sv_reftype for speed.
+ *
+ * Returns the type of the SV, identified by an integer. That integer
+ * may then be used to index the dynamic routine dispatch table.
+ */
+static int sv_type(sv)
+SV *sv;
+{
+ switch (SvTYPE(sv)) {
+ case SVt_NULL:
+ case SVt_IV:
+ case SVt_NV:
+ /*
+ * No need to check for ROK, that can't be set here since there
+ * is no field capable of hodling the xrv_rv reference.
+ */
+ return svis_SCALAR;
+ case SVt_PV:
+ case SVt_RV:
+ case SVt_PVIV:
+ case SVt_PVNV:
+ /*
+ * Starting from SVt_PV, it is possible to have the ROK flag
+ * set, the pointer to the other SV being either stored in
+ * the xrv_rv (in the case of a pure SVt_RV), or as the
+ * xpv_pv field of an SVt_PV and its heirs.
+ *
+ * However, those SV cannot be magical or they would be an
+ * SVt_PVMG at least.
+ */
+ return SvROK(sv) ? svis_REF : svis_SCALAR;
+ case SVt_PVMG:
+ case SVt_PVLV: /* Workaround for perl5.004_04 "LVALUE" bug */
+ case SVt_PVBM:
+ if (SvRMAGICAL(sv) && (mg_find(sv, 'q')))
+ return svis_TIED;
+ return SvROK(sv) ? svis_REF : svis_SCALAR;
+ case SVt_PVAV:
+ if (SvRMAGICAL(sv) && (mg_find(sv, 'P')))
+ return svis_TIED;
+ return svis_ARRAY;
+ case SVt_PVHV:
+ if (SvRMAGICAL(sv) && (mg_find(sv, 'P')))
+ return svis_TIED;
+ return svis_HASH;
+ default:
+ break;
+ }
+
+ return svis_OTHER;
+}
+
+/*
+ * store
+ *
+ * Recursively store objects pointed to by the sv to the specified file.
+ *
+ * Layout is <content> SX_STORED or SX_OBJECT <tagnum> SX_STORED if we
+ * reach an already stored object (one for which storage has started--
+ * it may not be over if we have a self-referenced structure). This data set
+ * forms a stored <object>.
+ */
+static int store(f, sv)
+PerlIO *f;
+SV *sv;
+{
+ SV **svh;
+ int ret;
+ int type;
+ SV *tag;
+
+ TRACEME(("store (0x%lx)", (unsigned long) sv));
+
+ /*
+ * If object has already been stored, do not duplicate data.
+ * Simply emit the SX_OBJECT marker followed by its tag data.
+ * The tag is always written in network order.
+ */
+
+ svh = hv_fetch(hseen, (char *) &sv, sizeof(sv), FALSE);
+ if (svh) {
+ I32 tagval = htonl((I32) (*svh));
+ TRACEME(("object 0x%lx seen as #%d.", (unsigned long) sv, tagval));
+ PUTMARK(SX_OBJECT);
+ WRITE(&tagval, sizeof(I32));
+ return 0;
+ }
+
+ /*
+ * Allocate a new tag and associate it with the address of the sv being
+ * stored, before recursing...
+ *
+ * In order to avoid creating new SvIVs to hold the tagnum we just
+ * cast the tagnum to a SV pointer and store that in the hash. This
+ * means that we must clean up the hash manually afterwards, but gives
+ * us a 15% throughput increase.
+ */
+
+ if (!hv_store(hseen, (char *) &sv, sizeof(sv), (SV*) (tagnum++), 0))
+ return -1;
+ TRACEME(("recorded 0x%lx as object #%d", (unsigned long) sv, tagnum));
+
+ /*
+ * Call the proper routine to store this SV.
+ * Abort immediately if we get a non-zero status back.
+ */
+
+ type = sv_type(sv);
+ TRACEME(("storing 0x%lx #%d type=%d...", (unsigned long) sv, tagnum, type));
+ if (ret = SV_STORE(type)(f, sv))
+ return ret;
+
+ /*
+ * If object is blessed, notify the blessing now.
+ *
+ * Since the storable mechanism is going to make usage of lots
+ * of blessed objects (!), we're trying to optimize the cost
+ * by having two separate blessing notifications:
+ * SX_BLESS <char-len> <class> for short classnames (<255 chars)
+ * SX_LG_BLESS <int-len> <class> for larger classnames.
+ */
+
+ if (SvOBJECT(sv)) {
+ char *class = HvNAME(SvSTASH(sv));
+ I32 len = strlen(class);
+ unsigned char clen;
+ TRACEME(("blessing 0x%lx in %s", (unsigned long) sv, class));
+ if (len <= LG_BLESS) {
+ PUTMARK(SX_BLESS);
+ clen = (unsigned char) len;
+ PUTMARK(clen);
+ } else {
+ PUTMARK(SX_LG_BLESS);
+ WLEN(len);
+ }
+ WRITE(class, len); /* Final \0 is omitted */
+ }
+
+ PUTMARK(SX_STORED);
+ TRACEME(("ok (store 0x%lx)", (unsigned long) sv));
+
+ return 0; /* Done, with success */
+}
+
+/*
+ * magic_write
+ *
+ * Write magic number and system information into the file.
+ * Layout is <magic> <network> [<len> <byteorder> <sizeof int> <sizeof long>
+ * <sizeof ptr>] where <len> is the length of the byteorder hexa string.
+ * All size and lenghts are written as single characters here.
+ *
+ * Note that no byte ordering info is emitted when <network> is true, since
+ * integers will be emitted in network order in that case.
+ */
+static int magic_write(f, use_network_order)
+PerlIO *f;
+int use_network_order;
+{
+ char buf[256]; /* Enough room for 256 hexa digits */
+ unsigned char c;
+
+ TRACEME(("magic_write on fd=%d", fileno(f)));
+
+ if (f)
+ WRITE(magicstr, strlen(magicstr)); /* Don't write final \0 */
+
+ /*
+ * Starting with 0.6, the "use_network_order" byte flag is also used to
+ * indicate the version number of the binary image, encoded in the upper
+ * bits. The bit 0 is always used to indicate network order.
+ */
+
+ c = (unsigned char)
+ ((use_network_order ? 0x1 : 0x0) | (STORABLE_BINARY << 1));
+ PUTMARK(c);
+
+ if (use_network_order)
+ return 0; /* Don't bother with byte ordering */
+
+ sprintf(buf, "%lx", (unsigned long) BYTEORDER);
+ c = (unsigned char) strlen(buf);
+ PUTMARK(c);
+ WRITE(buf, (unsigned int) c); /* Don't write final \0 */
+ PUTMARK((unsigned char) sizeof(int));
+ PUTMARK((unsigned char) sizeof(long));
+ PUTMARK((unsigned char) sizeof(char *));
+
+ TRACEME(("ok (magic_write byteorder = 0x%lx [%d], I%d L%d P%d)",
+ (unsigned long) BYTEORDER, (int) c,
+ sizeof(int), sizeof(long), sizeof(char *)));
+
+ return 0;
+}
+
+/*
+ * do_store
+ *
+ * Common code for pstore() and net_pstore().
+ */
+static int do_store(f, sv, use_network_order)
+PerlIO *f;
+SV *sv;
+int use_network_order;
+{
+ int status;
+
+ netorder = use_network_order; /* Global, not suited for multi-thread */
+ forgive_me = -1; /* Unknown, fetched from perl if needed */
+ canonical = -1; /* Idem */
+ tagnum = 0; /* Reset tag numbers */
+
+ if (-1 == magic_write(f, netorder)) /* Emit magic number and system info */
+ return 0; /* Error */
+
+ /*
+ * Ensure sv is actually a reference. From perl, we called something
+ * like:
+ * pstore(FILE, \@array);
+ * so we must get the scalar value behing that reference.
+ */
+
+ if (!SvROK(sv))
+ croak("Not a reference");
+ sv = SvRV(sv); /* So follow it to know what to store */
+
+ /*
+ * The hash table used to keep track of each SV stored and their
+ * associated tag numbers is special. It is "abused" because the
+ * values stored are not real SV, just integers cast to (SV *),
+ * which explains the freeing below.
+ *
+ * It is also one possible bottlneck to achieve good storing speed,
+ * so the "shared keys" optimization is turned off (unlikely to be
+ * of any use here), and the hash table is "pre-extended". Together,
+ * those optimizations increase the throughput by 12%.
+ */
+
+ hseen = newHV(); /* Table where seen objects are stored */
+ HvSHAREKEYS_off(hseen);
+
+ /*
+ * The following does not work well with perl5.004_04, and causes
+ * a core dump later on, in a completely unrelated spot, which
+ * makes me think there is a memory corruption going on.
+ *
+ * Calling hv_ksplit(hseen, HBUCKETS) instead of manually hacking
+ * it below does not make any difference. It seems to work fine
+ * with perl5.004_68 but given the probable nature of the bug,
+ * that does not prove anything.
+ *
+ * It's a shame because increasing the amount of buckets raises
+ * store() throughput by 5%, but until I figure this out, I can't
+ * allow for this to go into production.
+ */
+#if 0
+#define HBUCKETS 4096 /* Buckets for %hseen */
+ HvMAX(hseen) = HBUCKETS - 1; /* keys %hseen = $HBUCKETS; */
+#endif
+
+ /*
+ * Recursively store object...
+ */
+
+ status = store(f, sv); /* Just do it! */
+
+ /*
+ * Need to free the hseen table, but since we have stored fake
+ * value pointers in it, we need to make them real first.
+ */
+
+ {
+ HE * he;
+
+ hv_iterinit(hseen);
+ while (he = hv_iternext(hseen))
+ HeVAL(he) = &sv_undef;
+ }
+ hv_undef(hseen); /* Free seen object table */
+ sv_free((SV *) hseen); /* Free HV */
+
+ TRACEME(("do_store returns %d", status));
+
+ return status == 0;
+}
+
+/*
+ * mbuf2sv
+ *
+ * Build a new SV out of the content of the internal memory buffer.
+ */
+static SV *mbuf2sv()
+{
+ return newSVpv(mbase, MBUF_SIZE());
+}
+
+/*
+ * mstore
+ *
+ * Store the transitive data closure of given object to memory.
+ * Returns undef on error, a scalar value containing the data otherwise.
+ */
+SV *mstore(sv)
+SV *sv;
+{
+ TRACEME(("mstore"));
+ MBUF_INIT(0);
+ if (!do_store(0, sv, FALSE)) /* Not in network order */
+ return &sv_undef;
+
+ return mbuf2sv();
+}
+
+/*
+ * net_mstore
+ *
+ * Same as mstore(), but network order is used for integers and doubles are
+ * emitted as strings.
+ */
+SV *net_mstore(sv)
+SV *sv;
+{
+ TRACEME(("net_mstore"));
+ MBUF_INIT(0);
+ if (!do_store(0, sv, TRUE)) /* Use network order */
+ return &sv_undef;
+
+ return mbuf2sv();
+}
+
+/*
+ * pstore
+ *
+ * Store the transitive data closure of given object to disk.
+ * Returns 0 on error, a true value otherwise.
+ */
+int pstore(f, sv)
+PerlIO *f;
+SV *sv;
+{
+ TRACEME(("pstore"));
+ return do_store(f, sv, FALSE); /* Not in network order */
+
+}
+
+/*
+ * net_pstore
+ *
+ * Same as pstore(), but network order is used for integers and doubles are
+ * emitted as strings.
+ */
+int net_pstore(f, sv)
+PerlIO *f;
+SV *sv;
+{
+ TRACEME(("net_pstore"));
+ return do_store(f, sv, TRUE); /* Use network order */
+}
+
+/*
+ * retrieve_ref
+ *
+ * Retrieve reference to some other scalar.
+ * Layout is SX_REF <object>, with SX_REF already read.
+ */
+static SV *retrieve_ref(f)
+PerlIO *f;
+{
+ SV *rv;
+ SV *sv;
+
+ TRACEME(("retrieve_ref (#%d)", tagnum));
+
+ /*
+ * We need to create the SV that holds the reference to the yet-to-retrieve
+ * object now, so that we may record the address in the seen table.
+ * Otherwise, if the object to retrieve references us, we won't be able
+ * to resolve the SX_OBJECT we'll see at that point! Hence we cannot
+ * do the retrieve first and use rv = newRV(sv) since it will be too late
+ * for SEEN() recording.
+ */
+
+ rv = NEWSV(10002, 0);
+ SEEN(rv); /* Will return if rv is null */
+ sv = retrieve(f); /* Retrieve <object> */
+ if (!sv)
+ return (SV *) 0; /* Failed */
+
+ /*
+ * WARNING: breaks RV encapsulation.
+ *
+ * Now for the tricky part. We have to upgrade our existing SV, so that
+ * it is now an RV on sv... Again, we cheat by duplicating the code
+ * held in newSVrv(), since we already got our SV from retrieve().
+ *
+ * We don't say:
+ *
+ * SvRV(rv) = SvREFCNT_inc(sv);
+ *
+ * here because the reference count we got from retrieve() above is
+ * already correct: if the object was retrieved from the file, then
+ * its reference count is one. Otherwise, if it was retrieved via
+ * an SX_OBJECT indication, a ref count increment was done.
+ */
+
+ sv_upgrade(rv, SVt_RV);
+ SvRV(rv) = sv; /* $rv = \$sv */
+ SvROK_on(rv);
+
+ TRACEME(("ok (retrieve_ref at 0x%lx)", (unsigned long) rv));
+
+ return rv;
+}
+
+/*
+ * retrieve_tied_array
+ *
+ * Retrieve tied array
+ * Layout is SX_TIED_ARRAY <object>, with SX_TIED_ARRAY already read.
+ */
+static SV *retrieve_tied_array(f)
+PerlIO *f;
+{
+ SV *tv;
+ SV *sv;
+
+ TRACEME(("retrieve_tied_array (#%d)", tagnum));
+
+ tv = NEWSV(10002, 0);
+ SEEN(tv); /* Will return if tv is null */
+ sv = retrieve(f); /* Retrieve <object> */
+ if (!sv)
+ return (SV *) 0; /* Failed */
+
+ sv_upgrade(tv, SVt_PVAV);
+ AvREAL_off((AV *)tv);
+ sv_magic(tv, sv, 'P', Nullch, 0);
+ SvREFCNT_dec(sv); /* Undo refcnt inc from sv_magic() */
+
+ TRACEME(("ok (retrieve_tied_array at 0x%lx)", (unsigned long) tv));
+
+ return tv;
+}
+
+/*
+ * retrieve_tied_hash
+ *
+ * Retrieve tied hash
+ * Layout is SX_TIED_HASH <object>, with SX_TIED_HASH already read.
+ */
+static SV *retrieve_tied_hash(f)
+PerlIO *f;
+{
+ SV *tv;
+ SV *sv;
+
+ TRACEME(("retrieve_tied_hash (#%d)", tagnum));
+
+ tv = NEWSV(10002, 0);
+ SEEN(tv); /* Will return if rv is null */
+ sv = retrieve(f); /* Retrieve <object> */
+ if (!sv)
+ return (SV *) 0; /* Failed */
+
+ sv_upgrade(tv, SVt_PVHV);
+ sv_magic(tv, sv, 'P', Nullch, 0);
+ SvREFCNT_dec(sv); /* Undo refcnt inc from sv_magic() */
+
+ TRACEME(("ok (retrieve_tied_hash at 0x%lx)", (unsigned long) tv));
+
+ return tv;
+}
+
+/*
+ * retrieve_tied_scalar
+ *
+ * Retrieve tied scalar
+ * Layout is SX_TIED_SCALAR <object>, with SX_TIED_SCALAR already read.
+ */
+static SV *retrieve_tied_scalar(f)
+PerlIO *f;
+{
+ SV *tv;
+ SV *sv;
+
+ TRACEME(("retrieve_tied_scalar (#%d)", tagnum));
+
+ tv = NEWSV(10002, 0);
+ SEEN(tv); /* Will return if rv is null */
+ sv = retrieve(f); /* Retrieve <object> */
+ if (!sv)
+ return (SV *) 0; /* Failed */
+
+ sv_upgrade(tv, SVt_PVMG);
+ sv_magic(tv, sv, 'q', Nullch, 0);
+ SvREFCNT_dec(sv); /* Undo refcnt inc from sv_magic() */
+
+ TRACEME(("ok (retrieve_tied_scalar at 0x%lx)", (unsigned long) tv));
+
+ return tv;
+}
+
+/*
+ * retrieve_lscalar
+ *
+ * Retrieve defined long (string) scalar.
+ *
+ * Layout is SX_LSCALAR <length> <data>, with SX_LSCALAR already read.
+ * The scalar is "long" in that <length> is larger than LG_SCALAR so it
+ * was not stored on a single byte.
+ */
+static SV *retrieve_lscalar(f)
+PerlIO *f;
+{
+ STRLEN len;
+ SV *sv;
+
+ RLEN(len);
+ TRACEME(("retrieve_lscalar (#%d), len = %d", tagnum, len));
+
+ /*
+ * Allocate an empty scalar of the suitable length.
+ */
+
+ sv = NEWSV(10002, len);
+ SEEN(sv); /* Associate this new scalar with tag "tagnum" */
+
+ /*
+ * WARNING: duplicates parts of sv_setpv and breaks SV data encapsulation.
+ *
+ * Now, for efficiency reasons, read data directly inside the SV buffer,
+ * and perform the SV final settings directly by duplicating the final
+ * work done by sv_setpv. Since we're going to allocate lots of scalars
+ * this way, it's worth the hassle and risk.
+ */
+
+ SAFEREAD(SvPVX(sv), len, sv);
+ SvCUR_set(sv, len); /* Record C string length */
+ *SvEND(sv) = '\0'; /* Ensure it's null terminated anyway */
+ (void) SvPOK_only(sv); /* Validate string pointer */
+ SvTAINT(sv); /* External data cannot be trusted */
+
+ TRACEME(("large scalar len %d '%s'", len, SvPVX(sv)));
+ TRACEME(("ok (retrieve_lscalar at 0x%lx)", (unsigned long) sv));
+
+ return sv;
+}
+
+/*
+ * retrieve_scalar
+ *
+ * Retrieve defined short (string) scalar.
+ *
+ * Layout is SX_SCALAR <length> <data>, with SX_SCALAR already read.
+ * The scalar is "short" so <length> is single byte. If it is 0, there
+ * is no <data> section.
+ */
+static SV *retrieve_scalar(f)
+PerlIO *f;
+{
+ int len;
+ SV *sv;
+
+ GETMARK(len);
+ TRACEME(("retrieve_scalar (#%d), len = %d", tagnum, len));
+
+ /*
+ * Allocate an empty scalar of the suitable length.
+ */
+
+ sv = NEWSV(10002, len);
+ SEEN(sv); /* Associate this new scalar with tag "tagnum" */
+
+ /*
+ * WARNING: duplicates parts of sv_setpv and breaks SV data encapsulation.
+ */
+
+ if (len == 0) {
+ /*
+ * newSV did not upgrade to SVt_PV so the scalar is undefined.
+ * To make it defined with an empty length, upgrade it now...
+ */
+ sv_upgrade(sv, SVt_PV);
+ SvGROW(sv, 1);
+ *SvEND(sv) = '\0'; /* Ensure it's null terminated anyway */
+ TRACEME(("ok (retrieve_scalar empty at 0x%lx)", (unsigned long) sv));
+ } else {
+ /*
+ * Now, for efficiency reasons, read data directly inside the SV buffer,
+ * and perform the SV final settings directly by duplicating the final
+ * work done by sv_setpv. Since we're going to allocate lots of scalars
+ * this way, it's worth the hassle and risk.
+ */
+ SAFEREAD(SvPVX(sv), len, sv);
+ SvCUR_set(sv, len); /* Record C string length */
+ *SvEND(sv) = '\0'; /* Ensure it's null terminated anyway */
+ TRACEME(("small scalar len %d '%s'", len, SvPVX(sv)));
+ }
+
+ (void) SvPOK_only(sv); /* Validate string pointer */
+ SvTAINT(sv); /* External data cannot be trusted */
+
+ TRACEME(("ok (retrieve_scalar at 0x%lx)", (unsigned long) sv));
+ return sv;
+}
+
+/*
+ * retrieve_integer
+ *
+ * Retrieve defined integer.
+ * Layout is SX_INTEGER <data>, whith SX_INTEGER already read.
+ */
+static SV *retrieve_integer(f)
+PerlIO *f;
+{
+ SV *sv;
+ IV iv;
+
+ TRACEME(("retrieve_integer (#%d)", tagnum));
+
+ READ(&iv, sizeof(iv));
+ sv = newSViv(iv);
+ SEEN(sv); /* Associate this new scalar with tag "tagnum" */
+
+ TRACEME(("integer %d", iv));
+ TRACEME(("ok (retrieve_integer at 0x%lx)", (unsigned long) sv));
+
+ return sv;
+}
+
+/*
+ * retrieve_netint
+ *
+ * Retrieve defined integer in network order.
+ * Layout is SX_NETINT <data>, whith SX_NETINT already read.
+ */
+static SV *retrieve_netint(f)
+PerlIO *f;
+{
+ SV *sv;
+ int iv;
+
+ TRACEME(("retrieve_netint (#%d)", tagnum));
+
+ READ(&iv, sizeof(iv));
+#ifdef HAS_NTOHL
+ sv = newSViv((int) ntohl(iv));
+ TRACEME(("network integer %d", (int) ntohl(iv)));
+#else
+ sv = newSViv(iv);
+ TRACEME(("network integer (as-is) %d", iv));
+#endif
+ SEEN(sv); /* Associate this new scalar with tag "tagnum" */
+
+ TRACEME(("ok (retrieve_netint at 0x%lx)", (unsigned long) sv));
+
+ return sv;
+}
+
+/*
+ * retrieve_double
+ *
+ * Retrieve defined double.
+ * Layout is SX_DOUBLE <data>, whith SX_DOUBLE already read.
+ */
+static SV *retrieve_double(f)
+PerlIO *f;
+{
+ SV *sv;
+ double nv;
+
+ TRACEME(("retrieve_double (#%d)", tagnum));
+
+ READ(&nv, sizeof(nv));
+ sv = newSVnv(nv);
+ SEEN(sv); /* Associate this new scalar with tag "tagnum" */
+
+ TRACEME(("double %lf", nv));
+ TRACEME(("ok (retrieve_double at 0x%lx)", (unsigned long) sv));
+
+ return sv;
+}
+
+/*
+ * retrieve_byte
+ *
+ * Retrieve defined byte (small integer within the [-128, +127] range).
+ * Layout is SX_BYTE <data>, whith SX_BYTE already read.
+ */
+static SV *retrieve_byte(f)
+PerlIO *f;
+{
+ SV *sv;
+ int siv;
+
+ TRACEME(("retrieve_byte (#%d)", tagnum));
+
+ GETMARK(siv);
+ TRACEME(("small integer read as %d", (unsigned char) siv));
+ sv = newSViv((unsigned char) siv - 128);
+ SEEN(sv); /* Associate this new scalar with tag "tagnum" */
+
+ TRACEME(("byte %d", (unsigned char) siv - 128));
+ TRACEME(("ok (retrieve_byte at 0x%lx)", (unsigned long) sv));
+
+ return sv;
+}
+
+/*
+ * retrieve_undef
+ *
+ * Return the undefined value.
+ */
+static SV *retrieve_undef()
+{
+ SV* sv;
+
+ TRACEME(("retrieve_undef"));
+
+ sv = newSV(0);
+ SEEN(sv);
+
+ return sv;
+}
+
+/*
+ * retrieve_sv_undef
+ *
+ * Return the immortal undefined value.
+ */
+static SV *retrieve_sv_undef()
+{
+ SV *sv = &sv_undef;
+
+ TRACEME(("retrieve_sv_undef"));
+
+ SEEN(sv);
+ return sv;
+}
+
+/*
+ * retrieve_sv_yes
+ *
+ * Return the immortal yes value.
+ */
+static SV *retrieve_sv_yes()
+{
+ SV *sv = &sv_yes;
+
+ TRACEME(("retrieve_sv_yes"));
+
+ SEEN(sv);
+ return sv;
+}
+
+/*
+ * retrieve_sv_no
+ *
+ * Return the immortal no value.
+ */
+static SV *retrieve_sv_no()
+{
+ SV *sv = &sv_no;
+
+ TRACEME(("retrieve_sv_no"));
+
+ SEEN(sv);
+ return sv;
+}
+
+/*
+ * retrieve_other
+ *
+ * Return an error via croak, since it is not possible that we get here
+ * under normal conditions, when facing a file produced via pstore().
+ */
+static SV *retrieve_other()
+{
+ croak("Corrupted perl storable file");
+ return (SV *) 0;
+}
+
+/*
+ * retrieve_array
+ *
+ * Retrieve a whole array.
+ * Layout is SX_ARRAY <size> followed by each item, in increading index order.
+ * Each item is stored as <object>.
+ *
+ * When we come here, SX_ARRAY has been read already.
+ */
+static SV *retrieve_array(f)
+PerlIO *f;
+{
+ I32 len;
+ I32 i;
+ AV *av;
+ SV *sv;
+
+ TRACEME(("retrieve_array (#%d)", tagnum));
+
+ /*
+ * Read length, and allocate array, then pre-extend it.
+ */
+
+ RLEN(len);
+ TRACEME(("size = %d", len));
+ av = newAV();
+ SEEN(av); /* Will return if array not allocated nicely */
+ if (len)
+ av_extend(av, len);
+ else
+ return (SV *) av; /* No data follow if array is empty */
+
+ /*
+ * Now get each item in turn...
+ */
+
+ for (i = 0; i < len; i++) {
+ TRACEME(("(#%d) item", i));
+ sv = retrieve(f); /* Retrieve item */
+ if (!sv)
+ return (SV *) 0;
+ if (av_store(av, i, sv) == 0)
+ return (SV *) 0;
+ }
+
+ TRACEME(("ok (retrieve_array at 0x%lx)", (unsigned long) av));
+
+ return (SV *) av;
+}
+
+/*
+ * retrieve_hash
+ *
+ * Retrieve a whole hash table.
+ * Layout is SX_HASH <size> followed by each key/value pair, in random order.
+ * Keys are stored as <length> <data>, the <data> section being omitted
+ * if length is 0.
+ * Values are stored as <object>.
+ *
+ * When we come here, SX_HASH has been read already.
+ */
+static SV *retrieve_hash(f)
+PerlIO *f;
+{
+ I32 len;
+ I32 size;
+ I32 i;
+ HV *hv;
+ SV *sv;
+ static SV *sv_h_undef = (SV *) 0; /* hv_store() bug */
+
+ TRACEME(("retrieve_hash (#%d)", tagnum));
+
+ /*
+ * Read length, allocate table.
+ */
+
+ RLEN(len);
+ TRACEME(("size = %d", len));
+ hv = newHV();
+ SEEN(hv); /* Will return if table not allocated properly */
+ if (len == 0)
+ return (SV *) hv; /* No data follow if table empty */
+
+ /*
+ * Now get each key/value pair in turn...
+ */
+
+ for (i = 0; i < len; i++) {
+ /*
+ * Get value first.
+ */
+
+ TRACEME(("(#%d) value", i));
+ sv = retrieve(f);
+ if (!sv)
+ return (SV *) 0;
+
+ /*
+ * Get key.
+ * Since we're reading into kbuf, we must ensure we're not
+ * recursing between the read and the hv_store() where it's used.
+ * Hence the key comes after the value.
+ */
+
+ RLEN(size); /* Get key size */
+ KBUFCHK(size); /* Grow hash key read pool if needed */
+ if (size)
+ READ(kbuf, size);
+ kbuf[size] = '\0'; /* Mark string end, just in case */
+ TRACEME(("(#%d) key '%s'", i, kbuf));
+
+ /*
+ * Enter key/value pair into hash table.
+ */
+
+ if (hv_store(hv, kbuf, (U32) size, sv, 0) == 0)
+ return (SV *) 0;
+ }
+
+ TRACEME(("ok (retrieve_hash at 0x%lx)", (unsigned long) hv));
+
+ return (SV *) hv;
+}
+
+/*
+ * old_retrieve_array
+ *
+ * Retrieve a whole array in pre-0.6 binary format.
+ *
+ * Layout is SX_ARRAY <size> followed by each item, in increading index order.
+ * Each item is stored as SX_ITEM <object> or SX_IT_UNDEF for "holes".
+ *
+ * When we come here, SX_ARRAY has been read already.
+ */
+static SV *old_retrieve_array(f)
+PerlIO *f;
+{
+ I32 len;
+ I32 i;
+ AV *av;
+ SV *sv;
+ int c;
+
+ TRACEME(("old_retrieve_array (#%d)", tagnum));
+
+ /*
+ * Read length, and allocate array, then pre-extend it.
+ */
+
+ RLEN(len);
+ TRACEME(("size = %d", len));
+ av = newAV();
+ SEEN(av); /* Will return if array not allocated nicely */
+ if (len)
+ av_extend(av, len);
+ else
+ return (SV *) av; /* No data follow if array is empty */
+
+ /*
+ * Now get each item in turn...
+ */
+
+ for (i = 0; i < len; i++) {
+ GETMARK(c);
+ if (c == SX_IT_UNDEF) {
+ TRACEME(("(#%d) undef item", i));
+ continue; /* av_extend() already filled us with undef */
+ }
+ if (c != SX_ITEM)
+ (void) retrieve_other(); /* Will croak out */
+ TRACEME(("(#%d) item", i));
+ sv = retrieve(f); /* Retrieve item */
+ if (!sv)
+ return (SV *) 0;
+ if (av_store(av, i, sv) == 0)
+ return (SV *) 0;
+ }
+
+ TRACEME(("ok (old_retrieve_array at 0x%lx)", (unsigned long) av));
+
+ return (SV *) av;
+}
+
+/*
+ * old_retrieve_hash
+ *
+ * Retrieve a whole hash table in pre-0.6 binary format.
+ *
+ * Layout is SX_HASH <size> followed by each key/value pair, in random order.
+ * Keys are stored as SX_KEY <length> <data>, the <data> section being omitted
+ * if length is 0.
+ * Values are stored as SX_VALUE <object> or SX_VL_UNDEF for "holes".
+ *
+ * When we come here, SX_HASH has been read already.
+ */
+static SV *old_retrieve_hash(f)
+PerlIO *f;
+{
+ I32 len;
+ I32 size;
+ I32 i;
+ HV *hv;
+ SV *sv;
+ int c;
+ static SV *sv_h_undef = (SV *) 0; /* hv_store() bug */
+
+ TRACEME(("old_retrieve_hash (#%d)", tagnum));
+
+ /*
+ * Read length, allocate table.
+ */
+
+ RLEN(len);
+ TRACEME(("size = %d", len));
+ hv = newHV();
+ SEEN(hv); /* Will return if table not allocated properly */
+ if (len == 0)
+ return (SV *) hv; /* No data follow if table empty */
+
+ /*
+ * Now get each key/value pair in turn...
+ */
+
+ for (i = 0; i < len; i++) {
+ /*
+ * Get value first.
+ */
+
+ GETMARK(c);
+ if (c == SX_VL_UNDEF) {
+ TRACEME(("(#%d) undef value", i));
+ /*
+ * Due to a bug in hv_store(), it's not possible to pass &sv_undef
+ * to hv_store() as a value, otherwise the associated key will
+ * not be creatable any more. -- RAM, 14/01/97
+ */
+ if (!sv_h_undef)
+ sv_h_undef = newSVsv(&sv_undef);
+ sv = SvREFCNT_inc(sv_h_undef);
+ } else if (c == SX_VALUE) {
+ TRACEME(("(#%d) value", i));
+ sv = retrieve(f);
+ if (!sv)
+ return (SV *) 0;
+ } else
+ (void) retrieve_other(); /* Will croak out */
+
+ /*
+ * Get key.
+ * Since we're reading into kbuf, we must ensure we're not
+ * recursing between the read and the hv_store() where it's used.
+ * Hence the key comes after the value.
+ */
+
+ GETMARK(c);
+ if (c != SX_KEY)
+ (void) retrieve_other(); /* Will croak out */
+ RLEN(size); /* Get key size */
+ KBUFCHK(size); /* Grow hash key read pool if needed */
+ if (size)
+ READ(kbuf, size);
+ kbuf[size] = '\0'; /* Mark string end, just in case */
+ TRACEME(("(#%d) key '%s'", i, kbuf));
+
+ /*
+ * Enter key/value pair into hash table.
+ */
+
+ if (hv_store(hv, kbuf, (U32) size, sv, 0) == 0)
+ return (SV *) 0;
+ }
+
+ TRACEME(("ok (retrieve_hash at 0x%lx)", (unsigned long) hv));
+
+ return (SV *) hv;
+}
+
+/*
+ * Dynamic dispatching tables for SV retrieval.
+ */
+
+static SV *(*sv_old_retrieve[])() = {
+ 0, /* SX_OBJECT -- entry unused dynamically */
+ retrieve_lscalar, /* SX_LSCALAR */
+ old_retrieve_array, /* SX_ARRAY -- for pre-0.6 binaries */
+ old_retrieve_hash, /* SX_HASH -- for pre-0.6 binaries */
+ retrieve_ref, /* SX_REF */
+ retrieve_undef, /* SX_UNDEF */
+ retrieve_integer, /* SX_INTEGER */
+ retrieve_double, /* SX_DOUBLE */
+ retrieve_byte, /* SX_BYTE */
+ retrieve_netint, /* SX_NETINT */
+ retrieve_scalar, /* SX_SCALAR */
+ retrieve_tied_array, /* SX_ARRAY */
+ retrieve_tied_hash, /* SX_HASH */
+ retrieve_tied_scalar, /* SX_SCALAR */
+ retrieve_other, /* SX_SV_UNDEF not supported */
+ retrieve_other, /* SX_SV_YES not supported */
+ retrieve_other, /* SX_SV_NO not supported */
+ retrieve_other, /* SX_ERROR */
+};
+
+static SV *(*sv_retrieve[])() = {
+ 0, /* SX_OBJECT -- entry unused dynamically */
+ retrieve_lscalar, /* SX_LSCALAR */
+ retrieve_array, /* SX_ARRAY */
+ retrieve_hash, /* SX_HASH */
+ retrieve_ref, /* SX_REF */
+ retrieve_undef, /* SX_UNDEF */
+ retrieve_integer, /* SX_INTEGER */
+ retrieve_double, /* SX_DOUBLE */
+ retrieve_byte, /* SX_BYTE */
+ retrieve_netint, /* SX_NETINT */
+ retrieve_scalar, /* SX_SCALAR */
+ retrieve_tied_array, /* SX_ARRAY */
+ retrieve_tied_hash, /* SX_HASH */
+ retrieve_tied_scalar, /* SX_SCALAR */
+ retrieve_sv_undef, /* SX_SV_UNDEF */
+ retrieve_sv_yes, /* SX_SV_YES */
+ retrieve_sv_no, /* SX_SV_NO */
+ retrieve_other, /* SX_ERROR */
+};
+
+static SV *(**sv_retrieve_vtbl)(); /* One of the above -- XXX for threads*/
+
+#define RETRIEVE(x) (*sv_retrieve_vtbl[(x) >= SX_ERROR ? SX_ERROR : (x)])
+
+/*
+ * magic_check
+ *
+ * Make sure the stored data we're trying to retrieve has been produced
+ * on an ILP compatible system with the same byteorder. It croaks out in
+ * case an error is detected. [ILP = integer-long-pointer sizes]
+ * Returns null if error is detected, &sv_undef otherwise.
+ *
+ * Note that there's no byte ordering info emitted when network order was
+ * used at store time.
+ */
+static SV *magic_check(f)
+PerlIO *f;
+{
+ char buf[256];
+ char byteorder[256];
+ int c;
+ int use_network_order;
+ int version;
+
+ /*
+ * The "magic number" is only for files, not when freezing in memory.
+ */
+
+ if (f) {
+ STRLEN len = sizeof(magicstr) - 1;
+ STRLEN old_len;
+
+ READ(buf, len); /* Not null-terminated */
+ buf[len] = '\0'; /* Is now */
+
+ if (0 == strcmp(buf, magicstr))
+ goto magic_ok;
+
+ /*
+ * Try to read more bytes to check for the old magic number, which
+ * was longer.
+ */
+
+ old_len = sizeof(old_magicstr) - 1;
+ READ(&buf[len], old_len - len);
+ buf[old_len] = '\0'; /* Is now null-terminated */
+
+ if (strcmp(buf, old_magicstr))
+ croak("File is not a perl storable");
+ }
+
+magic_ok:
+ /*
+ * Starting with 0.6, the "use_network_order" byte flag is also used to
+ * indicate the version number of the binary, and therefore governs the
+ * setting of sv_retrieve_vtbl. See magic_write().
+ */
+
+ GETMARK(use_network_order);
+ version = use_network_order >> 1;
+ sv_retrieve_vtbl = version ? sv_retrieve : sv_old_retrieve;
+ TRACEME(("binary image version is %d", version));
+
+ if (netorder = (use_network_order & 0x1))
+ return &sv_undef; /* No byte ordering info */
+
+ sprintf(byteorder, "%lx", (unsigned long) BYTEORDER);
+ GETMARK(c);
+ READ(buf, c); /* Not null-terminated */
+ buf[c] = '\0'; /* Is now */
+
+ if (strcmp(buf, byteorder))
+ croak("Byte order is not compatible");
+
+ GETMARK(c); /* sizeof(int) */
+ if ((int) c != sizeof(int))
+ croak("Integer size is not compatible");
+
+ GETMARK(c); /* sizeof(long) */
+ if ((int) c != sizeof(long))
+ croak("Long integer size is not compatible");
+
+ GETMARK(c); /* sizeof(char *) */
+ if ((int) c != sizeof(char *))
+ croak("Pointer integer size is not compatible");
+
+ return &sv_undef; /* OK */
+}
+
+/*
+ * retrieve
+ *
+ * Recursively retrieve objects from the specified file and return their
+ * root SV (which may be an AV or an HV for what we care).
+ * Returns null if there is a problem.
+ */
+static SV *retrieve(f)
+PerlIO *f;
+{
+ int type;
+ SV **svh;
+ SV *sv;
+
+ TRACEME(("retrieve"));
+
+ /*
+ * Grab address tag which identifies the object if we are retrieving
+ * an older format. Since the new binary format counts objects and no
+ * longer explicitely tags them, we must keep track of the correspondance
+ * ourselves.
+ *
+ * The following section will disappear one day when the old format is
+ * no longer supported, hence the final "goto" in the "if" block.
+ */
+
+ if (hseen) { /* Retrieving old binary */
+ stag_t tag;
+ if (netorder) {
+ I32 nettag;
+ READ(&nettag, sizeof(I32)); /* Ordered sequence of I32 */
+ tag = (stag_t) nettag;
+ } else
+ READ(&tag, sizeof(stag_t)); /* Original address of the SV */
+
+ GETMARK(type);
+ if (type == SX_OBJECT) {
+ I32 tagn;
+ svh = hv_fetch(hseen, (char *) &tag, sizeof(tag), FALSE);
+ if (!svh)
+ croak("Old tag 0x%x should have been mapped already", tag);
+ tagn = SvIV(*svh); /* Mapped tag number computed earlier below */
+
+ /*
+ * The following code is common with the SX_OBJECT case below.
+ */
+
+ svh = av_fetch(aseen, tagn, FALSE);
+ if (!svh)
+ croak("Object #%d should have been retrieved already", tagn);
+ sv = *svh;
+ TRACEME(("already retrieved at 0x%lx", (unsigned long) sv));
+ SvREFCNT_inc(sv); /* One more reference to this same sv */
+ return sv; /* The SV pointer where object was retrieved */
+ }
+
+ /*
+ * Map new object, but don't increase tagnum. This will be done
+ * by each of the retrieve_* functions when they call SEEN().
+ *
+ * The mapping associates the "tag" initially present with a unique
+ * tag number. See test for SX_OBJECT above to see how this is perused.
+ */
+
+ if (!hv_store(hseen, (char *) &tag, sizeof(tag), newSViv(tagnum), 0))
+ return (SV *) 0;
+
+ goto first_time;
+ }
+
+ /*
+ * Regular post-0.6 binary format.
+ */
+
+ GETMARK(type);
+
+ TRACEME(("retrieve type = %d", type));
+
+ /*
+ * If the object type is SX_OBJECT, then we're dealing with an object we
+ * should have already retrieved. Otherwise, we've got a new one....
+ */
+
+ if (type == SX_OBJECT) {
+ I32 tag;
+ READ(&tag, sizeof(I32));
+ tag = ntohl(tag);
+ svh = av_fetch(aseen, tag, FALSE);
+ if (!svh)
+ croak("Object #%d should have been retrieved already", tag);
+ sv = *svh;
+ TRACEME(("already retrieved at 0x%lx", (unsigned long) sv));
+ SvREFCNT_inc(sv); /* One more reference to this same sv */
+ return sv; /* The SV pointer where object was retrieved */
+ }
+
+first_time: /* Will disappear when support for old format is dropped */
+
+ /*
+ * Okay, first time through for this one.
+ */
+
+ sv = RETRIEVE(type)(f);
+ if (!sv)
+ return (SV *) 0; /* Failed */
+
+ /*
+ * Final notifications, ended by SX_STORED may now follow.
+ * Currently, the only pertinent notification to apply on the
+ * freshly retrieved object is either:
+ * SX_BLESS <char-len> <classname> for short classnames.
+ * SX_LG_BLESS <int-len> <classname> for larger one (rare!).
+ * Class name is then read into the key buffer pool used by
+ * hash table key retrieval.
+ */
+
+ while ((type = GETCHAR()) != SX_STORED) {
+ I32 len;
+ HV *stash;
+ SV *ref;
+ switch (type) {
+ case SX_BLESS:
+ GETMARK(len); /* Length coded on a single char */
+ break;
+ case SX_LG_BLESS: /* Length coded on a regular integer */
+ RLEN(len);
+ break;
+ case EOF:
+ default:
+ return (SV *) 0; /* Failed */
+ }
+ KBUFCHK(len); /* Grow buffer as necessary */
+ if (len)
+ READ(kbuf, len);
+ kbuf[len] = '\0'; /* Mark string end */
+ TRACEME(("blessing 0x%lx in %s", (unsigned long) sv, kbuf));
+ stash = gv_stashpv(kbuf, TRUE);
+ ref = newRV_noinc(sv); /* To please sv_bless() */
+ (void) sv_bless(ref, stash);
+ SvRV(ref) = 0;
+ SvREFCNT_dec(ref); /* Reclaim temporary reference */
+ }
+
+ TRACEME(("ok (retrieved 0x%lx, refcnt=%d, %s)", (unsigned long) sv,
+ SvREFCNT(sv) - 1, sv_reftype(sv, FALSE)));
+
+ return sv; /* Ok */
+}
+
+/*
+ * do_retrieve
+ *
+ * Retrieve data held in file and return the root object.
+ * Common routine for pretrieve and mretrieve.
+ */
+static SV *do_retrieve(f)
+PerlIO *f;
+{
+ SV *sv;
+
+ TRACEME(("do_retrieve"));
+ KBUFINIT(); /* Allocate hash key reading pool once */
+
+ /*
+ * Magic number verifications.
+ */
+
+ if (!magic_check(f))
+ croak("Magic number checking on perl storable failed");
+
+ /*
+ * If retrieving an old binary version, the sv_retrieve_vtbl variable is
+ * set to sv_old_retrieve. We'll need a hash table to keep track of
+ * the correspondance between the tags and the tag number used by the
+ * new retrieve routines.
+ */
+
+ hseen = (sv_retrieve_vtbl == sv_old_retrieve) ? newHV() : 0;
+
+ aseen = newAV(); /* Table where retrieved objects are kept */
+ tagnum = 0; /* Have to count objects too */
+ sv = retrieve(f); /* Recursively retrieve object, get root SV */
+ av_undef(aseen); /* Free retrieved object table */
+ sv_free((SV *) aseen); /* Free AV */
+
+ if (hseen)
+ sv_free((SV *) hseen); /* Free HV if created above */
+
+ if (!sv) {
+ TRACEME(("retrieve ERROR"));
+ return &sv_undef; /* Something went wrong, return undef */
+ }
+
+ TRACEME(("retrieve got %s(0x%lx)",
+ sv_reftype(sv, FALSE), (unsigned long) sv));
+
+ /*
+ * Build a reference to the SV returned by pretrieve even if it is
+ * already one and not a scalar, for consistency reasons.
+ *
+ * Backward compatibility with Storable-0.5 at 9 (which we know we
+ * are retrieving if hseen is non-null): don't create an extra RV
+ * for objects since we special-cased it at store time.
+ */
+
+ if (hseen) {
+ SV *rv;
+ if (sv_type(sv) == svis_REF && (rv = SvRV(sv)) && SvOBJECT(rv))
+ return sv;
+ }
+
+ return newRV_noinc(sv);
+}
+
+/*
+ * pretrieve
+ *
+ * Retrieve data held in file and return the root object, undef on error.
+ */
+SV *pretrieve(f)
+PerlIO *f;
+{
+ TRACEME(("pretrieve"));
+ return do_retrieve(f);
+}
+
+/*
+ * mretrieve
+ *
+ * Retrieve data held in scalar and return the root object, undef on error.
+ */
+SV *mretrieve(sv)
+SV *sv;
+{
+ struct extendable mcommon; /* Temporary save area for global */
+ SV *rsv; /* Retrieved SV pointer */
+
+ TRACEME(("mretrieve"));
+ StructCopy(&membuf, &mcommon, struct extendable);
+
+ MBUF_LOAD(sv);
+ rsv = do_retrieve(0);
+
+ StructCopy(&mcommon, &membuf, struct extendable);
+ return rsv;
+}
+
+/*
+ * dclone
+ *
+ * Deep clone: returns a fresh copy of the original referenced SV tree.
+ *
+ * This is achieved by storing the object in memory and restoring from
+ * there. Not that efficient, but it should be faster than doing it from
+ * pure perl anyway.
+ */
+SV *dclone(sv)
+SV *sv;
+{
+ int size;
+
+ TRACEME(("dclone"));
+
+ MBUF_INIT(0);
+ if (!do_store(0, sv, FALSE)) /* Not in network order! */
+ return &sv_undef; /* Error during store */
+
+ size = MBUF_SIZE();
+ TRACEME(("dclone stored %d bytes", size));
+
+ MBUF_INIT(size);
+ return do_retrieve(0);
+}
+
+/*
+ * The Perl IO GV object distinguishes between input and output for sockets
+ * but not for plain files. To allow Storable to transparently work on
+ * plain files and sockets transparently, we have to ask xsubpp to fetch the
+ * right object for us. Hence the OutputStream and InputStream declarations.
+ *
+ * Before perl 5.004_05, those entries in the standard typemap are not
+ * defined in perl include files, so we do that here.
+ */
+
+#ifndef OutputStream
+#define OutputStream PerlIO *
+#define InputStream PerlIO *
+#endif /* !OutputStream */
+
+MODULE = Storable PACKAGE = Storable
+
+PROTOTYPES: ENABLE
+
+int
+pstore(f,obj)
+OutputStream f
+SV * obj
+
+int
+net_pstore(f,obj)
+OutputStream f
+SV * obj
+
+SV *
+mstore(obj)
+SV * obj
+
+SV *
+net_mstore(obj)
+SV * obj
+
+SV *
+pretrieve(f)
+InputStream f
+
+SV *
+mretrieve(sv)
+SV * sv
+
+SV *
+dclone(sv)
+SV * sv
+
Added: trunk/orca/packages/Storable-0.6 at 3/Storable.pm
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/Storable.pm (original)
+++ trunk/orca/packages/Storable-0.6 at 3/Storable.pm Sat Jul 13 18:45:55 2002
@@ -0,0 +1,429 @@
+;# $Id: Storable.pm,v 0.6.1.3 1998/07/03 11:32:52 ram Exp $
+;#
+;# Copyright (c) 1995-1998, Raphael Manfredi
+;#
+;# You may redistribute only under the terms of the Artistic License,
+;# as specified in the README file that comes with the distribution.
+;#
+;# $Log: Storable.pm,v $
+;# Revision 0.6.1.3 1998/07/03 11:32:52 ram
+;# patch3: recent optimizations increased store() throughput
+;# patch3: increased revision number
+;#
+;# Revision 0.6.1.2 1998/06/22 08:58:53 ram
+;# patch2: added Jeff Gresham to the list of contributors
+;# patch2: increased revision number
+;#
+;# Revision 0.6.1.1 1998/06/12 09:45:09 ram
+;# patch1: increased version number
+;#
+;# Revision 0.6 1998/06/04 16:08:20 ram
+;# Baseline for first beta release.
+;#
+
+require DynaLoader;
+require Exporter;
+package Storable; @ISA = qw(Exporter DynaLoader);
+
+ at EXPORT = qw(store retrieve);
+ at EXPORT_OK = qw(
+ nstore store_fd nstore_fd retrieve_fd
+ freeze nfreeze thaw
+ dclone
+);
+
+use AutoLoader;
+use Carp;
+use vars qw($forgive_me $VERSION);
+
+$VERSION = '0.603';
+*AUTOLOAD = \&AutoLoader::AUTOLOAD; # Grrr...
+
+bootstrap Storable;
+1;
+__END__
+
+#
+# store
+#
+# Store target object hierarchy, identified by a reference to its root.
+# The stored object tree may later be retrieved to memory via retrieve.
+# Returns undef if an I/O error occurred, in which case the file is
+# removed.
+#
+sub store {
+ return _store(0, @_);
+}
+
+#
+# nstore
+#
+# Same as store, but in network order.
+#
+sub nstore {
+ return _store(1, @_);
+}
+
+# Internal store to file routine
+sub _store {
+ my $netorder = shift;
+ my $self = shift;
+ my ($file) = @_;
+ croak "Not a reference" unless ref($self);
+ croak "Too many arguments" unless @_ == 1; # Watch out for @foo in arglist
+ local *FILE;
+ open(FILE, ">$file") || croak "Can't create $file: $!";
+ binmode FILE; # Archaic systems...
+ my $ret;
+ # Call C routine nstore or pstore, depending on network order
+ eval { $ret = $netorder ? net_pstore(*FILE, $self) : pstore(*FILE, $self) };
+ close(FILE) or $ret = undef;
+ unlink($file) or warn "Can't unlink $file: $!\n" if $@ || !defined $ret;
+ croak $@ if $@ =~ s/\.?\n$/,/;
+ return $ret ? $ret : undef;
+}
+
+#
+# store_fd
+#
+# Same as store, but perform on an already opened file descriptor instead.
+# Returns undef if an I/O error occurred.
+#
+sub store_fd {
+ return _store_fd(0, @_);
+}
+
+#
+# nstore_fd
+#
+# Same as store_fd, but in network order.
+#
+sub nstore_fd {
+ my ($self, $file) = @_;
+ return _store_fd(1, @_);
+}
+
+# Internal store routine on opened file descriptor
+sub _store_fd {
+ my $netorder = shift;
+ my $self = shift;
+ my ($file) = @_;
+ croak "Not a reference" unless ref($self);
+ croak "Too many arguments" unless @_ == 1; # Watch out for @foo in arglist
+ my $fd = fileno($file);
+ croak "Not a valid file descriptor" unless defined $fd;
+ my $ret;
+ # Call C routine nstore or pstore, depending on network order
+ eval { $ret = $netorder ? net_pstore($file, $self) : pstore($file, $self) };
+ croak $@ if $@ =~ s/\.?\n$/,/;
+ return $ret ? $ret : undef;
+}
+
+#
+# freeze
+#
+# Store oject and its hierarchy in memory and return a scalar
+# containing the result.
+#
+sub freeze {
+ _freeze(0, @_);
+}
+
+#
+# nfreeze
+#
+# Same as freeze but in network order.
+#
+sub nfreeze {
+ _freeze(1, @_);
+}
+
+# Internal freeze routine
+sub _freeze {
+ my $netorder = shift;
+ my $self = shift;
+ croak "Not a reference" unless ref($self);
+ croak "Too many arguments" unless @_ == 0; # Watch out for @foo in arglist
+ my $ret;
+ # Call C routine mstore or net_mstore, depending on network order
+ eval { $ret = $netorder ? net_mstore($self) : mstore($self) };
+ croak $@ if $@ =~ s/\.?\n$/,/;
+ return $ret ? $ret : undef;
+}
+#
+# retrieve
+#
+# Retrieve object hierarchy from disk, returning a reference to the root
+# object of that tree.
+#
+sub retrieve {
+ my ($file) = @_;
+ local *FILE;
+ open(FILE, "$file") || croak "Can't open $file: $!";
+ binmode FILE; # Archaic systems...
+ my $self;
+ eval { $self = pretrieve(*FILE) }; # Call C routine
+ close(FILE);
+ croak $@ if $@ =~ s/\.?\n$/,/;
+ return $self;
+}
+
+#
+# retrieve_fd
+#
+# Same as retrieve, but perform from an already opened file descriptor instead.
+#
+sub retrieve_fd {
+ my ($file) = @_;
+ my $fd = fileno($file);
+ croak "Not a valid file descriptor" unless defined $fd;
+ my $self;
+ eval { $self = pretrieve($file) }; # Call C routine
+ croak $@ if $@ =~ s/\.?\n$/,/;
+ return $self;
+}
+
+#
+# thaw
+#
+# Recreate objects in memory from an existing frozen image created
+# by freeze. If the frozen image passed is undef, return undef.
+#
+sub thaw {
+ my ($frozen) = @_;
+ return undef unless defined $frozen;
+ my $self;
+ eval { $self = mretrieve($frozen) }; # Call C routine
+ croak $@ if $@ =~ s/\.?\n$/,/;
+ return $self;
+}
+
+=head1 NAME
+
+Storable - persistency for perl data structures
+
+=head1 SYNOPSIS
+
+ use Storable;
+ store \%table, 'file';
+ $hashref = retrieve('file');
+
+ use Storable qw(nstore store_fd nstore_fd freeze thaw dclone);
+
+ # Network order
+ nstore \%table, 'file';
+ $hashref = retrieve('file'); # There is NO nretrieve()
+
+ # Storing to and retrieving from an already opened file
+ store_fd \@array, \*STDOUT;
+ nstore_fd \%table, \*STDOUT;
+ $aryref = retrieve_fd(\*SOCKET);
+ $hashref = retrieve_fd(\*SOCKET);
+
+ # Serializing to memory
+ $serialized = freeze \%table;
+ %table_clone = %{ thaw($serialized) };
+
+ # Deep (recursive) cloning
+ $cloneref = dclone($ref);
+
+=head1 DESCRIPTION
+
+The Storable package brings persistency to your perl data structures
+containing SCALAR, ARRAY, HASH or REF objects, i.e. anything that can be
+convenientely stored to disk and retrieved at a later time.
+
+It can be used in the regular procedural way by calling C<store> with
+a reference to the object to be stored, along with the file name where
+the image should be written.
+The routine returns C<undef> for I/O problems or other internal error,
+a true value otherwise. Serious errors are propagated as a C<die> exception.
+
+To retrieve data stored to disk, use C<retrieve> with a file name,
+and the objects stored into that file are recreated into memory for you,
+a I<reference> to the root object being returned. In case an I/O error
+occurs while reading, C<undef> is returned instead. Other serious
+errors are propagated via C<die>.
+
+Since storage is performed recursively, you might want to stuff references
+to objects that share a lot of common data into a single array or hash
+table, and then store that object. That way, when you retrieve back the
+whole thing, the objects will continue to share what they originally shared.
+
+At the cost of a slight header overhead, you may store to an already
+opened file descriptor using the C<store_fd> routine, and retrieve
+from a file via C<retrieve_fd>. Those names aren't imported by default,
+so you will have to do that explicitely if you need those routines.
+The file descriptor you supply must be already opened, for read
+if you're going to retrieve and for write if you wish to store.
+
+ store_fd(\%table, *STDOUT) || die "can't store to stdout\n";
+ $hashref = retrieve_fd(*STDIN);
+
+You can also store data in network order to allow easy sharing across
+multiple platforms, or when storing on a socket known to be remotely
+connected. The routines to call have an initial C<n> prefix for I<network>,
+as in C<nstore> and C<nstore_fd>. At retrieval time, your data will be
+correctly restored so you don't have to know whether you're restoring
+from native or network ordered data.
+
+When using C<retrieve_fd>, objects are retrieved in sequence, one
+object (i.e. one recursive tree) per associated C<store_fd>.
+
+If you're more from the object-oriented camp, you can inherit from
+Storable and directly store your objects by invoking C<store> as
+a method. The fact that the root of the to-be-stored tree is a
+blessed reference (i.e. an object) is special-cased so that the
+retrieve does not provide a reference to that object but rather the
+blessed object reference itself. (Otherwise, you'd get a reference
+to that blessed object).
+
+=head1 MEMORY STORE
+
+The Storable engine can also store data into a Perl scalar instead, to
+later retrieve them. This is mainly used to freeze a complex structure in
+some safe compact memory place (where it can possibly be sent to another
+process via some IPC, since freezing the structure also serializes it in
+effect). Later on, and maybe somewhere else, you can thaw the Perl scalar
+out and recreate the original complex structure in memory.
+
+Surprisingly, the routines to be called are named C<freeze> and C<thaw>.
+If you wish to send out the frozen scalar to another machine, use
+C<nfreeze> instead to get a portable image.
+
+Note that freezing an object structure and immediately thawing it
+actually achieves a deep cloning of that structure. Storable provides
+you with a C<dclone> interface which does not create that intermediary
+scalar but instead freezes the structure in some internal memory space
+and then immediatly thaws it out.
+
+=head1 SPEED
+
+The heart of Storable is written in C for decent speed. Extra low-level
+optimization have been made when manipulating perl internals, to
+sacrifice encapsulation for the benefit of a greater speed.
+
+Storage is now slightly slower than retrieval since the former has to
+also store data in a hash table to keep track of which objects
+have been stored already, whilst the latter uses an array instead of
+a hash table.
+
+On my HP 9000/712 machine running HPUX 9.03 and with perl 5.004, I can
+store 0.85 Mbyte/s and I can retrieve at 0.90 Mbytes/s, approximatively
+(CPU + system time).
+This was measured with Benchmark and the I<Magic: The Gathering>
+database from Tom Christiansen (1.6 Mbytes on disk).
+
+=head1 CANONICAL REPRESENTATION
+
+Normally Storable stores elements of hashes in the order they are
+stored internally by Perl, i.e. pseudo-randomly. If you set
+C<$Storable::canonical> to some C<TRUE> value, Storable will store
+hashes with the elements sorted by their key. This allows you to
+compare data structures by comparing their frozen representations (or
+even the compressed frozen representations), which can be useful for
+creating lookup tables for complicated queries.
+
+Canonical order does not imply network order, those are two orthogonal
+settings.
+
+=head1 EXAMPLES
+
+Here are some code samples showing a possible usage of Storable:
+
+ use Storable qw(store retrieve freeze thaw dclone);
+
+ %color = ('Blue' => 0.1, 'Red' => 0.8, 'Black' => 0, 'White' => 1);
+
+ store(\%color, '/tmp/colors') or die "Can't store %a in /tmp/colors!\n";
+
+ $colref = retrieve('/tmp/colors');
+ die "Unable to retrieve from /tmp/colors!\n" unless defined $colref;
+ printf "Blue is still %lf\n", $colref->{'Blue'};
+
+ $colref2 = dclone(\%color);
+
+ $str = freeze(\%color);
+ printf "Serialization of %%color is %d bytes long.\n", length($str);
+ $colref3 = thaw($str);
+
+which prints (on my machine):
+
+ Blue is still 0.100000
+ Serialization of %color is 102 bytes long.
+
+=head1 WARNING
+
+If you're using references as keys within your hash tables, you're bound
+to disapointment when retrieving your data. Indeed, Perl stringifies
+references used as hash table keys. If you later wish to access the
+items via another reference stringification (i.e. using the same
+reference that was used for the key originally to record the value into
+the hash table), it will work because both references stringify to the
+same string.
+
+It won't work across a C<store> and C<retrieve> operations however, because
+the addresses in the retrieved objects, which are part of the stringified
+references, will probably differ from the original addresses. The
+topology of your structure is preserved, but not hidden semantics
+like those.
+
+On platforms where it matters, be sure to call C<binmode()> on the
+descriptors that you pass to Storable functions.
+
+Storing data canonically that contains large hashes can be
+significantly slower than storing the same data normally, as
+temprorary arrays to hold the keys for each hash have to be allocated,
+populated, sorted and freed. Some tests have shown a halving of the
+speed of storing -- the exact penalty will depend on the complexity of
+your data. There is no slowdown on retrieval.
+
+=head1 BUGS
+
+You can't store GLOB, CODE, FORMLINE, etc... If you can define
+semantics for those operations, feel free to enhance Storable so that
+it can deal with them.
+
+The store functions will C<croak> if they run into such references
+unless you set C<$Storable::forgive_me> to some C<TRUE> value. In that
+case, the fatal message is turned in a warning and some
+meaningless string is stored instead.
+
+Setting C<$Storable::canonical> may not yield frozen strings that
+compare equal due to possible stringification of numbers. When the
+string version of a scalar exists, it is the form stored, therefore
+if you happen to use your numbers as strings between two freezing
+operations on the same data structures, you will get different
+results.
+
+Due to the aforementionned optimizations, Storable is at the mercy
+of perl's internal redesign or structure changes. If that bothers
+you, you can try convincing Larry that what is used in Storable
+should be documented and consistently kept in future revisions.
+
+=head1 CREDITS
+
+Thank you to (in chronological order):
+
+ Jarkko Hietaniemi <jhi at iki.fi>
+ Ulrich Pfeifer <pfeifer at charly.informatik.uni-dortmund.de>
+ Benjamin A. Holzman <benjamin.a.holzman at bender.com>
+ Andrew Ford <A.Ford at ford-mason.co.uk>
+ Gisle Aas <gisle at aas.no>
+ Jeff Gresham <gresham_jeffrey at jpmorgan.com>
+
+for their bug reports, suggestions and contributions.
+
+Benjamin Holzman contributed the tied variable support, Andrew Ford
+contributed the canonical order for hashes, and Gisle Aas fixed
+a few misunderstandings of mine regarding the Perl internals,
+and optimized the emission of "tags" in the output streams by
+simply counting the objects instead of tagging them (leading to
+a binary incompatibility for the Storable image starting at version
+0.6--older images are of course still properly understood).
+
+=head1 AUTHOR
+
+Raphael Manfredi F<E<lt>Raphael_Manfredi at grenoble.hp.comE<gt>>
+
+=cut
Added: trunk/orca/packages/Storable-0.6 at 3/MANIFEST
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/MANIFEST (original)
+++ trunk/orca/packages/Storable-0.6 at 3/MANIFEST Sat Jul 13 18:45:55 2002
@@ -0,0 +1,15 @@
+README Read this first
+MANIFEST This shipping list
+Makefile.PL Generic Makefile template
+Storable.pm The perl side of Storable
+Storable.xs The C side of Storable
+patchlevel.h Records current patchlevel
+t/canonical.t Test canonical hash table dumping
+t/dclone.t Test deep cloning
+t/dump.pl Small utility to dump data structures
+t/freeze.t Test memory store (freeze/thaw) operations
+t/retrieve.t Test retrieve operation
+t/store.t Test store operation
+t/forgive.t Test if $Storable::forgive_me works
+t/tied.t Test serialization of tied SVs.
+ChangeLog Changes since baseline
Added: trunk/orca/packages/Storable-0.6 at 3/Makefile.PL
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/Makefile.PL (original)
+++ trunk/orca/packages/Storable-0.6 at 3/Makefile.PL Sat Jul 13 18:45:56 2002
@@ -0,0 +1,23 @@
+# $Id: Makefile.PL,v 0.6 1998/06/04 16:08:18 ram Exp $
+#
+# Copyright (c) 1995-1998, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic License,
+# as specified in the README file that comes with the distribution.
+#
+# $Log: Makefile.PL,v $
+# Revision 0.6 1998/06/04 16:08:18 ram
+# Baseline for first beta release.
+#
+
+use ExtUtils::MakeMaker;
+use Config;
+
+WriteMakefile(
+ 'NAME' => 'Storable',
+ 'DISTNAME' => "Storable",
+ 'VERSION_FROM' => 'Storable.pm',
+ 'dist' => { SUFFIX => 'gz', COMPRESS => 'gzip -f' },
+ 'clean' => {'FILES' => '*%'},
+);
+
Added: trunk/orca/packages/Storable-0.6 at 3/ChangeLog
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/ChangeLog (original)
+++ trunk/orca/packages/Storable-0.6 at 3/ChangeLog Sat Jul 13 18:45:56 2002
@@ -0,0 +1,230 @@
+Fri Jul 3 13:38:16 METDST 1998 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Updated benchmark figures due to recent optimizations done in
+ store(): tagnums are now stored as-is in the hash table, so
+ no surrounding SV is created. And the "shared keys" mode for
+ hash table was turned off.
+
+ Fixed backward compatibility (wrt 0.5 at 9) for retrieval of
+ blessed refs. That old version did something wrong, but the
+ bugfix prevented correct retrieval of the old format.
+
+Mon Jun 22 11:00:48 METDST 1998 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Changed benchmark figures.
+
+ Adjust refcnt of tied objects after calling sv_magic() to avoid
+ memory leaks. Contributed by Jeff Gresham.
+
+Fri Jun 12 11:50:04 METDST 1998 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Added workaround for persistent LVALUE-ness in perl5.004. All
+ scalars tagged as being an lvalue are handled as if they were
+ not an lvalue at all. Added test for that LVALUE bug workaround.
+
+ Now handles Perl immortal scalars explicitely, by storing &sv_yes
+ as such, explicitely.
+
+ Retrieval of non-immortal undef cannot be shared. Previous
+ version was over-optimizing by not creating a separate SV for
+ all undefined scalars seen.
+
+Thu Jun 4 17:21:51 METDST 1998 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Baseline for Storable-0.6 at 0.
+
+ This version introduces a binary incompatibility in the generated
+ binary image, which is more compact than older ones by approximatively
+ 15%, depending on the exact degree of sharing in your structures.
+
+ The good news is that your older images can still be retrieved with
+ this version, i.e. backward compatibility is preserved. This version
+ of Storable can only generate new binaries however.
+
+ Another good news is that the retrieval of data structure is
+ significantly quicker than before, because a Perl array is used
+ instead of a hash table to keep track of retrieved objects, and
+ also because the image being smaller, less I/O function calls are
+ made.
+
+Tue May 12 09:15:15 METDST 1998 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Version number now got from Storable.pm directly.
+
+ Fixed overzealous sv_type() optimization, which would make
+ Storable fail when faced with an "upgraded" SV to the PVIV
+ or PVNV kind containing a reference.
+
+Thu Apr 30 15:11:30 METDST 1998 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Extended the SYNOPSIS section to give quick overview of the
+ routines and their signature.
+
+ Optimized sv_type() to avoid flags checking when not needed, i.e.
+ when their type makes it impossible for them to be refs or tied.
+ This slightly increases throughput by a few percents when refs
+ and tied variables are marginal occurrences in your data.
+
+ Stubs for XS now use OutputStream and InputStream file types to
+ make it work when the given file is actually a socket. Perl
+ makes a distinction for sockets in its internal I/O structures
+ by having both a read and a write structure, whereas plain files
+ share the same one.
+
+Tue Jun 3 09:41:33 METDST 1997 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Thanks to a contribution from Benjamin A. Holzman, Storable is now
+ able to correctly serialize tied SVs, i.e. tied arrays, hashes
+ and scalars.
+
+Thu Apr 9 18:07:51 METDST 1998 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ I said SvPOK() had changed to SvPOKp(), but that was a lie...
+
+Wed Apr 8 13:14:29 METDST 1998 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Wrote sizeof(SV *) instead of sizeof(I32) when portable, which
+ in effect mangled the object tags and prevented portability
+ accross 32/64 bit architectures!
+
+Wed Mar 25 14:57:02 MET 1998 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Added code example for store_fd() and retrieve_fd() in the
+ man page, to emphasize that file descriptors must be passed as
+ globs, not as plain strings.
+
+ Cannot use SV addresses as tag when using nstore() on LP64. This
+ was the cause of problems when creating a storable image on an
+ LP64 machine and retrieving it on an ILP32 system, which is
+ exactly what nstore() is meant for...
+
+ However, we continue to use SV addresses as tags for plain store(),
+ because benchamarking shows that it saves up to 8% of the store
+ time, and store() is meant to be fast at the expense of lack
+ of portability.
+
+ This means there will be approximately an 8% degradation of
+ performance for nstore(), but it's now working as expected.
+ That cost may vary on your machine of course, since it is
+ solely caused by the memory allocation overhead used to create
+ unique SV tags for each distinct stored SV.
+
+Tue Jan 20 09:21:53 MET 1998 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Don't use any '_' in version number.
+
+Tue Jan 13 17:51:50 MET 1998 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Updated version number.
+
+ added binmode() calls for systems where it matters.
+
+ Be sure to pass globs, not plain file strings, to C routines,
+ so that Storable can be used under the Perl debugger.
+
+Wed Nov 5 10:53:22 MET 1997 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Fix memory leaks on seen hash table and returned SV refs.
+
+ Storable did not work properly when tainting enabled.
+
+ Fixed "Allocation too large" messages in freeze/thaw and added.
+ proper regression test in t/freeze.t.
+
+Tue Jun 3 09:41:33 METDST 1997 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Updated version number
+
+ Added freeze/thaw interface and dclone.
+
+Fri May 16 10:45:47 METDST 1997 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Forgot that AutoLoader does not export its own AUTOLOAD.
+ I could use
+
+ use AutoLoader 'AUTOLOAD';
+
+ but that would not be backward compatible. So the export is
+ done by hand...
+
+Tue Mar 25 11:21:32 MET 1997 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Empty scalar strings are now "defined" at retrieval time.
+
+ New test to ensure an empty string is defined when retrieved.
+
+Thu Feb 27 16:32:44 MET 1997 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Updated version number
+
+ Declare VERSION as being used
+
+ Fixed a typo in the PerlIO_putc remapping.
+ PerlIO_read and perlIO_write inverted size/nb_items.
+ (only relevant for pre-perl5.004 versions)
+
+Thu Feb 27 15:58:31 MET 1997 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Updated version number
+
+ Added VERSION identification
+
+ Allow build with perl5.003, which is ante perlIO time
+
+Mon Jan 13 17:53:18 MET 1997 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Random code fixes.
+
+Wed Jan 22 15:19:56 MET 1997 Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+. Description:
+
+ Updated version number in Makefile.PL.
+
+ Added "thanks to" section to README.
+
+ Documented new forgive_me variable.
+
+ Made 64-bit clean.
+
+ Added forgive_me support to allow store() of data structures
+ containing non-storable items like CODE refs.
+
Added: trunk/orca/packages/Storable-0.6 at 3/patchlevel.h
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/patchlevel.h (original)
+++ trunk/orca/packages/Storable-0.6 at 3/patchlevel.h Sat Jul 13 18:45:56 2002
@@ -0,0 +1 @@
+#define PATCHLEVEL 3
Added: trunk/orca/packages/Storable-0.6 at 3/README
==============================================================================
--- trunk/orca/packages/Storable-0.6 at 3/README (original)
+++ trunk/orca/packages/Storable-0.6 at 3/README Sat Jul 13 18:45:56 2002
@@ -0,0 +1,150 @@
+ Storable 0.6
+ Copyright (c) 1995-1998, Raphael Manfredi
+
+------------------------------------------------------------------------
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the Artistic License, a copy of which can be
+ found with perl.
+
+ 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
+ Artistic License for more details.
+------------------------------------------------------------------------
+
+ *** This is beta software -- use at your own risks ***
+
+The Storable extension brings persistency to your data.
+
+You may recursively store to disk any data structure, no matter
+how complex and circular it is, provided it contains only SCALAR,
+ARRAY, HASH and references to those items, blessed or not.
+
+At a later stage, or in another program, you may retrieve data from
+the stored file and recreate the same hiearchy in memory. If you
+had blessed references, the retrieved references are blessed into
+the same package, so you must make sure you have access to the
+same perl class than the one used to create the relevant objects.
+
+For instance:
+
+ use Storable;
+
+ $scalar = 'scalar';
+ $hash{$scalar} = 'value';
+ $ref = \%hash;
+ @array = ('first', undef, $scalar, $ref, \$ref);
+
+ &show(\@array);
+
+ store(\@array, 'store');
+ $root = retrieve('store');
+
+ print '-' x 10, "\n";
+ &show($root) if ref($root) eq 'ARRAY';
+
+ sub show {
+ my ($aref) = @_;
+ foreach $i (@{$aref}) {
+ unless (defined $i) {
+ print "undef\n";
+ next;
+ }
+ print "$i";
+ print " ($$i)" if ref($i) eq 'SCALAR';
+ print "\n";
+ }
+ }
+
+
+when run on my machine produces:
+
+ first
+ undef
+ scalar
+ HASH(0x4001eec0)
+ SCALAR(0x4001ee60)
+ ----------
+ first
+ undef
+ scalar
+ HASH(0x40021fd4)
+ SCALAR(0x40017008)
+
+You can see that items are retrieved in memory at some other place,
+but the topology of the retrieved data is the same as the original.
+
+I had first written Storable in Perl, but the results were disappointing,
+because it took almost 20 seconds to store 200K worth of data. By having
+the heart of Storable in C, I can store the same amount of data in about
+0.6 seconds. To retrieve the same data, it takes roughly 1.0 seconds,
+because you have to allocate objects in memory whereas storing merely
+traverses structures.
+
+More accurately, using Benchmark, I get (for a 236802 byte long stored
+file):
+
+ Machine Time to store Time to retrieve
+ (cpu + sys) (cpu + sys)
+ HP 9000/712 0.61 s 1.02 s
+ HP 9000/856 0.33 s 0.39 s
+
+To store/retrieve the "Magic: The Gathering" (MTG) database (1.9 Mb) in
+native format:
+
+ Machine Time to store Time to retrieve
+ (cpu + sys) (cpu + sys)
+ HP 9000/712 1.95 s 2.19 s
+
+That's roughly 1Mb/s for store and 0.86Mb/s for retrieve.
+
+NOTE: The above figures were valid for Storable-0.5 and earlier. No
+similar benchmarking have been made with Storable-0.6 and higher,
+which use a different binary image.
+
+Comparison of Storable-0.5 at 9 and Storable-0.6 at 3 on a version of
+Tom Christiansen's MTG database (1.8 Mb in native 0.5 format, 1.6 Mb
+only in 0.6 format) gives:
+
+ Version Storable Image "store" "nstore" "retrieve"
+ Size in Mb in Kb/s in Kb/s in Kb/s
+
+ 0.5 at 9 1.817 801 701 692
+ 0.6 at 3 1.526 880 851 870
+
+Kb/s rates refer to the size of the Storable image. Since the image
+is shorter with version 0.6, we must normalize the results to compare
+relative speed correctly, and therefore measure the overall time it
+takes to store/retrieve the same database. We get:
+
+ Version Storable Image "store" "nstore" "retrieve"
+ Size in Mb in secs in secs in secs
+
+ 0.5 at 9 1.817 2.32 2.65 2.69
+ 0.6 at 3 1.526 1.78 1.84 1.80
+
+Notice the important gain at retrieval time, due to the fact that we
+now use an array instead of a hash table to keep track of retrieved
+objects. I have no explaination for the relative speed-up of nstore
+operations other than the fact that less tests for "netorder" are made.
+
+To compile this extension, run:
+
+ perl Makefile.PL [PERL_SRC=...where you put perl sources...]
+ make
+ make install
+
+There is an embeded POD manual page in Storable.pm.
+
+Raphael Manfredi <Raphael_Manfredi at grenoble.hp.com>
+
+Thanks to:
+
+ Jarkko Hietaniemi <jhi at iki.fi>
+ Ulrich Pfeifer <pfeifer at charly.informatik.uni-dortmund.de>
+ Benjamin A. Holzman <benjamin.a.holzman at bender.com>
+ Andrew Ford <A.Ford at ford-mason.co.uk>
+ Gisle Aas <gisle at aas.no>
+ Jeff Gresham <gresham_jeffrey at jpmorgan.com>
+
+for their contributions.
Added: trunk/orca/packages/Makefile.in
==============================================================================
--- trunk/orca/packages/Makefile.in (original)
+++ trunk/orca/packages/Makefile.in Sat Jul 13 18:45:56 2002
@@ -0,0 +1,136 @@
+ at SET_MAKE@
+
+PERL = @PERL@
+CFLAGS = @CFLAGS@
+digest_md5_dir = @DIGEST_MD5_DIR@
+math_interpolate_dir = @MATH_INTERPOLATE_DIR@
+rrdtool_dir = @RRDTOOL_DIR@
+storable_dir = @STORABLE_DIR@
+
+MAKE_DIGEST_MD5 = @MAKE_DIGEST_MD5@
+MAKE_MATH_INTERPOLATE = @MAKE_MATH_INTERPOLATE@
+MAKE_RRDTOOL = @MAKE_RRDTOOL@
+MAKE_STORABLE = @MAKE_STORABLE@
+MAKE_TARGETS = $(MAKE_DIGEST_MD5) $(MAKE_MATH_INTERPOLATE) $(MAKE_RRDTOOL) $(MAKE_STORABLE)
+
+TEST_DIGEST_MD5 = @TEST_DIGEST_MD5@
+TEST_MATH_INTERPOLATE = @TEST_MATH_INTERPOLATE@
+TEST_RRDTOOL = @TEST_RRDTOOL@
+TEST_STORABLE = @TEST_STORABLE@
+TEST_TARGETS = $(TEST_DIGEST_MD5) $(TEST_MATH_INTERPOLATE) $(TEST_RRDTOOL) $(TEST_STORABLE)
+
+INSTALL_DIGEST_MD5 = @INSTALL_DIGEST_MD5@
+INSTALL_MATH_INTERPOLATE= @INSTALL_MATH_INTERPOLATE@
+INSTALL_RRDTOOL = @INSTALL_RRDTOOL@
+INSTALL_STORABLE = @INSTALL_STORABLE@
+INSTALL_TARGETS = $(INSTALL_DIGEST_MD5) $(INSTALL_MATH_INTERPOLATE) $(INSTALL_RRDTOOL) $(INSTALL_STORABLE)
+
+CLEAN_DIGEST_MD5 = @CLEAN_DIGEST_MD5@
+CLEAN_MATH_INTERPOLATE = @CLEAN_MATH_INTERPOLATE@
+CLEAN_RRDTOOL = @CLEAN_RRDTOOL@
+CLEAN_STORABLE = @CLEAN_STORABLE@
+CLEAN_TARGETS = $(CLEAN_DIGEST_MD5) $(CLEAN_MATH_INTERPOLATE) $(CLEAN_RRDTOOL) $(CLEAN_STORABLE)
+
+DISTCLEAN_DIGEST_MD5 = @DISTCLEAN_DIGEST_MD5@
+DISTCLEAN_MATH_INTERPOLATE = @DISTCLEAN_MATH_INTERPOLATE@
+DISTCLEAN_RRDTOOL = @DISTCLEAN_RRDTOOL@
+DISTCLEAN_STORABLE = @DISTCLEAN_STORABLE@
+DISTCLEAN_TARGETS = $(DISTCLEAN_DIGEST_MD5) $(DISTCLEAN_MATH_INTERPOLATE) $(DISTCLEAN_RRDTOOL) $(DISTCLEAN_STORABLE)
+
+all: Makefile
+
+modules: Makefile $(MAKE_TARGETS)
+
+make_digest_md5: $(digest_md5_dir)/Makefile
+ (cd $(digest_md5_dir) && $(MAKE) OPTIMIZE="$(CFLAGS)")
+
+$(digest_md5_dir)/Makefile: $(digest_md5_dir)/Makefile.PL $(PERL)
+ (cd $(digest_md5_dir) && $(PERL) Makefile.PL)
+
+make_math_interpolate: $(math_interpolate_dir)/Makefile
+ (cd $(math_interpolate_dir) && $(MAKE) OPTIMIZE="$(CFLAGS)")
+
+$(math_interpolate_dir)/Makefile: $(math_interpolate_dir)/Makefile.PL $(PERL)
+ (cd $(math_interpolate_dir) && $(PERL) Makefile.PL)
+
+make_rrdtool: $(rrdtool_dir)/Makefile $(PERL)
+ (cd $(rrdtool_dir) && $(MAKE) CFLAGS="$(CFLAGS)")
+
+$(rrdtool_dir)/Makefile: $(rrdtool_dir)/Makefile.in
+ (cd .. && ./configure @CONFIGURE_COMMAND_LINE@)
+
+make_storable: $(storable_dir)/Makefile
+ (cd $(storable_dir) && $(MAKE) OPTIMIZE="$(CFLAGS)")
+
+$(storable_dir)/Makefile: $(storable_dir)/Makefile.PL $(PERL)
+ (cd $(storable_dir) && $(PERL) Makefile.PL)
+
+test:
+
+test_modules: $(TEST_TARGETS)
+
+test_digest_md5: $(digest_md5_dir)/Makefile
+ (cd $(digest_md5_dir) && $(MAKE) CFLAGS="$(CFLAGS)" test)
+
+test_math_interpolate: $(math_interpolate_dir)/Makefile
+ (cd $(math_interpolate_dir) && $(MAKE) test)
+
+test_rrdtool: make_rrdtool
+ (cd $(rrdtool_dir)/perl-shared && $(MAKE) CFLAGS="$(CFLAGS)" test)
+
+test_storable: make_storable
+ (cd $(storable_dir) && $(MAKE) CFLAGS="$(CFLAGS)" test)
+
+install:
+
+install_modules: $(INSTALL_TARGETS)
+
+install_digest_md5: make_digest_md5
+ (cd $(digest_md5_dir) && $(MAKE) install)
+
+install_math_interpolate: make_math_interpolate
+ (cd $(math_interpolate_dir) && $(MAKE) install)
+
+install_rrdtool: make_rrdtool
+ (cd $(rrdtool_dir)/perl-shared && $(MAKE) install)
+
+install_storable: make_storable
+ (cd $(storable_dir) && $(MAKE) install)
+
+clean: $(CLEAN_TARGETS)
+
+clean_digest_md5:
+ @if test -r $(digest_md5_dir)/Makefile; then \
+ echo '(cd $(digest_md5_dir); $(MAKE) clean'; \
+ (cd $(digest_md5_dir); $(MAKE) clean); \
+ fi
+
+clean_math_interpolate:
+ @if test -r $(math_interpolate_dir)/Makefile; then \
+ echo '(cd $(math_interpolate_dir); $(MAKE) clean)'; \
+ (cd $(math_interpolate_dir); $(MAKE) clean); \
+ fi
+
+clean_rrdtool:
+ (cd $(rrdtool_dir) && $(MAKE) clean)
+
+clean_storable:
+ @if test -r $(storable_dir)/Makefile; then \
+ echo '(cd $(storable_dir); $(MAKE) clean)'; \
+ (cd $(storable_dir); $(MAKE) clean); \
+ fi
+
+distclean: $(DISTCLEAN_TARGETS)
+
+distclean_digest_md5: clean_digest_md5
+
+distclean_math_interpolate: clean_math_interpolate
+
+distclean_rrdtool: clean_rrdtool
+ (cd $(rrdtool_dir) && $(MAKE) distclean)
+
+distclean_storable: clean_storable
+
+Makefile: Makefile.in
+ (cd ..; ./config.status)
+ $(MAKE)
Added: trunk/orca/packages/Digest-MD5-2.07/rfc1321.txt
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/rfc1321.txt (original)
+++ trunk/orca/packages/Digest-MD5-2.07/rfc1321.txt Sat Jul 13 18:45:56 2002
@@ -0,0 +1,1179 @@
+
+
+
+
+
+
+Network Working Group R. Rivest
+Request for Comments: 1321 MIT Laboratory for Computer Science
+ and RSA Data Security, Inc.
+ April 1992
+
+
+ The MD5 Message-Digest Algorithm
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard. Distribution of this memo is
+ unlimited.
+
+Acknowlegements
+
+ We would like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle,
+ David Chaum, and Noam Nisan for numerous helpful comments and
+ suggestions.
+
+Table of Contents
+
+ 1. Executive Summary 1
+ 2. Terminology and Notation 2
+ 3. MD5 Algorithm Description 3
+ 4. Summary 6
+ 5. Differences Between MD4 and MD5 6
+ References 7
+ APPENDIX A - Reference Implementation 7
+ Security Considerations 21
+ Author's Address 21
+
+1. Executive Summary
+
+ This document describes the MD5 message-digest algorithm. The
+ algorithm takes as input a message of arbitrary length and produces
+ as output a 128-bit "fingerprint" or "message digest" of the input.
+ It is conjectured that it is computationally infeasible to produce
+ two messages having the same message digest, or to produce any
+ message having a given prespecified target message digest. The MD5
+ algorithm is intended for digital signature applications, where a
+ large file must be "compressed" in a secure manner before being
+ encrypted with a private (secret) key under a public-key cryptosystem
+ such as RSA.
+
+
+
+
+
+
+
+Rivest [Page 1]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ The MD5 algorithm is designed to be quite fast on 32-bit machines. In
+ addition, the MD5 algorithm does not require any large substitution
+ tables; the algorithm can be coded quite compactly.
+
+ The MD5 algorithm is an extension of the MD4 message-digest algorithm
+ 1,2]. MD5 is slightly slower than MD4, but is more "conservative" in
+ design. MD5 was designed because it was felt that MD4 was perhaps
+ being adopted for use more quickly than justified by the existing
+ critical review; because MD4 was designed to be exceptionally fast,
+ it is "at the edge" in terms of risking successful cryptanalytic
+ attack. MD5 backs off a bit, giving up a little in speed for a much
+ greater likelihood of ultimate security. It incorporates some
+ suggestions made by various reviewers, and contains additional
+ optimizations. The MD5 algorithm is being placed in the public domain
+ for review and possible adoption as a standard.
+
+ For OSI-based applications, MD5's object identifier is
+
+ md5 OBJECT IDENTIFIER ::=
+ iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
+
+ In the X.509 type AlgorithmIdentifier [3], the parameters for MD5
+ should have type NULL.
+
+2. Terminology and Notation
+
+ In this document a "word" is a 32-bit quantity and a "byte" is an
+ eight-bit quantity. A sequence of bits can be interpreted in a
+ natural manner as a sequence of bytes, where each consecutive group
+ of eight bits is interpreted as a byte with the high-order (most
+ significant) bit of each byte listed first. Similarly, a sequence of
+ bytes can be interpreted as a sequence of 32-bit words, where each
+ consecutive group of four bytes is interpreted as a word with the
+ low-order (least significant) byte given first.
+
+ Let x_i denote "x sub i". If the subscript is an expression, we
+ surround it in braces, as in x_{i+1}. Similarly, we use ^ for
+ superscripts (exponentiation), so that x^i denotes x to the i-th
+ power.
+
+ Let the symbol "+" denote addition of words (i.e., modulo-2^32
+ addition). Let X <<< s denote the 32-bit value obtained by circularly
+ shifting (rotating) X left by s bit positions. Let not(X) denote the
+ bit-wise complement of X, and let X v Y denote the bit-wise OR of X
+ and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY
+ denote the bit-wise AND of X and Y.
+
+
+
+
+
+Rivest [Page 2]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+3. MD5 Algorithm Description
+
+ We begin by supposing that we have a b-bit message as input, and that
+ we wish to find its message digest. Here b is an arbitrary
+ nonnegative integer; b may be zero, it need not be a multiple of
+ eight, and it may be arbitrarily large. We imagine the bits of the
+ message written down as follows:
+
+ m_0 m_1 ... m_{b-1}
+
+ The following five steps are performed to compute the message digest
+ of the message.
+
+3.1 Step 1. Append Padding Bits
+
+ The message is "padded" (extended) so that its length (in bits) is
+ congruent to 448, modulo 512. That is, the message is extended so
+ that it is just 64 bits shy of being a multiple of 512 bits long.
+ Padding is always performed, even if the length of the message is
+ already congruent to 448, modulo 512.
+
+ Padding is performed as follows: a single "1" bit is appended to the
+ message, and then "0" bits are appended so that the length in bits of
+ the padded message becomes congruent to 448, modulo 512. In all, at
+ least one bit and at most 512 bits are appended.
+
+3.2 Step 2. Append Length
+
+ A 64-bit representation of b (the length of the message before the
+ padding bits were added) is appended to the result of the previous
+ step. In the unlikely event that b is greater than 2^64, then only
+ the low-order 64 bits of b are used. (These bits are appended as two
+ 32-bit words and appended low-order word first in accordance with the
+ previous conventions.)
+
+ At this point the resulting message (after padding with bits and with
+ b) has a length that is an exact multiple of 512 bits. Equivalently,
+ this message has a length that is an exact multiple of 16 (32-bit)
+ words. Let M[0 ... N-1] denote the words of the resulting message,
+ where N is a multiple of 16.
+
+3.3 Step 3. Initialize MD Buffer
+
+ A four-word buffer (A,B,C,D) is used to compute the message digest.
+ Here each of A, B, C, D is a 32-bit register. These registers are
+ initialized to the following values in hexadecimal, low-order bytes
+ first):
+
+
+
+
+Rivest [Page 3]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ word A: 01 23 45 67
+ word B: 89 ab cd ef
+ word C: fe dc ba 98
+ word D: 76 54 32 10
+
+3.4 Step 4. Process Message in 16-Word Blocks
+
+ We first define four auxiliary functions that each take as input
+ three 32-bit words and produce as output one 32-bit word.
+
+ F(X,Y,Z) = XY v not(X) Z
+ G(X,Y,Z) = XZ v Y not(Z)
+ H(X,Y,Z) = X xor Y xor Z
+ I(X,Y,Z) = Y xor (X v not(Z))
+
+ In each bit position F acts as a conditional: if X then Y else Z.
+ The function F could have been defined using + instead of v since XY
+ and not(X)Z will never have 1's in the same bit position.) It is
+ interesting to note that if the bits of X, Y, and Z are independent
+ and unbiased, the each bit of F(X,Y,Z) will be independent and
+ unbiased.
+
+ The functions G, H, and I are similar to the function F, in that they
+ act in "bitwise parallel" to produce their output from the bits of X,
+ Y, and Z, in such a manner that if the corresponding bits of X, Y,
+ and Z are independent and unbiased, then each bit of G(X,Y,Z),
+ H(X,Y,Z), and I(X,Y,Z) will be independent and unbiased. Note that
+ the function H is the bit-wise "xor" or "parity" function of its
+ inputs.
+
+ This step uses a 64-element table T[1 ... 64] constructed from the
+ sine function. Let T[i] denote the i-th element of the table, which
+ is equal to the integer part of 4294967296 times abs(sin(i)), where i
+ is in radians. The elements of the table are given in the appendix.
+
+ Do the following:
+
+ /* Process each 16-word block. */
+ For i = 0 to N/16-1 do
+
+ /* Copy block i into X. */
+ For j = 0 to 15 do
+ Set X[j] to M[i*16+j].
+ end /* of loop on j */
+
+ /* Save A as AA, B as BB, C as CC, and D as DD. */
+ AA = A
+ BB = B
+
+
+
+Rivest [Page 4]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ CC = C
+ DD = D
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+ /* Do the following 16 operations. */
+ [ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4]
+ [ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8]
+ [ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12]
+ [ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+ /* Do the following 16 operations. */
+ [ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20]
+ [ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24]
+ [ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28]
+ [ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32]
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+ /* Do the following 16 operations. */
+ [ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36]
+ [ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40]
+ [ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44]
+ [ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+ /* Do the following 16 operations. */
+ [ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52]
+ [ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56]
+ [ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60]
+ [ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ A = A + AA
+ B = B + BB
+ C = C + CC
+ D = D + DD
+
+ end /* of loop on i */
+
+
+
+Rivest [Page 5]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+3.5 Step 5. Output
+
+ The message digest produced as output is A, B, C, D. That is, we
+ begin with the low-order byte of A, and end with the high-order byte
+ of D.
+
+ This completes the description of MD5. A reference implementation in
+ C is given in the appendix.
+
+4. Summary
+
+ The MD5 message-digest algorithm is simple to implement, and provides
+ a "fingerprint" or message digest of a message of arbitrary length.
+ It is conjectured that the difficulty of coming up with two messages
+ having the same message digest is on the order of 2^64 operations,
+ and that the difficulty of coming up with any message having a given
+ message digest is on the order of 2^128 operations. The MD5 algorithm
+ has been carefully scrutinized for weaknesses. It is, however, a
+ relatively new algorithm and further security analysis is of course
+ justified, as is the case with any new proposal of this sort.
+
+5. Differences Between MD4 and MD5
+
+ The following are the differences between MD4 and MD5:
+
+ 1. A fourth round has been added.
+
+ 2. Each step now has a unique additive constant.
+
+ 3. The function g in round 2 was changed from (XY v XZ v YZ) to
+ (XZ v Y not(Z)) to make g less symmetric.
+
+ 4. Each step now adds in the result of the previous step. This
+ promotes a faster "avalanche effect".
+
+ 5. The order in which input words are accessed in rounds 2 and
+ 3 is changed, to make these patterns less like each other.
+
+ 6. The shift amounts in each round have been approximately
+ optimized, to yield a faster "avalanche effect." The shifts in
+ different rounds are distinct.
+
+
+
+
+
+
+
+
+
+
+Rivest [Page 6]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+References
+
+ [1] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1320, MIT and
+ RSA Data Security, Inc., April 1992.
+
+ [2] Rivest, R., "The MD4 message digest algorithm", in A.J. Menezes
+ and S.A. Vanstone, editors, Advances in Cryptology - CRYPTO '90
+ Proceedings, pages 303-311, Springer-Verlag, 1991.
+
+ [3] CCITT Recommendation X.509 (1988), "The Directory -
+ Authentication Framework."
+
+APPENDIX A - Reference Implementation
+
+ This appendix contains the following files taken from RSAREF: A
+ Cryptographic Toolkit for Privacy-Enhanced Mail:
+
+ global.h -- global header file
+
+ md5.h -- header file for MD5
+
+ md5c.c -- source code for MD5
+
+ For more information on RSAREF, send email to <rsaref at rsa.com>.
+
+ The appendix also includes the following file:
+
+ mddriver.c -- test driver for MD2, MD4 and MD5
+
+ The driver compiles for MD5 by default but can compile for MD2 or MD4
+ if the symbol MD is defined on the C compiler command line as 2 or 4.
+
+ The implementation is portable and should work on many different
+ plaforms. However, it is not difficult to optimize the implementation
+ on particular platforms, an exercise left to the reader. For example,
+ on "little-endian" platforms where the lowest-addressed byte in a 32-
+ bit word is the least significant and there are no alignment
+ restrictions, the call to Decode in MD5Transform can be replaced with
+ a typecast.
+
+A.1 global.h
+
+/* GLOBAL.H - RSAREF types and constants
+ */
+
+/* PROTOTYPES should be set to one if and only if the compiler supports
+ function argument prototyping.
+The following makes PROTOTYPES default to 0 if it has not already
+
+
+
+Rivest [Page 7]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ been defined with C compiler flags.
+ */
+#ifndef PROTOTYPES
+#define PROTOTYPES 0
+#endif
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef unsigned short int UINT2;
+
+/* UINT4 defines a four byte word */
+typedef unsigned long int UINT4;
+
+/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
+If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
+ returns an empty list.
+ */
+#if PROTOTYPES
+#define PROTO_LIST(list) list
+#else
+#define PROTO_LIST(list) ()
+#endif
+
+A.2 md5.h
+
+/* MD5.H - header file for MD5C.C
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+
+
+
+Rivest [Page 8]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+/* MD5 context. */
+typedef struct {
+ UINT4 state[4]; /* state (ABCD) */
+ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} MD5_CTX;
+
+void MD5Init PROTO_LIST ((MD5_CTX *));
+void MD5Update PROTO_LIST
+ ((MD5_CTX *, unsigned char *, unsigned int));
+void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
+
+A.3 md5c.c
+
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+#include "global.h"
+#include "md5.h"
+
+/* Constants for MD5Transform routine.
+ */
+
+
+
+Rivest [Page 9]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
+static void Encode PROTO_LIST
+ ((unsigned char *, UINT4 *, unsigned int));
+static void Decode PROTO_LIST
+ ((UINT4 *, unsigned char *, unsigned int));
+static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
+static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
+
+static unsigned char PADDING[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+
+
+
+Rivest [Page 10]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+void MD5Init (context)
+MD5_CTX *context; /* context */
+{
+ context->count[0] = context->count[1] = 0;
+ /* Load magic initialization constants.
+*/
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+void MD5Update (context, input, inputLen)
+MD5_CTX *context; /* context */
+unsigned char *input; /* input block */
+unsigned int inputLen; /* length of input block */
+{
+ unsigned int i, index, partLen;
+
+ /* Compute number of bytes mod 64 */
+ index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((UINT4)inputLen << 3))
+
+
+
+Rivest [Page 11]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ < ((UINT4)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((UINT4)inputLen >> 29);
+
+ partLen = 64 - index;
+
+ /* Transform as many times as possible.
+*/
+ if (inputLen >= partLen) {
+ MD5_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+ MD5Transform (context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD5Transform (context->state, &input[i]);
+
+ index = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ MD5_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)&input[i],
+ inputLen-i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+ the message digest and zeroizing the context.
+ */
+void MD5Final (digest, context)
+unsigned char digest[16]; /* message digest */
+MD5_CTX *context; /* context */
+{
+ unsigned char bits[8];
+ unsigned int index, padLen;
+
+ /* Save number of bits */
+ Encode (bits, context->count, 8);
+
+ /* Pad out to 56 mod 64.
+*/
+ index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ MD5Update (context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ MD5Update (context, bits, 8);
+
+
+
+Rivest [Page 12]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ /* Store state in digest */
+ Encode (digest, context->state, 16);
+
+ /* Zeroize sensitive information.
+*/
+ MD5_memset ((POINTER)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5Transform (state, block)
+UINT4 state[4];
+unsigned char block[64];
+{
+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ Decode (x, block, 64);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+
+
+
+Rivest [Page 13]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information.
+
+
+
+Rivest [Page 14]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+*/
+ MD5_memset ((POINTER)x, 0, sizeof (x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+ a multiple of 4.
+ */
+static void Encode (output, input, len)
+unsigned char *output;
+UINT4 *input;
+unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+ a multiple of 4.
+ */
+static void Decode (output, input, len)
+UINT4 *output;
+unsigned char *input;
+unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+ (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+/* Note: Replace "for loop" with standard memcpy if possible.
+ */
+
+static void MD5_memcpy (output, input, len)
+POINTER output;
+POINTER input;
+unsigned int len;
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+
+
+
+Rivest [Page 15]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ output[i] = input[i];
+}
+
+/* Note: Replace "for loop" with standard memset if possible.
+ */
+static void MD5_memset (output, value, len)
+POINTER output;
+int value;
+unsigned int len;
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ ((char *)output)[i] = (char)value;
+}
+
+A.4 mddriver.c
+
+/* MDDRIVER.C - test driver for MD2, MD4 and MD5
+ */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+rights reserved.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+/* The following makes MD default to MD5 if it has not already been
+ defined with C compiler flags.
+ */
+#ifndef MD
+#define MD MD5
+#endif
+
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include "global.h"
+#if MD == 2
+#include "md2.h"
+#endif
+#if MD == 4
+
+
+
+Rivest [Page 16]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+#include "md4.h"
+#endif
+#if MD == 5
+#include "md5.h"
+#endif
+
+/* Length of test block, number of test blocks.
+ */
+#define TEST_BLOCK_LEN 1000
+#define TEST_BLOCK_COUNT 1000
+
+static void MDString PROTO_LIST ((char *));
+static void MDTimeTrial PROTO_LIST ((void));
+static void MDTestSuite PROTO_LIST ((void));
+static void MDFile PROTO_LIST ((char *));
+static void MDFilter PROTO_LIST ((void));
+static void MDPrint PROTO_LIST ((unsigned char [16]));
+
+#if MD == 2
+#define MD_CTX MD2_CTX
+#define MDInit MD2Init
+#define MDUpdate MD2Update
+#define MDFinal MD2Final
+#endif
+#if MD == 4
+#define MD_CTX MD4_CTX
+#define MDInit MD4Init
+#define MDUpdate MD4Update
+#define MDFinal MD4Final
+#endif
+#if MD == 5
+#define MD_CTX MD5_CTX
+#define MDInit MD5Init
+#define MDUpdate MD5Update
+#define MDFinal MD5Final
+#endif
+
+/* Main driver.
+
+Arguments (may be any combination):
+ -sstring - digests string
+ -t - runs time trial
+ -x - runs test script
+ filename - digests file
+ (none) - digests standard input
+ */
+int main (argc, argv)
+int argc;
+
+
+
+Rivest [Page 17]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+char *argv[];
+{
+ int i;
+
+ if (argc > 1)
+ for (i = 1; i < argc; i++)
+ if (argv[i][0] == '-' && argv[i][1] == 's')
+ MDString (argv[i] + 2);
+ else if (strcmp (argv[i], "-t") == 0)
+ MDTimeTrial ();
+ else if (strcmp (argv[i], "-x") == 0)
+ MDTestSuite ();
+ else
+ MDFile (argv[i]);
+ else
+ MDFilter ();
+
+ return (0);
+}
+
+/* Digests a string and prints the result.
+ */
+static void MDString (string)
+char *string;
+{
+ MD_CTX context;
+ unsigned char digest[16];
+ unsigned int len = strlen (string);
+
+ MDInit (&context);
+ MDUpdate (&context, string, len);
+ MDFinal (digest, &context);
+
+ printf ("MD%d (\"%s\") = ", MD, string);
+ MDPrint (digest);
+ printf ("\n");
+}
+
+/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte
+ blocks.
+ */
+static void MDTimeTrial ()
+{
+ MD_CTX context;
+ time_t endTime, startTime;
+ unsigned char block[TEST_BLOCK_LEN], digest[16];
+ unsigned int i;
+
+
+
+
+Rivest [Page 18]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ printf
+ ("MD%d time trial. Digesting %d %d-byte blocks ...", MD,
+ TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
+
+ /* Initialize block */
+ for (i = 0; i < TEST_BLOCK_LEN; i++)
+ block[i] = (unsigned char)(i & 0xff);
+
+ /* Start timer */
+ time (&startTime);
+
+ /* Digest blocks */
+ MDInit (&context);
+ for (i = 0; i < TEST_BLOCK_COUNT; i++)
+ MDUpdate (&context, block, TEST_BLOCK_LEN);
+ MDFinal (digest, &context);
+
+ /* Stop timer */
+ time (&endTime);
+
+ printf (" done\n");
+ printf ("Digest = ");
+ MDPrint (digest);
+ printf ("\nTime = %ld seconds\n", (long)(endTime-startTime));
+ printf
+ ("Speed = %ld bytes/second\n",
+ (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime));
+}
+
+/* Digests a reference suite of strings and prints the results.
+ */
+static void MDTestSuite ()
+{
+ printf ("MD%d test suite:\n", MD);
+
+ MDString ("");
+ MDString ("a");
+ MDString ("abc");
+ MDString ("message digest");
+ MDString ("abcdefghijklmnopqrstuvwxyz");
+ MDString
+ ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ MDString
+ ("1234567890123456789012345678901234567890\
+1234567890123456789012345678901234567890");
+}
+
+/* Digests a file and prints the result.
+
+
+
+Rivest [Page 19]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ */
+static void MDFile (filename)
+char *filename;
+{
+ FILE *file;
+ MD_CTX context;
+ int len;
+ unsigned char buffer[1024], digest[16];
+
+ if ((file = fopen (filename, "rb")) == NULL)
+ printf ("%s can't be opened\n", filename);
+
+ else {
+ MDInit (&context);
+ while (len = fread (buffer, 1, 1024, file))
+ MDUpdate (&context, buffer, len);
+ MDFinal (digest, &context);
+
+ fclose (file);
+
+ printf ("MD%d (%s) = ", MD, filename);
+ MDPrint (digest);
+ printf ("\n");
+ }
+}
+
+/* Digests the standard input and prints the result.
+ */
+static void MDFilter ()
+{
+ MD_CTX context;
+ int len;
+ unsigned char buffer[16], digest[16];
+
+ MDInit (&context);
+ while (len = fread (buffer, 1, 16, stdin))
+ MDUpdate (&context, buffer, len);
+ MDFinal (digest, &context);
+
+ MDPrint (digest);
+ printf ("\n");
+}
+
+/* Prints a message digest in hexadecimal.
+ */
+static void MDPrint (digest)
+unsigned char digest[16];
+{
+
+
+
+Rivest [Page 20]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ unsigned int i;
+
+ for (i = 0; i < 16; i++)
+ printf ("%02x", digest[i]);
+}
+
+A.5 Test suite
+
+ The MD5 test suite (driver option "-x") should print the following
+ results:
+
+MD5 test suite:
+MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
+MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
+MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
+MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
+MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
+MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
+d174ab98d277d9f5a5611c2c9f419d9f
+MD5 ("123456789012345678901234567890123456789012345678901234567890123456
+78901234567890") = 57edf4a22be3c955ac49da2e2107b67a
+
+Security Considerations
+
+ The level of security discussed in this memo is considered to be
+ sufficient for implementing very high security hybrid digital-
+ signature schemes based on MD5 and a public-key cryptosystem.
+
+Author's Address
+
+ Ronald L. Rivest
+ Massachusetts Institute of Technology
+ Laboratory for Computer Science
+ NE43-324
+ 545 Technology Square
+ Cambridge, MA 02139-1986
+
+ Phone: (617) 253-5880
+ EMail: rivest at theory.lcs.mit.edu
+
+
+
+
+
+
+
+
+
+
+
+
+Rivest [Page 21]
+
Added: trunk/orca/packages/Digest-MD5-2.07/typemap
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/typemap (original)
+++ trunk/orca/packages/Digest-MD5-2.07/typemap Sat Jul 13 18:45:56 2002
@@ -0,0 +1,5 @@
+MD5_CTX* T_MD5_CTX
+
+INPUT
+T_MD5_CTX
+ $var = get_md5_ctx($arg)
Added: trunk/orca/packages/Digest-MD5-2.07/rfc2104.txt
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/rfc2104.txt (original)
+++ trunk/orca/packages/Digest-MD5-2.07/rfc2104.txt Sat Jul 13 18:45:56 2002
@@ -0,0 +1,619 @@
+
+
+
+
+
+
+Network Working Group H. Krawczyk
+Request for Comments: 2104 IBM
+Category: Informational M. Bellare
+ UCSD
+ R. Canetti
+ IBM
+ February 1997
+
+
+ HMAC: Keyed-Hashing for Message Authentication
+
+Status of This Memo
+
+ This memo provides information for the Internet community. This memo
+ does not specify an Internet standard of any kind. Distribution of
+ this memo is unlimited.
+
+Abstract
+
+ This document describes HMAC, a mechanism for message authentication
+ using cryptographic hash functions. HMAC can be used with any
+ iterative cryptographic hash function, e.g., MD5, SHA-1, in
+ combination with a secret shared key. The cryptographic strength of
+ HMAC depends on the properties of the underlying hash function.
+
+1. Introduction
+
+ Providing a way to check the integrity of information transmitted
+ over or stored in an unreliable medium is a prime necessity in the
+ world of open computing and communications. Mechanisms that provide
+ such integrity check based on a secret key are usually called
+ "message authentication codes" (MAC). Typically, message
+ authentication codes are used between two parties that share a secret
+ key in order to validate information transmitted between these
+ parties. In this document we present such a MAC mechanism based on
+ cryptographic hash functions. This mechanism, called HMAC, is based
+ on work by the authors [BCK1] where the construction is presented and
+ cryptographically analyzed. We refer to that work for the details on
+ the rationale and security analysis of HMAC, and its comparison to
+ other keyed-hash methods.
+
+
+
+
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 1]
+
+RFC 2104 HMAC February 1997
+
+
+ HMAC can be used in combination with any iterated cryptographic hash
+ function. MD5 and SHA-1 are examples of such hash functions. HMAC
+ also uses a secret key for calculation and verification of the
+ message authentication values. The main goals behind this
+ construction are
+
+ * To use, without modifications, available hash functions.
+ In particular, hash functions that perform well in software,
+ and for which code is freely and widely available.
+
+ * To preserve the original performance of the hash function without
+ incurring a significant degradation.
+
+ * To use and handle keys in a simple way.
+
+ * To have a well understood cryptographic analysis of the strength of
+ the authentication mechanism based on reasonable assumptions on the
+ underlying hash function.
+
+ * To allow for easy replaceability of the underlying hash function in
+ case that faster or more secure hash functions are found or
+ required.
+
+ This document specifies HMAC using a generic cryptographic hash
+ function (denoted by H). Specific instantiations of HMAC need to
+ define a particular hash function. Current candidates for such hash
+ functions include SHA-1 [SHA], MD5 [MD5], RIPEMD-128/160 [RIPEMD].
+ These different realizations of HMAC will be denoted by HMAC-SHA1,
+ HMAC-MD5, HMAC-RIPEMD, etc.
+
+ Note: To the date of writing of this document MD5 and SHA-1 are the
+ most widely used cryptographic hash functions. MD5 has been recently
+ shown to be vulnerable to collision search attacks [Dobb]. This
+ attack and other currently known weaknesses of MD5 do not compromise
+ the use of MD5 within HMAC as specified in this document (see
+ [Dobb]); however, SHA-1 appears to be a cryptographically stronger
+ function. To this date, MD5 can be considered for use in HMAC for
+ applications where the superior performance of MD5 is critical. In
+ any case, implementers and users need to be aware of possible
+ cryptanalytic developments regarding any of these cryptographic hash
+ functions, and the eventual need to replace the underlying hash
+ function. (See section 6 for more information on the security of
+ HMAC.)
+
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 2]
+
+RFC 2104 HMAC February 1997
+
+
+2. Definition of HMAC
+
+ The definition of HMAC requires a cryptographic hash function, which
+ we denote by H, and a secret key K. We assume H to be a cryptographic
+ hash function where data is hashed by iterating a basic compression
+ function on blocks of data. We denote by B the byte-length of such
+ blocks (B=64 for all the above mentioned examples of hash functions),
+ and by L the byte-length of hash outputs (L=16 for MD5, L=20 for
+ SHA-1). The authentication key K can be of any length up to B, the
+ block length of the hash function. Applications that use keys longer
+ than B bytes will first hash the key using H and then use the
+ resultant L byte string as the actual key to HMAC. In any case the
+ minimal recommended length for K is L bytes (as the hash output
+ length). See section 3 for more information on keys.
+
+ We define two fixed and different strings ipad and opad as follows
+ (the 'i' and 'o' are mnemonics for inner and outer):
+
+ ipad = the byte 0x36 repeated B times
+ opad = the byte 0x5C repeated B times.
+
+ To compute HMAC over the data `text' we perform
+
+ H(K XOR opad, H(K XOR ipad, text))
+
+ Namely,
+
+ (1) append zeros to the end of K to create a B byte string
+ (e.g., if K is of length 20 bytes and B=64, then K will be
+ appended with 44 zero bytes 0x00)
+ (2) XOR (bitwise exclusive-OR) the B byte string computed in step
+ (1) with ipad
+ (3) append the stream of data 'text' to the B byte string resulting
+ from step (2)
+ (4) apply H to the stream generated in step (3)
+ (5) XOR (bitwise exclusive-OR) the B byte string computed in
+ step (1) with opad
+ (6) append the H result from step (4) to the B byte string
+ resulting from step (5)
+ (7) apply H to the stream generated in step (6) and output
+ the result
+
+ For illustration purposes, sample code based on MD5 is provided as an
+ appendix.
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 3]
+
+RFC 2104 HMAC February 1997
+
+
+3. Keys
+
+ The key for HMAC can be of any length (keys longer than B bytes are
+ first hashed using H). However, less than L bytes is strongly
+ discouraged as it would decrease the security strength of the
+ function. Keys longer than L bytes are acceptable but the extra
+ length would not significantly increase the function strength. (A
+ longer key may be advisable if the randomness of the key is
+ considered weak.)
+
+ Keys need to be chosen at random (or using a cryptographically strong
+ pseudo-random generator seeded with a random seed), and periodically
+ refreshed. (Current attacks do not indicate a specific recommended
+ frequency for key changes as these attacks are practically
+ infeasible. However, periodic key refreshment is a fundamental
+ security practice that helps against potential weaknesses of the
+ function and keys, and limits the damage of an exposed key.)
+
+4. Implementation Note
+
+ HMAC is defined in such a way that the underlying hash function H can
+ be used with no modification to its code. In particular, it uses the
+ function H with the pre-defined initial value IV (a fixed value
+ specified by each iterative hash function to initialize its
+ compression function). However, if desired, a performance
+ improvement can be achieved at the cost of (possibly) modifying the
+ code of H to support variable IVs.
+
+ The idea is that the intermediate results of the compression function
+ on the B-byte blocks (K XOR ipad) and (K XOR opad) can be precomputed
+ only once at the time of generation of the key K, or before its first
+ use. These intermediate results are stored and then used to
+ initialize the IV of H each time that a message needs to be
+ authenticated. This method saves, for each authenticated message,
+ the application of the compression function of H on two B-byte blocks
+ (i.e., on (K XOR ipad) and (K XOR opad)). Such a savings may be
+ significant when authenticating short streams of data. We stress
+ that the stored intermediate values need to be treated and protected
+ the same as secret keys.
+
+ Choosing to implement HMAC in the above way is a decision of the
+ local implementation and has no effect on inter-operability.
+
+
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 4]
+
+RFC 2104 HMAC February 1997
+
+
+5. Truncated output
+
+ A well-known practice with message authentication codes is to
+ truncate the output of the MAC and output only part of the bits
+ (e.g., [MM, ANSI]). Preneel and van Oorschot [PV] show some
+ analytical advantages of truncating the output of hash-based MAC
+ functions. The results in this area are not absolute as for the
+ overall security advantages of truncation. It has advantages (less
+ information on the hash result available to an attacker) and
+ disadvantages (less bits to predict for the attacker). Applications
+ of HMAC can choose to truncate the output of HMAC by outputting the t
+ leftmost bits of the HMAC computation for some parameter t (namely,
+ the computation is carried in the normal way as defined in section 2
+ above but the end result is truncated to t bits). We recommend that
+ the output length t be not less than half the length of the hash
+ output (to match the birthday attack bound) and not less than 80 bits
+ (a suitable lower bound on the number of bits that need to be
+ predicted by an attacker). We propose denoting a realization of HMAC
+ that uses a hash function H with t bits of output as HMAC-H-t. For
+ example, HMAC-SHA1-80 denotes HMAC computed using the SHA-1 function
+ and with the output truncated to 80 bits. (If the parameter t is not
+ specified, e.g. HMAC-MD5, then it is assumed that all the bits of the
+ hash are output.)
+
+6. Security
+
+ The security of the message authentication mechanism presented here
+ depends on cryptographic properties of the hash function H: the
+ resistance to collision finding (limited to the case where the
+ initial value is secret and random, and where the output of the
+ function is not explicitly available to the attacker), and the
+ message authentication property of the compression function of H when
+ applied to single blocks (in HMAC these blocks are partially unknown
+ to an attacker as they contain the result of the inner H computation
+ and, in particular, cannot be fully chosen by the attacker).
+
+ These properties, and actually stronger ones, are commonly assumed
+ for hash functions of the kind used with HMAC. In particular, a hash
+ function for which the above properties do not hold would become
+ unsuitable for most (probably, all) cryptographic applications,
+ including alternative message authentication schemes based on such
+ functions. (For a complete analysis and rationale of the HMAC
+ function the reader is referred to [BCK1].)
+
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 5]
+
+RFC 2104 HMAC February 1997
+
+
+ Given the limited confidence gained so far as for the cryptographic
+ strength of candidate hash functions, it is important to observe the
+ following two properties of the HMAC construction and its secure use
+ for message authentication:
+
+ 1. The construction is independent of the details of the particular
+ hash function H in use and then the latter can be replaced by any
+ other secure (iterative) cryptographic hash function.
+
+ 2. Message authentication, as opposed to encryption, has a
+ "transient" effect. A published breaking of a message authentication
+ scheme would lead to the replacement of that scheme, but would have
+ no adversarial effect on information authenticated in the past. This
+ is in sharp contrast with encryption, where information encrypted
+ today may suffer from exposure in the future if, and when, the
+ encryption algorithm is broken.
+
+ The strongest attack known against HMAC is based on the frequency of
+ collisions for the hash function H ("birthday attack") [PV,BCK2], and
+ is totally impractical for minimally reasonable hash functions.
+
+ As an example, if we consider a hash function like MD5 where the
+ output length equals L=16 bytes (128 bits) the attacker needs to
+ acquire the correct message authentication tags computed (with the
+ _same_ secret key K!) on about 2**64 known plaintexts. This would
+ require the processing of at least 2**64 blocks under H, an
+ impossible task in any realistic scenario (for a block length of 64
+ bytes this would take 250,000 years in a continuous 1Gbps link, and
+ without changing the secret key K during all this time). This attack
+ could become realistic only if serious flaws in the collision
+ behavior of the function H are discovered (e.g. collisions found
+ after 2**30 messages). Such a discovery would determine the immediate
+ replacement of the function H (the effects of such failure would be
+ far more severe for the traditional uses of H in the context of
+ digital signatures, public key certificates, etc.).
+
+ Note: this attack needs to be strongly contrasted with regular
+ collision attacks on cryptographic hash functions where no secret key
+ is involved and where 2**64 off-line parallelizable (!) operations
+ suffice to find collisions. The latter attack is approaching
+ feasibility [VW] while the birthday attack on HMAC is totally
+ impractical. (In the above examples, if one uses a hash function
+ with, say, 160 bit of output then 2**64 should be replaced by 2**80.)
+
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 6]
+
+RFC 2104 HMAC February 1997
+
+
+ A correct implementation of the above construction, the choice of
+ random (or cryptographically pseudorandom) keys, a secure key
+ exchange mechanism, frequent key refreshments, and good secrecy
+ protection of keys are all essential ingredients for the security of
+ the integrity verification mechanism provided by HMAC.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 7]
+
+RFC 2104 HMAC February 1997
+
+
+Appendix -- Sample Code
+
+ For the sake of illustration we provide the following sample code for
+ the implementation of HMAC-MD5 as well as some corresponding test
+ vectors (the code is based on MD5 code as described in [MD5]).
+
+/*
+** Function: hmac_md5
+*/
+
+void
+hmac_md5(text, text_len, key, key_len, digest)
+unsigned char* text; /* pointer to data stream */
+int text_len; /* length of data stream */
+unsigned char* key; /* pointer to authentication key */
+int key_len; /* length of authentication key */
+caddr_t digest; /* caller digest to be filled in */
+
+{
+ MD5_CTX context;
+ unsigned char k_ipad[65]; /* inner padding -
+ * key XORd with ipad
+ */
+ unsigned char k_opad[65]; /* outer padding -
+ * key XORd with opad
+ */
+ unsigned char tk[16];
+ int i;
+ /* if key is longer than 64 bytes reset it to key=MD5(key) */
+ if (key_len > 64) {
+
+ MD5_CTX tctx;
+
+ MD5Init(&tctx);
+ MD5Update(&tctx, key, key_len);
+ MD5Final(tk, &tctx);
+
+ key = tk;
+ key_len = 16;
+ }
+
+ /*
+ * the HMAC_MD5 transform looks like:
+ *
+ * MD5(K XOR opad, MD5(K XOR ipad, text))
+ *
+ * where K is an n byte key
+ * ipad is the byte 0x36 repeated 64 times
+
+
+
+Krawczyk, et. al. Informational [Page 8]
+
+RFC 2104 HMAC February 1997
+
+
+ * opad is the byte 0x5c repeated 64 times
+ * and text is the data being protected
+ */
+
+ /* start out by storing key in pads */
+ bzero( k_ipad, sizeof k_ipad);
+ bzero( k_opad, sizeof k_opad);
+ bcopy( key, k_ipad, key_len);
+ bcopy( key, k_opad, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i=0; i<64; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+ /*
+ * perform inner MD5
+ */
+ MD5Init(&context); /* init context for 1st
+ * pass */
+ MD5Update(&context, k_ipad, 64) /* start with inner pad */
+ MD5Update(&context, text, text_len); /* then text of datagram */
+ MD5Final(digest, &context); /* finish up 1st pass */
+ /*
+ * perform outer MD5
+ */
+ MD5Init(&context); /* init context for 2nd
+ * pass */
+ MD5Update(&context, k_opad, 64); /* start with outer pad */
+ MD5Update(&context, digest, 16); /* then results of 1st
+ * hash */
+ MD5Final(digest, &context); /* finish up 2nd pass */
+}
+
+Test Vectors (Trailing '\0' of a character string not included in test):
+
+ key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+ key_len = 16 bytes
+ data = "Hi There"
+ data_len = 8 bytes
+ digest = 0x9294727a3638bb1c13f48ef8158bfc9d
+
+ key = "Jefe"
+ data = "what do ya want for nothing?"
+ data_len = 28 bytes
+ digest = 0x750c783e6ab0b503eaa86e310a5db738
+
+ key = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+
+
+Krawczyk, et. al. Informational [Page 9]
+
+RFC 2104 HMAC February 1997
+
+
+ key_len 16 bytes
+ data = 0xDDDDDDDDDDDDDDDDDDDD...
+ ..DDDDDDDDDDDDDDDDDDDD...
+ ..DDDDDDDDDDDDDDDDDDDD...
+ ..DDDDDDDDDDDDDDDDDDDD...
+ ..DDDDDDDDDDDDDDDDDDDD
+ data_len = 50 bytes
+ digest = 0x56be34521d144c88dbb8c733f0e8b3f6
+
+Acknowledgments
+
+ Pau-Chen Cheng, Jeff Kraemer, and Michael Oehler, have provided
+ useful comments on early drafts, and ran the first interoperability
+ tests of this specification. Jeff and Pau-Chen kindly provided the
+ sample code and test vectors that appear in the appendix. Burt
+ Kaliski, Bart Preneel, Matt Robshaw, Adi Shamir, and Paul van
+ Oorschot have provided useful comments and suggestions during the
+ investigation of the HMAC construction.
+
+References
+
+ [ANSI] ANSI X9.9, "American National Standard for Financial
+ Institution Message Authentication (Wholesale)," American
+ Bankers Association, 1981. Revised 1986.
+
+ [Atk] Atkinson, R., "IP Authentication Header", RFC 1826, August
+ 1995.
+
+ [BCK1] M. Bellare, R. Canetti, and H. Krawczyk,
+ "Keyed Hash Functions and Message Authentication",
+ Proceedings of Crypto'96, LNCS 1109, pp. 1-15.
+ (http://www.research.ibm.com/security/keyed-md5.html)
+
+ [BCK2] M. Bellare, R. Canetti, and H. Krawczyk,
+ "Pseudorandom Functions Revisited: The Cascade Construction",
+ Proceedings of FOCS'96.
+
+ [Dobb] H. Dobbertin, "The Status of MD5 After a Recent Attack",
+ RSA Labs' CryptoBytes, Vol. 2 No. 2, Summer 1996.
+ http://www.rsa.com/rsalabs/pubs/cryptobytes.html
+
+ [PV] B. Preneel and P. van Oorschot, "Building fast MACs from hash
+ functions", Advances in Cryptology -- CRYPTO'95 Proceedings,
+ Lecture Notes in Computer Science, Springer-Verlag Vol.963,
+ 1995, pp. 1-14.
+
+ [MD5] Rivest, R., "The MD5 Message-Digest Algorithm",
+ RFC 1321, April 1992.
+
+
+
+Krawczyk, et. al. Informational [Page 10]
+
+RFC 2104 HMAC February 1997
+
+
+ [MM] Meyer, S. and Matyas, S.M., Cryptography, New York Wiley,
+ 1982.
+
+ [RIPEMD] H. Dobbertin, A. Bosselaers, and B. Preneel, "RIPEMD-160: A
+ strengthened version of RIPEMD", Fast Software Encryption,
+ LNCS Vol 1039, pp. 71-82.
+ ftp://ftp.esat.kuleuven.ac.be/pub/COSIC/bosselae/ripemd/.
+
+ [SHA] NIST, FIPS PUB 180-1: Secure Hash Standard, April 1995.
+
+ [Tsu] G. Tsudik, "Message authentication with one-way hash
+ functions", In Proceedings of Infocom'92, May 1992.
+ (Also in "Access Control and Policy Enforcement in
+ Internetworks", Ph.D. Dissertation, Computer Science
+ Department, University of Southern California, April 1991.)
+
+ [VW] P. van Oorschot and M. Wiener, "Parallel Collision
+ Search with Applications to Hash Functions and Discrete
+ Logarithms", Proceedings of the 2nd ACM Conf. Computer and
+ Communications Security, Fairfax, VA, November 1994.
+
+Authors' Addresses
+
+ Hugo Krawczyk
+ IBM T.J. Watson Research Center
+ P.O.Box 704
+ Yorktown Heights, NY 10598
+
+ EMail: hugo at watson.ibm.com
+
+ Mihir Bellare
+ Dept of Computer Science and Engineering
+ Mail Code 0114
+ University of California at San Diego
+ 9500 Gilman Drive
+ La Jolla, CA 92093
+
+ EMail: mihir at cs.ucsd.edu
+
+ Ran Canetti
+ IBM T.J. Watson Research Center
+ P.O.Box 704
+ Yorktown Heights, NY 10598
+
+ EMail: canetti at watson.ibm.com
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 11]
+
Added: trunk/orca/packages/Digest-MD5-2.07/MD5.pm
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/MD5.pm (original)
+++ trunk/orca/packages/Digest-MD5-2.07/MD5.pm Sat Jul 13 18:45:56 2002
@@ -0,0 +1,250 @@
+package Digest::MD5;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT_OK);
+
+$VERSION = '2.07'; # $Date: 1999/04/03 18:07:49 $
+
+require Exporter;
+*import = \&Exporter::import;
+ at EXPORT_OK = qw(md5 md5_hex md5_base64);
+
+require DynaLoader;
+ at ISA=qw(DynaLoader);
+Digest::MD5->bootstrap($VERSION);
+
+*reset = \&new;
+
+1;
+__END__
+
+=head1 NAME
+
+Digest::MD5 - Perl interface to the MD5 Algorithm
+
+=head1 SYNOPSIS
+
+ # Functional style
+ use Digest::MD5 qw(md5 md5_hex md5_base64);
+
+ $digest = md5($data);
+ $digest = md5_hex($data);
+ $digest = md5_base64($data);
+
+
+ # OO style
+ use Digest::MD5;
+
+ $ctx = Digest::MD5->new;
+
+ $ctx->add($data);
+ $ctx->addfile(*FILE);
+
+ $digest = $ctx->digest;
+ $digest = $ctx->hexdigest;
+ $digest = $ctx->b64digest;
+
+=head1 DESCRIPTION
+
+The C<Digest::MD5> module allows you to use the RSA Data Security
+Inc. MD5 Message Digest algorithm from within Perl programs. The
+algorithm takes as input a message of arbitrary length and produces as
+output a 128-bit "fingerprint" or "message digest" of the input.
+
+The C<Digest::MD5> module provide a procedural interface for simple
+use, as well as an object oriented interface that can handle messages
+of arbitrary length and which can read files directly.
+
+A binary digest will be 16 bytes long. A hex digest will be 32
+characters long. A base64 digest will be 22 characters long.
+
+=head1 FUNCTIONS
+
+The following functions can be exported from the C<Digest::MD5>
+module. No functions are exported by default.
+
+=over 4
+
+=item md5($data,...)
+
+This function will concatenate all arguments, calculate the MD5 digest
+of this "message", and return it in binary form.
+
+=item md5_hex($data,...)
+
+Same as md5(), but will return the digest in hexadecimal form.
+
+=item md5_base64($data,...)
+
+Same as md5(), but will return the digest as a base64 encoded string.
+
+=back
+
+=head1 METHODS
+
+The following methods are available:
+
+=over 4
+
+=item $md5 = Digest::MD5->new
+
+The constructor returns a new C<Digest::MD5> object which encapsulate
+the state of the MD5 message-digest algorithm. You can add data to
+the object and finally ask for the digest.
+
+If called as a instance method (i.e. $md5->new) it will just reset the
+state the object to the state of a newly created object. No new
+object is created in this case.
+
+=item $md5->reset
+
+This is just an alias for $md5->new.
+
+=item $md5->add($data,...)
+
+The $data provided as argument are appended to the message we
+calculate the digest for. The return value is the $md5 object itself.
+
+=item $md5->addfile($io_handle)
+
+The $io_handle is read until EOF and the content is appended to the
+message we calculate the digest for. The return value is the $md5
+object itself.
+
+=item $md5->digest
+
+Return the binary digest for the message.
+
+Note that the C<digest> operation is effectively a destructive,
+read-once operation. Once it has been performed, the C<Digest::MD5>
+object is automatically C<reset> and can be used to calculate another
+digest value.
+
+=item $md5->hexdigest
+
+Same as $md5->digest, but will return the digest in hexadecimal form.
+
+=item $md5->b64digest
+
+Same as $md5->digest, but will return the digest as a base64 encoded
+string.
+
+=back
+
+
+=head1 EXAMPLES
+
+The simplest way to use this library is to import the md5_hex()
+function (or one of its cousins):
+
+ use Digest::MD5 qw(md5_hex);
+ print "Digest is ", md5_hex("foobarbaz"), "\n";
+
+The above example would print out the message
+
+ Digest is 6df23dc03f9b54cc38a0fc1483df6e21
+
+provided that the implementation is working correctly. The same
+checksum can also be calculated in OO style:
+
+ use Digest::MD5;
+
+ $md5 = Digest::MD5->new;
+ $md5->add('foo', 'bar');
+ $md5->add('baz');
+ $digest = $md5->digest();
+
+ print "Digest is ", unpack("H*", $digest), "\n";
+
+With OO style you can break the message arbitrary. This means that we
+are no longer limited to have space for the whole message in memory.
+We can handle messages of any size.
+
+This is useful when calculating checksum for files:
+
+ use Digest::MD5;
+
+ my $file = shift || "/etc/passwd";
+ open(FILE, $file) or die "Can't open '$file': $!";
+ binmode(FILE);
+
+ $md5 = Digest::MD5->new;
+ while (<FILE>) {
+ $md5->add($_);
+ }
+ close(FILE);
+ print $md5->b64digest, " $file\n";
+
+Or we can use the builtin addfile method to read the file much faster:
+
+ use Digest::MD5;
+
+ my $file = shift || "/etc/passwd";
+ open(FILE, $file) or die "Can't open '$file': $!";
+ binmode(FILE);
+
+ print Digest::MD5->new->addfile(*FILE)->hexdigest, " $file\n";
+
+=head1 SEE ALSO
+
+L<Digest>,
+L<Digest::MD2>,
+L<Digest::SHA1>,
+L<Digest::HMAC>
+
+L<md5sum(1)>
+
+RFC 1321
+
+=head1 COPYRIGHT
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+ Copyright 1998-1999 Gisle Aas.
+ Copyright 1995-1996 Neil Winton.
+ Copyright 1991-1992 RSA Data Security, Inc.
+
+The MD5 algorithm is defined in RFC 1321. The basic C code
+implementing the algorithm is derived from that in the RFC and is
+covered by the following copyright:
+
+=over 4
+
+=item
+
+Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+
+=back
+
+This copyright does not prohibit distribution of any version of Perl
+containing this extension under the terms of the GNU or Artistic
+licenses.
+
+=head1 AUTHORS
+
+The original MD5 interface was written by Neil Winton
+(C<N.Winton at axion.bt.co.uk>).
+
+This release was made by Gisle Aas <gisle at aas.no>
+
+=cut
Added: trunk/orca/packages/Digest-MD5-2.07/MD2/typemap
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/MD2/typemap (original)
+++ trunk/orca/packages/Digest-MD5-2.07/MD2/typemap Sat Jul 13 18:45:56 2002
@@ -0,0 +1,5 @@
+MD2_CTX* T_MD2_CTX
+
+INPUT
+T_MD2_CTX
+ $var = get_md2_ctx($arg)
Added: trunk/orca/packages/Digest-MD5-2.07/MD2/t/md2.t
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/MD2/t/md2.t (original)
+++ trunk/orca/packages/Digest-MD5-2.07/MD2/t/md2.t Sat Jul 13 18:45:56 2002
@@ -0,0 +1,34 @@
+print "1..7\n";
+use strict;
+
+use Digest::MD2 qw(md2 md2_hex);
+my $testno = 0;
+
+# From RFC 1319
+my $TESTS = <<'EOT';
+MD2 ("") = 8350e5a3e24c153df2275c9f80692773
+MD2 ("a") = 32ec01ec4a6dac72c0ab96fb34c0b5d1
+MD2 ("abc") = da853b0d3f88d99b30283a69e6ded6bb
+MD2 ("message digest") = ab4f496bfb2a530b219ff33031fe06b0
+MD2 ("abcdefghijklmnopqrstuvwxyz") = 4e8ddff3650292ab5a4108c3aa47940b
+MD2 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = da33def2a42df13975352846c30338cd
+MD2 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = d5976f79d83d3a0dc9806c3c66f3efd8
+EOT
+
+for (split(/^/, $TESTS)) {
+ die unless /^MD2\s*\(\"([^\"]*)\"\)\s*=\s*(.*)/;
+ my $message = $1;
+ my $hexdigest = $2;
+ my $bindigest = pack("H*", $hexdigest);
+
+ my $failed;
+ $failed++ unless md2($message) eq $bindigest;
+ $failed++ unless md2_hex($message) eq $hexdigest;
+
+ # Test OO interface
+ $failed++ unless Digest::MD2->new->add($message)->digest eq $bindigest;
+ $failed++ unless Digest::MD2->new->add($message)->hexdigest eq $hexdigest;
+
+ print "not " if $failed;
+ print "ok ", ++$testno, "\n";
+}
Added: trunk/orca/packages/Digest-MD5-2.07/MD2/rfc1319.txt
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/MD2/rfc1319.txt (original)
+++ trunk/orca/packages/Digest-MD5-2.07/MD2/rfc1319.txt Sat Jul 13 18:45:56 2002
@@ -0,0 +1,955 @@
+
+
+
+
+
+
+Network Working Group B. Kaliski
+Request for Comments: 1319 RSA Laboratories
+Updates: RFC 1115 April 1992
+
+
+ The MD2 Message-Digest Algorithm
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard. Distribution of this memo is
+ unlimited.
+
+Acknowlegements
+
+ The description of MD2 is based on material prepared by John Linn and
+ Ron Rivest. Their permission to incorporate that material is greatly
+ appreciated.
+
+Table of Contents
+
+ 1. Executive Summary 1
+ 2. Terminology and Notation 2
+ 3. MD2 Algorithm Description 2
+ 4. Summary 4
+ References 5
+ APPENDIX A - Reference Implementation 5
+ Security Considerations 17
+ Author's Address 17
+
+1. Executive Summary
+
+ This document describes the MD2 message-digest algorithm. The
+ algorithm takes as input a message of arbitrary length and produces
+ as output a 128-bit "fingerprint" or "message digest" of the input.
+ It is conjectured that it is computationally infeasible to produce
+ two messages having the same message digest, or to produce any
+ message having a given prespecified target message digest. The MD2
+ algorithm is intended for digital signature applications, where a
+ large file must be "compressed" in a secure manner before being
+ signed with a private (secret) key under a public-key cryptosystem
+ such as RSA.
+
+ License to use MD2 is granted for non-commerical Internet Privacy-
+ Enhanced Mail [1-3].
+
+ This document is an update to the August 1989 RFC 1115 [3], which
+ also gives a reference implementation of MD2. The main differences
+
+
+
+Kaliski [Page 1]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+ are that a textual description of MD2 is included, and that the
+ reference implementation of MD2 is more portable.
+
+ For OSI-based applications, MD2's object identifier is
+
+ md2 OBJECT IDENTIFIER ::=
+ iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 2}
+
+ In the X.509 type AlgorithmIdentifier [4], the parameters for MD2
+ should have type NULL.
+
+2. Terminology and Notation
+
+ In this document, a "byte" is an eight-bit quantity.
+
+ Let x_i denote "x sub i". If the subscript is an expression, we
+ surround it in braces, as in x_{i+1}. Similarly, we use ^ for
+ superscripts (exponentiation), so that x^i denotes x to the i-th
+ power.
+
+ Let X xor Y denote the bit-wise XOR of X and Y.
+
+3. MD2 Algorithm Description
+
+ We begin by supposing that we have a b-byte message as input, and
+ that we wish to find its message digest. Here b is an arbitrary
+ nonnegative integer; b may be zero, and it may be arbitrarily large.
+ We imagine the bytes of the message written down as follows:
+
+ m_0 m_1 ... m_{b-1}
+
+ The following five steps are performed to compute the message digest
+ of the message.
+
+3.1 Step 1. Append Padding Bytes
+
+ The message is "padded" (extended) so that its length (in bytes) is
+ congruent to 0, modulo 16. That is, the message is extended so that
+ it is a multiple of 16 bytes long. Padding is always performed, even
+ if the length of the message is already congruent to 0, modulo 16.
+
+ Padding is performed as follows: "i" bytes of value "i" are appended
+ to the message so that the length in bytes of the padded message
+ becomes congruent to 0, modulo 16. At least one byte and at most 16
+ 16 bytes are appended.
+
+ At this point the resulting message (after padding with bytes) has a
+ length that is an exact multiple of 16 bytes. Let M[0 ... N-1] denote
+
+
+
+Kaliski [Page 2]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+ the bytes of the resulting message, where N is a multiple of 16.
+
+3.2 Step 2. Append Checksum
+
+ A 16-byte checksum of the message is appended to the result of the
+ previous step.
+
+ This step uses a 256-byte "random" permutation constructed from the
+ digits of pi. Let S[i] denote the i-th element of this table. The
+ table is given in the appendix.
+
+ Do the following:
+
+ /* Clear checksum. */
+ For i = 0 to 15 do:
+ Set C[i] to 0.
+ end /* of loop on i */
+
+ Set L to 0.
+
+ /* Process each 16-word block. */
+ For i = 0 to N/16-1 do
+
+ /* Checksum block i. */
+ For j = 0 to 15 do
+ Set c to M[i*16+j].
+ Set C[j] to S[c xor L].
+ Set L to C[j].
+ end /* of loop on j */
+ end /* of loop on i */
+
+ The 16-byte checksum C[0 ... 15] is appended to the message. Let M[0
+ with checksum), where N' = N + 16.
+
+3.3 Step 3. Initialize MD Buffer
+
+ A 48-byte buffer X is used to compute the message digest. The buffer
+ is initialized to zero.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kaliski [Page 3]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+3.4 Step 4. Process Message in 16-Byte Blocks
+
+ This step uses the same 256-byte permutation S as step 2 does.
+
+ Do the following:
+
+ /* Process each 16-word block. */
+ For i = 0 to N'/16-1 do
+
+ /* Copy block i into X. */
+ For j = 0 to 15 do
+ Set X[16+j] to M[i*16+j].
+ Set X[32+j] to (X[16+j] xor X[j]).
+ end /* of loop on j */
+
+ Set t to 0.
+
+ /* Do 18 rounds. */
+ For j = 0 to 17 do
+
+ /* Round j. */
+ For k = 0 to 47 do
+ Set t and X[k] to (X[k] xor S[t]).
+ end /* of loop on k */
+
+ Set t to (t+j) modulo 256.
+ end /* of loop on j */
+
+ end /* of loop on i */
+
+3.5 Step 5. Output
+
+ The message digest produced as output is X[0 ... 15]. That is, we
+ begin with X[0], and end with X[15].
+
+ This completes the description of MD2. A reference implementation in
+ C is given in the appendix.
+
+4. Summary
+
+ The MD2 message-digest algorithm is simple to implement, and provides
+ a "fingerprint" or message digest of a message of arbitrary length.
+ It is conjectured that the difficulty of coming up with two messages
+ having the same message digest is on the order of 2^64 operations,
+ and that the difficulty of coming up with any message having a given
+ message digest is on the order of 2^128 operations. The MD2 algorithm
+ has been carefully scrutinized for weaknesses. It is, however, a
+ relatively new algorithm and further security analysis is of course
+
+
+
+Kaliski [Page 4]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+ justified, as is the case with any new proposal of this sort.
+
+References
+
+ [1] Linn, J., "Privacy Enhancement for Internet Electronic Mail: Part
+ I -- Message Encipherment and Authentication Procedures", RFC
+ 1113, DEC, IAB Privacy Task Force, August 1989.
+
+ [2] Kent, S., and J. Linn, "Privacy Enhancement for Internet
+ Electronic Mail: Part II -- Certificate-Based Key Management",
+ RFC 1114, BBNCC, DEC, IAB Privacy Task Force, August 1989.
+
+ [3] Linn, J., "Privacy Enhancement for Internet Electronic Mail: Part
+ III -- Algorithms, Modes, and Identifiers", RFC 1115 DEC, IAB
+ Privacy Task Force, August 1989.
+
+ [4] CCITT Recommendation X.509 (1988), "The Directory -
+ Authentication Framework".
+
+APPENDIX A - Reference Implementation
+
+ This appendix contains the following files taken from RSAREF: A
+ Cryptographic Toolkit for Privacy-Enhanced Mail:
+
+ global.h -- global header file
+
+ md2.h -- header file for MD2
+
+ md2c.c -- source code for MD2
+
+For more information on RSAREF, send email to <rsaref at rsa.com>.
+
+The appendix also includes the following file:
+
+ mddriver.c -- test driver for MD2, MD4 and MD5
+
+The driver compiles for MD5 by default but can compile for MD2 or MD4 if
+the symbol MD is defined on the C compiler command line as 2 or 4.
+
+A.1 global.h
+
+/* GLOBAL.H - RSAREF types and constants
+ */
+
+/* PROTOTYPES should be set to one if and only if the compiler supports
+ function argument prototyping.
+ The following makes PROTOTYPES default to 0 if it has not already
+ been defined with C compiler flags.
+
+
+
+Kaliski [Page 5]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+ */
+#ifndef PROTOTYPES
+#define PROTOTYPES 0
+#endif
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef unsigned short int UINT2;
+
+/* UINT4 defines a four byte word */
+typedef unsigned long int UINT4;
+
+/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
+ If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
+ returns an empty list.
+ */
+#if PROTOTYPES
+#define PROTO_LIST(list) list
+#else
+#define PROTO_LIST(list) ()
+#endif
+
+A.2 md2.h
+
+/* MD2.H - header file for MD2C.C
+ */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+ rights reserved.
+
+ License to copy and use this software is granted for
+ non-commercial Internet Privacy-Enhanced Mail provided that it is
+ identified as the "RSA Data Security, Inc. MD2 Message Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+
+
+
+
+Kaliski [Page 6]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+typedef struct {
+ unsigned char state[16]; /* state */
+ unsigned char checksum[16]; /* checksum */
+ unsigned int count; /* number of bytes, modulo 16 */
+ unsigned char buffer[16]; /* input buffer */
+} MD2_CTX;
+
+void MD2Init PROTO_LIST ((MD2_CTX *));
+void MD2Update PROTO_LIST
+ ((MD2_CTX *, unsigned char *, unsigned int));
+void MD2Final PROTO_LIST ((unsigned char [16], MD2_CTX *));
+
+A.3 md2c.c
+
+/* MD2C.C - RSA Data Security, Inc., MD2 message-digest algorithm
+ */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+ rights reserved.
+
+ License to copy and use this software is granted for
+ non-commercial Internet Privacy-Enhanced Mail provided that it is
+ identified as the "RSA Data Security, Inc. MD2 Message Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+#include "global.h"
+#include "md2.h"
+
+static void MD2Transform PROTO_LIST
+ ((unsigned char [16], unsigned char [16], unsigned char [16]));
+static void MD2_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
+static void MD2_memset PROTO_LIST ((POINTER, int, unsigned int));
+
+/* Permutation of 0..255 constructed from the digits of pi. It gives a
+ "random" nonlinear byte substitution operation.
+ */
+static unsigned char PI_SUBST[256] = {
+ 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
+
+
+
+Kaliski [Page 7]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+ 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
+ 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
+ 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
+ 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
+ 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
+ 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
+ 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
+ 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
+ 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
+ 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
+ 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
+ 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
+ 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
+ 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
+ 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
+ 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
+ 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
+};
+
+static unsigned char *PADDING[] = {
+ (unsigned char *)"",
+ (unsigned char *)"\001",
+ (unsigned char *)"\002\002",
+ (unsigned char *)"\003\003\003",
+ (unsigned char *)"\004\004\004\004",
+ (unsigned char *)"\005\005\005\005\005",
+ (unsigned char *)"\006\006\006\006\006\006",
+ (unsigned char *)"\007\007\007\007\007\007\007",
+ (unsigned char *)"\010\010\010\010\010\010\010\010",
+ (unsigned char *)"\011\011\011\011\011\011\011\011\011",
+ (unsigned char *)"\012\012\012\012\012\012\012\012\012\012",
+ (unsigned char *)"\013\013\013\013\013\013\013\013\013\013\013",
+ (unsigned char *)"\014\014\014\014\014\014\014\014\014\014\014\014",
+ (unsigned char *)
+ "\015\015\015\015\015\015\015\015\015\015\015\015\015",
+ (unsigned char *)
+ "\016\016\016\016\016\016\016\016\016\016\016\016\016\016",
+ (unsigned char *)
+ "\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017",
+ (unsigned char *)
+ "\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020"
+};
+
+/* MD2 initialization. Begins an MD2 operation, writing a new context.
+ */
+void MD2Init (context)
+MD2_CTX *context; /* context */
+{
+
+
+
+Kaliski [Page 8]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+ context->count = 0;
+ MD2_memset ((POINTER)context->state, 0, sizeof (context->state));
+ MD2_memset
+ ((POINTER)context->checksum, 0, sizeof (context->checksum));
+}
+
+/* MD2 block update operation. Continues an MD2 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+void MD2Update (context, input, inputLen)
+MD2_CTX *context; /* context */
+unsigned char *input; /* input block */
+unsigned int inputLen; /* length of input block */
+{
+ unsigned int i, index, partLen;
+
+ /* Update number of bytes mod 16 */
+ index = context->count;
+ context->count = (index + inputLen) & 0xf;
+
+ partLen = 16 - index;
+
+ /* Transform as many times as possible.
+ */
+ if (inputLen >= partLen) {
+ MD2_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+ MD2Transform (context->state, context->checksum, context->buffer);
+
+ for (i = partLen; i + 15 < inputLen; i += 16)
+ MD2Transform (context->state, context->checksum, &input[i]);
+
+ index = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ MD2_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)&input[i],
+ inputLen-i);
+}
+
+/* MD2 finalization. Ends an MD2 message-digest operation, writing the
+ message digest and zeroizing the context.
+ */
+void MD2Final (digest, context)
+
+
+
+Kaliski [Page 9]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+unsigned char digest[16]; /* message digest */
+MD2_CTX *context; /* context */
+{
+ unsigned int index, padLen;
+
+ /* Pad out to multiple of 16.
+ */
+ index = context->count;
+ padLen = 16 - index;
+ MD2Update (context, PADDING[padLen], padLen);
+
+ /* Extend with checksum */
+ MD2Update (context, context->checksum, 16);
+
+ /* Store state in digest */
+ MD2_memcpy ((POINTER)digest, (POINTER)context->state, 16);
+
+ /* Zeroize sensitive information.
+ */
+ MD2_memset ((POINTER)context, 0, sizeof (*context));
+}
+
+/* MD2 basic transformation. Transforms state and updates checksum
+ based on block.
+ */
+static void MD2Transform (state, checksum, block)
+unsigned char state[16];
+unsigned char checksum[16];
+unsigned char block[16];
+{
+ unsigned int i, j, t;
+ unsigned char x[48];
+
+ /* Form encryption block from state, block, state ^ block.
+ */
+ MD2_memcpy ((POINTER)x, (POINTER)state, 16);
+ MD2_memcpy ((POINTER)x+16, (POINTER)block, 16);
+ for (i = 0; i < 16; i++)
+ x[i+32] = state[i] ^ block[i];
+
+ /* Encrypt block (18 rounds).
+ */
+ t = 0;
+ for (i = 0; i < 18; i++) {
+ for (j = 0; j < 48; j++)
+ t = x[j] ^= PI_SUBST[t];
+ t = (t + i) & 0xff;
+ }
+
+
+
+Kaliski [Page 10]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+ /* Save new state */
+ MD2_memcpy ((POINTER)state, (POINTER)x, 16);
+
+ /* Update checksum.
+ */
+ t = checksum[15];
+ for (i = 0; i < 16; i++)
+ t = checksum[i] ^= PI_SUBST[block[i] ^ t];
+
+ /* Zeroize sensitive information.
+ */
+ MD2_memset ((POINTER)x, 0, sizeof (x));
+}
+
+/* Note: Replace "for loop" with standard memcpy if possible.
+ */
+static void MD2_memcpy (output, input, len)
+POINTER output;
+POINTER input;
+unsigned int len;
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ output[i] = input[i];
+}
+
+/* Note: Replace "for loop" with standard memset if possible.
+ */
+static void MD2_memset (output, value, len)
+POINTER output;
+int value;
+unsigned int len;
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ ((char *)output)[i] = (char)value;
+}
+
+A.4 mddriver.c
+
+/* MDDRIVER.C - test driver for MD2, MD4 and MD5
+ */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+ rights reserved.
+
+
+
+
+Kaliski [Page 11]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+/* The following makes MD default to MD5 if it has not already been
+ defined with C compiler flags.
+ */
+#ifndef MD
+#define MD MD5
+#endif
+
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include "global.h"
+#if MD == 2
+#include "md2.h"
+#endif
+#if MD == 4
+#include "md4.h"
+#endif
+#if MD == 5
+#include "md5.h"
+#endif
+
+/* Length of test block, number of test blocks.
+ */
+#define TEST_BLOCK_LEN 1000
+#define TEST_BLOCK_COUNT 1000
+
+static void MDString PROTO_LIST ((char *));
+static void MDTimeTrial PROTO_LIST ((void));
+static void MDTestSuite PROTO_LIST ((void));
+static void MDFile PROTO_LIST ((char *));
+static void MDFilter PROTO_LIST ((void));
+static void MDPrint PROTO_LIST ((unsigned char [16]));
+
+#if MD == 2
+#define MD_CTX MD2_CTX
+#define MDInit MD2Init
+#define MDUpdate MD2Update
+#define MDFinal MD2Final
+#endif
+
+
+
+Kaliski [Page 12]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+#if MD == 4
+#define MD_CTX MD4_CTX
+#define MDInit MD4Init
+#define MDUpdate MD4Update
+#define MDFinal MD4Final
+#endif
+#if MD == 5
+#define MD_CTX MD5_CTX
+#define MDInit MD5Init
+#define MDUpdate MD5Update
+#define MDFinal MD5Final
+#endif
+
+/* Main driver.
+
+ Arguments (may be any combination):
+ -sstring - digests string
+ -t - runs time trial
+ -x - runs test script
+ filename - digests file
+ (none) - digests standard input
+ */
+int main (argc, argv)
+int argc;
+char *argv[];
+{
+ int i;
+
+ if (argc > 1)
+ for (i = 1; i < argc; i++)
+ if (argv[i][0] == '-' && argv[i][1] == 's')
+ MDString (argv[i] + 2);
+ else if (strcmp (argv[i], "-t") == 0)
+ MDTimeTrial ();
+ else if (strcmp (argv[i], "-x") == 0)
+ MDTestSuite ();
+ else
+ MDFile (argv[i]);
+ else
+ MDFilter ();
+
+ return (0);
+}
+
+/* Digests a string and prints the result.
+ */
+static void MDString (string)
+char *string;
+
+
+
+Kaliski [Page 13]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+{
+ MD_CTX context;
+ unsigned char digest[16];
+ unsigned int len = strlen (string);
+
+ MDInit (&context);
+ MDUpdate (&context, string, len);
+ MDFinal (digest, &context);
+
+ printf ("MD%d (\"%s\") = ", MD, string);
+ MDPrint (digest);
+ printf ("\n");
+}
+
+/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte
+ blocks.
+ */
+static void MDTimeTrial ()
+{
+ MD_CTX context;
+ time_t endTime, startTime;
+ unsigned char block[TEST_BLOCK_LEN], digest[16];
+ unsigned int i;
+
+ printf
+ ("MD%d time trial. Digesting %d %d-byte blocks ...", MD,
+ TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
+
+ /* Initialize block */
+ for (i = 0; i < TEST_BLOCK_LEN; i++)
+ block[i] = (unsigned char)(i & 0xff);
+
+ /* Start timer */
+ time (&startTime);
+
+ /* Digest blocks */
+ MDInit (&context);
+ for (i = 0; i < TEST_BLOCK_COUNT; i++)
+ MDUpdate (&context, block, TEST_BLOCK_LEN);
+ MDFinal (digest, &context);
+
+ /* Stop timer */
+ time (&endTime);
+
+ printf (" done\n");
+ printf ("Digest = ");
+ MDPrint (digest);
+ printf ("\nTime = %ld seconds\n", (long)(endTime-startTime));
+
+
+
+Kaliski [Page 14]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+ printf
+ ("Speed = %ld bytes/second\n",
+ (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime));
+}
+/* Digests a reference suite of strings and prints the results.
+ */
+static void MDTestSuite ()
+{
+ printf ("MD%d test suite:\n", MD);
+
+ MDString ("");
+ MDString ("a");
+ MDString ("abc");
+ MDString ("message digest");
+ MDString ("abcdefghijklmnopqrstuvwxyz");
+ MDString
+ ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ MDString
+ ("1234567890123456789012345678901234567890\
+1234567890123456789012345678901234567890");
+}
+
+/* Digests a file and prints the result.
+ */
+static void MDFile (filename)
+char *filename;
+{
+ FILE *file;
+ MD_CTX context;
+ int len;
+ unsigned char buffer[1024], digest[16];
+
+ if ((file = fopen (filename, "rb")) == NULL)
+ printf ("%s can't be opened\n", filename);
+
+ else {
+ MDInit (&context);
+ while (len = fread (buffer, 1, 1024, file))
+ MDUpdate (&context, buffer, len);
+ MDFinal (digest, &context);
+
+ fclose (file);
+
+ printf ("MD%d (%s) = ", MD, filename);
+ MDPrint (digest);
+ printf ("\n");
+ }
+}
+
+
+
+Kaliski [Page 15]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+/* Digests the standard input and prints the result.
+ */
+static void MDFilter ()
+{
+ MD_CTX context;
+ int len;
+ unsigned char buffer[16], digest[16];
+
+ MDInit (&context);
+ while (len = fread (buffer, 1, 16, stdin))
+ MDUpdate (&context, buffer, len);
+ MDFinal (digest, &context);
+
+ MDPrint (digest);
+ printf ("\n");
+}
+
+/* Prints a message digest in hexadecimal.
+ */
+static void MDPrint (digest)
+unsigned char digest[16];
+{
+ unsigned int i;
+
+ for (i = 0; i < 16; i++)
+ printf ("%02x", digest[i]);
+}
+
+A.5 Test suite
+
+ The MD2 test suite (driver option "-x") should print the following
+ results:
+
+MD2 test suite:
+MD2 ("") = 8350e5a3e24c153df2275c9f80692773
+MD2 ("a") = 32ec01ec4a6dac72c0ab96fb34c0b5d1
+MD2 ("abc") = da853b0d3f88d99b30283a69e6ded6bb
+MD2 ("message digest") = ab4f496bfb2a530b219ff33031fe06b0
+MD2 ("abcdefghijklmnopqrstuvwxyz") = 4e8ddff3650292ab5a4108c3aa47940b
+MD2 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
+da33def2a42df13975352846c30338cd
+MD2 ("123456789012345678901234567890123456789012345678901234567890123456
+78901234567890") = d5976f79d83d3a0dc9806c3c66f3efd8
+
+
+
+
+
+
+
+
+Kaliski [Page 16]
+
+RFC 1319 MD2 Message-Digest Algorithm April 1992
+
+
+Security Considerations
+
+ The level of security discussed in this memo is considered to be
+ sufficient for implementing very high security hybrid digital
+ signature schemes based on MD2 and a public-key cryptosystem.
+
+Author's Address
+
+ Burton S. Kaliski Jr.
+ RSA Laboratories (a division of RSA Data Security, Inc.)
+ 10 Twin Dolphin Drive
+ Redwood City, CA 94065
+
+ Phone: (415) 595-8782
+ FAX: (415) 595-4126
+ EMail: burt at rsa.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kaliski [Page 17]
+
Added: trunk/orca/packages/Digest-MD5-2.07/MD2/Makefile.PL
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/MD2/Makefile.PL (original)
+++ trunk/orca/packages/Digest-MD5-2.07/MD2/Makefile.PL Sat Jul 13 18:45:57 2002
@@ -0,0 +1,8 @@
+require 5.004;
+use ExtUtils::MakeMaker;
+
+WriteMakefile(
+ 'NAME' => 'Digest::MD2',
+ 'VERSION_FROM' => 'MD2.pm',
+ 'dist' => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
+);
Added: trunk/orca/packages/Digest-MD5-2.07/MD2/MD2.xs
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/MD2/MD2.xs (original)
+++ trunk/orca/packages/Digest-MD5-2.07/MD2/MD2.xs Sat Jul 13 18:45:57 2002
@@ -0,0 +1,366 @@
+/* $Id: MD2.xs,v 1.8 1999/03/05 21:13:03 gisle Exp $ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the same terms as Perl itself.
+ *
+ * Copyright 1998 Gisle Aas.
+ * Copyright 1990-1992 RSA Data Security, Inc.
+ *
+ * This code is derived from the reference implementation in RFC 1231
+ * which comes with this message:
+ *
+ * Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted for
+ * non-commercial Internet Privacy-Enhanced Mail provided that it is
+ * identified as the "RSA Data Security, Inc. MD2 Message Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#ifdef __cplusplus
+}
+#endif
+
+typedef struct {
+ unsigned char state[16]; /* state */
+ unsigned char checksum[16]; /* checksum */
+ unsigned int count; /* number of bytes, modulo 16 */
+ unsigned char buffer[16]; /* input buffer */
+} MD2_CTX;
+
+
+/* Permutation of 0..255 constructed from the digits of pi. It gives a
+ "random" nonlinear byte substitution operation.
+ */
+static U8 PI_SUBST[256] = {
+ 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
+ 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
+ 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
+ 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
+ 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
+ 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
+ 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
+ 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
+ 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
+ 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
+ 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
+ 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
+ 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
+ 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
+ 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
+ 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
+ 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
+ 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
+};
+
+static U8 *PADDING[] = {
+ (U8 *)"",
+ (U8 *)"\001",
+ (U8 *)"\002\002",
+ (U8 *)"\003\003\003",
+ (U8 *)"\004\004\004\004",
+ (U8 *)"\005\005\005\005\005",
+ (U8 *)"\006\006\006\006\006\006",
+ (U8 *)"\007\007\007\007\007\007\007",
+ (U8 *)"\010\010\010\010\010\010\010\010",
+ (U8 *)"\011\011\011\011\011\011\011\011\011",
+ (U8 *)"\012\012\012\012\012\012\012\012\012\012",
+ (U8 *)"\013\013\013\013\013\013\013\013\013\013\013",
+ (U8 *)"\014\014\014\014\014\014\014\014\014\014\014\014",
+ (U8 *)"\015\015\015\015\015\015\015\015\015\015\015\015\015",
+ (U8 *)"\016\016\016\016\016\016\016\016\016\016\016\016\016\016",
+ (U8 *)"\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017",
+ (U8 *)"\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020"
+};
+
+
+static void
+MD2Init(MD2_CTX* context)
+{
+ Zero(context, 1, MD2_CTX);
+ context->count = 0;
+}
+
+
+static void
+MD2Transform (U8* state, U8* checksum, U8* block)
+{
+ unsigned int i, j, t;
+ U8 x[48];
+
+ /* Form encryption block from state, block, state ^ block.
+ */
+ Copy(state, x, 16, char);
+ Copy(block, x+16, 16, char);
+
+ for (i = 0; i < 16; i++)
+ x[i+32] = state[i] ^ block[i];
+
+ /* Encrypt block (18 rounds).
+ */
+ t = 0;
+ for (i = 0; i < 18; i++) {
+ for (j = 0; j < 48; j++)
+ t = x[j] ^= PI_SUBST[t];
+ t = (t + i) & 0xff;
+ }
+
+ Copy(x, state, 16, char); /* Save new state */
+
+ /* Update checksum.
+ */
+ t = checksum[15];
+ for (i = 0; i < 16; i++)
+ t = checksum[i] ^= PI_SUBST[block[i] ^ t];
+
+ Zero(x, 1, x); /* Zeroize sensitive information. */
+}
+
+
+static void
+MD2Update (MD2_CTX* context, U8 *input, STRLEN inputLen)
+{
+ unsigned int i, index, partLen;
+
+ /* Update number of bytes mod 16 */
+ index = context->count;
+ context->count = (index + inputLen) & 0xf;
+
+ partLen = 16 - index;
+
+ /* Transform as many times as possible.
+ */
+ if (inputLen >= partLen) {
+ Copy(input, context->buffer+index, partLen, char);
+ MD2Transform (context->state, context->checksum, context->buffer);
+
+ for (i = partLen; i + 15 < inputLen; i += 16)
+ MD2Transform (context->state, context->checksum, &input[i]);
+
+ index = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ Copy(input+i, context->buffer + index, inputLen-i, char);
+}
+
+
+static void
+MD2Final (U8* digest, MD2_CTX *context)
+{
+ unsigned int index, padLen;
+
+ /* Pad out to multiple of 16 */
+ index = context->count;
+ padLen = 16 - index;
+ MD2Update (context, PADDING[padLen], padLen);
+
+ /* Extend with checksum */
+ MD2Update (context, context->checksum, 16);
+
+ Copy(context->state, digest, 16, char); /* Store state in digest */
+ Zero(context, 1, MD2_CTX); /* Zeroize sensitive information. */
+}
+
+/*----------------------------------------------------------------*/
+
+static MD2_CTX* get_md2_ctx(SV* sv)
+{
+ if (sv_derived_from(sv, "Digest::MD2"))
+ return (MD2_CTX*)SvIV(SvRV(sv));
+ croak("Not a reference to a Digest::MD2 object");
+ return (MD2_CTX*)0; /* some compilers insist on a return value */
+}
+
+
+static char* hex_16(const unsigned char* from, char* to)
+{
+ static char *hexdigits = "0123456789abcdef";
+ const unsigned char *end = from + 16;
+ char *d = to;
+
+ while (from < end) {
+ *d++ = hexdigits[(*from >> 4)];
+ *d++ = hexdigits[(*from & 0x0F)];
+ from++;
+ }
+ *d = '\0';
+ return to;
+}
+
+static char* base64_16(const unsigned char* from, char* to)
+{
+ static char* base64 =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ const unsigned char *end = from + 16;
+ unsigned char c1, c2, c3;
+ char *d = to;
+
+ while (1) {
+ c1 = *from++;
+ *d++ = base64[c1>>2];
+ if (from == end) {
+ *d++ = base64[(c1 & 0x3) << 4];
+ break;
+ }
+ c2 = *from++;
+ c3 = *from++;
+ *d++ = base64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)];
+ *d++ = base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
+ *d++ = base64[c3 & 0x3F];
+ }
+ *d = '\0';
+ return to;
+}
+
+/* Formats */
+#define F_BIN 0
+#define F_HEX 1
+#define F_B64 2
+
+static SV* make_mortal_sv(const unsigned char *src, int type)
+{
+ STRLEN len;
+ char result[33];
+ char *ret;
+
+ switch (type) {
+ case F_BIN:
+ ret = (char*)src;
+ len = 16;
+ break;
+ case F_HEX:
+ ret = hex_16(src, result);
+ len = 32;
+ break;
+ case F_B64:
+ ret = base64_16(src, result);
+ len = 22;
+ break;
+ default:
+ croak("Bad convertion type (%d)", type);
+ break;
+ }
+ return sv_2mortal(newSVpv(ret,len));
+}
+
+
+/********************************************************************/
+
+typedef PerlIO* InputStream;
+
+MODULE = Digest::MD2 PACKAGE = Digest::MD2
+
+PROTOTYPES: DISABLE
+
+void
+new(xclass)
+ SV* xclass
+ PREINIT:
+ MD2_CTX* context;
+ PPCODE:
+ if (!SvROK(xclass)) {
+ STRLEN my_na;
+ char *sclass = SvPV(xclass, my_na);
+ New(55, context, 1, MD2_CTX);
+ ST(0) = sv_newmortal();
+ sv_setref_pv(ST(0), sclass, (void*)context);
+ SvREADONLY_on(SvRV(ST(0)));
+ } else {
+ context = get_md2_ctx(xclass);
+ }
+ MD2Init(context);
+ XSRETURN(1);
+
+void
+DESTROY(context)
+ MD2_CTX* context
+ CODE:
+ Safefree(context);
+
+void
+add(self, ...)
+ SV* self
+ PREINIT:
+ MD2_CTX* context = get_md2_ctx(self);
+ int i;
+ unsigned char *data;
+ STRLEN len;
+ PPCODE:
+ for (i = 1; i < items; i++) {
+ data = (unsigned char *)(SvPV(ST(i), len));
+ MD2Update(context, data, len);
+ }
+ XSRETURN(1); /* self */
+
+void
+addfile(self, fh)
+ SV* self
+ InputStream fh
+ PREINIT:
+ MD2_CTX* context = get_md2_ctx(self);
+ unsigned char buffer[4096];
+ int n;
+ CODE:
+ /* Process blocks until EOF */
+ while ( (n = PerlIO_read(fh, buffer, sizeof(buffer)))) {
+ MD2Update(context, buffer, n);
+ }
+ XSRETURN(1); /* self */
+
+void
+digest(context)
+ MD2_CTX* context
+ ALIAS:
+ Digest::MD2::digest = F_BIN
+ Digest::MD2::hexdigest = F_HEX
+ Digest::MD2::b64digest = F_B64
+ PREINIT:
+ unsigned char digeststr[16];
+ PPCODE:
+ MD2Final(digeststr, context);
+ MD2Init(context); /* In case it is reused */
+ ST(0) = make_mortal_sv(digeststr, ix);
+ XSRETURN(1);
+
+void
+md2(...)
+ ALIAS:
+ Digest::MD2::md2 = F_BIN
+ Digest::MD2::md2_hex = F_HEX
+ Digest::MD2::md2_base64 = F_B64
+ PREINIT:
+ MD2_CTX ctx;
+ int i;
+ unsigned char *data;
+ STRLEN len;
+ unsigned char digeststr[16];
+ PPCODE:
+ MD2Init(&ctx);
+ for (i = 0; i < items; i++) {
+ data = (unsigned char *)(SvPV(ST(i), len));
+ MD2Update(&ctx, data, len);
+ }
+ MD2Final(digeststr, &ctx);
+ ST(0) = make_mortal_sv(digeststr, ix);
+ XSRETURN(1);
Added: trunk/orca/packages/Digest-MD5-2.07/MD2/MD2.pm
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/MD2/MD2.pm (original)
+++ trunk/orca/packages/Digest-MD5-2.07/MD2/MD2.pm Sat Jul 13 18:45:57 2002
@@ -0,0 +1,73 @@
+package Digest::MD2;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT_OK);
+
+$VERSION = '1.00'; # $Date: 1998/11/04 21:53:42 $
+
+require Exporter;
+*import = \&Exporter::import;
+ at EXPORT_OK = qw(md2 md2_hex md2_base64);
+
+require DynaLoader;
+ at ISA=qw(DynaLoader);
+Digest::MD2->bootstrap($VERSION);
+
+*reset = \&new;
+
+1;
+__END__
+
+=head1 NAME
+
+Digest::MD2 - Perl interface to the MD2 Algorithm
+
+=head1 SYNOPSIS
+
+ # Functional style
+ use Digest::MD2 qw(md2 md2_hex md2_base64);
+
+ $digest = md2($data);
+ $digest = md2_hex($data);
+ $digest = md2_base64($data);
+
+
+ # OO style
+ use Digest::MD2;
+
+ $ctx = Digest::MD2->new;
+
+ $ctx->add($data);
+ $ctx->addfile(*FILE);
+
+ $digest = $ctx->digest;
+ $digest = $ctx->hexdigest;
+ $digest = $ctx->b64digest;
+
+=head1 DESCRIPTION
+
+The C<Digest::MD2> module allows you to use the RSA Data Security
+Inc. MD2 Message Digest algorithm from within Perl programs. The
+algorithm takes as input a message of arbitrary length and produces as
+output a 128-bit "fingerprint" or "message digest" of the input.
+
+The C<Digest::MD2> programming interface is identical to the interface
+of C<Digest::MD5>.
+
+=head1 SEE ALSO
+
+L<Digest::MD5>
+
+=head1 COPYRIGHT
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+ Copyright 1998 Gisle Aas.
+ Copyright 1990-1992 RSA Data Security, Inc.
+
+=head1 AUTHOR
+
+Gisle Aas <gisle at aas.no>
+
+=cut
Added: trunk/orca/packages/Digest-MD5-2.07/t/digest.t
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/t/digest.t (original)
+++ trunk/orca/packages/Digest-MD5-2.07/t/digest.t Sat Jul 13 18:45:57 2002
@@ -0,0 +1,12 @@
+print "1..3\n";
+
+use Digest;
+
+print "not " unless Digest->MD5->add("abc")->hexdigest eq "900150983cd24fb0d6963f7d28e17f72";
+print "ok 1\n";
+
+print "not " unless Digest->MD5->add("abc")->hexdigest eq "900150983cd24fb0d6963f7d28e17f72";
+print "ok 2\n";
+
+print "not " unless Digest->new("HMAC-MD5" => "Jefe")->add("what do ya want for nothing?")->hexdigest eq "750c783e6ab0b503eaa86e310a5db738";
+print "ok 3\n";
Added: trunk/orca/packages/Digest-MD5-2.07/t/rfc2202.t
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/t/rfc2202.t (original)
+++ trunk/orca/packages/Digest-MD5-2.07/t/rfc2202.t Sat Jul 13 18:45:57 2002
@@ -0,0 +1,603 @@
+print "1..14\n";
+
+$test_case = 0;
+$algorithm = "";
+
+while (<DATA>) {
+ next if /^\s+$/; # blank lines
+ next if /^Cheng & Glenn/; # page header
+ next if /^RFC 2202/; # page header
+ chomp;
+ if (/^2\. Test Cases for/ .. /4\. Security Considerations/) {
+ if (/^\d+\. Test Cases for (\S+)/) {
+ if (defined $key) { save($key, $val); undef($key) }
+ $algorithm = $1;
+ } elsif (/^(\w+(?:-\w+)*)\s+=\s+(.*)/) {
+ save($key, $val) if defined $key;
+ $key = $1;
+ $val = $2;
+ $test_case = $val if $key eq "test_case";
+ } elsif (/^\s+(.*)/) {
+ $val .= " $1";
+ } elsif (/^4\. /) {
+ # ignore
+ } else {
+ print ">>> $_\n";
+ }
+ }
+}
+close(DATA);
+save($key, $val) if $key;
+
+sub save
+{
+ my($key,$val) = @_;
+ if ($val =~ /^0x(..) repeated (\d+) times$/) {
+ $val = chr(hex($1)) x $2;
+ } elsif ($val =~ s/^0x//) {
+ $val = pack("H*", $val);
+ } elsif ($val =~ s/^\"// && $val =~ s/\"$//) {
+ # we already did it
+ }
+ $case{$algorithm}[$test_case-1]{$key} = $val;
+}
+
+#use Data::Dumper; print Dumper(\%case);
+
+
+$testno = 0;
+
+use Digest::HMAC_MD5 qw(hmac_md5);
+print "\n# HMAC-MD5 tests\n";
+foreach (@{$case{"HMAC-MD5"}}) {
+ $testno++;
+
+ # This is a temporary workaround necessitated by a DEC
+ # compiler bug which breaks the 'x' operator. See
+ #
+ # http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/1998-12/msg01720.html
+ #
+ if ($^O eq 'dec_osf' and $] < 5.00503) {
+ require Config;
+ my $temp=\%Config::Config; # suppress a silly warning
+ if ($testno =~ /^(?:3|4|6|7)$/ and ! $Config::Config{gccversion}) {
+ print "ok $testno # skipping test on this platform\n";
+ next;
+ }
+ }
+
+ #use Data::Dumper; print Dumper($_);
+ warn unless length($_->{key}) == $_->{key_len};
+ warn unless length($_->{data}) == $_->{data_len};
+
+ my $failed;
+ # Test OO interface
+ my $hasher = Digest::HMAC_MD5->new($_->{key});
+ $hasher->add($_->{data});
+ $failed++ unless $hasher->digest eq $_->{digest};
+
+ # Test functional interface
+ $failed++ if hmac_md5($_->{data}, $_->{key}) ne $_->{digest};
+ print "not " if $failed;
+ print "ok $testno\n";
+}
+
+# Digest::SHA1 might fail if the SHA module is not installed
+eval {
+ # use Digest::HMAC_SHA1 qw(hmac_sha1);
+ require Digest::HMAC_SHA1;
+ *hmac_sha1 = \&Digest::HMAC_SHA1::hmac_sha1;
+};
+if ($@) {
+ print "\n# HMAC-SHA-1 tests skipped\n$@\n";
+ for (8..14) { print "ok $_\n"; }
+}
+else {
+
+print "\n# HMAC-SHA-1 tests\n";
+foreach (@{$case{"HMAC-SHA-1"}}) {
+ $testno++;
+ #use Data::Dumper; print Dumper($_);
+ warn unless length($_->{key}) == $_->{key_len};
+ warn unless length($_->{data}) == $_->{data_len};
+
+ my $failed;
+ # Test OO interface
+ my $hasher = Digest::HMAC_SHA1->new($_->{key});
+ $hasher->add($_->{data});
+ $failed++ unless $hasher->digest eq $_->{digest};
+
+ # Test functional interface
+ $failed++ if hmac_sha1($_->{data}, $_->{key}) ne $_->{digest};
+
+ print "not " if $failed;
+ print "ok $testno\n";
+}
+}
+
+__END__
+
+
+Network Working Group P. Cheng
+Request for Comments: 2202 IBM
+Category: Informational R. Glenn
+ NIST
+ September 1997
+
+
+ Test Cases for HMAC-MD5 and HMAC-SHA-1
+
+Status of This Memo
+
+ This memo provides information for the Internet community. This memo
+ does not specify an Internet standard of any kind. Distribution of
+ this memo is unlimited.
+
+Abstract
+
+ This document provides two sets of test cases for HMAC-MD5 and HMAC-
+ SHA-1, respectively. HMAC-MD5 and HMAC-SHA-1 are two constructs of
+ the HMAC [HMAC] message authentication function using the MD5 [MD5]
+ hash function and the SHA-1 [SHA] hash function. Both constructs are
+ used by IPSEC [OG,CG] and other protocols to authenticate messages.
+ The test cases and results provided in this document are meant to be
+ used as a conformance test for HMAC-MD5 and HMAC-SHA-1
+ implementations.
+
+1. Introduction
+
+ The general method for constructing a HMAC message authentication
+ function using a particular hash function is described in section 2
+ of [HMAC]. We will not repeat the description here. Section 5 of
+ [HMAC] also discusses truncating the output of HMAC; the rule is that
+ we should keep the more significant bits (the bits in the left,
+ assuming a network byte order (big-endian)).
+
+ In sections 2 and 3 we provide test cases for HMAC-MD5 and HMAC-SHA-
+ 1, respectively. Each case includes the key, the data, and the
+ result. The values of keys and data are either hexadecimal numbers
+ (prefixed by "0x") or ASCII character strings in double quotes. If a
+ value is an ASCII character string, then the HMAC computation for the
+ corresponding test case DOES NOT include the trailing null character
+ ('\0') in the string.
+
+
+
+
+
+
+
+
+
+Cheng & Glenn Informational [Page 1]
+
+RFC 2202 Test Cases for HMAC-MD5 and HMAC-SHA-1 September 1997
+
+
+ The C source code of the functions used to generate HMAC-SHA-1
+ results is listed in the Appendix. Note that these functions are
+ meant to be simple and easy to understand; they are not optimized in
+ any way. The C source code for computing HMAC-MD5 can be found in
+ [MD5]; or you can do a simple modification to HMAC-SHA-1 code to get
+ HMAC-MD5 code, as explained in the Appendix.
+
+ The test cases in this document are cross-verified by three
+ independent implementations, one from NIST and two from IBM Research.
+ One IBM implementation uses optimized code that is very different
+ from the code in the Appendix. An implemenation that concurs with the
+ results provided in this document should be interoperable with other
+ similar implemenations. We do not claim that such an implementation
+ is absolutely correct with respect to the HMAC definition in [HMAC].
+
+2. Test Cases for HMAC-MD5
+
+test_case = 1
+key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+key_len = 16
+data = "Hi There"
+data_len = 8
+digest = 0x9294727a3638bb1c13f48ef8158bfc9d
+
+test_case = 2
+key = "Jefe"
+key_len = 4
+data = "what do ya want for nothing?"
+data_len = 28
+digest = 0x750c783e6ab0b503eaa86e310a5db738
+
+test_case = 3
+key = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+key_len = 16
+data = 0xdd repeated 50 times
+data_len = 50
+digest = 0x56be34521d144c88dbb8c733f0e8b3f6
+
+test_case = 4
+key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819
+key_len = 25
+data = 0xcd repeated 50 times
+data_len = 50
+digest = 0x697eaf0aca3a3aea3a75164746ffaa79
+
+
+
+
+
+
+
+Cheng & Glenn Informational [Page 2]
+
+RFC 2202 Test Cases for HMAC-MD5 and HMAC-SHA-1 September 1997
+
+
+test_case = 5
+key = 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+key_len = 16
+data = "Test With Truncation"
+data_len = 20
+digest = 0x56461ef2342edc00f9bab995690efd4c
+digest-96 = 0x56461ef2342edc00f9bab995
+
+test_case = 6
+key = 0xaa repeated 80 times
+key_len = 80
+data = "Test Using Larger Than Block-Size Key - Hash Key First"
+data_len = 54
+digest = 0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd
+
+test_case = 7
+key = 0xaa repeated 80 times
+key_len = 80
+data = "Test Using Larger Than Block-Size Key and Larger
+ Than One Block-Size Data"
+data_len = 73
+digest = 0x6f630fad67cda0ee1fb1f562db3aa53e
+
+3. Test Cases for HMAC-SHA-1
+
+test_case = 1
+key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+key_len = 20
+data = "Hi There"
+data_len = 8
+digest = 0xb617318655057264e28bc0b6fb378c8ef146be00
+
+test_case = 2
+key = "Jefe"
+key_len = 4
+data = "what do ya want for nothing?"
+data_len = 28
+digest = 0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
+
+test_case = 3
+key = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+key_len = 20
+data = 0xdd repeated 50 times
+data_len = 50
+digest = 0x125d7342b9ac11cd91a39af48aa17b4f63f175d3
+
+
+
+
+
+
+Cheng & Glenn Informational [Page 3]
+
+RFC 2202 Test Cases for HMAC-MD5 and HMAC-SHA-1 September 1997
+
+
+test_case = 4
+key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819
+key_len = 25
+data = 0xcd repeated 50 times
+data_len = 50
+digest = 0x4c9007f4026250c6bc8414f9bf50c86c2d7235da
+
+test_case = 5
+key = 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+key_len = 20
+data = "Test With Truncation"
+data_len = 20
+digest = 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04
+digest-96 = 0x4c1a03424b55e07fe7f27be1
+
+test_case = 6
+key = 0xaa repeated 80 times
+key_len = 80
+data = "Test Using Larger Than Block-Size Key - Hash Key First"
+data_len = 54
+digest = 0xaa4ae5e15272d00e95705637ce8a3b55ed402112
+
+test_case = 7
+key = 0xaa repeated 80 times
+key_len = 80
+data = "Test Using Larger Than Block-Size Key and Larger
+ Than One Block-Size Data"
+data_len = 73
+digest = 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91
+
+
+
+
+Cheng & Glenn Informational [Page 4]
+
+RFC 2202 Test Cases for HMAC-MD5 and HMAC-SHA-1 September 1997
+
+
+4. Security Considerations
+
+ This docuemnt raises no security issues. Discussion on the strength
+ of the HMAC construction can be found in [HMAC].
+
+References
+
+ [HMAC] Krawczyk, H., Bellare, M., and R. Canetti,
+ "HMAC: Keyed-Hashing for Message Authentication",
+ RFC 2104, February 1997.
+
+ [MD5] Rivest, R., "The MD5 Message-Digest Algorithm",
+ RFC 1321, April 1992.
+
+ [SHA] NIST, FIPS PUB 180-1: Secure Hash Standard, April 1995.
+
+ [OG] Oehler, M., and R. Glenn,
+ "HMAC-MD5 IP Authentication with Replay Prevention",
+ RFC 2085, February 1997.
+
+ [CG] Chang, S., and R. Glenn,
+ "HMAC-SHA IP Authentication with Replay Prevention",
+ Work in Progress.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Cheng & Glenn Informational [Page 5]
+
+RFC 2202 Test Cases for HMAC-MD5 and HMAC-SHA-1 September 1997
+
+
+Authors' Addresses
+
+ Pau-Chen Cheng
+ IBM T.J. Watson Research Center
+ P.O.Box 704
+ Yorktown Heights, NY 10598
+
+ EMail: pau at watson.ibm.com
+
+
+ Robert Glenn
+ NIST
+ Building 820, Room 455
+ Gaithersburg, MD 20899
+
+ EMail: rob.glenn at nist.gov
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Cheng & Glenn Informational [Page 6]
+
+RFC 2202 Test Cases for HMAC-MD5 and HMAC-SHA-1 September 1997
+
+
+Appendix
+
+ This appendix contains the C reference code which implements HMAC-
+ SHA-1 using an existing SHA-1 library. It assumes that the SHA-1
+ library has similar API's as those of the MD5 code described in RFC
+ 1321. The code for HMAC-MD5 is similar, just replace the strings
+ "SHA" and "sha" with "MD5" and "md5". HMAC-MD5 code is also listed in
+ RFC 2104.
+
+ #ifndef SHA_DIGESTSIZE
+ #define SHA_DIGESTSIZE 20
+ #endif
+
+ #ifndef SHA_BLOCKSIZE
+ #define SHA_BLOCKSIZE 64
+ #endif
+
+ #ifndef MD5_DIGESTSIZE
+ #define MD5_DIGESTSIZE 16
+ #endif
+
+ #ifndef MD5_BLOCKSIZE
+ #define MD5_BLOCKSIZE 64
+ #endif
+
+ /* Function to print the digest */
+ void
+ pr_sha(FILE* fp, char* s, int t)
+ {
+ int i ;
+
+ fprintf(fp, "0x") ;
+ for (i = 0 ; i < t ; i++)
+ fprintf(fp, "%02x", s[i]) ;
+ fprintf(fp, "0) ;
+ }
+
+ void truncate
+ (
+ char* d1, /* data to be truncated */
+ char* d2, /* truncated data */
+ int len /* length in bytes to keep */
+ )
+ {
+ int i ;
+ for (i = 0 ; i < len ; i++) d2[i] = d1[i];
+ }
+
+
+
+
+Cheng & Glenn Informational [Page 7]
+
+RFC 2202 Test Cases for HMAC-MD5 and HMAC-SHA-1 September 1997
+
+
+ /* Function to compute the digest */
+ void
+ hmac_sha
+ (
+ char* k, /* secret key */
+ int lk, /* length of the key in bytes */
+ char* d, /* data */
+ int ld, /* length of data in bytes */
+ char* out, /* output buffer, at least "t" bytes */
+ int t
+ )
+ {
+ SHA_CTX ictx, octx ;
+ char isha[SHA_DIGESTSIZE], osha[SHA_DIGESTSIZE] ;
+ char key[SHA_DIGESTSIZE] ;
+ char buf[SHA_BLOCKSIZE] ;
+ int i ;
+
+ if (lk > SHA_BLOCKSIZE) {
+
+ SHA_CTX tctx ;
+
+ SHAInit(&tctx) ;
+ SHAUpdate(&tctx, k, lk) ;
+ SHAFinal(key, &tctx) ;
+
+ k = key ;
+ lk = SHA_DIGESTSIZE ;
+ }
+
+ /**** Inner Digest ****/
+
+ SHAInit(&ictx) ;
+
+ /* Pad the key for inner digest */
+ for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x36 ;
+ for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x36 ;
+
+ SHAUpdate(&ictx, buf, SHA_BLOCKSIZE) ;
+ SHAUpdate(&ictx, d, ld) ;
+
+ SHAFinal(isha, &ictx) ;
+
+ /**** Outter Digest ****/
+
+ SHAInit(&octx) ;
+
+ /* Pad the key for outter digest */
+
+
+
+Cheng & Glenn Informational [Page 8]
+
+RFC 2202 Test Cases for HMAC-MD5 and HMAC-SHA-1 September 1997
+
+
+ for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x5C ;
+ for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x5C ;
+
+ SHAUpdate(&octx, buf, SHA_BLOCKSIZE) ;
+ SHAUpdate(&octx, isha, SHA_DIGESTSIZE) ;
+
+ SHAFinal(osha, &octx) ;
+
+ /* truncate and print the results */
+ t = t > SHA_DIGESTSIZE ? SHA_DIGESTSIZE : t ;
+ truncate(osha, out, t) ;
+ pr_sha(stdout, out, t) ;
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Cheng & Glenn Informational [Page 9]
+
Added: trunk/orca/packages/Digest-MD5-2.07/t/files.t
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/t/files.t (original)
+++ trunk/orca/packages/Digest-MD5-2.07/t/files.t Sat Jul 13 18:45:57 2002
@@ -0,0 +1,130 @@
+print "1..5\n";
+
+use strict;
+use Digest::MD5 qw(md5 md5_hex md5_base64);
+
+#
+# This is the output of: 'md5sum Changes README MD5.pm MD5.xs rfc1321.txt'
+#
+my $EXPECT = <<EOT;
+2eb85a6e3342d3dcd4695ef65e208a9b Changes
+3bb95afbdd85db7bb46b230b81c10466 README
+4cccdccc1aab2df360757e9034fa448f MD5.pm
+0ebd4a0bd1cc9840114d811254826cdd MD5.xs
+754b9db19f79dbc4992f7166eb0f37ce rfc1321.txt
+EOT
+
+if (!(-f "README") && -f "../README") {
+ chdir("..") or die "Can't chdir: $!";
+}
+
+my $testno = 0;
+
+my $B64 = 1;
+eval { require MIME::Base64; };
+if ($@) {
+ print $@;
+ print "Will not test base64 methods\n";
+ $B64 = 0;
+}
+
+for (split /^/, $EXPECT) {
+ my($md5hex, $file) = split ' ';
+ my $md5bin = pack("H*", $md5hex);
+ my $md5b64;
+ if ($B64) {
+ $md5b64 = MIME::Base64::encode($md5bin, "");
+ chop($md5b64); chop($md5b64); # remove padding
+ }
+ my $failed;
+
+ if (digest_file($file, 'digest') ne $md5bin) {
+ print "$file: Bad digest\n";
+ $failed++;
+ }
+
+ if (digest_file($file, 'hexdigest') ne $md5hex) {
+ print "$file: Bad hexdigest\n";
+ $failed++;
+ }
+
+ if ($B64 && digest_file($file, 'b64digest') ne $md5b64) {
+ print "$file: Bad b64digest\n";
+ $failed++;
+ }
+
+ my $data = cat_file($file);
+ if (md5($data) ne $md5bin) {
+ print "$file: md5() failed\n";
+ $failed++;
+ }
+ if (md5_hex($data) ne $md5hex) {
+ print "$file: md5_hex() failed\n";
+ $failed++;
+ }
+ if ($B64 && md5_base64($data) ne $md5b64) {
+ print "$file: md5_base64() failed\n";
+ $failed++;
+ }
+
+ if (Digest::MD5->new->add($data)->digest ne $md5bin) {
+ print "$file: MD5->new->add(...)->digest failed\n";
+ $failed++;
+ }
+ if (Digest::MD5->new->add($data)->hexdigest ne $md5hex) {
+ print "$file: MD5->new->add(...)->hexdigest failed\n";
+ $failed++;
+ }
+ if ($B64 && Digest::MD5->new->add($data)->b64digest ne $md5b64) {
+ print "$file: MD5->new->add(...)->b64digest failed\n";
+ $failed++;
+ }
+
+ my @data = split //, $data;
+ if (md5(@data) ne $md5bin) {
+ print "$file: md5(\@data) failed\n";
+ $failed++;
+ }
+ if (Digest::MD5->new->add(@data)->digest ne $md5bin) {
+ print "$file: MD5->new->add(\@data)->digest failed\n";
+ $failed++;
+ }
+ my $md5 = Digest::MD5->new;
+ for (@data) {
+ $md5->add($_);
+ }
+ if ($md5->digest ne $md5bin) {
+ print "$file: $md5->add()-loop failed\n";
+ $failed++;
+ }
+
+ print "not " if $failed;
+ print "ok ", ++$testno, "\n";
+}
+
+
+sub digest_file
+{
+ my($file, $method) = @_;
+ $method ||= "digest";
+ #print "$file $method\n";
+
+ open(FILE, $file) or die "Can't open $file: $!";
+ binmode(FILE);
+ my $digest = Digest::MD5->new->addfile(*FILE)->$method();
+ close(FILE);
+
+ $digest;
+}
+
+sub cat_file
+{
+ my($file) = @_;
+ local $/; # slurp
+ open(FILE, $file) or die "Can't open $file: $!";
+ binmode(FILE);
+ my $tmp = <FILE>;
+ close(FILE);
+ $tmp;
+}
+
Added: trunk/orca/packages/Digest-MD5-2.07/t/md5.t
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/t/md5.t (original)
+++ trunk/orca/packages/Digest-MD5-2.07/t/md5.t Sat Jul 13 18:45:57 2002
@@ -0,0 +1,173 @@
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN {print "1..14\n";}
+END {print "not ok 1\n" unless $loaded;}
+use MD5;
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
+package MD5Test;
+
+# 2: Constructor
+
+print (($md5 = new MD5) ? "ok 2\n" : "not ok 2\n");
+
+# 3: Basic test data as defined in RFC 1321
+
+%data = (
+ "" => "d41d8cd98f00b204e9800998ecf8427e",
+ "a" => "0cc175b9c0f1b6a831c399e269772661",
+ "abc" => "900150983cd24fb0d6963f7d28e17f72",
+ "message digest"
+ => "f96b697d7cb7938d525a2f31aaf161d0",
+ "abcdefghijklmnopqrstuvwxyz"
+ => "c3fcd3d76192e4007dfb496cca67e13b",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+ => "d174ab98d277d9f5a5611c2c9f419d9f",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ => "57edf4a22be3c955ac49da2e2107b67a",
+);
+
+$failed = 0;
+foreach (sort(keys(%data)))
+{
+ $md5->reset;
+ $md5->add($_);
+ $digest = $md5->digest;
+ $hex = unpack("H*", $digest);
+ if ($hex ne $data{$_}) {
+ print STDERR "\$md5->digest: $_\n";
+ print STDERR "expected: $data{$_}\n",
+ "got : $hex\n";
+ $failed++;
+ }
+
+ if (Digest::MD5::md5($_) ne $digest) {
+ print STDERR "md5($_) failed\n";
+ $failed++;
+ }
+
+ if (Digest::MD5::md5_hex($_) ne $hex) {
+ print STDERR "md5_hex($_) failed\n";
+ $failed++;
+ }
+
+ # same stuff ending with $md5->hexdigest instead
+ $md5->reset;
+ $md5->add($_);
+ $hex = $md5->hexdigest;
+ if ($hex ne $data{$_}) {
+ print STDERR "\$md5->hexdigest: $_\n";
+ print STDERR "expected: $data{$_}\n",
+ "got : $hex\n";
+ $failed++;
+ }
+}
+print ($failed ? "not ok 3\n" : "ok 3\n");
+
+# 4: Various flavours of file-handle to addfile
+
+open(F, "<$0");
+
+$md5->reset;
+
+$md5->addfile(F);
+$hex = $md5->hexdigest;
+print ($hex ne '' ? "ok 4\n" : "not ok 4\n");
+
+$orig = $hex;
+
+# 5: Fully qualified with ' operator
+
+seek(F, 0, 0);
+$md5->reset;
+$md5->addfile(MD5Test'F);
+$hex = $md5->hexdigest;
+print ($hex eq $orig ? "ok 5\n" : "not ok 5\n");
+
+# 6: Fully qualified with :: operator
+
+seek(F, 0, 0);
+$md5->reset;
+$md5->addfile(MD5Test::F);
+$hex = $md5->hexdigest;
+print ($hex eq $orig ? "ok 6\n" : "not ok 6\n");
+
+# 7: Type glob
+
+seek(F, 0, 0);
+$md5->reset;
+$md5->addfile(*F);
+$hex = $md5->hexdigest;
+print ($hex eq $orig ? "ok 7\n" : "not ok 7\n");
+
+# 8: Type glob reference (the prefered mechanism)
+
+seek(F, 0, 0);
+$md5->reset;
+$md5->addfile(\*F);
+$hex = $md5->hexdigest;
+print ($hex eq $orig ? "ok 8\n" : "not ok 8\n");
+
+# 9: File-handle passed by name (really the same as 6)
+
+seek(F, 0, 0);
+$md5->reset;
+$md5->addfile("MD5Test::F");
+$hex = $md5->hexdigest;
+print ($hex eq $orig ? "ok 9\n" : "not ok 9\n");
+
+# 10: Other ways of reading the data -- line at a time
+
+seek(F, 0, 0);
+$md5->reset;
+while (<F>)
+{
+ $md5->add($_);
+}
+$hex = $md5->hexdigest;
+print ($hex eq $orig ? "ok 10\n" : "not ok 10\n");
+
+# 11: Input lines as a list to add()
+
+seek(F, 0, 0);
+$md5->reset;
+$md5->add(<F>);
+$hex = $md5->hexdigest;
+print ($hex eq $orig ? "ok 11\n" : "not ok 11\n");
+
+# 12: Random chunks up to 128 bytes
+
+seek(F, 0, 0);
+$md5->reset;
+while (read(F, $hexata, (rand % 128) + 1))
+{
+ $md5->add($hexata);
+}
+$hex = $md5->hexdigest;
+print ($hex eq $orig ? "ok 12\n" : "not ok 12\n");
+
+# 13: All the data at once
+
+seek(F, 0, 0);
+$md5->reset;
+undef $/;
+$data = <F>;
+$hex = $md5->hexhash($data);
+print ($hex eq $orig ? "ok 13\n" : "not ok 13\n");
+
+close(F);
+
+# 14: Using static member function
+
+$hex = MD5->hexhash($data);
+print ($hex eq $orig ? "ok 14\n" : "not ok 14\n");
Added: trunk/orca/packages/Digest-MD5-2.07/t/md5-aaa.t
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/t/md5-aaa.t (original)
+++ trunk/orca/packages/Digest-MD5-2.07/t/md5-aaa.t Sat Jul 13 18:45:57 2002
@@ -0,0 +1,282 @@
+use strict;
+print "1..256\n";
+
+use Digest::MD5 qw(md5_hex);
+
+my $testno = 0;
+while (<DATA>) {
+ my($hexdigest, $message) = split;
+ $message =~ s/\"//g;
+
+ my $failed;
+ $failed++ unless md5_hex($message) eq $hexdigest;
+ $failed++ unless Digest::MD5->new->add(split(//, $message))->digest
+ eq pack("H*", $hexdigest);
+
+ print "not " if $failed;
+ print "ok ", ++$testno, "\n";
+}
+
+
+
+# This data was generated with:
+#
+# perl -e 'for (1..256) { system("md5sum --string=" . ("a" x $_)); }'
+#
+__END__
+0cc175b9c0f1b6a831c399e269772661 "a"
+4124bc0a9335c27f086f24ba207a4912 "aa"
+47bce5c74f589f4867dbd57e9ca9f808 "aaa"
+74b87337454200d4d33f80c4663dc5e5 "aaaa"
+594f803b380a41396ed63dca39503542 "aaaaa"
+0b4e7a0e5fe84ad35fb5f95b9ceeac79 "aaaaaa"
+5d793fc5b00a2348c3fb9ab59e5ca98a "aaaaaaa"
+3dbe00a167653a1aaee01d93e77e730e "aaaaaaaa"
+552e6a97297c53e592208cf97fbb3b60 "aaaaaaaaa"
+e09c80c42fda55f9d992e59ca6b3307d "aaaaaaaaaa"
+d57f21e6a273781dbf8b7657940f3b03 "aaaaaaaaaaa"
+45e4812014d83dde5666ebdf5a8ed1ed "aaaaaaaaaaaa"
+c162de19c4c3731ca3428769d0cd593d "aaaaaaaaaaaaa"
+451599a5f9afa91a0f2097040a796f3d "aaaaaaaaaaaaaa"
+12f9cf6998d52dbe773b06f848bb3608 "aaaaaaaaaaaaaaa"
+23ca472302f49b3ea5592b146a312da0 "aaaaaaaaaaaaaaaa"
+88e42e96cc71151b6e1938a1699b0a27 "aaaaaaaaaaaaaaaaa"
+2c60c24e7087e18e45055a33f9a5be91 "aaaaaaaaaaaaaaaaaa"
+639d76897485360b3147e66e0a8a3d6c "aaaaaaaaaaaaaaaaaaa"
+22d42eb002cefa81e9ad604ea57bc01d "aaaaaaaaaaaaaaaaaaaa"
+bd049f221af82804c5a2826809337c9b "aaaaaaaaaaaaaaaaaaaaa"
+ff49cfac3968dbce26ebe7d4823e58bd "aaaaaaaaaaaaaaaaaaaaaa"
+d95dbfee231e34cccb8c04444412ed7d "aaaaaaaaaaaaaaaaaaaaaaa"
+40edae4bad0e5bf6d6c2dc5615a86afb "aaaaaaaaaaaaaaaaaaaaaaaa"
+a5a8bfa3962f49330227955e24a2e67c "aaaaaaaaaaaaaaaaaaaaaaaaa"
+ae791f19bdf77357ff10bb6b0e97e121 "aaaaaaaaaaaaaaaaaaaaaaaaaa"
+aaab9c59a88bf0bdfcb170546c5459d6 "aaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b0f0545856af1a340acdedce23c54b97 "aaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f7ce3d7d44f3342107d884bfa90c966a "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+59e794d45697b360e18ba972bada0123 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3b0845db57c200be6052466f87b2198a "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5eca9bd3eb07c006cd43ae48dfde7fd3 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b4f13cb081e412f44e99742cb128a1a5 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4c660346451b8cf91ef50f4634458d41 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+11db24dc3f6c2145701db08625dd6d76 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+80dad3aad8584778352c68ab06250327 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+1227fe415e79db47285cb2689c93963f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8e084f489f1bdf08c39f98ff6447ce6d "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+08b2f2b0864bac1ba1585043362cbec9 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4697843037d962f62a5a429e611e0f5f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+10c4da18575c092b486f8ab96c01c02f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+af205d729450b663f48b11d839a1c8df "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0d3f91798fac6ee279ec2485b25f1124 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4c3c7c067634daec9716a80ea886d123 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d1e358e6e3b707282cdd06e919f7e08c "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8c6ded4f0af86e0a7e301f8a716c4363 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4c2d8bcb02d982d7cb77f649c0a2dea8 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+bdb662f765cd310f2a547cab1cfecef6 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+08ff5f7301d30200ab89169f6afdb7af "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+6eb6a030bcce166534b95bc2ab45d9cf "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+1bb77918e5695c944be02c16ae29b25e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b6fe77c19f0f0f4946c761d62585bfea "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e9e7e260dce84ffa6e0e7eb5fd9d37fc "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+eced9e0b81ef2bba605cbc5e2e76a1d0 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ef1772b6dff9a122358552954ad0df65 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3b0c8ac703f828b04c6c197006d17218 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+652b906d60af96844ebd21b674f35e93 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+dc2f2f2462a0d72358b2f99389458606 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+762fc2665994b217c52c3c2eb7d9f406 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+cc7ed669cf88f201c3297c6a91e1d18d "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+cced11f7bbbffea2f718903216643648 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+24612f0ce2c9d2cf2b022ef1e027a54f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b06521f39153d618550606be297466d5 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+014842d480b571495a4a0363793f7367 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+c743a45e0d2e6a95cb859adae0248435 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+def5d97e01e1219fb2fc8da6c4d6ba2f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+92cb737f8687ccb93022fdb411a77cca "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a0d1395c7fb36247bfe2d49376d9d133 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ab75504250558b788f99d1ebd219abf2 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0f5c6c4e740bfcc08c3c26ccb2673d46 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+cddd19bec7f310d8c87149ef47a1828f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+96b39b8b95e016c79d104d83395b8133 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f1fc0b14ff8fa674b02344577e23eeb1 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0e8d28a1cafa3ffcff22afd480cce7d8 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+448539ffc17e1e81005b65581855cef4 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+61e39aae7c53e6e77db2e4405d9fb157 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+618a426895ee6133a372bebd1129b63e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+046c90690c9e36578b9d4a7e1d249c75 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+aadab38075c43296ee7e12466ebb03e3 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b15af9cdabbaea0516866a33d8fd0f98 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+986e6938ed767a8ae9530eef54bfe5f1 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7ae25a72b71a42ccbc5477fd989cd512 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+98d34e50d4aa7a893cc7919a91acb0e3 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3fc53fc22ea40f1a0afd78fc2cd9aa0f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+923e37c738b9d7b1526f70b65229cc3d "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b3966b7a08e5d46fd0774b797ba78dc2 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f50c7286b540bb181db1d6e05a51a296 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4efd6c8826e65a61f82af954d431b59b "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ef1031e79e7a15a4470a5e98b23781b5 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+067876bfd0df0f4c5002780ec85e6f8c "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+789851dfa4c03563e9cef5f7bc050a7e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+baf934720818ee49477e74fc644faa5e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+9a0ea77ca26d2c121ddcc179edb76308 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+20c825561572e33d026f99ddfd999538 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+464c461455c5a927079a13609c20b637 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+cf37d42f89b6adb0e1a9e99104501b82 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d266af45e3d06b70d9f52e2df4344186 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f8b59fa22eb0ba944e2b7aa24d67b681 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0918d7c2f9062743450a86eae9dde1a3 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+36a92cc94a9e0fa21f625f8bfb007adf "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+681d73898dad5685d48b5e8438bc3a66 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+337ccef058459c3c16411381778da0c4 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+6ccdfcc742862036ce07583633c5f77e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ddfa1adc974649dc5b414be86def7457 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+650ebc28ad85f11aa4b63b6ee565b89d "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e4571793bcaba284017eeabd8df85697 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4fc040d354ad9ba5e4f62862109d3e17 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+25814274e02aa7cc03d6314eb703e655 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+11378ecaee0089c840d26352704027e3 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+86f950bfcd824d5546da01c40576db31 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+089f243d1e831c5879aa375ee364a06e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+9146ef3527c7cfcc66dc615c3986e391 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d727cfdfc9ed0347e6917a68b982f7bc "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+da8f45e1fdc12deecfe56aeb5288796e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+29cfcf52d8250a253a535cf7989c7bd2 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0f6eb555b8e3c35411eebe9348594193 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a922439f963e7e59040e4756992c6f1b "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+81f8453cf3f7e5ee5479c777e5a8d80c "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8a7bd0732ed6a28ce75f6dabc90e1613 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5f61c0ccad4cac44c75ff505e1f1e537 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f6acfca2d47c87f2b14ca038234d3614 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+269fc62c517f3d55c368152addca57e7 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+50587cb16413da779b35508018721647 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5e4a3ecfdaa4636b84a39b6a7be7c047 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+c5339dc2af6bf595580281ffb07353f6 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e51176a47347e167ed0ed766b6de1a0c "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+020406e1d05cdc2aa287641f7ae2cc39 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e510683b3f5ffe4093d021808bc6ff70 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b325dc1c6f5e7a2b7cf465b9feab7948 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e016e4ccc7fdaea56fc377600b58c4cb "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3870ec709d2fc64b255d65be3123ad69 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a92bde1f862c3fe797ecd69510bbd266 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+04daa146f3a2256fdcbf015c0f67e168 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3d13c8bf627421ccc937aa1c9ac87bf1 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+247dc7ffc545e4dda64ae12def481c4e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+2dfd4def392ee9563241b7db7eb7c346 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d11a18a4743a1a0a699d1704efb74a0d "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+55b62fabd9c77d44d86e992eeeb093e6 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+9a72cf7d0bd5ae2907c79f91837e3ced "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d3828cce1835534475029202ebd799e4 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b0bebbf0015658d4740679f263a3f01f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+02368ebf1f53bc4634211b1693021666 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+04960f7d18960e348372949e4baa9752 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+c6041e7a86d407e9402b175670519260 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+439fd4c056bec1d14acd393746f6ae59 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+81a855120e04494c5a6c874a2360fd57 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ef57bd47a964dc3aadd959c4131e64ac "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0b0ab27b16cbba267c141fe0f4ee9189 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+abccd84f340bfe4ba59095cc3d5ca6ad "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+bc620e8c15265f195c8818e2f3e3c58b "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+fdcd84c4143286f6fc70c69208acd18d "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+50e05071e773b1e9f3009a4a559ce6b2 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+9e69c7a6c1863fbba2532f09ba665bde "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+47a962111aa5187eeef3d17a278d95f2 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+c13e57e33526bc713b5a1825f92651bc "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+72b392f15593e42404b38e5c889fa75e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5327acd3278274265d44e22ccfc4042c "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+930dcac6da160b2a4c51879da76d3417 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+41292c326f926f1534ead47fe302f0a0 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+2bdecb5cf6b69a00f7832299ef2fb5a5 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8bf93e9e8a3e4396de3f211c788e177e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+eea9cb566e19d6a7f55fbae78d94ef2a "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3b8452700a829dec78397aa5c0458dd3 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7950059f699eaea1e0a1759340d7c153 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+40840c5f1de00f17a8e70d5bd4d00af2 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+80f86f6af38be9ca8e40c2dc44491a0a "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7aab2c2e72c77163e7102412dc332125 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+bfd6869ae2ee2fe2675846d341eaa67d "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7e4d976f6d552d1d5bac7e2693dc8759 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+37d9884c32abfc6f372ee899434e64ad "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e362cd83a4b49d81ac6788b7839a56fd "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+9203cbb93b25d80b9d1b75e3c6c4b0dc "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+77441eda11554ec5b915d942605f66ed "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e0fe0c02b5c9c5afe10ab9d6a3769efe "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+cc7682cf11b214e928f3df899772e789 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ade0901d347afb25ecf9df4955bb8061 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+987379587cbe8e94b7057269232ff826 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+fd44a60101b04b7ddbc2b4e9b509ca1f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+53107a7f1e6f13a2e63239b6f2bf0ef1 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0b82cdd562f26aaa2459610a7ba8cd76 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+79f12de7255e9c8c0ec9a9be45ee6210 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+92338d8de02ed7aa8b3adc9120b94e71 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8fc48efda580fce85b8705d540e8382e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+63642b027ee89938c922722650f2eb9b "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+fe54daa473502e9cc2c26dd66d564eab "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b90f3d4b7dcd8cdd8d96cb14695f4793 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3e73392e7a03bca45b67650d79a8fc63 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7fe51f2642dffbabc33eea2fcc2039ba "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+bc33790e52f99718cf920329961ee753 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+54d1e41ebac5db7886f01ab0afb65b17 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+16e2824f7a3f00ef0028994182071953 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+234c07907df5019d5f40f03936939bce "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8ea3af1d9476fa0b6c04ce4f3a336c03 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e95b69eae07d498d484afc771d1c45fc "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f22a673abbc4372544ba37b51a5f5a91 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7e6161eb1be7b06928c536fada91b7f1 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4dfe3c301e88fff67822e1cfcfece43f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+edda210ac6645fbf5815eb4c58821f6d "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+6a514de2bf1926129b08f9234cd0115e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+887f30b43b2867f4a9accceee7d16e6c "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+15936442c22dab9b685de350bfe75971 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+281a39e10bab29f1f2dead149a1f3f87 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+04d5f8a53b0eeda82d3c0ccafd02c98e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a91e6b80fe9d6db74fac76c7a67f065a "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+30334486fa9841044afb07f2573107a5 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0183c0cf15a3c2ed97d326f421b6d62c "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4dc2a01b2161653753019b5228f765f8 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+71ef2dbdec7f78005354abebbfec8d8f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a1d1cd1446c113726ba50cc86d8b6519 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ed6da79cfd13ece051c4cb7c88e80c2e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d2047852ce178d4ddb7978da3883f9c5 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+d75382e07dd096b618faeeac033eefff "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+3fb48e286d462dcc237c3335aa63ba14 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+55b959972677ea06c4d0e32f7fb2f10a "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0a479c3623cfb9745e54d3376d0b9ae2 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7825ad1ba19db7eec57d88b16936f32f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+833ccf25509cb423a4aa98accb15512d "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+cae9609b05a9782610a5a43d7cd4b8ff "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+6c303e1da7f8a3032d13fe995847a722 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+4c47143a568e30ecde86dafe3bcb0558 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+9c48f0592f504b86360cfb6de00203b3 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e1524f5686f170209366f9723880d9b0 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a96164a43a192543d40e538b9e9e4ece "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b774a4f788458a60e131d998705e4a06 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+1e97f0a7dfd3fac6ae585acdcf51a549 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b6364c77b6dd495c2a7f6b0211ac6fce "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5d22315e78df2bc4146aa66f6c405dbb "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+2a773d5b04e910612543a42deeaaaa62 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0165449ac66b086accdec3051e0b691e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+54884ba571054eae72b2a5271828a1fc "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+520fb61f8625ea916d72a54a37937bc6 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+7717f05d6e424a2c7a20ab7977b21ec8 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b64e4f62e3e14317e3a90f9ff2cde576 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+a49128259cfe50ba3bed80bbd11add7f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b10cb153b79c2e4af6a8431c265aa82d "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+2e50fee6f574241042bdfabfdd46a153 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5d5656a09b98c24edd01c530d3aad5e2 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+5ac1e1609d82274371c349d5b7875298 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+b7b40d64ffccebd78abcf522376b3aae "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8619933469d908a2d4a2d890909bea43 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+591a0ee6dccd872b46ae184eb0f9450e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+8cd256a02c8c5c1676e9220e655d9ac4 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+e48c0e2ed3e4e299a6e62e5416eb6d83 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+f30f75dce71e757ee562218c1efa0645 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+06bd7e90c0410dacb155732cf956f520 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+531a0a821a9304c215f1829b880306f1 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+93f4621c0b88499297ec3f8fbb3fb9c4 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+6af3d61e2e3ef8e189cffbea802c7e69 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+df84d21c884f99d6764d9bca4dec26e1 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+1bdbdf1c9087c796394bcda5789f7206 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+21f5b107cda33036590a19419afd7fb6 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+0eae304c738191613302fb6721ea3605 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+abed9cdef66dcec954b87124ba18c1ab "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+dfde09457e2017e31d4ecfaea010db8f "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+46bc249a5a8fc5d622cf12c42c463ae0 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+81109eec5aa1a284fb5327b10e9c16b9 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Added: trunk/orca/packages/Digest-MD5-2.07/hints/irix_6.pl
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/hints/irix_6.pl (original)
+++ trunk/orca/packages/Digest-MD5-2.07/hints/irix_6.pl Sat Jul 13 18:45:57 2002
@@ -0,0 +1,6 @@
+# The Mongoose v7.1 compiler freezes up somewhere in the optimization of
+# MD5Transform() in MD5.c with optimization -O3. This is a workaround:
+
+if ($Config{cc} =~ /64|n32/ && `$Config{cc} -version 2>&1` =~ /\s7\.1/) {
+ $self->{OPTIMIZE} = "-O1";
+}
Added: trunk/orca/packages/Digest-MD5-2.07/hints/dec_osf.pl
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/hints/dec_osf.pl (original)
+++ trunk/orca/packages/Digest-MD5-2.07/hints/dec_osf.pl Sat Jul 13 18:45:57 2002
@@ -0,0 +1,13 @@
+if ($] < 5.00503 and !$Config{gccversion}) {
+ print "
+ Because of a bug with the DEC system C compiler, some tests in
+ t/rfc2202.t will be skipped. These tests fail because the compiler
+ bug breaks Perl's 'x' operator for eight-bit characters. The
+ Digest:: modules themselves work and should be safe to install
+ anyway.
+
+ Versions of Perl after 5.005_03 will contain a workaround for the
+ bug.
+
+";
+}
Added: trunk/orca/packages/Digest-MD5-2.07/MANIFEST
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/MANIFEST (original)
+++ trunk/orca/packages/Digest-MD5-2.07/MANIFEST Sat Jul 13 18:45:57 2002
@@ -0,0 +1,36 @@
+README Guess what?
+MANIFEST This file
+MD2/MD2.pm Digest::MD2 Perl Module
+MD2/MD2.xs MD2 XS implementation
+MD2/Makefile.PL Perl Makefile builder
+MD2/rfc1319.txt The MD2 Message-Digest Algorithm
+MD2/t/md2.t Test if Digest::MD2 works
+MD2/typemap Supplementary typemap
+MD5.pm Digest::MD5 Perl Module
+hints/dec_osf.pl Workaround for DEC compiler bug
+hints/irix_6.pl Workaround for IRIX compiler bug
+lib/MD5.pm MD5 backwards compatibility stuff
+lib/Digest.pm Loading frontend
+lib/Digest/HMAC.pm HMAC implementation
+lib/Digest/HMAC_MD5.pm HMAC using MD5
+lib/Digest/HMAC_SHA1.pm HMAC using SHA-1
+MD5.xs MD5 Perl 'XS' source file
+typemap Supplementary typemap
+Makefile.PL Perl Makefile builder
+SHA1/Makefile.PL Perl Makefile builder
+SHA1/SHA1.pm Digest::SHA1 module
+SHA1/SHA1.xs SHA-1 XS implementation
+SHA1/lib/SHA.pm SHA backwards compatibility stuff
+SHA1/t/sha.t Uwe's old test
+SHA1/t/sha1.t Test if Digest::SHA1 works
+SHA1/typemap Supplementary typemap
+rfc1321.txt The MD5 Message-Digest Algorithm
+rfc2104.txt HMAC: Keyed-Hashing for Message Authentication
+t/digest.t Test Digest.pm loader
+t/files.t Check a few files.
+t/md5.t Test suite using standard Perl conventions
+t/md5-aaa.t Exercise padding code
+t/rfc2202.t Test Cases for HMAC-MD5 and HMAC-SHA-1
+Changes Version history
+examples/mddriver.pl Example driver script after mddriver.c in RFC 1321
+examples/twdigest.pl Example code to format a digest like Tripwire
Added: trunk/orca/packages/Digest-MD5-2.07/lib/Digest/HMAC_SHA1.pm
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/lib/Digest/HMAC_SHA1.pm (original)
+++ trunk/orca/packages/Digest-MD5-2.07/lib/Digest/HMAC_SHA1.pm Sat Jul 13 18:45:58 2002
@@ -0,0 +1,71 @@
+package Digest::HMAC_SHA1;
+$VERSION="1.00";
+
+use strict;
+use Digest::SHA1 qw(sha1);
+use Digest::HMAC qw(hmac);
+
+# OO interface
+use vars qw(@ISA);
+ at ISA=qw(Digest::HMAC);
+sub new
+{
+ my $class = shift;
+ $class->SUPER::new($_[0], "Digest::SHA1", 64);
+}
+
+# Functional interface
+require Exporter;
+*import = \&Exporter::import;
+use vars qw(@EXPORT_OK);
+ at EXPORT_OK=qw(hmac_sha1 hmac_sha1_hex);
+
+sub hmac_sha1
+{
+ hmac($_[0], $_[1], \&sha1, 64);
+}
+
+sub hmac_sha1_hex
+{
+ unpack("H*", &hmac_sha1)
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Digest::HMAC_SHA1 - Keyed-Hashing for Message Authentication
+
+=head1 SYNOPSIS
+
+ # Functional style
+ use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex);
+ $digest = hmac_sha1($data, $key);
+ print hmac_sha1_hex($data, $key);
+
+ # OO style
+ use Digest::HMAC_SHA1;
+ $hmac = Digest::HMAC_SHA1->new($key);
+
+ $hmac->add($data);
+ $hmac->addfile(*FILE);
+
+ $digest = $hmac->digest;
+ $digest = $hmac->hexdigest;
+ $digest = $hmac->b64digest;
+
+=head1 DESCRIPTION
+
+This module provide HMAC-SHA-1 hashing.
+
+=head1 SEE ALSO
+
+L<Digest::HMAC>, L<Digest::SHA1>, L<Digest::HMAC_MD5>
+
+=head1 AUTHOR
+
+Gisle Aas <gisle at aas.no>
+
+=cut
Added: trunk/orca/packages/Digest-MD5-2.07/lib/Digest/HMAC.pm
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/lib/Digest/HMAC.pm (original)
+++ trunk/orca/packages/Digest-MD5-2.07/lib/Digest/HMAC.pm Sat Jul 13 18:45:58 2002
@@ -0,0 +1,111 @@
+package Digest::HMAC;
+$VERSION = "1.00";
+
+use strict;
+
+# OO interface
+
+sub new
+{
+ my($class, $key, $hasher, $block_size) = @_;
+ $block_size ||= 64;
+ $key = $hasher->new->add($key)->digest if length($key) > $block_size;
+
+ my $self = bless {}, $class;
+ $self->{k_ipad} = $key ^ (chr(0x36) x $block_size);
+ $self->{k_opad} = $key ^ (chr(0x5c) x $block_size);
+ $self->{hasher} = $hasher->new->add($self->{k_ipad});
+ $self;
+}
+
+sub reset
+{
+ my $self = shift;
+ $self->{hasher}->reset->add($self->{k_ipad});
+ $self;
+}
+
+sub add { my $self = shift; $self->{hasher}->add(@_); $self; }
+sub addfile { my $self = shift; $self->{hasher}->addfile(@_); $self; }
+
+sub _digest
+{
+ my $self = shift;
+ my $inner_digest = $self->{hasher}->digest;
+ $self->{hasher}->reset->add($self->{k_opad}, $inner_digest);
+}
+
+sub digest { shift->_digest->digest; }
+sub hexdigest { shift->_digest->hexdigest; }
+sub b64digest { shift->_digest->b64digest; }
+
+
+# Functional interface
+
+require Exporter;
+*import = \&Exporter::import;
+use vars qw(@EXPORT_OK);
+ at EXPORT_OK = qw(hmac hmac_hex);
+
+sub hmac
+{
+ my($data, $key, $hash_func, $block_size) = @_;
+ $block_size ||= 64;
+ $key = &$hash_func($key) if length($key) > $block_size;
+
+ my $k_ipad = $key ^ (chr(0x36) x $block_size);
+ my $k_opad = $key ^ (chr(0x5c) x $block_size);
+
+ &$hash_func($k_opad, &$hash_func($k_ipad, $data));
+}
+
+sub hmac_hex { unpack("H*", &hmac); }
+
+1;
+
+__END__
+
+=head1 NAME
+
+Digest::HMAC - Keyed-Hashing for Message Authentication
+
+=head1 SYNOPSIS
+
+ # Functional style
+ use Digest::HMAC qw(hmac hmac_hex);
+ $digest = hmac($data, $key, \&myhash);
+ print hmac_hex($data, $key, \&myhash);
+
+ # OO style
+ use Digest::HMAC;
+ $hmac = Digest::HMAC->new($key, "Digest::MyHash");
+
+ $hmac->add($data);
+ $hmac->addfile(*FILE);
+
+ $digest = $hmac->digest;
+ $digest = $hmac->hexdigest;
+ $digest = $hmac->b64digest;
+
+=head1 DESCRIPTION
+
+HMAC is used for message integrity checks between two parties that
+share a secret key, and works in combination with some other Digest
+algorithm, usually MD5 or SHA-1. The HMAC mechanism is described in
+RFC 2104.
+
+HMAC follow the common C<Digest::> interface, but the constructor
+takes the secret key and the name of some other simple C<Digest::>
+as argument.
+
+=head1 SEE ALSO
+
+L<Digest::HMAC_MD5>, L<Digest::HMAC_SHA1>
+
+RFC 2104
+
+=head1 AUTHORS
+
+Graham Barr <gbarr at ti.com>, Gisle Aas <gisle at aas.no>
+
+=cut
Added: trunk/orca/packages/Digest-MD5-2.07/lib/Digest/HMAC_MD5.pm
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/lib/Digest/HMAC_MD5.pm (original)
+++ trunk/orca/packages/Digest-MD5-2.07/lib/Digest/HMAC_MD5.pm Sat Jul 13 18:45:58 2002
@@ -0,0 +1,71 @@
+package Digest::HMAC_MD5;
+$VERSION="1.00";
+
+use strict;
+use Digest::MD5 qw(md5);
+use Digest::HMAC qw(hmac);
+
+# OO interface
+use vars qw(@ISA);
+ at ISA=qw(Digest::HMAC);
+sub new
+{
+ my $class = shift;
+ $class->SUPER::new($_[0], "Digest::MD5", 64);
+}
+
+# Functional interface
+require Exporter;
+*import = \&Exporter::import;
+use vars qw(@EXPORT_OK);
+ at EXPORT_OK=qw(hmac_md5 hmac_md5_hex);
+
+sub hmac_md5
+{
+ hmac($_[0], $_[1], \&md5, 64);
+}
+
+sub hmac_md5_hex
+{
+ unpack("H*", &hmac_md5)
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Digest::HMAC_MD5 - Keyed-Hashing for Message Authentication
+
+=head1 SYNOPSIS
+
+ # Functional style
+ use Digest::HMAC_MD5 qw(hmac_md5 hmac_md5_hex);
+ $digest = hmac_md5($data, $key);
+ print hmac_md5_hex($data, $key);
+
+ # OO style
+ use Digest::HMAC_MD5;
+ $hmac = Digest::HMAC_MD5->new($key);
+
+ $hmac->add($data);
+ $hmac->addfile(*FILE);
+
+ $digest = $hmac->digest;
+ $digest = $hmac->hexdigest;
+ $digest = $hmac->b64digest;
+
+=head1 DESCRIPTION
+
+This module provide HMAC-MD5 hashing.
+
+=head1 SEE ALSO
+
+L<Digest::HMAC>, L<Digest::MD5>, L<Digest::HMAC_SHA1>
+
+=head1 AUTHOR
+
+Gisle Aas <gisle at aas.no>
+
+=cut
Added: trunk/orca/packages/Digest-MD5-2.07/lib/MD5.pm
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/lib/MD5.pm (original)
+++ trunk/orca/packages/Digest-MD5-2.07/lib/MD5.pm Sat Jul 13 18:45:58 2002
@@ -0,0 +1,54 @@
+package MD5; # legacy stuff
+
+use strict;
+use vars qw($VERSION @ISA);
+
+$VERSION = '2.00'; # $Date: 1998/10/23 11:19:27 $
+
+require Digest::MD5;
+ at ISA=qw(Digest::MD5);
+
+sub hash { shift->new->add(@_)->digest; }
+sub hexhash { shift->new->add(@_)->hexdigest; }
+
+1;
+__END__
+
+=head1 NAME
+
+MD5 - Perl interface to the MD5 Message-Digest Algorithm
+
+=head1 SYNOPSIS
+
+ use MD5;
+
+ $context = new MD5;
+ $context->reset();
+
+ $context->add(LIST);
+ $context->addfile(HANDLE);
+
+ $digest = $context->digest();
+ $string = $context->hexdigest();
+
+ $digest = MD5->hash(SCALAR);
+ $string = MD5->hexhash(SCALAR);
+
+=head1 DESCRIPTION
+
+The C<MD5> module is B<depreciated>. Use C<Digest::MD5> instead.
+
+The current C<MD5> module is just a wrapper around the C<Digest::MD5>
+module. It is provided so that legacy code that rely on the old
+interface get the speed benefit of the new module.
+
+In addition to the methods provided by C<Digest::MD5> this module
+provide the class methods MD5->hash() and MD5->hexhash() that
+basically do the same as the md5() and md5_hex() functions provided
+C<Digest::MD5>.
+
+=head1 SEE ALSO
+
+L<Digest::MD5>
+
+=cut
Added: trunk/orca/packages/Digest-MD5-2.07/lib/Digest.pm
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/lib/Digest.pm (original)
+++ trunk/orca/packages/Digest-MD5-2.07/lib/Digest.pm Sat Jul 13 18:45:58 2002
@@ -0,0 +1,178 @@
+package Digest;
+
+use strict;
+use vars qw($VERSION %MMAP $AUTOLOAD);
+
+$VERSION = "0.02";
+
+%MMAP = (
+ "SHA-1" => "Digest::SHA1",
+ "HMAC-MD5" => "Digest::HMAC_MD5",
+ "HMAC-SHA-1" => "Digest::HMAC_SHA1",
+);
+
+sub new
+{
+ shift; # class ignored
+ my $algorithm = shift;
+ my $class = $MMAP{$algorithm} || "Digest::$algorithm";
+ no strict 'refs';
+ unless (exists ${"$class\::"}{"VERSION"}) {
+ eval "require $class";
+ die $@ if $@;
+ }
+ $class->new(@_);
+}
+
+sub AUTOLOAD
+{
+ my $class = shift;
+ my $algorithm = substr($AUTOLOAD, rindex($AUTOLOAD, '::')+2);
+ $class->new($algorithm, @_);
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Digest:: - Modules that calculate message digests
+
+=head1 SYNOPSIS
+
+ $md2 = Digest->MD2;
+ $md5 = Digest->MD5;
+
+ $sha1 = Digest->SHA1;
+ $sha1 = Digest->new("SHA-1");
+
+ $hmac = Digest->HMAC_MD5($key);
+
+=head1 DESCRIPTION
+
+The C<Digest::> modules calculate digests, also called "fingerprints"
+or "hashes", of some data, called a message. The digest is some small
+fixed size string. The actual size depend of the algorithm used. The
+message is simply a sequence of arbitrary bytes.
+
+An important property of the digest algorithms is that the digest is
+I<likely> to change if the message change in some way. Another
+property is that digest functions are one-way functions, i.e. it
+should be I<hard> to find a message that correspond to some given
+digest. Algorithms differ in how "likely" and how "hard", as well as
+how efficient they are to compute.
+
+All C<Digest::> modules provide the same programming interface. A
+functional interface for simple use, as well as an object oriented
+interface that can handle messages of arbitrary length and which can
+read files directly.
+
+The digest can be delivered in three formats:
+
+=over 8
+
+=item I<binary>
+
+This is the most compact form, but it is not well suited for printing
+or embedding in places that can't handle arbitrary data.
+
+=item I<hex>
+
+A twice as long string of (lowercase) hexadecimal digits.
+
+=item I<base64>
+
+A string of portable printable characters. This is the base64 encoded
+representation of the digest with any trailing padding removed. The
+string will be about 30% longer than the binary version. The
+L<MIME::Base64> tells you more about this encoding.
+
+=back
+
+
+The functional interface is simply importable functions with the same
+name as the algorithm. The functions take the message as argument and
+return the digest. Example:
+
+ use Digest::MD5 qw(md5);
+ $digest = md5($message);
+
+There are also versions of the functions with "_hex" or "_base64"
+appended to the name, which returns the digest in the indicated form.
+
+=head1 OO INTERFACE
+
+The following methods are available for all C<Digest::> modules:
+
+=over 4
+
+=item $ctx = Digest->XXX($arg,...)
+
+=item $ctx = Digest->new(XXX => $arg,...)
+
+=item $ctx = Digest::XXX->new($arg,...)
+
+The constructor returns some object that encapsulate the state of the
+message-digest algorithm. You can add data to the object and finally
+ask for the digest. The "XXX" should of course be replaced by the proper
+name of the digest algorithm you want to use.
+
+The two first forms are simply syntactic sugar which automatically
+load the right module on first use. The second form allow you to use
+algorithm names which contains letters which are not legal perl
+identifiers, e.g. "SHA-1".
+
+If new() is called as a instance method (i.e. $ctx->new) it will just
+reset the state the object to the state of a newly created object. No
+new object is created in this case.
+
+=item $ctx->reset
+
+This is just an alias for $ctx->new.
+
+=item $ctx->add($data,...)
+
+The $data provided as argument are appended to the message we
+calculate the digest for. The return value is the $ctx object itself.
+
+=item $ctx->addfile($io_handle)
+
+The $io_handle is read until EOF and the content is appended to the
+message we calculate the digest for. The return value is the $ctx
+object itself.
+
+=item $ctx->digest
+
+Return the binary digest for the message.
+
+Note that the C<digest> operation is effectively a destructive,
+read-once operation. Once it has been performed, the $ctx object is
+automatically C<reset> and can be used to calculate another digest
+value.
+
+=item $ctx->hexdigest
+
+Same as $ctx->digest, but will return the digest in hexadecimal form.
+
+=item $ctx->b64digest
+
+Same as $ctx->digest, but will return the digest as a base64 encoded
+string.
+
+=back
+
+=head1 SEE ALSO
+
+L<Digest::MD5>, L<Digest::SHA1>, L<Digest::HMAC>, L<Digest::MD2>
+
+L<MIME::Base64>
+
+=head1 AUTHOR
+
+Gisle Aas <gisle at aas.no>
+
+The C<Digest::> interface is based on the interface originally
+developed by Neil Winton for his C<MD5> module.
+
+=cut
Added: trunk/orca/packages/Digest-MD5-2.07/Makefile.PL
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/Makefile.PL (original)
+++ trunk/orca/packages/Digest-MD5-2.07/Makefile.PL Sat Jul 13 18:45:58 2002
@@ -0,0 +1,118 @@
+require 5.004;
+use strict;
+use Config qw(%Config);
+use ExtUtils::MakeMaker;
+
+my @extra;
+ at extra = (DEFINE => "-DU32_ALIGNMENT_REQUIRED") unless free_u32_alignment();
+
+WriteMakefile(
+ 'NAME' => 'Digest::MD5',
+ 'VERSION_FROM' => 'MD5.pm',
+ @extra,
+ 'dist' => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
+);
+exit;
+
+#--------------
+
+
+sub free_u32_alignment
+{
+ $|=1;
+ print "Testing alignment requirements for U32... ";
+ return 1 if $^O eq 'VMS';
+
+ open(ALIGN_TEST, ">u32align.c") or die "$!";
+ print ALIGN_TEST <<'EOT'; close(ALIGN_TEST);
+/*--------------------------------------------------------------*/
+/* This program allocates a buffer of U8 (char) and then tries */
+/* to access it through a U32 pointer at every offset. The */
+/* program is expected to die with a bus error/seg fault for */
+/* machines that do not support unaligned integer read/write */
+/*--------------------------------------------------------------*/
+
+#include <stdio.h>
+#include "EXTERN.h"
+#include "perl.h"
+
+int main(int argc, char** argv, char** env)
+{
+#if BYTEORDER == 0x1234 || BYTEORDER == 0x4321
+ U8 buf[] = "\0\0\0\1\0\0\0\0";
+ U32 *up;
+ int i;
+
+ if (sizeof(U32) != 4) {
+ printf("sizeof(U32) is not 4, but %d\n", sizeof(U32));
+ exit(1);
+ }
+
+ fflush(stdout);
+
+ for (i = 0; i < 4; i++) {
+ up = (U32*)(buf + i);
+ if (! ((*up == 1 << (8*i)) || /* big-endian */
+ (*up == 1 << (8*(3-i))) /* little-endian */
+ )
+ )
+ {
+ printf("read failed (%x)\n", *up);
+ exit(2);
+ }
+ }
+
+ /* write test */
+ for (i = 0; i < 4; i++) {
+ up = (U32*)(buf + i);
+ *up = 0xBeef;
+ if (*up != 0xBeef) {
+ printf("write failed (%x)\n", *up);
+ exit(3);
+ }
+ }
+
+ printf("no restrictions\n");
+ exit(0);
+#else
+ printf("unusual byteorder, playing safe\n");
+ exit(1);
+#endif
+ return 0;
+}
+/*--------------------------------------------------------------*/
+EOT
+
+ my $cc_cmd = "$Config{cc} $Config{ccflags} -I$Config{archlibexp}/CORE";
+ my $exe = "u32align$Config{_exe}";
+ if ($^O eq 'MSWin32') {
+ $cc_cmd .= ' -DWIN32IO_IS_STDIO';
+ } else {
+ $cc_cmd .= " -o $exe";
+ }
+ my $rc;
+ $rc = system("$cc_cmd $Config{ldflags} u32align.c $Config{libs}");
+ if ($rc) {
+ print "Can't compile test program\n";
+ unlink("u32align.c", $exe, "u32align$Config{_o}");
+ return;
+ }
+
+ $rc = system("./$exe");
+ unlink("u32align.c", $exe, "u32align$Config{_o}");
+
+ return 1 unless $rc;
+
+ if ($rc > 0x80) {
+ $rc >>= 8;
+ print "Test program exit status was $rc\n";
+ } else {
+ if ($rc & 0x80) {
+ $rc &= ~0x80;
+ print "Core dump deleted\n";
+ unlink("core");
+ }
+ print "signal $rc\n";
+ }
+ return;
+}
Added: trunk/orca/packages/Digest-MD5-2.07/Changes
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/Changes (original)
+++ trunk/orca/packages/Digest-MD5-2.07/Changes Sat Jul 13 18:45:58 2002
@@ -0,0 +1,383 @@
+1999-04-26 Gisle Aas <gisle at aas.no>
+
+ Release 2.07
+
+ The Digest::SHA1 module failed on some 64-bit systems, because I
+ assumed there was a correspondence between the U32 size and
+ BYTEORDER. This version use 'unsigned long' as Uwe's original
+ SHA module did.
+
+ The module should now work better when liked statically with perl,
+ because we know use a safer module-loaded test in Digest.pm.
+
+ Assume we know the outcome of the alignment test on VMS. Patch by
+ Chuck Lane <lane at duphy4.physics.drexel.edu>
+
+
+
+1999-03-26 Gisle Aas <gisle at aas.no>
+
+ Release 2.06
+
+ Avoid LONG and BYTE types in SHA.xs as they was in conflict
+ with similar definitions in <winnt.h>.
+
+ Patch by Marko Asplund <aspa at hip.fi> to make the the alignment
+ test program link successfully with sfio-perl.
+
+ Fixed a typo in MD5.xs that might have affected 64-bit systems.
+ Spotted by Nick Ing-Simmons
+
+
+
+1999-03-15 Gisle Aas <gisle at aas.no>
+
+ Release 2.05
+
+ Included Digest::SHA1 based on Uwe Hollerbach's SHA module.
+
+
+
+1999-03-05 Gisle Aas <gisle at aas.no>
+
+ Release 2.04
+
+ Avoid the -o option when compiling alignment test program
+ for Win32 as suggested by Gurusamy Sarathy.
+
+ DEC Compiler bug workaround. Contributed by D Roland Walker
+ <walker at ncbi.nlm.nih.gov>
+
+ Having references to a local variable called "na" was not
+ very safe either. Some older versions of Perl can apparently
+ macroize this into something completely different.
+
+
+
+1999-02-27 Gisle Aas <gisle at aas.no>
+
+ Release 2.03
+
+ Patch from Christopher J. Madsen <chris_madsen at geocities.com> that
+ should help getting the u32align test program to compile with
+ Visual C++ 5 on Windows NT.
+
+ Got rid of references to PL_na.
+
+
+
+1999-01-31 Gisle Aas <gisle at aas.no>
+
+ Release 2.02
+
+ Added a hints file as workaround for an IRIX compiler bug.
+ Contributed by D Roland Walker <walker at ncbi.nlm.nih.gov>.
+
+ Note that the rfc2202 test can still fail on some DEC Alpha,
+ because of a compiler bug that affects the perl 'x' operator.
+ The Digest:: modules should work and be safe to install anyway.
+
+
+
+1998-12-18 Gisle Aas <aas at sn.no>
+
+ Release 2.01
+
+ Some casts and tweaks to make picky compilers more happy.
+
+
+
+1998-11-04 Gisle Aas <aas at sn.no>
+
+ Release 2.00.
+
+ Taken out Digest::SHA1 as this module will be provided from Uwe
+ Hollerbach later.
+
+ Some tweaks to MD2.xs and MD5.xs since "na" disappeared in
+ perl5.005_53
+
+
+
+1998-10-30 Gisle Aas <aas at sn.no>
+
+ Release 1.99_60
+
+ The 1.99_59 release introduced compilation problems for big-endian
+ systems with free U32 alignment. Bug reported, and fix suggested
+ by Paul J. Schinder <schinder at pobox.com>.
+
+
+
+1998-10-28 Gisle Aas <aas at sn.no>
+
+ Release 1.99_59
+
+ Makefile.PL will run a test program to find out if U32 values can
+ be aligned anywhere. This hopefully cures the core dumps reported
+ on Solaris and other big endian systems. Thanks to Graham Barr for
+ debugging this.
+
+
+
+1998-10-28 Gisle Aas <aas at sn.no>
+
+ Release 1.99_58
+
+ Should be very close to a 2.00 release now. Need some success
+ reports from people running on big-endian machines first I think.
+
+ Added a Digest::MD2 implementation.
+
+ Wrote Digest.pm documentation. This define the interface that all
+ Digest:: modules should provide.
+
+ Avoided some code duplication in MD5.xs
+
+ Fixed typo, that prevented Digest::SHA1::sha1_base64() from working.
+
+
+
+1998-10-27 Gisle Aas <aas at sn.no>
+
+ Release 1.99_57
+
+ Rewritten most of the MD5 C code to make it real fast (especially
+ on little-endian machines without alignment restrictions for U32).
+ Compared to MD5-1.7 we can process files 4 times as fast and we
+ digest small stuff in memory 7 times faster. I came to these
+ conclusions after these tests (gcc -O2, i586, Linux):
+
+ First tested calculation of the digest of a 31 MB file, using
+ perl -le 'print Digest::MD5->new->addfile(*STDIN)->hexdigest'
+ and similar stuff:
+
+ MD5-1.7: 21.06s
+ Digest::MD5-1.99_57: 5.23s
+ md5sum (GNU textutils): 4.90s
+
+ As you can see, we do nearly as good as the md5sum program. I
+ think the reason we don't beat md5sum is that perl always insist on
+ loading extra modules like Config.pm, Carp.pm, strict.pm, vars.pm,
+ AutoLoader.pm and DynaLoader.pm. When I simply wrapped the MD5.xs
+ hasher code in a C program I managed to process the file in 4.68s.
+
+ Then we calculated the digest of the same 6 byte sting, 20000
+ times:
+
+ MD5-1.7: 11.81s
+ Digest::MD5-1.99_57: 1.68s
+
+ Digest::MD5 benefit from making this into a plain procedure call
+ instead of a static method call.
+
+
+ Other changes in this release are:
+
+ Documentation update
+
+ Internal MD5.xs cleanup.
+
+ $md5->digest will automatically reset now.
+
+ Digest::HMAC methods add() and addfile() did not return the
+ corret object.
+
+ Added Digest.pm loading module. I am not sure this is a good idea.
+
+ Added Digest::SHA1 and Digest::HMAC_SHA1 module. The Digest::SHA1
+ module is just a wrapper around SHA.pm. I hope to get the author
+ of SHA.pm to move his module to the Digest:: category.
+
+
+
+1998-10-25 Gisle Aas <aas at sn.no>
+
+ Release 1.99_56
+
+ Fix memcpy_byteswap() function in MD5.xs. Must be careful with
+ htovl() as it might evaluate its arguments more than once.
+
+
+
+1998-10-25 Gisle Aas <aas at sn.no>
+
+ Release 1.99_55
+
+ Grahams HMAC_MD5.pm splitted into two modules. Digest::HMAC and
+ Digest::HMAC_MD5. Also provide functional interface. Documentation
+ is still lacking.
+
+ Included RFC 2202 based test for HMAC-MD5.
+
+
+
+1998-10-24 Gisle Aas <aas at sn.no>
+
+ Release 1.99_54
+
+ Included HMAC_MD5.pm, contributed by Graham Barr <gbarr at ti.com>.
+
+ I have a hard time to make up my mind :-) md5_bin() renamed back
+ to md5(). Functions are not exported by default any more.
+
+ Try to Encode/Decode with memcpy_byteswap for 32-bit big-endian
+ machines.
+
+
+
+1998-10-23 Gisle Aas <aas at sn.no>
+
+ Release 1.99_53
+
+ Renamed core module as Digest::MD5. Leave a MD5.pm stub for
+ legacy code.
+
+ The md5() function renamed as md5_bin().
+
+ The constructor, Digest::MD5->new, no longer takes any extra
+ arguments.
+
+ Added some new tests.
+
+ Updated the documentation.
+
+ $md5->b64digest implemented with same base64 encoder as md5_base64.
+
+
+
+1998-10-23 Gisle Aas <aas at sn.no>
+
+ Release 1.99_52
+
+ Patch from Graham Barr which make it work for big-endian machines
+ again.
+
+
+
+1998-10-22 Gisle Aas <aas at sn.no>
+
+ Release 1.99_51
+
+ The MD5 class is now subclassable.
+
+ The add() and addfile() methods now return $self.
+
+ The reset() method is just an alias for new().
+
+ The constructor (MD5->new) now takes optional arguments which are
+ automatically added. It means that we can now write:
+
+ MD5->new($data)->hexdigest;
+
+ New $md5->b64digest method.
+
+ New functions that are exported on request: md5, md5_hex, md5_base64
+
+ Included RFC 1321
+
+ Barely started to update the documentation.
+
+
+
+1998-10-22 Gisle Aas <aas at sn.no>
+
+ Release 1.99_50
+
+ Much better performance (more than twice as fast now). Mostly
+ because we use Copy/Zero instead of the original MD5_memcpy and
+ MD5_memset functions.
+
+ The addfile() and hexdigest() methods are now XS implemented.
+
+ All RSA functions now included in MD5.xs and made static.
+
+ Use perl's Copy/Zero.
+
+ Random cleanup, simplifications and reformatting.
+ Merged things better with the perl configuration.
+
+
+
+Neil Winton's versions below:
+
+
+*** 96/06/20 Version 1.7
+
+MD5 is now completely 64-bit clean (I hope). The basic MD5 code uses
+32-bit quantities and requires a typedef UINT4 to be defined in
+global.h. Perl configuration data (the value of BYTEORDER) is used to
+determine if unsigned longs have 4 or 8 bytes. On 64-bit platforms (eg
+DEC Alpha) then it assumes that "unsigned int" will be a 32-bit type.
+If this is incorrect then adding -DUINT4_IS_LONG to the DEFINES line in
+Makefile.PL will override this.
+
+On some machines (at least Cray that I know of) there is no 32-bit
+integer type. In this case defining TRUNCATE_UINT4 (which is done
+automatically for a Cray) will ensure that 64-bit values are masked
+down to 32 bits. I have done my best to test this but without easy
+access to a true 64-bit machine I can not totally guarantee it (unless
+anyone wants to lend me a spare Cray :-)
+
+There is one remaining limitation for 64-bit enabled processors. The
+amount of data passed to any single call to the underlying MD5
+routines is limited to (2^32 - 1) bytes -- that's 4 gigabytes. I'm
+sorry if that's a real problem for you ...
+
+And finally, a minor complilation warning (unsigned char * used with
+function having char * prototype) has also been eliminated.
+
+*** 96/04/09 Version 1.6
+
+Re-generated module framework using h2xs to pick up the latest module
+conventions for versions etc. You can now say "use MD5 1.6;" and things
+should work correctly. MD5.pod has been integrated into MD5.pm and
+CHANGES renamed to Changes. There is a fairly comprehensive test.pl
+which can be invoked via "make test". There are no functional changes
+to the MD5 routines themselves.
+
+*** 96/03/14 Version 1.5.3
+
+Fixed addfile method to accept type-glob references for the file-handle
+(eg \*STDOUT). This is more consistent with other routines and is now the
+recommended way of passing file-handles. The documentation now gives more
+examples as to how the routines might be used.
+
+*** 96/03/12 Version 1.5.2
+
+Minor fixes from Christopher J Madsen <madsen at computek.net> to provide
+support for building on OS/2 (and to work arround a perl -w bug).
+
+Remove warning about possible difference between add('foo', 'bar') and
+add('foobar'). This is not true (it may have been true in the earliest
+version of the module but is no longer the case).
+
+*** 96/03/08 Version 1.5.1
+
+Add CHANGES file to make it easier for people to figure out what has
+been going on. (Meant to do this as part of 1.5)
+
+*** 96/03/05 Version 1.5
+
+Add hash() and hexhash() methods at the suggestion/request of Gary
+Howland <gary at kampai.euronet.nl> before inclusion in a wider library
+of cryptography modules.
+
+*** 96/02/27 Version 1.4
+
+Finally fixed the pesky Solaris dynamic loading bug. All kudos to Ken
+Pizzini <kenp at spry.com>!
+
+*** 95/11/29 Version 1.3.1
+
+Add explanations of current known problems.
+
+*** 95/06/02 Version 1.3
+
+Fix problems with scope resolution in addfile() reported by
+Jean-Claude Giese <Jean-Claude.Giese at loria.fr>. Basically ARGV is
+always implicitly in package main while other filehandles aren't.
+
+*** 95/05/23 Version 1.2.1
+
+[Changes pre 1.2.1 not recorded]
Added: trunk/orca/packages/Digest-MD5-2.07/SHA1/typemap
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/SHA1/typemap (original)
+++ trunk/orca/packages/Digest-MD5-2.07/SHA1/typemap Sat Jul 13 18:45:58 2002
@@ -0,0 +1,5 @@
+SHA_INFO* T_SHA_INFO
+
+INPUT
+T_SHA_INFO
+ $var = get_sha_info($arg)
Added: trunk/orca/packages/Digest-MD5-2.07/SHA1/t/sha.t
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/SHA1/t/sha.t (original)
+++ trunk/orca/packages/Digest-MD5-2.07/SHA1/t/sha.t Sat Jul 13 18:45:58 2002
@@ -0,0 +1,48 @@
+#!/usr/local/bin/perl -w
+
+print "1..1\n";
+my $bad;
+
+use SHA qw(sha_version);
+$ver = &sha_version();
+
+sub do_test
+{
+ my ($label, $str, $expect0, $expect1, $skip_big_test) = @_;
+ my ($c, @tmp);
+ my $sha = new SHA;
+ $sha->add($str);
+ $expect = ($ver eq 'SHA-1') ? $expect1 : $expect0;
+ print "$label:\nEXPECT: $expect\n";
+ my $hexdigest = $sha->hexdigest();
+ my $hexhash = $sha->hexhash($str);
+ print "RESULT 1: $hexdigest\n";
+ print "RESULT 2: $hexhash\n";
+ $bad++ if $hexdigest ne $expect || $hexhash ne $expect;
+ unless ($skip_big_test) {
+ $sha->reset();
+ @tmp = split(//, $str);
+ foreach $c (@tmp) {
+ $sha->add($c);
+ }
+ my $hexdigest = $sha->hexdigest();
+ print "RESULT 3: $hexdigest\n";
+ $bad++ if $hexdigest ne $expect;
+ } else {
+ print "skipping RESULT 3\n";
+ }
+}
+
+print "Using digest version $ver, library version $SHA::VERSION\nIf the following results don't match, there's something wrong.\n";
+do_test("test1", "abc",
+ "0164b8a9 14cd2a5e 74c4f7ff 082c4d97 f1edf880",
+ "a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d");
+do_test("test2", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "d2516ee1 acfa5baf 33dfc1c4 71e43844 9ef134c8",
+ "84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1");
+do_test("test3", "a" x 1000000,
+ "3232affa 48628a26 653b5aaa 44541fd9 0d690603",
+ "34aa973c d4c4daa4 f61eeb2b dbad2731 6534016f", 1);
+
+print "not " if $bad;
+print "ok 1\n";
Added: trunk/orca/packages/Digest-MD5-2.07/SHA1/t/sha1.t
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/SHA1/t/sha1.t (original)
+++ trunk/orca/packages/Digest-MD5-2.07/SHA1/t/sha1.t Sat Jul 13 18:45:58 2002
@@ -0,0 +1,30 @@
+print "1..5\n";
+
+use Digest::SHA1 qw(sha1 sha1_hex sha1_base64);
+
+print "not " unless Digest::SHA1->new->add("abc")->hexdigest eq "a9993e364706816aba3e25717850c26c9cd0d89d";
+print "ok 1\n";
+
+print "not " unless sha1("abc") eq pack("H*", "a9993e364706816aba3e25717850c26c9cd0d89d");
+print "ok 2\n";
+
+print "not " unless sha1_hex("abc") eq "a9993e364706816aba3e25717850c26c9cd0d89d";
+print "ok 3\n";
+
+print "not " unless sha1_base64("abc") eq "qZk+NkcGgWq6PiVxeFDCbJzQ2J0";
+print "ok 4\n";
+
+# Test file checking from too...
+open(FILE, ">stest$$.txt") || die;
+binmode(FILE);
+for (1..512) {
+ print FILE "This is line $_\n";
+}
+close(FILE);
+
+open(FILE, "stest$$.txt") || die;
+$digest = Digest::SHA1->new->addfile(*FILE)->b64digest;
+print "$digest\nnot " unless $digest eq "1ZuIK/sQeBwqh+dIACqpnoRQUE4";
+print "ok 5\n";
+
+unlink("stest$$.txt");
Added: trunk/orca/packages/Digest-MD5-2.07/SHA1/SHA1.xs
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/SHA1/SHA1.xs (original)
+++ trunk/orca/packages/Digest-MD5-2.07/SHA1/SHA1.xs Sat Jul 13 18:45:58 2002
@@ -0,0 +1,485 @@
+/* $Id: SHA1.xs,v 1.4 1999/04/26 09:30:29 gisle Exp $ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#ifdef __cplusplus
+}
+#endif
+
+/* NIST Secure Hash Algorithm */
+/* heavily modified by Uwe Hollerbach <uh at alumni.caltech edu> */
+/* from Peter C. Gutmann's implementation as found in */
+/* Applied Cryptography by Bruce Schneier */
+/* Further modifications to include the "UNRAVEL" stuff, below */
+
+/* This code is in the public domain */
+
+/* Useful defines & typedefs */
+
+typedef unsigned long ULONG; /* 32-or-more-bit quantity */
+
+#define SHA_BLOCKSIZE 64
+#define SHA_DIGESTSIZE 20
+
+typedef struct {
+ ULONG digest[5]; /* message digest */
+ ULONG count_lo, count_hi; /* 64-bit bit count */
+ U8 data[SHA_BLOCKSIZE]; /* SHA data buffer */
+ int local; /* unprocessed amount in data */
+} SHA_INFO;
+
+
+/* UNRAVEL should be fastest & biggest */
+/* UNROLL_LOOPS should be just as big, but slightly slower */
+/* both undefined should be smallest and slowest */
+
+#define SHA_VERSION 1
+#define UNRAVEL
+/* #define UNROLL_LOOPS */
+
+/* SHA f()-functions */
+#define f1(x,y,z) ((x & y) | (~x & z))
+#define f2(x,y,z) (x ^ y ^ z)
+#define f3(x,y,z) ((x & y) | (x & z) | (y & z))
+#define f4(x,y,z) (x ^ y ^ z)
+
+/* SHA constants */
+#define CONST1 0x5a827999L
+#define CONST2 0x6ed9eba1L
+#define CONST3 0x8f1bbcdcL
+#define CONST4 0xca62c1d6L
+
+/* truncate to 32 bits -- should be a null op on 32-bit machines */
+#define T32(x) ((x) & 0xffffffffL)
+
+/* 32-bit rotate */
+#define R32(x,n) T32(((x << n) | (x >> (32 - n))))
+
+/* the generic case, for when the overall rotation is not unraveled */
+#define FG(n) \
+ T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); \
+ E = D; D = C; C = R32(B,30); B = A; A = T
+
+/* specific cases, for when the overall rotation is unraveled */
+#define FA(n) \
+ T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); B = R32(B,30)
+
+#define FB(n) \
+ E = T32(R32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n); A = R32(A,30)
+
+#define FC(n) \
+ D = T32(R32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n); T = R32(T,30)
+
+#define FD(n) \
+ C = T32(R32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n); E = R32(E,30)
+
+#define FE(n) \
+ B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30)
+
+#define FT(n) \
+ A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30)
+
+
+static void sha_transform(SHA_INFO *sha_info)
+{
+ int i;
+ U8 *dp;
+ ULONG T, A, B, C, D, E, W[80], *WP;
+
+ dp = sha_info->data;
+
+/*
+the following makes sure that at least one code block below is
+traversed or an error is reported, without the necessity for nested
+preprocessor if/else/endif blocks, which are a great pain in the
+nether regions of the anatomy...
+*/
+#undef SWAP_DONE
+
+#if BYTEORDER == 0x1234
+#define SWAP_DONE
+ for (i = 0; i < 16; ++i) {
+ T = *((ULONG *) dp);
+ dp += 4;
+ W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
+ ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
+ }
+#endif
+
+#if BYTEORDER == 0x4321
+#define SWAP_DONE
+ for (i = 0; i < 16; ++i) {
+ T = *((ULONG *) dp);
+ dp += 4;
+ W[i] = T32(T);
+ }
+#endif
+
+#if BYTEORDER == 0x12345678
+#define SWAP_DONE
+ for (i = 0; i < 16; i += 2) {
+ T = *((ULONG *) dp);
+ dp += 8;
+ W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
+ ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
+ T >>= 32;
+ W[i+1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
+ ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
+ }
+#endif
+
+#if BYTEORDER == 0x87654321
+#define SWAP_DONE
+ for (i = 0; i < 16; i += 2) {
+ T = *((ULONG *) dp);
+ dp += 8;
+ W[i] = T32(T >> 32);
+ W[i+1] = T32(T);
+ }
+#endif
+
+#ifndef SWAP_DONE
+#error Unknown byte order -- you need to add code here
+#endif /* SWAP_DONE */
+
+ for (i = 16; i < 80; ++i) {
+ W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
+#if (SHA_VERSION == 1)
+ W[i] = R32(W[i], 1);
+#endif /* SHA_VERSION */
+ }
+ A = sha_info->digest[0];
+ B = sha_info->digest[1];
+ C = sha_info->digest[2];
+ D = sha_info->digest[3];
+ E = sha_info->digest[4];
+ WP = W;
+#ifdef UNRAVEL
+ FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
+ FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
+ FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2);
+ FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2);
+ FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3);
+ FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3);
+ FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4);
+ FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4);
+ sha_info->digest[0] = T32(sha_info->digest[0] + E);
+ sha_info->digest[1] = T32(sha_info->digest[1] + T);
+ sha_info->digest[2] = T32(sha_info->digest[2] + A);
+ sha_info->digest[3] = T32(sha_info->digest[3] + B);
+ sha_info->digest[4] = T32(sha_info->digest[4] + C);
+#else /* !UNRAVEL */
+#ifdef UNROLL_LOOPS
+ FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
+ FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
+ FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
+ FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
+ FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
+ FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
+ FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
+ FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
+#else /* !UNROLL_LOOPS */
+ for (i = 0; i < 20; ++i) { FG(1); }
+ for (i = 20; i < 40; ++i) { FG(2); }
+ for (i = 40; i < 60; ++i) { FG(3); }
+ for (i = 60; i < 80; ++i) { FG(4); }
+#endif /* !UNROLL_LOOPS */
+ sha_info->digest[0] = T32(sha_info->digest[0] + A);
+ sha_info->digest[1] = T32(sha_info->digest[1] + B);
+ sha_info->digest[2] = T32(sha_info->digest[2] + C);
+ sha_info->digest[3] = T32(sha_info->digest[3] + D);
+ sha_info->digest[4] = T32(sha_info->digest[4] + E);
+#endif /* !UNRAVEL */
+}
+
+/* initialize the SHA digest */
+
+static void sha_init(SHA_INFO *sha_info)
+{
+ sha_info->digest[0] = 0x67452301L;
+ sha_info->digest[1] = 0xefcdab89L;
+ sha_info->digest[2] = 0x98badcfeL;
+ sha_info->digest[3] = 0x10325476L;
+ sha_info->digest[4] = 0xc3d2e1f0L;
+ sha_info->count_lo = 0L;
+ sha_info->count_hi = 0L;
+ sha_info->local = 0;
+}
+
+/* update the SHA digest */
+
+static void sha_update(SHA_INFO *sha_info, U8 *buffer, int count)
+{
+ int i;
+ ULONG clo;
+
+ clo = T32(sha_info->count_lo + ((ULONG) count << 3));
+ if (clo < sha_info->count_lo) {
+ ++sha_info->count_hi;
+ }
+ sha_info->count_lo = clo;
+ sha_info->count_hi += (ULONG) count >> 29;
+ if (sha_info->local) {
+ i = SHA_BLOCKSIZE - sha_info->local;
+ if (i > count) {
+ i = count;
+ }
+ memcpy(((U8 *) sha_info->data) + sha_info->local, buffer, i);
+ count -= i;
+ buffer += i;
+ sha_info->local += i;
+ if (sha_info->local == SHA_BLOCKSIZE) {
+ sha_transform(sha_info);
+ } else {
+ return;
+ }
+ }
+ while (count >= SHA_BLOCKSIZE) {
+ memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
+ buffer += SHA_BLOCKSIZE;
+ count -= SHA_BLOCKSIZE;
+ sha_transform(sha_info);
+ }
+ memcpy(sha_info->data, buffer, count);
+ sha_info->local = count;
+}
+
+/* finish computing the SHA digest */
+
+static void sha_final(unsigned char digest[20], SHA_INFO *sha_info)
+{
+ int count;
+ ULONG lo_bit_count, hi_bit_count;
+
+ lo_bit_count = sha_info->count_lo;
+ hi_bit_count = sha_info->count_hi;
+ count = (int) ((lo_bit_count >> 3) & 0x3f);
+ ((U8 *) sha_info->data)[count++] = 0x80;
+ if (count > SHA_BLOCKSIZE - 8) {
+ memset(((U8 *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
+ sha_transform(sha_info);
+ memset((U8 *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
+ } else {
+ memset(((U8 *) sha_info->data) + count, 0,
+ SHA_BLOCKSIZE - 8 - count);
+ }
+ sha_info->data[56] = (hi_bit_count >> 24) & 0xff;
+ sha_info->data[57] = (hi_bit_count >> 16) & 0xff;
+ sha_info->data[58] = (hi_bit_count >> 8) & 0xff;
+ sha_info->data[59] = (hi_bit_count >> 0) & 0xff;
+ sha_info->data[60] = (lo_bit_count >> 24) & 0xff;
+ sha_info->data[61] = (lo_bit_count >> 16) & 0xff;
+ sha_info->data[62] = (lo_bit_count >> 8) & 0xff;
+ sha_info->data[63] = (lo_bit_count >> 0) & 0xff;
+ sha_transform(sha_info);
+ digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
+ digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
+ digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
+ digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
+ digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
+ digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
+ digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
+ digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
+ digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
+ digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
+ digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
+ digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
+ digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
+ digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
+ digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
+ digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
+ digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
+ digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
+ digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
+ digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
+}
+
+
+
+
+/*----------------------------------------------------------------*/
+
+static SHA_INFO* get_sha_info(SV* sv)
+{
+ if (sv_derived_from(sv, "Digest::SHA1"))
+ return (SHA_INFO*)SvIV(SvRV(sv));
+ croak("Not a reference to a Digest::SHA1 object");
+ return (SHA_INFO*)0; /* some compilers insist on a return value */
+}
+
+
+static char* hex_20(const unsigned char* from, char* to)
+{
+ static char *hexdigits = "0123456789abcdef";
+ const unsigned char *end = from + 20;
+ char *d = to;
+
+ while (from < end) {
+ *d++ = hexdigits[(*from >> 4)];
+ *d++ = hexdigits[(*from & 0x0F)];
+ from++;
+ }
+ *d = '\0';
+ return to;
+}
+
+static char* base64_20(const unsigned char* from, char* to)
+{
+ static char* base64 =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ const unsigned char *end = from + 20;
+ unsigned char c1, c2, c3;
+ char *d = to;
+
+ while (1) {
+ c1 = *from++;
+ c2 = *from++;
+ *d++ = base64[c1>>2];
+ *d++ = base64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)];
+ if (from == end) {
+ *d++ = base64[(c2 & 0xF) << 2];
+ break;
+ }
+ c3 = *from++;
+ *d++ = base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
+ *d++ = base64[c3 & 0x3F];
+ }
+ *d = '\0';
+ return to;
+}
+
+/* Formats */
+#define F_BIN 0
+#define F_HEX 1
+#define F_B64 2
+
+static SV* make_mortal_sv(const unsigned char *src, int type)
+{
+ STRLEN len;
+ char result[41];
+ char *ret;
+
+ switch (type) {
+ case F_BIN:
+ ret = (char*)src;
+ len = 20;
+ break;
+ case F_HEX:
+ ret = hex_20(src, result);
+ len = 40;
+ break;
+ case F_B64:
+ ret = base64_20(src, result);
+ len = 27;
+ break;
+ default:
+ croak("Bad convertion type (%d)", type);
+ break;
+ }
+ return sv_2mortal(newSVpv(ret,len));
+}
+
+
+/********************************************************************/
+
+typedef PerlIO* InputStream;
+
+MODULE = Digest::SHA1 PACKAGE = Digest::SHA1
+
+PROTOTYPES: DISABLE
+
+void
+new(xclass)
+ SV* xclass
+ PREINIT:
+ SHA_INFO* context;
+ PPCODE:
+ if (!SvROK(xclass)) {
+ STRLEN my_na;
+ char *sclass = SvPV(xclass, my_na);
+ New(55, context, 1, SHA_INFO);
+ ST(0) = sv_newmortal();
+ sv_setref_pv(ST(0), sclass, (void*)context);
+ SvREADONLY_on(SvRV(ST(0)));
+ } else {
+ context = get_sha_info(xclass);
+ }
+ sha_init(context);
+ XSRETURN(1);
+
+void
+DESTROY(context)
+ SHA_INFO* context
+ CODE:
+ Safefree(context);
+
+void
+add(self, ...)
+ SV* self
+ PREINIT:
+ SHA_INFO* context = get_sha_info(self);
+ int i;
+ unsigned char *data;
+ STRLEN len;
+ PPCODE:
+ for (i = 1; i < items; i++) {
+ data = (unsigned char *)(SvPV(ST(i), len));
+ sha_update(context, data, len);
+ }
+ XSRETURN(1); /* self */
+
+void
+addfile(self, fh)
+ SV* self
+ InputStream fh
+ PREINIT:
+ SHA_INFO* context = get_sha_info(self);
+ unsigned char buffer[4096];
+ int n;
+ CODE:
+ /* Process blocks until EOF */
+ while ( (n = PerlIO_read(fh, buffer, sizeof(buffer)))) {
+ sha_update(context, buffer, n);
+ }
+ XSRETURN(1); /* self */
+
+void
+digest(context)
+ SHA_INFO* context
+ ALIAS:
+ Digest::SHA1::digest = F_BIN
+ Digest::SHA1::hexdigest = F_HEX
+ Digest::SHA1::b64digest = F_B64
+ PREINIT:
+ unsigned char digeststr[20];
+ PPCODE:
+ sha_final(digeststr, context);
+ sha_init(context); /* In case it is reused */
+ ST(0) = make_mortal_sv(digeststr, ix);
+ XSRETURN(1);
+
+void
+sha1(...)
+ ALIAS:
+ Digest::SHA1::sha1 = F_BIN
+ Digest::SHA1::sha1_hex = F_HEX
+ Digest::SHA1::sha1_base64 = F_B64
+ PREINIT:
+ SHA_INFO ctx;
+ int i;
+ unsigned char *data;
+ STRLEN len;
+ unsigned char digeststr[20];
+ PPCODE:
+ sha_init(&ctx);
+ for (i = 0; i < items; i++) {
+ data = (unsigned char *)(SvPV(ST(i), len));
+ sha_update(&ctx, data, len);
+ }
+ sha_final(digeststr, &ctx);
+ ST(0) = make_mortal_sv(digeststr, ix);
+ XSRETURN(1);
Added: trunk/orca/packages/Digest-MD5-2.07/SHA1/lib/SHA.pm
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/SHA1/lib/SHA.pm (original)
+++ trunk/orca/packages/Digest-MD5-2.07/SHA1/lib/SHA.pm Sat Jul 13 18:45:58 2002
@@ -0,0 +1,73 @@
+package SHA;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT_OK);
+
+$VERSION = '2.00'; # $Date: 1999/03/08 12:04:41 $
+
+require Digest::SHA1;
+ at ISA=qw(Digest::SHA1);
+
+require Exporter;
+*import = *Exporter::imprt;
+ at EXPORT_OK=qw(sha_version);
+
+sub hexdigest
+{
+ my $self = shift;
+ join(" ", unpack("A8 A8 A8 A8 A8", $self->SUPER::hexdigest(@_)));
+}
+
+sub hash { shift->new->add(@_)->digest; }
+sub hexhash { shift->new->add(@_)->hexdigest; }
+sub sha_version { "SHA-1"; }
+
+1;
+
+__END__
+
+=head1 NAME
+
+SHA - Perl interface to the NIST Secure Hash Algorithm
+
+=head1 SYNOPSIS
+
+ use SHA;
+
+ $version = &SHA::sha_version;
+
+ $context = new SHA;
+ $context->reset();
+
+ $context->add(LIST);
+ $context->addfile(HANDLE);
+
+ $digest = $context->digest();
+ $string = $context->hexdigest();
+
+ $digest = $context->hash($string);
+ $string = $context->hexhash($string);
+
+=head1 DESCRIPTION
+
+The C<SHA> module is B<depreciated>. Use C<Digest::SHA1> instead.
+
+The current C<SHA> module is just a wrapper around the C<Digest::SHA1>
+module. It is provided so that legacy code that rely on the old
+interface still work. This wrapper does not support the old (and
+buggy) SHA-0 algorithm.
+
+In addition to the methods provided by C<Digest::SHA1> this module
+provide the class methods SHA->hash() and SHA->hexhash() that
+basically do the same as the sha1() and sha1_hex() functions provided
+C<Digest::SHA1>.
+
+The SHA->hex* methods will insert spaces between groups of 8 hex
+characters, while the Digest::SHA1 version of the same methods will not
+do this.
+
+=head1 SEE ALSO
+
+L<Digest::SHA1>
+
+=cut
Added: trunk/orca/packages/Digest-MD5-2.07/SHA1/Makefile.PL
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/SHA1/Makefile.PL (original)
+++ trunk/orca/packages/Digest-MD5-2.07/SHA1/Makefile.PL Sat Jul 13 18:45:59 2002
@@ -0,0 +1,8 @@
+require 5.004;
+use ExtUtils::MakeMaker;
+
+WriteMakefile(
+ 'NAME' => 'Digest::SHA1',
+ 'VERSION_FROM' => 'SHA1.pm',
+ 'dist' => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
+);
Added: trunk/orca/packages/Digest-MD5-2.07/SHA1/SHA1.pm
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/SHA1/SHA1.pm (original)
+++ trunk/orca/packages/Digest-MD5-2.07/SHA1/SHA1.pm Sat Jul 13 18:45:59 2002
@@ -0,0 +1,120 @@
+package Digest::SHA1;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT_OK);
+
+$VERSION = '1.01'; # $Date: 1999/04/26 09:24:25 $
+
+require Exporter;
+*import = \&Exporter::import;
+ at EXPORT_OK = qw(sha1 sha1_hex sha1_base64);
+
+require DynaLoader;
+ at ISA=qw(DynaLoader);
+Digest::SHA1->bootstrap($VERSION);
+
+*reset = \&new;
+
+1;
+__END__
+
+=head1 NAME
+
+Digest::SHA1 - Perl interface to the SHA-1 Algorithm
+
+=head1 SYNOPSIS
+
+ # Functional style
+ use Digest::SHA1 qw(sha1 sha1_hex sha1_base64);
+
+ $digest = sha1($data);
+ $digest = sha1_hex($data);
+ $digest = sha1_base64($data);
+
+
+ # OO style
+ use Digest::SHA1;
+
+ $ctx = Digest::SHA1->new;
+
+ $ctx->add($data);
+ $ctx->addfile(*FILE);
+
+ $digest = $ctx->digest;
+ $digest = $ctx->hexdigest;
+ $digest = $ctx->b64digest;
+
+=head1 DESCRIPTION
+
+The C<Digest::SHA1> module allows you to use the NIST SHA-1 message
+digest algorithm from within Perl programs. The algorithm takes as
+input a message of arbitrary length and produces as output a 160-bit
+"fingerprint" or "message digest" of the input.
+
+The C<Digest::SHA1> module provide a procedural interface for simple
+use, as well as an object oriented interface that can handle messages
+of arbitrary length and which can read files directly.
+
+A binary digest will be 20 bytes long. A hex digest will be 40
+characters long. A base64 digest will be 27 characters long.
+
+
+=head1 FUNCTIONS
+
+The following functions can be exported from the C<Digest::SHA1>
+module. No functions are exported by default.
+
+=over 4
+
+=item sha1($data,...)
+
+This function will concatenate all arguments, calculate the SHA-1
+digest of this "message", and return it in binary form.
+
+=item sha1_hex($data,...)
+
+Same as sha1(), but will return the digest in hexadecimal form.
+
+=item sha1_base64($data,...)
+
+Same as sha1(), but will return the digest as a base64 encoded string.
+
+=back
+
+=head1 METHODS
+
+The C<Digest::SHA1> module provide the standard C<Digest> OO-interface.
+The constructor looks like this:
+
+=over 4
+
+=item $sha1 = Digest->new('SHA-1')
+
+=item $sha1 = Digest::SHA1->new
+
+The constructor returns a new C<Digest::SHA1> object which encapsulate
+the state of the SHA-1 message-digest algorithm. You can add data to
+the object and finally ask for the digest using the methods described
+in L<Digest>.
+
+=back
+
+=head1 SEE ALSO
+
+L<Digest>, L<Digest::HMAC_SHA1>, L<Digest::MD5>
+
+=head1 COPYRIGHT
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+ Copyright 1999 Gisle Aas.
+ Copyright 1997 Uwe Hollerbach.
+
+=head1 AUTHORS
+
+Peter C. Gutmann,
+Uwe Hollerbach <uh at alumni.caltech.edu>,
+Gisle Aas <gisle at aas.no>
+
+=cut
Added: trunk/orca/packages/Digest-MD5-2.07/README
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/README (original)
+++ trunk/orca/packages/Digest-MD5-2.07/README Sat Jul 13 18:45:59 2002
@@ -0,0 +1,22 @@
+Digest:: MD5, MD2, SHA1, and HMAC
+---------------------------------
+
+This is a Perl extension interface to the RSA Data Security Inc. MD5,
+MD2, as well as NIST SHA-1, Message Digest algorithms. This package
+also provide modules which calculate HMAC digests.
+
+To build the extensions, unpack this distribution somewhere, create
+the Makefile by running 'perl Makefile.PL' and do a 'make', 'make
+test', and if successful 'make install'.
+
+You will need perl version 5.004 or better to install these modules.
+Further documentation is embedded in the individual modules.
+
+Copyright 1998-1999 Gisle Aas.
+Copyright 1998 Graham Barr.
+Copyright 1997 Uwe Hollerbach.
+Copyright 1995-1996 Neil Winton.
+Copyright 1990-1992 RSA Data Security, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
Added: trunk/orca/packages/Digest-MD5-2.07/MD5.xs
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/MD5.xs (original)
+++ trunk/orca/packages/Digest-MD5-2.07/MD5.xs Sat Jul 13 18:45:59 2002
@@ -0,0 +1,611 @@
+/* $Id: MD5.xs,v 1.23 1999/03/26 13:27:49 gisle Exp $ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the same terms as Perl itself.
+ *
+ * Copyright 1998 Gisle Aas.
+ * Copyright 1995-1996 Neil Winton.
+ * Copyright 1991-1992 RSA Data Security, Inc.
+ *
+ * This code is derived from Neil Winton's MD5-1.7 Perl module, which in
+ * turn is derived from the reference implementation in RFC 1231 which
+ * comes with this message:
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD5 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#ifdef __cplusplus
+}
+#endif
+
+/*#define MD5_DEBUG /**/
+
+/* Perl does not guarantee that U32 is exactly 32 bits. Some system
+ * has no integral type with exactly 32 bits. For instance, A Cray has
+ * short, int and long all at 64 bits so we need to apply this macro
+ * to reduce U32 values to 32 bits at appropriate places. If U32
+ * really does have 32 bits then this is a no-op.
+ */
+#if BYTEORDER > 0x4321 || defined(TRUNCATE_U32)
+ #define TO32(x) ((x) & 0xFFFFffff)
+ #define TRUNC32(x) ((x) &= 0xFFFFffff)
+#else
+ #define TO32(x) (x)
+ #define TRUNC32(x) /*nothing*/
+#endif
+
+/* The MD5 algorithm is defined in terms of little endian 32-bit
+ * values. The following macros (and functions) allow us to convert
+ * between native integers and such values.
+ */
+#undef BYTESWAP
+#ifndef U32_ALIGNMENT_REQUIRED
+ #if BYTEORDER == 0x1234 /* 32-bit little endian */
+ #define BYTESWAP(x) (x) /* no-op */
+
+ #elif BYTEORDER == 0x4321 /* 32-bit big endian */
+ #define BYTESWAP(x) ((((x)&0xFF)<<24) \
+ |(((x)>>24)&0xFF) \
+ |(((x)&0x0000FF00)<<8) \
+ |(((x)&0x00FF0000)>>8) )
+ #endif
+#endif
+
+#ifndef BYTESWAP
+static void u2s(U32 u, U8* s)
+{
+ *s++ = u & 0xFF;
+ *s++ = (u >> 8) & 0xFF;
+ *s++ = (u >> 16) & 0xFF;
+ *s = (u >> 24) & 0xFF;
+}
+
+#define s2u(s,u) ((u) = (U32)(*s) | \
+ ((U32)(*(s+1)) << 8) | \
+ ((U32)(*(s+2)) << 16) | \
+ ((U32)(*(s+3)) << 24))
+#endif
+
+
+/* This stucture keeps the current state of algorithm.
+ */
+typedef struct {
+ U32 A, B, C, D; /* current digest */
+ U32 bytes_low; /* counts bytes in message */
+ U32 bytes_high; /* turn it into a 64-bit counter */
+ U8 buffer[128]; /* collect complete 64 byte blocks */
+} MD5_CTX;
+
+
+/* Padding is added at the end of the message in order to fill a
+ * complete 64 byte block (- 8 bytes for the message length). The
+ * padding is also the reason the buffer in MD5_CTX have to be
+ * 128 bytes.
+ */
+static unsigned char PADDING[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* Constants for MD5Transform routine.
+ */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & ((y) ^ (z)) ^ (z)))
+#define G(x, y, z) F(z, x, y)
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n) | ((x) >> (32-(n)))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, s, ac) \
+ (a) += F ((b), (c), (d)) + (NEXTx) + (U32)(ac); \
+ TRUNC32((a)); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ TRUNC32((a));
+
+#define GG(a, b, c, d, x, s, ac) \
+ (a) += G ((b), (c), (d)) + X[x] + (U32)(ac); \
+ TRUNC32((a)); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ TRUNC32((a));
+
+#define HH(a, b, c, d, x, s, ac) \
+ (a) += H ((b), (c), (d)) + X[x] + (U32)(ac); \
+ TRUNC32((a)); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ TRUNC32((a));
+
+#define II(a, b, c, d, x, s, ac) \
+ (a) += I ((b), (c), (d)) + X[x] + (U32)(ac); \
+ TRUNC32((a)); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ TRUNC32((a));
+
+
+static void
+MD5Init(MD5_CTX *ctx)
+{
+ /* Start state */
+ ctx->A = 0x67452301;
+ ctx->B = 0xefcdab89;
+ ctx->C = 0x98badcfe;
+ ctx->D = 0x10325476;
+
+ /* message length */
+ ctx->bytes_low = ctx->bytes_high = 0;
+}
+
+
+static void
+MD5Transform(MD5_CTX* ctx, const U8* buf, STRLEN blocks)
+{
+ static int tcount = 0;
+
+ U32 A = ctx->A;
+ U32 B = ctx->B;
+ U32 C = ctx->C;
+ U32 D = ctx->D;
+
+#ifndef U32_ALIGNMENT_REQUIRED
+ const U32 *x = (U32*)buf; /* really just type casting */
+#endif
+
+ do {
+ U32 a = A;
+ U32 b = B;
+ U32 c = C;
+ U32 d = D;
+
+#if BYTEORDER == 0x1234 && !defined(U32_ALIGNMENT_REQUIRED)
+ const U32 *X = x;
+ #define NEXTx (*x++)
+#else
+ U32 X[16]; /* converted values, used in round 2-4 */
+ U32 *uptr = X;
+ U32 tmp;
+ #ifdef BYTESWAP
+ #define NEXTx (tmp=*x++, *uptr++ = BYTESWAP(tmp))
+ #else
+ #define NEXTx (s2u(buf,tmp), buf += 4, *uptr++ = tmp)
+ #endif
+#endif
+
+#ifdef MD5_DEBUG
+ if (buf == ctx->buffer)
+ fprintf(stderr,"%5d: Transform ctx->buffer", ++tcount);
+ else
+ fprintf(stderr,"%5d: Transform %p (%d)", ++tcount, buf, blocks);
+
+ {
+ int i;
+ fprintf(stderr,"[");
+ for (i = 0; i < 16; i++) {
+ fprintf(stderr,"%x,", x[i]);
+ }
+ fprintf(stderr,"]\n");
+ }
+#endif
+
+ /* Round 1 */
+ FF (a, b, c, d, S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, 1, S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, 6, S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, 11, S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, 0, S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, 5, S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, 10, S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, 15, S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, 4, S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, 9, S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, 14, S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, 3, S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, 8, S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, 13, S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, 2, S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, 7, S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, 12, S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, 5, S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, 8, S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, 11, S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, 14, S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, 1, S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, 4, S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, 7, S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, 10, S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, 13, S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, 0, S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, 3, S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, 6, S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, 9, S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, 12, S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, 15, S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, 2, S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, 0, S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, 7, S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, 14, S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, 5, S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, 12, S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, 3, S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, 10, S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, 1, S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, 8, S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, 15, S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, 6, S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, 13, S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, 4, S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, 11, S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, 2, S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, 9, S44, 0xeb86d391); /* 64 */
+
+ A += a; TRUNC32(A);
+ B += b; TRUNC32(B);
+ C += c; TRUNC32(C);
+ D += d; TRUNC32(D);
+
+ } while (--blocks);
+ ctx->A = A;
+ ctx->B = B;
+ ctx->C = C;
+ ctx->D = D;
+}
+
+
+#ifdef MD5_DEBUG
+static char*
+ctx_dump(MD5_CTX* ctx)
+{
+ static char buf[1024];
+ sprintf(buf, "{A=%x,B=%x,C=%x,D=%x,%d,%d(%d)}",
+ ctx->A, ctx->B, ctx->C, ctx->D,
+ ctx->bytes_low, ctx->bytes_high, (ctx->bytes_low&0x3F));
+ return buf;
+}
+#endif
+
+
+static void
+MD5Update(MD5_CTX* ctx, const U8* buf, STRLEN len)
+{
+ STRLEN blocks;
+ STRLEN fill = ctx->bytes_low & 0x3F;
+
+#ifdef MD5_DEBUG
+ static int ucount = 0;
+ fprintf(stderr,"%5i: Update(%s, %p, %d)\n", ++ucount, ctx_dump(ctx),
+ buf, len);
+#endif
+
+ ctx->bytes_low += len;
+ if (ctx->bytes_low < len) /* wrap around */
+ ctx->bytes_high++;
+
+ if (fill) {
+ STRLEN missing = 64 - fill;
+ if (len < missing) {
+ Copy(buf, ctx->buffer + fill, len, U8);
+ return;
+ }
+ Copy(buf, ctx->buffer + fill, missing, U8);
+ MD5Transform(ctx, ctx->buffer, 1);
+ buf += missing;
+ len -= missing;
+ }
+
+ blocks = len >> 6;
+ if (blocks)
+ MD5Transform(ctx, buf, blocks);
+ if ( (len &= 0x3F)) {
+ Copy(buf + (blocks << 6), ctx->buffer, len, U8);
+ }
+}
+
+
+static void
+MD5Final(U8* digest, MD5_CTX *ctx)
+{
+ STRLEN fill = ctx->bytes_low & 0x3F;
+ STRLEN padlen = (fill < 56 ? 56 : 120) - fill;
+ U32 bits_low, bits_high;
+#ifdef MD5_DEBUG
+ fprintf(stderr," Final: %s\n", ctx_dump(ctx));
+#endif
+ Copy(PADDING, ctx->buffer + fill, padlen, U8);
+ fill += padlen;
+
+ bits_low = ctx->bytes_low << 3;
+ bits_high = (ctx->bytes_high << 3) | (ctx->bytes_low >> 29);
+#ifdef BYTESWAP
+ *(U32*)(ctx->buffer + fill) = BYTESWAP(bits_low); fill += 4;
+ *(U32*)(ctx->buffer + fill) = BYTESWAP(bits_high); fill += 4;
+#else
+ u2s(bits_low, ctx->buffer + fill); fill += 4;
+ u2s(bits_high, ctx->buffer + fill); fill += 4;
+#endif
+
+ MD5Transform(ctx, ctx->buffer, fill >> 6);
+#ifdef MD5_DEBUG
+ fprintf(stderr," Result: %s\n", ctx_dump(ctx));
+#endif
+
+#ifdef BYTESWAP
+ *(U32*)digest = BYTESWAP(ctx->A); digest += 4;
+ *(U32*)digest = BYTESWAP(ctx->B); digest += 4;
+ *(U32*)digest = BYTESWAP(ctx->C); digest += 4;
+ *(U32*)digest = BYTESWAP(ctx->D);
+#else
+ u2s(ctx->A, digest);
+ u2s(ctx->B, digest+4);
+ u2s(ctx->C, digest+8);
+ u2s(ctx->D, digest+12);
+#endif
+}
+
+
+static MD5_CTX* get_md5_ctx(SV* sv)
+{
+ if (sv_derived_from(sv, "Digest::MD5"))
+ return (MD5_CTX*)SvIV(SvRV(sv));
+ croak("Not a reference to a Digest::MD5 object");
+ return (MD5_CTX*)0; /* some compilers insist on a return value */
+}
+
+
+static char* hex_16(const unsigned char* from, char* to)
+{
+ static char *hexdigits = "0123456789abcdef";
+ const unsigned char *end = from + 16;
+ char *d = to;
+
+ while (from < end) {
+ *d++ = hexdigits[(*from >> 4)];
+ *d++ = hexdigits[(*from & 0x0F)];
+ from++;
+ }
+ *d = '\0';
+ return to;
+}
+
+static char* base64_16(const unsigned char* from, char* to)
+{
+ static char* base64 =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ const unsigned char *end = from + 16;
+ unsigned char c1, c2, c3;
+ char *d = to;
+
+ while (1) {
+ c1 = *from++;
+ *d++ = base64[c1>>2];
+ if (from == end) {
+ *d++ = base64[(c1 & 0x3) << 4];
+ break;
+ }
+ c2 = *from++;
+ c3 = *from++;
+ *d++ = base64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)];
+ *d++ = base64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
+ *d++ = base64[c3 & 0x3F];
+ }
+ *d = '\0';
+ return to;
+}
+
+/* Formats */
+#define F_BIN 0
+#define F_HEX 1
+#define F_B64 2
+
+static SV* make_mortal_sv(const unsigned char *src, int type)
+{
+ STRLEN len;
+ char result[33];
+ char *ret;
+
+ switch (type) {
+ case F_BIN:
+ ret = (char*)src;
+ len = 16;
+ break;
+ case F_HEX:
+ ret = hex_16(src, result);
+ len = 32;
+ break;
+ case F_B64:
+ ret = base64_16(src, result);
+ len = 22;
+ break;
+ default:
+ croak("Bad convertion type (%d)", type);
+ break;
+ }
+ return sv_2mortal(newSVpv(ret,len));
+}
+
+
+/********************************************************************/
+
+typedef PerlIO* InputStream;
+
+MODULE = Digest::MD5 PACKAGE = Digest::MD5
+
+PROTOTYPES: DISABLE
+
+void
+new(xclass)
+ SV* xclass
+ PREINIT:
+ MD5_CTX* context;
+ PPCODE:
+ if (!SvROK(xclass)) {
+ STRLEN my_na;
+ char *sclass = SvPV(xclass, my_na);
+ New(55, context, 1, MD5_CTX);
+ ST(0) = sv_newmortal();
+ sv_setref_pv(ST(0), sclass, (void*)context);
+ SvREADONLY_on(SvRV(ST(0)));
+ } else {
+ context = get_md5_ctx(xclass);
+ }
+ MD5Init(context);
+ XSRETURN(1);
+
+void
+DESTROY(context)
+ MD5_CTX* context
+ CODE:
+ Safefree(context);
+
+void
+add(self, ...)
+ SV* self
+ PREINIT:
+ MD5_CTX* context = get_md5_ctx(self);
+ int i;
+ unsigned char *data;
+ STRLEN len;
+ PPCODE:
+ for (i = 1; i < items; i++) {
+ data = (unsigned char *)(SvPV(ST(i), len));
+ MD5Update(context, data, len);
+ }
+ XSRETURN(1); /* self */
+
+void
+addfile(self, fh)
+ SV* self
+ InputStream fh
+ PREINIT:
+ MD5_CTX* context = get_md5_ctx(self);
+ STRLEN fill = context->bytes_low & 0x3F;
+ unsigned char buffer[4096];
+ int n;
+ CODE:
+ if (fill) {
+ /* The MD5Update() function is faster if it can work with
+ * complete blocks. This will fill up any buffered block
+ * first.
+ */
+ STRLEN missing = 64 - fill;
+ if ( (n = PerlIO_read(fh, buffer, missing)))
+ MD5Update(context, buffer, n);
+ else
+ XSRETURN(1); /* self */
+ }
+
+ /* Process blocks until EOF */
+ while ( (n = PerlIO_read(fh, buffer, sizeof(buffer)))) {
+ MD5Update(context, buffer, n);
+ }
+ XSRETURN(1); /* self */
+
+void
+digest(context)
+ MD5_CTX* context
+ ALIAS:
+ Digest::MD5::digest = F_BIN
+ Digest::MD5::hexdigest = F_HEX
+ Digest::MD5::b64digest = F_B64
+ PREINIT:
+ unsigned char digeststr[16];
+ PPCODE:
+ MD5Final(digeststr, context);
+ MD5Init(context); /* In case it is reused */
+ ST(0) = make_mortal_sv(digeststr, ix);
+ XSRETURN(1);
+
+void
+md5(...)
+ ALIAS:
+ Digest::MD5::md5 = F_BIN
+ Digest::MD5::md5_hex = F_HEX
+ Digest::MD5::md5_base64 = F_B64
+ PREINIT:
+ MD5_CTX ctx;
+ int i;
+ unsigned char *data;
+ STRLEN len;
+ unsigned char digeststr[16];
+ PPCODE:
+ MD5Init(&ctx);
+ for (i = 0; i < items; i++) {
+ data = (unsigned char *)(SvPV(ST(i), len));
+ MD5Update(&ctx, data, len);
+ }
+ MD5Final(digeststr, &ctx);
+ ST(0) = make_mortal_sv(digeststr, ix);
+ XSRETURN(1);
Added: trunk/orca/packages/Digest-MD5-2.07/examples/twdigest.pl
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/examples/twdigest.pl (original)
+++ trunk/orca/packages/Digest-MD5-2.07/examples/twdigest.pl Sat Jul 13 18:45:59 2002
@@ -0,0 +1,35 @@
+#!/usr/local/bin/perl
+
+use MD5;
+
+#
+# twdigest -- format MD5 digest like TripWire does
+#
+# This converts the md5->digest binary string to
+# 64-radix ascii, given the base-vector:
+# 0 - 9, A - Z, a - z, :, .
+#
+
+sub twdigest {
+ my($digest) = @_;
+ my(@chunks, $bits);
+
+ # Convert to ASCII bit-string
+ $bits = unpack("B*", $digest);
+
+ # Round up length to multiple of 6 by prepending zeros
+ $bits = ("0" x ((6 - (length($bits) % 6)) % 6)) . $bits;
+
+ # Split into 6-bit chunks
+ @chunks = grep {$_ ne ''} (split(/(.{6})/, $bits, -1));
+
+ # Convert each 6-bit value to a single character
+ foreach (@chunks)
+ {
+ $_ = pack("B8", "00" . $_);
+ tr/\000-\011\012-\043\044-\075\076\077/0-9A-Za-z:./;
+ }
+
+ # Join all of the chunks into one string
+ join('', @chunks);
+}
Added: trunk/orca/packages/Digest-MD5-2.07/examples/mddriver.pl
==============================================================================
--- trunk/orca/packages/Digest-MD5-2.07/examples/mddriver.pl (original)
+++ trunk/orca/packages/Digest-MD5-2.07/examples/mddriver.pl Sat Jul 13 18:45:59 2002
@@ -0,0 +1,69 @@
+#!/usr/local/bin/perl
+# SCCS ID @(#)mddriver.pl 1.3 95/05/01
+
+require 'getopts.pl';
+use MD5;
+sub DoTest;
+
+&Getopts('s:x');
+
+$md5 = new MD5;
+
+if (defined($opt_s))
+{
+ $md5->add($opt_s);
+ $digest = $md5->digest();
+ print("MD5(\"$opt_s\") = " . unpack("H*", $digest) . "\n");
+}
+elsif ($opt_x)
+{
+ DoTest("", "d41d8cd98f00b204e9800998ecf8427e");
+ DoTest("a", "0cc175b9c0f1b6a831c399e269772661");
+ DoTest("abc", "900150983cd24fb0d6963f7d28e17f72");
+ DoTest("message digest", "f96b697d7cb7938d525a2f31aaf161d0");
+ DoTest("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b");
+ DoTest("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "d174ab98d277d9f5a5611c2c9f419d9f");
+ DoTest("12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ "57edf4a22be3c955ac49da2e2107b67a");
+}
+else
+{
+ if ($#ARGV >= 0)
+ {
+ foreach $ARGV (@ARGV)
+ {
+ die "Can't open file '$ARGV' ($!)\n" unless open(ARGV, $ARGV);
+
+ $md5->reset();
+ $md5->addfile(ARGV);
+ $hex = $md5->hexdigest();
+ print "MD5($ARGV) = $hex\n";
+
+ close(ARGV);
+ }
+ }
+ else
+ {
+ $md5->reset();
+ $md5->addfile(STDIN);
+ $hex = $md5->hexdigest();
+
+ print "$hex\n";
+ }
+}
+
+exit 0;
+
+sub DoTest
+{
+ my ($str, $expect) = @_;
+ my ($digest, $hex);
+ my $md5 = new MD5;
+
+ $md5->add($str);
+ $digest = $md5->digest();
+ $hex = unpack("H*", $digest);
+
+ print "MD5(\"$str\") =>\nEXPECT: $expect\nRESULT: $hex\n"
+}
Added: trunk/orca/packages/rrdtool-0.99.29.1/Makefile.dist
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/Makefile.dist (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/Makefile.dist Sat Jul 13 18:45:59 2002
@@ -0,0 +1,41 @@
+SHELL = /bin/sh
+.SUFFIXES:
+.SUFFIXES: .c .o .pl .pm .pod .html .man
+
+# variables we got from configure
+# (you can mess with these, if you want)
+
+###
+### Things you might NOT want to play with ...
+###
+
+VER = 0.99.29
+PVER = 0.99029
+
+ARCHIVE = rrdtool-$(VER).tar.gz
+DIRNAME = rrdtool-$(VER)
+
+perl-piped/examples/%.pl.in: perl-piped/examples/%.pl
+ perl -p -e 's|^#!\s*/\S+perl\S* +|#! \@PERL\@ |' $< > $@
+
+perl-shared/examples/%.pl.in: perl-shared/examples/%.pl
+ perl -p -e 's|^#!\s*/\S+perl\S* +|#! \@PERL\@ |' $< > $@
+
+all: dist
+
+docs:
+ (cd doc && $(MAKE))
+versync:
+ perl -i -p -e 's|VERSION\s*=\s*[\d.]+|VERSION = $(PVER)|' perl-piped/RRDp.pm perl-shared/RRDs.pm
+ perl -i -p -e 's|RRDTOOL\s+\d+\.\d+\.\d+|RRDTOOL $(VER)|' src/*.c src/*.h
+
+tar: perl-piped/examples/piped-demo.pl.in perl-shared/examples/shared-demo.pl.in docs versync
+
+ (cd .. ; ln -s rrdtool $(DIRNAME))
+ (cd .. ; sed -e "s/^/$(DIRNAME)\//" $(DIRNAME)/MANIFEST | xargs tar zcvf $(DIRNAME)/archive/$(ARCHIVE) --exclude="*~")
+ rm ../$(DIRNAME)
+
+dist: tar
+ scp CHANGES tardis:/home/oetiker/public_html/webtools/rrdtool/pub/
+ cat archive/$(ARCHIVE) | ssh tardis dd of=/home/oetiker/public_html/webtools/rrdtool/pub/$(ARCHIVE)
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/configure
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/configure (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/configure Sat Jul 13 18:46:00 2002
@@ -0,0 +1,2138 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=src/rrd_tool.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi at caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:530: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:560: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:611: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:643: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 654 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:659: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:685: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:690: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:699: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:718: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:750: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 765 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:771: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 782 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:788: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 799 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:805: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:860: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:913: checking whether ln -s works" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+ rm -f conftestdata
+ ac_cv_prog_LN_S="ln -s"
+else
+ ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:934: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:963: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "perl", so it can be a program name with args.
+set dummy perl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:993: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$PERL" in
+ /*)
+ ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_PERL="$PERL" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_PERL="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_PERL" && ac_cv_path_PERL="no"
+ ;;
+esac
+fi
+PERL="$ac_cv_path_PERL"
+if test -n "$PERL"; then
+ echo "$ac_t""$PERL" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+echo $ac_n "checking for acos in -lm""... $ac_c" 1>&6
+echo "configure:1029: checking for acos in -lm" >&5
+ac_lib_var=`echo m'_'acos | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lm $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1037 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char acos();
+
+int main() {
+acos()
+; return 0; }
+EOF
+if { (eval echo configure:1048: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo m | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lm $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1077: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1082 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1090: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1107 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1125 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1146 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1157: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+for ac_hdr in fcntl.h malloc.h unistd.h math.h sys/time.h sys/times.h sys/resource.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1184: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1189 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1194: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:1222: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1227 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:1276: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:1297: checking whether time.h and sys/time.h may both be included" >&5
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1302 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:1311: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+ cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
+echo "configure:1332: checking whether struct tm is in sys/time.h or time.h" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1337 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <time.h>
+int main() {
+struct tm *tp; tp->tm_sec;
+; return 0; }
+EOF
+if { (eval echo configure:1345: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_tm=time.h
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_struct_tm" 1>&6
+if test $ac_cv_struct_tm = sys/time.h; then
+ cat >> confdefs.h <<\EOF
+#define TM_IN_SYS_TIME 1
+EOF
+
+fi
+
+
+if test ${CC-gcc} = gcc; then
+ rd_cv_prog_hpcc=no
+oCFLAGS_EXTRA=$CFLAGS_EXTRA
+CFLAGS_EXTRA="$CFLAGS_EXTRA -Wall -pedantic -fPIC"
+echo $ac_n "checking if we can use GCC-specific compiler options""... $ac_c" 1>&6
+echo "configure:1371: checking if we can use GCC-specific compiler options" >&5
+if eval "test \"`echo '$''{'rd_cv_gcc_opt'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+cat > conftest.$ac_ext <<EOF
+#line 1377 "configure"
+#include "confdefs.h"
+
+int main() {
+return 0
+; return 0; }
+EOF
+if { (eval echo configure:1384: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ rd_cv_gcc_opt=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ rd_cv_gcc_opt=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$rd_cv_gcc_opt" 1>&6
+if test $rd_cv_gcc_opt = no; then
+ CFLAGS_EXTRA=$oCFLAGS_EXTRA
+fi
+
+else
+echo $ac_n "checking if we should use HP compiler options""... $ac_c" 1>&6
+echo "configure:1404: checking if we should use HP compiler options" >&5
+if eval "test \"`echo '$''{'rd_cv_prog_hpcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+cat > conftest.c <<EOF
+#ifdef _HPUX_SOURCE
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -Ae -z -E conftest.c'; { (eval echo configure:1414: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1
+then
+ rd_cv_prog_hpcc=yes
+else
+ rd_cv_prog_hpcc=no
+fi
+fi
+
+echo "$ac_t""$rd_cv_prog_hpcc" 1>&6
+fi
+if test $rd_cv_prog_hpcc = yes; then
+ CFLAGS_EXTRA="$CFLAGS_EXTRA -Ae -z"
+fi
+
+echo $ac_n "checking for strftime""... $ac_c" 1>&6
+echo "configure:1429: checking for strftime" >&5
+if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1434 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char strftime(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strftime();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_strftime) || defined (__stub___strftime)
+choke me
+#else
+strftime();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1457: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_strftime=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_strftime=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'strftime`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_STRFTIME 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+# strftime is in -lintl on SCO UNIX.
+echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6
+echo "configure:1479: checking for strftime in -lintl" >&5
+ac_lib_var=`echo intl'_'strftime | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lintl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1487 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strftime();
+
+int main() {
+strftime()
+; return 0; }
+EOF
+if { (eval echo configure:1498: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_STRFTIME 1
+EOF
+
+LIBS="-lintl $LIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking for vprintf""... $ac_c" 1>&6
+echo "configure:1525: checking for vprintf" >&5
+if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1530 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char vprintf(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char vprintf();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_vprintf) || defined (__stub___vprintf)
+choke me
+#else
+vprintf();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1553: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_vprintf=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_vprintf=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'vprintf`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_VPRINTF 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test "$ac_cv_func_vprintf" != yes; then
+echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
+echo "configure:1577: checking for _doprnt" >&5
+if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1582 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char _doprnt(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _doprnt();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub__doprnt) || defined (__stub____doprnt)
+choke me
+#else
+_doprnt();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1605: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func__doprnt=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func__doprnt=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'_doprnt`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_DOPRNT 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+
+for ac_func in mktime getrusage gettimeofday
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1633: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1638 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1661: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+oCFLAGS_EXTRA=$CFLAGS_EXTRA
+echo $ac_n "checking if the compiler does proper IEEE math""... $ac_c" 1>&6
+echo "configure:1688: checking if the compiler does proper IEEE math" >&5
+if eval "test \"`echo '$''{'rd_cv_ieee_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1696 "configure"
+#include "confdefs.h"
+int main(void){
+ double a=0.0/0.0,b=0.0,c;
+ c=a/b;if (c==a) c=a;return isnan(a/c)?0:1;
+ }
+EOF
+if { (eval echo configure:1703: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ rd_cv_ieee_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+
+echo "$ac_t""no it does not" 1>&6
+CFLAGS_EXTRA="$CFLAGS_EXTRA -ieee"
+echo $ac_n "checking if the compiler does proper IEEE math with -ieee""... $ac_c" 1>&6
+echo "configure:1714: checking if the compiler does proper IEEE math with -ieee" >&5
+if eval "test \"`echo '$''{'rd_cv_ieee_switch'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1722 "configure"
+#include "confdefs.h"
+int main(void){
+ double a=0.0/0.0,b=0.0,c;
+ c=a/b;if (c==a) c=a;return isnan(a/c)?0:1;
+ }
+EOF
+if { (eval echo configure:1729: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ rd_cv_ieee_switch=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ rd_cv_ieee_switch=no;
+echo "$ac_t""nope" 1>&6
+echo "--------------------------------------------------------------"
+echo "Your Compiler does not do propper IEEE math ... "
+echo "Please find out how to make IEEE math work with your Compiler"
+echo "And let me know (oetiker at ee.ethz.ch)"
+echo ""
+exit 1
+
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$rd_cv_ieee_switch" 1>&6
+
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$rd_cv_ieee_works" 1>&6
+
+CFLAGS_EXTRA=$oCFLAGS_EXTRA
+
+if test x$rd_cv_ieee_switch = xyes; then
+ CFLAGS_EXTRA="$CFLAGS_EXTRA -ieee"
+fi
+
+
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile src/Makefile gd1.2/Makefile doc/GNUmakefile perl-shared/examples/shared-demo.pl perl-piped/examples/piped-demo.pl config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@LN_S@%$LN_S%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@RANLIB@%$RANLIB%g
+s%@PERL@%$PERL%g
+s%@CFLAGS_EXTRA@%$CFLAGS_EXTRA%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile src/Makefile gd1.2/Makefile doc/GNUmakefile perl-shared/examples/shared-demo.pl perl-piped/examples/piped-demo.pl"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+chmod +x perl-*/examples/*.pl
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+
+echo $ac_n "checking in""... $ac_c" 1>&6
+echo "configure:2134: checking in" >&5
+echo "$ac_t""and out again" 1>&6
+
+echo $ac_n "ordering CD from http://cdnow.com/gift/oetiker@ee.ethz.ch""... $ac_c" 1>&6
+sleep 3
+echo "$ac_t""just kidding ;-)" 1>&6
Added: trunk/orca/packages/rrdtool-0.99.29.1/Makefile.in
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/Makefile.in (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/Makefile.in Sat Jul 13 18:46:00 2002
@@ -0,0 +1,53 @@
+# things that the GNU standards document suggests all makefiles
+# should have.
+SHELL = /bin/sh
+ at SET_MAKE@
+INSTALL = @INSTALL@
+PREFIX = @prefix@
+CFLAGS = @CFLAGS@
+
+.SUFFIXES:
+.SUFFIXES: .c .o .pl .pm .pod .html .man
+
+all:
+ (cd gd1.2 && $(MAKE) CFLAGS="$(CFLAGS)" libgd.a)
+ (cd src && $(MAKE) CFLAGS="$(CFLAGS)")
+ $(MAKE) perl-piped perl-shared
+ (cd doc && $(MAKE))
+
+perl-piped: perl-piped/Makefile
+ (cd perl-piped && $(MAKE) OPTIMIZE="$(CFLAGS)")
+
+perl-shared: perl-shared/Makefile
+ (cd perl-shared && $(MAKE) OPTIMIZE="$(CFLAGS)")
+
+
+perl-piped/Makefile: perl-piped/Makefile.PL
+ (cd perl-piped && @PERL@ Makefile.PL)
+
+perl-shared/Makefile: perl-shared/Makefile.PL
+ (cd perl-shared && @PERL@ Makefile.PL)
+
+clean:
+ (cd gd1.2 && $(MAKE) clean)
+ (cd src && $(MAKE) clean)
+
+distclean realclean:
+ (cd gd1.2 && $(MAKE) realclean)
+ (cd src && $(MAKE) realclean)
+ @if test -f perl-shared/Makefile; then \
+ echo '(cd perl-shared; $(MAKE) clean)' ; \
+ (cd perl-shared; $(MAKE) clean); \
+ fi
+ @if test -f perl-piped/Makefile; then \
+ echo '(cd perl-piped; $(MAKE) clean)' ; \
+ (cd perl; $(MAKE) clean); \
+ fi
+ -rm -f config.cache config.h config.log config.status Makefile
+
+install: all
+ (cd perl-piped && $(MAKE) install)
+ (cd perl-shared && $(MAKE) install)
+ $(INSTALL) -m 755 -o root -g root src/rrdtool $(PREFIX)/bin
+ $(INSTALL) -m 644 -o root -g root doc/*.3 $(PREFIX)/man/man3
+ $(INSTALL) -m 644 -o root -g root doc/*.1 $(PREFIX)/man/man1
Added: trunk/orca/packages/rrdtool-0.99.29.1/configure.in
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/configure.in (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/configure.in Sat Jul 13 18:46:00 2002
@@ -0,0 +1,138 @@
+dnl This file is the master file for the configure process.
+dnl It is only edited by developers. If you are trying to compile
+dnl rrd_tool, use "sh configure" instead of this file.
+dnl
+dnl From it, config.h.in and configure are both made.
+dnl To make them, you (a developer) will need to install the latest
+dnl versions of GNU m4 and GNU autoconf. Then you run "autoheader"
+dnl in the distribution directory to make config.h.in, and
+dnl "autoconf" to make the configure script. These two files
+dnl must be shipped with the distribution; end users should not need
+dnl m4 and autoconf to be able to compile. All they need is
+dnl to run "sh configure".
+dnl
+dnl The format of this file is basically one macro to a line.
+dnl Text that is not a macro and not a comment is passed straight
+dnl through to the configure script.
+dnl
+dnl Comments are "dnl" followed by comments. It means delete
+dnl to newline.
+dnl
+dnl When you want to pass a literal bit of text to a macro as
+dnl an argument, you use square brackets. Thus, you cannot use
+dnl the bracket shorthand for /bin/test... you must use the
+dnl actual program name.
+dnl
+dnl Our tests do not cache. This is because I'm too lazy to
+dnl figure out how to use the caching macros. There's not many,
+dnl so it's not a big problem.
+dnl
+dnl -jra
+
+AC_INIT(src/rrd_tool.c)
+AC_CONFIG_HEADER(config.h)
+
+dnl Check for programs.
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+AC_PATH_PROG(PERL, perl, no)
+
+
+dnl Checks for libraries.
+AC_CHECK_LIB(m, acos)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h malloc.h unistd.h math.h sys/time.h sys/times.h sys/resource.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_HEADER_TIME
+AC_STRUCT_TM
+
+dnl If CC is not set we assume gcc
+if test ${CC-gcc} = gcc; then
+ rd_cv_prog_hpcc=no
+oCFLAGS_EXTRA=$CFLAGS_EXTRA
+CFLAGS_EXTRA="$CFLAGS_EXTRA -Wall -pedantic -fPIC"
+AC_CACHE_CHECK(if we can use GCC-specific compiler options, rd_cv_gcc_opt,
+[
+AC_TRY_COMPILE( , return 0 ,
+ rd_cv_gcc_opt=yes,
+ rd_cv_gcc_opt=no )
+])
+if test $rd_cv_gcc_opt = no; then
+ CFLAGS_EXTRA=$oCFLAGS_EXTRA
+fi
+
+else
+AC_CACHE_CHECK(if we should use HP compiler options, rd_cv_prog_hpcc,
+[
+cat > conftest.c <<EOF
+#ifdef _HPUX_SOURCE
+ yes;
+#endif
+EOF
+if AC_TRY_COMMAND(${CC-cc} -Ae -z -E conftest.c) | egrep yes >/dev/null 2>&1
+then
+ rd_cv_prog_hpcc=yes
+else
+ rd_cv_prog_hpcc=no
+fi])
+fi
+if test $rd_cv_prog_hpcc = yes; then
+ CFLAGS_EXTRA="$CFLAGS_EXTRA -Ae -z"
+fi
+
+dnl Checks for library functions.
+AC_FUNC_STRFTIME
+AC_FUNC_VPRINTF
+
+AC_CHECK_FUNCS(mktime getrusage gettimeofday)
+
+oCFLAGS_EXTRA=$CFLAGS_EXTRA
+AC_CACHE_CHECK([if the compiler does proper IEEE math], rd_cv_ieee_works,
+[AC_TRY_RUN([int main(void){
+ double a=0.0/0.0,b=0.0,c;
+ c=a/b;if (c==a) c=a;return isnan(a/c)?0:1;
+ }],
+ [rd_cv_ieee_works=yes],[
+AC_MSG_RESULT(no it does not)
+CFLAGS_EXTRA="$CFLAGS_EXTRA -ieee"
+AC_CACHE_CHECK([if the compiler does proper IEEE math with -ieee], rd_cv_ieee_switch,
+[AC_TRY_RUN([int main(void){
+ double a=0.0/0.0,b=0.0,c;
+ c=a/b;if (c==a) c=a;return isnan(a/c)?0:1;
+ }],
+ [rd_cv_ieee_switch=yes],[rd_cv_ieee_switch=no;
+AC_MSG_RESULT(nope)
+echo "--------------------------------------------------------------"
+echo "Your Compiler does not do propper IEEE math ... "
+echo "Please find out how to make IEEE math work with your Compiler"
+echo "And let me know (oetiker at ee.ethz.ch)"
+echo ""
+exit 1
+],:)])
+],:)])
+
+CFLAGS_EXTRA=$oCFLAGS_EXTRA
+
+if test x$rd_cv_ieee_switch = xyes; then
+ CFLAGS_EXTRA="$CFLAGS_EXTRA -ieee"
+fi
+
+AC_SUBST(CFLAGS_EXTRA)
+AC_SUBST(CFLAGS)
+
+AC_OUTPUT(Makefile src/Makefile gd1.2/Makefile doc/GNUmakefile perl-shared/examples/shared-demo.pl perl-piped/examples/piped-demo.pl, [chmod +x perl-*/examples/*.pl])
+
+AC_MSG_CHECKING(in)
+AC_MSG_RESULT(and out again)
+
+echo $ac_n "ordering CD from http://cdnow.com/gift/oetiker@ee.ethz.ch""... $ac_c" 1>&6
+sleep 3
+AC_MSG_RESULT([just kidding ;-)])
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/parsetime.h
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/parsetime.h (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/parsetime.h Sat Jul 13 18:46:00 2002
@@ -0,0 +1,23 @@
+#ifndef __PARSETIME_H__
+#define __PARSETIME_H__
+
+#include <time.h>
+#include <stdio.h>
+
+typedef enum {
+ ABSOLUTE_TIME,
+ RELATIVE_TO_START_TIME,
+ RELATIVE_TO_END_TIME
+} timetype;
+
+#define TIME_OK NULL
+
+struct time_value {
+ timetype type;
+ long offset;
+ struct tm tm;
+};
+
+char *parsetime(char *spec, struct time_value *ptv);
+
+#endif
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_format.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_format.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_format.c Sat Jul 13 18:46:01 2002
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1999
+ *****************************************************************************
+ * rrd_format.c RRD Database Format helper functions
+ *****************************************************************************
+ * $Id: rrd_format.c,v 1.3 1998/03/08 12:35:11 oetiker Exp oetiker $
+ * $Log: rrd_format.c,v $
+ * Revision 1.3 1998/03/08 12:35:11 oetiker
+ * checkpointing things because the current setup seems to work
+ * according to the things said in the manpages
+ *
+ * Revision 1.2 1998/02/26 22:58:22 oetiker
+ * fixed define
+ *
+ * Revision 1.1 1998/02/21 16:14:41 oetiker
+ * Initial revision
+ *
+ *
+ *****************************************************************************/
+#include "rrd_tool.h"
+
+#define converter(VV,VVV) \
+ if (strcmp(#VV, string) == 0) return VVV;
+
+/* conversion functions to allow symbolic entry of enumerations */
+enum dst_en dst_conv(char *string)
+{
+ converter(COUNTER,DST_COUNTER)
+ converter(ABSOLUTE,DST_ABSOLUTE)
+ converter(GAUGE,DST_GAUGE)
+ converter(DERIVE,DST_DERIVE)
+ rrd_set_error("unknown date aquisition function '%s'",string);
+ return(-1);
+}
+
+
+enum cf_en cf_conv(char *string)
+{
+
+ converter(AVERAGE,CF_AVERAGE)
+ converter(MIN,CF_MINIMUM)
+ converter(MAX,CF_MAXIMUM)
+ converter(LAST,CF_LAST)
+ rrd_set_error("unknown consolidation function '%s'",string);
+ return(-1);
+}
+
+#undef converter
+
+long
+ds_match(rrd_t *rrd,char *ds_nam){
+ long i;
+ for(i=0;i<rrd->stat_head->ds_cnt;i++)
+ if ((strcmp(ds_nam,rrd->ds_def[i].ds_nam))==0)
+ return i;
+ rrd_set_error("unknown data source name '%s'",ds_nam);
+ return -1;
+}
+
+
+
+
+
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_error.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_error.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_error.c Sat Jul 13 18:46:01 2002
@@ -0,0 +1,53 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1997, 1998, 1999
+ *****************************************************************************
+ * rrd_error.c Common Header File
+ *****************************************************************************
+ * $Id: rrd_tool.h,v 1.5 1998/03/08 12:35:11 oetiker Exp oetiker $
+ * $Log: rrd_tool.h,v $
+ *************************************************************************** */
+
+#include "rrd_tool.h"
+static char* rrd_error = NULL;
+#include <stdarg.h>
+
+
+
+void
+rrd_set_error(char *fmt, ...)
+{
+ int maxlen = strlen(fmt)*4;
+ va_list argp;
+ rrd_clear_error();
+ rrd_error = malloc(sizeof(char)*maxlen);
+ va_start(argp, fmt);
+ vsprintf(rrd_error, fmt, argp);
+ va_end(argp);
+}
+
+int
+rrd_test_error(void) {
+ return rrd_error != NULL;
+}
+
+void
+rrd_clear_error(void){
+ free(rrd_error);
+ rrd_error = NULL;
+}
+
+char *
+rrd_get_error(void){
+ return rrd_error;
+}
+
+
+
+
+
+
+
+
+
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrdtool.dsw
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrdtool.dsw (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrdtool.dsw Sat Jul 13 18:46:01 2002
@@ -0,0 +1,53 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "gd"="..\gd1.2\gd.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "rrd"=".\rrd.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "rrdtool"=".\rrdtool.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_fetch.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_fetch.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_fetch.c Sat Jul 13 18:46:01 2002
@@ -0,0 +1,461 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1997, 1998, 1999
+ *****************************************************************************
+ * rrd_fetch.c read date from an rrd to use for further processing
+ *****************************************************************************
+ * $Id: rrd_fetch.c,v 1.8 1998/03/08 12:35:11 oetiker Exp oetiker $
+ * $Log: rrd_fetch.c,v $
+ *****************************************************************************/
+
+#include "rrd_tool.h"
+/*#define DEBUG*/
+
+int
+rrd_fetch(int argc,
+ char **argv,
+ time_t *start,
+ time_t *end, /* which time frame do you want ?
+ * will be changed to represent reality */
+ unsigned long *step, /* which stepsize do you want?
+ * will be changed to represent reality */
+ unsigned long *ds_cnt, /* number of data sources in file */
+ char ***ds_namv, /* names of data sources */
+ rrd_value_t **data) /* two dimensional array containing the data */
+{
+
+
+ long step_tmp = 1, start_tmp = -24*3600, end_tmp=time(NULL);
+ enum cf_en cf_idx;
+
+#ifdef WANT_AT_STYLE_TIMESPEC
+ struct time_value start_tv, end_tv;
+ char *parsetime_error = NULL;
+ int start_tmp_is_ok = 0,
+ end_tmp_is_ok = 0;
+
+ end_tv.type = ABSOLUTE_TIME;
+ end_tv.tm = *localtime(&end_tmp);
+ end_tv.offset = 0;
+
+ start_tv.type = RELATIVE_TO_END_TIME;
+ start_tv.tm = *localtime(&end_tmp); /* to init tm_zone and tm_gmtoff */
+ start_tv.offset = -24*3600;/* to be compatible with the original code. */
+ start_tv.tm.tm_sec = 0; /** alternatively we could set tm_mday to -1 */
+ start_tv.tm.tm_min = 0; /** but this would yield -23(25) hours offset */
+ start_tv.tm.tm_hour = 0; /** twice a year, when DST is coming in or */
+ start_tv.tm.tm_mday = 0; /** out of effect */
+ start_tv.tm.tm_mon = 0;
+ start_tv.tm.tm_year = 0;
+ start_tv.tm.tm_wday = 0;
+ start_tv.tm.tm_yday = 0;
+ start_tv.tm.tm_isdst = -1; /* for mktime to guess */
+#endif
+
+ while (1){
+ static struct option long_options[] =
+ {
+ {"resolution", required_argument, 0, 'r'},
+ {"start", required_argument, 0, 's'},
+ {"end", required_argument, 0, 'e'},
+ {0,0,0,0}
+ };
+ int option_index = 0;
+ int opt;
+ opt = getopt_long(argc, argv, "r:s:e:",
+ long_options, &option_index);
+
+ if (opt == EOF)
+ break;
+
+ switch(opt) {
+ case 's':
+#ifdef WANT_AT_STYLE_TIMESPEC
+ {
+ char *endp;
+ start_tmp_is_ok = 0;
+ start_tmp = strtol(optarg, &endp, 0);
+ if (*endp == '\0') /* it was a valid number */
+ if (start_tmp > 31122038 || /* 31 Dec 2038 in DDMMYYYY */
+ start_tmp < 0) {
+ start_tmp_is_ok = 1;
+ break;
+ }
+ if ((parsetime_error = parsetime(optarg, &start_tv))) {
+ rrd_set_error( "start time: %s", parsetime_error );
+ return -1;
+ }
+ }
+#else
+ start_tmp = atol(optarg);
+#endif
+ break;
+ case 'e':
+#ifdef WANT_AT_STYLE_TIMESPEC
+ {
+ char *endp;
+ end_tmp_is_ok = 0;
+ end_tmp = strtol(optarg, &endp, 0);
+ if (*endp == '\0') /* it was a valid number */
+ if (end_tmp > 31122038) { /* 31 Dec 2038 in DDMMYYYY */
+ end_tmp_is_ok = 1;
+ break;
+ }
+ if ((parsetime_error = parsetime(optarg, &end_tv))) {
+ rrd_set_error( "end time: %s", parsetime_error );
+ return -1;
+ }
+ }
+#else
+ end_tmp = atol(optarg);
+#endif
+ break;
+ case 'r':
+ step_tmp = atol(optarg);
+ break;
+ case '?':
+ rrd_set_error("unknown option '-%c'",optopt);
+ return(-1);
+ }
+ }
+#ifdef WANT_AT_STYLE_TIMESPEC
+ if ((start_tv.type == RELATIVE_TO_END_TIME ||
+ (start_tmp_is_ok && start_tmp < 0)) && /* same as the line above */
+ end_tv.type == RELATIVE_TO_START_TIME) {
+ rrd_set_error("the start and end times cannot be specified "
+ "relative to each other");
+ return(-1);
+ }
+
+ if (start_tv.type == RELATIVE_TO_START_TIME) {
+ rrd_set_error("the start time cannot be specified relative to itself");
+ return(-1);
+ }
+
+ if (end_tv.type == RELATIVE_TO_END_TIME) {
+ rrd_set_error("the end time cannot be specified relative to itself");
+ return(-1);
+ }
+
+ /* We don't care to keep all the values in their range,
+ mktime will do this for us */
+ if (start_tv.type == RELATIVE_TO_END_TIME) {
+ if (end_tmp_is_ok)
+ end_tv.tm = *localtime( &end_tmp );
+ start_tv.tm.tm_sec += end_tv.tm.tm_sec;
+ start_tv.tm.tm_min += end_tv.tm.tm_min;
+ start_tv.tm.tm_hour += end_tv.tm.tm_hour;
+ start_tv.tm.tm_mday += end_tv.tm.tm_mday;
+ start_tv.tm.tm_mon += end_tv.tm.tm_mon;
+ start_tv.tm.tm_year += end_tv.tm.tm_year;
+ }
+ if (end_tv.type == RELATIVE_TO_START_TIME) {
+ if (start_tmp_is_ok)
+ start_tv.tm = *localtime( &start_tmp );
+ end_tv.tm.tm_sec += start_tv.tm.tm_sec;
+ end_tv.tm.tm_min += start_tv.tm.tm_min;
+ end_tv.tm.tm_hour += start_tv.tm.tm_hour;
+ end_tv.tm.tm_mday += start_tv.tm.tm_mday;
+ end_tv.tm.tm_mon += start_tv.tm.tm_mon;
+ end_tv.tm.tm_year += start_tv.tm.tm_year;
+ }
+ if (!start_tmp_is_ok)
+ start_tmp = mktime(&start_tv.tm) + start_tv.offset;
+ if (!end_tmp_is_ok)
+ end_tmp = mktime(&end_tv.tm) + end_tv.offset;
+#endif
+
+ if (start_tmp <= 0)
+ start_tmp = end_tmp + start_tmp;
+
+
+ if (start_tmp < 3600*24*365*10){
+ rrd_set_error("the first entry to fetch should be after 1980");
+ return(-1);
+ }
+
+ if (end_tmp < start_tmp) {
+ rrd_set_error("start (%ld) should be less than end (%ld)", start_tmp, end_tmp);
+ return(-1);
+ }
+
+ *start = start_tmp;
+ *end = end_tmp;
+
+ if (step_tmp < 1) {
+ rrd_set_error("step must be >= 1 second");
+ return -1;
+ }
+ *step = step_tmp;
+
+ if (optind + 1 >= argc){
+ rrd_set_error("not enough arguments");
+ return -1;
+ }
+
+ if ((cf_idx=cf_conv(argv[optind+1])) == -1 ){
+ return -1;
+ }
+
+ if (rrd_fetch_fn(argv[optind],cf_idx,start,end,step,ds_cnt,ds_namv,data) == -1)
+ return(-1);
+ return (0);
+}
+
+int
+rrd_fetch_fn(
+ char *filename, /* name of the rrd */
+ enum cf_en cf_idx, /* which consolidation function ?*/
+ time_t *start,
+ time_t *end, /* which time frame do you want ?
+ * will be changed to represent reality */
+ unsigned long *step, /* which stepsize do you want?
+ * will be changed to represent reality */
+ unsigned long *ds_cnt, /* number of data sources in file */
+ char ***ds_namv, /* names of data_sources */
+ rrd_value_t **data) /* two dimensional array containing the data */
+{
+ long i,ii;
+ FILE *in_file;
+ time_t cal_start,cal_end, rra_start_time,rra_end_time;
+ long best_full_rra=0, best_part_rra=0, chosen_rra=0, rra_pointer=0;
+ long best_step_diff=0, tmp_step_diff=0, tmp_match=0, best_match=0;
+ long full_match, rra_base;
+ long start_offset, end_offset;
+ int first_full = 1;
+ int first_part = 1;
+ rrd_t rrd;
+ rrd_value_t *data_ptr;
+ unsigned long rows;
+
+ if(rrd_open(filename,&in_file,&rrd, RRD_READONLY)==-1)
+ return(-1);
+
+ /* when was the realy last update of this file ? */
+
+ if (((*ds_namv) = (char **) malloc(rrd.stat_head->ds_cnt * sizeof(char*)))==NULL){
+ rrd_set_error("malloc fetch ds_namv array");
+ rrd_free(&rrd);
+ fclose(in_file);
+ return(-1);
+ }
+
+ for(i=0;i<rrd.stat_head->ds_cnt;i++){
+ if ((((*ds_namv)[i]) = malloc(sizeof(char) * DS_NAM_SIZE))==NULL){
+ rrd_set_error("malloc fetch ds_namv entry");
+ rrd_free(&rrd);
+ free(*ds_namv);
+ fclose(in_file);
+ return(-1);
+ }
+ strncpy((*ds_namv)[i],rrd.ds_def[i].ds_nam,DS_NAM_SIZE);
+ }
+
+ /* find the rra which best matches the requirements */
+ for(i=0;i<rrd.stat_head->rra_cnt;i++){
+ if(cf_conv(rrd.rra_def[i].cf_nam) == cf_idx){
+
+
+ cal_end = (rrd.live_head->last_up - (rrd.live_head->last_up
+ % (rrd.rra_def[i].pdp_cnt
+ * rrd.stat_head->pdp_step)));
+ cal_start = (cal_end
+ - (rrd.rra_def[i].pdp_cnt
+ * rrd.rra_def[i].row_cnt
+ * rrd.stat_head->pdp_step));
+
+ full_match = *start - *end;
+ /* best full match */
+ if(cal_end >= *end
+ && cal_start <= *start){
+ tmp_step_diff = labs(*step - (rrd.stat_head->pdp_step
+ * rrd.rra_def[i].pdp_cnt));
+ if (first_full || (tmp_step_diff < best_step_diff)){
+ first_full=0;
+ best_step_diff = tmp_step_diff;
+ best_full_rra=i;
+ }
+
+ } else {
+ /* best partial match */
+ tmp_match = full_match;
+ if (cal_start>*start)
+ tmp_match -= (cal_start-*start);
+ if (cal_end<*end)
+ tmp_match -= (*end-cal_end);
+ if (first_part || best_match < tmp_match){
+ first_part=0;
+ best_match = tmp_match;
+ best_part_rra =i;
+ }
+ }
+ }
+ }
+
+ /* lets see how the matching went. */
+
+ if (first_full==0)
+ chosen_rra = best_full_rra;
+ else if (first_part==0)
+ chosen_rra = best_part_rra;
+ else {
+ rrd_set_error("the RRD does not contain an RRA matching the chosen CF");
+ rrd_free(&rrd);
+ fclose(in_file);
+ return(-1);
+ }
+
+ /* set the wish parameters to their real values */
+
+ *step = rrd.stat_head->pdp_step * rrd.rra_def[chosen_rra].pdp_cnt;
+ *start -= (*start % *step);
+ if (*end % *step) *end += (*step - *end % *step);
+ rows = (*end - *start) / *step +1;
+
+#ifdef DEBUG
+ fprintf(stderr,"start %lu end %lu step %lu rows %lu\n",
+ *start,*end,*step,rows);
+#endif
+
+ *ds_cnt = rrd.stat_head->ds_cnt;
+ if (((*data) = malloc(*ds_cnt * rows * sizeof(rrd_value_t)))==NULL){
+ long i;
+ rrd_set_error("malloc fetch data area");
+ for (i=0;i<*ds_cnt;i++)
+ free((*ds_namv)[i]);
+ free(*ds_namv);
+ rrd_free(&rrd);
+ fclose(in_file);
+ return(-1);
+ }
+
+ data_ptr=(*data);
+
+ /* find base address of rra */
+ rra_base=ftell(in_file);
+ for(i=0;i<chosen_rra;i++)
+ rra_base += ( *ds_cnt
+ * rrd.rra_def[i].row_cnt
+ * sizeof(rrd_value_t));
+
+ /* find start and end offset */
+ rra_end_time = (rrd.live_head->last_up
+ - (rrd.live_head->last_up % *step));
+ rra_start_time = (rra_end_time
+ - ( *step * (rrd.rra_def[chosen_rra].row_cnt-1)));
+ start_offset = (*start - rra_start_time) / (long)*step;
+ end_offset = (rra_end_time - *end ) / (long)*step;
+#ifdef DEBUG
+ fprintf(stderr,"rra_start %lu, rra_end %lu, start_off %li, end_off %li\n",
+ rra_start_time,rra_end_time,start_offset,end_offset);
+#endif
+
+ /* fill the gap at the start if needs be */
+
+ if (start_offset <= 0)
+ rra_pointer = rrd.rra_ptr[chosen_rra].cur_row+1;
+ else
+ rra_pointer = rrd.rra_ptr[chosen_rra].cur_row+1+start_offset;
+
+ if(fseek(in_file,(rra_base
+ + (rra_pointer
+ * *ds_cnt
+ * sizeof(rrd_value_t))),SEEK_SET) != 0){
+ long i;
+ rrd_set_error("seek error in RRA");
+ for (i=0;i<*ds_cnt;i++)
+ free((*ds_namv)[i]);
+ free(*ds_namv);
+ rrd_free(&rrd);
+ free(*data);
+ *data = NULL;
+ fclose(in_file);
+ return(-1);
+
+ }
+#ifdef DEBUG
+ fprintf(stderr,"First Seek: rra_base %lu rra_pointer %lu\n",
+ rra_base, rra_pointer);
+#endif
+ /* step trough the array */
+
+ for (i=start_offset;
+ i<(long)(rrd.rra_def[chosen_rra].row_cnt-end_offset);
+ i++){
+ /* no valid data yet */
+ if (i<0) {
+#ifdef DEBUG
+ fprintf(stderr,"pre fetch %li -- ",i);
+#endif
+ for(ii=0;ii<*ds_cnt;ii++){
+ *(data_ptr++) = DNAN;
+#ifdef DEBUG
+ fprintf(stderr,"%10.2f ",*(data_ptr-1));
+#endif
+ }
+ }
+ /* past the valid data area */
+ else if (i>=rrd.rra_def[chosen_rra].row_cnt) {
+#ifdef DEBUG
+ fprintf(stderr,"post fetch %li -- ",i);
+#endif
+ for(ii=0;ii<*ds_cnt;ii++){
+ *(data_ptr++) = DNAN;
+#ifdef DEBUG
+ fprintf(stderr,"%10.2f ",*(data_ptr-1));
+#endif
+ }
+ } else {
+ /* OK we are inside the valid area but the pointer has to
+ * be wrapped*/
+ if (rra_pointer >= rrd.rra_def[chosen_rra].row_cnt) {
+ rra_pointer -= rrd.rra_def[chosen_rra].row_cnt;
+ if(fseek(in_file,(rra_base+rra_pointer
+ * *ds_cnt
+ * sizeof(rrd_value_t)),SEEK_SET) != 0){
+ long i;
+ rrd_set_error("wrap seek in RRA did fail");
+ for (i=0;i<*ds_cnt;i++)
+ free((*ds_namv)[i]);
+ free(*ds_namv);
+ rrd_free(&rrd);
+ free(*data);
+ *data = NULL;
+ fclose(in_file);
+ return(-1);
+ }
+#ifdef DEBUG
+ fprintf(stderr,"wrap seek ...\n");
+#endif
+ }
+
+ if(fread(data_ptr,
+ sizeof(rrd_value_t),
+ *ds_cnt,in_file) != rrd.stat_head->ds_cnt){
+ long i;
+ rrd_set_error("fetching cdp from rra");
+ for (i=0;i<*ds_cnt;i++)
+ free((*ds_namv)[i]);
+ free(*ds_namv);
+ rrd_free(&rrd);
+ free(*data);
+ *data = NULL;
+ fclose(in_file);
+ return(-1);
+ }
+#ifdef DEBUG
+ fprintf(stderr,"post fetch %li -- ",i);
+ for(ii=0;ii<*ds_cnt;ii++)
+ fprintf(stderr,"%10.2f ",*(data_ptr+ii));
+#endif
+ data_ptr += *ds_cnt;
+ rra_pointer ++;
+ }
+#ifdef DEBUG
+ fprintf(stderr,"\n");
+#endif
+
+ }
+ rrd_free(&rrd);
+ fclose(in_file);
+ return(0);
+}
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/Makefile.in
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/Makefile.in (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/Makefile.in Sat Jul 13 18:46:01 2002
@@ -0,0 +1,54 @@
+# things that the GNU standards document suggests all makefiles
+# should have.
+SHELL = /bin/sh
+.SUFFIXES:
+.SUFFIXES: .c .o .pl .pm .pod .html .man
+
+# variables we got from configure
+# (you can mess with these, if you want)
+
+CC = @CC@
+AR = ar
+CFLAGS_EXTRA = @CFLAGS_EXTRA@
+CFLAGS = @CFLAGS@
+CFLAGS_ALL = $(CFLAGS) $(CFLAGS_EXTRA) -I.. -I../gd1.2 -DHAVE_CONFIG_H \
+ -DWANT_AT_STYLE_TIMESPEC
+LDFLAGS = @LDFLAGS@
+LIBS = -L../gd1.2 -lgd @LIBS@
+LIBS_DEPEND = ../gd1.2/libgd.a
+
+###
+### Things you might NOT want to play with ...
+###
+
+HEADERS = rrd_tool.h rrd_format.h getopt.h parsetime.h
+
+SRCLIB = rrd_fetch.c rrd_create.c rrd_dump.c rrd_graph.c rrd_tune.c\
+ rrd_open.c rrd_diff.c rrd_last.c rrd_update.c rrd_format.c rrd_error.c\
+ getopt.c getopt1.c parsetime.c
+
+SRC = $(SRCLIB) rrd_tool.c
+
+OBJ = $(SRC:.c=.o)
+OBJLIB = $(SRCLIB:.c=.o)
+
+all: rrdtool librrd.a
+
+rrdtool: $(OBJ) $(LIBS_DEPEND)
+ $(CC) -o rrdtool $(OBJ) $(LDFLAGS) $(LIBS)
+
+librrd.a: $(OBJLIB)
+ $(AR) rc librrd.a $(OBJLIB)
+ @RANLIB@ librrd.a
+
+rrdtool.pure: $(OBJ) $(LIBS_DEPEND)
+ purify $(CC) -o rrdtool.pure $(OBJ) $(LDFLAGS) $(LIBS)
+
+clean:
+ -rm *.o *.a
+
+realclean: clean
+ -rm rrdtool rrdtool.pure
+
+.c.o: $(HEADERS)
+ $(CC) $(CFLAGS_ALL) -c $<
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/getopt.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/getopt.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/getopt.c Sat Jul 13 18:46:01 2002
@@ -0,0 +1,1000 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to roland at gnu.ai.mit.edu
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
+ Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library. Its master source is NOT part of
+ the C library, however. The master source lives in /gd/gnu/lib.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if !defined (__STDC__) || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+#include <stdlib.h>
+#include <unistd.h>
+#endif /* GNU C library. */
+
+#ifdef VMS
+#include <unixlib.h>
+#if HAVE_STRING_H - 0
+#include <string.h>
+#endif
+#endif
+
+#if defined (WIN32) && !defined (__CYGWIN32__)
+/* It's not Unix, really. See? Capital letters. */
+#include <windows.h>
+#define getpid() GetCurrentProcessId()
+#endif
+
+#ifndef _
+/* This is for other GNU distributions with internationalized messages.
+ When compiling libc, the _ macro is predefined. */
+#ifdef HAVE_LIBINTL_H
+# include <libintl.h>
+# define _(msgid) gettext (msgid)
+#else
+# define _(msgid) (msgid)
+#endif
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+ causes problems with re-calling getopt as programs generally don't
+ know that. */
+
+int __getopt_initialized = 0;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return -1 with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+#include <string.h>
+#define my_index strchr
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+#if !defined (__STDC__) || !__STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+#ifdef _LIBC
+/* Bash 2.0 gives us an environment variable containing flags
+ indicating ARGV elements that should not be considered arguments. */
+
+static const char *nonoption_flags;
+static int nonoption_flags_len;
+
+static int original_argc;
+static char *const *original_argv;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+ is valid for the getopt call we must make sure that the ARGV passed
+ to getopt is that one passed to the process. */
+static void store_args (int argc, char *const *argv) __attribute__ ((unused));
+static void
+store_args (int argc, char *const *argv)
+{
+ /* XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+ original_argc = argc;
+ original_argv = argv;
+}
+text_set_element (__libc_subinit, store_args);
+#endif
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+#if defined (__STDC__) && __STDC__
+static void exchange (char **);
+#endif
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+#if defined (__STDC__) && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
+static const char *
+_getopt_initialize (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+#ifdef _LIBC
+ if (posixly_correct == NULL
+ && argc == original_argc && argv == original_argv)
+ {
+ /* Bash 2.0 puts a special variable in the environment for each
+ command it runs, specifying which ARGV elements are the results of
+ file name wildcard expansion and therefore should not be
+ considered as options. */
+ char var[100];
+ sprintf (var, "_%d_GNU_nonoption_argv_flags_", getpid ());
+ nonoption_flags = getenv (var);
+ if (nonoption_flags == NULL)
+ nonoption_flags_len = 0;
+ else
+ nonoption_flags_len = strlen (nonoption_flags);
+ }
+ else
+ nonoption_flags_len = 0;
+#endif
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns -1.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ optarg = NULL;
+
+ if (!__getopt_initialized || optind == 0)
+ {
+ optstring = _getopt_initialize (argc, argv, optstring);
+ optind = 1; /* Don't scan ARGV[0], the program name. */
+ __getopt_initialized = 1;
+ }
+
+ /* Test whether ARGV[optind] points to a non-option argument.
+ Either it does not have option syntax, or there is an environment flag
+ from the shell indicating it is not an option. The later information
+ is only used when the used in the GNU libc. */
+#ifdef _LIBC
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
+ || (optind < nonoption_flags_len \
+ && nonoption_flags[optind] == '1'))
+#else
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+ moved back by the user (who may also have changed the arguments). */
+ if (last_nonopt > optind)
+ last_nonopt = optind;
+ if (first_nonopt > optind)
+ first_nonopt = optind;
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc && NONOPTION_P)
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return -1;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if (NONOPTION_P)
+ {
+ if (ordering == REQUIRE_ORDER)
+ return -1;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = -1;
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar)
+ == (unsigned int) strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (opterr)
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ _("%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ _("%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0], pfound->name);
+
+ nextchar += strlen (nextchar);
+
+ optopt = pfound->val;
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ optopt = pfound->val;
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: illegal option -- %c\n"),
+ argv[0], c);
+ else
+ fprintf (stderr, _("%s: invalid option -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ /* Convenience. Treat POSIX -W foo same as long option --foo */
+ if (temp[0] == 'W' && temp[1] == ';')
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0;
+ int option_index;
+
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ return c;
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+
+ /* optarg is now the argument, see if it's in the
+ table of longopts. */
+
+ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar) == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (opterr)
+ fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ nextchar = NULL;
+ return 'W'; /* Let the application handle it. */
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* Not ELIDE_CODE. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd.dsw
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd.dsw (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd.dsw Sat Jul 13 18:46:01 2002
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "rrd"=".\rrd.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_format.h
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_format.h (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_format.h Sat Jul 13 18:46:01 2002
@@ -0,0 +1,299 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1997, 1998, 1999
+ *****************************************************************************
+ * rrd_format.h RRD Database Format header
+ *****************************************************************************/
+
+#ifndef _RRD_FORMAT_H
+#define _RRD_FORMAT_H
+
+/*****************************************************************************
+ * put this in your /usr/lib/magic file (/etc/magic on HPUX)
+ *
+ * # rrd database format
+ * 0 string RRD\0 rrd file
+ * >5 string >\0 version '%s'
+ *
+ *****************************************************************************/
+
+#define RRD_COOKIE "RRD"
+#define RRD_VERSION "0001"
+#define FLOAT_COOKIE 8.642135E130
+
+#if defined(WIN32) || defined(_HPUX_SOURCE)
+#define DNAN ((double)fmod(0.0,0.0))
+#else
+
+#define DNAN ((double)(0.0/0.0)) /* we use a DNAN to
+ * represent the UNKNOWN
+ * */
+#endif
+
+typedef double rrd_value_t; /* the data storage type is
+ * double */
+
+typedef union unival {
+ unsigned long u_cnt;
+ rrd_value_t u_val;
+} unival;
+
+
+/****************************************************************************
+ * The RRD Database Structure
+ * ---------------------------
+ *
+ * In oder to properly describe the database structure lets define a few
+ * new words:
+ *
+ * ds - Data Source (ds) providing input to the database. A Data Source (ds)
+ * can be a traffic counter, a temperature, the number of users logged
+ * into a system. The rrd database format can handle the input of
+ * several Data Sources (ds) in a singe database.
+ *
+ * dst - Data Source Type (dst). The Data Source Type (dst) defines the rules
+ * applied to Build Primary Data Points from the input provided by the
+ * data sources (ds).
+ *
+ * pdp - Primary Data Point (pdp). After the database has accepted the
+ * input from the data sources (ds). It starts building Primary
+ * Data Points (pdp) from the data. Primary Data Points (pdp)
+ * are evenly spaced along the time axis (pdp_step). The values
+ * of the Primary Data Points are calculated from the values of
+ * the data source (ds) and the exact time these values were
+ * provided by the data source (ds).
+ *
+ * pdp_st - PDP Start (pdp_st). The moments (pdp_st) in time where
+ * these steps occur are defined by the moments where the
+ * number of seconds since 1970-jan-1 modulo pdp_step equals
+ * zero (pdp_st).
+ *
+ * cf - Consolidation Function (cf). An arbitrary Consolidation Function (cf)
+ * (averaging, min, max) is applied to the primary data points (pdp) to
+ * calculate the consolidated data point.
+ *
+ * cdp - Consolidated Data Point (cdp) is the long term storage format for data
+ * in the rrd database. Consolidated Data Points represent one or
+ * several primary data points collected along the time axis. The
+ * Consolidated Data Points (cdp) are stored in Round Robin Archives
+ * (rra).
+ *
+ * rra - Round Robin Archive (rra). This is the place where the
+ * consolidated data points (cdp) get stored. The data is
+ * organized in rows (row) and columns (col). The Round Robin
+ * Archive got its name from the method data is stored in
+ * there. An RRD database can contain several Round Robin
+ * Archives. Each Round Robin Archive can have a different row
+ * spacing along the time axis (pdp_cnt) and a different
+ * consolidation function (cf) used to build its consolidated
+ * data points (cdp).
+ *
+ * rra_st - RRA Start (rra_st). The moments (rra_st) in time where
+ * Consolidated Data Points (cdp) are added to an rra are
+ * defined by the moments where the number of seconds since
+ * 1970-jan-1 modulo pdp_cnt*pdp_step equals zero (rra_st).
+ *
+ * row - Row (row). A row represent all consolidated data points (cdp)
+ * in a round robin archive who are of the same age.
+ *
+ * col - Column (col). A column (col) represent all consolidated
+ * data points (cdp) in a round robin archive (rra) who
+ * originated from the same data source (ds).
+ *
+ */
+
+/****************************************************************************
+ * POS 1: stat_head_t static header of the database
+ ****************************************************************************/
+
+typedef struct stat_head_t {
+
+ /* Data Base Identification Section ***/
+ char cookie[4]; /* RRD */
+ char version[5]; /* version of the format */
+ double float_cookie; /* is it the correct double
+ * representation ? */
+
+ /* Data Base Structure Definition *****/
+ unsigned long ds_cnt; /* how many different ds provide
+ * input to the rrd */
+ unsigned long rra_cnt; /* how many rras will be maintained
+ * in the rrd */
+ unsigned long pdp_step; /* pdp interval in seconds */
+
+ unival par[10]; /* global parameters ... unused
+ at the moment */
+} stat_head_t;
+
+
+/****************************************************************************
+ * POS 2: ds_def_t (* ds_cnt) Data Source definitions
+ ****************************************************************************/
+
+enum dst_en { DST_COUNTER=0, /* data source types available */
+ DST_ABSOLUTE,
+ DST_GAUGE,
+ DST_DERIVE};
+
+enum ds_param_en { DS_mrhb_cnt=0, /* minimum required heartbeat. A
+ * data source must provide input at
+ * least every ds_mrhb seconds,
+ * otherwise it is regarded dead and
+ * will be set to UNKNOWN */
+ DS_min_val, /* the processed input of a ds must */
+ DS_max_val }; /* be between max_val and min_val
+ * both can be set to UNKNOWN if you
+ * do not care. Data outside the limits
+ * set to UNKNOWN */
+#define DS_NAM_FMT "%19[a-zA-Z0-9_]"
+#define DS_NAM_SIZE 20
+
+#define DST_FMT "%19[A-Z]"
+#define DST_SIZE 20
+
+typedef struct ds_def_t {
+ char ds_nam[DS_NAM_SIZE]; /* Name of the data source (null terminated)*/
+ char dst[DST_SIZE]; /* Type of data source (null terminated)*/
+ unival par[10]; /* index of this array see ds_param_en */
+} ds_def_t;
+
+/****************************************************************************
+ * POS 3: rra_def_t ( * rra_cnt) one for each store to be maintained
+ ****************************************************************************/
+enum cf_en { CF_AVERAGE=0, /* data consolidation functions */
+ CF_MINIMUM,
+ CF_MAXIMUM,
+ CF_LAST};
+
+enum rra_par_en { RRA_cdp_xff_val=0}; /* what part of the consolidated
+ datapoint must be known, to produce a
+ valid entry in the rra */
+
+#define CF_NAM_FMT "%19[A-Z]"
+#define CF_NAM_SIZE 20
+
+typedef struct rra_def_t {
+ char cf_nam[CF_NAM_SIZE];/* consolidation function (null term) */
+ unsigned long row_cnt; /* number of entries in the store */
+ unsigned long pdp_cnt; /* how many primary data points are
+ * required for a consolidated data
+ * point?*/
+ unival par[10]; /* index see rra_param_en */
+
+} rra_def_t;
+
+
+/****************************************************************************
+ ****************************************************************************
+ ****************************************************************************
+ * LIVE PART OF THE HEADER. THIS WILL BE WRITTEN ON EVERY UPDATE *
+ ****************************************************************************
+ ****************************************************************************
+ ****************************************************************************/
+/****************************************************************************
+ * POS 4: live_head_t
+ ****************************************************************************/
+
+typedef struct live_head_t {
+ time_t last_up; /* when was rrd last updated */
+} live_head_t;
+
+
+/****************************************************************************
+ * POS 5: pdp_prep_t (* ds_cnt) here we prepare the pdps
+ ****************************************************************************/
+#define LAST_DS_LEN 30 /* DO NOT CHANGE THIS ... */
+
+enum pdp_par_en { PDP_unkn_sec_cnt=0, /* how many seconds of the current
+ * pdp value is unknown data? */
+
+ PDP_val}; /* current value of the pdp.
+ this depends on dst */
+
+typedef struct pdp_prep_t{
+ char last_ds[LAST_DS_LEN]; /* the last reading from the data
+ * source. this is stored in ASCII
+ * to cater for very large counters
+ * we might encounter in connection
+ * with SNMP. */
+ unival scratch[10]; /* contents according to pdp_par_en */
+} pdp_prep_t;
+
+/* data is passed from pdp to cdp when seconds since epoch modulo pdp_step == 0
+ obviously the updates do not occur at these times only. Especially does the
+ format allow for updates to occur at different times for each data source.
+ The rules which makes this work is as follows:
+
+ * DS updates may only occur at ever increasing points in time
+ * When any DS update arrives after a cdp update time, the *previous*
+ update cycle gets executed. All pdps are transfered to cdps and the
+ cdps feed the rras where necessary. Only then the new DS value
+ is loaded into the PDP. */
+
+
+/****************************************************************************
+ * POS 6: cdp_prep_t (* rra_cnt * ds_cnt ) data prep area for cdp values
+ ****************************************************************************/
+enum cdp_par_en { CDP_val=0, /* the base_interval is always an
+ * average */
+ CDP_unkn_pdp_cnt }; /* how many unknown pdp were
+ * integrated. This and the cdp_xff
+ will decide if this is going to
+ be a UNKNOWN or a valid value */
+
+typedef struct cdp_prep_t{
+ unival scratch[10]; /* contents according to cdp_par_en *
+ * init state should be NAN */
+
+} cdp_prep_t;
+
+/****************************************************************************
+ * POS 7: rra_ptr_t (* rra_cnt) pointers to the current row in each rra
+ ****************************************************************************/
+
+typedef struct rra_ptr_t {
+ unsigned long cur_row; /* current row in the rra*/
+} rra_ptr_t;
+
+
+/****************************************************************************
+ ****************************************************************************
+ * One single struct to hold all the others. For convenience.
+ ****************************************************************************
+ ****************************************************************************/
+typedef struct rrd_t {
+ stat_head_t *stat_head; /* the static header */
+ ds_def_t *ds_def; /* list of data source definitions */
+ rra_def_t *rra_def; /* list of round robin archive def */
+ live_head_t *live_head;
+ pdp_prep_t *pdp_prep; /* pdp data prep area */
+ cdp_prep_t *cdp_prep; /* cdp prep area */
+ rra_ptr_t *rra_ptr; /* list of rra pointers */
+} rrd_t;
+
+/****************************************************************************
+ ****************************************************************************
+ * AFTER the header section we have the DATA STORAGE AREA it is made up from
+ * Consolidated Data Points organized in Round Robin Archives.
+ ****************************************************************************
+ ****************************************************************************
+
+ *RRA 0
+ (0,0) .................... ( ds_cnt -1 , 0)
+ .
+ .
+ .
+ (0, row_cnt -1) ... (ds_cnt -1, row_cnt -1)
+
+ *RRA 1
+ *RRA 2
+
+ *RRA rra_cnt -1
+
+ ****************************************************************************/
+
+
+#endif
+
+
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/getopt.h
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/getopt.h (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/getopt.h Sat Jul 13 18:46:02 2002
@@ -0,0 +1,133 @@
+/* Declarations for getopt.
+ Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library. Its master source is NOT part of
+ the C library, however. The master source lives in /gd/gnu/lib.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+#if defined (__STDC__) && __STDC__
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+#if defined (__STDC__) && __STDC__
+#ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_open.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_open.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_open.c Sat Jul 13 18:46:02 2002
@@ -0,0 +1,89 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1997, 1998, 1999
+ *****************************************************************************
+ * rrd_open.c Open an RRD File
+ *****************************************************************************
+ * $Id: rrd_open.c,v 1.6 1998/03/08 12:35:11 oetiker Exp oetiker $
+ * $Log: rrd_open.c,v $
+ *****************************************************************************/
+
+#include "rrd_tool.h"
+
+/* open a database file, return its header and a open filehandle */
+/* positioned to the first cdp in the first rra */
+
+int
+rrd_open(char *file_name, FILE **in_file, rrd_t *rrd, int rdwr)
+{
+
+ char *mode = NULL;
+ if (rdwr == RRD_READONLY) {
+ mode = "rb";
+ } else {
+ mode = "rb+";
+ }
+
+ if ((*in_file = fopen(file_name,mode)) == NULL ){
+ rrd_set_error("rrdopen can't open '%s'",file_name);
+ return (-1);
+ }
+
+#define MYFREAD(MYVAR,MYVART,MYCNT) \
+ if ((MYVAR = malloc(sizeof(MYVART) * MYCNT)) == NULL) {\
+ rrd_set_error("" #MYVAR " malloc"); \
+ return (-1); } \
+ fread(MYVAR,sizeof(MYVART),MYCNT, *in_file);
+
+
+ MYFREAD(rrd->stat_head, stat_head_t, 1)
+
+ /* lets do some test if we are on track ... */
+ if (strncmp(rrd->stat_head->cookie,RRD_COOKIE,4) != 0){
+ rrd_set_error("not an RRD file");
+ free(rrd->stat_head);
+ return(-1);}
+
+ if (strncmp(rrd->stat_head->version,RRD_VERSION,5) != 0){
+ rrd_set_error("cant handle RRD file version %s",
+ rrd->stat_head->version);
+ free(rrd->stat_head);
+ return(-1);}
+
+ if (rrd->stat_head->float_cookie != FLOAT_COOKIE){
+ rrd_set_error("This RRD created on other architecture");
+ free(rrd->stat_head);
+ return(-1);}
+
+ MYFREAD(rrd->ds_def, ds_def_t, rrd->stat_head->ds_cnt)
+ MYFREAD(rrd->rra_def, rra_def_t, rrd->stat_head->rra_cnt)
+ MYFREAD(rrd->live_head, live_head_t, 1)
+ MYFREAD(rrd->pdp_prep, pdp_prep_t, rrd->stat_head->ds_cnt)
+ MYFREAD(rrd->cdp_prep, cdp_prep_t, (rrd->stat_head->rra_cnt
+ * rrd->stat_head->ds_cnt))
+ MYFREAD(rrd->rra_ptr, rra_ptr_t, rrd->stat_head->rra_cnt)
+#undef MYFREAD
+
+ return(0);
+}
+
+void rrd_init(rrd_t *rrd)
+{
+ rrd->stat_head = NULL;
+ rrd->ds_def = NULL;
+ rrd->rra_def = NULL;
+ rrd->live_head = NULL;
+ rrd->rra_ptr = NULL;
+ rrd->pdp_prep = NULL;
+ rrd->cdp_prep = NULL;
+}
+
+void rrd_free(rrd_t *rrd)
+{
+ free(rrd->stat_head);
+ free(rrd->ds_def);
+ free(rrd->rra_def);
+ free(rrd->live_head);
+ free(rrd->rra_ptr);
+ free(rrd->pdp_prep);
+ free(rrd->cdp_prep);
+}
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_graph.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_graph.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_graph.c Sat Jul 13 18:46:03 2002
@@ -0,0 +1,2719 @@
+/****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1997,1998, 1999
+ ****************************************************************************
+ * rrd__graph.c make creates ne rrds
+ ****************************************************************************/
+
+#include "rrd_tool.h"
+#include <gd.h>
+#include <gdfonts.h>
+#include <gdfontmb.h>
+
+/* #define DEBUG */
+
+#ifdef DEBUG
+# define DPRINT(x) (void)(printf x, printf("\n"))
+#else
+# define DPRINT(x)
+#endif
+
+enum tmt_en {TMT_SECOND=0,TMT_MINUTE,TMT_HOUR,TMT_DAY,
+ TMT_WEEK,TMT_MONTH,TMT_YEAR};
+
+enum grc_en {GRC_CANVAS=0,GRC_BACK,GRC_SHADEA,GRC_SHADEB,
+ GRC_GRID,GRC_MGRID,GRC_FONT,GRC_FRAME,GRC_ARROW,__GRC_END__};
+
+enum gf_en {GF_PRINT=0,GF_GPRINT,GF_COMMENT,GF_HRULE,GF_VRULE,GF_LINE1,
+ GF_LINE2,GF_LINE3,GF_AREA,GF_STACK, GF_DEF, GF_CDEF };
+
+enum op_en {OP_NUMBER=0,OP_VARIABLE,OP_ADD,OP_SUB,OP_MUL,OP_DIV,OP_SIN,
+ OP_COS,OP_LOG,OP_EXP,OP_LT,OP_LE,OP_GT,OP_GE,OP_EQ,OP_IF,
+ OP_UN,OP_END};
+
+typedef struct rpnp_t {
+ enum op_en op;
+ double val; /* value for a OP_NUMBER */
+ long ptr; /* pointer into the gdes array for OP_VAR */
+ double *data; /* pointer to the current value from OP_VAR DAS*/
+ long ds_cnt; /* data source count for data pointer */
+ long step; /* time step for OP_VAR das */
+} rpnp_t;
+
+
+typedef struct col_trip_t {
+ int red; /* red = -1 is no color */
+ int green;
+ int blue;
+ int i; /* color index assigned in gif image i=-1 is unasigned*/
+} col_trip_t;
+
+
+typedef struct xlab_t {
+ long minsec; /* minimum sec per pix */
+ enum tmt_en gridtm; /* grid interval in what ?*/
+ long gridst; /* how many whats per grid*/
+ enum tmt_en mgridtm; /* label interval in what ?*/
+ long mgridst; /* how many whats per label*/
+ enum tmt_en labtm; /* label interval in what ?*/
+ long labst; /* how many whats per label*/
+ long precis; /* label precision -> label placement*/
+ char *stst; /* strftime string*/
+} xlab_t;
+
+xlab_t xlab[] = {
+ {0, TMT_SECOND,30, TMT_MINUTE,5, TMT_MINUTE,5, 0,"%H:%M"},
+ {2, TMT_MINUTE,1, TMT_MINUTE,5, TMT_MINUTE,5, 0,"%H:%M"},
+ {5, TMT_MINUTE,2, TMT_MINUTE,10, TMT_MINUTE,10, 0,"%H:%M"},
+ {10, TMT_MINUTE,5, TMT_MINUTE,20, TMT_MINUTE,20, 0,"%H:%M"},
+ {30, TMT_MINUTE,10, TMT_HOUR,1, TMT_HOUR,1, 0,"%H:%M"},
+ {60, TMT_MINUTE,30, TMT_HOUR,2, TMT_HOUR,2, 0,"%H:%M"},
+ {180, TMT_HOUR,1, TMT_HOUR,6, TMT_HOUR,6, 0,"%H:%M"},
+ /*{300, TMT_HOUR,3, TMT_HOUR,12, TMT_HOUR,12, 12*3600,"%a %p"}, this looks silly*/
+ {600, TMT_HOUR,6, TMT_DAY,1, TMT_DAY,1, 24*3600,"%a"},
+ {1800, TMT_HOUR,12, TMT_DAY,1, TMT_DAY,2, 24*3600,"%a"},
+ {3600, TMT_DAY,1, TMT_WEEK,1, TMT_WEEK,1, 7*24*3600,"Week %W"},
+ {3*3600, TMT_WEEK,1, TMT_MONTH,1, TMT_WEEK,2, 7*24*3600,"Week %W"},
+ {6*3600, TMT_MONTH,1, TMT_MONTH,1, TMT_MONTH,1, 30*24*3600,"%b"},
+ {48*3600, TMT_MONTH,1, TMT_MONTH,3, TMT_MONTH,3, 30*24*3600,"%b"},
+ {10*24*3600, TMT_YEAR,1, TMT_YEAR,1, TMT_YEAR,1, 365*24*3600,"%y"},
+ {-1,TMT_MONTH,0,TMT_MONTH,0,TMT_MONTH,0,0,""}
+};
+
+/* sensible logarithmic y label intervals ...
+ the first element of each row defines the possible starting points on the
+ y axis ... the other specify the */
+
+double yloglab[][12]= {{ 1e9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1e3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 1e1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ /* { 1e1, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, */
+ { 1e1, 1, 2.5, 5, 7.5, 0, 0, 0, 0, 0, 0, 0 },
+ { 1e1, 1, 2, 4, 6, 8, 0, 0, 0, 0, 0, 0 },
+ { 1e1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }};
+
+/* sensible y label intervals ...*/
+
+typedef struct ylab_t {
+ double grid; /* grid spacing */
+ int lfac[4]; /* associated label spacing*/
+} ylab_t;
+
+ylab_t ylab[]= {
+ {0.1, {1,2, 5,10}},
+ {0.2, {1,5,10,20}},
+ {0.5, {1,2, 4,10}},
+ {1.0, {1,2, 5,10}},
+ {2.0, {1,5,10,20}},
+ {5.0, {1,2, 4,10}},
+ {10.0, {1,2, 5,10}},
+ {20.0, {1,5,10,20}},
+ {50.0, {1,2, 4,10}},
+ {100.0, {1,2, 5,10}},
+ {200.0, {1,5,10,20}},
+ {500.0, {1,2, 4,10}},
+ {0.0, {0,0,0,0}}};
+
+
+
+col_trip_t graph_col[] = { /* default colors */
+ {255,255,255,-1}, /* canvas */
+ {245,245,245,-1}, /* background */
+ {200,200,200,-1}, /* shade A */
+ {150,150,150,-1}, /* shade B */
+ {140,140,140,-1}, /* grid */
+ {130,30,30,-1}, /* major grid */
+ {0,0,0,-1}, /* font */
+ {0,0,0,-1}, /* frame */
+ {255,0,0,-1} /*arrow*/
+};
+
+/* this structure describes the elements which can make up a graph.
+ because they are quite diverse, not all elements will use all the
+ possible parts of the structure. */
+
+#define FMT_LEG_LEN 120
+
+typedef struct graph_desc_t {
+ enum gf_en gf; /* graphing function */
+ char vname[30]; /* name of the variable */
+ long vidx; /* gdes reference */
+ char rrd[255]; /* name of the rrd_file containing data */
+ char ds_nam[DS_NAM_SIZE]; /* data source name */
+ long ds; /* data source number */
+ enum cf_en cf; /* consolidation function */
+ col_trip_t col; /* graph color */
+ char format[FMT_LEG_LEN+5]; /* format for PRINT AND GPRINT */
+ char legend[FMT_LEG_LEN+5]; /* legend*/
+ gdPoint legloc; /* location of legend */
+ double yrule; /* value for y rule line */
+ time_t xrule; /* value for x rule line */
+ rpnp_t *rpnp; /* instructions for CDEF function */
+
+ /* description of data fetched for the graph element */
+ time_t start,end; /* first and last data element */
+ unsigned long step; /* time between samples */
+ unsigned long ds_cnt; /* how many data sources are there in the fetch */
+ long data_first; /* first pointer to this data */
+ char **ds_namv; /* name of datasources in the fetch. */
+ rrd_value_t *data; /* the raw data drawn from the rrd */
+ rrd_value_t *p_data; /* processed data, xsize elments */
+
+} graph_desc_t;
+
+
+typedef struct image_desc_t {
+
+ /* configuration of graph */
+
+ char graphfile[255]; /* filename for graphic */
+ long xsize,ysize; /* graph area size in pixels */
+ col_trip_t graph_col[__GRC_END__]; /* real colors for the graph */
+ char ylegend[200]; /* legend along the yaxis */
+ char title[200]; /* title for graph */
+ xlab_t xlab_user; /* user defined labeling for xaxis */
+ char xlab_form[200]; /* format for the label on the xaxis */
+
+ double ygridstep; /* user defined step for y grid */
+ int ylabfact; /* every how many y grid shall a label be written ? */
+
+ time_t start,end; /* what time does the graph cover */
+ rrd_value_t minval,maxval; /* extreme values in the data */
+ int rigid; /* do not expand range even with
+ values outside */
+ int logarithmic; /* scale the yaxis logarithmic */
+
+ /* status information */
+
+ long xorigin,yorigin;/* where is (0,0) of the graph */
+ long xgif,ygif; /* total size of the gif */
+ int interlaced; /* will the graph be interlaced? */
+ double magfact; /* numerical magnitude*/
+ long base; /* 1000 or 1024 depending on what we graph */
+ char symbol; /* magnitude symbol for y-axis */
+
+ /* data elements */
+
+ long gdes_c; /* number of graphics elements */
+ graph_desc_t *gdes; /* points to an array of graph elements */
+
+} image_desc_t;
+
+
+
+
+/* translate time values into x coordinates */
+/*#define xtr(x) (int)((double)im->xorigin \
+ + ((double) im->xsize / (double)(im->end - im->start) ) \
+ * ((double)(x) - im->start)+0.5) */
+/* initialize with xtr(im,0); */
+int
+xtr(image_desc_t *im,time_t time){
+ static double pixie;
+ if (time==0){
+ pixie = (double) im->xsize / (double)(im->end - im->start);
+ return im->xorigin;
+ }
+ return (int)((double)im->xorigin
+ + pixie * ( time - im->start ) );
+}
+
+/* translate data values into y coordinates */
+
+/* #define ytr(x) (int)((double)im->yorigin \
+ - ((double) im->ysize / (im->maxval - im->minval) ) \
+ * ((double)(x) - im->minval)+0.5) */
+int
+ytr(image_desc_t *im, double value){
+ static double pixie;
+ double yval;
+ if (isnan(value)){
+ if(!im->logarithmic)
+ pixie = (double) im->ysize / (im->maxval - im->minval);
+ else
+ pixie = (double) im->ysize / (log10(im->maxval) - log10(im->minval));
+ yval = im->yorigin;
+ } else if(!im->logarithmic) {
+ yval = im->yorigin - pixie * (value - im->minval) + 0.5;
+ } else {
+ if (value < im->minval) {
+ yval = im->yorigin;
+ } else {
+ yval = im->yorigin - pixie * (log10(value) - log10(im->minval)) + 0.5;
+ }
+ }
+ /* make sure we don't return anything too unreasonable. GD lib can
+ get terribly slow when drawing lines outside its scope. This is
+ especially problematic in connection with the rigid option */
+ if (! im->rigid) {
+ return (int)yval;
+ } else if ((int)yval > im->yorigin) {
+ return im->yorigin+2;
+ } else if ((int) yval < im->yorigin - im->ysize){
+ return im->yorigin - im->ysize - 2;
+ } else {
+ return (int)yval;
+ }
+}
+
+
+
+
+
+/* conversion function for symbolic entry names */
+
+#define conv_if(VV,VVV) \
+ if (strcmp(#VV, string) == 0) return VVV ;
+
+enum gf_en gf_conv(char *string){
+
+ conv_if(PRINT,GF_PRINT)
+ conv_if(GPRINT,GF_GPRINT)
+ conv_if(COMMENT,GF_COMMENT)
+ conv_if(HRULE,GF_HRULE)
+ conv_if(VRULE,GF_VRULE)
+ conv_if(LINE1,GF_LINE1)
+ conv_if(LINE2,GF_LINE2)
+ conv_if(LINE3,GF_LINE3)
+ conv_if(AREA,GF_AREA)
+ conv_if(STACK,GF_STACK)
+ conv_if(DEF,GF_DEF)
+ conv_if(CDEF,GF_CDEF)
+
+ return (-1);
+}
+
+enum tmt_en tmt_conv(char *string){
+
+ conv_if(SECOND,TMT_SECOND)
+ conv_if(MINUTE,TMT_MINUTE)
+ conv_if(HOUR,TMT_HOUR)
+ conv_if(DAY,TMT_DAY)
+ conv_if(WEEK,TMT_WEEK)
+ conv_if(MONTH,TMT_MONTH)
+ conv_if(YEAR,TMT_YEAR)
+ return (-1);
+}
+
+enum grc_en grc_conv(char *string){
+
+ conv_if(BACK,GRC_BACK)
+ conv_if(CANVAS,GRC_CANVAS)
+ conv_if(SHADEA,GRC_SHADEA)
+ conv_if(SHADEB,GRC_SHADEB)
+ conv_if(GRID,GRC_GRID)
+ conv_if(MGRID,GRC_MGRID)
+ conv_if(FONT,GRC_FONT)
+ conv_if(FRAME,GRC_FRAME)
+ conv_if(ARROW,GRC_ARROW)
+
+ return -1;
+}
+
+#undef conv_if
+
+
+
+int
+im_free(image_desc_t *im)
+{
+ long i,ii;
+ if (im == NULL) return 0;
+ for(i=0;i<im->gdes_c;i++){
+ if (im->gdes[i].data_first){
+ /* careful here, because a single pointer can occur several times */
+ free (im->gdes[i].data);
+ if (im->gdes[i].ds_namv){
+ for (ii=0;ii<im->gdes[i].ds_cnt;ii++)
+ free(im->gdes[i].ds_namv[ii]);
+ free(im->gdes[i].ds_namv);
+ }
+ }
+ free (im->gdes[i].p_data);
+ free (im->gdes[i].rpnp);
+ }
+ free(im->gdes);
+ return 0;
+}
+
+/* find SI magnitude symbol for the numbers on the y-axis*/
+void
+si_unit(
+ image_desc_t *im /* image description */
+)
+{
+
+ char symbol[] = {'a', /* 10e-18 Ato */
+ 'f', /* 10e-15 Femto */
+ 'p', /* 10e-12 Pico */
+ 'n', /* 10e-9 Nano */
+ 'µ', /* 10e-6 Micro */
+ 'm', /* 10e-3 Milli */
+ ' ', /* Base */
+ 'k', /* 10e3 Kilo */
+ 'M', /* 10e6 Mega */
+ 'G', /* 10e9 Giga */
+ 'T', /* 10e12 Terra */
+ 'P', /* 10e15 Peta */
+ 'E'};/* 10e18 Exa */
+
+ int symbcenter = 6;
+ double digits;
+
+
+ digits = floor( log( max( fabs(im->minval),fabs(im->maxval)))/log(im->base));
+ im->magfact = pow(im->base , digits);
+#ifdef DEBUG
+ printf("digits %6.3f im->magfact %6.3f\n",digits,im->magfact);
+#endif
+ if ( ((digits+symbcenter) < sizeof(symbol)) &&
+ ((digits+symbcenter) >= 0) )
+ im->symbol = symbol[(int)digits+symbcenter];
+ else
+ im->symbol = ' ';
+ }
+
+/* move min and max values around to become sensible */
+
+void
+expand_range(image_desc_t *im)
+{
+ double sensiblevalues[] ={1000.0,900.0,800.0,750.0,700.0,
+ 600.0,500.0,400.0,300.0,250.0,
+ 200.0,125.0,100.0,90.0,80.0,
+ 75.0,70.0,60.0,50.0,40.0,30.0,
+ 25.0,20.0,10.0,9.0,8.0,
+ 7.0,6.0,5.0,4.0,3.5,3.0,
+ 2.5,2.0,1.8,1.5,1.2,1.0,
+ 0.8,0.7,0.6,0.5,0.4,0.3,0.2,0.1,0.0,-1};
+
+ double scaled_min,scaled_max;
+ int i;
+
+
+ scaled_min = im->minval / im->magfact;
+ scaled_max = im->maxval / im->magfact;
+
+ #ifdef DEBUG
+ printf("Min: %6.2f Max: %6.2f MagFactor: %6.2f\n",
+ im->minval,im->maxval,im->magfact);
+ #endif
+
+ for (i=1; sensiblevalues[i] > 0; i++){
+ if (sensiblevalues[i-1]>=scaled_min &&
+ sensiblevalues[i]<=scaled_min)
+ im->minval = sensiblevalues[i]*(im->magfact);
+
+ if (-sensiblevalues[i-1]<=scaled_min &&
+ -sensiblevalues[i]>=scaled_min)
+ im->minval = -sensiblevalues[i-1]*(im->magfact);
+
+ if (sensiblevalues[i-1] >= scaled_max &&
+ sensiblevalues[i] <= scaled_max)
+ im->maxval = sensiblevalues[i-1]*(im->magfact);
+
+ if (-sensiblevalues[i-1]<=scaled_max &&
+ -sensiblevalues[i] >=scaled_max)
+ im->maxval = -sensiblevalues[i]*(im->magfact);
+ }
+#ifdef DEBUG
+ printf("SCALED Min: %6.2f Max: %6.2f Factor: %6.2f\n",
+ im->minval,im->maxval,im->magfact);
+#endif
+}
+
+
+
+void
+reduce_data(
+ enum cf_en cf, /* which consolidation function ?*/
+ unsigned long cur_step, /* step the data currently is in */
+ time_t *start,
+ time_t *end, /* which time frame do you want ?
+ * will be changed to represent reality */
+ unsigned long *step, /* step the data currently is in */
+ unsigned long *ds_cnt, /* number of data sources in file */
+ rrd_value_t **data) /* two dimensional array containing the data */
+{
+ int i,reduce_factor = ceil((double)*step / cur_step);
+ unsigned long src_row,trg_row,col,row_cnt,start_offset,rowadjust;
+ row_cnt = (*end-*start)/cur_step;
+
+ *step = cur_step*reduce_factor;
+ /* adjust the start time so that it is a multiple of the new steptime */
+
+ start_offset = *start % *step;
+ if (start_offset > 0) {
+ start_offset = *step - start_offset;
+ *start = *start + start_offset - *step;
+ /* we don't have any data for the first row, so fill it with
+ *UNKNOWN* */
+ for (col=0;col<*ds_cnt;col++)
+ (*data)[col] = DNAN;
+ }
+
+
+ rowadjust = start_offset / cur_step;
+
+ trg_row=0;
+
+ for (src_row = rowadjust; src_row <= row_cnt-reduce_factor; src_row+=reduce_factor) {
+ for (col=0;col<*ds_cnt;col++){
+ double newval=0;
+ unsigned long validval=0;
+ for (i=0;i<reduce_factor && src_row<row_cnt;i += reduce_factor) {
+ unsigned long ptr = (src_row+i)* *ds_cnt+col;
+ if (isnan((*data)[ptr])) continue; /* we can't help with NAN */
+ validval++;
+ switch (cf) {
+ case CF_AVERAGE:
+ newval += (*data)[ptr];
+ break;
+ case CF_MINIMUM:
+ newval = min (newval,(*data)[ptr]);
+ break;
+ case CF_MAXIMUM:
+ newval = max (newval,(*data)[ptr]);
+ break;
+ case CF_LAST:
+ newval = (*data)[ptr];
+ break;
+ }
+ }
+ if (validval == 0){newval = DNAN;} else{
+ switch (cf) {
+ case CF_AVERAGE:
+ newval /= validval;
+ break;
+ case CF_MINIMUM:
+ case CF_MAXIMUM:
+ case CF_LAST:
+ break;
+ }
+ }
+ (*data)[(trg_row)* *ds_cnt+col] = newval;
+ }
+ trg_row++;
+ }
+ *end = *start+ *step *trg_row;
+ for (col=0;col<*ds_cnt;col++){
+ (*data)[(trg_row)* *ds_cnt+col] = DNAN;
+ }
+}
+
+
+/* get the data required for the graphs from the
+ relevant rrds ... */
+
+int
+data_fetch( image_desc_t *im )
+{
+ int i,ii;
+ int skip;
+ /* pull the data from the log files ... */
+ for (i=0;i<im->gdes_c;i++){
+ /* only GF_DEF elements fetch data */
+ if (im->gdes[i].gf != GF_DEF)
+ continue;
+
+ skip=0;
+ /* do we have it already ?*/
+ for (ii=0;ii<i;ii++){
+ if (im->gdes[ii].gf != GF_DEF)
+ continue;
+ if((strcmp(im->gdes[i].rrd,im->gdes[ii].rrd) == 0)
+ && (im->gdes[i].cf == im->gdes[ii].cf)){
+ /* OK the data it is here already ...
+ * we just copy the header portion */
+ im->gdes[i].start = im->gdes[ii].start;
+ im->gdes[i].end = im->gdes[ii].end;
+ im->gdes[i].step = im->gdes[ii].step;
+ im->gdes[i].ds_cnt = im->gdes[ii].ds_cnt;
+ im->gdes[i].ds_namv = im->gdes[ii].ds_namv;
+ im->gdes[i].data = im->gdes[ii].data;
+ im->gdes[i].data_first = 0;
+ skip=1;
+ }
+ if (skip)
+ break;
+ }
+ if (! skip) {
+ unsigned long ft_step = im->gdes[i].step ;
+
+ if((rrd_fetch_fn(im->gdes[i].rrd,
+ im->gdes[i].cf,
+ &im->gdes[i].start,
+ &im->gdes[i].end,
+ &ft_step,
+ &im->gdes[i].ds_cnt,
+ &im->gdes[i].ds_namv,
+ &im->gdes[i].data)) == -1){
+ return -1;
+ }
+ im->gdes[i].data_first = 1;
+
+ if (ft_step < im->gdes[i].step) {
+ reduce_data(im->gdes[i].cf,
+ ft_step,
+ &im->gdes[i].start,
+ &im->gdes[i].end,
+ &im->gdes[i].step,
+ &im->gdes[i].ds_cnt,
+ &im->gdes[i].data);
+ } else {
+ im->gdes[i].step = ft_step;
+ }
+ }
+
+ /* lets see if the required data source is realy there */
+ for(ii=0;ii<im->gdes[i].ds_cnt;ii++){
+ if(strcmp(im->gdes[i].ds_namv[ii],im->gdes[i].ds_nam) == 0){
+ im->gdes[i].ds=ii; }
+ }
+ if (im->gdes[i].ds== -1){
+ rrd_set_error("No DS called '%s' in '%s'",
+ im->gdes[i].ds_nam,im->gdes[i].rrd);
+ return -1;
+ }
+
+ }
+ return 0;
+}
+
+/* evaluate the expressions in the CDEF functions */
+
+/*************************************************************
+ * CDEF stuff
+ *************************************************************/
+
+/* find gdes containing var*/
+long
+find_var(image_desc_t *im, char *key){
+ long ii;
+ for(ii=0;ii<im->gdes_c-1;ii++){
+ if((im->gdes[ii].gf == GF_DEF
+ || im->gdes[ii].gf == GF_CDEF)
+ && (strcmp(im->gdes[ii].vname,key) == 0)){
+ return ii;
+ }
+ }
+ return -1;
+}
+
+/* find the largest common denominator for all the numbers
+ in the 0 terminated num array */
+long
+lcd(long *num){
+ long rest;
+ int i;
+ for (i=0;num[i+1]!=0;i++){
+ do {
+ rest=num[i] % num[i+1];
+ num[i]=num[i+1]; num[i+1]=rest;
+ } while (rest!=0);
+ num[i+1] = num[i];
+ }
+/* return i==0?num[i]:num[i-1]; */
+ return num[i];
+}
+
+
+/* convert string to rpnp */
+rpnp_t *
+str2rpn(image_desc_t *im,char *expr){
+ int pos=0;
+ long steps=-1;
+ rpnp_t *rpnp;
+ char vname[30];
+
+ rpnp=NULL;
+
+ while(*expr){
+ if ((rpnp = (rpnp_t *) realloc(rpnp, (++steps + 2)*
+ sizeof(rpnp_t)))==NULL){
+ return NULL;
+ }
+
+ if(sscanf(expr,"%lf%n",&rpnp[steps].val,&pos) == 1){
+ rpnp[steps].op = OP_NUMBER;
+ expr+=pos;
+ }
+ else if ((sscanf(expr,"%29[_A-Za-z0-9]%n",
+ vname,&pos) == 1)
+ && ((rpnp[steps].ptr = find_var(im,vname)) != -1)){
+ rpnp[steps].op = OP_VARIABLE;
+ expr+=pos;
+ }
+
+#define match_op(VV,VVV) \
+ else if (strncmp(expr, #VVV, strlen(#VVV))==0){ \
+ rpnp[steps].op = VV; \
+ expr+=strlen(#VVV); \
+ }
+
+ match_op(OP_ADD,+)
+ match_op(OP_SUB,-)
+ match_op(OP_MUL,*)
+ match_op(OP_DIV,/)
+ match_op(OP_SIN,SIN)
+ match_op(OP_COS,COS)
+ match_op(OP_LOG,LOG)
+ match_op(OP_EXP,EXP)
+ match_op(OP_LT,LT)
+ match_op(OP_LE,LE)
+ match_op(OP_GT,GT)
+ match_op(OP_GE,GE)
+ match_op(OP_EQ,EQ)
+ match_op(OP_IF,IF)
+ match_op(OP_UN,UN)
+
+#undef match_op
+
+ else {
+ free(rpnp);
+ return NULL;
+ }
+ if (*expr == 0)
+ break;
+ if (*expr == ',')
+ expr++;
+ else {
+ free(rpnp);
+ return NULL;
+ }
+ }
+ rpnp[steps+1].op = OP_END;
+ return rpnp;
+}
+
+
+#define dc_stacksize 30
+
+/* run the rpn calculator on all the CDEF arguments */
+
+int
+data_calc( image_desc_t *im){
+
+ int gdi,rpi;
+ int dataidx;
+ long *steparray;
+ int stepcnt;
+ time_t now;
+
+ for (gdi=0;gdi<im->gdes_c;gdi++){
+ /* only GF_CDEF elements are of interest */
+ if (im->gdes[gdi].gf != GF_CDEF)
+ continue;
+ im->gdes[gdi].ds_cnt = 1;
+ im->gdes[gdi].ds = 0;
+ im->gdes[gdi].data_first = 1;
+ im->gdes[gdi].start = 0;
+ im->gdes[gdi].end = 0;
+ steparray=NULL;
+ stepcnt = 0;
+ dataidx=-1;
+
+ /* find the variables in the expression. And calc the lowest
+ common denominator of all step sizes of the data sources involved.
+ this will be the step size for the cdef created data source*/
+
+ for(rpi=0;im->gdes[gdi].rpnp[rpi].op != OP_END;rpi++){
+ if(im->gdes[gdi].rpnp[rpi].op == OP_VARIABLE){
+ long ptr = im->gdes[gdi].rpnp[rpi].ptr;
+ if ((steparray = realloc(steparray, (++stepcnt+1)*sizeof(double)))==NULL){
+ rrd_set_error("realloc steparray");
+ return -1;
+ };
+
+
+ steparray[stepcnt-1] = im->gdes[ptr].step;
+
+ /* adjust start and end of cdef (gdi) so that it runs from
+ the latest start point to the earliest endpoint of any of the
+ rras involved (ptr) */
+
+ if(im->gdes[gdi].start < im->gdes[ptr].start)
+ im->gdes[gdi].start = im->gdes[ptr].start;
+
+ if(im->gdes[gdi].end == 0
+ || im->gdes[gdi].end > im->gdes[ptr].end)
+ im->gdes[gdi].end = im->gdes[ptr].end;
+
+ /* store pointer to the first element of the rra providing
+ data for variable, further save step size and data source count
+ of this rra*/
+ im->gdes[gdi].rpnp[rpi].data =
+ im->gdes[ptr].data + im->gdes[ptr].ds;
+ im->gdes[gdi].rpnp[rpi].step = im->gdes[ptr].step;
+ im->gdes[gdi].rpnp[rpi].ds_cnt = im->gdes[ptr].ds_cnt;
+ }
+
+ }
+ if(steparray == NULL){
+ rrd_set_error("rpn expressions without variables are not supported");
+ return -1;
+ }
+ steparray[stepcnt]=0;
+ /* now find the step for the result of the cdef. so that we land on
+ each step in all of the variables rras */
+
+ im->gdes[gdi].step = lcd(steparray);
+
+
+ free(steparray);
+
+ if((im->gdes[gdi].data = malloc(((im->gdes[gdi].end
+ -im->gdes[gdi].start)
+ / im->gdes[gdi].step +1)
+ * sizeof(double)))==NULL){
+ rrd_set_error("malloc im->gdes[gdi].data");
+ return -1;
+ }
+
+ /* step through the new cdef results array and calculate the values */
+ for (now = im->gdes[gdi].start;
+ now<=im->gdes[gdi].end;
+ now += im->gdes[gdi].step){
+ double stack[dc_stacksize];
+ int stptr=-1;
+ /* process each op from the rpn in turn */
+ for (rpi=0;im->gdes[gdi].rpnp[rpi].op != OP_END;rpi++){
+ switch (im->gdes[gdi].rpnp[rpi].op){
+ case OP_NUMBER:
+ if(stptr>=dc_stacksize){
+ rrd_set_error("RPN stack overflow");
+ return -1;
+ }
+ stack[++stptr] = im->gdes[gdi].rpnp[rpi].val;
+ break;
+ case OP_VARIABLE:
+ if(stptr>=dc_stacksize){
+ rrd_set_error("RPN stack overflow");
+ return -1;
+ }
+ /* make sure we pull the correct value from the *.data array */
+ /* adjust the pointer into the array acordingly. */
+ if(now > im->gdes[gdi].start &&
+ now % im->gdes[gdi].rpnp[rpi].step == 0){
+ im->gdes[gdi].rpnp[rpi].data +=
+ im->gdes[gdi].rpnp[rpi].ds_cnt;
+ }
+ stack[++stptr] = *im->gdes[gdi].rpnp[rpi].data;
+ break;
+ case OP_ADD:
+ if(stptr<1){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr-1] = stack[stptr-1] + stack[stptr];
+ stptr--;
+ break;
+ case OP_SUB:
+ if(stptr<1){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr-1] = stack[stptr-1] - stack[stptr];
+ stptr--;
+ break;
+ case OP_MUL:
+ if(stptr<1){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr-1] = stack[stptr-1] * stack[stptr];
+ stptr--;
+ break;
+ case OP_DIV:
+ if(stptr<1){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr-1] = stack[stptr-1] / stack[stptr];
+ stptr--;
+ break;
+ case OP_SIN:
+ if(stptr<0){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr] = sin(stack[stptr]);
+ break;
+ case OP_COS:
+ if(stptr<0){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr] = cos(stack[stptr]);
+ break;
+ case OP_LOG:
+ if(stptr<0){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr] = log(stack[stptr]);
+ break;
+ case OP_EXP:
+ if(stptr<0){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr] = exp(stack[stptr]);
+ break;
+ case OP_LT:
+ if(stptr<1){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr-1] = stack[stptr-1] < stack[stptr] ? 1.0 : 0.0;
+ stptr--;
+ break;
+ case OP_LE:
+ if(stptr<1){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr-1] = stack[stptr-1] <= stack[stptr] ? 1.0 : 0.0;
+ stptr--;
+ break;
+ case OP_GT:
+ if(stptr<1){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr-1] = stack[stptr-1] > stack[stptr] ? 1.0 : 0.0;
+ stptr--;
+ break;
+ case OP_GE:
+ if(stptr<1){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr-1] = stack[stptr-1] >= stack[stptr] ? 1.0 : 0.0;
+ stptr--;
+ break;
+ case OP_EQ:
+ if(stptr<1){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr-1] = stack[stptr-1] == stack[stptr] ? 1.0 : 0.0;
+ stptr--;
+ break;
+ case OP_IF:
+ if(stptr<2){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr-2] = stack[stptr-2] != 0.0 ? stack[stptr-1] : stack[stptr];
+ stptr--;
+ stptr--;
+ break;
+ case OP_UN:
+ if(stptr<0){
+ rrd_set_error("RPN stack underflow");
+ return -1;
+ }
+ stack[stptr] = isnan(stack[stptr]) ? 1.0 : 0.0;
+ break;
+ case OP_END:
+ break;
+ }
+ }
+ if(stptr!=0){
+ rrd_set_error("RPN final stack size != 1");
+ return -1;
+ }
+ im->gdes[gdi].data[++dataidx] = stack[0];
+ }
+ }
+ return 0;
+}
+#undef dc_stacksize
+
+/* massage data so, that we get one value for each x coordinate in the graph */
+int
+data_proc( image_desc_t *im ){
+ long i,ii;
+ double pixstep = (double)(im->end-im->start)
+ /(double)im->xsize; /* how much time
+ passes in one pixel */
+ double paintval;
+ double minval=DNAN,maxval=DNAN;
+
+ unsigned long gr_time;
+
+ /* memory for the processed data */
+ for(i=0;i<im->gdes_c;i++){
+ if((im->gdes[i].gf==GF_LINE1) ||
+ (im->gdes[i].gf==GF_LINE2) ||
+ (im->gdes[i].gf==GF_LINE3) ||
+ (im->gdes[i].gf==GF_AREA) ||
+ (im->gdes[i].gf==GF_STACK)){
+ if((im->gdes[i].p_data = malloc((im->xsize +1)
+ * sizeof(rrd_value_t)))==NULL){
+ rrd_set_error("malloc data_proc");
+ return -1;
+ }
+ }
+ }
+
+ for(i=0;i<im->xsize;i++){
+ long vidx;
+ gr_time = im->start+pixstep*i; /* time of the
+ current step */
+ paintval=0.0;
+
+ for(ii=0;ii<im->gdes_c;ii++){
+ switch(im->gdes[ii].gf){
+ case GF_LINE1:
+ case GF_LINE2:
+ case GF_LINE3:
+ case GF_AREA:
+ paintval = 0.0;
+ case GF_STACK:
+ vidx = im->gdes[ii].vidx;
+ paintval +=
+ im->gdes[vidx].data[
+ (unsigned long)(
+ (double)(gr_time
+ - im->gdes[vidx].start + im->gdes[vidx].step
+ )
+ / (double)im->gdes[vidx].step
+ )
+
+ *im->gdes[vidx].ds_cnt
+ +im->gdes[vidx].ds];
+
+ im->gdes[ii].p_data[i] = paintval;
+
+ if (! isnan(paintval)){
+ if (isnan(minval) || paintval < minval)
+ minval = paintval;
+ if (isnan(maxval) || paintval > maxval)
+ maxval = paintval;
+ }
+ break;
+ case GF_PRINT:
+ case GF_GPRINT:
+ case GF_COMMENT:
+ case GF_HRULE:
+ case GF_VRULE:
+ case GF_DEF:
+ case GF_CDEF:
+ break;
+ }
+ }
+ }
+
+ /* if min or max have not been asigned a value this is because
+ there was no data in the graph ... this is not good ...
+ lets set these to dummy values then ... */
+
+ if (isnan(minval)) minval = 0.0;
+ if (isnan(maxval)) maxval = 1.0;
+
+ /* adjust min and max values */
+ if (isnan(im->minval)
+ || ((!im->logarithmic && !im->rigid) /* don't adjust low-end with log scale */
+ && im->minval > minval))
+ im->minval = minval;
+ if (isnan(im->maxval)
+ || (!im->rigid
+ && im->maxval < maxval)){
+ if (im->logarithmic)
+ im->maxval = maxval * 1.1;
+ else
+ im->maxval = maxval;
+ }
+ /* make sure min and max are not equal */
+ if (im->minval == im->maxval) {
+ im->maxval *= 1.01;
+ if (! im->logarithmic) {
+ im->minval *= 0.99;
+ }
+
+ /* make sure min and max are not both zero */
+ if (im->maxval == 0.0) {
+ im->maxval = 1.0;
+ }
+
+ }
+ return 0;
+}
+
+
+
+/* identify the point where the first gridline, label ... gets placed */
+
+time_t
+find_first_time(
+ time_t start, /* what is the initial time */
+ enum tmt_en baseint, /* what is the basic interval */
+ long basestep /* how many if these do we jump a time */
+ )
+{
+ struct tm *tm;
+ tm = localtime(&start);
+ switch(baseint){
+ case TMT_SECOND:
+ tm->tm_sec -= tm->tm_sec % basestep; break;
+ case TMT_MINUTE:
+ tm->tm_sec=0;
+ tm->tm_min -= tm->tm_min % basestep;
+ break;
+ case TMT_HOUR:
+ tm->tm_sec=0;
+ tm->tm_min = 0;
+ tm->tm_hour -= tm->tm_hour % basestep; break;
+ case TMT_DAY:
+ /* we do NOT look at the basestep for this ... */
+ tm->tm_sec=0;
+ tm->tm_min = 0;
+ tm->tm_hour = 0; break;
+ case TMT_WEEK:
+ /* we do NOT look at the basestep for this ... */
+ tm->tm_sec=0;
+ tm->tm_min = 0;
+ tm->tm_hour = 0;
+ tm->tm_mday -= tm->tm_wday -1 ; break; /* -1 because we want the monday */
+ if (tm->tm_wday==0) tm->tm_mday -= 7; /* we want the *previous* monday */
+ case TMT_MONTH:
+ tm->tm_sec=0;
+ tm->tm_min = 0;
+ tm->tm_hour = 0;
+ tm->tm_mday = 1;
+ tm->tm_mon -= tm->tm_mon % basestep; break;
+
+ case TMT_YEAR:
+ tm->tm_sec=0;
+ tm->tm_min = 0;
+ tm->tm_hour = 0;
+ tm->tm_mday = 1;
+ tm->tm_mon = 0;
+ tm->tm_year -= (tm->tm_year+1900) % basestep;
+
+ }
+ return mktime(tm);
+}
+/* identify the point where the next gridline, label ... gets placed */
+time_t
+find_next_time(
+ time_t current, /* what is the initial time */
+ enum tmt_en baseint, /* what is the basic interval */
+ long basestep /* how many if these do we jump a time */
+ )
+{
+ struct tm *tm;
+ time_t madetime;
+ tm = localtime(¤t);
+ do {
+ switch(baseint){
+ case TMT_SECOND:
+ tm->tm_sec += basestep; break;
+ case TMT_MINUTE:
+ tm->tm_min += basestep; break;
+ case TMT_HOUR:
+ tm->tm_hour += basestep; break;
+ case TMT_DAY:
+ tm->tm_mday += basestep; break;
+ case TMT_WEEK:
+ tm->tm_mday += 7*basestep; break;
+ case TMT_MONTH:
+ tm->tm_mon += basestep; break;
+ case TMT_YEAR:
+ tm->tm_year += basestep;
+ }
+ madetime = mktime(tm);
+ } while (madetime == -1); /* this is necessary to skip impssible times
+ like the daylight saving time skips */
+ return madetime;
+
+}
+
+/* create a grid on the graph. it determines what to do
+ from the values of xsize, start and end */
+/* the xaxis labels are determined from the number of seconds per pixel
+ in the requested graph */
+
+
+void gator( gdImagePtr gif, int x, int y){
+
+ int li[]={0,0,1, 0,4,5, 0,8,9, 0,12,14, 0,17,17, 0,21,21,
+ 0,24,24, 0,34,34, 0,40,42, 0,45,45, 0,48,49, 0,52,54,
+ 0,61,61, 0,64,66, 0,68,70, 0,72,74, 0,76,76, 0,78,78,
+ 0,80,82, 0,84,85,
+ 1,0,0, 1,2,2, 1,4,4, 1,6,6, 1,8,8, 1,10,10,
+ 1,13,13, 1,16,16, 1,18,18, 1,20,20, 1,22,22, 1,24,24,
+ 1,34,34, 1,41,41, 1,44,44, 1,46,46, 1,48,48, 1,50,50,
+ 1,53,53, 1,60,60, 1,62,62, 1,64,64, 1,69,69, 1,73,73,
+ 1,76,76, 1,78,78, 1,80,80, 1,84,84, 1,86,86,
+ 2,0,1, 2,4,5, 2,8,8, 2,10,10, 2,13,13, 2,16,16,
+ 2,18,18, 2,20,20, 2,22,22, 2,24,24, 2,33,33, 2,41,41,
+ 2,44,44, 2,46,46, 2,48,49, 2,53,53, 2,60,60, 2,62,62,
+ 2,64,65, 2,69,69, 2,73,73, 2,76,77, 2,80,81, 2,84,85,
+ 3,0,0, 3,2,2, 3,4,4, 3,6,6, 3,8,8, 3,10,10,
+ 3,13,13, 3,16,16, 3,18,18, 3,20,20, 3,22,22, 3,24,24,
+ 3,32,32, 3,41,41, 3,44,44, 3,46,46, 3,48,48, 3,50,50,
+ 3,53,53, 3,60,60, 3,62,62, 3,64,64, 3,69,69, 3,73,73,
+ 3,76,76, 3,78,78, 3,80,80, 3,84,84, 3,86,86,
+ 4,0,0, 4,2,2, 4,4,4, 4,6,6, 4,8,9, 4,13,13,
+ 4,17,17, 4,21,21, 4,24,26, 4,32,32, 4,41,41, 4,45,45,
+ 4,48,49, 4,52,54, 4,61,61, 4,64,66, 4,69,69, 4,72,74,
+ 4,76,76, 4,78,78, 4,80,82, 4,84,84};
+ int i,ii;
+ for(i=0; i<DIM(li); i=i+3)
+ for(ii=y+li[i+1]; ii<=y+li[i+2];ii++)
+ gdImageSetPixel(gif,x-li[i],ii,graph_col[GRC_GRID].i);
+}
+
+/* calculate values required for PRINT and GPRINT functions */
+
+int
+print_calc(image_desc_t *im, char ***prdata)
+{
+ long i,ii,validsteps;
+ double printval;
+ int graphelement = 0;
+ long vidx;
+ int max_ii;
+ int prlines = 1;
+ for(i=0;i<im->gdes_c;i++){
+ switch(im->gdes[i].gf){
+ case GF_PRINT:
+ prlines++;
+ if((*prdata = realloc(*prdata,prlines*sizeof(char *)))==NULL){
+ rrd_set_error("realloc prdata");
+ return 0;
+ }
+ case GF_GPRINT:
+ vidx = im->gdes[i].vidx;
+ max_ii =((im->gdes[vidx].end
+ - im->gdes[vidx].start)
+ /im->gdes[vidx].step
+ *im->gdes[vidx].ds_cnt);
+ printval = DNAN;
+ validsteps = 0;
+ for(ii=im->gdes[vidx].ds;
+ ii < max_ii;
+ ii+=im->gdes[vidx].ds_cnt){
+ if (isnan(im->gdes[vidx].data[ii]))
+ continue;
+ if (isnan(printval)){
+ printval = im->gdes[vidx].data[ii];
+ validsteps++;
+ continue;
+ }
+
+ switch (im->gdes[i].cf){
+ case CF_AVERAGE:
+ validsteps++;
+ printval += im->gdes[vidx].data[ii];
+ break;
+ case CF_MINIMUM:
+ printval = min( printval, im->gdes[vidx].data[ii]);
+ break;
+ case CF_MAXIMUM:
+ printval = max( printval, im->gdes[vidx].data[ii]);
+ break;
+ case CF_LAST:
+ printval = im->gdes[vidx].data[ii];
+ }
+ }
+ if (im->gdes[i].cf == CF_AVERAGE)
+ if (validsteps > 1) {
+ printval = (printval / validsteps);
+ }
+ if (im->gdes[i].gf == GF_PRINT){
+ (*prdata)[prlines-2] = malloc((strlen(im->gdes[i].format)+100)*sizeof(char));
+ sprintf((*prdata)[prlines-2],im->gdes[i].format,printval);
+ (*prdata)[prlines-1] = NULL;
+ } else {
+ /* GF_GPRINT */
+ sprintf(im->gdes[i].legend,im->gdes[i].format,printval);
+ graphelement = 1;
+ }
+ break;
+ case GF_COMMENT:
+ case GF_LINE1:
+ case GF_LINE2:
+ case GF_LINE3:
+ case GF_AREA:
+ case GF_STACK:
+ case GF_HRULE:
+ case GF_VRULE:
+ case GF_DEF:
+ case GF_CDEF:
+ graphelement = 1;
+ break;
+ }
+ }
+ return graphelement;
+}
+
+
+/* place legends with color spots */
+void
+leg_place(image_desc_t *im)
+{
+
+ /* graph labels */
+ int interleg = gdFontSmall->w*2;
+ int box = gdFontSmall->h*1.2;
+ int border = gdFontSmall->w*2;
+ int fill=0, fill_last;
+ int leg_c = 0;
+ int leg_x = border, leg_y = im->ygif;
+ int leg_cc;
+ int glue = 0;
+ int i,ii, mark = 0;
+ char prt_fctn; /*special printfunctions */
+
+ for(i=0;i<im->gdes_c;i++){
+ fill_last = fill;
+
+ leg_cc = strlen(im->gdes[i].legend);
+
+ /* is there a controle code ant the end of the legend string ? */
+ if (leg_cc >= 2 && im->gdes[i].legend[leg_cc-2] == '\\') {
+ prt_fctn = im->gdes[i].legend[leg_cc-1];
+ im->gdes[i].legend[leg_cc-2] = '\0';
+ leg_cc -= 2;
+ } else {
+ prt_fctn = '\0';
+ }
+
+ if (leg_cc != 0 ){
+ if (fill > 0)
+ fill += interleg;
+ if (im->gdes[i].gf != GF_GPRINT &&
+ im->gdes[i].gf != GF_COMMENT)
+ fill += box;
+ fill += leg_cc * gdFontSmall->w;
+ leg_c++;
+ }
+
+ if (prt_fctn == '\0') {
+ if (i == im->gdes_c -1 ) prt_fctn ='l';
+
+ /* is it time to place the legends ? */
+ if (fill > im->xgif - 2*border){
+ if (leg_c > 1) {
+ /* go back one */
+ i--;
+ fill = fill_last;
+ leg_c--;
+ prt_fctn = 'j';
+ } else {
+ prt_fctn = 'l';
+ }
+
+ }
+ }
+
+
+ if (prt_fctn != '\0'){
+ leg_x = border;
+ if (leg_c >= 2 && prt_fctn == 'j') {
+ glue = (im->xgif - fill - 2* border) / (leg_c-1);
+ /* if (glue > 2 * gdFontSmall->w) glue = 0; */
+ } else {
+ glue = 0;
+ }
+ if (prt_fctn =='c') leg_x = (im->xgif - fill) / 2.0;
+ if (prt_fctn =='r') leg_x = im->xgif - fill - border;
+
+ for(ii=mark;ii<=i;ii++){
+ if(im->gdes[ii].legend[0]=='\0')
+ continue;
+ im->gdes[ii].legloc.x = leg_x;
+ im->gdes[ii].legloc.y = leg_y;
+ leg_x = leg_x
+ + strlen(im->gdes[ii].legend)*gdFontSmall->w
+ + interleg
+ + glue;
+ if (im->gdes[ii].gf != GF_GPRINT &&
+ im->gdes[ii].gf != GF_COMMENT)
+ leg_x += box;
+ }
+ leg_y = leg_y + gdFontSmall->h*1.2;
+ if (prt_fctn == 's') leg_y += gdFontSmall->h *0.5;
+ fill = 0;
+ leg_c = 0;
+ mark = ii;
+ }
+ }
+ im->ygif = leg_y+(border+3);
+}
+
+
+
+int
+horizontal_grid(gdImagePtr gif, image_desc_t *im)
+{
+ double range;
+ double scaledrange;
+ int pixel,i;
+ int sgrid,egrid;
+ double gridstep;
+ double scaledstep;
+ char graph_label[100];
+ gdPoint polyPoints[4];
+ int labfact,gridind;
+ int styleMinor[2],styleMajor[2];
+
+ labfact=2;
+ gridind=-1;
+ range = im->maxval - im->minval;
+ scaledrange = range / im->magfact;
+
+ /* does the scale of this graph make it impossible to put lines
+ on it? If so, give up. */
+ if (isnan(scaledrange)) {
+ return 0;
+ }
+
+ styleMinor[0] = graph_col[GRC_GRID].i;
+ styleMinor[1] = gdTransparent;
+
+ styleMajor[0] = graph_col[GRC_MGRID].i;
+ styleMajor[1] = gdTransparent;
+
+ /* find grid spaceing */
+ pixel=1;
+ if(isnan(im->ygridstep)){
+ for(i=0;ylab[i].grid > 0;i++){
+ pixel = im->ysize / (scaledrange / ylab[i].grid);
+ if (gridind == -1 && pixel > 5) {
+ gridind = i;
+ break;
+ }
+ }
+
+ for(i=0; i<4;i++) {
+ if (pixel * ylab[gridind].lfac[i] >= 2 * gdFontSmall->h) {
+ labfact = ylab[gridind].lfac[i];
+ break;
+ }
+ }
+
+ gridstep = ylab[gridind].grid * im->magfact;
+ } else {
+ gridstep = im->ygridstep;
+ labfact = im->ylabfact;
+ }
+
+ polyPoints[0].x=im->xorigin;
+ polyPoints[1].x=im->xorigin+im->xsize;
+ sgrid = (int)( im->minval / gridstep - 1);
+ egrid = (int)( im->maxval / gridstep + 1);
+ scaledstep = gridstep/im->magfact;
+ for (i = sgrid; i <= egrid; i++){
+ polyPoints[0].y=ytr(im,gridstep*i);
+ if ( polyPoints[0].y >= im->yorigin-im->ysize
+ && polyPoints[0].y <= im->yorigin) {
+ if(i % labfact == 0){
+ if (i==0 || im->symbol == ' ') {
+ if(scaledstep < 1){
+ sprintf(graph_label,"%4.1f",scaledstep*i);
+ } else {
+ sprintf(graph_label,"%4.0f",scaledstep*i);
+ }
+ }else {
+ if(scaledstep < 1){
+ sprintf(graph_label,"%4.1f %c",scaledstep*i, im->symbol);
+ } else {
+ sprintf(graph_label,"%4.0f %c",scaledstep*i, im->symbol);
+ }
+ }
+
+ gdImageString(gif, gdFontSmall,
+ (polyPoints[0].x - (strlen(graph_label) *
+ gdFontSmall->w)-7),
+ polyPoints[0].y - gdFontSmall->h/2+1,
+ graph_label, graph_col[GRC_FONT].i);
+
+ gdImageSetStyle(gif, styleMajor, 2);
+
+ gdImageLine(gif, polyPoints[0].x-2,polyPoints[0].y,
+ polyPoints[0].x+2,polyPoints[0].y,graph_col[GRC_MGRID].i);
+ gdImageLine(gif, polyPoints[1].x-2,polyPoints[0].y,
+ polyPoints[1].x+2,polyPoints[0].y,graph_col[GRC_MGRID].i);
+ } else {
+ gdImageSetStyle(gif, styleMinor, 2);
+ gdImageLine(gif, polyPoints[0].x-1,polyPoints[0].y,
+ polyPoints[0].x+1,polyPoints[0].y,graph_col[GRC_GRID].i);
+ gdImageLine(gif, polyPoints[1].x-1,polyPoints[0].y,
+ polyPoints[1].x+1,polyPoints[0].y,graph_col[GRC_GRID].i);
+ }
+ gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
+ polyPoints[1].x,polyPoints[0].y,gdStyled);
+ }
+ }
+/* if(im->minval * im->maxval < 0){
+ polyPoints[0].y=ytr(0);
+ gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
+ polyPoints[1].x,polyPoints[0].y,graph_col[GRC_MGRID].i);
+ } */
+
+ return 1;
+}
+
+/* logaritmic horizontal grid */
+int
+horizontal_log_grid(gdImagePtr gif, image_desc_t *im)
+{
+ double pixpex;
+ int ii,i;
+ int minoridx=0, majoridx=0;
+ char graph_label[100];
+ gdPoint polyPoints[4];
+ int styleMinor[2],styleMajor[2];
+ double value, pixperstep, minstep;
+
+ /* find grid spaceing */
+ pixpex= (double)im->ysize / (log10(im->maxval) - log10(im->minval));
+
+ if (isnan(pixpex)) {
+ return 0;
+ }
+
+ for(i=0;yloglab[i][0] > 0;i++){
+ minstep = log10(yloglab[i][0]);
+ for(ii=1;yloglab[i][ii+1] > 0;ii++){
+ if(yloglab[i][ii+2]==0){
+ minstep = log10(yloglab[i][ii+1])-log10(yloglab[i][ii]);
+ break;
+ }
+ }
+ pixperstep = pixpex * minstep;
+ if(pixperstep > 5){minoridx = i;}
+ if(pixperstep > 2 * gdFontSmall->h){majoridx = i;}
+ }
+
+ styleMinor[0] = graph_col[GRC_GRID].i;
+ styleMinor[1] = gdTransparent;
+
+ styleMajor[0] = graph_col[GRC_MGRID].i;
+ styleMajor[1] = gdTransparent;
+
+ polyPoints[0].x=im->xorigin;
+ polyPoints[1].x=im->xorigin+im->xsize;
+ /* paint minor grid */
+ for (value = pow(10, log10(im->minval)
+ - fmod(log10(im->minval),log10(yloglab[minoridx][0])));
+ value <= im->maxval;
+ value *= yloglab[minoridx][0]){
+ if (value < im->minval) continue;
+ i=0;
+ while(yloglab[minoridx][++i] > 0){
+ polyPoints[0].y = ytr(im,value * yloglab[minoridx][i]);
+ if (polyPoints[0].y <= im->yorigin - im->ysize) break;
+ gdImageSetStyle(gif, styleMinor, 2);
+ gdImageLine(gif, polyPoints[0].x-1,polyPoints[0].y,
+ polyPoints[0].x+1,polyPoints[0].y,graph_col[GRC_GRID].i);
+ gdImageLine(gif, polyPoints[1].x-1,polyPoints[0].y,
+ polyPoints[1].x+1,polyPoints[0].y,graph_col[GRC_GRID].i);
+
+ gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
+ polyPoints[1].x,polyPoints[0].y,gdStyled);
+ }
+ }
+
+ /* paint major grid and labels*/
+ for (value = pow(10, log10(im->minval)
+ - fmod(log10(im->minval),log10(yloglab[majoridx][0])));
+ value <= im->maxval;
+ value *= yloglab[majoridx][0]){
+ if (value < im->minval) continue;
+ i=0;
+ while(yloglab[majoridx][++i] > 0){
+ polyPoints[0].y = ytr(im,value * yloglab[majoridx][i]);
+ if (polyPoints[0].y <= im->yorigin - im->ysize) break;
+ gdImageSetStyle(gif, styleMajor, 2);
+ gdImageLine(gif, polyPoints[0].x-2,polyPoints[0].y,
+ polyPoints[0].x+2,polyPoints[0].y,graph_col[GRC_MGRID].i);
+ gdImageLine(gif, polyPoints[1].x-2,polyPoints[0].y,
+ polyPoints[1].x+2,polyPoints[0].y,graph_col[GRC_MGRID].i);
+
+ gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
+ polyPoints[1].x,polyPoints[0].y,gdStyled);
+ sprintf(graph_label,"%3.0e",value * yloglab[majoridx][i]);
+ gdImageString(gif, gdFontSmall,
+ (polyPoints[0].x - (strlen(graph_label) *
+ gdFontSmall->w)-7),
+ polyPoints[0].y - gdFontSmall->h/2+1,
+ graph_label, graph_col[GRC_FONT].i);
+ }
+ }
+ return 1;
+}
+
+
+void
+vertical_grid(
+ gdImagePtr gif,
+ image_desc_t *im )
+{
+ int xlab_sel; /* which sort of label and grid ? */
+ time_t ti, tilab;
+ long factor;
+ char graph_label[100];
+ gdPoint polyPoints[4]; /* points for filled graph and more*/
+
+ /* style for grid lines */
+ int styleDotted[4];
+
+
+ /* the type of time grid is determined by finding
+ the number of seconds per pixel in the graph */
+
+
+ if(im->xlab_user.minsec == -1){
+ factor=(im->end - im->start)/im->xsize;
+ xlab_sel=0;
+ while ( xlab[xlab_sel+1].minsec != -1
+ && xlab[xlab_sel+1].minsec <= factor){ xlab_sel++; }
+ im->xlab_user.gridtm = xlab[xlab_sel].gridtm;
+ im->xlab_user.gridst = xlab[xlab_sel].gridst;
+ im->xlab_user.mgridtm = xlab[xlab_sel].mgridtm;
+ im->xlab_user.mgridst = xlab[xlab_sel].mgridst;
+ im->xlab_user.labtm = xlab[xlab_sel].labtm;
+ im->xlab_user.labst = xlab[xlab_sel].labst;
+ im->xlab_user.precis = xlab[xlab_sel].precis;
+ im->xlab_user.stst = xlab[xlab_sel].stst;
+ }
+
+ /* y coords are the same for every line ... */
+ polyPoints[0].y = im->yorigin;
+ polyPoints[1].y = im->yorigin-im->ysize;
+
+ /* paint the minor grid */
+ for(ti = find_first_time(im->start,
+ im->xlab_user.gridtm,
+ im->xlab_user.gridst);
+ ti < im->end;
+ ti = find_next_time(ti,im->xlab_user.gridtm,im->xlab_user.gridst)
+ ){
+ /* are we inside the graph ? */
+ if (ti < im->start || ti > im->end) continue;
+ polyPoints[0].x = xtr(im,ti);
+ styleDotted[0] = graph_col[GRC_GRID].i;
+ styleDotted[1] = gdTransparent;
+
+ gdImageSetStyle(gif, styleDotted, 2);
+
+ gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
+ polyPoints[0].x,polyPoints[1].y,gdStyled);
+ gdImageLine(gif, polyPoints[0].x,polyPoints[0].y-1,
+ polyPoints[0].x,polyPoints[0].y+1,graph_col[GRC_GRID].i);
+ gdImageLine(gif, polyPoints[0].x,polyPoints[1].y-1,
+ polyPoints[0].x,polyPoints[1].y+1,graph_col[GRC_GRID].i);
+ }
+
+ /* paint the major grid */
+ for(ti = find_first_time(im->start,
+ im->xlab_user.mgridtm,
+ im->xlab_user.mgridst);
+ ti < im->end;
+ ti = find_next_time(ti,im->xlab_user.mgridtm,im->xlab_user.mgridst)
+ ){
+ /* are we inside the graph ? */
+ if (ti < im->start || ti > im->end) continue;
+ polyPoints[0].x = xtr(im,ti);
+ styleDotted[0] = graph_col[GRC_MGRID].i;
+ styleDotted[1] = gdTransparent;
+ gdImageSetStyle(gif, styleDotted, 2);
+
+ gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
+ polyPoints[0].x,polyPoints[1].y,gdStyled);
+ gdImageLine(gif, polyPoints[0].x,polyPoints[0].y-2,
+ polyPoints[0].x,polyPoints[0].y+2,graph_col[GRC_MGRID].i);
+ gdImageLine(gif, polyPoints[0].x,polyPoints[1].y-2,
+ polyPoints[0].x,polyPoints[1].y+2,graph_col[GRC_MGRID].i);
+ }
+ /* paint the labels below the graph */
+ for(ti = find_first_time(im->start,
+ im->xlab_user.labtm,
+ im->xlab_user.labst);
+ ti <= im->end;
+ ti = find_next_time(ti,im->xlab_user.labtm,im->xlab_user.labst)
+ ){
+ int gr_pos,width;
+ tilab= ti + im->xlab_user.precis/2; /* correct time for the label */
+
+#if HAVE_STRFTIME
+ strftime(graph_label,99,im->xlab_user.stst,localtime(&tilab));
+#else
+# error "your libc has no strftime I guess we'll abort the exercise here."
+#endif
+ width=strlen(graph_label) * gdFontSmall->w;
+ gr_pos=xtr(im,tilab) - width/2;
+ if (gr_pos >= im->xorigin
+ && gr_pos + width <= im->xorigin+im->xsize)
+ gdImageString(gif, gdFontSmall,
+ gr_pos, polyPoints[0].y+4,
+ graph_label, graph_col[GRC_FONT].i);
+ }
+
+}
+
+
+void
+axis_paint(
+ image_desc_t *im,
+ gdImagePtr gif
+ )
+{
+ /* draw x and y axis */
+ gdImageLine(gif, im->xorigin+im->xsize,im->yorigin,
+ im->xorigin+im->xsize,im->yorigin-im->ysize,
+ graph_col[GRC_GRID].i);
+
+ gdImageLine(gif, im->xorigin,im->yorigin-im->ysize,
+ im->xorigin+im->xsize,im->yorigin-im->ysize,
+ graph_col[GRC_GRID].i);
+
+ gdImageLine(gif, im->xorigin-4,im->yorigin,
+ im->xorigin+im->xsize+4,im->yorigin,
+ graph_col[GRC_FONT].i);
+
+ gdImageLine(gif, im->xorigin,im->yorigin,
+ im->xorigin,im->yorigin-im->ysize,
+ graph_col[GRC_GRID].i);
+
+ /* arrow for X axis direction */
+ gdImageLine(gif, im->xorigin+im->xsize+4, im->yorigin-3, im->xorigin+im->xsize+4, im->yorigin+3,graph_col[GRC_ARROW].i);
+ gdImageLine(gif, im->xorigin+im->xsize+4, im->yorigin-3, im->xorigin+im->xsize+9, im->yorigin,graph_col[GRC_ARROW].i);
+ gdImageLine(gif, im->xorigin+im->xsize+4, im->yorigin+3, im->xorigin+im->xsize+9, im->yorigin,graph_col[GRC_ARROW].i);
+
+ /* gdImageLine(gif, im->xorigin+im->xsize-1, im->yorigin-3, im->xorigin+im->xsize-1, im->yorigin+3,graph_col[GRC_MGRID].i);
+ gdImageLine(gif, im->xorigin+im->xsize, im->yorigin-2, im->xorigin+im->xsize, im->yorigin+2,graph_col[GRC_MGRID].i);
+ gdImageLine(gif, im->xorigin+im->xsize+1, im->yorigin-2, im->xorigin+im->xsize+1, im->yorigin+2,graph_col[GRC_MGRID].i);
+ gdImageLine(gif, im->xorigin+im->xsize+2, im->yorigin-2, im->xorigin+im->xsize+2, im->yorigin+2,graph_col[GRC_MGRID].i);
+ gdImageLine(gif, im->xorigin+im->xsize+3, im->yorigin-1, im->xorigin+im->xsize+3, im->yorigin+1,graph_col[GRC_MGRID].i);
+ gdImageLine(gif, im->xorigin+im->xsize+4, im->yorigin-1, im->xorigin+im->xsize+4, im->yorigin+1,graph_col[GRC_MGRID].i);
+ gdImageLine(gif, im->xorigin+im->xsize+5, im->yorigin, im->xorigin+im->xsize+5, im->yorigin,graph_col[GRC_MGRID].i); */
+
+
+
+}
+
+void
+grid_paint(
+ image_desc_t *im,
+ gdImagePtr gif
+ )
+{
+ long i;
+ int boxH=8, boxV=8;
+ int res;
+ gdPoint polyPoints[4]; /* points for filled graph and more*/
+
+ /* draw 3d border */
+ gdImageLine(gif,0,0,im->xgif-1,0,graph_col[GRC_SHADEA].i);
+ gdImageLine(gif,1,1,im->xgif-2,1,graph_col[GRC_SHADEA].i);
+ gdImageLine(gif,0,0,0,im->ygif-1,graph_col[GRC_SHADEA].i);
+ gdImageLine(gif,1,1,1,im->ygif-2,graph_col[GRC_SHADEA].i);
+ gdImageLine(gif,im->xgif-1,0,im->xgif-1,im->ygif-1,graph_col[GRC_SHADEB].i);
+ gdImageLine(gif,0,im->ygif-1,im->xgif-1,im->ygif-1,graph_col[GRC_SHADEB].i);
+ gdImageLine(gif,im->xgif-2,1,im->xgif-2,im->ygif-2,graph_col[GRC_SHADEB].i);
+ gdImageLine(gif,1,im->ygif-2,im->xgif-2,im->ygif-2,graph_col[GRC_SHADEB].i);
+
+
+ vertical_grid(gif, im);
+
+ /* dont draw horizontal grid if there is no min and max val */
+ if(im->logarithmic){
+ res = horizontal_log_grid(gif,im);
+ } else {
+ res = horizontal_grid(gif,im);
+ }
+ if (! res) {
+ char *nodata = "No Data found";
+ gdImageString(gif, gdFontMediumBold,
+ im->xgif/2
+ - (strlen(nodata)*gdFontMediumBold->w)/2,
+ (2*im->yorigin-im->ysize) / 2,
+ nodata, graph_col[GRC_FONT].i);
+ }
+
+
+ /* yaxis description */
+ gdImageStringUp(gif, gdFontSmall,
+ 7,
+ (im->yorigin - im->ysize/2
+ +(strlen(im->ylegend)*gdFontSmall->w)/2 ),
+ im->ylegend, graph_col[GRC_FONT].i);
+
+
+ /* graph title */
+ gdImageString(gif, gdFontMediumBold,
+ im->xgif/2
+ - (strlen(im->title)*gdFontMediumBold->w)/2,
+ 8,
+ im->title, graph_col[GRC_FONT].i);
+
+ /* graph labels */
+
+ for(i=0;i<im->gdes_c;i++){
+ if(im->gdes[i].legend[0] =='\0')
+ continue;
+
+ if(im->gdes[i].gf != GF_GPRINT && im->gdes[i].gf != GF_COMMENT){
+
+ polyPoints[0].x = im->gdes[i].legloc.x;
+ polyPoints[0].y = im->gdes[i].legloc.y+1;
+ polyPoints[1].x = polyPoints[0].x+boxH;
+ polyPoints[2].x = polyPoints[0].x+boxH;
+ polyPoints[3].x = polyPoints[0].x;
+ polyPoints[1].y = polyPoints[0].y;
+ polyPoints[2].y = polyPoints[0].y+boxV;
+ polyPoints[3].y = polyPoints[0].y+boxV;
+ gdImageFilledPolygon(gif,polyPoints,4,im->gdes[i].col.i);
+ gdImagePolygon(gif,polyPoints,4,graph_col[GRC_FRAME].i);
+
+ gdImageString(gif, gdFontSmall,
+ polyPoints[0].x+boxH+6,
+ polyPoints[0].y-1,
+ im->gdes[i].legend,
+ graph_col[GRC_FONT].i);
+ } else {
+ polyPoints[0].x = im->gdes[i].legloc.x;
+ polyPoints[0].y = im->gdes[i].legloc.y;
+
+ gdImageString(gif, gdFontSmall,
+ polyPoints[0].x,
+ polyPoints[0].y,
+ im->gdes[i].legend,
+ graph_col[GRC_FONT].i);
+ }
+ }
+
+
+ gator(gif, (int) im->xgif-5, 5);
+
+}
+
+
+gdImagePtr
+MkLineBrush(image_desc_t *im,long cosel, enum gf_en typsel){
+ gdImagePtr brush;
+ int pen;
+ switch (typsel){
+ case GF_LINE1:
+ brush=gdImageCreate(1,1);
+ break;
+ case GF_LINE2:
+ brush=gdImageCreate(2,2);
+ break;
+ case GF_LINE3:
+ brush=gdImageCreate(3,3);
+ break;
+ default:
+ return NULL;
+ }
+
+ gdImageColorTransparent(brush,
+ gdImageColorAllocate(brush, 0, 0, 0));
+
+ pen = gdImageColorAllocate(brush,
+ im->gdes[cosel].col.red,
+ im->gdes[cosel].col.green,
+ im->gdes[cosel].col.blue);
+
+ switch (typsel){
+ case GF_LINE1:
+ gdImageSetPixel(brush,0,0,pen);
+ break;
+ case GF_LINE2:
+ gdImageSetPixel(brush,0,0,pen);
+ gdImageSetPixel(brush,0,1,pen);
+ gdImageSetPixel(brush,1,0,pen);
+ gdImageSetPixel(brush,1,1,pen);
+ break;
+ case GF_LINE3:
+ gdImageSetPixel(brush,1,0,pen);
+ gdImageSetPixel(brush,0,1,pen);
+ gdImageSetPixel(brush,1,1,pen);
+ gdImageSetPixel(brush,2,1,pen);
+ gdImageSetPixel(brush,1,2,pen);
+ break;
+ default:
+ return NULL;
+ }
+ return brush;
+}
+
+/* draw that picture thing ... */
+int
+graph_paint(image_desc_t *im, char ***calcpr)
+{
+ int i,ii;
+ FILE *fo;
+
+ /* gif stuff */
+ gdImagePtr gif,brush;
+
+ double areazero = 0.0;
+ enum gf_en lastgf = GF_LINE1;
+ gdPoint canvas[4], back[4]; /* points for canvas*/
+
+ /* pull the data from the rrd files ... */
+ if(data_fetch(im)==-1)
+ return -1;
+
+ /* evaluate CDEF operations ... */
+ if(data_calc(im)==-1)
+ return -1;
+
+ /* calculate and PRINT and GPRINT definitions. We have to do it at
+ * this point because it will affect the length of the legends
+ * if there are no graph elements we stop here ...
+ */
+ if(print_calc(im,calcpr)==0)
+ return 0;
+
+ /* get actual drawing data and find min and max values*/
+ if(data_proc(im)==-1)
+ return -1;
+
+ if(!im->logarithmic){si_unit(im);} /* identify si magnitude Kilo, Mega Giga ? */
+
+ if(!im->rigid && ! im->logarithmic)
+ expand_range(im); /* make sure the upper and lower limit are
+ sensible values */
+
+ /* init xtr and ytr */
+ /* determine the actual size of the gif to draw. The size given
+ on the cmdline is the graph area. But we need more as we have
+ draw labels and other things outside the graph area */
+
+
+ im->xorigin = 10 + 9 * gdFontSmall->w+gdFontSmall->h;
+ xtr(im,0);
+
+ im->yorigin = 14 + im->ysize;
+ ytr(im,DNAN);
+
+ if(im->title[0] != '\0')
+ im->yorigin += (gdFontMediumBold->h+4);
+
+ im->xgif=20+im->xsize + im->xorigin;
+ im->ygif= im->yorigin+2*gdFontSmall->h;
+
+ /* determine where to place the legends onto the graphics.
+ and set im->ygif to match space requirements for text */
+ leg_place(im);
+
+ gif=gdImageCreate(im->xgif,im->ygif);
+
+ gdImageInterlace(gif, im->interlaced);
+
+ /* allocate colors for the screen elements */
+ for(i=0;i<DIM(graph_col);i++)
+ /* check for user override values */
+ if(im->graph_col[i].red != -1)
+ graph_col[i].i =
+ gdImageColorAllocate( gif,
+ im->graph_col[i].red,
+ im->graph_col[i].green,
+ im->graph_col[i].blue);
+ else
+ graph_col[i].i =
+ gdImageColorAllocate( gif,
+ graph_col[i].red,
+ graph_col[i].green,
+ graph_col[i].blue);
+
+
+ /* allocate colors for the graph */
+ for(i=0;i<im->gdes_c;i++)
+ /* only for elements which have a color defined */
+ if (im->gdes[i].col.red != -1)
+ im->gdes[i].col.i =
+ gdImageColorAllocate(gif,
+ im->gdes[i].col.red,
+ im->gdes[i].col.green,
+ im->gdes[i].col.blue);
+
+
+ /* the actual graph is created by going through the individual
+ graph elements and then drawing them */
+
+ back[0].x = 0;
+ back[0].y = 0;
+ back[1].x = back[0].x+im->xgif;
+ back[1].y = back[0].y;
+ back[2].x = back[1].x;
+ back[2].y = back[0].y+im->ygif;
+ back[3].x = back[0].x;
+ back[3].y = back[2].y;
+
+ gdImageFilledPolygon(gif,back,4,graph_col[GRC_BACK].i);
+
+ canvas[0].x = im->xorigin;
+ canvas[0].y = im->yorigin;
+ canvas[1].x = canvas[0].x+im->xsize;
+ canvas[1].y = canvas[0].y;
+ canvas[2].x = canvas[1].x;
+ canvas[2].y = canvas[0].y-im->ysize;
+ canvas[3].x = canvas[0].x;
+ canvas[3].y = canvas[2].y;
+
+ gdImageFilledPolygon(gif,canvas,4,graph_col[GRC_CANVAS].i);
+
+ if (im->minval > 0.0)
+ areazero = im->minval;
+ if (im->maxval < 0.0)
+ areazero = im->maxval;
+
+ axis_paint(im,gif);
+
+ for(i=0;i<im->gdes_c;i++){
+
+ switch(im->gdes[i].gf){
+ case GF_CDEF:
+ case GF_DEF:
+ case GF_PRINT:
+ case GF_GPRINT:
+ case GF_COMMENT:
+ case GF_HRULE:
+ case GF_VRULE:
+ break;
+ case GF_LINE1:
+ case GF_LINE2:
+ case GF_LINE3:
+ case GF_AREA:
+
+ lastgf = im->gdes[i].gf;
+ case GF_STACK:
+ if (im->gdes[i].col.i != -1){
+ /* GF_LINE and frined */
+ if(lastgf == GF_LINE1 || lastgf == GF_LINE2 || lastgf == GF_LINE3 ){
+ brush = MkLineBrush(im,i,lastgf);
+ gdImageSetBrush(gif, brush);
+ for(ii=1;ii<im->xsize;ii++){
+ if (isnan(im->gdes[i].p_data[ii-1]) ||
+ isnan(im->gdes[i].p_data[ii]))
+ continue;
+ gdImageLine(gif,
+ ii+im->xorigin-1,ytr(im,im->gdes[i].p_data[ii-1]),
+ ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
+ gdBrushed);
+
+ }
+ gdImageDestroy(brush);
+ }
+ else
+ /* GF_AREA STACK type*/
+ if (im->gdes[i].gf == GF_STACK )
+ for(ii=0;ii<im->xsize;ii++){
+ if ((i>0 && isnan(im->gdes[i-1].p_data[ii])) ||
+ isnan(im->gdes[i].p_data[ii]))
+ continue;
+ gdImageLine(gif,
+ ii+im->xorigin,ytr(im,im->gdes[i-1].p_data[ii]),
+ ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
+ im->gdes[i].col.i);
+ }
+
+ else /* simple GF_AREA */
+ for(ii=0;ii<im->xsize;ii++){
+ if (isnan(im->gdes[i].p_data[ii]))
+ continue;
+ gdImageLine(gif,
+ ii+im->xorigin,ytr(im,areazero),
+ ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
+ im->gdes[i].col.i);
+ }
+ }
+
+ break;
+ }
+ }
+
+ grid_paint(im,gif);
+
+ /* the RULES are the last thing to paint ... */
+ for(i=0;i<im->gdes_c;i++){
+
+ switch(im->gdes[i].gf){
+ case GF_HRULE:
+ if(im->gdes[i].yrule >= im->minval
+ && im->gdes[i].yrule <= im->maxval)
+ gdImageLine(gif,
+ im->xorigin,ytr(im,im->gdes[i].yrule),
+ im->xorigin+im->xsize,ytr(im,im->gdes[i].yrule),
+ im->gdes[i].col.i);
+ break;
+ case GF_VRULE:
+ if(im->gdes[i].xrule >= im->start
+ && im->gdes[i].xrule <= im->end)
+ gdImageLine(gif,
+ xtr(im,im->gdes[i].xrule),im->yorigin,
+ xtr(im,im->gdes[i].xrule),im->yorigin-im->ysize,
+ im->gdes[i].col.i);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (strcmp(im->graphfile,"-")==0) {
+ fo = stdout;
+ } else {
+ if ((fo = fopen(im->graphfile,"wb")) == NULL) {
+ perror("rrd_graph gif write:");
+ rrd_set_error("cannot open %s for write",im->graphfile);
+ return (-1);
+ }
+ }
+ gdImageGif(gif, fo);
+ if (strcmp(im->graphfile,"-") != 0)
+ fclose(fo);
+ gdImageDestroy(gif);
+ return 0;
+}
+
+
+/*****************************************************
+ * graph stuff
+ *****************************************************/
+
+int
+gdes_alloc(image_desc_t *im){
+
+ long def_step = (im->end-im->start)/im->xsize;
+
+ im->gdes_c++;
+
+ if ((im->gdes = (graph_desc_t *) realloc(im->gdes, (im->gdes_c)
+ * sizeof(graph_desc_t)))==NULL){
+ rrd_set_error("realloc graph_descs");
+ return -1;
+ }
+
+
+ im->gdes[im->gdes_c-1].step=def_step;
+ im->gdes[im->gdes_c-1].start=im->start;
+ im->gdes[im->gdes_c-1].end=im->end;
+ im->gdes[im->gdes_c-1].vname[0]='\0';
+ im->gdes[im->gdes_c-1].data=NULL;
+ im->gdes[im->gdes_c-1].ds_namv=NULL;
+ im->gdes[im->gdes_c-1].data_first=0;
+ im->gdes[im->gdes_c-1].p_data=NULL;
+ im->gdes[im->gdes_c-1].rpnp=NULL;
+ im->gdes[im->gdes_c-1].col.red = -1;
+ im->gdes[im->gdes_c-1].col.i=-1;
+ im->gdes[im->gdes_c-1].legend[0]='\0';
+ im->gdes[im->gdes_c-1].rrd[0]='\0';
+ im->gdes[im->gdes_c-1].ds=-1;
+ im->gdes[im->gdes_c-1].p_data=NULL;
+ return 0;
+}
+
+/* copies input untill the first unescaped colon is found
+ or until input ends. backslashes have to be escaped as well */
+int
+scan_for_col(char *input, int len, char *output)
+{
+ int inp,outp=0;
+ for (inp=0;
+ inp < len &&
+ input[inp] != ':' &&
+ input[inp] != '\0';
+ inp++){
+ if (input[inp] == '\\' &&
+ input[inp+1] != '\0' &&
+ input[inp+1] == ':')
+ output[outp++] = input[++inp];
+ else
+ output[outp++] = input[inp];
+ }
+ output[outp] = '\0';
+ return inp;
+}
+
+int
+rrd_graph(int argc, char **argv, char ***prdata, int *xsize, int *ysize)
+{
+
+ image_desc_t im;
+ int i;
+ long long_tmp,start_tmp,end_tmp;
+ char scan_gtm[12],scan_mtm[12],scan_ltm[12],col_nam[12];
+ char symname[100];
+ unsigned int col_red,col_green,col_blue;
+ long scancount;
+ int linepass = 0; /* stack can only follow directly after LINE* AREA or STACK */
+#ifdef WANT_AT_STYLE_TIMESPEC
+ struct time_value start_tv, end_tv;
+ char *parsetime_error = NULL;
+ int start_tmp_is_ok = 0,
+ end_tmp_is_ok = 0;
+#endif
+
+ /* default values */
+ end_tmp = time(NULL);
+ start_tmp = -24*3600;
+#ifdef WANT_AT_STYLE_TIMESPEC
+ end_tv.type = ABSOLUTE_TIME;
+ end_tv.tm = *localtime(&end_tmp);
+ end_tv.offset = 0;
+
+ start_tv.type = RELATIVE_TO_END_TIME;
+ start_tv.tm = *localtime(&end_tmp); /* to init tm_zone and tm_gmtoff */
+ start_tv.offset = -24*3600;/* to be compatible with the original code. */
+ start_tv.tm.tm_sec = 0; /** alternatively we could set tm_mday to -1 */
+ start_tv.tm.tm_min = 0; /** but this would yield -23(25) hours offset */
+ start_tv.tm.tm_hour = 0; /** twice a year, when DST is coming in or */
+ start_tv.tm.tm_mday = 0; /** out of effect */
+ start_tv.tm.tm_mon = 0;
+ start_tv.tm.tm_year = 0;
+ start_tv.tm.tm_wday = 0;
+ start_tv.tm.tm_yday = 0;
+ start_tv.tm.tm_isdst = -1; /* for mktime to guess */
+#endif
+ im.xlab_user.minsec = -1;
+ im.xgif=0;
+ im.ygif=0;
+ im.xsize = 400;
+ im.ysize = 100;
+ im.ylegend[0] = '\0';
+ im.title[0] = '\0';
+ im.minval = DNAN;
+ im.maxval = DNAN;
+ im.interlaced = 0;
+ im.rigid = 0;
+ im.logarithmic = 0;
+ im.ygridstep = DNAN;
+ im.base = 1000;
+ im.gdes_c = 0;
+ im.gdes = NULL;
+
+
+ for(i=0;i<DIM(graph_col);i++)
+ im.graph_col[i].red=-1;
+
+
+ while (1){
+ static struct option long_options[] =
+ {
+ {"start", required_argument, 0, 's'},
+ {"end", required_argument,0,'e'},
+ {"x-grid", required_argument,0,'x'},
+ {"y-grid", required_argument,0,'y'},
+ {"vertical-label",required_argument,0,'v'},
+ {"width", required_argument,0,'w'},
+ {"height", required_argument,0,'h'},
+ {"interlaced", no_argument,0,'i'},
+ {"upper-limit",required_argument,0,'u'},
+ {"lower-limit",required_argument,0,'l'},
+ {"rigid", no_argument,0,'r'},
+ {"base", required_argument,0,'b'},
+ {"logarithmic",no_argument,0,'o'},
+ {"color", required_argument,0,'c'},
+ {"title", required_argument,0,'t'},
+ {0,0,0,0}};
+ int option_index = 0;
+ int opt;
+
+
+ opt = getopt_long(argc, argv,
+ "s:e:x:y:v:w:h:iu:b:l:roc:t:",
+ long_options, &option_index);
+
+ if (opt == EOF)
+ break;
+
+ switch(opt) {
+ case 's':
+ if(im.gdes_c > 0){
+ rrd_set_error("set start before graphing");
+ im_free(&im);
+ return -1;
+ }
+#ifdef WANT_AT_STYLE_TIMESPEC
+ {
+ char *endp;
+ start_tmp_is_ok = 0;
+ start_tmp = strtol(optarg, &endp, 0);
+ if (*endp == '\0') /* it was a valid number */
+ if (start_tmp > 31122038 || /* 31 Dec 2038 in DDMMYYYY */
+ start_tmp < 0) {
+ start_tmp_is_ok = 1;
+ break;
+ }
+ if ((parsetime_error = parsetime(optarg, &start_tv))) {
+ rrd_set_error( "start time: %s", parsetime_error );
+ im_free(&im);
+ return -1;
+ }
+ }
+#else
+ start_tmp = atol(optarg);
+#endif
+ break;
+ case 'e':
+ if(im.gdes_c > 0){
+ rrd_set_error("set end before graphing");
+ im_free(&im);
+ return -1;
+ }
+#ifdef WANT_AT_STYLE_TIMESPEC
+ {
+ char *endp;
+ end_tmp_is_ok = 0;
+ end_tmp = strtol(optarg, &endp, 0);
+ if (*endp == '\0') /* it was a valid number */
+ if (end_tmp > 31122038) { /* 31 Dec 2038 in DDMMYYYY */
+ end_tmp_is_ok = 1;
+ break;
+ }
+ if ((parsetime_error = parsetime(optarg, &end_tv))) {
+ rrd_set_error( "end time: %s", parsetime_error );
+ im_free(&im);
+ return -1;
+ }
+ }
+#else
+ end_tmp = atol(optarg);
+#endif
+ break;
+ case 'x':
+ if(sscanf(optarg,
+ "%10[A-Z]:%lu:%10[A-Z]:%lu:%10[A-Z]:%lu:%lu:%100s",
+ scan_gtm,
+ &im.xlab_user.gridst,
+ scan_mtm,
+ &im.xlab_user.mgridst,
+ scan_ltm,
+ &im.xlab_user.labst,
+ &im.xlab_user.precis,
+ im.xlab_form) == 8){
+ if((im.xlab_user.gridtm = tmt_conv(scan_gtm)) == -1){
+ rrd_set_error("unknown keyword %s",scan_gtm);
+ im_free(&im); return -1;
+ } else if ((im.xlab_user.mgridtm = tmt_conv(scan_mtm)) == -1){
+ rrd_set_error("unknown keyword %s",scan_mtm);
+ im_free(&im); return -1;
+ } else if ((im.xlab_user.labtm = tmt_conv(scan_ltm)) == -1){
+ rrd_set_error("unknown keyword %s",scan_ltm);
+ im_free(&im); return -1;
+ }
+ im.xlab_user.minsec = 1;
+ im.xlab_user.stst = im.xlab_form;
+ } else {
+ rrd_set_error("invalid xgrid format");
+ im_free(&im);return -1;
+ }
+ break;
+ case 'y':
+ if(sscanf(optarg,
+ "%lf:%d",
+ &im.ygridstep,
+ &im.ylabfact) == 2) {
+ if(im.ygridstep<=0){
+ rrd_set_error("grid step must be > 0");
+ im_free(&im);return -1;
+ } else if (im.ylabfact < 1){
+ rrd_set_error("label factor must be > 0");
+ im_free(&im);return -1;
+ }
+ } else {
+ rrd_set_error("invalid ygrid format");
+ im_free(&im);return -1;
+ }
+ break;
+ case 'v':
+ strncpy(im.ylegend,optarg,150);
+ break;
+ case 'u':
+ im.maxval = atof(optarg);
+ break;
+ case 'l':
+ im.minval = atof(optarg);
+ break;
+ case 'b':
+ im.base = atol(optarg);
+ if(im.base != 1024 && im.base != 1000 ){
+ rrd_set_error("the only sensible value for base apart from 1000 is 1024");
+ im_free(&im);
+ return -1;
+ }
+ break;
+ case 'w':
+ long_tmp = atol(optarg);
+ if(im.gdes_c > 0){
+ rrd_set_error("set width before graphing");
+ im_free(&im);
+ return -1;
+ }
+ if (long_tmp < 10) {
+ rrd_set_error("width below 10 pixels");
+ im_free(&im);return -1;
+ }
+ im.xsize = long_tmp;
+ break;
+ case 'h':
+ long_tmp = atol(optarg);
+ if (long_tmp < 10) {
+ rrd_set_error("height below 10 pixels");
+ im_free(&im); return -1;
+ }
+ im.ysize = long_tmp;
+ break;
+ case 'i':
+ im.interlaced = 1;
+ break;
+ case 'r':
+ im.rigid = 1;
+ break;
+ case 'o':
+ im.logarithmic = 1;
+ if (isnan(im.minval))
+ im.minval=1;
+ break;
+ case 'c':
+ if(sscanf(optarg,
+ "%10[A-Z]#%2x%2x%2x",
+ col_nam,&col_red,&col_green,&col_blue) == 4){
+ int ci;
+ if((ci=grc_conv(col_nam)) != -1){
+ im.graph_col[ci].red=col_red;
+ im.graph_col[ci].green=col_green;
+ im.graph_col[ci].blue=col_blue;
+ } else {
+ rrd_set_error("invalid color name '%s'",col_nam);
+ }
+ } else {
+ rrd_set_error("invalid color def format");
+ im_free(&im);return -1;
+ }
+ break;
+ case 't':
+ strncpy(im.title,optarg,150);
+ break;
+
+ case '?':
+ rrd_set_error("unknown option '%s'",argv[optind-1]);
+ return(-1);
+ }
+ }
+
+ if (im.logarithmic == 1 && (im.minval <= 0 || isnan(im.minval))){
+ rrd_set_error("for a logarithmic yaxis you must specify a lower-limit > 0");
+ return(-1);
+ }
+
+ strncpy(im.graphfile,argv[optind],254);
+
+#ifdef WANT_AT_STYLE_TIMESPEC
+ if ((start_tv.type == RELATIVE_TO_END_TIME ||
+ (start_tmp_is_ok && start_tmp < 0)) && /* same as the line above */
+ end_tv.type == RELATIVE_TO_START_TIME) {
+ rrd_set_error("the start and end times cannot be specified "
+ "relative to each other");
+ return(-1);
+ }
+
+ if (start_tv.type == RELATIVE_TO_START_TIME) {
+ rrd_set_error("the start time cannot be specified relative to itself");
+ return(-1);
+ }
+
+ if (end_tv.type == RELATIVE_TO_END_TIME) {
+ rrd_set_error("the end time cannot be specified relative to itself");
+ return(-1);
+ }
+
+ /* We don't care to keep all the values in their range,
+ mktime will do this for us */
+ if (start_tv.type == RELATIVE_TO_END_TIME) {
+ if (end_tmp_is_ok)
+ end_tv.tm = *localtime( &end_tmp );
+ start_tv.tm.tm_sec += end_tv.tm.tm_sec;
+ start_tv.tm.tm_min += end_tv.tm.tm_min;
+ start_tv.tm.tm_hour += end_tv.tm.tm_hour;
+ start_tv.tm.tm_mday += end_tv.tm.tm_mday;
+ start_tv.tm.tm_mon += end_tv.tm.tm_mon;
+ start_tv.tm.tm_year += end_tv.tm.tm_year;
+ }
+ if (end_tv.type == RELATIVE_TO_START_TIME) {
+ if (start_tmp_is_ok)
+ start_tv.tm = *localtime( &start_tmp );
+ end_tv.tm.tm_sec += start_tv.tm.tm_sec;
+ end_tv.tm.tm_min += start_tv.tm.tm_min;
+ end_tv.tm.tm_hour += start_tv.tm.tm_hour;
+ end_tv.tm.tm_mday += start_tv.tm.tm_mday;
+ end_tv.tm.tm_mon += start_tv.tm.tm_mon;
+ end_tv.tm.tm_year += start_tv.tm.tm_year;
+ }
+ if (!start_tmp_is_ok)
+ start_tmp = mktime(&start_tv.tm) + start_tv.offset;
+ if (!end_tmp_is_ok)
+ end_tmp = mktime(&end_tv.tm) + end_tv.offset;
+#endif
+
+ if (start_tmp < 0)
+ start_tmp = end_tmp + start_tmp;
+
+ if (start_tmp < 3600*24*365*10){
+ rrd_set_error("the first entry to fetch should be after 1980 (%ld)",start_tmp);
+ return(-1);
+ }
+
+ if (end_tmp < start_tmp) {
+ rrd_set_error("start (%ld) should be less than end (%ld)",
+ start_tmp, end_tmp);
+ return(-1);
+ }
+
+ im.start = start_tmp;
+ im.end = end_tmp;
+
+ for(i=optind+1;i<argc;i++){
+ int argstart=0;
+ int strstart=0;
+ char varname[30],rpnex[256];
+ gdes_alloc(&im);
+ if(sscanf(argv[i],"%10[A-Z0-9]:%n",symname,&argstart)==1){
+ if((im.gdes[im.gdes_c-1].gf=gf_conv(symname))==-1){
+ im_free(&im);
+ rrd_set_error("unknown function '%s'",symname);
+ return -1;
+ }
+ } else {
+ rrd_set_error("can't parse '%s'",argv[i]);
+ im_free(&im);
+ return -1;
+ }
+ /* reset linepass if a non LINE/STACK/AREA operator gets parsed */
+ if (im.gdes[im.gdes_c-1].gf != GF_LINE1 &&
+ im.gdes[im.gdes_c-1].gf != GF_LINE2 &&
+ im.gdes[im.gdes_c-1].gf != GF_LINE3 &&
+ im.gdes[im.gdes_c-1].gf != GF_AREA &&
+ im.gdes[im.gdes_c-1].gf != GF_STACK) {
+ linepass = 0;
+ }
+ /* allow \: to use : in strings */
+
+
+ /* if we are still alive we got a valid graph operator */
+
+ switch(im.gdes[im.gdes_c-1].gf){
+ case GF_PRINT:
+ case GF_GPRINT:
+ if(sscanf(
+ &argv[i][argstart],
+ "%29[^#:]:" CF_NAM_FMT ":%n",
+ varname,symname,&strstart) == 2){
+ scan_for_col(&argv[i][argstart+strstart],FMT_LEG_LEN,im.gdes[im.gdes_c-1].format);
+ if((im.gdes[im.gdes_c-1].vidx=find_var(&im,varname))==-1){
+ im_free(&im);
+ rrd_set_error("unknown variable '%s'",varname);
+ return -1;
+ }
+ if((im.gdes[im.gdes_c-1].cf=cf_conv(symname))==-1){
+ im_free(&im);
+ return -1;
+ }
+
+ } else {
+ im_free(&im);
+ rrd_set_error("can't parse '%s'",&argv[i][argstart]);
+ return -1;
+ }
+ break;
+ case GF_COMMENT:
+ if(strlen(&argv[i][argstart])>FMT_LEG_LEN) argv[i][argstart+FMT_LEG_LEN-3]='\0' ;
+ strcpy(im.gdes[im.gdes_c-1].legend, &argv[i][argstart]);
+ break;
+ case GF_HRULE:
+ if(sscanf(
+ &argv[i][argstart],
+ "%lf#%2x%2x%2x:%n",
+ &im.gdes[im.gdes_c-1].yrule,
+ &col_red,&col_green,&col_blue,
+ &strstart) >= 4){
+ im.gdes[im.gdes_c-1].col.red = col_red;
+ im.gdes[im.gdes_c-1].col.green = col_green;
+ im.gdes[im.gdes_c-1].col.blue = col_blue;
+ if(strstart <= 0){
+ im.gdes[im.gdes_c-1].legend[0] = '\0';
+ } else {
+ scan_for_col(&argv[i][argstart+strstart],FMT_LEG_LEN,im.gdes[im.gdes_c-1].legend);
+ }
+ } else {
+ im_free(&im);
+ rrd_set_error("can't parse '%s'",&argv[i][argstart]);
+ return -1;
+ }
+ break;
+ case GF_VRULE:
+ if(sscanf(
+ &argv[i][argstart],
+ "%lu#%2x%2x%2x:%n",
+ &im.gdes[im.gdes_c-1].xrule,
+ &col_red,
+ &col_green,
+ &col_blue,
+ &strstart) >= 4){
+ im.gdes[im.gdes_c-1].col.red = col_red;
+ im.gdes[im.gdes_c-1].col.green = col_green;
+ im.gdes[im.gdes_c-1].col.blue = col_blue;
+ if(strstart <= 0){
+ im.gdes[im.gdes_c-1].legend[0] = '\0';
+ } else {
+ scan_for_col(&argv[i][argstart+strstart],FMT_LEG_LEN,im.gdes[im.gdes_c-1].legend);
+ }
+ } else {
+ im_free(&im);
+ rrd_set_error("can't parse '%s'",&argv[i][argstart]);
+ return -1;
+ }
+ break;
+ case GF_STACK:
+ if(linepass == 0){
+ im_free(&im);
+ rrd_set_error("STACK must follow AREA, LINE or STACK");
+ return -1;
+ }
+ case GF_LINE1:
+ case GF_LINE2:
+ case GF_LINE3:
+ case GF_AREA:
+ linepass = 1;
+ if((scancount=sscanf(
+ &argv[i][argstart],
+ "%29[^:#]#%2x%2x%2x:%n",
+ varname,
+ &col_red,
+ &col_green,
+ &col_blue,
+ &strstart))>=1){
+ im.gdes[im.gdes_c-1].col.red = col_red;
+ im.gdes[im.gdes_c-1].col.green = col_green;
+ im.gdes[im.gdes_c-1].col.blue = col_blue;
+ if(strstart <= 0){
+ im.gdes[im.gdes_c-1].legend[0] = '\0';
+ } else {
+ scan_for_col(&argv[i][argstart+strstart],FMT_LEG_LEN,im.gdes[im.gdes_c-1].legend);
+ }
+ if((im.gdes[im.gdes_c-1].vidx=find_var(&im,varname))==-1){
+ im_free(&im);
+ rrd_set_error("unknown variable '%s'",varname);
+ return -1;
+ }
+ if (scancount < 4)
+ im.gdes[im.gdes_c-1].col.red = -1;
+
+ } else {
+ im_free(&im);
+ rrd_set_error("can't parse '%s'",&argv[i][argstart]);
+ return -1;
+ }
+ break;
+ case GF_CDEF:
+ if(sscanf(
+ &argv[i][argstart],
+ "%29[_A-Za-z0-9]=%254[^: ]",
+ im.gdes[im.gdes_c-1].vname,
+ rpnex) != 2){
+ im_free(&im);
+ rrd_set_error("can't parse CDEF '%s'",&argv[i][argstart]);
+ return -1;
+ }
+ /* checking for duplicate DEF CDEFS */
+ if(find_var(&im,im.gdes[im.gdes_c-1].vname) != -1){
+ im_free(&im);
+ rrd_set_error("duplicate variable '%s'",
+ im.gdes[im.gdes_c-1].vname);
+ return -1;
+ }
+ if((im.gdes[im.gdes_c-1].rpnp = str2rpn(&im,rpnex))== NULL){
+ rrd_set_error("invalid rpn expression '%s'", rpnex);
+ im_free(&im);
+ return -1;
+ }
+
+ break;
+ case GF_DEF:
+#ifdef WIN32
+/* count the number of ':', if 2 : short filename, if 3 : complete filename */
+ {
+ char * a; int cnt = 0;
+ for ( a = &argv[i][argstart]; *a !=0; a++ ) {
+ if ( *a == ':' ) cnt++;
+ }
+ if (cnt == 3) {
+ if(sscanf(
+ &argv[i][argstart],
+ "%29[_A-Za-z0-9]=%1[A-Za-z]:%252[^:]:" DS_NAM_FMT ":" CF_NAM_FMT,
+ im.gdes[im.gdes_c-1].vname,
+ im.gdes[im.gdes_c-1].rrd,im.gdes[im.gdes_c-1].rrd+2,
+ im.gdes[im.gdes_c-1].ds_nam,
+ symname) != 5) {
+ im_free(&im);
+ rrd_set_error("can't parse DEF '%s'",&argv[i][argstart]);
+ return -1;
+ }
+ *(im.gdes[im.gdes_c-1].rrd+1) = ':';
+ } else {
+#endif /*WIN32*/
+ if(sscanf(
+ &argv[i][argstart],
+ "%29[_A-Za-z0-9]=%254[^:]:" DS_NAM_FMT ":" CF_NAM_FMT,
+ im.gdes[im.gdes_c-1].vname,
+ im.gdes[im.gdes_c-1].rrd,
+ im.gdes[im.gdes_c-1].ds_nam,
+ symname) != 4){
+ im_free(&im);
+ rrd_set_error("can't parse DEF '%s'",&argv[i][argstart]);
+ return -1;
+ }
+#ifdef WIN32
+ }
+ }
+#endif /*WIN32*/
+
+ /* checking for duplicate DEF CDEFS */
+ if(find_var(&im,im.gdes[im.gdes_c-1].vname) != -1){
+ im_free(&im);
+ rrd_set_error("duplicate variable '%s'",
+ im.gdes[im.gdes_c-1].vname);
+ return -1;
+ }
+ if((im.gdes[im.gdes_c-1].cf=cf_conv(symname))==-1){
+ im_free(&im);
+ rrd_set_error("unknown cf '%s'",symname);
+ return -1;
+ }
+ break;
+ }
+
+ }
+
+
+ if (im.gdes_c==0){
+ rrd_set_error("can't make a graph without contents");
+ im_free(&im);
+ return(-1);
+ }
+
+
+ /* parse rest of arguments containing information on what to draw*/
+
+ if (graph_paint(&im,prdata)==-1){
+ im_free(&im);
+ return -1;
+ }
+ *xsize=im.xgif;
+ *ysize=im.ygif;
+ im_free(&im);
+ return 0;
+}
+
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_last.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_last.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_last.c Sat Jul 13 18:46:03 2002
@@ -0,0 +1,34 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1997, 1998, 1999
+ *****************************************************************************
+ * rrd_last.c
+ *****************************************************************************
+ * Initial version by Russ Wright, @Home Network, 9/28/98
+ *****************************************************************************/
+
+#include "rrd_tool.h"
+
+time_t
+rrd_last(int argc, char **argv)
+{
+ FILE *in_file;
+ time_t lastup;
+
+ rrd_t rrd;
+
+ if(argc < 2){
+ rrd_set_error("please specify an rrd");
+ return(-1);
+ }
+ if(rrd_open(argv[1], &in_file, &rrd, RRD_READONLY)==-1){
+ return(-1);
+ }
+ lastup = rrd.live_head->last_up;
+ rrd_free(&rrd);
+ fclose(in_file);
+ return(lastup);
+}
+
+
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_create.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_create.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_create.c Sat Jul 13 18:46:03 2002
@@ -0,0 +1,332 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1997, 1998, 1999
+ *****************************************************************************
+ * rrd_create.c creates new rrds
+ *****************************************************************************/
+
+#include "rrd_tool.h"
+
+
+int
+rrd_create(int argc, char **argv)
+{
+ rrd_t rrd;
+ long i,long_tmp;
+ time_t last_up;
+#ifdef WANT_AT_STYLE_TIMESPEC
+ struct time_value last_up_tv;
+ char *parsetime_error = NULL;
+ int last_up_is_ok = 0;
+#endif
+
+ /* init rrd clean */
+ rrd_init(&rrd);
+ /* static header */
+ if((rrd.stat_head = calloc(1,sizeof(stat_head_t)))==NULL){
+ rrd_set_error("allocating rrd.stat_head");
+ return(-1);
+ }
+
+ /* live header */
+ if((rrd.live_head = calloc(1,sizeof(live_head_t)))==NULL){
+ rrd_set_error("allocating rrd.live_head");
+ return(-1);
+ }
+
+ /* set some defaults */
+ strcpy(rrd.stat_head->cookie,RRD_COOKIE);
+ strcpy(rrd.stat_head->version,RRD_VERSION);
+ rrd.stat_head->float_cookie = FLOAT_COOKIE;
+ rrd.stat_head->ds_cnt = 0; /* this will be adjusted later */
+ rrd.stat_head->rra_cnt = 0; /* ditto */
+ rrd.stat_head->pdp_step = 300; /* 5 minute default */
+
+ /* a default value */
+ rrd.ds_def = NULL;
+ rrd.rra_def = NULL;
+ last_up = time(NULL);
+ while (1){
+ static struct option long_options[] =
+ {
+ {"start", required_argument, 0, 'b'},
+ {"step", required_argument,0,'s'},
+ {0,0,0,0}
+ };
+ int option_index = 0;
+ int opt;
+ opt = getopt_long(argc, argv, "b:s:",
+ long_options, &option_index);
+
+ if (opt == EOF)
+ break;
+
+ switch(opt) {
+ case 'b':
+#ifdef WANT_AT_STYLE_TIMESPEC
+ {
+ char *endp;
+ last_up_is_ok = 0;
+ last_up = strtol(optarg, &endp, 0);
+ if (*endp == '\0') /* it was a valid number */
+ if (last_up > 31122038 || /* 31 Dec 2038 in DDMMYYYY */
+ last_up < 0) {
+ last_up_is_ok = 1;
+ break;
+ }
+ if ((parsetime_error = parsetime(optarg, &last_up_tv))) {
+ rrd_set_error("last update time: %s", parsetime_error );
+ rrd_free(&rrd);
+ return(-1);
+ }
+ if (last_up_tv.type == RELATIVE_TO_END_TIME ||
+ last_up_tv.type == RELATIVE_TO_START_TIME) {
+ rrd_set_error("specifying time relative to the 'start' "
+ "or 'end' makes no sense here");
+ rrd_free(&rrd);
+ return(-1);
+ }
+ if (!last_up_is_ok)
+ last_up = mktime(&last_up_tv.tm) + last_up_tv.offset;
+ }/* this is for the entire block */
+
+#else
+ last_up = atol(optarg);
+#endif
+ if (last_up < 0) /* if time is negative this means go back from now. */
+ last_up = time(NULL)+last_up;
+ if (last_up < 3600*24*365*10){
+ rrd_set_error("the first entry to the RRD should be after 1980");
+ rrd_free(&rrd);
+ return(-1);
+ }
+ break;
+
+ case 's':
+ long_tmp = atol(optarg);
+ if (long_tmp < 1){
+ rrd_set_error("step size should be no less than one second");
+ rrd_free(&rrd);
+ return(-1);
+ }
+ rrd.stat_head->pdp_step = long_tmp;
+ break;
+
+ case '?':
+ rrd_set_error("unknown option '%s'",argv[optind-1]);
+ rrd_free(&rrd);
+ return(-1);
+ }
+ }
+ rrd.live_head->last_up = last_up;
+
+ for(i=optind+1;i<argc;i++){
+ char minstr[20], maxstr[20];
+ if (strncmp(argv[i],"DS:",3)==0){
+ size_t old_size = sizeof(ds_def_t)*(rrd.stat_head->ds_cnt);
+ if((rrd.ds_def = realloc(rrd.ds_def,
+ old_size+sizeof(ds_def_t)))==NULL){
+ rrd_set_error("allocating rrd.ds_def");
+ rrd_free(&rrd);
+ return(-1);
+ }
+ memset(&rrd.ds_def[rrd.stat_head->ds_cnt], 0, sizeof(ds_def_t));
+ if (sscanf(&argv[i][3],
+ DS_NAM_FMT ":" DST_FMT ":%lu:%18[^:]:%18[^:]",
+ rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
+ rrd.ds_def[rrd.stat_head->ds_cnt].dst,
+ &rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_mrhb_cnt].u_cnt,
+ minstr,maxstr) == 5){
+ if(dst_conv(rrd.ds_def[rrd.stat_head->ds_cnt].dst) == -1){
+ rrd_free(&rrd);
+ return (-1);
+ }
+ if (minstr[0] == 'U' && minstr[1] == 0)
+ rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_min_val].u_val = DNAN;
+ else
+ rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_min_val].u_val = atof(minstr);
+
+ if (maxstr[0] == 'U' && maxstr[1] == 0)
+ rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_max_val].u_val = DNAN;
+ else
+ rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_max_val].u_val = atof(maxstr);
+
+ if (! isnan(rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_min_val].u_val) &&
+ ! isnan(rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_max_val].u_val) &&
+ rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_min_val].u_val
+ >= rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_max_val].u_val ) {
+ rrd_set_error("min must be less than max in DS definition");
+ rrd_free(&rrd);
+ return (-1);
+ }
+ rrd.stat_head->ds_cnt++;
+ } else {
+ rrd_set_error("can't parse argument '%s'",argv[i]);
+ rrd_free(&rrd);
+ return (-1);
+ }
+ } else if (strncmp(argv[i],"RRA:",3)==0){
+ size_t old_size = sizeof(rra_def_t)*(rrd.stat_head->rra_cnt);
+ if((rrd.rra_def = realloc(rrd.rra_def,
+ old_size+sizeof(rra_def_t)))==NULL){
+ rrd_set_error("allocating rrd.rra_def");
+ rrd_free(&rrd);
+ return(-1);
+ }
+ memset(&rrd.rra_def[rrd.stat_head->rra_cnt], 0, sizeof(rra_def_t));
+ if (sscanf(&argv[i][4],
+ CF_NAM_FMT ":%lf:%lu:%lu",
+ rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam,
+ &rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_cdp_xff_val].u_val,
+ &rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt,
+ &rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt) == 4){
+ if(cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) == -1){
+ rrd_free(&rrd);
+ return (-1);
+ }
+ if (rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_cdp_xff_val].u_val<0.0 ||
+ rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_cdp_xff_val].u_val>=1.0) {
+ rrd_set_error("the xff must always be >= 0 and < 1");
+ rrd_free(&rrd);
+ return (-1);
+ }
+ rrd.stat_head->rra_cnt++;
+ }
+ else {
+ rrd_set_error("can't parse argument '%s'",argv[i]);
+ rrd_free(&rrd);
+ return (-1);
+ }
+
+ } else {
+ rrd_set_error("can't parse argument '%s'",argv[i]);
+ rrd_free(&rrd);
+ return -1;
+ }
+ }
+
+
+ if (rrd.stat_head->rra_cnt < 1){
+ rrd_set_error("you must define at least one Round Robin Archive");
+ rrd_free(&rrd);
+ return(-1);
+ }
+
+ if (rrd.stat_head->ds_cnt < 1){
+ rrd_set_error("you must define at least one Data Source");
+ rrd_free(&rrd);
+ return(-1);
+ }
+ return rrd_create_fn(argv[optind],&rrd);
+}
+
+/* create and empty rrd file according to the specs given */
+
+int
+rrd_create_fn(char *file_name, rrd_t *rrd)
+{
+ unsigned long i,ii;
+ FILE *rrd_file;
+ rrd_value_t unknown = DNAN ;
+
+ if ((rrd_file = fopen(file_name,"wb")) == NULL ) {
+ rrd_set_error("can't create '%s'",file_name);
+ free(rrd->stat_head);
+ free(rrd->ds_def);
+ free(rrd->rra_def);
+ return(-1);
+ }
+
+ fwrite(rrd->stat_head,
+ sizeof(stat_head_t), 1, rrd_file);
+
+ fwrite(rrd->ds_def,
+ sizeof(ds_def_t), rrd->stat_head->ds_cnt, rrd_file);
+
+ fwrite(rrd->rra_def,
+ sizeof(rra_def_t), rrd->stat_head->rra_cnt, rrd_file);
+
+ fwrite(rrd->live_head,
+ sizeof(live_head_t),1, rrd_file);
+
+ if((rrd->pdp_prep = calloc(1,sizeof(pdp_prep_t))) == NULL){
+ rrd_set_error("allocating pdp_prep");
+ rrd_free(rrd);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ strcpy(rrd->pdp_prep->last_ds,"UNKN");
+
+ rrd->pdp_prep->scratch[PDP_val].u_val = 0.0;
+ rrd->pdp_prep->scratch[PDP_unkn_sec_cnt].u_cnt =
+ rrd->live_head->last_up % rrd->stat_head->pdp_step;
+
+ for(i=0; i < rrd->stat_head->ds_cnt; i++)
+ fwrite( rrd->pdp_prep,sizeof(pdp_prep_t),1,rrd_file);
+
+ if((rrd->cdp_prep = calloc(1,sizeof(cdp_prep_t))) == NULL){
+ rrd_set_error("allocating cdp_prep");
+ rrd_free(rrd);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ /* can not be zero because we don't know nothing ... */
+ rrd->cdp_prep->scratch[CDP_val].u_val = DNAN;
+ for(i=0; i < rrd->stat_head->rra_cnt; i++) {
+
+ /* startup missing pdp count */
+ rrd->cdp_prep->scratch[CDP_unkn_pdp_cnt].u_cnt =
+ ((rrd->live_head->last_up -
+ rrd->pdp_prep->scratch[PDP_unkn_sec_cnt].u_cnt)
+ % (rrd->stat_head->pdp_step
+ * rrd->rra_def[i].pdp_cnt)) / rrd->stat_head->pdp_step;
+
+
+ for(ii=0; ii < rrd->stat_head->ds_cnt; ii++) {
+ fwrite( rrd->cdp_prep,sizeof(cdp_prep_t),1,rrd_file);
+ }
+ }
+
+ /* now, we must make sure that the rest of the rrd
+ struct is properly initialized */
+
+ if((rrd->rra_ptr = calloc(1,sizeof(rra_ptr_t))) == NULL) {
+ rrd_set_error("allocating rra_ptr");
+ rrd_free(rrd);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ rrd->rra_ptr->cur_row = 0;
+ for(i=0; i <rrd->stat_head->rra_cnt; i++)
+ fwrite( rrd->rra_ptr,
+ sizeof(rra_ptr_t), 1,rrd_file);
+
+
+
+ /* write the empty data area */
+ for(i=0;
+ i < rrd->stat_head->rra_cnt;
+ i++)
+ {
+ for(ii=0;
+ ii < rrd->rra_def[i].row_cnt
+ * rrd->stat_head->ds_cnt;
+ ii++){
+ fwrite(&unknown,sizeof(rrd_value_t),1,rrd_file);
+ }
+ }
+
+ /* lets see if we had an error */
+ if(ferror(rrd_file)){
+ rrd_set_error("a file error occurred while creating '%s'",file_name);
+ fclose(rrd_file);
+ rrd_free(rrd);
+ return(-1);
+ }
+
+ fclose(rrd_file);
+ rrd_free(rrd);
+ return (0);
+}
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/ntconfig.h
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/ntconfig.h (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/ntconfig.h Sat Jul 13 18:46:03 2002
@@ -0,0 +1,10 @@
+/* config.h.nt: what configure _would_ say, if it ran on NT */
+
+#define STDC_HEADERS 1
+
+/* Define if you have the strftime function. */
+#define HAVE_STRFTIME 1
+
+/* Define if you have the <math.h> header file. */
+#define HAVE_MATH_H 1
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_dump.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_dump.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_dump.c Sat Jul 13 18:46:03 2002
@@ -0,0 +1,154 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1997, 1998, 1999
+ *****************************************************************************
+ * rrd_dump Display a RRD
+ *****************************************************************************
+ * $Id: rrd_dump.c,v 1.5 1998/03/08 12:35:11 oetiker Exp oetiker $
+ * $Log: rrd_dump.c,v $
+ *****************************************************************************/
+
+#include "rrd_tool.h"
+
+int
+rrd_dump(int argc, char **argv)
+{
+ int i,ii,iii,full=0;
+ time_t now;
+ char somestring[255];
+ rrd_value_t my_cdp;
+
+ FILE *in_file;
+ rrd_t rrd;
+
+
+ while (1){
+ static struct option long_options[] =
+ {
+ {"full", no_argument, 0, 'f'},
+ {0,0,0,0}
+ };
+ int option_index = 0;
+ int opt;
+ opt = getopt_long(argc, argv, "f",
+ long_options, &option_index);
+ if (opt == EOF)
+ break;
+
+ switch(opt) {
+ case 'f':
+ full=1;
+ break;
+ case '?':
+ rrd_set_error("unknown option '%s'",argv[optind-1]);
+ return(-1);
+ }
+ }
+
+ if(optind >= argc){
+ rrd_set_error("please specify an rrd");
+ return(-1);
+ }
+ if(rrd_open(argv[optind],&in_file,&rrd, RRD_READONLY)==-1){
+ return(-1);
+ }
+ puts("RRD Header");
+ puts("---------------------------");
+ puts("");
+ puts("* stat_head");
+ printf("\tcookie: '%s'\n",rrd.stat_head->cookie);
+ printf("\tversion: '%s'\n",rrd.stat_head->version);
+ printf("\tfloat_cookie: %e\n",rrd.stat_head->float_cookie);
+
+ printf("\tds_cnt: %lu\n",rrd.stat_head->ds_cnt);
+ printf("\trra_cnt: %lu\n",rrd.stat_head->rra_cnt);
+ printf("\tpdp_step: %lu seconds\n",rrd.stat_head->pdp_step);
+
+ for(i=0;i<rrd.stat_head->ds_cnt;i++){
+ printf("\n* ds_def[%i]\n",i);
+ printf("\tds-nam: %s\n",rrd.ds_def[i].ds_nam);
+ printf("\tdst: %s\n",rrd.ds_def[i].dst);
+ printf("\tds_mrhb: %lu\n",rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt);
+ printf("\tmax_val: %e\n",rrd.ds_def[i].par[DS_max_val].u_val);
+ printf("\tmin_val: %e\n",rrd.ds_def[i].par[DS_min_val].u_val);
+ }
+
+ for(i=0;i<rrd.stat_head->rra_cnt;i++){
+ printf("\n* rra_def[%i]\n",i);
+ printf("\tcf_name: %s\n",rrd.rra_def[i].cf_nam);
+ printf("\trow_cnt: %lu\n",rrd.rra_def[i].row_cnt);
+ printf("\tpdp_cnt: %lu\n",rrd.rra_def[i].pdp_cnt);
+ }
+
+ printf("\n* live_head\n");
+#if HAVE_STRFTIME
+ strftime(somestring,200,"%Y-%m-%d %H:%M:%S",
+ localtime(&rrd.live_head->last_up));
+#else
+# error "Need strftime"
+#endif
+ printf("\tlast_up: '%lu' %s\n",
+ rrd.live_head->last_up,somestring);
+
+ printf("\n* pdp_prep\n");
+ for(i=0;i<rrd.stat_head->ds_cnt;i++){
+ printf("\n (ds='%s')\n",rrd.ds_def[i].ds_nam);
+
+
+ printf("\tlast_ds: '%s'\n",rrd.pdp_prep[i].last_ds);
+ printf("\tvalue: %e\n",rrd.pdp_prep[i].scratch[PDP_val].u_val);
+ printf("\tunkn_sec: %lu seconds\n",
+ rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
+ }
+
+ printf("\n* cdp_prep");
+ for(i=0;i<rrd.stat_head->rra_cnt;i++){
+ printf("\n (rra=%i)\n",i);
+ for(ii=0;ii<rrd.stat_head->ds_cnt;ii++){
+ printf("\n (ds=%s)\n",rrd.ds_def[ii].ds_nam);
+ printf("\tvalue: %e\n",
+ rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_val].u_val);
+ printf("\tunkn_pdp: %lu pdp\n",
+ rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_unkn_pdp_cnt].u_cnt);
+ }
+ }
+
+ for(i=0;i<rrd.stat_head->rra_cnt;i++){
+ printf("\n* rra_ptr[%i]\n",i);
+ printf("\tcur_row: %lu\n",rrd.rra_ptr[i].cur_row);
+ }
+
+ if (full) {
+ puts("");
+ puts("RRD Contents");
+ puts("-----------------------");
+ puts("");
+ for(i=0;i<rrd.stat_head->rra_cnt;i++){
+ printf("[%3i]:\n",i);
+ now = (rrd.live_head->last_up
+ - rrd.live_head->last_up % (rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step)
+ - rrd.rra_ptr[i].cur_row * rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step);
+ for(ii=0;ii<rrd.rra_def[i].row_cnt;ii++){
+ if (rrd.rra_ptr[i].cur_row==ii) {
+ printf("-> ");
+ } else {
+ printf(" ");
+ }
+ printf("%10lu",now);
+ now += rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step;
+ if (rrd.rra_ptr[i].cur_row==ii)
+ now -= rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step*rrd.rra_def[i].row_cnt;
+
+ for(iii=0;iii<rrd.stat_head->ds_cnt;iii++){
+ fread(&my_cdp,sizeof(rrd_value_t),1,in_file);
+
+ printf(" %12.3f",my_cdp);
+ }
+ printf("\n");
+ }
+ }
+ }
+ rrd_free(&rrd);
+ fclose(in_file);
+ return(0);
+}
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_diff.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_diff.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_diff.c Sat Jul 13 18:46:03 2002
@@ -0,0 +1,89 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1999
+ * This code is stolen from rateup (mrtg-2.x) by Dave Rand
+ *****************************************************************************
+ * diff calculate the difference between two very long integers available as
+ * strings
+ *****************************************************************************
+ * $Id: diff.c,v 1.1 1998/10/08 18:21:45 oetiker Exp oetiker $
+ * $Log: diff.c,v $
+ * Revision 1.1 1998/10/08 18:21:45 oetiker
+ * Initial revision
+ *
+ * Revision 1.3 1998/02/06 21:10:52 oetiker
+ * removed max define .. it is now in rrd_tool.h
+ *
+ * Revision 1.2 1997/12/07 20:38:03 oetiker
+ * ansified
+ *
+ * Revision 1.1 1997/11/28 23:31:59 oetiker
+ * Initial revision
+ *
+ *****************************************************************************/
+
+#include "rrd_tool.h"
+
+double
+rrd_diff(char *a, char *b)
+{
+ char res[LAST_DS_LEN+1], *a1, *b1, *r1, *fix;
+ int c,x,m;
+
+ while (!isdigit((int)*a) || *a==0)
+ a++;
+ fix=a;
+ while (isdigit((int)*fix))
+ fix++;
+ *fix = 0; /* maybe there is some non digit data in the string */
+ while (!isdigit((int)*b) || *b==0)
+ b++;
+ fix=b;
+ while (isdigit((int)*fix))
+ fix++;
+ *fix = 0; /* maybe there is some non digit data in the string */
+ if(!isdigit((int)*a) || !isdigit((int)*b))
+ return DNAN;
+ a1 = &a[strlen(a)-1];
+ m = max(strlen(a),strlen(b));
+ if (m > LAST_DS_LEN) return DNAN; /* result string too short */
+
+ r1 = &res[m+1];
+ for (b1 = res;b1 <= r1; b1++) *b1 = ' ';
+ b1 = &b[strlen(b)-1];
+ r1[1] = 0; /* Null terminate result */
+ c = 0;
+ for (x=0; x<m; x++) {
+ if (a1 >= a && b1 >= b) {
+ *r1 = ((*a1 - c) - *b1) + '0';
+ } else if (a1 >= a) {
+ *r1 = (*a1 - c);
+ } else {
+ *r1 = ('0' - *b1 - c) + '0';
+ }
+ if (*r1 < '0') {
+ *r1 += 10;
+ c=1;
+ } else
+ if (*r1 > '9') { /* 0 - 10 */
+ *r1 -= 10;
+ c=1;
+ } else {
+ c=0;
+ }
+ a1--;b1--;r1--;
+ }
+ if (c) {
+ r1 = &res[m+1];
+ for (x=0; isdigit((int)*r1) && x<m; x++,r1--) {
+ *r1 = ('9' - *r1 + c) + '0';
+ if (*r1 > '9') {
+ *r1 -= 10;
+ c=1;
+ } else {
+ c=0;
+ }
+ }
+ return(-atof(res));
+ } else
+ return(atof(res));
+}
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_tune.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_tune.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_tune.c Sat Jul 13 18:46:03 2002
@@ -0,0 +1,159 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1997, 1998, 1999
+ *****************************************************************************
+ * change header parameters of an rrd
+ *****************************************************************************
+ * $Id: rrd_dump.c,v 1.5 1998/03/08 12:35:11 oetiker Exp oetiker $
+ * $Log: rrd_dump.c,v $
+ *****************************************************************************/
+
+#include "rrd_tool.h"
+
+int
+rrd_tune(int argc, char **argv)
+{
+ rrd_t rrd;
+ FILE *rrd_file;
+ int matches;
+ int optcnt = 0;
+ long ds;
+ char ds_nam[DS_NAM_SIZE];
+ char ds_new[DS_NAM_SIZE];
+ long heartbeat;
+ double min;
+ double max;
+ char dst[DST_SIZE];
+
+
+ if(rrd_open(argv[1],&rrd_file,&rrd, RRD_READWRITE)==-1){
+ return -1;
+ }
+
+
+ while (1){
+ static struct option long_options[] =
+ {
+ {"heartbeat", required_argument, 0, 'h'},
+ {"minimum", required_argument, 0, 'i'},
+ {"maximum", required_argument, 0, 'a'},
+ {"data-source-type", required_argument, 0, 'd'},
+ {"data-source-rename", required_argument, 0, 'r'},
+ {0,0,0,0}
+ };
+ int option_index = 0;
+ int opt;
+ opt = getopt_long(argc, argv, "h:i:a:d:r:",
+ long_options, &option_index);
+ if (opt == EOF)
+ break;
+
+ optcnt++;
+ switch(opt) {
+ case 'h':
+ if ((matches = sscanf(optarg, DS_NAM_FMT ":%ld",ds_nam,&heartbeat)) != 2){
+ rrd_set_error("invalid arguments for heartbeat");
+ rrd_free(&rrd);
+ return -1;
+ }
+ if ((ds=ds_match(&rrd,ds_nam))==-1){
+ rrd_free(&rrd);
+ return -1;
+ }
+ rrd.ds_def[ds].par[DS_mrhb_cnt].u_cnt = heartbeat;
+ break;
+
+ case 'i':
+ if ((matches = sscanf(optarg,DS_NAM_FMT ":%lf",ds_nam,&min)) <1){
+ rrd_set_error("invalid arguments for minimum ds value");
+ rrd_free(&rrd);
+ return -1;
+ }
+ if ((ds=ds_match(&rrd,ds_nam))==-1){
+ rrd_free(&rrd);
+ return -1;
+ }
+
+ if(matches == 1)
+ min= DNAN;
+ rrd.ds_def[ds].par[DS_min_val].u_val = min;
+ break;
+
+ case 'a':
+ if ((matches = sscanf(optarg, DS_NAM_FMT ":%lf",ds_nam,&max)) <1){
+ rrd_set_error("invalid arguments for maximum ds value");
+ rrd_free(&rrd);
+ return -1;
+ }
+ if ((ds=ds_match(&rrd,ds_nam))==-1){
+ rrd_free(&rrd);
+ return -1;
+ }
+ if(matches == 1)
+ max= DNAN;
+ rrd.ds_def[ds].par[DS_max_val].u_val = max;
+ break;
+
+ case 'd':
+ if ((matches = sscanf(optarg, DS_NAM_FMT ":" DST_FMT ,ds_nam,dst)) != 2){
+ rrd_set_error("invalid arguments for data source type");
+ rrd_free(&rrd);
+ return -1;
+ }
+ if ((ds=ds_match(&rrd,ds_nam))==-1){
+ rrd_free(&rrd);
+ return -1;
+ }
+ if (dst_conv(dst) == -1){
+ rrd_free(&rrd);
+ return -1;
+ }
+ strncpy(rrd.ds_def[ds].dst,dst,DST_SIZE);
+
+ rrd.pdp_prep[ds].last_ds[0] = 'U';
+ rrd.pdp_prep[ds].last_ds[1] = 'N';
+ rrd.pdp_prep[ds].last_ds[2] = 'K';
+ rrd.pdp_prep[ds].last_ds[3] = 'N';
+ rrd.pdp_prep[ds].last_ds[4] = '\0';
+
+ break;
+ case 'r':
+ if ((matches =
+ sscanf(optarg,DS_NAM_FMT ":" DS_NAM_FMT , ds_nam,ds_new)) != 2){
+ rrd_set_error("invalid arguments for data source type");
+ rrd_free(&rrd);
+ return -1;
+ }
+ if ((ds=ds_match(&rrd,ds_nam))==-1){
+ rrd_free(&rrd);
+ return -1;
+ }
+ strncpy(rrd.ds_def[ds].ds_nam,ds_new,DS_NAM_SIZE);
+ break;
+ case '?':
+ rrd_set_error("unknown option '%s'",argv[optind-1]);
+ rrd_free(&rrd);
+ return -1;
+ }
+ }
+ if(optcnt>0){
+
+ fseek(rrd_file,0,SEEK_SET);
+ fwrite(rrd.stat_head,
+ sizeof(stat_head_t),1, rrd_file);
+ fwrite(rrd.ds_def,
+ sizeof(ds_def_t), rrd.stat_head->ds_cnt, rrd_file);
+ } else {
+ int i;
+ for(i=0;i< rrd.stat_head->ds_cnt;i++)
+ printf("DS[%s] typ: %s\thbt: %ld\tmin: %1.4f\tmax: %1.4f\n",
+ rrd.ds_def[i].ds_nam,
+ rrd.ds_def[i].dst,
+ rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt,
+ rrd.ds_def[i].par[DS_min_val].u_val,
+ rrd.ds_def[i].par[DS_max_val].u_val);
+ }
+ fclose(rrd_file);
+ rrd_free(&rrd);
+ return 0;
+}
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/getopt1.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/getopt1.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/getopt1.c Sat Jul 13 18:46:03 2002
@@ -0,0 +1,189 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+ Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library. Its master source is NOT part of
+ the C library, however. The master source lives in /gd/gnu/lib.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "getopt.h"
+
+#if !defined (__STDC__) || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif /* Not ELIDE_CODE. */
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_tool.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_tool.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_tool.c Sat Jul 13 18:46:04 2002
@@ -0,0 +1,308 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1997, 1998, 1999
+ *****************************************************************************
+ * rrd_tool.c Startup wrapper
+ *****************************************************************************
+ * $Id: rrd_tool.c,v 1.8 1998/03/08 12:35:11 oetiker Exp oetiker $
+ * $Log: rrd_tool.c,v $
+ *****************************************************************************/
+
+#include "rrd_tool.h"
+
+void PrintUsage(void);
+int CountArgs(char *aLine);
+int CreateArgs(char *, char *, int, char **);
+int HandleInputLine(int, char **, FILE*);
+#define TRUE 1
+#define FALSE 0
+#define MAX_LENGTH 10000
+
+
+void PrintUsage(void)
+{
+ printf("\n"
+ "RRD TOOL 0.99.28 Copyright (C) 1999 by Tobias Oetiker <tobi at oetiker.ch>\n\n"
+ "Usage: rrdtool [options] command command_options\n\n"
+ "Valid commands and command_options are listed below.\n\n"
+
+ "* create - create a new RRD\n\n"
+ "\trrdtool create filename [--start|-b start time]\n"
+ "\t\t[--step|-s step]\n"
+ "\t\t[DS:ds-name:DST:heartbeat:min:max] [RRA:CF:xff:steps:rows]\n\n"
+
+ "* dump - dump an RRD\n\n"
+ "\trrdtool dump filename.rrd [--full|-f]\n\n"
+
+ "* last - show last update time for RRD\n\n"
+ "\trrdtool last filename.rrd\n\n"
+
+ "* update - update an RRD\n\n"
+ "\trrdtool update filename\n"
+ "\t\ttime|N:value[:value...]\n\n"
+ "\t\t[ time:value[:value...] ..]\n\n"
+
+ "* fetch - fetch data out of an RRD\n\n"
+ "\trrdtool fetch filename.rrd CF\n"
+ "\t\t[--resolution|-r resolution]\n"
+ "\t\t[--start|-s start] [--end|-e end]\n\n"
+
+ "* graph - generate a graph from one or several RRD\n\n"
+ "\trrdtool graph filename [-s|--start seconds] [-e|--end seconds]\n"
+ "\t\t[-x|--x-grid x-axis grid and label]\n"
+ "\t\t[-y|--y-grid y-axis grid and label]\n"
+ "\t\t[-v|--vertical-label string] [-w|--width pixels]\n"
+ "\t\t[-h|--height pixels] [-o|--logarithmic]\n"
+ "\t\t[-u|--upper-limit value]\n"
+ "\t\t[-l|--lower-limit value] [-r|--rigid]\n"
+ "\t\t[-c|--color COLORTAG#rrggbb] [-t|--title string]\n"
+ "\t\t[DEF:vname=rrd:ds-name:CF]\n"
+ "\t\t[CDEF:vname=rpn-expression]\n"
+ "\t\t[PRINT:vname:CF:format]\n"
+ "\t\t[GPRINT:vname:CF:format]\n"
+ "\t\t[HRULE:value#rrggbb[:legend]]\n"
+ "\t\t[VRULE:value#rrggbb[:legend]]\n"
+ "\t\t[LINE{1|2|3}:vname[#rrggbb[:legend]]]\n"
+ "\t\t[AREA:vname[#rrggbb[:legend]]]\n"
+ "\t\t[STACK:vname[#rrggbb[:legend]]]\n\n"
+
+
+ " * tune - Modify some basic properties of an RRD\n\n"
+ "\trrdtool tune filename\n"
+ "\t\t[--heartbeat|-h ds-name:heartbeat]\n"
+ "\t\t[--data-source-type|-d ds-name:DST\n"
+ "\t\t[--data-source-rename|-r old-name:new-name\n"
+ "\t\t[--minimum|-i ds-name:min] [--maximum|-a ds-name:max]\n\n"
+
+ "RRD TOOL is distributed under the Terms of the GNU General\n"
+ "Public License Version 2. (www.gnu.org/copyleft/gpl.html)\n\n"
+
+ "For more information read the RRD manpages\n\n");
+}
+
+
+int main(int argc, char *argv[])
+{
+ char **myargv;
+ char aLine[MAX_LENGTH];
+
+ if (argc == 1)
+ {
+ PrintUsage();
+ return 0;
+ }
+
+ if ((argc == 2) && (*argv[1] == '-'))
+ {
+#if HAVE_GETRUSAGE
+ struct rusage myusage;
+ struct timeval starttime;
+ struct timeval currenttime;
+ struct timezone tz;
+
+ tz.tz_minuteswest =0;
+ tz.tz_dsttime=0;
+ gettimeofday(&starttime,&tz);
+#endif
+
+ while (fgets(aLine, sizeof(aLine)-1, stdin)){
+ if ((argc = CountArgs(aLine)) == 0) {
+ fprintf(stderr,"ERROR: not enough arguments\n");
+ }
+ if ((myargv = (char **) malloc((argc+1) *
+ sizeof(char *))) == NULL) {
+ perror("malloc");
+ return -1;
+ }
+ if ((argc=CreateArgs(argv[0], aLine, argc, myargv)) < 0) {
+ fprintf(stderr, "ERROR: creating arguments\n");
+ return -1;
+ }
+
+ if (HandleInputLine(argc, myargv, stdout))
+ return -1;
+ free(myargv);
+
+#if HAVE_GETRUSAGE
+ getrusage(RUSAGE_SELF,&myusage);
+ gettimeofday(¤ttime,&tz);
+ printf("OK u:%1.2f s:%1.2f r:%1.2f\n",
+ (double)myusage.ru_utime.tv_sec+
+ (double)myusage.ru_utime.tv_usec/1000000.0,
+ (double)myusage.ru_stime.tv_sec+
+ (double)myusage.ru_stime.tv_usec/1000000.0,
+ (double)(currenttime.tv_sec-starttime.tv_sec)
+ +(double)(currenttime.tv_usec-starttime.tv_usec)
+ /1000000.0);
+#else
+ printf("OK\n");
+#endif
+ fflush(stdout); /* this is important for pipes to work */
+ }
+ }
+ else
+ HandleInputLine(argc, argv, stderr);
+ return 0;
+}
+
+int HandleInputLine(int argc, char **argv, FILE* out)
+{
+ optind=0; /* reset gnu getopt */
+ opterr=0; /* no error messages */
+
+ if (argc < 3
+ || strcmp("help", argv[1]) == 0
+ || strcmp("-h", argv[1]) == 0 ) {
+ PrintUsage();
+ return 0;
+ }
+
+ if (strcmp("create", argv[1]) == 0)
+ rrd_create(argc-1, &argv[1]);
+ else if (strcmp("dump", argv[1]) == 0)
+ rrd_dump(argc-1, &argv[1]);
+ else if (strcmp("last", argv[1]) == 0)
+ printf("%ld\n",rrd_last(argc-1, &argv[1]));
+ else if (strcmp("update", argv[1]) == 0)
+ rrd_update(argc-1, &argv[1]);
+ else if (strcmp("fetch", argv[1]) == 0) {
+ time_t start,end;
+ unsigned long step, ds_cnt,i,ii;
+ rrd_value_t *data,*datai;
+ char **ds_namv;
+ if (rrd_fetch(argc-1, &argv[1],&start,&end,&step,&ds_cnt,&ds_namv,&data) != -1) {
+ datai=data;
+ printf(" ");
+ for (i = 0; i<ds_cnt;i++)
+ printf("%10s",ds_namv[i]);
+ printf ("\n\n");
+ for (i = start; i <= end; i += step){
+ printf("%10lu:", i);
+ for (ii = 0; ii < ds_cnt; ii++)
+ printf("%10.2f", *(datai++));
+ printf("\n");
+ }
+ for (i=0;i<ds_cnt;i++)
+ free(ds_namv[i]);
+ free(ds_namv);
+ free (data);
+ }
+ }
+ else if (strcmp("graph", argv[1]) == 0) {
+ char **calcpr;
+ int xsize, ysize;
+ int i;
+ calcpr = NULL;
+ if( rrd_graph(argc-1, &argv[1], &calcpr, &xsize, &ysize) != -1 ) {
+ if (strcmp(argv[2],"-") != 0)
+ printf ("%dx%d\n",xsize,ysize);
+ if (calcpr) {
+ for(i=0;calcpr[i];i++){
+ if (strcmp(argv[2],"-") != 0)
+ printf("%s\n",calcpr[i]);
+ free(calcpr[i]);
+ }
+ free(calcpr);
+ }
+ }
+
+ } else if (strcmp("tune", argv[1]) == 0)
+ rrd_tune(argc-1, &argv[1]);
+ else {
+ rrd_set_error("unknown function '%s'",argv[1]);
+ }
+ if (rrd_test_error()) {
+ fprintf(out, "ERROR: %s\n",rrd_get_error());
+ rrd_clear_error();
+ }
+ return(0);
+}
+
+int CountArgs(char *aLine)
+{
+ int i=0;
+ int aCount = 0;
+ int inarg = 0;
+ while (aLine[i] == ' ') i++;
+ while (aLine[i] != 0){
+ if((aLine[i]== ' ') && inarg){
+ inarg = 0;
+ }
+ if((aLine[i]!= ' ') && ! inarg){
+ inarg = 1;
+ aCount++;
+ }
+ i++;
+ }
+ return aCount;
+}
+
+/*
+ * CreateArgs - take a string (aLine) and tokenize
+ */
+int CreateArgs(char *pName, char *aLine, int argc, char **argv)
+{
+ char *getP, *putP;
+ char **pargv = argv;
+ char Quote = 0;
+ int inArg = 0;
+ int len;
+
+ len = strlen(aLine);
+ /* remove trailing space and newlines */
+ while (len && aLine[len] <= ' ') {
+ aLine[len] = 0 ; len--;
+ }
+ /* sikp leading blanks */
+ while (*aLine && *aLine <= ' ') aLine++;
+
+ pargv[0] = pName;
+ argc = 1;
+ getP = aLine;
+ putP = aLine;
+ while (*getP){
+ switch (*getP) {
+ case ' ':
+ if (Quote){
+ *(putP++)=*getP;
+ } else
+ if(inArg) {
+ *(putP++) = 0;
+ inArg = 0;
+ }
+ break;
+ case '"':
+ case '\'':
+ if (Quote != 0) {
+ if (Quote == *getP)
+ Quote = 0;
+ else {
+ *(putP++)=*getP;
+ }
+ } else {
+ if(!inArg){
+ pargv[argc++] = putP;
+ inArg=1;
+ }
+ Quote = *getP;
+ }
+ break;
+ default:
+ if(!inArg){
+ pargv[argc++] = putP;
+ inArg=1;
+ }
+ *(putP++)=*getP;
+ break;
+ }
+ getP++;
+ }
+
+ *putP = '\0';
+
+ if (Quote)
+ return -1;
+ else
+ return argc;
+}
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/parsetime.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/parsetime.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/parsetime.c Sat Jul 13 18:46:04 2002
@@ -0,0 +1,857 @@
+/*
+ * parsetime.c - parse time for at(1)
+ * Copyright (C) 1993, 1994 Thomas Koenig
+ *
+ * modifications for english-language times
+ * Copyright (C) 1993 David Parsons
+ *
+ * A lot of modifications and extensions
+ * (including the new syntax being useful for RRDB)
+ * Copyright (C) 1999 Oleg Cherevko (aka Olwi Deer)
+ *
+ * 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. The name of the author(s) may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * The BNF-like specification of the time syntax parsed is below:
+ *
+ * As usual, [ X ] means that X is optional, { X } means that X may
+ * be either omitted or specified as many times as needed,
+ * alternatives are separated by |, brackets are used for grouping.
+ * (# marks the beginning of comment that extends to the end of line)
+ *
+ * TIME-SPECIFICATION ::= TIME-REFERENCE [ OFFSET-SPEC ] |
+ * OFFSET-SPEC |
+ * ( START | END ) OFFSET-SPEC
+ *
+ * TIME-REFERENCE ::= NOW | TIME-OF-DAY-SPEC [ DAY-SPEC-1 ] |
+ * [ TIME-OF-DAY-SPEC ] DAY-SPEC-2
+ *
+ * TIME-OF-DAY-SPEC ::= NUMBER [(':'|'.') NUMBER] [am|pm] | # HH:MM HH.MM HH[MM]
+ * 'noon' | 'midnight' | 'teatime'
+ *
+ * DAY-SPEC-1 ::= NUMBER '/' NUMBER '/' NUMBER | # MM/DD/[YY]YY
+ * NUMBER '.' NUMBER '.' NUMBER | # DD.MM.[YY]YY
+ * NUMBER # DDMM[YY]YY
+ *
+ * DAY-SPEC-2 ::= MONTH-NAME NUMBER [NUMBER] | # Month DD [YY]YY
+ * 'yesterday' | 'today' | 'tomorrow' |
+ * DAY-OF-WEEK
+ *
+ *
+ * OFFSET-SPEC ::= '+'|'-' NUMBER TIME-UNIT { ['+'|'-'] NUMBER TIME-UNIT }
+ *
+ * TIME-UNIT ::= SECONDS | MINUTES | HOURS |
+ * DAYS | WEEKS | MONTHS | YEARS
+ *
+ * NOW ::= 'now' | 'n'
+ *
+ * START ::= 'start' | 's'
+ * END ::= 'end' | 'e'
+ *
+ * SECONDS ::= 'seconds' | 'second' | 'sec' | 's'
+ * MINUTES ::= 'minutes' | 'minute' | 'min' | 'm'
+ * HOURS ::= 'hours' | 'hour' | 'hr' | 'h'
+ * DAYS ::= 'days' | 'day' | 'd'
+ * WEEKS ::= 'weeks' | 'week' | 'wk' | 'w'
+ * MONTHS ::= 'months' | 'month' | 'mon' | 'm'
+ * YEARS ::= 'years' | 'year' | 'yr' | 'y'
+ *
+ * MONTH-NAME ::= 'jan' | 'january' | 'feb' | 'february' | 'mar' | 'march' |
+ * 'apr' | 'april' | 'may' | 'jun' | 'june' | 'jul' | 'july' |
+ * 'aug' | 'august' | 'sep' | 'september' | 'oct' | 'october' |
+ * 'nov' | 'november' | 'dec' | 'december'
+ *
+ * DAY-OF-WEEK ::= 'sunday' | 'sun' | 'monday' | 'mon' | 'tuesday' | 'tue' |
+ * 'wednesday' | 'wed' | 'thursday' | 'thu' | 'friday' | 'fri' |
+ * 'saturday' | 'sat'
+ *
+ *
+ * As you may note, there is an ambiguity with respect to
+ * the 'm' time unit (which can mean either minutes or months).
+ * To cope with this, code tries to read users mind :) by applying
+ * certain heuristics. There are two of them:
+ *
+ * 1. If 'm' is used in context of (i.e. right after the) years,
+ * months, weeks, or days it is assumed to mean months, while
+ * in the context of hours, minutes, and seconds it means minutes.
+ * (e.g., in -1y6m or +3w1m 'm' means 'months', while in
+ * -3h20m or +5s2m 'm' means 'minutes')
+ *
+ * 2. Out of context (i.e. right after the '+' or '-' sign) the
+ * meaning of 'm' is guessed from the number it directly follows.
+ * Currently, if the number absolute value is below 25 it is assumed
+ * that 'm' means months, otherwise it is treated as minutes.
+ * (e.g., -25m == -25 minutes, while +24m == +24 months)
+ *
+ */
+
+/* System Headers */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+/* Local headers */
+
+#include "parsetime.h"
+
+/* Structures and unions */
+
+enum { /* symbols */
+ MIDNIGHT, NOON, TEATIME,
+ PM, AM, YESTERDAY, TODAY, TOMORROW, NOW, START, END,
+ SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS,
+ MONTHS_MINUTES,
+ NUMBER, PLUS, MINUS, DOT, COLON, SLASH, ID, JUNK,
+ JAN, FEB, MAR, APR, MAY, JUN,
+ JUL, AUG, SEP, OCT, NOV, DEC,
+ SUN, MON, TUE, WED, THU, FRI, SAT
+ };
+
+/* the below is for plus_minus() */
+#define PREVIOUS_OP (-1)
+
+/* parse translation table - table driven parsers can be your FRIEND!
+ */
+struct SpecialToken {
+ char *name; /* token name */
+ int value; /* token id */
+};
+static struct SpecialToken VariousWords[] = {
+ { "midnight", MIDNIGHT }, /* 00:00:00 of today or tomorrow */
+ { "noon", NOON }, /* 12:00:00 of today or tomorrow */
+ { "teatime", TEATIME }, /* 16:00:00 of today or tomorrow */
+ { "am", AM }, /* morning times for 0-12 clock */
+ { "pm", PM }, /* evening times for 0-12 clock */
+ { "tomorrow", TOMORROW },
+ { "yesterday", YESTERDAY },
+ { "today", TODAY },
+ { "now", NOW },
+ { "n", NOW },
+ { "start", START },
+ { "s", START },
+ { "end", END },
+ { "e", END },
+
+ { "jan", JAN },
+ { "feb", FEB },
+ { "mar", MAR },
+ { "apr", APR },
+ { "may", MAY },
+ { "jun", JUN },
+ { "jul", JUL },
+ { "aug", AUG },
+ { "sep", SEP },
+ { "oct", OCT },
+ { "nov", NOV },
+ { "dec", DEC },
+ { "january", JAN },
+ { "february", FEB },
+ { "march", MAR },
+ { "april", APR },
+ { "may", MAY },
+ { "june", JUN },
+ { "july", JUL },
+ { "august", AUG },
+ { "september", SEP },
+ { "october", OCT },
+ { "november", NOV },
+ { "december", DEC },
+ { "sunday", SUN },
+ { "sun", SUN },
+ { "monday", MON },
+ { "mon", MON },
+ { "tuesday", TUE },
+ { "tue", TUE },
+ { "wednesday", WED },
+ { "wed", WED },
+ { "thursday", THU },
+ { "thu", THU },
+ { "friday", FRI },
+ { "fri", FRI },
+ { "saturday", SAT },
+ { "sat", SAT },
+ { NULL, 0 } /*** SENTINEL ***/
+};
+
+static struct SpecialToken TimeMultipliers[] = {
+ { "second", SECONDS }, /* seconds multiplier */
+ { "seconds", SECONDS }, /* (pluralized) */
+ { "sec", SECONDS }, /* (generic) */
+ { "s", SECONDS }, /* (short generic) */
+ { "minute", MINUTES }, /* minutes multiplier */
+ { "minutes", MINUTES }, /* (pluralized) */
+ { "min", MINUTES }, /* (generic) */
+ { "m", MONTHS_MINUTES }, /* (short generic) */
+ { "hour", HOURS }, /* hours ... */
+ { "hours", HOURS }, /* (pluralized) */
+ { "hr", HOURS }, /* (generic) */
+ { "h", HOURS }, /* (short generic) */
+ { "day", DAYS }, /* days ... */
+ { "days", DAYS }, /* (pluralized) */
+ { "d", DAYS }, /* (short generic) */
+ { "week", WEEKS }, /* week ... */
+ { "weeks", WEEKS }, /* (pluralized) */
+ { "wk", WEEKS }, /* (generic) */
+ { "w", WEEKS }, /* (short generic) */
+ { "month", MONTHS }, /* week ... */
+ { "months", MONTHS }, /* (pluralized) */
+ { "mon", MONTHS }, /* (generic) */
+ { "year", YEARS }, /* year ... */
+ { "years", YEARS }, /* (pluralized) */
+ { "yr", YEARS }, /* (generic) */
+ { "y", YEARS }, /* (short generic) */
+ { NULL, 0 } /*** SENTINEL ***/
+};
+
+/* File scope variables */
+
+/* context dependant list of specials for parser to recognize,
+ * required for us to be able distinguish between 'mon' as 'month'
+ * and 'mon' as 'monday'
+ */
+static struct SpecialToken *Specials;
+
+static char **scp; /* scanner - pointer at arglist */
+static char scc; /* scanner - count of remaining arguments */
+static char *sct; /* scanner - next char pointer in current argument */
+static int need; /* scanner - need to advance to next argument */
+
+static char *sc_token; /* scanner - token buffer */
+static size_t sc_len; /* scanner - lenght of token buffer */
+static int sc_tokid; /* scanner - token id */
+
+static int need_to_free = 0; /* means that we need deallocating memory */
+
+/* Local functions */
+
+void EnsureMemFree ()
+{
+ if( need_to_free )
+ {
+ free(sc_token);
+ need_to_free = 0;
+ }
+}
+
+/*
+ * A hack to compensate for the lack of the C++ exceptions
+ *
+ * Every function func that might generate parsing "exception"
+ * should return TIME_OK (aka NULL) or pointer to the error message,
+ * and should be called like this: try(func(args));
+ *
+ * [NOTE: when try(...) is used as the only statement in the "if-true"
+ * part of the if statement that also has an "else" part it should be
+ * either enclosed in the curly braces (despite the fact that it looks
+ * like a single statement) or NOT follwed by the ";"]
+ */
+#define try(b) { \
+ char *_e; \
+ if((_e=(b))) \
+ { \
+ EnsureMemFree(); \
+ return _e; \
+ } \
+ }
+
+/*
+ * The panic() function was used in the original code to die, we redefine
+ * it as macro to start the chain of ascending returns that in conjunction
+ * with the try(b) above will simulate a sort of "exception handling"
+ */
+
+#define panic(e) { \
+ EnsureMemFree(); \
+ return (e); \
+ }
+
+/*
+ * ve() and e() are used to set the return error,
+ * the most aprropriate use for these is inside panic(...)
+ */
+#define MAX_ERR_MSG_LEN 1024
+static char errmsg[ MAX_ERR_MSG_LEN ];
+
+static char *
+ve ( char *fmt, va_list ap )
+{
+/* vsnprintf( errmsg, MAX_ERR_MSG_LEN, fmt, ap ); */
+ vsprintf( errmsg, fmt, ap );
+ EnsureMemFree();
+ return( errmsg );
+}
+
+static char *
+e ( char *fmt, ... )
+{
+ char *err;
+ va_list ap;
+ va_start( ap, fmt );
+ err = ve( fmt, ap );
+ va_end( ap );
+ return( err );
+}
+
+/*
+ * parse a token, checking if it's something special to us
+ */
+static int
+parse_token(char *arg)
+{
+ int i;
+
+ for (i=0; Specials[i].name != NULL; i++)
+ if (strcasecmp(Specials[i].name, arg) == 0)
+ return sc_tokid = Specials[i].value;
+
+ /* not special - must be some random id */
+ return sc_tokid = ID;
+} /* parse_token */
+
+
+/*
+ * init_scanner() sets up the scanner to eat arguments
+ */
+static char *
+init_scanner(int argc, char **argv)
+{
+ scp = argv;
+ scc = argc;
+ need = 1;
+ sc_len = 1;
+ while (argc-- > 0)
+ sc_len += strlen(*argv++);
+
+ sc_token = (char *) malloc(sc_len);
+ if( sc_token == NULL )
+ return "Failed to allocate memory";
+ need_to_free = 1;
+ return TIME_OK;
+} /* init_scanner */
+
+/*
+ * token() fetches a token from the input stream
+ */
+static int
+token()
+{
+ int idx;
+
+ while (1) {
+ memset(sc_token, 0, sc_len);
+ sc_tokid = EOF;
+ idx = 0;
+
+ /* if we need to read another argument, walk along the argument list;
+ * when we fall off the arglist, we'll just return EOF forever
+ */
+ if (need) {
+ if (scc < 1)
+ return sc_tokid;
+ sct = *scp;
+ scp++;
+ scc--;
+ need = 0;
+ }
+ /* eat whitespace now - if we walk off the end of the argument,
+ * we'll continue, which puts us up at the top of the while loop
+ * to fetch the next argument in
+ */
+ while (isspace(*sct) || *sct == '_' || *sct == ',' )
+ ++sct;
+ if (!*sct) {
+ need = 1;
+ continue;
+ }
+
+ /* preserve the first character of the new token
+ */
+ sc_token[0] = *sct++;
+
+ /* then see what it is
+ */
+ if (isdigit(sc_token[0])) {
+ while (isdigit(*sct))
+ sc_token[++idx] = *sct++;
+ sc_token[++idx] = 0;
+ return sc_tokid = NUMBER;
+ }
+ else if (isalpha(sc_token[0])) {
+ while (isalpha(*sct))
+ sc_token[++idx] = *sct++;
+ sc_token[++idx] = 0;
+ return parse_token(sc_token);
+ }
+ else switch(sc_token[0]) {
+ case ':': return sc_tokid = COLON;
+ case '.': return sc_tokid = DOT;
+ case '+': return sc_tokid = PLUS;
+ case '-': return sc_tokid = MINUS;
+ case '/': return sc_tokid = SLASH;
+ default: return sc_tokid = JUNK;
+ }
+ } /* while (1) */
+} /* token */
+
+
+/*
+ * expect() gets a token and complins if it's not the token we want
+ */
+static char *
+expect(int desired, char *complain_fmt, ...)
+{
+ va_list ap;
+ va_start( ap, complain_fmt );
+ if (token() != desired) {
+ panic(ve( complain_fmt, ap ));
+ }
+ va_end( ap );
+ return TIME_OK;
+
+} /* expect */
+
+
+/*
+ * plus_minus() is used to parse a single NUMBER TIME-UNIT pair
+ * for the OFFSET-SPEC.
+ * It allso applies those m-guessing euristics.
+ */
+static char *
+plus_minus(struct time_value *ptv, int doop)
+{
+ static int op = PLUS;
+ static int prev_multiplier = -1;
+ int delta;
+
+ if( doop >= 0 )
+ {
+ op = doop;
+ try(expect(NUMBER,"There should be number after '%c'", op == PLUS ? '+' : '-'));
+ prev_multiplier = -1; /* reset months-minutes guessing mechanics */
+ }
+ /* if doop is < 0 then we repeat the previous op
+ * with the prefetched number */
+
+ delta = atoi(sc_token);
+
+ if( token() == MONTHS_MINUTES )
+ {
+ /* hard job to guess what does that -5m means: -5mon or -5min? */
+ switch(prev_multiplier)
+ {
+ case DAYS:
+ case WEEKS:
+ case MONTHS:
+ case YEARS:
+ sc_tokid = MONTHS;
+ break;
+
+ case SECONDS:
+ case MINUTES:
+ case HOURS:
+ sc_tokid = MINUTES;
+ break;
+
+ default:
+ if( delta < 25 ) /* it may be some other value but in the context
+ * of RRD who needs less than 25 min deltas? */
+ sc_tokid = MONTHS;
+ else
+ sc_tokid = MINUTES;
+ }
+ }
+ prev_multiplier = sc_tokid;
+ switch (sc_tokid) {
+ case YEARS:
+ ptv->tm.tm_year += (op == PLUS) ? delta : -delta;
+ return TIME_OK;
+ case MONTHS:
+ ptv->tm.tm_mon += (op == PLUS) ? delta : -delta;
+ return TIME_OK;
+ case WEEKS:
+ delta *= 7;
+ /* FALLTHRU */
+ case DAYS:
+ ptv->tm.tm_mday += (op == PLUS) ? delta : -delta;
+ return TIME_OK;
+ case HOURS:
+ ptv->offset += (op == PLUS) ? delta*60*60 : -delta*60*60;
+ return TIME_OK;
+ case MINUTES:
+ ptv->offset += (op == PLUS) ? delta*60 : -delta*60;
+ return TIME_OK;
+ case SECONDS:
+ ptv->offset += (op == PLUS) ? delta : -delta;
+ return TIME_OK;
+ }
+ panic(e("well-known time unit expected after %d", delta));
+ /* NORETURN */
+ return TIME_OK; /* to make compiler happy :) */
+} /* plus_minus */
+
+
+/*
+ * tod() computes the time of day (TIME-OF-DAY-SPEC)
+ */
+static char *
+tod(struct time_value *ptv)
+{
+ int hour, minute = 0;
+ int tlen;
+
+ hour = atoi(sc_token);
+ tlen = strlen(sc_token);
+
+ /* first pick out the time of day - if it's 4 digits, we assume
+ * a HHMM time, otherwise it's HH (COLON|DOT) MM time
+ */
+ token();
+ if (sc_tokid == COLON || sc_tokid == DOT) {
+ try(expect(NUMBER,
+ "Parsing HH%cMM syntax, expecting MM as number, got none",
+ sc_tokid == DOT ? '.' : ':' ));
+ minute = atoi(sc_token);
+ if (minute > 59) {
+ panic(e("parsing HH%cMM syntax, got MM = %d (>59!)",
+ sc_tokid == DOT ? '.' : ':', minute ));
+ }
+ token();
+ }
+ else if (tlen == 4) {
+ minute = hour%100;
+ if (minute > 59) {
+ panic(e("parsing HHMM syntax, got MM = %d (>59!)", minute ));
+ }
+ hour = hour/100;
+ }
+
+ /* check if an AM or PM specifier was given
+ */
+ if (sc_tokid == AM || sc_tokid == PM) {
+ if (hour > 12) {
+ panic(e("there cannot be more than 12 AM or PM hours"));
+ }
+ if (sc_tokid == PM) {
+ if (hour != 12) /* 12:xx PM is 12:xx, not 24:xx */
+ hour += 12;
+ } else {
+ if (hour == 12) /* 12:xx AM is 00:xx, not 12:xx */
+ hour = 0;
+ }
+ token();
+ }
+ else if (hour > 23) {
+ panic(e("the time-of-day hour > 23"));
+ }
+ ptv->tm.tm_hour = hour;
+ ptv->tm.tm_min = minute;
+ ptv->tm.tm_sec = 0;
+ if (ptv->tm.tm_hour == 24) {
+ ptv->tm.tm_hour = 0;
+ ptv->tm.tm_mday++;
+ }
+ return TIME_OK;
+} /* tod */
+
+
+/*
+ * assign_date() assigns a date, adjusting year as appropriate
+ */
+static char *
+assign_date(struct time_value *ptv, long mday, long mon, long year)
+{
+ if (year > 99) {
+ if (year > 1899)
+ year -= 1900;
+ else {
+ panic(e("invalid year %d (should be either 00-99 or >1900)",
+ year));
+ }
+ } else if( year >= 0 && year < 38 ) {
+ year += 100; /* Allow year 2000-2037 to be specified as */
+ } /* 00-37 until the problem of 2038 year will */
+ /* arise for unices with 32-bit time_t :) */
+ if (year < 0) {
+ panic(e("don't know what's the use of the year %d (negative!)?", year));
+ }
+ if (year < 70) {
+ panic(e("won't handle dates before epoch (01/01/1970), sorry"));
+ }
+
+ ptv->tm.tm_mday = mday;
+ ptv->tm.tm_mon = mon;
+ ptv->tm.tm_year = year;
+ return TIME_OK;
+} /* assign_date */
+
+
+/*
+ * day() picks apart DAY-SPEC-[12]
+ */
+static char *
+day(struct time_value *ptv)
+{
+ long mday, wday, mon, year = ptv->tm.tm_year;
+ int tlen;
+
+ switch (sc_tokid) {
+ case YESTERDAY:
+ ptv->tm.tm_mday--;
+ /* FALLTRHU */
+ case TODAY: /* force ourselves to stay in today - no further processing */
+ token();
+ break;
+ case TOMORROW:
+ ptv->tm.tm_mday++;
+ token();
+ break;
+
+ case JAN: case FEB: case MAR: case APR: case MAY: case JUN:
+ case JUL: case AUG: case SEP: case OCT: case NOV: case DEC:
+ /* do month mday [year]
+ */
+ mon = (sc_tokid-JAN);
+ try(expect(NUMBER,
+ "the day of the month should follow month name"));
+ mday = atol(sc_token);
+ if (token() == NUMBER) {
+ year = atol(sc_token);
+ token();
+ }
+ else
+ year = ptv->tm.tm_year;
+ try(assign_date(ptv, mday, mon, year));
+ break;
+
+ case SUN: case MON: case TUE:
+ case WED: case THU: case FRI:
+ case SAT:
+ /* do a particular day of the week
+ */
+ wday = (sc_tokid-SUN);
+ ptv->tm.tm_mday += (wday - ptv->tm.tm_wday);
+ break;
+ /*
+ mday = ptv->tm.tm_mday;
+ mday += (wday - ptv->tm.tm_wday);
+ ptv->tm.tm_wday = wday;
+
+ try(assign_date(ptv, mday, ptv->tm.tm_mon, ptv->tm.tm_year));
+ break;
+ */
+
+ case NUMBER:
+ /* get numeric DDMM[YY]YY, MM/DD/[YY]YY, or DD.MM.[YY]YY
+ */
+ tlen = strlen(sc_token);
+ mon = atol(sc_token);
+ token();
+
+ if (sc_tokid == SLASH || sc_tokid == DOT) {
+ int sep;
+
+ sep = sc_tokid;
+ try(expect(NUMBER,"there should be %s number after '%c'",
+ sep == DOT ? "month" : "day", sep == DOT ? '.' : '/'));
+ mday = atol(sc_token);
+ if (token() == sep) {
+ try(expect(NUMBER,"there should be year number after '%c'",
+ sep == DOT ? '.' : '/'));
+ year = atol(sc_token);
+ token();
+ }
+
+ /* flip months and days for european timing
+ */
+ if (sep == DOT) {
+ long x = mday;
+ mday = mon;
+ mon = x;
+ }
+ }
+ else if (tlen == 6 || tlen == 8) {
+ if (tlen == 8) {
+ year = (mon % 10000) - 1900;
+ mon /= 10000;
+ }
+ else {
+ year = mon % 100;
+ mon /= 100;
+ }
+ mday = mon / 100;
+ mon %= 100;
+ }
+ else {
+ panic(e("can't parse your date as DDMM[YY]YY"));
+ }
+
+ mon--;
+ if(mon < 0 || mon > 11 ) {
+ panic(e("did you really mean month %d?", mon+1));
+ }
+ if(mday < 1 || mday > 31) {
+ panic(e("I'm afraid that %d is not a valid day of the month",
+ mday));
+ }
+
+ try(assign_date(ptv, mday, mon, year));
+ break;
+ } /* case */
+ return TIME_OK;
+} /* month */
+
+
+/* Global functions */
+
+
+/*
+ * parsetime() is the external interface that takes tspec, parses
+ * it and puts the result in the time_value structure *ptv.
+ * It can return either absolute times (these are ensured to be
+ * correct) or relative time references that are expected to be
+ * added to some absolute time value and then normalized by
+ * mktime() The return value is either TIME_OK (aka NULL) or
+ * the pointer to the error message in the case of problems
+ */
+char *
+parsetime(char *tspec, struct time_value *ptv)
+{
+ time_t now = time(NULL);
+ int hr = 0;
+ /* this MUST be initialized to zero for midnight/noon/teatime */
+
+ Specials = VariousWords; /* initialize special words context */
+
+ try(init_scanner( 1, &tspec ));
+
+ /* establish the default time reference */
+ ptv->type = ABSOLUTE_TIME;
+ ptv->offset = 0;
+ ptv->tm = *localtime(&now);
+ ptv->tm.tm_isdst = -1; /* ?not needed? */
+
+ token();
+ switch (sc_tokid) {
+ case PLUS:
+ case MINUS:
+ break; /* jump to OFFSET-SPEC part */
+
+ case START:
+ ptv->type = RELATIVE_TO_START_TIME;
+ goto KeepItRelative;
+ case END:
+ ptv->type = RELATIVE_TO_END_TIME;
+ KeepItRelative:
+ ptv->tm.tm_sec = 0;
+ ptv->tm.tm_min = 0;
+ ptv->tm.tm_hour = 0;
+ ptv->tm.tm_mday = 0;
+ ptv->tm.tm_mon = 0;
+ ptv->tm.tm_year = 0;
+ /* FALLTHRU */
+ case NOW:
+ {
+ int time_reference = sc_tokid;
+ token();
+ if( sc_tokid == PLUS || sc_tokid == MINUS )
+ break;
+ if( time_reference != NOW ) {
+ panic(e("'start' or 'end' MUST be followed by +|- offset"));
+ }
+ else
+ if( sc_tokid != EOF ) {
+ panic(e("'now' can be followed only be +|- offset"));
+ }
+ };
+ break;
+
+ /* Only absolute time specifications below */
+ case NUMBER:
+ try(tod(ptv));
+ try(day(ptv));
+ break;
+
+ /* evil coding for TEATIME|NOON|MIDNIGHT - we've initialised
+ * hr to zero up above, then fall into this case in such a
+ * way so we add +12 +4 hours to it for teatime, +12 hours
+ * to it for noon, and nothing at all for midnight, then
+ * set our rettime to that hour before leaping into the
+ * month scanner
+ */
+ case TEATIME:
+ hr += 4;
+ /* FALLTHRU */
+ case NOON:
+ hr += 12;
+ /* FALLTHRU */
+ case MIDNIGHT:
+ if (ptv->tm.tm_hour >= hr) {
+ ptv->tm.tm_mday++;
+ ptv->tm.tm_wday++;
+ }
+ ptv->tm.tm_hour = hr;
+ ptv->tm.tm_min = 0;
+ token();
+ /* fall through to month setting */
+ /* FALLTHRU */
+ default:
+ try(day(ptv));
+ break;
+ } /* ugly case statement */
+
+ /*
+ * the OFFSET-SPEC part
+ *
+ * (NOTE, the sc_tokid was prefetched for us by the previous code)
+ */
+ if( sc_tokid == PLUS || sc_tokid == MINUS ) {
+ Specials = TimeMultipliers; /* switch special words context */
+ while( sc_tokid == PLUS || sc_tokid == MINUS ||
+ sc_tokid == NUMBER ) {
+ if( sc_tokid == NUMBER ) {
+ try(plus_minus(ptv, PREVIOUS_OP ));
+ } else
+ try(plus_minus(ptv, sc_tokid));
+ token(); /* We will get EOF eventually but that's OK, since
+ token() will return us as many EOFs as needed */
+ }
+ }
+
+ /* now we should be at EOF */
+ if( sc_tokid != EOF ) {
+ panic(e("unparsable trailing text: '...%s%s'", sc_token, sct ));
+ }
+
+ ptv->tm.tm_isdst = -1; /* for mktime to guess DST status */
+ if( ptv->type == ABSOLUTE_TIME )
+ if( mktime( &ptv->tm ) == -1 ) { /* normalize & check */
+ /* can happen for "nonexistent" times, e.g. around 3am */
+ /* when winter -> summer time correction eats a hour */
+ panic(e("the specified time is incorrect (out of range?)"));
+ }
+ return TIME_OK;
+} /* parsetime */
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_tool.h
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_tool.h (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_tool.h Sat Jul 13 18:46:04 2002
@@ -0,0 +1,133 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1997,1998, 1999
+ *****************************************************************************
+ * rrd_tool.h Common Header File
+ *****************************************************************************
+ * $Id: rrd_tool.h,v 1.5 1998/03/08 12:35:11 oetiker Exp oetiker $
+ * $Log: rrd_tool.h,v $
+ *****************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef _RRD_TOOL_H
+#define _RRD_TOOL_H
+
+#ifdef WIN32
+# include "ntconfig.h"
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+#if HAVE_MATH_H
+# include <math.h>
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#if HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#if HAVE_SYS_TIMES_H
+# include <sys/times.h>
+#endif
+#if HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#if (defined(__svr4__) && defined(__sun__))
+/* Solaris headers (pre 2.6) don't have a getrusage prototype.
+ Use this instead. */
+extern int getrusage(int, struct rusage *);
+#endif /* __svr4__ && __sun__ */
+#endif
+
+#ifdef WANT_AT_STYLE_TIMESPEC
+#include "parsetime.h"
+#endif
+
+#ifndef WIN32
+
+/* unix-only includes */
+#ifndef isnan
+int isnan(double value);
+#endif
+
+#else
+
+/* Win32 only includes */
+
+#include <float.h> /* for _isnan */
+#define isnan _isnan
+
+#endif
+
+/* local include files -- need to be after the system ones */
+#include "getopt.h"
+#include "rrd_format.h"
+
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define DIM(x) (sizeof(x)/sizeof(x[0]))
+
+/* main function blocks */
+int rrd_create(int argc, char **argv);
+int rrd_update(int argc, char **argv);
+int rrd_graph(int argc, char **argv, char ***prdata, int *xsize, int *ysize);
+int rrd_fetch(int argc, char **argv,
+ time_t *start, time_t *end, unsigned long *step,
+ unsigned long *ds_cnt, char ***ds_namv, rrd_value_t **data);
+int rrd_dump(int argc, char **argv);
+int rrd_tune(int argc, char **argv);
+time_t rrd_last(int argc, char **argv);
+
+/* HELPER FUNCTIONS */
+void rrd_set_error(char *fmt,...);
+void rrd_clear_error(void);
+int rrd_test_error(void);
+char *rrd_get_error(void);
+
+int rrd_create_fn(char *file_name, rrd_t *rrd);
+int rrd_fetch_fn(char *filename, enum cf_en cf_idx,
+ time_t *start,time_t *end,
+ unsigned long *step,
+ unsigned long *ds_cnt,
+ char ***ds_namv,
+ rrd_value_t **data);
+void rrd_free(rrd_t *rrd);
+void rrd_init(rrd_t *rrd);
+
+int rrd_open(char *file_name, FILE **in_file, rrd_t *rrd, int rdwr);
+
+
+#define RRD_READONLY 0
+#define RRD_READWRITE 1
+
+enum cf_en cf_conv(char *string);
+enum dst_en dst_conv(char *string);
+long ds_match(rrd_t *rrd,char *ds_nam);
+double rrd_diff(char *a, char *b);
+
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_update.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_update.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd_update.c Sat Jul 13 18:46:04 2002
@@ -0,0 +1,732 @@
+/*****************************************************************************
+ * RRDTOOL 0.99.29 Copyright Tobias Oetiker, 1997, 1998, 1999
+ *****************************************************************************
+ * rrd_update.c RRD Update Function
+ *****************************************************************************
+ * $Id: rrd_update.c,v 1.7 1998/03/08 12:35:11 oetiker Exp oetiker $
+ * $Log: rrd_update.c,v $
+ *****************************************************************************/
+
+#include "rrd_tool.h"
+#include <sys/types.h>
+#include <fcntl.h>
+
+#ifdef WIN32
+ #include <sys/locking.h>
+ #include <sys/stat.h>
+ #include <io.h>
+#else
+ #include <unistd.h>
+#endif
+
+
+/* Prototypes */
+int LockRRD(FILE *rrd_file);
+
+/*#define DEBUG */
+
+int
+rrd_update(int argc, char **argv)
+{
+
+ int arg_i = 2;
+ long i,ii,iii;
+
+ unsigned long rra_begin; /* byte pointer to the rra
+ * area in the rrd file. this
+ * pointer never changes value */
+ unsigned long rra_start; /* byte pointer to the rra
+ * area in the rrd file. this
+ * pointer changes as each rrd is
+ * processed. */
+ unsigned long interval,
+ pre_int,post_int; /* interval between this and
+ * the last run */
+ unsigned long proc_pdp_st; /* which pdp_st was the last
+ * to be processed */
+ unsigned long occu_pdp_st; /* when was the pdp_st
+ * before the last update
+ * time */
+ unsigned long proc_pdp_age; /* how old was the data in
+ * the pdp prep area when it
+ * was last updated */
+ unsigned long occu_pdp_age; /* how long ago was the last
+ * pdp_step time */
+ unsigned long pdp_st; /* helper for cdp_prep
+ * processing */
+ rrd_value_t *pdp_new; /* prepare the incoming data
+ * to be added the the
+ * existing entry */
+ rrd_value_t *pdp_temp; /* prepare the pdp values
+ * to be added the the
+ * cdp values */
+
+ long *tmpl_idx; /* index representing the settings
+ transported by the template index */
+ long tmpl_max = 0;
+
+ FILE *rrd_file;
+ rrd_t rrd;
+ time_t current_time = time(NULL);
+ char **updvals;
+ int wrote_to_file = 0;
+ char *template = NULL;
+
+ rrd_init(&rrd);
+ while (1) {
+ static struct option long_options[] =
+ {
+ {"template", required_argument, 0, 't'},
+ {0,0,0,0}
+ };
+ int option_index = 0;
+ int opt;
+ opt = getopt_long(argc, argv, "t:",
+ long_options, &option_index);
+
+ if (opt == EOF)
+ break;
+
+ switch(opt) {
+ case 't':
+ template = optarg;
+ break;
+
+ case '?':
+ rrd_set_error("unknown option '%s'",argv[optind-1]);
+ rrd_free(&rrd);
+ return(-1);
+ }
+ }
+
+ /* need at least 2 arguments: filename, data. */
+ if (argc-optind < 2) {
+ rrd_set_error("not enough arguments");
+ return -1;
+ }
+
+ if(rrd_open(argv[optind],&rrd_file,&rrd, RRD_READWRITE)==-1){
+ return -1;
+ }
+ rra_begin=ftell(rrd_file);
+ rra_start=rra_begin;
+
+ /* get exclusive lock to whole file.
+ * lock gets removed when we close the file.
+ */
+ if (LockRRD(rrd_file) != 0) {
+ rrd_set_error("could not lock RRD");
+ rrd_free(&rrd);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ if((updvals = malloc( sizeof(char*) * (rrd.stat_head->ds_cnt+1)))==NULL){
+ rrd_set_error("allocating updvals pointer array");
+ rrd_free(&rrd);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ if ((pdp_temp = malloc(sizeof(rrd_value_t)
+ *rrd.stat_head->ds_cnt))==NULL){
+ rrd_set_error("allocating pdp_temp ...");
+ free(updvals);
+ rrd_free(&rrd);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ if ((tmpl_idx = malloc(sizeof(unsigned long)
+ *(rrd.stat_head->ds_cnt+1)))==NULL){
+ rrd_set_error("allocating template_idx ...");
+ free(pdp_temp);
+ free(updvals);
+ rrd_free(&rrd);
+ fclose(rrd_file);
+ return(-1);
+ }
+ /* initialize template redirector */
+ for (i=0;i<=rrd.stat_head->ds_cnt;i++) tmpl_idx[i]=i;
+ tmpl_max=rrd.stat_head->ds_cnt;
+ if (template) {
+ char *dsname;
+ long temp_len;
+ dsname = template;
+ temp_len = strlen(template);
+ tmpl_max = 0;
+ for (i=0;i<=temp_len;i++) {
+ if (template[i] == ':' || template[i] =='\0') {
+ template[i] = '\0';
+ if ((tmpl_idx[++tmpl_max] = ds_match(&rrd,dsname)) == -1){ free(updvals);
+ free(pdp_temp);
+ free(tmpl_idx);
+ rrd_free(&rrd);
+ fclose(rrd_file);
+ return(-1);
+ }
+ /* the first element is always the time */
+ tmpl_idx[tmpl_max]++;
+ }
+ }
+ }
+ if ((pdp_new = malloc(sizeof(rrd_value_t)
+ *rrd.stat_head->ds_cnt))==NULL){
+ rrd_set_error("allocating pdp_new ...");
+ free(updvals);
+ free(pdp_temp);
+ free(tmpl_idx);
+ rrd_free(&rrd);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ /* loop through the arguments. */
+ for(arg_i=optind+1; arg_i<argc;arg_i++) {
+ unsigned long count_colons = 0;
+
+/* fprintf(stderr, "Handling %s\t%s\n", argv[arg_i]); */
+ /* parse the update line ... the first value is the time, the
+ remaining ones are the datasources */
+ /* skip any initial :'s */
+ i=0;
+ while (argv[arg_i][i] && argv[arg_i][i] == ':')
+ ++i;
+
+ /* initialize all ds input to unknown except the first one
+ which has always got to be set */
+ for(ii=1;ii<=rrd.stat_head->ds_cnt;ii++)
+ updvals[ii] = "U";
+ ii=0;
+ updvals[ii++] = &argv[arg_i][i];
+ for (;argv[arg_i][i] != '\0';++i) {
+ if (argv[arg_i][i] == ':') {
+ count_colons++;
+ argv[arg_i][i] = '\0';
+ if (ii<=tmpl_max) {
+ updvals[tmpl_idx[ii++]] = &argv[arg_i][i+1];
+ }
+ }
+ }
+
+ if (ii-1 != count_colons || ii-1 != tmpl_max) {
+ rrd_set_error("expected %lu data source readings (got %lu) from %s...",
+ tmpl_max, count_colons, argv[arg_i]);
+ break;
+ }
+
+ /* get the time from the reading ... handle N */
+ if (strcmp(updvals[0],"N")==0){
+ current_time = time(NULL);
+ } else {
+ current_time = atol(updvals[0]);
+ }
+
+ if(current_time <= rrd.live_head->last_up){
+ rrd_set_error("illegal attempt to update using time %ld when "
+ "last update time is %ld (minimum one second step ",
+ current_time, rrd.live_head->last_up);
+ break;
+ }
+
+
+ /* seek to the beginning of the rrd's */
+ if(fseek(rrd_file, rra_begin, SEEK_SET) != 0) {
+ rrd_set_error("seek error in rrd");
+ break;
+ }
+
+ rra_start = rra_begin;
+
+ /* when was the current pdp started */
+ proc_pdp_age = rrd.live_head->last_up % rrd.stat_head->pdp_step;
+ proc_pdp_st = rrd.live_head->last_up - proc_pdp_age;
+
+ /* when did the last pdp_st occur */
+ occu_pdp_age = current_time % rrd.stat_head->pdp_step;
+ occu_pdp_st = current_time - occu_pdp_age;
+ interval = current_time - rrd.live_head->last_up;
+
+ if (occu_pdp_st > proc_pdp_st){
+ /* OK we passed the pdp_st moment*/
+ pre_int = occu_pdp_st - rrd.live_head->last_up; /* how much of the input data
+ * occurred before the latest
+ * pdp_st moment*/
+ post_int = occu_pdp_age; /* how much after it */
+ } else {
+ pre_int = interval;
+ post_int = 0;
+ }
+
+#ifdef DEBUG
+ printf(
+ "proc_pdp_age %lu\t"
+ "proc_pdp_st %lu\t"
+ "occu_pfp_age %lu\t"
+ "occu_pdp_st %lu\t"
+ "int %lu\t"
+ "pre_int %lu\t"
+ "post_int %lu\n", proc_pdp_age, proc_pdp_st,
+ occu_pdp_age, occu_pdp_st,
+ interval, pre_int, post_int);
+#endif
+
+ /* process the data sources and update the pdp_prep
+ * area accordingly */
+ for(i=0;i<rrd.stat_head->ds_cnt;i++){
+ enum dst_en dst_idx;
+ dst_idx= dst_conv(rrd.ds_def[i].dst);
+ if((updvals[i+1][0] != 'U') &&
+ rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt >= interval) {
+ /* the data source type defines how to process the data */
+ /* pdp_temp contains rate * time ... eg the bytes
+ * transferred during the interval. Doing it this way saves
+ * a lot of math operations */
+
+
+ switch(dst_idx){
+ case DST_COUNTER:
+ case DST_DERIVE:
+ if(rrd.pdp_prep[i].last_ds[0] != 'U'){
+ pdp_new[i]= rrd_diff(updvals[i+1],rrd.pdp_prep[i].last_ds);
+ if(dst_idx == DST_COUNTER) {
+ /* simple overflow catcher sugestet by andres kroonmaa */
+ /* this will fail terribly for non 32 or 64 bit counters ... */
+ /* are there any others in SNMP land ? */
+ if (pdp_new[i] < (double)0.0 )
+ pdp_new[i] += (double)4294967296.0 ; /* 2^32 */
+ if (pdp_new[i] < (double)0.0 )
+ pdp_new[i] += (double)18446744069414584320.0; /* 2^64-2^32 */;
+ }
+ }
+ else
+ pdp_new[i]= DNAN;
+ break;
+ case DST_ABSOLUTE:
+ pdp_new[i]= atof(updvals[i+1]);
+ break;
+ case DST_GAUGE:
+ pdp_new[i] = atof(updvals[i+1]) * interval;
+ break;
+ default:
+ rrd_set_error("rrd contains and DS type : '%s'",
+ rrd.ds_def[i].dst);
+ break;
+ }
+ /* break out of this for loop if the error string is set */
+ if (rrd_test_error())
+ break;
+ } else {
+ /* no news is news all the same */
+ pdp_new[i] = DNAN;
+ }
+
+ /* make a copy of the command line argument for the next run */
+#ifdef DEBUG
+ fprintf(stderr,
+ "prep ds[%lu]\t"
+ "last_arg '%s'\t"
+ "this_arg '%s'\t"
+ "pdp_new %10.2f\n",
+ i,
+ rrd.pdp_prep[i].last_ds,
+ updvals[i+1], pdp_new[i]);
+#endif
+ if(dst_idx == DST_COUNTER || dst_idx == DST_DERIVE){
+ strncpy(rrd.pdp_prep[i].last_ds,
+ updvals[i+1],LAST_DS_LEN-1);
+ rrd.pdp_prep[i].last_ds[LAST_DS_LEN]=0;
+ }
+ }
+ /* break out of the argument parsing loop if the error_string is set */
+ if (rrd_test_error())
+ break;
+
+ /* has a pdp_st moment occurred since the last run ? */
+
+ if (proc_pdp_st == occu_pdp_st){
+ /* no we have not passed a pdp_st moment. therefore update is simple */
+
+ for(i=0;i<rrd.stat_head->ds_cnt;i++){
+ if(isnan(pdp_new[i]))
+ rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt += interval;
+ else
+ rrd.pdp_prep[i].scratch[PDP_val].u_val+= pdp_new[i];
+#ifdef DEBUG
+ fprintf(stderr,
+ "NO PDP ds[%lu]\t"
+ "value %10.2f\t"
+ "unkn_sec %5lu\n",
+ i,
+ rrd.pdp_prep[i].scratch[PDP_val].u_val,
+ rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
+#endif
+ }
+ } else {
+ /* an pdp_st has occurred. */
+
+ /* in pdp_prep[].scratch[PDP_val].u_val we have collected rate*seconds which
+ * occurred up to the last run.
+ pdp_new[] contains rate*seconds from the latest run.
+ pdp_temp[] will contain the rate for cdp */
+
+
+ for(i=0;i<rrd.stat_head->ds_cnt;i++){
+ /* update pdp_prep to the current pdp_st */
+ if(isnan(pdp_new[i]))
+ rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt += pre_int;
+ else
+ rrd.pdp_prep[i].scratch[PDP_val].u_val +=
+ pdp_new[i]/(double)interval*(double)pre_int;
+
+ /* if too much of the pdp_prep is unknown we dump it */
+ if ((rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt
+ > rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt) ||
+ (occu_pdp_st-proc_pdp_st <=
+ rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt)) {
+ pdp_temp[i] = DNAN;
+ } else {
+ pdp_temp[i] = rrd.pdp_prep[i].scratch[PDP_val].u_val
+ / (double)( occu_pdp_st
+ - proc_pdp_st
+ - rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
+ }
+ /* make pdp_prep ready for the next run */
+ if(isnan(pdp_new[i])){
+ rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt = post_int;
+ rrd.pdp_prep[i].scratch[PDP_val].u_val = 0.0;
+ } else {
+ rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt = 0;
+ rrd.pdp_prep[i].scratch[PDP_val].u_val =
+ pdp_new[i]/(double)interval*(double)post_int;
+ }
+ /* make sure pdp_temp is neither too large or too small
+ * if any of these occur it becomes unknown ...
+ * sorry folks ... */
+ if (! isnan(pdp_temp[i]) &&
+ ((! isnan(rrd.ds_def[i].par[DS_max_val].u_val) &&
+ pdp_temp[i] > rrd.ds_def[i].par[DS_max_val].u_val) ||
+ (! isnan(rrd.ds_def[i].par[DS_min_val].u_val) &&
+ pdp_temp[i] < rrd.ds_def[i].par[DS_min_val].u_val))) {
+ pdp_temp[i] = DNAN;
+ }
+#ifdef DEBUG
+ fprintf(stderr,
+ "PDP UPD ds[%lu]\t"
+ "pdp_temp %10.2f\t"
+ "new_prep %10.2f\t"
+ "new_unkn_sec %5lu\n",
+ i, pdp_temp[i],
+ rrd.pdp_prep[i].scratch[PDP_val].u_val,
+ rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
+#endif
+ }
+
+
+ /* now we have to integrate this data into the cdp_prep areas */
+ /* going through the round robin archives */
+ for(i = 0;
+ i < rrd.stat_head->rra_cnt;
+ i++){
+ enum cf_en current_cf = cf_conv(rrd.rra_def[i].cf_nam);
+ /* going through all pdp_st moments which have occurred
+ * since the last run */
+ for(pdp_st = proc_pdp_st+rrd.stat_head->pdp_step;
+ pdp_st <= occu_pdp_st;
+ pdp_st += rrd.stat_head->pdp_step){
+
+#ifdef DEBUG
+ fprintf(stderr,"RRA %lu STEP %lu\n",i,pdp_st);
+#endif
+
+ if((pdp_st %
+ (rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step)) == 0){
+
+ /* later on the cdp_prep values will be transferred to
+ * the rra. we want to be in the right place. */
+ rrd.rra_ptr[i].cur_row++;
+ if (rrd.rra_ptr[i].cur_row >= rrd.rra_def[i].row_cnt)
+ /* oops ... we have to wrap the beast ... */
+ rrd.rra_ptr[i].cur_row=0;
+#ifdef DEBUG
+ fprintf(stderr," -- RRA Preseek %ld\n",ftell(rrd_file));
+#endif
+
+ if(fseek(rrd_file,
+ (rra_start + (rrd.stat_head->ds_cnt
+ *rrd.rra_ptr[i].cur_row
+ * sizeof(rrd_value_t))), SEEK_SET) != 0){
+ rrd_set_error("seek error in rrd");
+ break;
+ }
+#ifdef DEBUG
+ fprintf(stderr," -- RRA Postseek %ld\n",ftell(rrd_file));
+#endif
+ }
+
+ for(ii = 0;
+ ii < rrd.stat_head->ds_cnt;
+ ii++){
+ iii=i*rrd.stat_head->ds_cnt+ii;
+
+ /* the contents of cdp_prep[].scratch[CDP_val].u_val depends
+ * on the consolidation function ! */
+
+ if (isnan(pdp_temp[ii])){ /* pdp is unknown */
+ rrd.cdp_prep[iii].scratch[CDP_unkn_pdp_cnt].u_cnt++;
+#ifdef DEBUG
+ fprintf(stderr," ** UNKNOWN ADD %lu\n",
+ rrd.cdp_prep[iii].scratch[CDP_unkn_pdp_cnt].u_cnt);
+#endif
+ } else {
+ if (isnan(rrd.cdp_prep[iii].scratch[CDP_val].u_val)){
+ /* cdp_prep is unknown when it does not
+ * yet contain data. It can not be zero for
+ * things like mim and max consolidation
+ * functions */
+#ifdef DEBUG
+ fprintf(stderr," ** INIT CDP %e\n", pdp_temp[ii]);
+#endif
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val = pdp_temp[ii];
+ }
+ else {
+ switch (current_cf){
+ case CF_AVERAGE:
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val+=pdp_temp[ii];
+#ifdef DEBUG
+ fprintf(stderr," ** AVERAGE %e\n",
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val);
+#endif
+ break;
+ case CF_MINIMUM:
+ if (pdp_temp[ii] < rrd.cdp_prep[iii].scratch[CDP_val].u_val)
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val = pdp_temp[ii];
+#ifdef DEBUG
+ fprintf(stderr," ** MINIMUM %e\n",
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val);
+#endif
+ break;
+ case CF_MAXIMUM:
+ if (pdp_temp[ii] > rrd.cdp_prep[iii].scratch[CDP_val].u_val)
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val = pdp_temp[ii];
+#ifdef DEBUG
+ fprintf(stderr," ** MAXIMUM %e\n",
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val);
+#endif
+ break;
+ case CF_LAST:
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val=pdp_temp[ii];
+#ifdef DEBUG
+ fprintf(stderr," ** LAST %e\n",
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val);
+#endif
+ break;
+ default:
+ rrd_set_error("Unknown cf %s",
+ rrd.rra_def[i].cf_nam);
+ break;
+ }
+ }
+ }
+
+
+ /* is the data in the cdp_prep ready to go into
+ * its rra ? */
+ if((pdp_st %
+ (rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step)) == 0){
+
+ /* prepare cdp_pref for its transition to the rra. */
+ if (rrd.cdp_prep[iii].scratch[CDP_unkn_pdp_cnt].u_cnt
+ > rrd.rra_def[i].pdp_cnt*
+ rrd.rra_def[i].par[RRA_cdp_xff_val].u_val)
+ /* to much of the cdp_prep is unknown ... */
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val = DNAN;
+ else if (current_cf == CF_AVERAGE){
+ /* for a real average we have to divide
+ * the sum we built earlier on. While ignoring
+ * the unknown pdps */
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val
+ /= (rrd.rra_def[i].pdp_cnt
+ -rrd.cdp_prep[iii].scratch[CDP_unkn_pdp_cnt].u_cnt);
+ }
+ /* we can write straight away, because we are
+ * already in the right place ... */
+
+#ifdef DEBUG
+ fprintf(stderr," -- RRA WRITE VALUE %e, at %ld\n",
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val,ftell(rrd_file));
+#endif
+
+ if(fwrite(&(rrd.cdp_prep[iii].scratch[CDP_val].u_val),
+ sizeof(rrd_value_t),1,rrd_file) != 1){
+ rrd_set_error("writing rrd");
+ break;
+ }
+ wrote_to_file = 1;
+
+#ifdef DEBUG
+ fprintf(stderr," -- RRA WROTE new at %ld\n",ftell(rrd_file));
+#endif
+
+ /* make cdp_prep ready for the next run */
+ rrd.cdp_prep[iii].scratch[CDP_val].u_val = DNAN;
+ rrd.cdp_prep[iii].scratch[CDP_unkn_pdp_cnt].u_cnt = 0;
+ }
+ }
+ /* break out of this loop if error_string has been set */
+ if (rrd_test_error())
+ break;
+ }
+ /* break out of this loop if error_string has been set */
+ if (rrd_test_error())
+ break;
+ /* to be able to position correctly in the next rra w move
+ * the rra_start pointer on to the next rra */
+ rra_start += rrd.rra_def[i].row_cnt
+ *rrd.stat_head->ds_cnt*sizeof(rrd_value_t);
+
+ }
+ /* break out of the argument parsing loop if error_string is set */
+ if (rrd_test_error())
+ break;
+ }
+ rrd.live_head->last_up = current_time;
+ }
+
+ /* if we got here and if there is an error and if the file has not been
+ * written to, then close things up and return. */
+ if (rrd_test_error()) {
+ free(updvals);
+ free(tmpl_idx);
+ rrd_free(&rrd);
+ free(pdp_temp);
+ free(pdp_new);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ /* aargh ... that was tough ... so many loops ... anyway, its done.
+ * we just need to write back the live header portion now*/
+
+ if (fseek(rrd_file, (sizeof(stat_head_t)
+ + sizeof(ds_def_t)*rrd.stat_head->ds_cnt
+ + sizeof(rra_def_t)*rrd.stat_head->rra_cnt),
+ SEEK_SET) != 0) {
+ rrd_set_error("seek rrd for live header writeback");
+ free(updvals);
+ free(tmpl_idx);
+ rrd_free(&rrd);
+ free(pdp_temp);
+ free(pdp_new);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ if(fwrite( rrd.live_head,
+ sizeof(live_head_t), 1, rrd_file) != 1){
+ rrd_set_error("fwrite live_head to rrd");
+ free(updvals);
+ rrd_free(&rrd);
+ free(tmpl_idx);
+ free(pdp_temp);
+ free(pdp_new);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ if(fwrite( rrd.pdp_prep,
+ sizeof(pdp_prep_t),
+ rrd.stat_head->ds_cnt, rrd_file) != rrd.stat_head->ds_cnt){
+ rrd_set_error("ftwrite pdp_prep to rrd");
+ free(updvals);
+ rrd_free(&rrd);
+ free(tmpl_idx);
+ free(pdp_temp);
+ free(pdp_new);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ if(fwrite( rrd.cdp_prep,
+ sizeof(cdp_prep_t),
+ rrd.stat_head->rra_cnt *rrd.stat_head->ds_cnt, rrd_file)
+ != rrd.stat_head->rra_cnt *rrd.stat_head->ds_cnt){
+
+ rrd_set_error("ftwrite cdp_prep to rrd");
+ free(updvals);
+ free(tmpl_idx);
+ rrd_free(&rrd);
+ free(pdp_temp);
+ free(pdp_new);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ if(fwrite( rrd.rra_ptr,
+ sizeof(rra_ptr_t),
+ rrd.stat_head->rra_cnt,rrd_file) != rrd.stat_head->rra_cnt){
+ rrd_set_error("fwrite rra_ptr to rrd");
+ free(updvals);
+ free(tmpl_idx);
+ rrd_free(&rrd);
+ free(pdp_temp);
+ free(pdp_new);
+ fclose(rrd_file);
+ return(-1);
+ }
+
+ /* OK now close the files and free the memory */
+ if(fclose(rrd_file) != 0){
+ rrd_set_error("closing rrd");
+ free(updvals);
+ free(tmpl_idx);
+ rrd_free(&rrd);
+ free(pdp_temp);
+ free(pdp_new);
+ return(-1);
+ }
+
+ rrd_free(&rrd);
+ free(updvals);
+ free(tmpl_idx);
+ free(pdp_new);
+ free(pdp_temp);
+ return(0);
+}
+
+/*
+ * get exclusive lock to whole file.
+ * lock gets removed when we close the file
+ *
+ * returns 0 on success
+ */
+int
+LockRRD(FILE *rrdfile)
+{
+ int rrd_fd; /* File descriptor for RRD */
+ int stat;
+
+ rrd_fd = fileno(rrdfile);
+
+ {
+#ifndef WIN32
+ struct flock lock;
+ lock.l_type = F_WRLCK; /* exclusive write lock */
+ lock.l_len = 0; /* whole file */
+ lock.l_start = 0; /* start of file */
+ lock.l_whence = SEEK_SET; /* end of file */
+
+ stat = fcntl(rrd_fd, F_SETLK, &lock);
+#else
+ struct _stat st;
+
+ if ( _fstat( rrd_fd, &st ) == 0 ) {
+ stat = _locking ( rrd_fd, _LK_NBLCK, st.st_size );
+ } else {
+ stat = -1;
+ }
+#endif
+ }
+
+ return(stat);
+}
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrdtool.dsp
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrdtool.dsp (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrdtool.dsp Sat Jul 13 18:46:04 2002
@@ -0,0 +1,92 @@
+# Microsoft Developer Studio Project File - Name="rrdtool" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=rrdtool - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "rrdtool.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rrdtool.mak" CFG="rrdtool - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rrdtool - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "rrdtool - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rrdtool - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "rrdtool_"
+# PROP BASE Intermediate_Dir "rrdtool_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "toolrelease"
+# PROP Intermediate_Dir "toolrelease"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I "..\gd1.2" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_CTYPE_DISABLE_MACROS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x100c /d "NDEBUG"
+# ADD RSC /l 0x100c /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib g!
di32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\gd1.2\release\gd.lib release\rrd.lib /nologo /subsystem:console /incremental:yes /debug /machine:I386
+
+!ELSEIF "$(CFG)" == "rrdtool - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "rrdtool0"
+# PROP BASE Intermediate_Dir "rrdtool0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "tooldebug"
+# PROP Intermediate_Dir "tooldebug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "." /I "..\gd1.2" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_CTYPE_DISABLE_MACROS" /FR /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x100c /d "_DEBUG"
+# ADD RSC /l 0x100c /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo /o"rrdtool.bsc"
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\gd1.2\debug\gd.lib debug\rrd.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "rrdtool - Win32 Release"
+# Name "rrdtool - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\rrd_tool.c
+# End Source File
+# End Target
+# End Project
Added: trunk/orca/packages/rrdtool-0.99.29.1/src/rrd.dsp
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/src/rrd.dsp (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/src/rrd.dsp Sat Jul 13 18:46:04 2002
@@ -0,0 +1,138 @@
+# Microsoft Developer Studio Project File - Name="rrd" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=rrd - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "rrd.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rrd.mak" CFG="rrd - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rrd - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "rrd - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rrd - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "rrd___Wi"
+# PROP BASE Intermediate_Dir "rrd___Wi"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I "..\gd1.2" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_CTYPE_DISABLE_MACROS" /FD /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x100c
+# ADD RSC /l 0x100c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "rrd - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "rrd___W0"
+# PROP BASE Intermediate_Dir "rrd___W0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_D!
ir "debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "." /I "..\gd1.2" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_CTYPE_DISABLE_MACROS" /FR /FD /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x100c
+# ADD RSC /l 0x100c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo /o"rrd.bsc"
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "rrd - Win32 Release"
+# Name "rrd - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\diff.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\getopt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\getopt1.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rrd_create.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rrd_dump.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rrd_error.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rrd_fetch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rrd_format.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rrd_graph.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rrd_last.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rrd_open.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rrd_tune.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rrd_update.c
+# End Source File
+# End Target
+# End Project
Added: trunk/orca/packages/rrdtool-0.99.29.1/README
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/README (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/README Sat Jul 13 18:46:04 2002
@@ -0,0 +1,77 @@
+Round Robin Database Tools
+==========================
+
+It is pretty easy to gather status information from all sorts of things,
+ranging from the temperature in your office to the number of octets which
+have passed through the FDDI interface of your router. But it is not so
+trivial to store this data in a efficient and systematic manner. This is
+where rrdtool kicks in. It lets you log and analyze the data you gather from
+all kinds of data- sources (DS). The data analysis part of rrdtool is based
+on the ability to quickly generate graphical representations of the data
+values collected over a definable time period.
+
+
+To compile:
+-----------
+
+ sh configure
+ make
+
+ (Please report configure/compilation problems to
+ the developers list, so I can make it better. -jra)
+
+ Please note that you should get perl-5.004 for things to work
+
+ Win32 users:
+ ------------
+
+ Win32 things are controlled by the #define WIN32.
+ If your compiler doesn't define that, you should add it to
+ the compile line. -jeff (jeff.allen at acm.org)
+
+
+Perl bindings:
+--------------
+The package contains two sets of Perl bindings.
+
+a) perl-piped which uses teh rrdtool through a set of pipes
+b) perl-shared which builds a shared library from rrdtool
+
+Both bindings get built by the toplevel make. Additionally
+you might want to:
+
+make test
+make install
+
+There is an example script in each of the directories. The example
+scrips work even when you don't intall the perl extensions.
+
+To learn:
+---------
+
+Read the documentation in the doc directory. Start of with
+rrdtool. All documents are available as html and as ascii text.
+
+If you want to know about the format of the logfiles check
+src/rrd_format.h there are a lot of comments in there ...
+
+To Contribute:
+--------------
+
+Contributed feature and bug patches are most welcome. But please
+send complete patches. A complete patch patches the CODE as well
+as the CHANGES, CONTRIBUTORS and the POD files.
+
+If you want to keep in touch, make sure you subscribe to the
+mrtg-developers mailinglist by sending a message with the subject
+'subscribe' to mrtg-developers-request at list.ee.ethz.ch
+
+The latest Version:
+-------------------
+
+Is available from http://ee-staff.ethz.ch/~oetiker/webtools/rrdtool/
+
+
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/CONTRIBUTORS
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/CONTRIBUTORS (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/CONTRIBUTORS Sat Jul 13 18:46:05 2002
@@ -0,0 +1,53 @@
+I would like to thank to following people for helping to
+bring mrtg 3.0 into existence.
+
+Planning and Inspiration
+
+ Daniel Wesemann
+ Krister Karlson
+ Simon Leinen
+
+Debugging and code contributions
+
+ Jeff R. Allen <jeff.allen at acm.org> (autoconfigure, portability)
+ Philippe.Simonet <Philippe.Simonet at swisscom.com> (NT porting)
+ Wrolf Courtney <wrolf at concentric.net> (HP-UX)
+ Dan Dunn <dandunn at computer.org>
+ Russ Wright <wright at LBL.Gov>
+ Simon Leinen <simon at switch.ch>
+ Jost.Krieger <Jost.Krieger at ruhr-uni-bochum.de>
+ Blair Zajac <bzajac at geostaff.com>
+ Andrew Turner <turner at mint.net> (LAST and TOTAL consolidators)
+ Andreas Kroomaa <andre at ml.ee>
+ Oleg Cherevko <olwi at icyb.kiev.ua>
+ Otmar Lendl <O.Lendl at Austria.EU.net> (core dump fix)
+ Tom Crawley <Tom.Crawley at hi.riotinto.com.au> (GCC&HP configuration)
+ Jeremy Fischer <jeremy at pobox.com> (Makefile changes & RPM builds)
+ Alan Lichty <alan_lichty at eli.net>
+ Steen Linden <Steen.Linden at ebone.net>
+
+Documentation
+
+ Russ Wright <rwwright at home.com>
+ Wrolf Courtney <wrolf at concentric.net>
+ Amos Shapira <amos at gezernet.co.il>
+ Kai Siering <kai.siering at mediaways.net>
+ Alex van den Bogaerdt <alex at ergens.op.het.net>
+ Alan Lichty <alan_lichty at eli.net>
+
+Further I would like to note, that rrdtool would not exist without
+the following free software products:
+
+ Perl by Larry Wall
+ gd library by Thomas Boutell
+ SNMP Perl-Module by Simon Leinen
+
+ and last but not least
+
+ Linux by Linus Torvalds
+
+I would also like to thank the Department of Electrical Engineering
+at the Swiss Federal Institute of Technology who allow me to
+use their network resources to publish rrdtool ...
+
+Tobias Oetiker <oetiker at ee.ethz.ch>
Added: trunk/orca/packages/rrdtool-0.99.29.1/config.h.in
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/config.h.in (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/config.h.in Sat Jul 13 18:46:05 2002
@@ -0,0 +1,34 @@
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if you have the strftime function. */
+#undef HAVE_STRFTIME
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if your <sys/time.h> declares struct tm. */
+#undef TM_IN_SYS_TIME
+
+/* Define if you have the getrusage function. */
+#undef HAVE_GETRUSAGE
+
+/* Define if you have the mktime function. */
+#undef HAVE_MKTIME
+
+/* Define if you have the <math.h> header file. */
+#undef HAVE_MATH_H
+
+/* Define if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <sys/times.h> header file. */
+#undef HAVE_SYS_TIMES_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the m library (-lm). */
+#undef HAVE_LIBM
Added: trunk/orca/packages/rrdtool-0.99.29.1/contrib/log2rrd/log2rrd.pl
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/contrib/log2rrd/log2rrd.pl (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/contrib/log2rrd/log2rrd.pl Sat Jul 13 18:46:05 2002
@@ -0,0 +1,231 @@
+#! /usr/local/bin/perl
+#
+# Log 2 RRD. This script translates a MRTG 2.x log file
+# into a RRD archive. The original version was written by
+# Wrolf Courtney <wrolf at concentric.net> and
+# Russ Wright <wright at LBL.Gov> with an early test version
+# of RRDTOOL (mrtg-19980526.08) and has been modified to match
+# the parameters of rrdtool version 99.23 by Alan Lichty at
+# Electric Lightwave, Inc. <alichty at eli.net>.
+#
+# this script optimized for being called up by another script
+# that cycles through a list of routers and invokes this for each
+# interface. It can be run just as easily from a command line for
+# small numbers of logfiles.
+#
+# The RRD we create looks like the following: Note
+# that we have to use type GAUGE in order to have RRDTOOL
+# populate the new rr archive correctly. Otherwise RRDTOOL will try
+# to interpet the data as new octet counts instead of existing
+# data rate averages.
+#
+# DS:GAUGE:86400:U:U # in counter
+# DS:GAUGE:86400:U:U # out counter
+# RRA:AVERAGE:0.5:1:600 # 5 minute samples
+# RRA:MAX:0.5:1:600 # 5 minute samples
+# RRA:AVERAGE:0.5:6:600 # 30 minute samples
+# RRA:MAX:0.5:6:600 # 30 minute samples
+# RRA:AVERAGE:0.5:24:600 # 2 hour samples
+# RRA:MAX:0.5:24:600 # 2 hour samples
+# RRA:AVERAGE:0.5:288:732 # 1 day samples
+# RRA:MAX:0.5:288:732 # 1 day samples
+#
+#
+
+use English;
+use strict;
+
+require "ctime.pl";
+
+use RRDs;
+
+my $DEBUG=0;
+
+&main;
+
+sub main {
+
+ my($inBytes, $outBytes);
+ my($lastRunDate, $firstRunDate);
+ my($i, $dataFile, $firstRun);
+ my($oldestRun, $lastRun);
+ my($curTime, $oldestTime, $totRec);
+ my($avgIn, $avgOut, $maxIn, $maxOut);
+ my(@lines, @finalRecs);
+ my($RRD, $START, $destDir, $dsType);
+
+#
+# get the logfile name to process
+# the default is to strip out the .log extension and create
+# a new file with the extension .rrd
+#
+
+ $dataFile=$ARGV[0];
+
+ $destDir = $ARGV[1];
+
+#
+# strip off .log from file name - complain and die if no .log
+# in the filename
+#
+
+ if ($dataFile =~ /(.*)\.log$/) {
+ $RRD = "$1";
+ }
+
+ if ($RRD eq "") {
+ printf("Usage: log2rrd [log file] [destination dir]\n");
+ exit;
+ }
+
+#
+# strip out path info (if present) to get at just the filename
+#
+
+ if ($RRD =~ /(.*)\/(.*)$/){
+ $RRD = "$2";
+ }
+
+#
+# add the destination path (if present) and .rrd suffix
+#
+
+ if ($destDir){
+ $RRD = "$destDir/$RRD.rrd";
+
+ }else{
+ $RRD = "$RRD.rrd";
+ }
+
+ open(IN,"$dataFile") || die ("Couldn't open $dataFile");
+
+#
+# Get first line - has most current sample
+#
+
+ $_ = <IN>;
+ chop;
+ ($lastRun, $inBytes, $outBytes) = split;
+ $lastRunDate = &ctime($lastRun);
+ chop $lastRunDate;
+
+ $firstRun = $lastRun;
+ $i=2;
+
+#
+# start w/line 2 and read them into the lines array
+# (2nd line is in position 2)
+#
+ while (<IN>) {
+ chop;
+ $lines[$i++] = $_;
+ ($curTime) = split;
+ if ($curTime < $firstRun) {
+ $firstRun = $curTime;
+ }
+ }
+ close(IN);
+
+#
+# Let's say source start time is 5 minutes before 1st sample
+#
+
+ $START=$firstRun - 300;
+ print STDERR "\$START = $START\n" if $DEBUG>1;
+
+ $firstRunDate = &ctime($firstRun);
+ chop $firstRunDate;
+
+ printf("Data from $firstRunDate\n to $lastRunDate\n") if $DEBUG>0;
+
+ $oldestTime=$lastRun;
+#
+# OK- sort through the data and put it in a new array.
+# This gives us a chance to find errors in the log files and
+# handles any overlap of data (there shouldn't be any)
+#
+# NOTE: We start w/ record # 3, not #2 since #2 could be partial
+#
+
+ for ($i=3; $i <= 2533; $i++) {
+
+ ($curTime, $avgIn, $avgOut, $maxIn, $maxOut) = split(/\s+/, $lines[$i]);
+
+ if ($curTime < $oldestTime) {
+
+#
+# only add data if older than anything already in array
+# this should always be true, just checking
+#
+
+ $oldestTime = $curTime;
+ $finalRecs[$totRec++]=$lines[$i];
+ }
+ }
+
+
+ PopulateRRD($totRec, $RRD, $START, \@finalRecs);
+
+#
+# if you know that most of your MRTG logfiles are using
+# counter data, uncomment the following lines to automatically
+# run rrdtune and change the data type.
+#
+# my(@tuneparams) = ("$RRD", "-d", "ds0:COUNTER", "-d", "ds1:COUNTER");
+# RRDs::tune(@tuneparams);
+
+
+}
+
+sub PopulateRRD {
+
+ my($totRec, $RRD, $START, $finalRecs) = @_;
+ my($i, $curTime, $avgIn, $avgOut, $maxIn, $maxOut);
+ my($saveReal, $line);
+ my($createret, $updret);
+
+ print "* Creating RRD $RRD\n\n" if $DEBUG>0;
+
+#
+# We'll create RRAs for both AVG and MAX. MAX isn't currently filled but
+# may be later
+#
+
+ RRDs::create ("$RRD", "-b", $START, "-s", 300,
+ "DS:ds0:GAUGE:86400:U:U",
+ "DS:ds1:GAUGE:86400:U:U",
+ "RRA:AVERAGE:0.5:1:600",
+ "RRA:MAX:0.5:1:600",
+ "RRA:AVERAGE:0.5:6:600",
+ "RRA:MAX:0.5:6:600",
+ "RRA:AVERAGE:0.5:24:600",
+ "RRA:MAX:0.5:24:600",
+ "RRA:AVERAGE:0.5:288:600",
+ "RRA:MAX:0.5:288:600");
+
+ if (my $error = RRDs::error()) {
+ print "Cannot create $RRD: $error\n";
+ }
+
+
+ print "* Adding entries to $RRD\n\n" if $DEBUG>0;
+
+ for ($i=$totRec - 1; $i >= 0; $i--) {
+
+ ($curTime, $avgIn, $avgOut, $maxIn, $maxOut) = split(/\s+/, @$finalRecs[$i]);
+
+ RRDs::update ("$RRD", "$curTime:$avgIn:$avgOut");
+
+ if (my $error = RRDs::error()) {
+ print "Cannot update $RRD: $error\n";
+ }
+
+
+# NOTE: Need to add checking on RRDread and include the Max values
+# print status every now and then
+# print $i if $i % 25 && $DEBUG>0;
+# print "$i\n";
+
+ }
+
+}
Added: trunk/orca/packages/rrdtool-0.99.29.1/contrib/log2rrd/README
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/contrib/log2rrd/README (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/contrib/log2rrd/README Sat Jul 13 18:46:05 2002
@@ -0,0 +1,62 @@
+ log2rrd
+
+Usage:
+
+log2rrd.pl {mrtg logfile} {destination directory}
+
+Log2rrd is a simple tool for converting MRTG logfiles into round robin
+database (RRD) files. The original version was written last year by
+Wrolf Courtney <wrolf at concentric.net> and Russ Wright <wright at LBL.Gov>
+with an early test version of RRDTOOL (mrtg-19980526.08). This
+version has been modified to work with the current shared-perl release
+of RRD (RRDs).
+
+This script only moves the input/output data averages and does not
+make any effort to retain the maximum data rate info that is present
+in the mrtg logfiles. This means that when you request maximum values
+for a given time range from your new rrd archive, it will only show
+you the averaged max values and not the original data peaks that
+occured in the averaged time period. This may or may not be a problem
+at your site.
+
+The conversion script expects 2 arguments - the mrtg logfile to read
+and the path for the resulting rrd file. The script will attempt to
+isolate the filename from any path specified for the mrtg input
+logfile to create the rrd output file name with the specified
+destination directory. If no destination directory name is included,
+the rrd file will be written in the connected directory.
+
+Note that the resulting rrd DS type is GAUGE. With a DS type of
+counter, rrdupdate will attempt to interpret input data as a counter
+value and make a new data average for the specified time interval.
+In this case, we need to trick rrdcreate/rrdupdate into letting us
+input the data values directly because mrtg had already consolidated
+the counter data. The script contains lines of code that can be
+uncommented to allow log2rrd to automatically call rrdtune to change
+the resulting file to use the COUNTER data type after the mrtg
+logfiles have been read in. Since not all mrtg data files are counter
+data, I leave this option up to the user as to whether to convert
+later by hand with rrdtune or let log2rrd perform the task.
+
+Considerations for filenames and converting large numbers of files:
+
+At my own site, I have over 40 Cisco 75xx routers with lots of
+interfaces being monitored per router plus about 60 Cisco 5300
+terminal servers. Running log2rrd for each interface individually
+would be a very painful process. Since I am in the process of moving
+all of my mrtg datasets over to Cricket, I hacked a separate version
+of log2rrd that had more specific file name conversion code to match
+my Cricket target names. This version of log2rrd was called up by
+another script that looped through an entire mrtg workdir and
+converted all logfiles present in that directory. This code was far
+too specific to my site's version of mrtg logfile names and desired
+Cricket target info to be included here. It would not be a difficult
+task to wrap this log2rrd script in a similar fashion tailored to your
+own needs. If you have 100's or 1000's of logfiles to move, the
+effort is well worthwhile.
+
+Alan Lichty
+Internetworking Planner
+Electric Lightwave, Inc.
+(360)816-4167
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/contrib/README
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/contrib/README (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/contrib/README Sat Jul 13 18:46:05 2002
@@ -0,0 +1,7 @@
+This directory should contain YOUR scripts ... please sent them to me ...
+
+each script should come with an apropriate README file ...
+
+
+cheees
+tobi
Added: trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/Makefile
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/Makefile (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/Makefile Sat Jul 13 18:46:05 2002
@@ -0,0 +1,43 @@
+# Generated automatically from Makefile.in by configure.
+# things that the GNU standards document suggests all makefiles
+# should have.
+SHELL = /bin/sh
+.SUFFIXES:
+.SUFFIXES: .c .o .pl .pm .pod .html .man
+
+# variables we got from configure
+# (you can mess with these, if you want)
+
+CC = gcc
+AR = ar
+CFLAGS_EXTRA = -Wall -pedantic -fpic
+CFLAGS = -g -O2
+CFLAGS_ALL = $(CFLAGS) $(CFLAGS_EXTRA) -I.. -I../../src -DHAVE_CONFIG_H \
+ -DWANT_AT_STYLE_TIMESPEC
+LDFLAGS =
+LIBS = -L../../src -lrrd
+LIBS_DEPEND = ../../src/librrd.a
+
+###
+### Things you might NOT want to play with ...
+###
+
+HEADERS = ../../src/getopt.h ../../src/parsetime.h
+
+SRC = trytime.c
+
+OBJ = $(SRC:.c=.o)
+
+all: trytime
+
+trytime: $(OBJ) $(LIBS_DEPEND)
+ $(CC) -o trytime $(OBJ) $(LDFLAGS) $(LIBS)
+
+clean:
+ -rm *.o
+
+realclean: clean
+ -rm trytime
+
+.c.o: $(HEADERS)
+ $(CC) $(CFLAGS_ALL) -c $<
Added: trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/README
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/README (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/README Sat Jul 13 18:46:05 2002
@@ -0,0 +1,85 @@
+"trytime" is a small program that allows you to play with at-style
+time specifications without actually bothering any of the rrd databases.
+It takes either single at-style specification or two of those
+(for start and end time, just like rrdtool fetch or graph do) and
+reports what it thinks of it. The diagnostic is as close as possible
+to that of rrdtool compiled for at-style time specification support.
+
+To learn what's possible with at-style time specifications, see
+the AT-STYLE TIME SPECIFICATION section in the rrdfetch documentation.
+
+The formal syntax parsed is (this is taken right from the parsetime.c):
+
+/*
+ * The BNF-like specification of the time syntax parsed is below:
+ *
+ * As usual, [ X ] means that X is optional, { X } means that X may
+ * be either omitted or specified as many times as needed,
+ * alternatives are separated by |, brackets are used for grouping.
+ * (# marks the beginning of comment that extends to the end of line)
+ *
+ * TIME-SPECIFICATION ::= TIME-REFERENCE [ OFFSET-SPEC ] |
+ * OFFSET-SPEC |
+ * ( START | END ) OFFSET-SPEC
+ *
+ * TIME-REFERENCE ::= NOW | TIME-OF-DAY-SPEC [ DAY-SPEC-1 ] |
+ * [ TIME-OF-DAY-SPEC ] DAY-SPEC-2
+ *
+ * TIME-OF-DAY-SPEC ::= NUMBER [(':'|'.') NUMBER] [am|pm] | # HH:MM HH.MM HH[MM]
+ * 'noon' | 'midnight' | 'teatime'
+ *
+ * DAY-SPEC-1 ::= NUMBER '/' NUMBER '/' NUMBER | # MM/DD/[YY]YY
+ * NUMBER '.' NUMBER '.' NUMBER | # DD.MM.[YY]YY
+ * NUMBER # DDMM[YY]YY
+ *
+ * DAY-SPEC-2 ::= MONTH-NAME NUMBER [NUMBER] | # Month DD [YY]YY
+ * 'yesterday' | 'today' | 'tomorrow' |
+ * DAY-OF-WEEK
+ *
+ *
+ * OFFSET-SPEC ::= '+'|'-' NUMBER TIME-UNIT { ['+'|'-'] NUMBER TIME-UNIT }
+ *
+ * TIME-UNIT ::= SECONDS | MINUTES | HOURS |
+ * DAYS | WEEKS | MONTHS | YEARS
+ *
+ * NOW ::= 'now' | 'n'
+ *
+ * START ::= 'start' | 's'
+ * END ::= 'end' | 'e'
+ *
+ * SECONDS ::= 'seconds' | 'second' | 'sec' | 's'
+ * MINUTES ::= 'minutes' | 'minute' | 'min' | 'm'
+ * HOURS ::= 'hours' | 'hour' | 'hr' | 'h'
+ * DAYS ::= 'days' | 'day' | 'd'
+ * WEEKS ::= 'weeks' | 'week' | 'wk' | 'w'
+ * MONTHS ::= 'months' | 'month' | 'mon' | 'm'
+ * YEARS ::= 'years' | 'year' | 'yr' | 'y'
+ *
+ * MONTH-NAME ::= 'jan' | 'january' | 'feb' | 'february' | 'mar' | 'march' |
+ * 'apr' | 'april' | 'may' | 'jun' | 'june' | 'jul' | 'july' |
+ * 'aug' | 'august' | 'sep' | 'september' | 'oct' | 'october' |
+ * 'nov' | 'november' | 'dec' | 'december'
+ *
+ * DAY-OF-WEEK ::= 'sunday' | 'sun' | 'monday' | 'mon' | 'tuesday' | 'tue' |
+ * 'wednesday' | 'wed' | 'thursday' | 'thu' | 'friday' | 'fri' |
+ * 'saturday' | 'sat'
+ *
+ *
+ * As you may note, there is an ambiguity with respect to
+ * the 'm' time unit (which can mean either minutes or months).
+ * To cope with this, code tries to read users mind :) by applying
+ * certain heuristics. There are two of them:
+ *
+ * 1. If 'm' is used in context of (i.e. right after the) years,
+ * months, weeks, or days it is assumed to mean months, while
+ * in the context of hours, minutes, and seconds it means minutes.
+ * (e.g., in -1y6m or +3w1m 'm' means 'months', while in
+ * -3h20m or +5s2m 'm' means 'minutes')
+ *
+ * 2. Out of context (i.e. right after the '+' or '-' sign) the
+ * meaning of 'm' is guessed from the number it directly follows.
+ * Currently, if the number absolute value is below 25 it is assumed
+ * that 'm' means months, otherwise it is treated as minutes.
+ * (e.g., -25m == -25 minutes, while +24m == +24 months)
+ *
+ */
Added: trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/trytime.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/trytime.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/contrib/trytime/trytime.c Sat Jul 13 18:46:05 2002
@@ -0,0 +1,258 @@
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#include "parsetime.h"
+
+#ifndef WANT_AT_STYLE_TIMESPEC
+#define WANT_AT_STYLE_TIMESPEC
+#endif
+
+#define BUF_LEN 128
+
+static char soption[BUF_LEN];
+static char eoption[BUF_LEN];
+
+int main ( int ac, char **av )
+{
+ static struct option long_options[] =
+ {
+ {"start", required_argument, 0, 's'},
+ {"end", required_argument, 0, 'e'},
+ {0,0,0,0}};
+ int option_index = 0;
+ int opt;
+
+ time_t start_tmp, end_tmp, Now = time(NULL);
+ char *ct;
+
+#ifdef WANT_AT_STYLE_TIMESPEC
+ struct time_value start_tv, end_tv;
+ char *parsetime_error = NULL;
+ int start_tmp_is_ok = 0,
+ end_tmp_is_ok = 0;
+#endif
+
+ /* default values */
+ end_tmp = time(NULL);
+ start_tmp = -24*3600;
+#ifdef WANT_AT_STYLE_TIMESPEC
+ end_tv.type = ABSOLUTE_TIME;
+ end_tv.tm = *localtime(&end_tmp);
+ end_tv.offset = 0;
+
+ start_tv.type = RELATIVE_TO_END_TIME;
+ start_tv.tm = *localtime(&end_tmp); /* to init tm_zone and tm_gmtoff */
+ start_tv.offset = -24*3600;/* to be compatible with the original code. */
+ start_tv.tm.tm_sec = 0; /** alternatively we could set tm_mday to -1 */
+ start_tv.tm.tm_min = 0; /** but this would yield -23(25) hours offset */
+ start_tv.tm.tm_hour = 0; /** twice a year, when DST is coming in or */
+ start_tv.tm.tm_mday = 0; /** out of effect */
+ start_tv.tm.tm_mon = 0;
+ start_tv.tm.tm_year = 0;
+ start_tv.tm.tm_wday = 0;
+ start_tv.tm.tm_yday = 0;
+ start_tv.tm.tm_isdst = -1; /* for mktime to guess */
+#endif
+ *soption = '\0';
+ *eoption = '\0';
+
+ if( ac < 2 )
+ {
+ printf( "usage: %s time-specification-to-try\n"
+ "or %s [--start|-s start] [--end|-e end]\n"
+ "\n"
+ "In plain English, this means that to time specification try\n"
+ "a single time specification (just like in the rrdtool create)\n"
+ "you can use the first form, while to try two of them at once\n"
+ "(just like in rrdtool graph or fetch) you need the seconf form\n",
+ av[0], av[0] );
+ exit(0);
+ }
+
+ printf( "The time now is: %s\n", ctime(&Now) );
+
+ if( av[1][0] != '-' )
+ {
+ if( ac > 2 )
+ {
+ printf( "Warning: you specified several arguments,\n"
+ " of those I will use only one: '%s'\n"
+ "(hint: perhaps, you should put quotes around your timespec?)\n",
+ av[1] );
+ }
+#ifdef WANT_AT_STYLE_TIMESPEC
+ {
+ char *endp;
+ start_tmp_is_ok = 0;
+ start_tmp = strtol(av[1], &endp, 0);
+ if (*endp == '\0') /* it was a valid number */
+ if (start_tmp > 31122038 || /* 31 Dec 2038 in DDMMYYYY */
+ start_tmp < 0) {
+ start_tmp_is_ok = 1;
+ goto CheckRelative;
+ }
+ if ((parsetime_error = parsetime(av[1], &start_tv))) {
+ fprintf( stderr, "ERROR: %s\n", parsetime_error );
+ return(-1);
+ }
+ if (start_tv.type == RELATIVE_TO_END_TIME ||
+ start_tv.type == RELATIVE_TO_START_TIME) {
+ fprintf( stderr, "ERROR: specifying time relative to the 'start' "
+ "or 'end' makes no sense here\n");
+ return(-1);
+ }
+ if (!start_tmp_is_ok)
+ start_tmp = mktime(&start_tv.tm) + start_tv.offset;
+ }/* this is for the entire block */
+
+#else
+ start_tmp = atol(av[1]);
+#endif
+CheckRelative:
+ if (start_tmp < 0) /* if time is negative this means go back from now. */
+ start_tmp = time(NULL)+start_tmp;
+
+ {
+ ct = ctime(&start_tmp);
+ ct[24] = '\0'; /* zap that nasty embedded'\n' */
+ printf( "You specified the following: '%s',\n"
+ "for me this means: %s (or %ld sec since epoch)\n\n",
+ av[1], ct, start_tmp );
+
+ }
+ exit(0);
+ }/* if( av[1][0]... */
+
+ while(1)
+ {
+ opt = getopt_long(ac, av, "s:e:", long_options, &option_index);
+
+ if (opt == EOF)
+ break;
+
+ switch(opt)
+ {
+ case 's':
+ strncpy( soption, optarg, BUF_LEN );
+#ifdef WANT_AT_STYLE_TIMESPEC
+ {
+ char *endp;
+ start_tmp_is_ok = 0;
+ start_tmp = strtol(optarg, &endp, 0);
+ if (*endp == '\0') /* it was a valid number */
+ if (start_tmp > 31122038 || /* 31 Dec 2038 in DDMMYYYY */
+ start_tmp < 0) {
+ start_tmp_is_ok = 1;
+ break;
+ }
+ if ((parsetime_error = parsetime(optarg, &start_tv))) {
+ fprintf( stderr, "ERROR: start time: %s\n", parsetime_error );
+ return -1;
+ }
+ }
+#else
+ start_tmp = atol(optarg);
+#endif
+ break;
+ case 'e':
+ strncpy( eoption, optarg, BUF_LEN );
+#ifdef WANT_AT_STYLE_TIMESPEC
+ {
+ char *endp;
+ end_tmp_is_ok = 0;
+ end_tmp = strtol(optarg, &endp, 0);
+ if (*endp == '\0') /* it was a valid number */
+ if (end_tmp > 31122038) { /* 31 Dec 2038 in DDMMYYYY */
+ end_tmp_is_ok = 1;
+ break;
+ }
+ if ((parsetime_error = parsetime(optarg, &end_tv))) {
+ fprintf( stderr, "ERROR: end time: %s\n", parsetime_error );
+ return -1;
+ }
+ }
+#else
+ end_tmp = atol(optarg);
+#endif
+ break;
+ }
+ }
+
+#ifdef WANT_AT_STYLE_TIMESPEC
+ if ((start_tv.type == RELATIVE_TO_END_TIME ||
+ (start_tmp_is_ok && start_tmp < 0)) && /* same as the line above */
+ end_tv.type == RELATIVE_TO_START_TIME) {
+ fprintf( stderr, "the start and end times cannot be specified "
+ "relative to each other\n");
+ return(-1);
+ }
+
+ if (start_tv.type == RELATIVE_TO_START_TIME) {
+ fprintf( stderr, "the start time cannot be specified relative to itself\n");
+ return(-1);
+ }
+
+ if (end_tv.type == RELATIVE_TO_END_TIME) {
+ fprintf( stderr, "the end time cannot be specified relative to itself\n");
+ return(-1);
+ }
+
+ /* We don't care to keep all the values in their range,
+ mktime will do this for us */
+ if (start_tv.type == RELATIVE_TO_END_TIME) {
+ if (end_tmp_is_ok)
+ end_tv.tm = *localtime( &end_tmp );
+ start_tv.tm.tm_sec += end_tv.tm.tm_sec;
+ start_tv.tm.tm_min += end_tv.tm.tm_min;
+ start_tv.tm.tm_hour += end_tv.tm.tm_hour;
+ start_tv.tm.tm_mday += end_tv.tm.tm_mday;
+ start_tv.tm.tm_mon += end_tv.tm.tm_mon;
+ start_tv.tm.tm_year += end_tv.tm.tm_year;
+ }
+ if (end_tv.type == RELATIVE_TO_START_TIME) {
+ if (start_tmp_is_ok)
+ start_tv.tm = *localtime( &start_tmp );
+ end_tv.tm.tm_sec += start_tv.tm.tm_sec;
+ end_tv.tm.tm_min += start_tv.tm.tm_min;
+ end_tv.tm.tm_hour += start_tv.tm.tm_hour;
+ end_tv.tm.tm_mday += start_tv.tm.tm_mday;
+ end_tv.tm.tm_mon += start_tv.tm.tm_mon;
+ end_tv.tm.tm_year += start_tv.tm.tm_year;
+ }
+ if (!start_tmp_is_ok)
+ start_tmp = mktime(&start_tv.tm) + start_tv.offset;
+ if (!end_tmp_is_ok)
+ end_tmp = mktime(&end_tv.tm) + end_tv.offset;
+#endif
+
+ if (start_tmp < 0)
+ start_tmp = end_tmp + start_tmp;
+
+ ct = ctime(&start_tmp);
+ ct[24] = '\0'; /* zap that nasty embedded'\n' */
+ if( *soption )
+ printf( "Start time was specified as: '%s',\n"
+ "for me this means: %s (or %ld sec since epoch)\n\n",
+ soption, ct, start_tmp );
+ else
+ printf( "Start time was not specified, default value will be used (-86400)\n"
+ "for me this means: %s (or %ld sec since epoch)\n\n",
+ ct, start_tmp );
+
+ ct = ctime(&end_tmp);
+ ct[24] = '\0';
+ if( *eoption )
+ printf( "End time was specified as: '%s',\n"
+ "for me this means: %s (or %ld sec since epoch)\n",
+ eoption, ct, end_tmp );
+ else
+ printf( "End time was not specified, default value will be used (now)\n"
+ "for me this means: %s (or %ld sec since epoch)\n\n",
+ ct, start_tmp );
+
+ exit(0);
+}
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/RRDp.pm
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/RRDp.pm (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/RRDp.pm Sat Jul 13 18:46:06 2002
@@ -0,0 +1,188 @@
+package RRDp;
+
+=head1 NAME
+
+RRDp - Attach rrdtool from within a perl script via a set of pipes;
+
+=head1 SYNOPSIS
+
+use B<RRDp>
+
+B<RRDp::start> I<path to rrdtool executable>
+
+B<RRDp::cmd> I<rrdtool commandline>
+
+$answer = B<RRD::read>
+
+$status = B<RRD::end>
+
+B<$RRDp::user>, B<$RRDp::sys>, B<$RRDp::real>
+
+=head1 DESCRIPTION
+
+With this module you can safely communicate with the rrdtool.
+
+After every B<RRDp::cmd> you have to issue an B<RRDp::read> command to get
+B<rrdtool>s answer to your command. The answer is returned as a pointer,
+in order to speed things up. If the last command did not return any
+data, B<RRDp::read> will return an undefined variable.
+
+If you import the PERFORMANCE variables into your namespace,
+you can access rrdtools internal performance measurements.
+
+=over 8
+
+=item use B<RRDp>
+
+Load the RRDp::pipe module.
+
+=item B<RRDp::start> I<path to rrdtool executable>
+
+start rrdtool. The argument must be the path to the rrdtool executable
+
+=item B<RRDp::cmd> I<rrdtool commandline>
+
+pass commands on to rrdtool. check the rrdtool documentation for
+more info on the rrdtool commands.
+
+=item $answer = B<RRDp::read>
+
+read rrdtools response to your command. Note that the $answer variable will
+only contain a pointer to the returned data. The reason for this is, that
+rrdtool can potentially return quite excessive amounts of data
+and we don't want to copy this around in memory. So when you want to
+access the contents of $answer you have to use $$answer which dereferences
+the variable.
+
+=item $status = B<RRDp::end>
+
+terminates rrdtool and returns rrdtools status ...
+
+=item B<$RRDp::user>, B<$RRDp::sys>, B<$RRDp::real>
+
+these variables will contain totals of the user time, system time and
+real time as seen by rrdtool. User time is the time rrdtool is
+running, System time is the time spend in system calls and real time
+is the total time rrdtool has been running.
+
+The difference between user + system and real is the time spent
+waiting for things like the hard disk and new input from the perl
+script.
+
+=back
+
+
+=head1 EXAMPLE
+
+ use RRDp;
+ RRDp::start "/usr/local/bin/rrdtool";
+ RRDp::cmd qw(create demo.rrd --step 100
+ DS:in:GAUGE:100:U:U
+ RRA:AVERAGE:0.5:1:10);
+ $answer = RRDp::read;
+ print $$answer;
+ ($usertime,$systemtime,$realtime) = ($RRDp::user,$RRDp::sys,$RRDp::real);
+
+=head1 SEE ALSO
+
+For more information on how to use rrdtool, check the manpages.
+
+=head1 AUTHOR
+
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
+=cut
+#' this is to make cperl.el happy
+
+use strict;
+use Fcntl;
+use Carp;
+use IO::Handle;
+use IPC::Open2;
+use vars qw($Sequence $RRDpid $VERSION);
+my $Sequence;
+my $RRDpid;
+
+# Prototypes
+
+sub start ($);
+sub cmd (@);
+sub end ();
+sub read ();
+
+$VERSION = 0.99029 ;
+
+sub start ($){
+ croak "rrdtool is already running"
+ if defined $Sequence;
+ $Sequence = 'S';
+ my $rrdtool = shift @_;
+ $RRDpid = open2 \*RRDreadHand,\*RRDwriteHand, $rrdtool,"-"
+ or croak "Can't Start rrdtool: $!";
+ RRDwriteHand->autoflush(); #flush after every write
+ fcntl RRDreadHand, F_SETFL,O_NONBLOCK|O_NDELAY; #make readhandle NON BLOCKING
+ return $RRDpid;
+}
+
+
+sub read () {
+ croak "RRDp::read can only be called after RRDp::cmd"
+ unless $Sequence eq 'C';
+ $Sequence = 'R';
+ my $inmask = 0;
+ my $srbuf;
+ my $minibuf;
+ my $buffer;
+ my $nfound;
+ my $timeleft;
+ my $ERR = 0;
+ vec($inmask,fileno(RRDreadHand),1) = 1; # setup select mask for Reader
+ while (1) {
+ my $rout;
+ $nfound = select($rout=$inmask,undef,undef,2);
+ if ($nfound == 0 ) {
+ # here, we could do something sensible ...
+ next;
+ }
+ sysread(RRDreadHand,$srbuf,4096);
+ $minibuf .= $srbuf;
+ while ($minibuf =~ s|^(.+?)\n||s) {
+ my $line = $1;
+ # print $line,"\n";
+ if ($line =~ m|^ERROR|) {
+ croak $line;
+ $ERR = 1;
+ }
+ elsif ($line =~ m|^OK u:([\d\.]+) s:([\d\.]+) r:([\d\.]+)|){
+ ($RRDp::sys,$RRDp::user,$RRDp::real)=($1,$2,$3);
+ return $ERR == 1 ? undef : \$buffer;
+ } else {
+ $buffer .= $line. "\n";
+ }
+ }
+ }
+}
+
+sub cmd (@){
+ croak "RRDp::cmd can only be called after RRDp::read or RRDp::start"
+ unless $Sequence eq 'R' or $Sequence eq 'S';
+ $Sequence = 'C';
+ my $cmd = join " ", @_;
+ if ($Sequence ne 'S') {
+ }
+ $cmd =~ s/\n/ /gs;
+ $cmd =~ s/\s/ /gs;
+ print RRDwriteHand "$cmd\n";
+}
+
+sub end (){
+ croak "RRDp::end can only be called after RRDp::start"
+ unless $Sequence;
+ close RRDwriteHand;
+ close RRDreadHand;
+ $Sequence = undef;
+ waitpid $RRDpid,0;
+ return $?
+}
+
+1;
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/t/base.t
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/t/base.t (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/t/base.t Sat Jul 13 18:46:06 2002
@@ -0,0 +1,42 @@
+#! /usr/bin/perl
+
+# this exercises just the perl module .. not rrdtool as such ...
+
+BEGIN { $| = 1; print "1..5\n"; }
+END {
+ print "not ok 1\n" unless $loaded;
+ unlink "demo.rrd";
+}
+
+sub ok
+{
+ $ok_count++;
+ my($what, $result) = @_ ;
+ print "not " unless $result;
+ print "ok $ok_count $what\n";
+}
+
+use RRDp;
+
+$loaded = 1;
+$ok_count = 1;
+
+print "ok 1 module load\n";
+
+ok("RRDp::start", RRDp::start "../src/rrdtool" > 0);
+
+$now=time();
+RRDp::cmd qw(create demo.rrd --start ), $now, qw(--step 100 ),
+ qw( DS:in:GAUGE:100:U:U RRA:AVERAGE:0.5:1:10 );
+
+$answer = RRDp::read;
+ok("RRDp::cmd", -s "demo.rrd" );
+
+RRDp::cmd qw(last demo.rrd);
+$answer = RRDp::read;
+
+ok("RRDp::read", $$answer =~ /$now/);
+
+$status = RRDp::end;
+
+ok("RRDp::end", $status == 0);
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/MANIFEST
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/MANIFEST (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/MANIFEST Sat Jul 13 18:46:06 2002
@@ -0,0 +1,6 @@
+MANIFEST
+README
+Makefile.PL
+RRDp.pm
+t/base.t
+examples/piped-demo.pl
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/Makefile.PL
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/Makefile.PL (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/Makefile.PL Sat Jul 13 18:46:06 2002
@@ -0,0 +1,10 @@
+use ExtUtils::MakeMaker;
+
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+ 'NAME' => 'RRDp',
+ 'VERSION' => '0.99.0', # finds $VERSION
+ 'linkext' => {LINKTYPE => ''},
+ 'dist' => {COMPRESS=>'gzip', SUFFIX=>'gz'},
+);
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/README
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/README (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/README Sat Jul 13 18:46:06 2002
@@ -0,0 +1,5 @@
+This is a Perl module for using rrdtool process via a set of pipes.
+
+perl Makefile.PL
+make test
+make install
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/examples/piped-demo.pl.in
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/examples/piped-demo.pl.in (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-piped/examples/piped-demo.pl.in Sat Jul 13 18:46:06 2002
@@ -0,0 +1,177 @@
+#! @PERL@
+
+=head1 NAME
+
+rrd_demo.pl - exercise rrdtool
+
+=head1 SYNOPSIS
+
+rrd_demo.pl
+
+=head1 DESCRIPTION
+
+The purpose of this script is to exercise rrdtool.
+First it will create an rrd file and fill it with data.
+Then it will use the graphing function to generate some gifs ...
+
+=head1 AUTHOR
+
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
+=cut
+
+BEGIN { unshift @INC, "../blib/lib"; }
+
+use RRDp;
+
+
+$main::DEBUG=0;
+$STEP1 = 200;
+$STEP2 = 300;
+$RUNS1 = 3000;
+$RUNS2 = 3000;
+$GRUNS = 20;
+$RRD1 = "demo1.rrd";
+$RRD2 = "demo2.rrd";
+$GIF = "demo.gif";
+
+
+RRDp::start "../../src/rrdtool";
+
+print "* Creating First RRD $RRD1\n\n";
+
+$START1 = time()-$RUNS1*$STEP1;
+
+RRDp::cmd "create $RRD1 -b $START1 -s $STEP1
+ DS:in:GAUGE:400:U:U
+ DS:out:GAUGE:400:U:U
+ RRA:AVERAGE:0.5:1:5000
+ RRA:AVERAGE:0.5:8:5000";
+
+$answer = RRDp::read;
+
+print "* Creating Second RRD $RRD2\n\n";
+
+$START2 = time()-$RUNS2*$STEP2;
+
+RRDp::cmd "create $RRD2 -b $START2 -s $STEP2
+ DS:in:GAUGE:400:U:U
+ DS:out:GAUGE:400:U:U
+ RRA:AVERAGE:0.5:1:4000
+ RRA:AVERAGE:0.5:8:5000";
+
+$answer = RRDp::read;
+($user,$sys,$real) = ($RRDp::user,$RRDp::sys,$RRDp::real);
+
+print "* Filling both RRDs with ".(($RUNS1+$RUNS2)*2)." Values. One moment please ...\n";
+print " If you are running over NFS this will take *MUCH* longer\n\n";
+
+for ($i=$START1+1;
+ $i<$START1+$STEP1*$RUNS1;
+ $i+=$STEP1+int((rand()-0.5)*7)){
+
+ $line = "update $RRD1 $i:".
+ (2000*cos($i/1550)).":".
+ (3220*sin($i/3420));
+
+ RRDp::cmd $line;
+ $answer = RRDp::read;
+}
+
+for ($i=$START2+1;
+ $i<$START2+$STEP2*$RUNS2;
+ $i+=$STEP2+int((rand()-0.5)*7)){
+
+ $line = "update $RRD2 $i:".
+ (1000+500*sin($i/1000)).":".
+ (1000+900*sin($i/2330));
+
+ RRDp::cmd $line;
+
+ $answer = RRDp::read;
+}
+($user1,$sys1,$real1) = ($RRDp::user,$RRDp::sys,$RRDp::real);
+
+printf "-- Average Time for one Update (2 RRD 2 DS 2 RRA)\n".
+ " usr: %1.4fs sys: %1.4fs real: %1.4fs logs/s: %1.4f\n",
+ ($user1-$user)/($RUNS1+$RUNS2), ($sys1-$sys)/($RUNS1+$RUNS2),
+ ($real1-$real)/($RUNS1+$RUNS2), ($RUNS1+$RUNS2)/($real1-$real);
+print "\n";
+# creating some graphs
+
+print "* Creating $GRUNS graphs: $GIF\n\n";
+$now = time;
+for ($i=0;$i<$GRUNS;$i++) {
+RRDp::cmd "graph $GIF ", "--title 'Test GRAPH' ",
+ "--height 100 --vertical-label 'Dummy Units' --start ".(-$RUNS1*$STEP1/10),
+ "--color ARROW#bfbfbf",
+ "DEF:alpha=$RRD1:in:AVERAGE",
+ "DEF:beta=$RRD1:out:AVERAGE",
+ "DEF:gamma=$RRD2:in:AVERAGE",
+ "DEF:delta=$RRD2:out:AVERAGE",
+ "CDEF:calc=alpha,beta,+,1.5,/",
+ "AREA:alpha#0022e9:Alpha",
+ "STACK:beta#00b871:'Beta Text\\j'",
+ "LINE1:gamma#ff0000:'Gamma 1'",
+ "LINE2:delta#888800:'Delta 2\\c'",
+ "LINE3:calc#00ff44:'calc 3'",
+ "HRULE:2300#ff8800:'Horizontal Line at 2300'",
+ "PRINT:alpha:AVERAGE:'Average Alpha\\: %1.2f'",
+ "PRINT:alpha:MIN:'Min Alpha\\: %1.2f'",
+ "PRINT:alpha:MAX:'Max Alpha\\: %1.2f'",
+ "GPRINT:calc:AVERAGE:'Average calc\\: %1.2f\\r'",
+ "GPRINT:calc:MAX:'Max calc\\: %1.2f'",
+ "GPRINT:calc:MIN:'Min calc\\: %1.2f'",
+ "VRULE:".($now-3600)."#008877:'60 Minutes ago'",
+ "VRULE:".($now-4600)."#ff8877:",
+ "VRULE:".($now-7200)."#ffff00",
+ "COMMENT:'\\s'",
+ "COMMENT:'a last one centered with some more space aboce\\c'";
+
+$answer = RRDp::read;
+}
+($user2,$sys2,$real2) = ($RRDp::user,$RRDp::sys,$RRDp::real);
+
+print "ANSWER:\n$$answer";
+
+printf "\n-- average Time for one Graph (5 graph, 8 print)\n".
+ " usr: %1.4fs sys: %1.4fs real: %1.4fs graphs/sec: %1.4f\n",
+ ($user2-$user1)/$GRUNS,
+ ($sys2-$sys1)/$GRUNS,
+ ($real2-$real1)/$GRUNS,
+ $GRUNS/($real2-$real1);
+
+RRDp::cmd "graph log$GIF ", "--title 'Log Test GRAPH' ",
+ "--logarithmic --lower-limit 10 --height 200 --vertical-label 'Dummy Units' --start ".(-$RUNS1*$STEP1/10),
+ "DEF:alpha=$RRD1:in:AVERAGE",
+ "DEF:beta=$RRD1:out:AVERAGE",
+ "DEF:gamma=$RRD2:in:AVERAGE",
+ "DEF:delta=$RRD2:out:AVERAGE",
+ "CDEF:calc=alpha,beta,+,1.5,/",
+ "AREA:alpha#0022e9:Alpha",
+ "STACK:beta#00b871:'Beta Text'",
+ "LINE1:gamma#ff0000:'Gamma 1'",
+ "LINE2:delta#888800:'Delta 2'",
+ "LINE3:calc#00ff44:'calc 3'",
+ "GPRINT:calc:AVERAGE:'Average calc\\: %1.2f'",
+ "GPRINT:calc:MAX:'Max calc\\: %1.2f'",
+ "GPRINT:calc:MIN:'Min calc\\: %1.2f'";
+
+$answer = RRDp::read;
+
+print "\n* Created log$GIF to demonstrate logarithmic scaling\n\n";
+
+RRDp::end;
+
+
+
+
+
+
+
+
+
+
+
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/TODO
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/TODO (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/TODO Sat Jul 13 18:46:06 2002
@@ -0,0 +1,9 @@
+let the user define the base resolution of the
+graph independantly of the pixle resolution. If it is smaller than one
+pixle it will simply be ignored
+
+do not fail if the same DEF gets stacked twice
+im->gdes[ii].p_data = im->gdes[vidx].p_data;
+is a bad idea ...
+
+get 1.0 out ...
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.1
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.1 (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.1 Sat Jul 13 18:46:06 2002
@@ -0,0 +1,366 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+''' \*(L" and \*(R", except that they are used on ".xx" lines,
+''' such as .IP and .SH, which do another additional levels of
+''' double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH RRDTOOL 1 "19990426.22" "12/Feb/99" "rrdtool"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+rrdtool \- round robin database tool
+.SH "SYNOPSIS"
+\fBrrdtool\fR \fB\-\fR | \fIfunction\fR
+.SH "DESCRIPTION"
+.Sh "\s-1OVERVIEW\s0"
+It is pretty easy to gather status information from all sorts of
+things, ranging from the temperature in your office to the number of
+octets which have passed through the \s-1FDDI\s0 interface of your
+router. But it is not so trivial to store this data in a efficient and
+systematic manner. This is where \fBrrdtool\fR kicks in. It lets you
+\fIlog and analyze\fR the data you gather from all kinds of data-sources
+(\fB\s-1DS\s0\fR). The data analysis part of rrdtool is based on the ability to
+quickly generate graphical representations of the data values
+collected over a definable time period.
+.PP
+In this man page you will find general information on the design and
+functionality of the Round Robin Database Tool (rrdtool). For a more
+detailed description of how to use the individual functions of the
+\fBrrdtool\fR check the corresponding man page.
+.Sh "\s-1FUNCTIONS\s0"
+While the man pages talk of command line switches you have to set in order to
+make \fBrrdtool\fR work it is important to note that the \fBrrdtool\fR can be
+\&'remote controlled\*(R' through a set of pipes. This saves a considerable
+amount of startup time when you plan to make \fBrrdtool\fR do a lot of
+things quickly. Check the section on the section on \fIRemote Control\fR further down.
+.Ip "\fBcreate\fR" 8
+Set up a new Round Robin Database (\s-1RRD\s0). Check rrdcreate
+.Ip "\fBupdate\fR" 8
+Store new data values into an \s-1RRD\s0. Check rrdupdate
+.Ip "\fBgraph\fR" 8
+Create a graph from data stored in one or several \s-1RRD\s0. Apart from
+generating graphs, data can also be extracted to stdout. Check rrdgraph
+.Ip "\fBdump\fR" 8
+Dump the contents of an \s-1RRD\s0 in plain \s-1ASCII\s0. This is manly used for
+debugging. Check rrddump
+.Ip "\fBfetch\fR" 8
+Get data for a certain time period from a \s-1RRD\s0. The graph function
+uses fetch to retrieve its data from an rrd. Check rrdfetch
+.Ip "\fBtune\fR" 8
+Alter setup of an \s-1RRD\s0
+.Ip "\fBlast\fR" 8
+Find last update time of an \s-1RRD\s0
+.Sh "\s-1HOW\s0 \s-1DOES\s0 \s-1RRDTOOL\s0 \s-1WORK\s0?"
+.Ip "Data acquisition" 8
+When monitoring the state of a system, it is convenient to have the
+data available at a constant interval. Unfortunately you may not
+always be able to fetch data at exactly the time you want
+to. Therefore \fBrrdtool\fR lets you update the logfile at any time you
+want. It will automatically interpolate the value of the data-source
+(\fB\s-1DS\s0\fR) at the latest official time-slot and write this value to the
+log. The value you have supplied is stored as well and is also taken
+into account when interpolating the next log entry.
+.Ip "Consolidation" 8
+You may log data at a 1 minute interval, but you are also be
+interested to know the development of the data over the last year. You
+could do this by simply storing the data in 1 minute interval, for one
+year. While this would take considerable disk space it would also take
+a lot of time to analyze the data when you wanted to create a graph
+covering the whole year. \fBrrdtool\fR offers a solution to this of this
+problem through its data consolidation feature. When setting up
+an Round Robin Database (\fB\s-1RRD\s0\fR), you can define at which interval
+this consolidation should occur, and what consolidation function
+(\fB\s-1CF\s0\fR) (average, minimum, maximum, total, last) should be used to
+build the consolidated values (see rrdcreate). You can define any
+number of different consolidation setups within one \fB\s-1RRD\s0\fR. They will
+all be maintained on the fly when new data is loaded into the \fB\s-1RRD\s0\fR.
+.Ip "Round Robin Archives" 8
+Data values of the same consolidation setup are stored into Round
+Robin Archives (\fB\s-1RRA\s0\fR). This is a very efficient manner to store data
+for a certain amount of time, while using a known amount of storage
+space.
+.Sp
+It works like this: If you want to store 1000 values in 5 minute
+interval, \fBrrdtool\fR will allocate space for 1000 data values and a
+header area. In the header it will store a pointer telling
+which one of the values in the storage area was last written to. New
+values are written to the Round Robin Archive in a ... you guess it
+\&... round robin manner. This automatically limits the history to the last
+1000 values. Because you can define several \fB\s-1RRA\s0\fRs within a single \fB\s-1RRD\s0\fR,
+you can setup another one, storing 750 data values at a 2 hour interval
+and thus keeping a log for the last two months although at a lower
+resolution.
+.Sp
+The use of \fB\s-1RRA\s0\fRs guarantees that the \fB\s-1RRD\s0\fR does not grow over
+time and that old data is automatically eliminated. By using the
+consolidation feature, you can still keep data for a very long time,
+while gradually reducing the resolution of the data along the time
+axis. Using different consolidation functions (\fB\s-1CF\s0\fR) allows you to
+store exactly the type of information that actually interests
+you. (Maximum one minute traffic on the \s-1LAN\s0, minimum temperature of
+the wine cellar, total minutes down time ...)
+.Ip "Unknown Data" 8
+As mentioned earlier, the \fB\s-1RRD\s0\fR stores data at a constant
+interval. Now it may happen that no new data is available when a
+value has to be written to the \fB\s-1RRD\s0\fR. Data acquisition may not be
+possible for one reason or an other. The \fBrrdtool\fR handles these
+situations by storing an \fI*\s-1UNKNOWN\s0*\fR value into the database. The
+value \*(L'\fI*\s-1UNKNOWN\s0*\fR\*(R' is supported through all the functions of the
+database. When consolidating the amount of \fI*\s-1UNKNOWN\s0*\fR data is
+accumulated and when a new consolidated value is ready to be written
+to its Round Robin Archive (\fB\s-1RRA\s0\fR) a validity check is performed to
+make sure that the percentage of unknown data in the new value is
+below a configurable level. If so, an \fI*\s-1UNKNOWN\s0*\fR value will be
+written to the \fB\s-1RRA\s0\fR.
+.Ip "Graphing" 8
+The \fBrrdtool\fR also allows one to generate reports in numerical and
+graphical form based on the data stored in one or several
+\fB\s-1RRD\s0\fRs. The graphing feature is fully configurable. Size, color and
+contents of the graph can be defined freely. Check rrdgraph
+for more information on this.
+.Sh "\s-1REMOTE\s0 \s-1CONTROL\s0"
+When you start \fBrrdtool\fR with the command line option \*(L'\fB\-\fR\*(R', it waits
+for input via standard in. With this feature you can improve
+performance by attaching \fBrrdtool\fR to another process (mrtg is one
+example) through a set of pipes. Over the pipes \fBrrdtool\fR accepts the
+same arguments as on the command line. When a command is completed,
+rrdtool will print the string \*(L'\f(CWOK\fR\*(R', followed by timing information of
+the form \fBu:\fR\fIusertime\fR \fBs:\fR\fIsystemtime\fR both values are running
+totals of seconds since rrdtool was started. If an error occurs, a line
+of the form \*(L'\f(CWERROR:\fR \fIDescription of error\fR\*(R' will be printed. \fBrrdtool\fR
+will not abort if possible, but follow the \s-1ERROR\s0 line with an \s-1OK\s0 line.
+.SH "SEE ALSO"
+rrdcreate, rrdupdate, rrdgraph, rrddump, rrdfetch, rrdtune, rrdlast
+.SH "BUGS"
+There must be plenty ... this is alpha code ;\-) ...
+.SH "AUTHOR"
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
+.rn }` ''
+.IX Title "RRDTOOL 1"
+.IX Name "rrdtool - round robin database tool"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Subsection "\s-1OVERVIEW\s0"
+
+.IX Subsection "\s-1FUNCTIONS\s0"
+
+.IX Item "\fBcreate\fR"
+
+.IX Item "\fBupdate\fR"
+
+.IX Item "\fBgraph\fR"
+
+.IX Item "\fBdump\fR"
+
+.IX Item "\fBfetch\fR"
+
+.IX Item "\fBtune\fR"
+
+.IX Item "\fBlast\fR"
+
+.IX Subsection "\s-1HOW\s0 \s-1DOES\s0 \s-1RRDTOOL\s0 \s-1WORK\s0?"
+
+.IX Item "Data acquisition"
+
+.IX Item "Consolidation"
+
+.IX Item "Round Robin Archives"
+
+.IX Item "Unknown Data"
+
+.IX Item "Graphing"
+
+.IX Subsection "\s-1REMOTE\s0 \s-1CONTROL\s0"
+
+.IX Header "SEE ALSO"
+
+.IX Header "BUGS"
+
+.IX Header "AUTHOR"
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdintro.pod
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdintro.pod (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdintro.pod Sat Jul 13 18:46:06 2002
@@ -0,0 +1,1391 @@
+
+From alex at slot.hollandcasino.nl Tue May 4 23:16:13 1999
+Date: Sun, 2 May 1999 15:03:21 +0200 (MET DST)
+From: Alex van den Bogaerdt <alex at slot.hollandcasino.nl>
+To: Tobias Oetiker <oetiker at ee.ethz.ch>
+Subject: Corrected document
+
+Hi Tobi,
+
+Here are the two files again. I implemented the changes you suggested
+and made some minor changes myself.
+
+We both agree that a native English speaker should correct it before
+it goes online and do so for the same reason. I know that some parts may
+sound odd. I think it may be wise to have two or even more people look
+at it, at least one beginner and one experienced RRDtool user.
+
+You offered to convert it into the POD format, I suggest you do this
+and then ask some people to look it over.
+
+I'm still looking for a document I once read about color usage. It
+described a set of colors that are safe to use in an HTML document.
+You once suggested to look at /usr/X11/lib/X11/rgb.txt but this contains
+over 500 different colors (so: after removing descriptive labels and
+going trough sort -u) and I know for sure that the document I talk about
+describes about 240 different colors. I think it will be a valuable
+addition to both MRTG and RRDtool.
+
+Regards,
+Alex
+
+#!/bin/sh
+# This is RRDbeginnersGuide, a shell archive (produced by GNU sharutils 4.2)
+# To extract the files from this archive, save it to some FILE, remove
+# everything before the `!/bin/sh' line above, then type `sh FILE'.
+#
+# Made on 1999-05-02 14:44 MET DST by <alex at ergens.op.Het.Net>.
+# Source directory was `/mnt/sdb1/RrdDummy/workdir'.
+#
+# Existing files will *not* be overwritten unless `-c' is specified.
+# This format requires very little intelligence at unshar time.
+# "if test", "echo", "mkdir", and "sed" may be needed.
+#
+# This shar contains:
+# length mode name
+# ------ ---------- ------------------------------------------
+# 47151 -rw-r--r-- RRDbeginner
+# 12288 -rw-r--r-- binhex
+#
+echo=echo
+if mkdir _sh06095; then
+ $echo 'x -' 'creating lock directory'
+else
+ $echo 'failed to create lock directory'
+ exit 1
+fi
+# ============= RRDbeginner ==============
+if test -f 'RRDbeginner' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'RRDbeginner' '(file already exists)'
+else
+ $echo 'x -' extracting 'RRDbeginner' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'RRDbeginner' &&
+XNot so technical explanation of RRDtool (c) by Alex van den Bogaerdt
+X
+XRRDtool (c) 1999 by Tobias Oetiker
+X
+XRRDtool is written by Tobias Oetiker <oetiker at ee.ethz.ch> with
+Xcontributions from many people all around the world. This document is
+Xwritten by Alex van den Bogaerdt <alex at ergens.op.het.net> to help you
+Xunderstand what RRDtool is and what it can do for you.
+X
+XThe documentation provided with RRDtool can be too technical for some
+Xpeople and here we help you to understand the basics in order to
+Xprepare you to read the documentation yourself. It also explains the
+Xgeneral things about statistics with a focus on networking.
+X
+XThis document may not be redistributed by any means without prior
+Xwritten permission from the author.
+XPermission to distribute copies of this document for non-commercial
+Xpurposes is hereby granted provided that the document is kept intact
+Xincluding this copyright message and disclamer, and provided that
+Xit comes together with the documentation for RRDtool.
+X
+XVersion: may 1999.
+X
+XPlease make sure you have a reasonable recent copy. If you do and you
+Xfeel this document contains errors or is incomplete, please mail me
+Xwith a description of the error/missing part, and why you think so.
+XThis will help me to improve it. Your help is appreciated.
+XPlease note that I will ignore request like
+X"my copy is from may 1999, could you mail me a more recent one ?"
+XIf there is a newer version, it will come with the RRDtool release.
+X
+XChange history:
+X199903xx: Alex van den Bogaerdt
+X Initial draft
+X19990502: Alex van den Bogaerdt
+X Made some textual improvements as suggested by Tobias Oetiker
+X199905xx: Tobias Oetiker
+X Converted document to POD format
+X
+X ============================== do not cut here ===============================
+X
+X0 IMPORTANT
+X
+XWe first have to do some uninteresting reading folks, don't skip this
+Xpart! Later on, in the examples, you need to know the basics.
+X
+X1 What is RRDtool ?
+X
+XRRDtool means Round Robin Database tool.
+XRound robin is a technique that works with a fixed amount of data, and a
+Xpointer to the current element. Think of a circle with some dots plotted
+Xon the edge, these dots are the places where data can be stored. Draw an
+Xarrow from the center of the circle to one of the dots, this is the pointer.
+XWhen the current data is read or written, the pointer moves to the next
+Xelement. As we are on a circle there is no beginning nor an end, you can
+Xgo on and on. After a while, all the available places will be used and
+Xthe process automatically reuses old locations.
+XRRDtool works with with Round Robin Databases (RRDs). It stores and retrieves
+Xdata from them.
+X
+X2 What data can be put into an RDD ?
+X
+XYou name it, it will probably fit. You should be able to measure some value
+Xat several points in time and provide this to RRDtool. If you can do this,
+XRRDtool will probably be able to store it.
+X
+XMany examples talk about SNMP which is an acronym for
+XSimple Network Management Protocol. The "simple" is about the protocol,
+Xit does not mean it is simple to manage a network. After working your
+Xway through this document, you will know enough to be able to understand
+Xwhat people are talking about. For now, just assume SNMP is a way to
+Xtalk to devices and ask those devices about counters they keep.
+XIt is the value from those counters that are kept in the RRD.
+X
+X3 What can I do with this tool ?
+X
+XRRDtool originated from MRTG (multi router traffic grapher) which itself
+Xcame from a tiny little script to monitor the performance of a connection
+Xto the Internet. Since then, MRTG has also been used for several other
+Xpurposes including temperature, speed, voltage, number of printouts and
+Xmany other things. Most likely you will start to use the RRDtool to store
+Xand process data collected via SNMP. The data will most likely be bytes
+X(or bits) transfered from and to a network or a computer.
+XRRDtool lets you create a database, store data in it, retrieve that data
+Xand create graphs in GIF format for display on a web browser. Those GIF
+Ximages are dependant on the data you collected and could be, for instance,
+Xan overview of the average network usage, or rather the peaks that occurred.
+XIt can also be used to display tidal waves, solar radiation, power
+Xconsumption, number of visitors at an exibition, noise levels near an
+Xairport, temperature on your favorite holiday location, temperature in the
+Xfridge and whatever you imagination can come up with. You need a sensor to
+Xmeasure the data and be able to feed the numbers to RRDtool. Many devices
+Xhave such a sensor.
+X
+X4 What if I still have problems after reading this document ?
+X
+XMore exact, after re-reading this document :)
+XIt all depends on the kind of problems you have. If you are unable to
+Xcompile the sources and you have a fairly common OS, it will probably
+Xnot be the fault of RRDtool. There may be precompiled versions around
+Xon the Internet. If they come from trusted sources, get one of those.
+XIf on the other hand the program works but does not give you the
+Xexpected results, it will be a problem with configuring it. Review
+Xyour configuration and compare it with the examples that follow.
+X
+XThere is a mailing list and an archive of it. Read the list for a few
+Xweeks and search the archive. It is considered rude to just ask
+Xa question without reading the list, your problem may already have been
+Xsolved for somebody else and you will be helped without writing a new
+Xa message at all ... This is true for most, if not all, mailing lists
+Xand not only for this particular list! Look in the documentation that
+Xcame with RRDtool for the location and usage of the list.
+X
+XI suggest you take a moment to subscribe to the mailing list right now
+Xby sending an email to <rrdtool-users-request at list.ee.ethz.ch> with a
+Xsubject of "subscribe". If you ever want to leave this list, you write
+Xan email to the same address but now with a subject of "unsubscribe".
+X
+X5 How will you help me ?
+X
+XBy giving you some detailed descriptions with detailed examples.
+XIt is assumed that following the instructions in the order presented
+Xwill build up enough knowledge of the program to experiment for yourself.
+XIf it doesn't work the first time, don't give up. Reread the stuff that
+Xyou did understand, you may have missed something.
+XBy following the examples you get some hands-on experience and, even
+Xmore important, some background information of how it works.
+X
+XYou will need to know something about hexadecimal numbers. If you don't
+Xthen start with reading "binhex" before you continue here.
+X
+XIn my opinion the best way to learn something is to actually do it.
+XWhy not start right now. We will create a database, put some values in
+Xit and extract this data again. It is expected that you get the same
+Xresults when you try these examples yourself so do that.
+XWe will start with some easy stuff and compare a car with a router,
+Xor compare kilometers (miles if you wish) with bits and bytes. It's
+Xall the same: Some number over some time.
+X
+XAssume we have a device that transfers bytes to and from the Internet.
+XThis device keeps a counter that starts at zero when it is turned on,
+Xincreasing with every byte that is transfered. This counter will have
+Xa maximum value, if that value is reached and an extra byte is counted,
+Xthe counter starts all over at zero. This is the same as many counters
+Xin the world such as the mileage counter in a car.
+XMost discussions about networking talk about bits per second so lets
+Xget used to that right away. Assume a byte is eight bits and start to
+Xthink in bits not bytes. The counter however still counts bytes !
+XIn the SNMP world most of the counters are 32 bits. That means they are
+Xcounting from 0 to 4294967295. We will use these values in the examples.
+XThe device, when asked, returns the current value of the counter. We
+Xknow the time that has passes since we last asked so we now know how
+Xmany bytes have been transfered ***on average*** per second. This is
+Xnot very hard to calculate. First in words, then in calculi:
+X 1) Take the current counter, subtract the previous value from it.
+X 2) Do the same with the current time and the previous time.
+X 3) Divide the outcome of (1) by the outcome of (2), the result is
+X the amount of bytes per second. Multiply by eight to get the
+X number of bits per second (bps).
+X bps = (counter_now - counter_before) / (time_now - time_before) * 8
+X
+XFor some people it may help to translate this to a automobile example:
+XDo not try this example, and if you do, don't blame me for the results.
+X
+XPeople who are not used to think in kilometers per hour can translate
+Xmost into miles per hour by dividing km by 1.6 (close enough).
+XI will use the following abbreviations:
+XM: meter
+XKM: kilometer (= 1000 meters).
+XH: hour
+XS: second
+XKM/H: kilometers per hour
+XM/S: meters per second
+X
+XYou're driving a car. At 12:05 you read the counter in the dashboard
+Xand it tells you that the car has moved 12345 KM until that moment.
+XAt 12:10 you look again, it reads 12357 KM. This means you have
+Xtraveled 12 KM in five minutes. A scientist would translate that
+Xinto meters per second and this makes a nice comparison towards the
+Xproblem of (bytes per five minutes) versus (bits per second).
+X
+XWe traveled 12 kilometers which is 12000 meters. We did that in five
+Xminutes which translates into 300 seconds. Our speed is 12000M / 300S
+Xequals 40 M/S.
+X
+XWe could also calculate the speed in KM/H: twelve times five minutes
+Xis an hour so we have to multiply 12 KM by 12 to get 144 KM/H.
+XFor our native English speaking friends: this is ninety MPH and
+Xtherefore not recommended to try for yourself where I live :)
+X
+XRemember: these numbers are averages and there is no way to figure out
+Xfrom the numbers we got that you drove at a constant speed.
+X
+XI hope you understand that there is no difference in calculating M/S or
+Xbps, only the way we collect the data is different. Even the K from kilo
+Xis the same as in networking terms k also means 1000.
+X
+XWe will now create a database where we can keep all these interesting
+Xnumbers. The method used to start the program may differ slightly from
+XOS to OS but I assume you can figure it out if it works different on
+Xyour OS. Make sure you do not overwrite any file on your system when
+Xexecuting the following command (so: first look if it's safe!) and type
+Xthe whole line as one long line (I had to split it for readability)
+Xand skip all of the '\' characters.
+X
+X rrdtool create test.rrd \
+X --start 920804400 \
+X DS:speed:COUNTER:600:U:U \
+X RRA:AVERAGE:0.5:1:24 \
+X RRA:AVERAGE:0.5:6:10
+X
+X (So enter: rrdtool create test.rrd --start 920804400 DS ...)
+X
+XWhat has been created ?
+XWe created the round robin database called test (test.rrd)
+Xwhich starts at noon the day I started (7th of march, 1999) writing
+Xthis document. It holds one data source (DS) named "speed" that gets
+Xbuilt from a counter. This counter is read every five minutes (default)
+XIn the same database two round robin archives (RRAs) are kept, one
+Xaverages the data every time it is read (so: there's nothing to average)
+Xand keeps 24 samples (24 times 5 minutes is 2 hours). The other averages
+X6 values (half hour) and contains 10 of such averages (so: 5 hours)
+XThe remaining options will be discussed later on.
+XChances are that you are not in the same part of the world as I am.
+XThis means your time zone is different. In all examples where I talk
+Xabout time, the hours may be wrong for you. This has little effect on
+Xthe results of the examples, just correct the hours while reading.
+X
+XWe now have to fill our database with some numbers. We'll pretend to
+Xhave read the following numbers:
+X
+X12:05 12345 KM
+X12:10 12357 KM
+X12:15 12363 KM
+X12:20 12363 KM
+X12:25 12363 KM
+X12:30 12373 KM
+X12:35 12383 KM
+X12:40 12393 KM
+X12:45 12399 KM
+X12:50 12405 KM
+X12:55 12411 KM
+X13:00 12415 KM
+X13:05 12420 KM
+X13:10 12422 KM
+X13:15 12423 KM
+X
+XWe fill the database as follows:
+X
+X rrdtool update test.rrd 920804700:12345 920805000:12357 920805300:12363
+X rrdtool update test.rrd 920805600:12363 920805900:12363 920806200:12373
+X rrdtool update test.rrd 920806500:12383 920806800:12393 920807100:12399
+X rrdtool update test.rrd 920807400:12405 920807700:12411 920808000:12415
+X rrdtool update test.rrd 920808300:12420 920808600:12422 920808900:12423
+X
+XThis reads: update our test database with the following numbers
+X time 920804700, value 12345
+X time 920805000, value 12357
+X etcetera.
+X
+XAs you can see, it is possible to feed more than one value into the
+Xdatabase in one command. I had to stop at three for readability but
+Xthe real maximum will be OS dependent.
+X
+XThe time value may look strange to you, it is written in seconds since
+Xthe first of January, 1970, midnight. Don't worry about this yet, just
+Xnotice that there is a difference of 300 in between all values.
+X
+XIt is time to do some graphics now:
+X
+X rrdtool graph speed.gif \
+X --start 920804400 --end 920808000 \
+X DEF:myspeed=test.rrd:speed:AVERAGE \
+X LINE2:myspeed#FF0000
+X
+XThis will create speed.gif which starts at 12:00 and ends at 13:00.
+XThere is a definition of variable myspeed, it is the data from RRA
+X"speed" out of database "test.rrd". The line drawn is 2 pixels high,
+Xand comes from variable myspeed. The color is red.
+XYou'll notice that the start of the graph is not at 12:00 but at 12:05
+Xand this is because we have insufficient data to tell the average before
+Xthat time. This will only happen when you miss some samples, this will
+Xnot happen a lot, hopefully.
+X
+XIf this has worked: Congratulations. If not, check what went wrong.
+X
+X
+XThe colors are built up from red, green and blue. For each of the
+Xcomponents, you specify how much to use in hexadecimal where 00 means
+Xnot included and FF means fully included.
+XThe color white is a mixture of red, green and blue: FFFFFF
+XThe color black is all colors off: 000000
+X(Please, no discussions if black and white can be called colors)
+X
+X red #FF0000
+X green #00FF00
+X blue #0000FF
+X purple #FF00FF (mixed red with blue)
+X gray #555555 (one third of all components)
+X
+X
+X
+XThe GIF you just created can be displayed using a web browser or other
+Xsoftware you like. I can not provide you with an example of that, there
+Xare too many different setups, possibilities etc.
+X
+XWhen looking at the image, you notice that the horizontal axis displays
+X12:10, 12:20, 12:30, 12:40 and 12:50. The two remaining times (12:00 and
+X13:00) would not be displayed nicely so they are skipped.
+XThe vertical axis displays the range we entered. We provided kilometers
+Xand when divided by 300 seconds, we get very small numbers. To be exact,
+Xthe first value was 12 (12357-12345) and divided by 300 this makes 0.04
+XRRDtool displays this as 40 m which means 40 mili (so: NOT meters).
+XWhat we did wrong was that we should have measured in meters, this would
+Xhave been (12357000-12345000)/300 = 12000/300 = 40.
+X
+XLet's correct that. We could recreate our database and store the correct
+Xdata but there is another way: do some calculations while creating the
+Xgif file !
+X
+X rrdtool graph speed2.gif \
+X --start 920804400 --end 920808000 \
+X --vertical-label m/s \
+X DEF:myspeed=test.rrd:speed:AVERAGE \
+X CDEF:realspeed=myspeed,1000,* \
+X LINE2:realspeed#FF0000
+X
+XAfter viewing this GIF, you notice the "m" has disappeared. This it what
+Xthe correct result would be. Also, a label has been added to the image.
+XApart from the things mentioned above, the GIF should be the same.
+X
+XThe calculations are done with the CDEF part. What it says is: take the
+Xdata source myspeed and the number 1000, multiply those. The calculations
+Xare done using Reverse Polish Notation. It is an easy way of performing
+Xcalculations after you understand it. You will, eventually but for now
+Xassume it is correct what I write and just keep to the examples in this
+Xfile. Read the documentation that came with RRDtool (look in rrdgraph.doc)
+Xwhen you're ready for it.
+X
+XHang on! If we can multiply values with 1000, it should also be possible
+Xto display kilometers per hour from the same data !
+XWhat do we need to do ? If we have meters per second, we can make this
+Xmeters per hour by multiplying the value with 3600 (there go 3600 seconds
+Xin one hour). To get kilometers per hour, we need to divide by 1000.
+XWe end up with: value * 3600 / 1000 = value * 3.6 . Remember we also have
+Xto correct our mistake, so it is value * 3600 for us.
+X
+XNow lets create this GIF, and add some more magic ...
+X
+X rrdtool graph speed3.gif \
+X --start 920804400 --end 920808000 \
+X --vertical-label km/h \
+X DEF:myspeed=test.rrd:speed:AVERAGE \
+X CDEF:kmh=myspeed,3600,* \
+X CDEF:fast=0,kmh,kmh,100,GT,IF \
+X CDEF:good=kmh,0,kmh,100,GT,IF \
+X HRULE:100#0000FF:"Maximum allowed" \
+X AREA:good#00FF00:"Good speed" \
+X AREA:fast#FF0000:"Too fast"
+X
+XThis looks much better. Speed in KM/H and even an extra line with the
+Xmaximum allowed speed (on the road I travel at). I also changed the
+Xcolors used to display speed and changed it from a line into an area.
+X
+XThe calculations are more complex now. For the "good" speed they are:
+X- Check if kmh is greater than 100 ( kmh,100 ) GT
+X- If so, return 0, else kmh ( kmh,0, (( kmh,100 ) GT ) IF
+XFor the other speed:
+X- Check if kmh is greater than 100 ( kmh,100 ) GT
+X- If so, return kmh, else return 0 ( 0,kmh, (( kmh,100) GT ) IF
+X
+X
+XI like to believe there are virtually no limits about what RRDtool
+Xcan do. I will not explain how it works, but look at the following
+XGIF:
+X
+X rrdtool graph speed4.gif \
+X --start 920804400 --end 920808000 \
+X --vertical-label km/h \
+X DEF:myspeed=test.rrd:speed:AVERAGE \
+X CDEF:kmh=myspeed,3600,* \
+X CDEF:fast=0,100,kmh,100,GT,IF \
+X CDEF:over=0,kmh,100,-,kmh,100,GT,IF \
+X CDEF:good=kmh,0,kmh,100,GT,IF \
+X HRULE:100#0000FF:"Maximum allowed" \
+X AREA:good#00FF00:"Good speed" \
+X AREA:fast#550000:"Too fast" \
+X STACK:over#FF0000:"Over speed"
+X
+XLet's create a quick and dirty HTML page to view three GIFs:
+X
+X <HTML><HEAD><TITLE>Speed</TITLE></HEAD><BODY>
+X <IMG src="speed2.gif" alt="Speed in meters per second">
+X <BR>
+X <IMG src="speed3.gif" alt="Speed in kilometers per hour">
+X <BR>
+X <IMG src="speed4.gif" alt="Traveled too fast?">
+X </BODY></HTML>
+X
+XName the file "speed.html" or similar, and view it.
+X
+XNow, all you have to do is measure the values regularly and update the
+Xdatabase. Every time you create these three GIFs and reload the page
+Xand the GIFs (better reread this last three words!) you know how fast
+Xyou traveled.
+X
+XYou already looked at the "update" tool. It took one or more parameters
+Xin the form of "<time>:<value>". You'll be glad to know that you can
+Xget the current time by filling in a "N" as the time.
+XIf you wish, you can also use the "time" function in perl.
+XThe shortest example in this doc :)
+X
+X perl -e 'print time, "\n" '
+X
+XHow you can run a program on regular intervals is OS specific, so I just
+Xgive you an example script in a sort of pseudo code:
+X(Do not try this with our test database, it is used in further examples)
+X
+X Get the value, put it in variable "$speed"
+X rrdtool update speed.rrd N:$speed
+X
+XThis is all. Run this script every five minutes. When you need to know
+Xwhat the graphics look like, run the examples above. You could put them
+Xin a script. After running that script, view index.html
+X
+XI can imagine very few people will be able to get real data from their
+Xcar every five minutes, all other people will have to settle for some
+Xother kind of counter. You could measure the number of pages printed by
+Xthe laser-jet printer, the coffee made by the coffee machine, a device
+Xthat counts the electricity used, whatever. Just as long as it is an
+Xincrementing counter that you can measure regularly, you can graph it
+Xagainst time as we did. Most people will use the counter that keeps track
+Xof octets (bytes) transfered by a routing device so we have to do just
+Xthat. We will start with a description of how to collect data.
+XSome people will make a remark that there are tools who can do this data
+Xcollection for you. They are right! However, I feel it is important that
+Xyou understand they are not necessary. If you have to look why things
+Xwent wrong, you need to know how the stuff works.
+X
+XOne tool used in the example has been talked about very briefly in the
+Xbeginning of this document, it is called SNMP. It is a way of talking to
+Xequipment. The tool I use below is called "snmpget" and this is how it
+Xworks:
+X
+X snmpget device password OID
+X
+XFor device you substitute the name of your device, for password you
+Xuse the "community" as it is called. For most devices "public" will do
+Xbut this can be disabled, altered or protected for privacy and security
+Xreasons. You will need to find this out as there is no way I can tell
+Xwhat you ( ...your device... ) are keeping a secret for me.
+X
+XThen there is this third parameter, called OID.
+XWhen you start to learn about SNMP it looks very confusing. It isn't
+Xall that difficult when you look at the Management Information Base
+Xor in short: the MIB. It is an up-side-down tree, with a single node
+Xas the root and from there a number of branches. These branches end
+Xup in another node, they branch out etc. All the branches have a name
+Xand they form the path that we follow all the way down. The branches
+Xthat we follow are named: iso, org, dod, internet, mgmt and mib-2.
+XThese names can also be written down as numbers and are 1 3 6 1 2 1.
+X
+X iso.org.dod.internet.mgmt.mib-2 (1.3.6.1.2.1)
+X
+XFrom there, we are especially interested in the branch "interfaces"
+Xwhich has number 2 (so: 1.3.6.1.2.1.2 or 1.3.6.1.2.1.interfaces).
+X
+XThe SNMP programs that I know can take above path as a default, so
+XI could walk to interfaces without writing it in full. To do that,
+Xthe path has to be written as interfaces, without a leading dot.
+XI could also use the long form, then I need to start with a dot.
+X
+XI can intermix numbers and names as I like. 1.3.6.1.2.1 is the same
+Xas iso.org.dod.1.2.1 and 1.3.6.internet.2.mib-2
+XFor interfaces I could write "interfaces", 2, or a long version by
+Xprefixing it with ".1.3.6.1.2.1.". Just try what works for you and
+Xdo read the manual for snmpget.
+X
+XFirst, we have to get some SNMP program. First look if there is a
+Xpre-compiled package available for your OS. This is the preferred way.
+XIf not, you will have to get yourself the sources and compile those.
+XThe Internet is full of sources, programs etc. Find information using
+Xa search engine or whatever you prefer. You are on your own here, sorry.
+X
+XRight, you got the program. First try to collect some data that is
+Xavailable on most systems. Remember: there is a short name for the
+Xpart of the tree that interests us most in the world we live in !
+XI will use the short version as I think this document is large enough
+Xas it is. If that doesn't work for you, prefix with .1.3.6.1.2.1 and
+Xtry again. Also, Read The Fine Manual. Skip the parts you cannot
+Xunderstand yet, you should be able to find out how to start the
+Xprogram and use it.
+X
+X snmpget myrouter public system.sysdescr.0
+X
+XThe device should answer with a description of itself, perhaps empty.
+XUntil you got a valid answer from a device, perhaps using a different
+X"password", or a different device, there is no point in continuing.
+X
+X snmpget myrouter public interfaces.ifnumber.0
+X
+XHopefully you get a number as a result, the number of interfaces.
+XIf so, you can carry on and try a different program called "snmpwalk".
+X
+X snmpwalk myrouter public interfaces.iftable.ifentry.ifdescr
+X
+XIf it returns with a list of interfaces, you're almost there.
+XHere's an example:
+X [user at host /home/alex]$ snmpwalk cisco public 2.2.1.2
+X
+X interfaces.ifTable.ifEntry.ifDescr.1 = "BRI0: B-Channel 1"
+X interfaces.ifTable.ifEntry.ifDescr.2 = "BRI0: B-Channel 2"
+X interfaces.ifTable.ifEntry.ifDescr.3 = "BRI0" Hex: 42 52 49 30
+X interfaces.ifTable.ifEntry.ifDescr.4 = "Ethernet0"
+X interfaces.ifTable.ifEntry.ifDescr.5 = "Loopback0"
+X
+XOn this cisco equipment, I would like to monitor the "Ethernet0"
+Xinterface and see that it is number four. I try:
+X
+X [user at host /home/alex]$ snmpget cisco public 2.2.1.10.4 2.2.1.16.4
+X
+X interfaces.ifTable.ifEntry.ifInOctets.4 = 2290729126
+X interfaces.ifTable.ifEntry.ifOutOctets.4 = 1256486519
+X
+XSo now I have two OIDs to monitor and they are (in full, this time):
+X 1.3.6.1.2.1.2.2.10
+Xand
+X 1.3.6.1.2.1.2.2.16
+Xboth with an interface number of 4.
+X
+XDon't get fooled, this wasn't my first try. It took some time for me too
+Xto understand what all these numbers mean, it does help a lot when they
+Xget translated into descriptive text... At least, when people are talking
+Xabout MIBs and OIDs you know what it's all about.
+XDo not forget the interface number (0 if it is not interface dependent)
+Xand try snmpwalk if you don't get an answer from snmpget.
+X
+XIf you understand above part, and get numbers from your device, it is
+Xtime to continue with the following. If not, then go back.
+X
+XLet the fun begin. First, create a new database. It contains data from
+Xtwo counters, called input and output. The data is put into archives
+Xthat average it. They take 1, 6, 24 or 288 samples at a time.
+XThey also go into archives that keep the maximum numbers. This will be
+Xexplained later on. The time in-between samples is 300 seconds, a good
+Xstarting point, which is the same as five minutes.
+X
+X1 sample averaged stays 1 period of 5 minutes
+X6 samples averaged become one average on 30 minutes
+X24 samples averaged become one average on 2 hours
+X288 samples averaged become one average on 1 day
+X
+XThere are 600 samples of five minutes, together just over two days
+XThere are 600 samples of 30 minutes, almost two weeks
+XThere are 600 samples of 2 hours, 50 hour or almost two months
+XThere are 732 samples of 1 day, just over two year
+X
+XFor people used to MRTG that even have read the manuals, these numbers
+Xshould look familiar...
+X
+X rrdtool create myrouter.rrd \
+X DS:input:COUNTER:600:U:U \
+X DS:output:COUNTER:600:U:U \
+X RRA:AVERAGE:0.5:1:600 \
+X RRA:AVERAGE:0.5:6:600 \
+X RRA:AVERAGE:0.5:24:600 \
+X RRA:AVERAGE:0.5:288:732 \
+X RRA:MAX:0.5:1:600 \
+X RRA:MAX:0.5:6:600 \
+X RRA:MAX:0.5:24:600 \
+X RRA:MAX:0.5:288:732
+X
+XNext thing to do is collect data and store it. Here is an example.
+XIt is written partially in pseudo code so you will have to find out what
+Xto do exactly on your OS to make it work.
+X
+X while not the end of the universe
+X do
+X get result of
+X snmpget router community 2.2.1.10.4
+X into variable $in
+X get result of
+X snmpget router community 2.2.1.16.4
+X into variable $out
+X
+X rrdtool update myrouter.rrd N:$in:$out
+X
+X wait for 5 minutes
+X done
+X
+XThen, after collecting data for a day, try to create an image using:
+X
+X rrdtool graph myrouter-day.gif --start -86400 \
+X DEF:inoctets=myrouter.rrd:input:AVERAGE \
+X DEF:outoctets=myrouter.rrd:output:AVERAGE \
+X AREA:inoctets#00FF00:"In traffic" \
+X LINE1:outoctets#0000FF:"Out traffic"
+X
+XThis should produce a picture with one day worth of traffic.
+XOne day is 24 hours of 60 minutes of 60 seconds: 24*60*60=86400, we
+Xstart at now minus 86400 seconds. We DEFine inoctets and outoctets
+Xas the average values from the database myrouter.rrd and draw an area
+Xfor the "in" traffic and a line for the "out" traffic.
+X
+XView the image and keep logging for a few more days.
+XIf you like, you could try the examples from the test database and
+Xsee if you can play around with the options and calculations.
+XSuggestion:
+XDisplay in bytes per second and in bits per second. Make the ethernet
+Xgraphics go red if they are over four megabit per second.
+X
+X
+XA few paragraphs back I mentioned the possibility to keep the maximum
+Xvalues instead of the average values. Lets go into this a bit more.
+X
+XRecall all the stuff about the speed of the car. Suppose we drove at 144
+XKM/H during 5 minutes and then were stopped by the police for 25 minutes.
+XAt the end of the lecture we would take our laptop and create+view the
+Ximage taken from the database. If we would look at the second RRA we did
+Xcreate, we would have the average from 6 samples. The samples measured
+Xwould be 144+0+0+0+0+0=144, divided by 30 minutes, corrected for the
+Xerror by 1000, translated into KM/H, with a result of 24 KM/H.
+XI would still get a ticket but not for speeding anymore :)
+X
+XObviously, in this case, we shouldn't look at the averages. In some
+Xcases they are handy. If you want to know how much KM you had traveled,
+Xthe picture would be the right one to look at. On the other hand, for
+Xthe speed that we traveled at, the maximum number seen is much more
+Xvaluable. (later we will see more types)
+X
+XIt is the same for data. If you want to know the amount, look at the
+Xaverages. If you want to know the rate, look at the maxima.
+XOver time, they will grow apart more and more. In the last database
+Xwe have created, there are two archives that keep data per day. The
+Xarchive that keeps averages will show low numbers, the archive that
+Xshows maxima will have higher numbers.
+XFor my car this would translate in averages per day of 96/24=4 KM/H
+X(as I travel about 94 kilometers on a day) during week days, and
+Xmaxima of 120 KM/H on weekdays (my top speed that I reach every day).
+X
+XBig difference. Do not look at the second graph to estimate the
+Xdistances that I travel and do not look at the first graph to
+Xestimate my speed. This will work if the samples are close together,
+Xas they are in five minutes, but not if you average.
+X
+XOn some days, I go for a long ride. If I go across Europe and travel
+Xfor over 12 hours, the first graph will rise to about 60 KM/H. The
+Xsecond one will show 180 KM/H. This means that I traveled a distance
+Xof 60 KM/H times 24 H = 1440 KM. I did this with a higher speed and
+Xa maximum around 180 KM/H. This doesn't mean that I traveled for 8
+Xhours at a constant speed of 180 KM/H !
+XThis is a real example: go with the flow through Germany and stop
+Xa few times for gas and coffee. Drive slowly through Austria and the
+XNetherlands. Be careful in the mountains and villages. If you would
+Xlook at the graphs created from the five-minute averages you would
+Xget a totally different picture. You would see the same values on the
+Xaverage and maximum graphs (provided I measured every 300 seconds).
+XYou would be able to see when I stopped, when I was in top gear, when
+XI drove over fast motor-ways etc. The granularity of the data is much
+Xhigher, so you can see more. However, this takes 12 samples per hour,
+Xor 288 values per day, so it would be too much to keep for a long
+Xperiod of time. Therefore we average it, eventually to one value per
+Xday. From this one value, we cannot see much detail.
+X
+XMake sure you understand the last few paragraphs. There is no value
+Xin only a line and a few axises, you need to know what they mean and
+Xinterpret the data in a good way. This is true for all data.
+X
+XThe biggest mistake you can make is to use the collected data for
+Xsomething that it is not suitable for. You would be better off if
+Xyou would not have the graphics at all in that case.
+X
+X
+XLet's review what you now should know.
+XYou now know how to create a database. You can put the numbers in it,
+Xget them out again by creating an image, do math on the data from the
+Xdatabase and view the outcome instead of the raw data.
+XYou know about the difference between averages and maxima, and when
+Xto use which (or at least you have an idea).
+X
+XRRDtool can do more than what we have learned until know. Before you
+Xcontinue with the rest of this doc, I recommend that you reread from
+Xthe start and try some modifications on the examples. Make sure you
+Xfully understand everything. It will be worth the effort and helps
+Xyou not only with the rest of this doc but also in your day to day
+Xmonitoring long after you read this introduction.
+X
+X
+X
+X
+X
+X
+XAll right, you feel like continuing. Welcome back and get ready
+Xfor an increased speed in the examples and explanation.
+X
+XYou know that in order to view a counter over time, you have to
+Xtake two numbers and divide the difference of them between the
+Xtime lapsed. This makes sense for the examples I gave you but there
+Xare other possibilities. For instance, I'm able to retrieve the
+Xtemperature from my router in three places namely the inlet, the
+Xso called hot-spot and the exhaust. If I would take the difference of
+Xtwo samples and divide that by 300 (seconds) there would not be very
+Xmuch to display ... If there would be anything to display it would
+Xbe the fluctuations in the temperature and if they produce noticeable
+Xresults when divided by 300, I'd better look for a new computer room.
+X
+XSo, what can we do ?
+XRRDtool can also store the values you measure directly as they are
+X(this is not entirely true but close enough). The graphs we make look
+Xmuch better, they will show a value that is rather constant. I know
+Xwhen the router is busy (it works -> it uses more electricity -> it
+Xgenerates more heat -> the temperature rises). I know when the doors
+Xare left open (the room is cooled -> the warm air from the rest of
+Xthe building flows into the computer room -> the inlet temperature
+Xrises) etc. The data type we use when creating the database before
+Xwas counter, we now have a different data type and thus a different
+Xname for it. It is called GAUGE. There are more such data types:
+X - COUNTER we already know this one
+X - GAUGE we just learned this one
+X - DERIVE
+X - ABSOLUTE
+X
+XThe two new types are derive and absolute. Absolute can be used like
+Xcounter with one difference: RRDtool assumes the counter is reset when
+Xit's read. That is: its delta is known without calculation by RRDtool
+Xwhereas RRDtool needs to calculate it for the counter type.
+XExample: our first example (12345, 12357, 12363, 12363) would read:
+Xunknown, 12, 6, 0. The rest of the calculations stay the same.
+XThe other one, derive, is like counter. Unlike counter, it can also
+Xdecrease so it can have a negative delta. Again, the rest of the
+Xcalculations stay the same.
+X
+XLet's try them all:
+X
+X rrdtool create all.rrd --start 978300900 \
+X DS:a:COUNTER:600:U:U \
+X DS:b:GAUGE:600:U:U \
+X DS:c:DERIVE:600:U:U \
+X DS:d:ABSOLUTE:600:U:U \
+X RRA:AVERAGE:0.5:1:10
+X rrdtool update all.rrd \
+X 978301200:300:1:600:300 \
+X 978301500:600:3:1200:600 \
+X 978301800:900:5:1800:900 \
+X 978302100:1200:3:2400:1200 \
+X 978302400:1500:1:2400:1500 \
+X 978302700:1800:2:1800:1800 \
+X 978303000:2100:4:0:2100 \
+X 978303300:2400:6:600:2400 \
+X 978303600:2700:4:600:2700 \
+X 978303900:3000:2:1200:3000
+X rrdtool graph all1.gif -s 978300600 -e 978304200 -h 400 \
+X DEF:linea=all.rrd:a:AVERAGE LINE3:linea#FF0000:"Line A" \
+X DEF:lineb=all.rrd:b:AVERAGE LINE3:lineb#00FF00:"Line B" \
+X DEF:linec=all.rrd:c:AVERAGE LINE3:linec#0000FF:"Line C" \
+X DEF:lined=all.rrd:d:AVERAGE LINE3:lined#000000:"Line D"
+X
+XWhat do we expect ?
+X - Line A is a counter so it should continuously increment and RRDtool
+X should calculate the differences. Also, RRDtool needs to divide the
+X difference by the amount of time lapsed. This should end up as a
+X straight line at 1 (the deltas are 300, the time is 300).
+X - Line B is of type gauge. These are "real" values so they should match
+X what we put in: a sort of a wave.
+X - Line C is derive. It should be a counter that can decrease. It does
+X so between 2400 and 0, with 1800 in-between.
+X - Line D is of type absolute. This is like counter but it works on
+X values without calculating the difference. The numbers are the same
+X and as you can see (hopefully) this has a different result.
+X
+XThis translates in the following values, starting at 23:10 and ending
+Xat 00:10 the next day (where U means unknown/unplotted):
+X
+X - Line A: u u 1 1 1 1 1 1 1 1 1 u
+X - Line B: u 1 3 5 3 1 2 4 6 4 2 u
+X - Line C: u u 2 2 2 0 -2 -6 -2 0 2 u
+X - Line D: u 1 2 3 4 5 6 7 8 9 10 u
+X
+XIf your GIF shows all this, you know you have typed the data correct,
+Xthe RRDtool executable is working properly, your viewer doesn't fool you
+Xand you successfully entered the year 2000 :)
+XYou could try the same example four times, each time with only one of
+Xthe lines.
+X
+XLet's go over the data again:
+X- Line A: 300,600,900 and so on. The counter delta is a constant 300 and
+X so it the time delta. A number divided by itself is always 1 (except
+X when dividing by zero which is undefined/illegal).
+X Why is it that the first point is unknown ? We do know what we put into
+X the database ? True ! But we didn't have a value to calculate the delta
+X from so we don't know where we started. It would be wrong to assume we
+X started at zero so we don't !
+X- Line B: There is nothing to calculate. The numbers are as is.
+X- Line C: Again, the start-out value is unknown. The same story is valid
+X like for line A. In this case the deltas are not constant so the line
+X is not. If we would put the same numbers in the database as we did for
+X line A, we would have gotten the same line. Unlike type counter, this
+X type can decrease and why there is a difference I hope to show you later
+X on.
+X- Line D: Here the device calculates the deltas. Therefore we DO know the
+X first delta and it is plotted. We had the same input as with line A but
+X the meaning of this input is different. Therefore the line is different.
+X In this case the deltas increase each time with 300. The time delta
+X stays at a constant 300 and therefore the division of the two gives
+X increasing results.
+X
+XThere are a few more basics to show. Some important options are still to
+Xbe covered and we haven't look at counter wraps yet. First the counter wrap:
+XIn our car we notice that our counter shows 999987. We travel 20 KM and
+Xthe counter should go to 1000007. Unfortunately, there are only six digits
+Xon our counter so it really shows 000007. If we would plot that on a type
+XDERIVE, it would mean that the counter was set back 999980 KM. It wasn't,
+Xand there has to be some protection for this. This protection is only
+Xavailable for type COUNTER which should be used for this kind of counter
+Xanyways. How does it work ? Type counter should never decrease and
+Xtherefore RRDtool must assume it wrapped if it does decrease !
+XIf the delta is negative, this can be compensated for by adding the
+Xmaximum value of the counter + 1. For our car this would be:
+X
+XDelta = 7 - 999987 = -999980 (instead of 1000007-999987=20)
+XReal delta = -999980 + 999999 + 1 = 20
+X
+XAt the moment of writing this document, RRDtool knows of counters that
+Xare either 32 bits or 64 bits of size. These counters can handle the
+Xfollowing different values:
+X - 32 bits: 0 .. 4294967295
+X - 64 bits: 0 .. 18446744073709551615
+XIf these numbers look strange to you, you would like to view them in
+Xtheir hexadecimal form:
+X - 32 bits: 0 .. FFFFFFFF
+X - 64 bits: 0 .. FFFFFFFFFFFFFFFF
+XRRDtool handles both counters the same. If an overflow would occur and
+Xthe delta would be negative, RRDtool first adds the maximum of a small
+Xcounter + 1 to the delta. If the delta is still negative, it had to be
+Xthe large counter that wrapped. Add the maximum possible value of the
+Xlarge counter + 1 and subtract the falsely added small value.
+XThere is a risk in this: suppose the large counter wrapped while adding
+Xa huge delta, it could happen in theory that adding the smaller value
+Xwould make the delta positive. In this unlikely case the results would
+Xnot be correct. The increase should be nearly as high as the maximum
+Xcounter value for that to happen so chances are you would have several
+Xother problems as well and this particular problem would not even be
+Xworth thinking about. Even though I did include an example of it so you
+Xcan judge that for yourself.
+X
+XThe next section gives you some numerical examples for counter-wraps.
+XTry to do the calculations yourself or just believe me if your calculator
+Xcan't handle the numbers :)
+X
+XCorrection numbers:
+X- 32 bits: (4294967295+1) = 4294967296
+X- 64 bits: (18446744073709551615+1)-correction1 = 18446744069414584320
+X
+XBefore: 4294967200
+XIncrease: 100
+XShould become: 4294967300
+XBut really is: 4
+XDelta: -4294967196
+XCorrection1: -4294967196 +4294967296 = 100
+X
+XBefore: 18446744073709551000
+XIncrease: 800
+XShould become: 18446744073709551800
+XBut really is: 184
+XDelta: -18446744073709550816
+XCorrection1: -18446744073709550816 +4294967296 = -18446744069414583520
+XCorrection2: -18446744069414583520 +18446744069414584320 = 800
+X
+XBefore: 18446744073709551615 ( maximum value )
+XIncrease: 18446744069414584320 ( absurd increase, minimum for
+XShould become: 36893488143124135935 this example to work )
+XBut really is: 18446744069414584319
+XDelta: -4294967296
+XCorrection1: -4294967296 + 4294967296 = 0
+X(not negative -> no correction2)
+X
+XBefore: 18446744073709551615 ( maximum value )
+XIncrease: 18446744069414584319 ( one less increase )
+XShould become: 36893488143124135934
+XBut really is: 18446744069414584318
+XDelta: -4294967297
+XCorrection1: -4294967297 +4294967296 = -1
+XCorrection2: -1 +18446744069414584320 = 18446744069414584319
+X
+X
+XAs you can see from the last two examples, you need strange numbers
+Xfor RRDtool to fail (provided it's bug free of course) so this should
+Xnot happen. However, SNMP or whatever method you choose to collect the
+Xdata might also fail and it is not uncommon to get wrong numbers
+Xoccasionally. We can't prevent all errors but there are some things we
+Xcould do. RRDtool create takes two special parameters for this. They define
+Xthe minimum and maximum allowed value. Until now, we made them "U"
+Xfrom Unknown. You may (not: must) provide values for one or both of them
+Xand if RRDtool receives values that are outside these limits, it will ignore
+Xthem. For a thermometer in degrees Celsius, the absolute minimum is
+Xjust under -273. For my router, I can assume this minimum is much higher
+Xso I would say it is 10. The maximum temperature for my router I would
+Xstate as 80. Any higher and the device would be out of order.
+XFor my car, I would never expect negative numbers and also I would not
+Xexpect numbers to be higher than 230. Anything else, and there must have
+Xbeen an error. Remember: the opposite is not true, if the numbers pass
+Xthis check it doesn't mean that they are correct. Always judge the
+Xgraph with a healthy doses of paranoia if it looks weird.
+X
+XOne important feature of RRDtool has not been explained yet:
+XIt is virtually impossible to collect the data and feed it into RRDtool
+Xon exact intervals. RRDtool therefore interpolates the data so it is on
+Xexact intervals. If you do not know what this means or how it works,
+Xthen here's the help you seek:
+X
+XSuppose a counter increases with exactly one for every second. You want
+Xto measure it in 300 seconds intervals. You should retrieve values
+Xthat are exactly 300 apart. However, due to various circumstances you
+Xare a few seconds late and the interval is 303. The delta will also be
+X303 in that case. Obviously RRDtool should not put 303 in the database
+Xand make you believe that the counter increased 303 in 300 seconds.
+XThis is where RRDtool interpolates: it alters the 303 value as if it
+Xwould have been stored earlier and it will be 300 in 300 seconds.
+XNext time you are at exactly the right time. This means that the current
+Xinterval is 297 seconds and also the counter increased with 297. Again
+XRRDtool alters the value and stores 300 as it should be.
+X
+X in the RDD in real
+X
+Xtime+000: 0 delta="U" time+000: 0 delta="U"
+Xtime+300: 300 delta=300 time+300: 300 delta=300
+Xtime+600: 600 delta=300 time+603: 603 delta=303
+Xtime+900: 900 delta=300 time+900: 900 delta=297
+X
+XLet's create two identical databases. I've chosen time 920805000
+Xto 920805900 as this goes very well with the example numbers.
+X
+X rrdtool create seconds1.rrd \
+X --start 920804700 \
+X DS:seconds:COUNTER:600:U:U \
+X RRA:AVERAGE:0.5:1:24
+X
+X for Unix: cp seconds1.rrd seconds2.rrd
+X for Dos: copy seconds1.rrd seconds2.rrd
+X for vms: how would I know :)
+X
+X rrdtool update seconds1.rrd \
+X 920805000:000 920805300:300 920805600:600 920805900:900
+X rrdtool update seconds2.rrd \
+X 920805000:000 920805300:300 920805603:603 920805900:900
+X
+X rrdtool graph seconds1.gif \
+X --start 920804700 --end 920806200 \
+X --height 200 \
+X --upper-limit 1.05 --lower-limit 0.95 --rigid \
+X DEF:seconds=seconds1.rrd:seconds:AVERAGE \
+X CDEF:unknown=seconds,UN \
+X LINE2:seconds#0000FF \
+X AREA:unknown#FF0000
+X rrdtool graph seconds2.gif \
+X --start 920804700 --end 920806200 \
+X --height 200 \
+X --upper-limit 1.05 --lower-limit 0.95 --rigid \
+X DEF:seconds=seconds2.rrd:seconds:AVERAGE \
+X CDEF:unknown=seconds,UN \
+X LINE2:seconds#0000FF \
+X AREA:unknown#FF0000
+X
+XBoth graphs should show the same.
+X
+X
+X
+XIt's time to wrap up this document. You now know all the basics to be
+Xable to work with RRDtool and to read the documentation available.
+XThere is plenty more to discover about RRDtool and you will find more and
+Xmore uses for the program. You could create easy graphics using just the
+Xexamples provided and using only RRDtool. You could also use the front
+Xends that are available.
+X
+XRemember to subscribe to the mailing-list. Even if you are not answering
+Xthe mails that come by, it helps both you and the rest. A lot of the stuff
+Xthat I know about MRTG (and therefore about RRDtool) I've learned while
+Xjust reading the list without posting to it. I did not need to ask the
+Xbasic questions as they are answered in the FAQ (so: read that too) and
+Xin various mails by other users.
+XWith thousands of users all over the world, there will always be people
+Xwho ask questions that you can answer because you read this and other
+Xdocumentation and they didn't.
+X
+XI hope you enjoyed the examples and their descriptions. If you do, help
+Xother people by pointing them to this document when they are asking
+Xbasic questions. They will not only get their answer but at the same
+Xtime learn a whole lot more.
+X
+XAlex van den Bogaerdt
+SHAR_EOF
+ : || $echo 'restore of' 'RRDbeginner' 'failed'
+fi
+# ============= binhex ==============
+if test -f 'binhex' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'binhex' '(file already exists)'
+else
+ $echo 'x -' extracting 'binhex' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'binhex' &&
+XMost people use the decimal numbering system. This system uses ten
+Xsymbols to represent numbers. When those ten symbols are used up, they
+Xstart all over again and increment the position just before this. The
+Xdigit 0 is only shown if it is the only symbol in the sequence, or if
+Xit is not the first one.
+XIf this sounds as crypto to you, this is what I've said in numbers:
+X 0
+X 1
+X 2
+X 3
+X 4
+X 5
+X 6
+X 7
+X 8
+X 9
+X 10
+X 11
+X 12
+X 13
+Xand so on.
+X
+XEach time the digit nine should be incremented, it is reset to 0 and the
+Xposition before is incremented. Then number 9 can be seen as "00009" and
+Xwhen we should increment 9, we reset it to zero and increment the digit
+Xjust before the 9 so the number becomes "00010". For zero's we write a
+Xspace if it is not the only digit (so: number 0) and if it is the first
+Xdigit: "00010" -> " 0010" -> " 010" -> " 10". It is not " 1 ".
+X
+XThis was pretty basic, you already knew this. Why did I tell it ?
+XWell, computers do not represent numbers with 10 different digits. They
+Xknow of only two different symbols, being 0 and 1. Apply the same rules
+Xto this set of digits and you get the binary numbering system:
+X 0
+X 1
+X 10
+X 11
+X 100
+X 101
+X 110
+X 111
+X 1000
+X 1001
+X 1010
+X 1011
+X 1100
+X 1101
+Xand so on.
+X
+XIf you count the number of rows, you'll see that these are again 14
+Xdifferent numbers. The numbers are the same and mean the same. It is
+Xonly a different representation. This means that you have to know the
+Xrepresentation used, or as it is called the numbering system or base.
+XNormally if we do not speak about the numbering system used, we're
+Xusing the decimal system. If we are talking about another numbering
+Xsystem, we'll have to make that clear. There are a few wide-spread
+Xmethods to do so. One common form is to write 1010(2) which means that
+Xyou wrote down a number in the binary form. It is the number ten.
+XIf you would write 1010 it means the number one thousand and ten.
+X
+XIn books, another form is most used. It uses subscript (little chars,
+Xmore or less in between two rows). You can leave out the parentheses
+Xin that case and write down the number in normal characters followed
+Xwith a little two just behind it.
+X
+XThe numbering system used is also called the base. We talk of the number
+X1100 base 2, the number 12 base 10.
+X
+XFor the binary system, is is common to write leading zero's. The numbers
+Xare written down in series of four, eight or sixteen depending on the
+Xcontext.
+X
+XWe can use the binary form when talking to computers (...programming...)
+Xbut the numbers will have large representations. The number 65535 would
+Xbe written down as 1111111111111111(2) which is 16 times the digit 1.
+XThis is difficult and prone to errors. Therefore we normally would use
+Xanother base, called hexadecimal. It uses 16 different symbols. First
+Xthe symbols from the decimal system are used, thereafter we continue
+Xwith the alfabetic characters. We get 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A,
+XB, C, D, E and F. This system is choosen because the hexadecimal form
+Xcan be converted into the binary system very easy (and back).
+X
+XThere is yet another system in use, called the octal system. This was
+Xmore common in the old days but not anymore. You will find it in use
+Xon some places so get used to it. The same story applies, but now with
+Xonly eight different symbols.
+X
+XBinary (2)
+XOctal (8)
+XDecimal (10)
+XHexadecimal (16)
+X
+X(2) (8) (10) (16)
+X00000 0 0 0
+X00001 1 1 1
+X00010 2 2 2
+X00011 3 3 3
+X00100 4 4 4
+X00101 5 5 5
+X00110 6 6 6
+X00111 7 7 7
+X01000 10 8 8
+X01001 11 9 9
+X01010 12 10 A
+X01011 13 11 B
+X01100 14 12 C
+X01101 15 13 D
+X01110 16 14 E
+X01111 17 15 F
+X10000 20 16 10
+X10001 21 17 11
+X10010 22 18 12
+X10011 23 19 13
+X10100 24 20 14
+X10101 25 21 15
+X
+XMost computers used nowadays are using bytes of eight bits. This means
+Xthat they store eight bits at a time. You can see why the octal system
+Xis not the most preferred for that: You'd need three digits to represent
+Xthe eight bits and this means that you'd have to use one complete digit
+Xto represent only two bits (2+3+3=8). This is a waste. For hexadecimal
+Xdigits, you need only two digits which are used completely:
+X
+X(2) (8) (10) (16)
+X11111111 377 255 FF
+X
+XYou can see why binary and hexadecimal can be converted quickly:
+XFor each hexadecimal digit there are exactly four binary digits.
+XTake a binary number. Each time take four digits from the right and make
+Xa hexadecimal digit from it (see the table above). Stop when there are
+Xno more digits.
+XOther way around: Take a hexadecimal number. For each digit, write down
+Xits binary equivalent.
+X
+XComputers (or rather the parsers running on them) would have a hard time
+Xconverting a number like 1234(16). Therefore hexadecimal numbers get a
+Xprefix. This prefix depends on the language you're writing in. Some of
+Xthe prefixes are "0x" for C, "$" for pascal, "#" for HTML.
+XIt is common to assume that if a number starts with a zero, it is octal.
+XIt does not matter what is used as long as you know what it is.
+XI will use "0x" for hexadecimal, "%" for binary and "0" for octal.
+XThe following numbers are all the same, just the way they are written is
+Xdifferent: 021 0x11 17 %00010001
+X
+XTo do arithmetics and conversions you need to understand one more thing.
+XIt is something you already know but perhaps you do not "see" it yet:
+X
+XIf you write down 1234, (so it is decimal) you are talking about the
+Xnumber one thousand, two hundred and thirty four. In sort of a formula:
+X
+X1 * 1000 = 1000
+X2 * 100 = 200
+X3 * 10 = 30
+X4 * 1 = 4
+X
+XThis can also be written as:
+X1 * 10^3
+X2 * 10^2
+X3 * 10^1
+X4 * 10^0
+Xwhere ^ means "to the power of".
+X
+XWe are using the base 10, and the positions 0,1,2 and 3.
+XThe right-most position should NOT be multiplied with 10. The second
+Xfrom the right should be multiplied one time with 10. The third from
+Xthe right is multiplied with 10 two times. This continues for whatever
+Xpositions are used.
+X
+XIt is the same in all other representations:
+X
+X0x1234 will be
+X1 * 16^3
+X2 * 16^2
+X3 * 16^1
+X4 * 16^0
+X
+X01234 would be
+X1 * 8^3
+X2 * 8^2
+X3 * 8^1
+X4 * 8^0
+X
+XThis example can not be done for binary as that system can only use two
+Xsymbols. Another example:
+X
+X%1010 would be
+X1 * 2^3
+X0 * 2^2
+X1 * 2^1
+X0 * 2^0
+XIt would have been more easy to convert it to its hexadecimal form and
+Xjust translate %1010 into 0xA. After a while you get used to it. You will
+Xnot need to do any calculations anymore but just know that 0xA means 10.
+X
+XTo convert a decimal number into a hexadecimal one you could use the next
+Xmethod. It will take some time to be able to do the estimates but it will
+Xbe more and more easy when you use the system more frequent. Another way
+Xis presented to you thereafter.
+X
+XFirst you will need to know how many positions will be used in the other
+Xsystem. To do so, you need to know the maximum numbers. Well, that's not
+Xso hard as it looks. In decimal, the maximum number that you can form
+Xwith two digits is "99". The maximum for three: "999". The next number
+Xwould need an extra position. Reverse this idea and you will see that
+Xthe number can be found by taking 10^3 (10*10*10 is 1000) minus 1 or
+X10^2 minus one.
+X
+XThis can be done for hexadecimal too:
+X16^4 = 0x10000 = 65536
+X16^3 = 0x1000 = 4096
+X16^2 = 0x100 = 256
+X16^1 = 0x10 = 16
+X
+XIf a number is smaller than 65536 it will thus fit in four positions.
+XIf the number is bigger than 4095, you will need to use position 4.
+XHow many times can you take 4096 from the number without going below
+Xzero is the first digit you write down. This will always be a number
+Xfrom 1 to 15 (0x1 to 0xF). Do the same for the other positions.
+X
+XNumber is 41029. It is smaller than 16^4 but bigger than 16^3-1. This
+Xmeans that we have to use four positions.
+XWe can subtract 16^3 from 41029 ten times without going below zero.
+XThe leftmost digit will be "A" so we have 0xA????.
+XThe number is reduced to 41029 - 10*4096 = 41029-40960 = 69.
+X69 is smaller than 16^3 but not bigger than 16^2-1. The second digit
+Xis therefore "0" and we know 0xA0??.
+X69 is smaller than 16^2 and bigger than 16^1-1. We can subtract 16^1
+X(which is just plain 16) four times and write down "4" to get 0xA04?.
+XTake 64 from 69 (69 - 4*16) and the last digit is 5 --> 0xA045.
+X
+XThe other method builds the number from the right. Take again 41029.
+XDivide by 16 and do not use fractions (only whole numbers).
+X41029 / 16 is 2564 with a remainder of 5. Write down 5.
+X2564 / 16 is 160 with a remainder of 4. Write the 4 before the 5.
+X160 / 16 is 10 with no remainder. Prepend 45 with 0.
+X10 / 16 is below one. End here and prepend 0xA. End up with 0xA045.
+X
+XWhich method to use is up to you. Use whatever works for you. Personally
+XI use them both without being able to tell what method I use in each
+Xcase, it just depends on the number, I think. Fact is, some numbers
+Xwill occur frequently while programming, if the number is close then
+XI will use the first method (like 32770, translate into 32768 + 2 and
+Xjust know that it is 0x8000 + 0x2 = 0x8002).
+X
+X
+XFor binary the same approach can be used. The base is 2 and not 16,
+Xand the number of positions will grow rapidly. Using the second method
+Xhas the advantage that you can see very simple if you should write down
+Xa zero or a one: if you divide by two the remainder will be zero if it
+Xwas an even number and one if it was an odd number:
+X41029 / 2 = 20514 remainder 1
+X20514 / 2 = 10257 remainder 0
+X10257 / 2 = 5128 remainder 1
+X 5128 / 2 = 2564 remainder 0
+X 2564 / 2 = 1282 remainder 0
+X 1282 / 2 = 641 remainder 0
+X 641 / 2 = 320 remainder 1
+X 320 / 2 = 160 remainder 0
+X 160 / 2 = 80 remainder 0
+X 80 / 2 = 40 remainder 0
+X 40 / 2 = 20 remainder 0
+X 20 / 2 = 10 remainder 0
+X 10 / 2 = 5 remainder 0
+X 5 / 2 = 2 remainder 1
+X 2 / 2 = 1 remainder 0
+X 1 / 2 below 0 remainder 1
+XWrite down the results from right to left: %1010000001000101
+XGroup by four:
+X%1010000001000101
+X%101000000100 0101
+X%10100000 0100 0101
+X%1010 0000 0100 0101
+XConvert into hexadecimal: 0xA045
+XGroup %1010000001000101 by three and convert into octal:
+X%1010000001000101
+X%1010000001000 101
+X%1010000001 000 101
+X%1010000 001 000 101
+X%1010 000 001 000 101
+X%1 010 000 001 000 101
+X%001 010 000 001 000 101
+X 1 2 0 1 0 5 --> 0120105
+X
+XSo: %1010000001000101 = 0120105 = 0xA045 = 41029
+XOr: 1010000001000101(2) = 120105(8) = A045(16) = 41029(10)
+XOr: 1010000001000101(2) = 120105(8) = A045(16) = 41029
+X
+X
+XAt first while adding numbers, you'll convert them to their decimal
+Xform and then back into their original form after doing the addition.
+XIf you use the other numbering system often, you will see that you'll
+Xbe able to do arithmetics in the base that is used.
+XIn any representation it is the same, add the numbers on the right,
+Xwrite down the rightmost digit from the result, remember the other
+Xdigits and use them in the next round. Continue with the second digits
+Xfrom the right and so on:
+X
+X %1010 + %0111 --> 10 + 7 --> 17 --> %00010001
+Xwill become
+X %1010
+X %0111 +
+X ||||
+X |||+-- add 0 + 1, result is 1, nothing to remember
+X ||+--- add 1 + 1, result is %10, write down 0 and remember 1
+X |+---- add 0 + 1 + 1(remembered), result = 0, remember 1
+X +----- add 1 + 0 + 1(remembered), result = 0, remember 1
+X nothing to add, 1 remembered, result = 1
+X----------
+X %10001 is the result, I like to write it as %00010001
+X
+XFor low values, try to do the calculations yourself, check them with
+Xa calculator. The more you do the calculations yourself, the more you
+Xfind that you didn't make mistakes. In the end, you'll do calcula in
+Xother bases as easy as you do in decimal.
+X
+XWhen the numbers get bigger, you'll have to realise that a computer is
+Xnot called a computer just to have a nice name. There are many different
+Xcalculators available. Use them. For unix you could use "bc" which is
+Xcalled so as it is short for Binary Calculator. It calculates not only
+Xin decimal, but in all bases you'll ever use (among them Binary).
+X
+XFor people on Windows:
+XStart the calculator (start->programs->accessories->calculator)
+Xand if necessary click view->scientific. You now have a scientific
+Xcalculator and can compute in binary or hexadecimal.
+SHAR_EOF
+ : || $echo 'restore of' 'binhex' 'failed'
+fi
+rm -fr _sh06095
+exit 0
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.html Sat Jul 13 18:46:07 2002
@@ -0,0 +1,159 @@
+ <HTML>
+ <HEAD>
+ <TITLE>tune - Modify some basic properties of a Round Robin Database
+
+</TITLE>
+ </HEAD>
+
+ <BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+ <LI><A HREF="#NAME">NAME</A>
+ <LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+ <LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+ <LI><A HREF="#EXAMPLE">EXAMPLE</A>
+ <LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME
+
+</A></H1>
+rrdtool tune - Modify some basic properties of a Round Robin Database
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS
+
+</A></H1>
+<STRONG>rrdtool</STRONG> <STRONG>tune</STRONG> <EM>filename</EM>
+
+[<STRONG>--heartbeat</STRONG>|<STRONG>-h</STRONG> <EM>ds-name</EM>:<EM>heartbeat</EM>]
+
+[<STRONG>--minimum</STRONG>|<STRONG>-i</STRONG> <EM>ds-name</EM>:<EM>min</EM>]
+
+[<STRONG>--maximum</STRONG>|<STRONG>-a</STRONG> <EM>ds-name</EM>:<EM>max</EM>]
+
+[<STRONG>--data-source-type</STRONG>|<STRONG>-d</STRONG> <EM>ds-name</EM>:<EM>DST</EM>]
+
+[<STRONG>--data-source-rename</STRONG>|<STRONG>-r</STRONG> <EM>old-name</EM>:<EM>new-name</EM>]
+
+
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION
+
+</A></H1>
+The tune option allows you to alter some of the basic configuration values
+stored in the header area of a Round Robin Database (<STRONG>RRD</STRONG>). All these tunable parameters together decide when data fed into an
+<STRONG>RRD</STRONG> is to be regarded as invalid. Invalid data is entered into the database as
+*UNKNOWN*.
+
+
+<P>
+
+The main application of the <STRONG>tune</STRONG> function is to relax the validation rules on an <STRONG>RRD</STRONG>. This allows to fill a new <STRONG>RRD</STRONG> with data available in larger intervals than what you would normally want
+to permit.
+
+
+<P>
+
+<DL>
+<DT><STRONG><A NAME="item_filename">filename
+
+</A></STRONG><DD>
+The name of the <STRONG>RRD</STRONG> you want to tune.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__heartbeat_h">--heartbeat|-h ds-name:heartbeat
+
+</A></STRONG><DD>
+modify the <EM>heartbeat</EM> of a data source. By setting this to a high value the rrd will accept
+things like one value per day ...
+
+
+<P>
+
+<DT><STRONG><A NAME="item__minimum_i">--minimum|-i ds-name:min
+
+</A></STRONG><DD>
+alter the minimum value acceptable as input from the data source. Setting <EM>min</EM> to 'U' will disable this limit.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__maximum_a">--maximum|-a ds-name:max
+
+</A></STRONG><DD>
+alter the maximum value acceptable as input from the data source. Setting <EM>max</EM> to 'U' will disable this limit.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__data_source_type_d">--data-source-type|-d ds-name:DST
+
+</A></STRONG><DD>
+alter the type <STRONG>DST</STRONG> of a data source.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__data_source_rename_r">[--data-source-rename|-r old-name:new-name]
+
+</A></STRONG><DD>
+rename a data source
+
+
+<P>
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="EXAMPLE">EXAMPLE
+
+</A></H1>
+<CODE>rrdtool tune data.rrd -h in:100000 -h in:100000 -h in:100000</CODE>
+
+
+
+
+<P>
+
+Set the minimum required heartbeat for data sources 'in', 'out' and
+'through' to 10000 seconds which is a little over one day in data.rrd. This
+would allow to feed old data from mrtg-2.0 right into rrdtool without
+generating *UNKNOWN* entries.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR
+
+</A></H1>
+Tobias Oetiker <A
+HREF="MAILTO:<oetiker at ee.ethz.ch>"><oetiker at ee.ethz.ch></A>
+
+
+<P>
+
+</DL>
+ </BODY>
+
+ </HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.1
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.1 (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.1 Sat Jul 13 18:46:07 2002
@@ -0,0 +1,263 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+''' \*(L" and \*(R", except that they are used on ".xx" lines,
+''' such as .IP and .SH, which do another additional levels of
+''' double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH RRDUPDATE 1 "19990426.22" "7/Mar/99" "rrdtool"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+rrdtool update \- Store a new set of values into the rrd
+.SH "SYNOPSIS"
+\fBrrdtool\fR \fBupdate\fR \fIfilename\fR
+[\fB--template\fR|\fB\-t\fR\ \fIds-name\fR[\fB:\fR\fIds-name\fR]...]
+\fBN\fR|\fItimestamp\fR\fB:\fR\fIvalue\fR[\fB:\fR\fIvalue\fR...]
+[\fItimestamp\fR\fB:\fR\fIvalue\fR[\fB:\fR\fIvalue\fR...]\ ...]
+.SH "DESCRIPTION"
+The \fBupdate\fR function feeds new data values into an \fBRRD\fR. The
+data gets time aligned according to the properties of the \fBRRD\fR to
+which the data is written.
+.Ip "\fIfilename\fR" 8
+The name of the \fB\s-1RRD\s0\fR you want to update.
+.Ip "\fB--template\fR|\fB\-t\fR \fIds-name\fR[\fB:\fR\fIds-name\fR]..." 8
+by default, the update function expects the data input in the order,
+the data sources are defined in the \s-1RRD\s0. This is not very error
+resistant, as you might be sending the wrong data into a \s-1RRD\s0.
+.Sp
+The template switch alows you to specify which data sources you are
+going to update and in which order. If the datasources specified in
+the template are not available in the rrd file, the update process
+will abort with an error message.
+.Ip "\fBN\fR|\fItimestamp\fR\fB:\fR\fIvalue\fR[\fB:\fR\fIvalue\fR...]" 8
+The data used for updating the \s-1RRD\s0 was acquired at a certain time. This
+time can either be defined in seconds since 1970-01-01. Or by using the
+letter \*(L'N\*(R' the update time is set to be the current time. Negative time
+values are subtracted from the current time.
+Getting the timing right to the second is especially
+important when you are working with data-sources of type \fB\s-1COUNTER\s0\fR,
+\fB\s-1DERIVE\s0\fR or \fB\s-1ABSOLUTE\s0\fR.
+.Sp
+The remaining elements of the argument are \s-1DS\s0 updates. The order of this list is
+the same as the order the datasources were defined in the rra.
+If there is no data for a certain data-source, the letter
+\fBU\fR (eg. N:0.1:U:1) can be defined.
+.Sp
+The format of the value acquired from the datasource is dependent of the
+datasource type chosen. Normally it will be numeric, but the data acquisition
+modules my impose their very own parsing of this parameter as long as the colon
+(\fB:\fR) remains the datasource value separator.
+.SH "EXAMPLE"
+\f(CWrrdtool update demo1.rrd N:3.44:3.15:U:23\fR
+.PP
+Update the database file demo1.rrd with 3 known and one \fI*UNKNOWN*\fR
+value. Use the current time as the update time.
+.PP
+\f(CWrrdtool update demo2.rrd 887457267:U 887457521:22 88745790:2.7\fR
+.PP
+Update the database file demo2.rrd which expects data from a single
+data-source, three times. First with an \fI*UNKNOWN*\fR value then with two
+normal readings. The update interval seems to be around 300 seconds.
+.SH "AUTHOR"
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
+.rn }` ''
+.IX Title "RRDUPDATE 1"
+.IX Name "rrdtool update - Store a new set of values into the rrd"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Item "\fIfilename\fR"
+
+.IX Item "\fB--template\fR|\fB\-t\fR \fIds-name\fR[\fB:\fR\fIds-name\fR]..."
+
+.IX Item "\fBN\fR|\fItimestamp\fR\fB:\fR\fIvalue\fR[\fB:\fR\fIvalue\fR...]"
+
+.IX Header "EXAMPLE"
+
+.IX Header "AUTHOR"
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.txt
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.txt (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.txt Sat Jul 13 18:46:07 2002
@@ -0,0 +1,198 @@
+
+
+
+RRDCREATE(1) rrdtool RRDCREATE(1)
+
+
+NNNNAAAAMMMMEEEE
+ rrdtool create - Set up a new Round Robin Database
+
+SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
+ rrrrrrrrddddttttoooooooollll ccccrrrreeeeaaaatttteeee _f_i_l_e_n_a_m_e [--------ssssttttaaaarrrrtttt|----bbbb _s_t_a_r_t _t_i_m_e]
+ [--------sssstttteeeepppp|----ssss _s_t_e_p] [DDDDSSSS::::_d_s_-_n_a_m_e::::_D_S_T::::_h_e_a_r_t_b_e_a_t::::_m_i_n::::_m_a_x]
+ [RRRRRRRRAAAA::::_C_F::::_x_f_f::::_s_t_e_p_s::::_r_o_w_s]
+
+DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
+ The create function of the rrd tool lets you set up new
+ Round Robin Database (RRRRRRRRDDDD) files. The file is created at
+ its final, full size and filled with _*_U_N_K_N_O_W_N_* data.
+
+ _f_i_l_e_n_a_m_e
+ The name of the RRRRRRRRDDDD you want to create. RRRRRRRRDDDD files
+ should end with the extension _._r_r_d. However,
+ rrrrrrrrddddttttoooooooollll will accept any filename.
+
+ --------ssssttttaaaarrrrtttt|----bbbb _s_t_a_r_t _t_i_m_e (default: current time)
+ Specifies the time in seconds since 1970-01-01 UTC
+ when the first value should be added to the RRRRRRRRDDDD.
+ rrrrrrrrddddttttoooooooollll will not accept any data timed before or
+ at the time specified.
+
+ Negative input is treated as current time minus
+ the specified number of seconds. See also AT-STYLE
+ TIME SPECIFICATION section in the _r_r_d_f_e_t_c_h
+ documentation for alternative ways to specify
+ time.
+
+ --------sssstttteeeepppp|----ssss _s_t_e_p (default: 300 seconds)
+ Specifies the base interval in seconds with which
+ data will be fed into the RRRRRRRRDDDD.
+
+ DDDDSSSS::::_d_s_-_n_a_m_e::::_D_S_T::::_h_e_a_r_t_b_e_a_t::::_m_i_n::::_m_a_x
+ A single RRRRRRRRDDDD can accept input from several data
+ sources (DDDDSSSS). (e.g. Incoming and Outgoing traffic
+ on a specific communication line). With the DDDDSSSS
+ configuration option you must define some basic
+ properties of each data source you want to use to
+ feed the RRRRRRRRDDDD.
+
+ _d_s_-_n_a_m_e is the name you will use to reference this
+ particular data source from an RRRRRRRRDDDD. A _d_s_-_n_a_m_e must
+ be 1 to 19 characters long in the characters [a-
+ zA-Z0-9_].
+
+ _D_S_T defines the Data Source Type. It can be one of
+ the following: GGGGAAAAUUUUGGGGEEEE this is for things like
+ temperatures or number of people in a room.
+ CCCCOOOOUUUUNNNNTTTTEEEERRRR is for continuous incrementing counters
+ like the InOctets counter in a router. The CCCCOOOOUUUUNNNNTTTTEEEERRRR
+ data source assumes that the counter never
+ decreases, except when a counter overflows. The
+
+
+
+21/Apr/99 19990426.22 1
+
+
+
+
+
+RRDCREATE(1) rrdtool RRDCREATE(1)
+
+
+ update function takes the overflow into account.
+ The counter is stored as a per-second rate. DDDDEEEERRRRIIIIVVVVEEEE
+ will store the the derivative of the line going
+ from the last to the current value of the data
+ source. This can be useful for gauges, for
+ example, to measure the rate of people entering or
+ leaving a room. AAAABBBBSSSSOOOOLLLLUUUUTTTTEEEE is for counters which get
+ reset upon reading.
+
+ _h_e_a_r_t_b_e_a_t defines the maximum number of seconds
+ that may pass between two updates of this data
+ source before the value of the data source is
+ assumed to be _*_U_N_K_N_O_W_N_*.
+
+ _m_i_n and _m_a_x are optional entries defining the
+ expected range of the data supplied by this data
+ source. If _m_i_n and/or _m_a_x are defined, any value
+ outside the defined range will be regarded as
+ _*_U_N_K_N_O_W_N_*. If you do not know or care about min
+ and max, set them to U for unknown. Note that min
+ and max always refere to the processed values of
+ the DS. For a traffic-CCCCOOOOUUUUNNNNTTTTEEEERRRR type DS this would
+ be the max and min data-rate expected from the
+ device.
+
+ RRRRRRRRAAAA::::_C_F::::_x_f_f::::_s_t_e_p_s::::_r_o_w_s
+ The purpose of an RRRRRRRRDDDD is to store data in the
+ round robin archives (RRRRRRRRAAAA). An archive consists of
+ a number of data values from all the defined data-
+ sources (DDDDSSSS) and is defined with an RRRRRRRRAAAA line.
+
+ When data is entered into an RRRRRRRRDDDD, it is first fit
+ into time slots of the length defined with the ----ssss
+ option becoming a _p_r_i_m_a_r_y _d_a_t_a _p_o_i_n_t.
+
+ The data is also consolidated with the
+ consolidation function (_C_F) of the archive. The
+ following consolidation functions are defined:
+ AAAAVVVVEEEERRRRAAAAGGGGEEEE, MMMMIIIINNNN, MMMMAAAAXXXX, LLLLAAAASSSSTTTT.
+
+ _x_f_f The xfiles factor defines what part of a
+ consolidation interval may be made up from
+ _*_U_N_K_N_O_W_N_* data while the consolidated value is
+ sill regarded as known.
+
+ _s_t_e_p_s defines how many of these _p_r_i_m_a_r_y _d_a_t_a
+ _p_o_i_n_t_s are used to build a _c_o_n_s_o_l_i_d_a_t_e_d _d_a_t_a _p_o_i_n_t
+ which then goes into the archive.
+
+ _r_o_w_s defines how many generations of data values
+ are kept in an RRRRRRRRAAAA.
+
+EEEEXXXXAAAAMMMMPPPPLLLLEEEE
+ rrdtool create temperature.rrd --step 300
+
+
+
+21/Apr/99 19990426.22 2
+
+
+
+
+
+RRDCREATE(1) rrdtool RRDCREATE(1)
+
+
+ DS:temp:GAUGE:600:-273:5000 RRA:AVERAGE:0.5:1:1200
+ RRA:MIN:0.5:12:2400 RRA:MAX:0.5:12:2400
+ RRA:AVERAGE:0.5:12:2400
+
+ This sets up an RRRRRRRRDDDD called _t_e_m_p_e_r_a_t_u_r_e_._r_r_d which accepts
+ one temperature value every 300 seconds. If no new data is
+ supplied for more than 600 seconds, the temperature
+ becomes _*_U_N_K_N_O_W_N_*. The minimum acceptable value is -273
+ and the maximum is 5000.
+
+ A few archives areas are also defined. The first stores
+ the temperatures supplied for 100 hours (1200 * 300
+ seconds = 100 hours). The second RRA stores the minimum
+ temperature recorded over every hour (12 * 300 seconds = 1
+ hour), for 100 days (2400 hours). The third and the fourth
+ RRA's do the same with the for the maximum and average
+ temperature, respectively.
+
+AAAAUUUUTTTTHHHHOOOORRRR
+ Tobias Oetiker <oetiker at ee.ethz.ch>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+21/Apr/99 19990426.22 3
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.html Sat Jul 13 18:46:07 2002
@@ -0,0 +1,569 @@
+ <HTML>
+ <HEAD>
+ <TITLE>Hexadecimal - How does it wok
+
+</TITLE>
+ </HEAD>
+
+ <BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+ <LI><A HREF="#NAME">NAME</A>
+ <LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+ <LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME
+
+</A></H1>
+Binary Decimal Hexadecimal - How does it wok
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION
+
+</A></H1>
+Most people use the decimal numbering system. This system uses ten symbols
+to represent numbers. When those ten symbols are used up, they start all
+over again and increment the position just before this. The digit 0 is only
+shown if it is the only symbol in the sequence, or if it is not the first
+one.
+
+
+<P>
+
+If this sounds as crypto to you, this is what I've said in numbers:
+
+
+<P>
+
+<PRE> 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+</PRE>
+
+<P>
+
+and so on.
+
+
+<P>
+
+Each time the digit nine should be incremented, it is reset to 0 and the
+position before is incremented. Then number 9 can be seen as ``00009'' and
+when we should increment 9, we reset it to zero and increment the digit
+just before the 9 so the number becomes ``00010''. For zero's we write a
+space if it is not the only digit (so: number 0) and if it is the first
+digit: ``00010'' -> `` 0010'' -> `` 010'' -> `` 10''. It is not ``
+1 ''.
+
+
+<P>
+
+This was pretty basic, you already knew this. Why did I tell it ? Well,
+computers do not represent numbers with 10 different digits. They know of
+only two different symbols, being 0 and 1. Apply the same rules to this set
+of digits and you get the binary numbering system:
+
+
+<P>
+
+<PRE> 0
+ 1
+ 10
+ 11
+ 100
+ 101
+ 110
+ 111
+ 1000
+ 1001
+ 1010
+ 1011
+ 1100
+ 1101
+</PRE>
+
+<P>
+
+and so on.
+
+
+<P>
+
+If you count the number of rows, you'll see that these are again 14
+different numbers. The numbers are the same and mean the same. It is only a
+different representation. This means that you have to know the
+representation used, or as it is called the numbering system or base.
+Normally if we do not speak about the numbering system used, we're using
+the decimal system. If we are talking about another numbering system, we'll
+have to make that clear. There are a few wide-spread methods to do so. One
+common form is to write <CODE>1010(2)</CODE> which means that you wrote
+down a number in the binary form. It is the number ten. If you would write
+1010 it means the number one thousand and ten.
+
+
+<P>
+
+In books, another form is most used. It uses subscript (little chars, more
+or less in between two rows). You can leave out the parentheses in that
+case and write down the number in normal characters followed with a little
+two just behind it.
+
+
+<P>
+
+The numbering system used is also called the base. We talk of the number
+1100 base 2, the number 12 base 10.
+
+
+<P>
+
+For the binary system, is is common to write leading zero's. The numbers
+are written down in series of four, eight or sixteen depending on the
+context.
+
+
+<P>
+
+We can use the binary form when talking to computers (...programming...)
+but the numbers will have large representations. The number 65535 would be
+written down as <CODE>1111111111111111(2)</CODE> which is 16 times the
+digit 1. This is difficult and prone to errors. Therefore we normally would
+use another base, called hexadecimal. It uses 16 different symbols. First
+the symbols from the decimal system are used, thereafter we continue with
+the alfabetic characters. We get 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D,
+E and F. This system is choosen because the hexadecimal form can be
+converted into the binary system very easy (and back).
+
+
+<P>
+
+There is yet another system in use, called the octal system. This was more
+common in the old days but not anymore. You will find it in use on some
+places so get used to it. The same story applies, but now with only eight
+different symbols.
+
+
+<P>
+
+<PRE> Binary (2)
+ Octal (8)
+ Decimal (10)
+ Hexadecimal (16)
+</PRE>
+
+<P>
+
+<PRE> (2) (8) (10) (16)
+ 00000 0 0 0
+ 00001 1 1 1
+ 00010 2 2 2
+ 00011 3 3 3
+ 00100 4 4 4
+ 00101 5 5 5
+ 00110 6 6 6
+ 00111 7 7 7
+ 01000 10 8 8
+ 01001 11 9 9
+ 01010 12 10 A
+ 01011 13 11 B
+ 01100 14 12 C
+ 01101 15 13 D
+ 01110 16 14 E
+ 01111 17 15 F
+ 10000 20 16 10
+ 10001 21 17 11
+ 10010 22 18 12
+ 10011 23 19 13
+ 10100 24 20 14
+ 10101 25 21 15
+</PRE>
+
+<P>
+
+Most computers used nowadays are using bytes of eight bits. This means that
+they store eight bits at a time. You can see why the octal system is not
+the most preferred for that: You'd need three digits to represent the eight
+bits and this means that you'd have to use one complete digit to represent
+only two bits (2+3+3=8). This is a waste. For hexadecimal digits, you need
+only two digits which are used completely:
+
+
+<P>
+
+<PRE> (2) (8) (10) (16)
+ 11111111 377 255 FF
+</PRE>
+
+<P>
+
+You can see why binary and hexadecimal can be converted quickly: For each
+hexadecimal digit there are exactly four binary digits. Take a binary
+number. Each time take four digits from the right and make a hexadecimal
+digit from it (see the table above). Stop when there are no more digits.
+Other way around: Take a hexadecimal number. For each digit, write down its
+binary equivalent.
+
+
+<P>
+
+Computers (or rather the parsers running on them) would have a hard time
+converting a number like <CODE>1234(16).</CODE> Therefore hexadecimal
+numbers get a prefix. This prefix depends on the language you're writing
+in. Some of the prefixes are ``0x'' for C, ``$'' for pascal, ``#'' for
+HTML. It is common to assume that if a number starts with a zero, it is
+octal. It does not matter what is used as long as you know what it is. I
+will use ``0x'' for hexadecimal, ``%'' for binary and ``0'' for octal. The
+following numbers are all the same, just the way they are written is
+different: 021 0x11 17 <CODE>%00010001</CODE>
+
+
+<P>
+
+To do arithmetics and conversions you need to understand one more thing. It
+is something you already know but perhaps you do not ``see'' it yet:
+
+
+<P>
+
+If you write down 1234, (so it is decimal) you are talking about the number
+one thousand, two hundred and thirty four. In sort of a formula:
+
+
+<P>
+
+<PRE> 1 * 1000 = 1000
+ 2 * 100 = 200
+ 3 * 10 = 30
+ 4 * 1 = 4
+</PRE>
+
+<P>
+
+This can also be written as:
+
+
+<P>
+
+<PRE> 1 * 10^3
+ 2 * 10^2
+ 3 * 10^1
+ 4 * 10^0
+</PRE>
+
+<P>
+
+where ^ means ``to the power of''.
+
+
+<P>
+
+We are using the base 10, and the positions 0,1,2 and 3. The right-most
+position should NOT be multiplied with 10. The second from the right should
+be multiplied one time with 10. The third from the right is multiplied with
+10 two times. This continues for whatever positions are used.
+
+
+<P>
+
+It is the same in all other representations:
+
+
+<P>
+
+0x1234 will be
+
+
+<P>
+
+<PRE> 1 * 16^3
+ 2 * 16^2
+ 3 * 16^1
+ 4 * 16^0
+</PRE>
+
+<P>
+
+01234 would be
+
+
+<P>
+
+<PRE> 1 * 8^3
+ 2 * 8^2
+ 3 * 8^1
+ 4 * 8^0
+</PRE>
+
+<P>
+
+This example can not be done for binary as that system can only use two
+symbols. Another example:
+
+
+<P>
+
+<CODE>%1010</CODE> would be
+
+
+<P>
+
+<PRE> 1 * 2^3
+ 0 * 2^2
+ 1 * 2^1
+ 0 * 2^0
+</PRE>
+
+<P>
+
+It would have been more easy to convert it to its hexadecimal form and just
+translate <CODE>%1010</CODE> into 0xA. After a while you get used to it.
+You will not need to do any calculations anymore but just know that 0xA
+means 10.
+
+
+<P>
+
+To convert a decimal number into a hexadecimal one you could use the next
+method. It will take some time to be able to do the estimates but it will
+be more and more easy when you use the system more frequent. Another way is
+presented to you thereafter.
+
+
+<P>
+
+First you will need to know how many positions will be used in the other
+system. To do so, you need to know the maximum numbers. Well, that's not so
+hard as it looks. In decimal, the maximum number that you can form with two
+digits is ``99''. The maximum for three: ``999''. The next number would
+need an extra position. Reverse this idea and you will see that the number
+can be found by taking 10^3 (10*10*10 is 1000) minus 1 or 10^2 minus one.
+
+
+<P>
+
+This can be done for hexadecimal too:
+
+
+<P>
+
+<PRE> 16^4 = 0x10000 = 65536
+ 16^3 = 0x1000 = 4096
+ 16^2 = 0x100 = 256
+ 16^1 = 0x10 = 16
+</PRE>
+
+<P>
+
+If a number is smaller than 65536 it will thus fit in four positions. If
+the number is bigger than 4095, you will need to use position 4. How many
+times can you take 4096 from the number without going below zero is the
+first digit you write down. This will always be a number from 1 to 15 (0x1
+to 0xF). Do the same for the other positions.
+
+
+<P>
+
+Number is 41029. It is smaller than 16^4 but bigger than 16^3-1. This means
+that we have to use four positions. We can subtract 16^3 from 41029 ten
+times without going below zero. The leftmost digit will be ``A'' so we have
+0xA????. The number is reduced to 41029 - 10*4096 = 41029-40960 = 69. 69 is
+smaller than 16^3 but not bigger than 16^2-1. The second digit is therefore
+``0'' and we know 0xA0??. 69 is smaller than 16^2 and bigger than 16^1-1.
+We can subtract 16^1 (which is just plain 16) four times and write down
+``4'' to get 0xA04?. Take 64 from 69 (69 - 4*16) and the last digit is 5
+--> 0xA045.
+
+
+<P>
+
+The other method builds the number from the right. Take again 41029. Divide
+by 16 and do not use fractions (only whole numbers).
+
+
+<P>
+
+<PRE> 41029 / 16 is 2564 with a remainder of 5. Write down 5.
+ 2564 / 16 is 160 with a remainder of 4. Write the 4 before the 5.
+ 160 / 16 is 10 with no remainder. Prepend 45 with 0.
+ 10 / 16 is below one. End here and prepend 0xA. End up with 0xA045.
+</PRE>
+
+<P>
+
+Which method to use is up to you. Use whatever works for you. Personally I
+use them both without being able to tell what method I use in each case, it
+just depends on the number, I think. Fact is, some numbers will occur
+frequently while programming, if the number is close then I will use the
+first method (like 32770, translate into 32768 + 2 and just know that it is
+0x8000 + 0x2 = 0x8002).
+
+
+<P>
+
+For binary the same approach can be used. The base is 2 and not 16, and the
+number of positions will grow rapidly. Using the second method has the
+advantage that you can see very simple if you should write down a zero or a
+one: if you divide by two the remainder will be zero if it was an even
+number and one if it was an odd number: 41029 / 2 = 20514 remainder 1 20514
+/ 2 = 10257 remainder 0 10257 / 2 = 5128 remainder 1 5128 / 2 = 2564
+remainder 0 2564 / 2 = 1282 remainder 0 1282 / 2 = 641 remainder 0 641 / 2
+= 320 remainder 1 320 / 2 = 160 remainder 0 160 / 2 = 80 remainder 0 80 / 2
+= 40 remainder 0 40 / 2 = 20 remainder 0 20 / 2 = 10 remainder 0 10 / 2 = 5
+remainder 0 5 / 2 = 2 remainder 1 2 / 2 = 1 remainder 0 1 / 2 below 0
+remainder 1
+
+
+<P>
+
+Write down the results from right to left: <CODE>%1010000001000101</CODE>
+
+
+<P>
+
+Group by four:
+
+
+<P>
+
+<PRE> %1010000001000101
+ %101000000100 0101
+ %10100000 0100 0101
+ %1010 0000 0100 0101
+</PRE>
+
+<P>
+
+Convert into hexadecimal: 0xA045
+
+
+<P>
+
+Group <CODE>%1010000001000101</CODE> by three and convert into octal:
+
+
+<P>
+
+<PRE> %1010000001000101
+ %1010000001000 101
+ %1010000001 000 101
+ %1010000 001 000 101
+ %1010 000 001 000 101
+ %1 010 000 001 000 101
+ %001 010 000 001 000 101
+ 1 2 0 1 0 5 --> 0120105
+</PRE>
+
+<P>
+
+<PRE> So: %1010000001000101 = 0120105 = 0xA045 = 41029
+ Or: 1010000001000101(2) = 120105(8) = A045(16) = 41029(10)
+ Or: 1010000001000101(2) = 120105(8) = A045(16) = 41029
+</PRE>
+
+<P>
+
+At first while adding numbers, you'll convert them to their decimal form
+and then back into their original form after doing the addition. If you use
+the other numbering system often, you will see that you'll be able to do
+arithmetics in the base that is used. In any representation it is the same,
+add the numbers on the right, write down the rightmost digit from the
+result, remember the other digits and use them in the next round. Continue
+with the second digits from the right and so on:
+
+
+<P>
+
+<PRE> %1010 + %0111 --> 10 + 7 --> 17 --> %00010001
+</PRE>
+
+<P>
+
+will become
+
+
+<P>
+
+<PRE> %1010
+ %0111 +
+ ||||
+ |||+-- add 0 + 1, result is 1, nothing to remember
+ ||+--- add 1 + 1, result is %10, write down 0 and remember 1
+ |+---- add 0 + 1 + 1(remembered), result = 0, remember 1
+ +----- add 1 + 0 + 1(remembered), result = 0, remember 1
+ nothing to add, 1 remembered, result = 1
+ --------
+ %10001 is the result, I like to write it as %00010001
+</PRE>
+
+<P>
+
+For low values, try to do the calculations yourself, check them with a
+calculator. The more you do the calculations yourself, the more you find
+that you didn't make mistakes. In the end, you'll do calcula in other bases
+as easy as you do in decimal.
+
+
+<P>
+
+When the numbers get bigger, you'll have to realise that a computer is not
+called a computer just to have a nice name. There are many different
+calculators available. Use them. For unix you could use ``bc'' which is
+called so as it is short for Binary Calculator. It calculates not only in
+decimal, but in all bases you'll ever use (among them Binary).
+
+
+<P>
+
+For people on Windows: Start the calculator
+(start->programs->accessories->calculator) and if necessary click
+view->scientific. You now have a scientific calculator and can compute
+in binary or hexadecimal.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR
+
+</A></H1>
+I hope you enjoyed the examples and their descriptions. If you do, help
+other people by pointing them to this document when they are asking basic
+questions. They will not only get their answer but at the same time learn a
+whole lot more.
+
+
+<P>
+
+Alex van den Bogaerdt <A
+HREF="MAILTO:<alex at ergens.op.het.net>"><alex at ergens.op.het.net></A>
+
+<P>
+
+</DL>
+ </BODY>
+
+ </HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/GNUmakefile.in
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/GNUmakefile.in (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/GNUmakefile.in Sat Jul 13 18:46:07 2002
@@ -0,0 +1,72 @@
+####
+#### Sorry, but this one will only work with GNU make ...
+####
+
+# things that the GNU standards document suggests all makefiles
+# should have.
+SHELL = /bin/sh
+.SUFFIXES:
+.SUFFIXES: .c .o .pl .pm .pod .html .man .1 .3 .txt
+
+# variables we got from configure
+# (you can mess with these, if you want)
+
+###
+### Things you might NOT want to play with ...
+###
+VER = `date +%Y%m%d.%H`
+
+POD = rrdtool.pod rrdlast.pod rrdcreate.pod rrdupdate.pod rrdgraph.pod RRDs.pm RRDp.pm \
+ rrdfetch.pod rrddump.pod rrdtune.pod
+
+MAN = $(POD:.pod=.1) $(POD:.pl=.1) $(POD:.pm=.3)
+TXT = $(MAN:.1=.txt) $(POD:.3=.txt)
+HTML = $(POD:.pod=.html) $(POD:.pl=.html) $(POD:.pm=.html)
+
+
+all: link txt man html
+
+
+.pod.1:
+ pod2man --release=$(VER) --center=rrdtool $< > $@
+
+.pm.3:
+ pod2man --release=$(VER) --center=rrdtool $< > $@
+
+.pl.1:
+ pod2man --release=$(VER) --center=rrdtool $< > $@
+
+.1.txt:
+ nroff -man -Tlp $< > $@
+
+.3.txt:
+ nroff -man -Tlp $< > $@
+
+.pod.html:
+ pod2html --infile=$< --outfile=$@ --noindex --htmlroot=. --podpath=. --title=$*
+
+.pl.html:
+ pod2html --infile=$< --outfile=$@ --noindex --htmlroot=. --podpath=. --title=$*
+
+.pm.html:
+ pod2html --infile=$< --outfile=$@ --noindex --htmlroot=. --podpath=. --title=$*
+
+RRDs.pm:
+ ln -s ../perl-shared/RRDs.pm .
+
+RRDp.pm:
+ ln -s ../perl-piped/RRDp.pm .
+
+link: RRDp.pm RRDs.pm
+
+man: $(MAN)
+
+html: $(HTML)
+
+txt: $(TXT)
+
+clean:
+ -rm *.txt *.html *.1 *.3
+
+realclean: clean
+ -rm -f GNUmakefile
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.pod
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.pod (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.pod Sat Jul 13 18:46:07 2002
@@ -0,0 +1,122 @@
+=head1 NAME
+
+rrdtool create - Set up a new Round Robin Database
+
+=head1 SYNOPSIS
+
+B<rrdtool> B<create> I<filename>
+S<[B<--start>|B<-b> I<start time>]>
+S<[B<--step>|B<-s> I<step>]>
+S<[B<DS:>I<ds-name>B<:>I<DST>B<:>I<heartbeat>B<:>I<min>B<:>I<max>]>
+S<[B<RRA:>I<CF>B<:>I<xff>B<:>I<steps>B<:>I<rows>]>
+
+=head1 DESCRIPTION
+
+The create function of the rrd tool lets you set up new
+Round Robin Database (B<RRD>) files.
+The file is created at its final, full size and filled
+with I<*UNKNOWN*> data.
+
+=over 8
+
+=item I<filename>
+
+The name of the B<RRD> you want to create. B<RRD> files should end
+with the extension F<.rrd>. However, B<rrdtool> will accept any
+filename.
+
+=item B<--start>|B<-b> I<start time> (default: current time)
+
+Specifies the time in seconds since 1970-01-01 UTC when the first
+value should be added to the B<RRD>. B<rrdtool> will not accept
+any data timed before or at the time specified.
+
+Negative input is treated as current time minus the specified number
+of seconds. See also AT-STYLE TIME SPECIFICATION section in the
+I<rrdfetch> documentation for alternative ways to specify time.
+
+=item B<--step>|B<-s> I<step> (default: 300 seconds)
+
+Specifies the base interval in seconds with which data will be fed
+into the B<RRD>.
+
+=item B<DS:>I<ds-name>B<:>I<DST>B<:>I<heartbeat>B<:>I<min>B<:>I<max>
+
+A single B<RRD> can accept input from several data sources (B<DS>).
+(e.g. Incoming and Outgoing traffic on a specific communication
+line). With the B<DS> configuration option you must define some basic
+properties of each data source you want to use to feed the B<RRD>.
+
+I<ds-name> is the name you will use to reference this particular data
+source from an B<RRD>. A I<ds-name> must be 1 to 19 characters long in
+the characters [a-zA-Z0-9_].
+
+I<DST> defines the Data Source Type. It can be one of the following:
+B<GAUGE> this is for things like temperatures or number of people in a
+room. B<COUNTER> is for continuous incrementing counters like the
+InOctets counter in a router. The B<COUNTER> data source assumes that
+the counter never decreases, except when a counter overflows. The update
+function takes the overflow into account. The counter is stored as a
+per-second rate. B<DERIVE> will store the
+the derivative of the line going from the last to the current value of the
+data source. This can be useful for gauges,
+for example, to measure the rate of people
+entering or leaving a room. B<ABSOLUTE> is for counters which get reset upon reading.
+
+I<heartbeat> defines the maximum number of seconds that may pass
+between two updates of this data source before the value of the
+data source is assumed to be I<*UNKNOWN*>.
+
+I<min> and I<max> are optional entries defining the expected range of
+the data supplied by this data source. If I<min> and/or I<max> are
+defined, any value outside the defined range will be regarded as
+I<*UNKNOWN*>. If you do not know or care about min and max, set them
+to U for unknown. Note that min and max always refere to the processed values
+of the DS. For a traffic-B<COUNTER> type DS this would be the max and min
+data-rate expected from the device.
+
+=item B<RRA:>I<CF>B<:>I<xff>B<:>I<steps>B<:>I<rows>
+
+The purpose of an B<RRD> is to store data in the round robin archives
+(B<RRA>). An archive consists of a number of data values from all the
+defined data-sources (B<DS>) and is defined with an B<RRA> line.
+
+When data is entered into an B<RRD>, it is first fit into time slots of
+the length defined with the B<-s> option becoming a I<primary data point>.
+
+The data is also consolidated with the consolidation function (I<CF>)
+of the archive. The following consolidation functions are defined:
+B<AVERAGE>, B<MIN>, B<MAX>, B<LAST>.
+
+I<xff> The xfiles factor defines what part of a consolidation interval may
+be made up from I<*UNKNOWN*> data while the consolidated value is sill
+regarded as known.
+
+I<steps> defines how many of these I<primary data points> are used to
+build a I<consolidated data point> which then goes into the archive.
+
+I<rows> defines how many generations of data values are kept in an B<RRA>.
+
+=back
+
+=head1 EXAMPLE
+
+C<rrdtool create temperature.rrd --step 300 DS:temp:GAUGE:600:-273:5000
+RRA:AVERAGE:0.5:1:1200 RRA:MIN:0.5:12:2400 RRA:MAX:0.5:12:2400
+RRA:AVERAGE:0.5:12:2400>
+
+This sets up an B<RRD> called F<temperature.rrd> which accepts one
+temperature value every 300 seconds. If no new data is supplied for
+more than 600 seconds, the temperature becomes I<*UNKNOWN*>. The
+minimum acceptable value is -273 and the maximum is 5000.
+
+A few archives areas are also defined. The first stores the
+temperatures supplied for 100 hours (1200 * 300 seconds = 100
+hours). The second RRA stores the minimum temperature recorded over
+every hour (12 * 300 seconds = 1 hour), for 100 days (2400 hours). The
+third and the fourth RRA's do the same with the for the maximum and
+average temperature, respectively.
+
+=head1 AUTHOR
+
+Tobias Oetiker <oetiker at ee.ethz.ch>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.html Sat Jul 13 18:46:07 2002
@@ -0,0 +1,165 @@
+ <HTML>
+ <HEAD>
+ <TITLE>update - Store a new set of values into the rrd
+
+</TITLE>
+ </HEAD>
+
+ <BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+ <LI><A HREF="#NAME">NAME</A>
+ <LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+ <LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+ <LI><A HREF="#EXAMPLE">EXAMPLE</A>
+ <LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME
+
+</A></H1>
+rrdtool update - Store a new set of values into the rrd
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS
+
+</A></H1>
+<STRONG>rrdtool</STRONG> <STRONG>update</STRONG> <EM>filename</EM>
+
+[<STRONG>--template</STRONG>|<STRONG>-t</STRONG> <EM>ds-name</EM>[<STRONG>:</STRONG><EM>ds-name</EM>]...]
+
+<STRONG>N</STRONG>|<EM>timestamp</EM><STRONG>:</STRONG><EM>value</EM>[<STRONG>:</STRONG><EM>value</EM>...]
+
+[<EM>timestamp</EM><STRONG>:</STRONG><EM>value</EM>[<STRONG>:</STRONG><EM>value</EM>...] ...]
+
+
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION
+
+</A></H1>
+The <STRONG>update</STRONG> function feeds new data values into an <STRONG>RRD</STRONG>. The data gets time aligned according to the properties of the <STRONG>RRD</STRONG> to which the data is written.
+
+
+<P>
+
+<DL>
+<DT><STRONG><A NAME="item_filename">filename
+
+</A></STRONG><DD>
+The name of the <STRONG>RRD</STRONG> you want to update.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__template_t">--template|-t ds-name[:ds-name]...
+
+</A></STRONG><DD>
+by default, the update function expects the data input in the order, the
+data sources are defined in the RRD. This is not very error resistant, as
+you might be sending the wrong data into a RRD.
+
+
+<P>
+
+The template switch alows you to specify which data sources you are going
+to update and in which order. If the datasources specified in the template
+are not available in the rrd file, the update process will abort with an
+error message.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_N">N|timestamp:value[:value...]
+
+</A></STRONG><DD>
+The data used for updating the RRD was acquired at a certain time. This
+time can either be defined in seconds since 1970-01-01. Or by using the
+letter 'N' the update time is set to be the current time. Negative time
+values are subtracted from the current time. Getting the timing right to
+the second is especially important when you are working with data-sources
+of type <STRONG>COUNTER</STRONG>,
+<STRONG>DERIVE</STRONG> or <STRONG>ABSOLUTE</STRONG>.
+
+
+<P>
+
+The remaining elements of the argument are DS updates. The order of this
+list is the same as the order the datasources were defined in the rra. If
+there is no data for a certain data-source, the letter
+<STRONG>U</STRONG> (eg. N:0.1:U:1) can be defined.
+
+
+<P>
+
+The format of the value acquired from the datasource is dependent of the
+datasource type chosen. Normally it will be numeric, but the data
+acquisition modules my impose their very own parsing of this parameter as
+long as the colon (<STRONG>:</STRONG>) remains the datasource value separator.
+
+
+<P>
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="EXAMPLE">EXAMPLE
+
+</A></H1>
+<CODE>rrdtool update demo1.rrd N:3.44:3.15:U:23</CODE>
+
+
+
+
+<P>
+
+Update the database file demo1.rrd with 3 known and one <EM>*UNKNOWN*</EM>
+value. Use the current time as the update time.
+
+
+<P>
+
+<CODE>rrdtool update demo2.rrd 887457267:U 887457521:22 88745790:2.7</CODE>
+
+
+
+
+<P>
+
+Update the database file demo2.rrd which expects data from a single
+data-source, three times. First with an <EM>*UNKNOWN*</EM> value then with two normal readings. The update interval seems to be around
+300 seconds.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR
+
+</A></H1>
+Tobias Oetiker <A
+HREF="MAILTO:<oetiker at ee.ethz.ch>"><oetiker at ee.ethz.ch></A>
+
+
+<P>
+
+</DL>
+ </BODY>
+
+ </HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.txt
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.txt (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.txt Sat Jul 13 18:46:08 2002
@@ -0,0 +1,132 @@
+
+
+
+RRDTUNE(1) rrdtool RRDTUNE(1)
+
+
+NNNNAAAAMMMMEEEE
+ rrdtool tune - Modify some basic properties of a Round
+ Robin Database
+
+SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
+ rrrrrrrrddddttttoooooooollll ttttuuuunnnneeee _f_i_l_e_n_a_m_e [--------hhhheeeeaaaarrrrttttbbbbeeeeaaaatttt|----hhhh _d_s_-_n_a_m_e:_h_e_a_r_t_b_e_a_t]
+ [--------mmmmiiiinnnniiiimmmmuuuummmm|----iiii _d_s_-_n_a_m_e:_m_i_n] [--------mmmmaaaaxxxxiiiimmmmuuuummmm|----aaaa _d_s_-_n_a_m_e:_m_a_x]
+ [--------ddddaaaattttaaaa----ssssoooouuuurrrrcccceeee----ttttyyyyppppeeee|----dddd _d_s_-_n_a_m_e:_D_S_T]
+ [--------ddddaaaattttaaaa----ssssoooouuuurrrrcccceeee----rrrreeeennnnaaaammmmeeee|----rrrr _o_l_d_-_n_a_m_e:_n_e_w_-_n_a_m_e]
+
+DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
+ The tune option allows you to alter some of the basic
+ configuration values stored in the header area of a Round
+ Robin Database (RRRRRRRRDDDD). All these tunable parameters
+ together decide when data fed into an RRRRRRRRDDDD is to be
+ regarded as invalid. Invalid data is entered into the
+ database as *UNKNOWN*.
+
+ The main application of the ttttuuuunnnneeee function is to relax the
+ validation rules on an RRRRRRRRDDDD. This allows to fill a new RRRRRRRRDDDD
+ with data available in larger intervals than what you
+ would normally want to permit.
+
+ _f_i_l_e_n_a_m_e
+ The name of the RRRRRRRRDDDD you want to tune.
+
+ --------hhhheeeeaaaarrrrttttbbbbeeeeaaaatttt|----hhhh _d_s_-_n_a_m_e:_h_e_a_r_t_b_e_a_t
+ modify the _h_e_a_r_t_b_e_a_t of a data source. By setting
+ this to a high value the rrd will accept things
+ like one value per day ...
+
+ --------mmmmiiiinnnniiiimmmmuuuummmm|----iiii _d_s_-_n_a_m_e:_m_i_n
+ alter the minimum value acceptable as input from
+ the data source. Setting _m_i_n to 'U' will disable
+ this limit.
+
+ --------mmmmaaaaxxxxiiiimmmmuuuummmm|----aaaa _d_s_-_n_a_m_e:_m_a_x
+ alter the maximum value acceptable as input from
+ the data source. Setting _m_a_x to 'U' will disable
+ this limit.
+
+ --------ddddaaaattttaaaa----ssssoooouuuurrrrcccceeee----ttttyyyyppppeeee|----dddd _d_s_-_n_a_m_e:_D_S_T
+ alter the type DDDDSSSSTTTT of a data source.
+
+ [--------ddddaaaattttaaaa----ssssoooouuuurrrrcccceeee----rrrreeeennnnaaaammmmeeee|----rrrr _o_l_d_-_n_a_m_e:_n_e_w_-_n_a_m_e]
+ rename a data source
+
+EEEEXXXXAAAAMMMMPPPPLLLLEEEE
+ rrdtool tune data.rrd -h in:100000 -h in:100000 -h
+ in:100000
+
+ Set the minimum required heartbeat for data sources 'in',
+ 'out' and 'through' to 10000 seconds which is a little
+ over one day in data.rrd. This would allow to feed old
+
+
+
+14/Jan/99 19990426.22 1
+
+
+
+
+
+RRDTUNE(1) rrdtool RRDTUNE(1)
+
+
+ data from mrtg-2.0 right into rrdtool without generating
+ *UNKNOWN* entries.
+
+AAAAUUUUTTTTHHHHOOOORRRR
+ Tobias Oetiker <oetiker at ee.ethz.ch>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+14/Jan/99 19990426.22 2
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.html Sat Jul 13 18:46:08 2002
@@ -0,0 +1,308 @@
+ <HTML>
+ <HEAD>
+ <TITLE>fetch - fetch data from an rrd.
+
+</TITLE>
+ </HEAD>
+
+ <BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+ <LI><A HREF="#NAME">NAME</A>
+ <LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+ <LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+ <UL>
+
+ <LI><A HREF="#AT_STYLE_TIME_SPECIFICATION">AT-STYLE TIME SPECIFICATION</A>
+ <LI><A HREF="#TIME_REFERENCE_SPECIFICATION">TIME REFERENCE SPECIFICATION</A>
+ <LI><A HREF="#TIME_OFFSET_SPECIFICATION">TIME OFFSET SPECIFICATION</A>
+ <LI><A HREF="#TIME_SPECIFICATION_EXAMPLES">TIME SPECIFICATION EXAMPLES</A>
+ </UL>
+
+ <LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME
+
+</A></H1>
+rrdtool fetch - fetch data from an rrd.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS
+
+</A></H1>
+<STRONG>rrdtool</STRONG> <STRONG>fetch</STRONG> <EM>filename</EM> <EM>CF</EM>
+
+[<STRONG>--resolution</STRONG>|<STRONG>-r</STRONG> <EM>resolution</EM>]
+
+[<STRONG>--start</STRONG>|<STRONG>-s</STRONG> <EM>start</EM>]
+
+[<STRONG>--end</STRONG>|<STRONG>-e</STRONG> <EM>end</EM>]
+
+
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION
+
+</A></H1>
+The <STRONG>fetch</STRONG> function is normally used internally by the graph function, to get data
+from <STRONG>RRD</STRONG>s. <STRONG>fetch</STRONG> will analyze the <STRONG>RRD</STRONG> and will try to retrieve the data in the resolution requested. The data
+fetched is printed to stdout. <EM>*UNKNOWN*</EM> data is often represented by the string ``NaN'' depending on your OSs
+printf function.
+
+
+<P>
+
+<DL>
+<DT><STRONG><A NAME="item_filename">filename
+
+</A></STRONG><DD>
+the name of the <STRONG>RRD</STRONG> you want to fetch the data from.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_CF">CF
+
+</A></STRONG><DD>
+which consolidation function should have been applied to the data you want
+to fetch? (AVERAGE,MIN,MAX,LAST)
+
+
+<P>
+
+<DT><STRONG><A NAME="item__resolution_r">--resolution|-r resolution (default is the highest resolution)
+
+</A></STRONG><DD>
+what interval should the values have (seconds per value). <STRONG>rrdfetch</STRONG> will try to match your request, but it will return data even if no absolute
+match is possible.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__start_s">--start|-s start (default -24*3600)
+
+</A></STRONG><DD>
+when should the data begin. A time in seconds since epoch (1970-01-01) is
+required. Negative numbers are relative to the end time. By default one day
+worth of data will be fetched. See also AT-STYLE TIME SPECIFICATION section
+for alternative ways to specify start time.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__end_e">--end|-e end (default current time)
+
+</A></STRONG><DD>
+when should the data end. Time in seconds since epoch. See also AT-STYLE
+TIME SPECIFICATION section for alternative ways to specify end time.
+
+
+<P>
+
+</DL>
+<P>
+<HR>
+<H2><A NAME="AT_STYLE_TIME_SPECIFICATION">AT-STYLE TIME SPECIFICATION
+
+</A></H2>
+The rrdtool does also understand at-style time specification. The
+specification is called ``at-style'' after unix command <CODE>at(1)</CODE>
+that has moderately complex ways to specify time to run your job at. The
+at-style specification consists of two parts: <STRONG>TIME REFERENCE</STRONG>
+specification and <STRONG>TIME OFFSET</STRONG> specification.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="TIME_REFERENCE_SPECIFICATION">TIME REFERENCE SPECIFICATION
+
+</A></H2>
+Time reference specification is used, well,... to establish a reference
+moment in time (for time offset to be applied to). When present, it should
+come first, when omitted, it defaults to <STRONG>now</STRONG>. On its own part, time reference consists of <EM>time-of-day</EM> reference (which should come first, if present) and <EM>day</EM> reference.
+
+
+<P>
+
+<EM>Time-of-day</EM> can be specified as <STRONG>HH:MM</STRONG>, <STRONG>HH.MM</STRONG>, <STRONG>HHMM</STRONG>, or just <STRONG>HH</STRONG>, you can suffix it with <STRONG>am</STRONG> or <STRONG>pm</STRONG> or use 24-hours clock. The few special times of day are understood as well,
+these include <STRONG>midnight</STRONG> (00:00), <STRONG>noon</STRONG> (12:00) and british
+<STRONG>teatime</STRONG> (16:00).
+
+
+<P>
+
+The <EM>day</EM> can be specified as <EM>month-name</EM> <EM>day-of-the-month</EM>
+and optional 2- or 4-digit <EM>year</EM> number (e.g. March 8 1999). Alternatively, you can use <EM>day-of-week-name</EM> (e.g. Monday), or one of the words: <STRONG>yesterday</STRONG>, <STRONG>today</STRONG>, <STRONG>tomorrow</STRONG>. You can also specify <EM>day</EM> as a full date in several numerical formats; these include: <STRONG>MM/DD/[YY]YY</STRONG>, <STRONG>DD.MM.[YY]YY</STRONG>, <STRONG>DDMM[YY]YY</STRONG>
+(<EM>NOTE1</EM>: this is different from the original <CODE>at(1)</CODE> behavior, which
+interprets a single-number date as MMDD[YY]YY)
+<EM>NOTE2</EM>: if you specify <EM>day</EM> this way, the <EM>time-of-day</EM> is REQUIRED to be present in front of it.
+
+
+<P>
+
+Finally, you can use words <STRONG>now</STRONG>, <STRONG>start</STRONG>, or <STRONG>end</STRONG> as your time reference. <STRONG>Now</STRONG> refers to the current moment (and is also a default time reference). <STRONG>Start</STRONG> (<STRONG>end</STRONG>) can be used to specify time relative to the start (end) time for those
+tools that use these categories (rrdfetch, rrdgraph).
+
+
+<P>
+
+Month and weekday names can be used in their naturally abbreviated form
+(e.g., Dec for December, Sun for Sunday, etc.). The words <STRONG>now</STRONG>,
+<STRONG>start</STRONG>, <STRONG>end</STRONG> can be abbreviated to <STRONG>n</STRONG>, <STRONG>s</STRONG>, <STRONG>e</STRONG>.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="TIME_OFFSET_SPECIFICATION">TIME OFFSET SPECIFICATION
+
+</A></H2>
+Time offset specification is used to add (or substract) certain time
+interval to (from) the time reference moment. It consists of <EM>sign</EM>
+(<STRONG>+</STRONG> or <STRONG>-</STRONG>) and <EM>amount</EM>. The following time units can be used to specify the <EM>amount</EM>: <STRONG>years</STRONG>, <STRONG>months</STRONG>, <STRONG>weeks</STRONG>, <STRONG>days</STRONG>,
+<STRONG>hours</STRONG>, <STRONG>minutes</STRONG>, <STRONG>seconds</STRONG>, these can be used in singular or plural form, and abbreviated naturally
+or to a single letter (e.g. +3days, -1wk, -3y). Several time units can be
+combined together (e.g., -5mon1w2d), as well as several time offsets can be
+concatenated (e.g., -5h45min = -5h-45min = -6h+15min = -7h+1h30m-15min,
+etc.)
+
+
+<P>
+
+<EM>NOTE3</EM>: If you specify time offset in days, weeks, months, or years, you will end
+with the time offset that may vary depending on you time reference, because
+all those time units have no single well defined time interval value (1 year contains either 365 or 366 days, 1 month
+is 28 to 31 days long, and even 1 day may be not equal to 24 hours twice a year, when DST-related clock
+adjustments take place). To cope with this, when you use days, weeks,
+months, or years as your time offset units your time reference date is
+adjusted accordingly without taking too much further effort to ensure
+anything about it (in the hope that <CODE>mktime(3)</CODE> will take care
+of this later). This may lead to some surprising (or even invalid!)
+results, e.g. 'May 31 -1month' = 'Apr 31' (meaningless) = 'May 1'
+(after <CODE>mktime(3)</CODE> normalization); in the EET timezone '3:30am
+Mar 29 1999 -1 day' yields '3:30am Mar 28 1999' (Sunday) which is invalid
+time/date combination (because of 3am -> 4am DST forward clock
+ajustment, see the below example). On the other hand, hours, minutes, and
+seconds are well defined time intervals, and these are guaranteed to always
+produce time offsets exactly as specified (e.g. for EET timezone, '8:00 Mar 27 1999 +2 days' =
+'8:00 Mar 29 1999', but since there is 1-hour DST forward clock adjustment takes place around 3:00 Mar 28 1999, the actual time interval between
+8:00 Mar 27 1999 and 8:00 Mar 29 1999 equals 47 hours; on the other hand,
+'8:00 Mar 27 1999 +48 hours' = '9:00 Mar 29 1999', as expected)
+
+
+<P>
+
+<EM>NOTE4</EM>: The single-letter abbreviation for both <STRONG>months</STRONG> and <STRONG>minutes</STRONG>
+is <STRONG>m</STRONG>. To disambiguiate, the parser tries to read your mind :)
+by applying the following two heuristics:
+
+
+<P>
+
+<OL>
+<LI><STRONG><A NAME="item_">
+
+</A></STRONG>
+If <STRONG>m</STRONG> is used in context of (i.e. right after the) years, months, weeks, or days
+it is assumed to mean <STRONG>months</STRONG>, while in the context of hours, minutes, and seconds it means minutes.
+(e.g., in -1y6m or +3w1m <STRONG>m</STRONG> means <STRONG>months</STRONG>, while in -3h20m or +5s2m <STRONG>m</STRONG> means <STRONG>minutes</STRONG>)
+
+
+<P>
+
+<LI><STRONG><A NAME="item_">
+
+</A></STRONG>
+Out of context (i.e. right after the <STRONG>+</STRONG> or <STRONG>-</STRONG> sign) the meaning of <STRONG>m</STRONG> is guessed from the number it directly follows. Currently, if the number
+absolute value is below 25 it is assumed that <STRONG>m</STRONG> means <STRONG>months</STRONG>, otherwise it is treated as <STRONG>minutes</STRONG>. (e.g., -25m == -25 minutes, while +24m == +24 months)
+
+
+<P>
+
+</OL>
+<EM>Final NOTES</EM>: Time specification is case-insensitive. Whitespace can be inserted freely
+or omitted altogether, there are, however, cases when whitespace is
+required (e.g., 'midnight Thu'). In this case you should either quote the whole phrase to prevent it from
+bieng taken apart by your shell or use '_' (underscore) or ',' (comma)
+which also count as whitespace (e.g., midnight_Thu or midnight,Thu)
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="TIME_SPECIFICATION_EXAMPLES">TIME SPECIFICATION EXAMPLES
+
+</A></H2>
+<EM>Oct 12</EM> -- October 12 this year
+
+
+<P>
+
+<EM>-1month</EM> or <EM>-1m</EM> -- current time of day, only a month before (may yield surprises, see the
+NOTE3 above)
+
+
+<P>
+
+<EM>noon yesterday -3hours</EM> -- yesterday morning; can be put also as <EM>9am-1day</EM>
+
+
+
+
+<P>
+
+<EM>23:59 31.12.1999</EM> -- 1 minute to the year 2000
+
+
+<P>
+
+<EM>12am 010101</EM> -- start of the new millenium
+
+
+<P>
+
+<EM>end-3weeks</EM> or <EM>e-3w</EM> -- 3 weeks before end time (may be used as start time specification)
+
+
+<P>
+
+<EM>start+6hours</EM> or <EM>s+6h</EM> -- 6 hours after start time (may be used as end time specification)
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR
+
+</A></H1>
+Tobias Oetiker <A
+HREF="MAILTO:<oetiker at ee.ethz.ch>"><oetiker at ee.ethz.ch></A>
+
+
+<P>
+
+</DL>
+ </BODY>
+
+ </HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.pod
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.pod (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.pod Sat Jul 13 18:46:08 2002
@@ -0,0 +1,70 @@
+=head1 NAME
+
+rrdtool tune - Modify some basic properties of a Round Robin Database
+
+=head1 SYNOPSIS
+
+B<rrdtool> B<tune> I<filename>
+S<[B<--heartbeat>|B<-h> I<ds-name>:I<heartbeat>]>
+S<[B<--minimum>|B<-i> I<ds-name>:I<min>]>
+S<[B<--maximum>|B<-a> I<ds-name>:I<max>]>
+S<[B<--data-source-type>|B<-d> I<ds-name>:I<DST>]>
+S<[B<--data-source-rename>|B<-r> I<old-name>:I<new-name>]>
+
+=head1 DESCRIPTION
+
+The tune option allows you to alter some of the basic configuration
+values stored in the header area of a Round Robin Database (B<RRD>).
+All these tunable parameters together decide when data fed into an
+B<RRD> is to be regarded as invalid. Invalid data is entered into the
+database as *UNKNOWN*.
+
+The main application of the B<tune> function is to relax the
+validation rules on an B<RRD>. This allows to fill a new B<RRD> with
+data available in larger intervals than what you would normally want
+to permit.
+
+=over 8
+
+=item I<filename>
+
+The name of the B<RRD> you want to tune.
+
+=item S<B<--heartbeat>|B<-h> I<ds-name>:I<heartbeat>>
+
+modify the I<heartbeat> of a data source. By setting this to a high
+value the rrd will accept things like one value per day ...
+
+=item S<B<--minimum>|B<-i> I<ds-name>:I<min>>
+
+alter the minimum value acceptable as input from the data source.
+Setting I<min> to 'U' will disable this limit.
+
+=item S<B<--maximum>|B<-a> I<ds-name>:I<max>>
+
+alter the maximum value acceptable as input from the data source.
+Setting I<max> to 'U' will disable this limit.
+
+=item S<B<--data-source-type>|B<-d> I<ds-name>:I<DST>>
+
+alter the type B<DST> of a data source.
+
+=item S<[B<--data-source-rename>|B<-r> I<old-name>:I<new-name>]>
+
+rename a data source
+
+=back
+
+=head1 EXAMPLE
+
+C<rrdtool tune data.rrd -h in:100000 -h in:100000 -h in:100000>
+
+Set the minimum required heartbeat for data sources 'in', 'out'
+and 'through' to 10000 seconds which is a little over one day in data.rrd.
+This would allow to feed old data from mrtg-2.0 right into
+rrdtool without generating *UNKNOWN* entries.
+
+=head1 AUTHOR
+
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.txt
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.txt (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.txt Sat Jul 13 18:46:08 2002
@@ -0,0 +1,528 @@
+
+
+
+BIN_DEC_HEX(1) rrdtool BIN_DEC_HEX(1)
+
+
+NNNNAAAAMMMMEEEE
+ Binary Decimal Hexadecimal - How does it wok
+
+DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
+ Most people use the decimal numbering system. This system
+ uses ten symbols to represent numbers. When those ten
+ symbols are used up, they start all over again and
+ increment the position just before this. The digit 0 is
+ only shown if it is the only symbol in the sequence, or if
+ it is not the first one.
+
+ If this sounds as crypto to you, this is what I've said in
+ numbers:
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+
+ and so on.
+
+ Each time the digit nine should be incremented, it is
+ reset to 0 and the position before is incremented. Then
+ number 9 can be seen as "00009" and when we should
+ increment 9, we reset it to zero and increment the digit
+ just before the 9 so the number becomes "00010". For
+ zero's we write a space if it is not the only digit (so:
+ number 0) and if it is the first digit: "00010" -> " 0010"
+ -> " 010" -> " 10". It is not " 1 ".
+
+ This was pretty basic, you already knew this. Why did I
+ tell it ? Well, computers do not represent numbers with
+ 10 different digits. They know of only two different
+ symbols, being 0 and 1. Apply the same rules to this set
+ of digits and you get the binary numbering system:
+
+
+
+
+
+
+
+
+
+
+
+
+4/May/99 19990504.23 1
+
+
+
+
+
+BIN_DEC_HEX(1) rrdtool BIN_DEC_HEX(1)
+
+
+ 0
+ 1
+ 10
+ 11
+ 100
+ 101
+ 110
+ 111
+ 1000
+ 1001
+ 1010
+ 1011
+ 1100
+ 1101
+
+ and so on.
+
+ If you count the number of rows, you'll see that these are
+ again 14 different numbers. The numbers are the same and
+ mean the same. It is only a different representation. This
+ means that you have to know the representation used, or as
+ it is called the numbering system or base. Normally if we
+ do not speak about the numbering system used, we're using
+ the decimal system. If we are talking about another
+ numbering system, we'll have to make that clear. There are
+ a few wide-spread methods to do so. One common form is to
+ write _1_0_1_0(2) which means that you wrote down a number in
+ the binary form. It is the number ten. If you would write
+ 1010 it means the number one thousand and ten.
+
+ In books, another form is most used. It uses subscript
+ (little chars, more or less in between two rows). You can
+ leave out the parentheses in that case and write down the
+ number in normal characters followed with a little two
+ just behind it.
+
+ The numbering system used is also called the base. We talk
+ of the number 1100 base 2, the number 12 base 10.
+
+ For the binary system, is is common to write leading
+ zero's. The numbers are written down in series of four,
+ eight or sixteen depending on the context.
+
+ We can use the binary form when talking to computers
+ (...programming...) but the numbers will have large
+ representations. The number 65535 would be written down as
+ _1_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1(2) which is 16 times the digit 1. This
+ is difficult and prone to errors. Therefore we normally
+ would use another base, called hexadecimal. It uses 16
+ different symbols. First the symbols from the decimal
+ system are used, thereafter we continue with the alfabetic
+ characters. We get 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C,
+ D, E and F. This system is choosen because the hexadecimal
+ form can be converted into the binary system very easy
+
+
+
+4/May/99 19990504.23 2
+
+
+
+
+
+BIN_DEC_HEX(1) rrdtool BIN_DEC_HEX(1)
+
+
+ (and back).
+
+ There is yet another system in use, called the octal
+ system. This was more common in the old days but not
+ anymore. You will find it in use on some places so get
+ used to it. The same story applies, but now with only
+ eight different symbols.
+
+ Binary (2)
+ Octal (8)
+ Decimal (10)
+ Hexadecimal (16)
+
+ (2) (8) (10) (16)
+ 00000 0 0 0
+ 00001 1 1 1
+ 00010 2 2 2
+ 00011 3 3 3
+ 00100 4 4 4
+ 00101 5 5 5
+ 00110 6 6 6
+ 00111 7 7 7
+ 01000 10 8 8
+ 01001 11 9 9
+ 01010 12 10 A
+ 01011 13 11 B
+ 01100 14 12 C
+ 01101 15 13 D
+ 01110 16 14 E
+ 01111 17 15 F
+ 10000 20 16 10
+ 10001 21 17 11
+ 10010 22 18 12
+ 10011 23 19 13
+ 10100 24 20 14
+ 10101 25 21 15
+
+ Most computers used nowadays are using bytes of eight
+ bits. This means that they store eight bits at a time. You
+ can see why the octal system is not the most preferred for
+ that: You'd need three digits to represent the eight bits
+ and this means that you'd have to use one complete digit
+ to represent only two bits (2+3+3=8). This is a waste. For
+ hexadecimal digits, you need only two digits which are
+ used completely:
+
+ (2) (8) (10) (16)
+ 11111111 377 255 FF
+
+ You can see why binary and hexadecimal can be converted
+ quickly: For each hexadecimal digit there are exactly four
+ binary digits. Take a binary number. Each time take four
+ digits from the right and make a hexadecimal digit from it
+ (see the table above). Stop when there are no more digits.
+
+
+
+4/May/99 19990504.23 3
+
+
+
+
+
+BIN_DEC_HEX(1) rrdtool BIN_DEC_HEX(1)
+
+
+ Other way around: Take a hexadecimal number. For each
+ digit, write down its binary equivalent.
+
+ Computers (or rather the parsers running on them) would
+ have a hard time converting a number like _1_2_3_4(16).
+ Therefore hexadecimal numbers get a prefix. This prefix
+ depends on the language you're writing in. Some of the
+ prefixes are "0x" for C, "$" for pascal, "#" for HTML. It
+ is common to assume that if a number starts with a zero,
+ it is octal. It does not matter what is used as long as
+ you know what it is. I will use "0x" for hexadecimal, "%"
+ for binary and "0" for octal. The following numbers are
+ all the same, just the way they are written is different:
+ 021 0x11 17 %00010001
+
+ To do arithmetics and conversions you need to understand
+ one more thing. It is something you already know but
+ perhaps you do not "see" it yet:
+
+ If you write down 1234, (so it is decimal) you are talking
+ about the number one thousand, two hundred and thirty
+ four. In sort of a formula:
+
+ 1 * 1000 = 1000
+ 2 * 100 = 200
+ 3 * 10 = 30
+ 4 * 1 = 4
+
+ This can also be written as:
+
+ 1 * 10^3
+ 2 * 10^2
+ 3 * 10^1
+ 4 * 10^0
+
+ where ^ means "to the power of".
+
+ We are using the base 10, and the positions 0,1,2 and 3.
+ The right-most position should NOT be multiplied with 10.
+ The second from the right should be multiplied one time
+ with 10. The third from the right is multiplied with 10
+ two times. This continues for whatever positions are used.
+
+ It is the same in all other representations:
+
+ 0x1234 will be
+
+ 1 * 16^3
+ 2 * 16^2
+ 3 * 16^1
+ 4 * 16^0
+
+ 01234 would be
+
+
+
+
+4/May/99 19990504.23 4
+
+
+
+
+
+BIN_DEC_HEX(1) rrdtool BIN_DEC_HEX(1)
+
+
+ 1 * 8^3
+ 2 * 8^2
+ 3 * 8^1
+ 4 * 8^0
+
+ This example can not be done for binary as that system can
+ only use two symbols. Another example:
+
+ %1010 would be
+
+ 1 * 2^3
+ 0 * 2^2
+ 1 * 2^1
+ 0 * 2^0
+
+ It would have been more easy to convert it to its
+ hexadecimal form and just translate %1010 into 0xA. After
+ a while you get used to it. You will not need to do any
+ calculations anymore but just know that 0xA means 10.
+
+ To convert a decimal number into a hexadecimal one you
+ could use the next method. It will take some time to be
+ able to do the estimates but it will be more and more easy
+ when you use the system more frequent. Another way is
+ presented to you thereafter.
+
+ First you will need to know how many positions will be
+ used in the other system. To do so, you need to know the
+ maximum numbers. Well, that's not so hard as it looks. In
+ decimal, the maximum number that you can form with two
+ digits is "99". The maximum for three: "999". The next
+ number would need an extra position. Reverse this idea and
+ you will see that the number can be found by taking 10^3
+ (10*10*10 is 1000) minus 1 or 10^2 minus one.
+
+ This can be done for hexadecimal too:
+
+ 16^4 = 0x10000 = 65536
+ 16^3 = 0x1000 = 4096
+ 16^2 = 0x100 = 256
+ 16^1 = 0x10 = 16
+
+ If a number is smaller than 65536 it will thus fit in four
+ positions. If the number is bigger than 4095, you will
+ need to use position 4. How many times can you take 4096
+ from the number without going below zero is the first
+ digit you write down. This will always be a number from 1
+ to 15 (0x1 to 0xF). Do the same for the other positions.
+
+ Number is 41029. It is smaller than 16^4 but bigger than
+ 16^3-1. This means that we have to use four positions. We
+ can subtract 16^3 from 41029 ten times without going below
+ zero. The leftmost digit will be "A" so we have 0xA????.
+ The number is reduced to 41029 - 10*4096 = 41029-40960 =
+
+
+
+4/May/99 19990504.23 5
+
+
+
+
+
+BIN_DEC_HEX(1) rrdtool BIN_DEC_HEX(1)
+
+
+ 69. 69 is smaller than 16^3 but not bigger than 16^2-1.
+ The second digit is therefore "0" and we know 0xA0??. 69
+ is smaller than 16^2 and bigger than 16^1-1. We can
+ subtract 16^1 (which is just plain 16) four times and
+ write down "4" to get 0xA04?. Take 64 from 69 (69 - 4*16)
+ and the last digit is 5 --> 0xA045.
+
+ The other method builds the number from the right. Take
+ again 41029. Divide by 16 and do not use fractions (only
+ whole numbers).
+
+ 41029 / 16 is 2564 with a remainder of 5. Write down 5.
+ 2564 / 16 is 160 with a remainder of 4. Write the 4 before the 5.
+ 160 / 16 is 10 with no remainder. Prepend 45 with 0.
+ 10 / 16 is below one. End here and prepend 0xA. End up with 0xA045.
+
+ Which method to use is up to you. Use whatever works for
+ you. Personally I use them both without being able to tell
+ what method I use in each case, it just depends on the
+ number, I think. Fact is, some numbers will occur
+ frequently while programming, if the number is close then
+ I will use the first method (like 32770, translate into
+ 32768 + 2 and just know that it is 0x8000 + 0x2 = 0x8002).
+
+ For binary the same approach can be used. The base is 2
+ and not 16, and the number of positions will grow rapidly.
+ Using the second method has the advantage that you can see
+ very simple if you should write down a zero or a one: if
+ you divide by two the remainder will be zero if it was an
+ even number and one if it was an odd number:
+
+ 41029 / 2 = 20514 remainder 1
+ 20514 / 2 = 10257 remainder 0
+ 10257 / 2 = 5128 remainder 1
+ 5128 / 2 = 2564 remainder 0
+ 2564 / 2 = 1282 remainder 0
+ 1282 / 2 = 641 remainder 0
+ 641 / 2 = 320 remainder 1
+ 320 / 2 = 160 remainder 0
+ 160 / 2 = 80 remainder 0
+ 80 / 2 = 40 remainder 0
+ 40 / 2 = 20 remainder 0
+ 20 / 2 = 10 remainder 0
+ 10 / 2 = 5 remainder 0
+ 5 / 2 = 2 remainder 1
+ 2 / 2 = 1 remainder 0
+ 1 / 2 below 0 remainder 1
+
+ Write down the results from right to left:
+ %1010000001000101
+
+ Group by four:
+
+
+
+
+
+4/May/99 19990504.23 6
+
+
+
+
+
+BIN_DEC_HEX(1) rrdtool BIN_DEC_HEX(1)
+
+
+ %1010000001000101
+ %101000000100 0101
+ %10100000 0100 0101
+ %1010 0000 0100 0101
+
+ Convert into hexadecimal: 0xA045
+
+ Group %1010000001000101 by three and convert into octal:
+
+ %1010000001000101
+ %1010000001000 101
+ %1010000001 000 101
+ %1010000 001 000 101
+ %1010 000 001 000 101
+ %1 010 000 001 000 101
+ %001 010 000 001 000 101
+ 1 2 0 1 0 5 --> 0120105
+
+ So: %1010000001000101 = 0120105 = 0xA045 = 41029
+ Or: 1010000001000101(2) = 120105(8) = A045(16) = 41029(10)
+ Or: 1010000001000101(2) = 120105(8) = A045(16) = 41029
+
+ At first while adding numbers, you'll convert them to
+ their decimal form and then back into their original form
+ after doing the addition. If you use the other numbering
+ system often, you will see that you'll be able to do
+ arithmetics in the base that is used. In any
+ representation it is the same, add the numbers on the
+ right, write down the rightmost digit from the result,
+ remember the other digits and use them in the next round.
+ Continue with the second digits from the right and so on:
+
+ %1010 + %0111 --> 10 + 7 --> 17 --> %00010001
+
+ will become
+
+ %1010
+ %0111 +
+ ||||
+ |||+-- add 0 + 1, result is 1, nothing to remember
+ ||+--- add 1 + 1, result is %10, write down 0 and remember 1
+ |+---- add 0 + 1 + 1(remembered), result = 0, remember 1
+ +----- add 1 + 0 + 1(remembered), result = 0, remember 1
+ nothing to add, 1 remembered, result = 1
+ --------
+ %10001 is the result, I like to write it as %00010001
+
+ For low values, try to do the calculations yourself, check
+ them with a calculator. The more you do the calculations
+ yourself, the more you find that you didn't make mistakes.
+ In the end, you'll do calcula in other bases as easy as
+ you do in decimal.
+
+ When the numbers get bigger, you'll have to realise that a
+
+
+
+4/May/99 19990504.23 7
+
+
+
+
+
+BIN_DEC_HEX(1) rrdtool BIN_DEC_HEX(1)
+
+
+ computer is not called a computer just to have a nice
+ name. There are many different calculators available. Use
+ them. For unix you could use "bc" which is called so as it
+ is short for Binary Calculator. It calculates not only in
+ decimal, but in all bases you'll ever use (among them
+ Binary).
+
+ For people on Windows: Start the calculator
+ (start->programs->accessories->calculator) and if
+ necessary click view->scientific. You now have a
+ scientific calculator and can compute in binary or
+ hexadecimal.
+
+AAAAUUUUTTTTHHHHOOOORRRR
+ I hope you enjoyed the examples and their descriptions. If
+ you do, help other people by pointing them to this
+ document when they are asking basic questions. They will
+ not only get their answer but at the same time learn a
+ whole lot more.
+
+ Alex van den Bogaerdt <alex at ergens.op.het.net>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4/May/99 19990504.23 8
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.pod
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.pod (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.pod Sat Jul 13 18:46:08 2002
@@ -0,0 +1,363 @@
+=head1 NAME
+
+Binary Decimal Hexadecimal - How does it wok
+
+=head1 DESCRIPTION
+
+Most people use the decimal numbering system. This system uses ten
+symbols to represent numbers. When those ten symbols are used up, they
+start all over again and increment the position just before this. The
+digit 0 is only shown if it is the only symbol in the sequence, or if
+it is not the first one.
+
+If this sounds as crypto to you, this is what I've said in numbers:
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+
+and so on.
+
+Each time the digit nine should be incremented, it is reset to 0 and the
+position before is incremented. Then number 9 can be seen as "00009" and
+when we should increment 9, we reset it to zero and increment the digit
+just before the 9 so the number becomes "00010". For zero's we write a
+space if it is not the only digit (so: number 0) and if it is the first
+digit: "00010" -> " 0010" -> " 010" -> " 10". It is not " 1 ".
+
+This was pretty basic, you already knew this. Why did I tell it ?
+Well, computers do not represent numbers with 10 different digits. They
+know of only two different symbols, being 0 and 1. Apply the same rules
+to this set of digits and you get the binary numbering system:
+
+ 0
+ 1
+ 10
+ 11
+ 100
+ 101
+ 110
+ 111
+ 1000
+ 1001
+ 1010
+ 1011
+ 1100
+ 1101
+
+and so on.
+
+If you count the number of rows, you'll see that these are again 14
+different numbers. The numbers are the same and mean the same. It is
+only a different representation. This means that you have to know the
+representation used, or as it is called the numbering system or base.
+Normally if we do not speak about the numbering system used, we're
+using the decimal system. If we are talking about another numbering
+system, we'll have to make that clear. There are a few wide-spread
+methods to do so. One common form is to write 1010(2) which means that
+you wrote down a number in the binary form. It is the number ten.
+If you would write 1010 it means the number one thousand and ten.
+
+In books, another form is most used. It uses subscript (little chars,
+more or less in between two rows). You can leave out the parentheses
+in that case and write down the number in normal characters followed
+with a little two just behind it.
+
+The numbering system used is also called the base. We talk of the number
+1100 base 2, the number 12 base 10.
+
+For the binary system, is is common to write leading zero's. The numbers
+are written down in series of four, eight or sixteen depending on the
+context.
+
+We can use the binary form when talking to computers (...programming...)
+but the numbers will have large representations. The number 65535 would
+be written down as 1111111111111111(2) which is 16 times the digit 1.
+This is difficult and prone to errors. Therefore we normally would use
+another base, called hexadecimal. It uses 16 different symbols. First
+the symbols from the decimal system are used, thereafter we continue
+with the alfabetic characters. We get 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A,
+B, C, D, E and F. This system is choosen because the hexadecimal form
+can be converted into the binary system very easy (and back).
+
+There is yet another system in use, called the octal system. This was
+more common in the old days but not anymore. You will find it in use
+on some places so get used to it. The same story applies, but now with
+only eight different symbols.
+
+ Binary (2)
+ Octal (8)
+ Decimal (10)
+ Hexadecimal (16)
+
+ (2) (8) (10) (16)
+ 00000 0 0 0
+ 00001 1 1 1
+ 00010 2 2 2
+ 00011 3 3 3
+ 00100 4 4 4
+ 00101 5 5 5
+ 00110 6 6 6
+ 00111 7 7 7
+ 01000 10 8 8
+ 01001 11 9 9
+ 01010 12 10 A
+ 01011 13 11 B
+ 01100 14 12 C
+ 01101 15 13 D
+ 01110 16 14 E
+ 01111 17 15 F
+ 10000 20 16 10
+ 10001 21 17 11
+ 10010 22 18 12
+ 10011 23 19 13
+ 10100 24 20 14
+ 10101 25 21 15
+
+Most computers used nowadays are using bytes of eight bits. This means
+that they store eight bits at a time. You can see why the octal system
+is not the most preferred for that: You'd need three digits to represent
+the eight bits and this means that you'd have to use one complete digit
+to represent only two bits (2+3+3=8). This is a waste. For hexadecimal
+digits, you need only two digits which are used completely:
+
+ (2) (8) (10) (16)
+ 11111111 377 255 FF
+
+You can see why binary and hexadecimal can be converted quickly:
+For each hexadecimal digit there are exactly four binary digits.
+Take a binary number. Each time take four digits from the right and make
+a hexadecimal digit from it (see the table above). Stop when there are
+no more digits.
+Other way around: Take a hexadecimal number. For each digit, write down
+its binary equivalent.
+
+Computers (or rather the parsers running on them) would have a hard time
+converting a number like 1234(16). Therefore hexadecimal numbers get a
+prefix. This prefix depends on the language you're writing in. Some of
+the prefixes are "0x" for C, "$" for pascal, "#" for HTML.
+It is common to assume that if a number starts with a zero, it is octal.
+It does not matter what is used as long as you know what it is.
+I will use "0x" for hexadecimal, "%" for binary and "0" for octal.
+The following numbers are all the same, just the way they are written is
+different: 021 0x11 17 %00010001
+
+To do arithmetics and conversions you need to understand one more thing.
+It is something you already know but perhaps you do not "see" it yet:
+
+If you write down 1234, (so it is decimal) you are talking about the
+number one thousand, two hundred and thirty four. In sort of a formula:
+
+ 1 * 1000 = 1000
+ 2 * 100 = 200
+ 3 * 10 = 30
+ 4 * 1 = 4
+
+This can also be written as:
+
+ 1 * 10^3
+ 2 * 10^2
+ 3 * 10^1
+ 4 * 10^0
+
+where ^ means "to the power of".
+
+We are using the base 10, and the positions 0,1,2 and 3.
+The right-most position should NOT be multiplied with 10. The second
+from the right should be multiplied one time with 10. The third from
+the right is multiplied with 10 two times. This continues for whatever
+positions are used.
+
+It is the same in all other representations:
+
+0x1234 will be
+
+ 1 * 16^3
+ 2 * 16^2
+ 3 * 16^1
+ 4 * 16^0
+
+01234 would be
+
+ 1 * 8^3
+ 2 * 8^2
+ 3 * 8^1
+ 4 * 8^0
+
+This example can not be done for binary as that system can only use two
+symbols. Another example:
+
+%1010 would be
+
+ 1 * 2^3
+ 0 * 2^2
+ 1 * 2^1
+ 0 * 2^0
+
+It would have been more easy to convert it to its hexadecimal form and
+just translate %1010 into 0xA. After a while you get used to it. You will
+not need to do any calculations anymore but just know that 0xA means 10.
+
+To convert a decimal number into a hexadecimal one you could use the next
+method. It will take some time to be able to do the estimates but it will
+be more and more easy when you use the system more frequent. Another way
+is presented to you thereafter.
+
+First you will need to know how many positions will be used in the other
+system. To do so, you need to know the maximum numbers. Well, that's not
+so hard as it looks. In decimal, the maximum number that you can form
+with two digits is "99". The maximum for three: "999". The next number
+would need an extra position. Reverse this idea and you will see that
+the number can be found by taking 10^3 (10*10*10 is 1000) minus 1 or
+10^2 minus one.
+
+This can be done for hexadecimal too:
+
+ 16^4 = 0x10000 = 65536
+ 16^3 = 0x1000 = 4096
+ 16^2 = 0x100 = 256
+ 16^1 = 0x10 = 16
+
+If a number is smaller than 65536 it will thus fit in four positions.
+If the number is bigger than 4095, you will need to use position 4.
+How many times can you take 4096 from the number without going below
+zero is the first digit you write down. This will always be a number
+from 1 to 15 (0x1 to 0xF). Do the same for the other positions.
+
+Number is 41029. It is smaller than 16^4 but bigger than 16^3-1. This
+means that we have to use four positions.
+We can subtract 16^3 from 41029 ten times without going below zero.
+The leftmost digit will be "A" so we have 0xA????.
+The number is reduced to 41029 - 10*4096 = 41029-40960 = 69.
+69 is smaller than 16^3 but not bigger than 16^2-1. The second digit
+is therefore "0" and we know 0xA0??.
+69 is smaller than 16^2 and bigger than 16^1-1. We can subtract 16^1
+(which is just plain 16) four times and write down "4" to get 0xA04?.
+Take 64 from 69 (69 - 4*16) and the last digit is 5 --> 0xA045.
+
+The other method builds the number from the right. Take again 41029.
+Divide by 16 and do not use fractions (only whole numbers).
+
+ 41029 / 16 is 2564 with a remainder of 5. Write down 5.
+ 2564 / 16 is 160 with a remainder of 4. Write the 4 before the 5.
+ 160 / 16 is 10 with no remainder. Prepend 45 with 0.
+ 10 / 16 is below one. End here and prepend 0xA. End up with 0xA045.
+
+Which method to use is up to you. Use whatever works for you. Personally
+I use them both without being able to tell what method I use in each
+case, it just depends on the number, I think. Fact is, some numbers
+will occur frequently while programming, if the number is close then
+I will use the first method (like 32770, translate into 32768 + 2 and
+just know that it is 0x8000 + 0x2 = 0x8002).
+
+
+For binary the same approach can be used. The base is 2 and not 16,
+and the number of positions will grow rapidly. Using the second method
+has the advantage that you can see very simple if you should write down
+a zero or a one: if you divide by two the remainder will be zero if it
+was an even number and one if it was an odd number:
+
+ 41029 / 2 = 20514 remainder 1
+ 20514 / 2 = 10257 remainder 0
+ 10257 / 2 = 5128 remainder 1
+ 5128 / 2 = 2564 remainder 0
+ 2564 / 2 = 1282 remainder 0
+ 1282 / 2 = 641 remainder 0
+ 641 / 2 = 320 remainder 1
+ 320 / 2 = 160 remainder 0
+ 160 / 2 = 80 remainder 0
+ 80 / 2 = 40 remainder 0
+ 40 / 2 = 20 remainder 0
+ 20 / 2 = 10 remainder 0
+ 10 / 2 = 5 remainder 0
+ 5 / 2 = 2 remainder 1
+ 2 / 2 = 1 remainder 0
+ 1 / 2 below 0 remainder 1
+
+Write down the results from right to left: %1010000001000101
+
+Group by four:
+
+ %1010000001000101
+ %101000000100 0101
+ %10100000 0100 0101
+ %1010 0000 0100 0101
+
+Convert into hexadecimal: 0xA045
+
+Group %1010000001000101 by three and convert into octal:
+
+ %1010000001000101
+ %1010000001000 101
+ %1010000001 000 101
+ %1010000 001 000 101
+ %1010 000 001 000 101
+ %1 010 000 001 000 101
+ %001 010 000 001 000 101
+ 1 2 0 1 0 5 --> 0120105
+
+ So: %1010000001000101 = 0120105 = 0xA045 = 41029
+ Or: 1010000001000101(2) = 120105(8) = A045(16) = 41029(10)
+ Or: 1010000001000101(2) = 120105(8) = A045(16) = 41029
+
+
+At first while adding numbers, you'll convert them to their decimal
+form and then back into their original form after doing the addition.
+If you use the other numbering system often, you will see that you'll
+be able to do arithmetics in the base that is used.
+In any representation it is the same, add the numbers on the right,
+write down the rightmost digit from the result, remember the other
+digits and use them in the next round. Continue with the second digits
+from the right and so on:
+
+ %1010 + %0111 --> 10 + 7 --> 17 --> %00010001
+
+will become
+
+ %1010
+ %0111 +
+ ||||
+ |||+-- add 0 + 1, result is 1, nothing to remember
+ ||+--- add 1 + 1, result is %10, write down 0 and remember 1
+ |+---- add 0 + 1 + 1(remembered), result = 0, remember 1
+ +----- add 1 + 0 + 1(remembered), result = 0, remember 1
+ nothing to add, 1 remembered, result = 1
+ --------
+ %10001 is the result, I like to write it as %00010001
+
+For low values, try to do the calculations yourself, check them with
+a calculator. The more you do the calculations yourself, the more you
+find that you didn't make mistakes. In the end, you'll do calcula in
+other bases as easy as you do in decimal.
+
+When the numbers get bigger, you'll have to realise that a computer is
+not called a computer just to have a nice name. There are many different
+calculators available. Use them. For unix you could use "bc" which is
+called so as it is short for Binary Calculator. It calculates not only
+in decimal, but in all bases you'll ever use (among them Binary).
+
+For people on Windows:
+Start the calculator (start->programs->accessories->calculator)
+and if necessary click view->scientific. You now have a scientific
+calculator and can compute in binary or hexadecimal.
+
+=head1 AUTHOR
+
+I hope you enjoyed the examples and their descriptions. If you do, help
+other people by pointing them to this document when they are asking
+basic questions. They will not only get their answer but at the same
+time learn a whole lot more.
+
+Alex van den Bogaerdt
+<alex at ergens.op.het.net>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDp.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDp.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDp.html Sat Jul 13 18:46:08 2002
@@ -0,0 +1,210 @@
+ <HTML>
+ <HEAD>
+ <TITLE>RRDp - Attach rrdtool from within a perl script via a set of pipes;
+
+</TITLE>
+ </HEAD>
+
+ <BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+ <LI><A HREF="#NAME">NAME</A>
+ <LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+ <LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+ <LI><A HREF="#EXAMPLE">EXAMPLE</A>
+ <LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+ <LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME
+
+</A></H1>
+RRDp - Attach rrdtool from within a perl script via a set of pipes;
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS
+
+</A></H1>
+use <STRONG>RRDp</STRONG>
+
+
+
+
+<P>
+
+<STRONG>RRDp::start</STRONG> <EM>path to rrdtool executable</EM>
+
+
+
+
+<P>
+
+<STRONG>RRDp::cmd</STRONG> <EM>rrdtool commandline</EM>
+
+
+
+
+<P>
+
+<CODE>$answer</CODE> = <STRONG>RRD::read</STRONG>
+
+
+
+
+<P>
+
+<CODE>$status</CODE> = <STRONG>RRD::end</STRONG>
+
+
+
+
+<P>
+
+<STRONG>$RRDp::user</STRONG>, <STRONG>$RRDp::sys</STRONG>, <STRONG>$RRDp::real</STRONG>
+
+
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION
+
+</A></H1>
+With this module you can safely communicate with the rrdtool.
+
+
+<P>
+
+After every <STRONG>RRDp::cmd</STRONG> you have to issue an <STRONG>RRDp::read</STRONG> command to get
+<STRONG>rrdtool</STRONG>s answer to your command. The answer is returned as a pointer, in order to
+speed things up. If the last command did not return any data, <STRONG>RRDp::read</STRONG> will return an undefined variable.
+
+
+<P>
+
+If you import the PERFORMANCE variables into your namespace, you can access
+rrdtools internal performance measurements.
+
+
+<P>
+
+<DL>
+<DT><STRONG><A NAME="item_use">use RRDp
+
+</A></STRONG><DD>
+Load the RRDp::pipe module.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_RRDp">RRDp::start path to rrdtool executable
+
+</A></STRONG><DD>
+start rrdtool. The argument must be the path to the rrdtool executable
+
+
+<P>
+
+<DT><STRONG><A NAME="item_RRDp">RRDp::cmd rrdtool commandline
+
+</A></STRONG><DD>
+pass commands on to rrdtool. check the rrdtool documentation for more info
+on the rrdtool commands.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__answer">$answer = RRDp::read
+
+</A></STRONG><DD>
+read rrdtools response to your command. Note that the <CODE>$answer</CODE>
+variable will only contain a pointer to the returned data. The reason for
+this is, that rrdtool can potentially return quite excessive amounts of
+data and we don't want to copy this around in memory. So when you want to
+access the contents of <CODE>$answer</CODE> you have to use
+<CODE>$$answer</CODE> which dereferences the variable.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__status">$status = RRDp::end
+
+</A></STRONG><DD>
+terminates rrdtool and returns rrdtools status ...
+
+
+<P>
+
+<DT><STRONG><A NAME="item__RRDp_user_">$RRDp::user, $RRDp::sys, $RRDp::real
+
+</A></STRONG><DD>
+these variables will contain totals of the user time, system time and real
+time as seen by rrdtool. User time is the time rrdtool is running, System
+time is the time spend in system calls and real time is the total time
+rrdtool has been running.
+
+
+<P>
+
+The difference between user + system and real is the time spent waiting for
+things like the hard disk and new input from the perl script.
+
+
+<P>
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="EXAMPLE">EXAMPLE
+
+</A></H1>
+<PRE> use RRDp;
+ RRDp::start "/usr/local/bin/rrdtool";
+ RRDp::cmd qw(create demo.rrd --step 100
+ DS:in:GAUGE:100:U:U
+ RRA:AVERAGE:0.5:1:10);
+ $answer = RRDp::read;
+ print $$answer;
+ ($usertime,$systemtime,$realtime) = ($RRDp::user,$RRDp::sys,$RRDp::real);
+</PRE>
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO
+
+</A></H1>
+For more information on how to use rrdtool, check the manpages.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR
+
+</A></H1>
+Tobias Oetiker <A
+HREF="MAILTO:<oetiker at ee.ethz.ch>"><oetiker at ee.ethz.ch></A>
+
+
+<P>
+
+</DL>
+ </BODY>
+
+ </HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.1
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.1 (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.1 Sat Jul 13 18:46:08 2002
@@ -0,0 +1,313 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+''' \*(L" and \*(R", except that they are used on ".xx" lines,
+''' such as .IP and .SH, which do another additional levels of
+''' double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH RRDCREATE 1 "19990426.22" "21/Apr/99" "rrdtool"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+rrdtool create \- Set up a new Round Robin Database
+.SH "SYNOPSIS"
+\fBrrdtool\fR \fBcreate\fR \fIfilename\fR
+[\fB--start\fR|\fB\-b\fR\ \fIstart\ time\fR]
+[\fB--step\fR|\fB\-s\fR\ \fIstep\fR]
+[\fBDS:\fR\fIds-name\fR\fB:\fR\fIDST\fR\fB:\fR\fIheartbeat\fR\fB:\fR\fImin\fR\fB:\fR\fImax\fR]
+[\fBRRA:\fR\fICF\fR\fB:\fR\fIxff\fR\fB:\fR\fIsteps\fR\fB:\fR\fIrows\fR]
+.SH "DESCRIPTION"
+The create function of the rrd tool lets you set up new
+Round Robin Database (\fBRRD\fR) files.
+The file is created at its final, full size and filled
+with \fI*UNKNOWN*\fR data.
+.Ip "\fIfilename\fR" 8
+The name of the \fB\s-1RRD\s0\fR you want to create. \fB\s-1RRD\s0\fR files should end
+with the extension \fI.rrd\fR. However, \fBrrdtool\fR will accept any
+filename.
+.Ip "\fB--start\fR|\fB\-b\fR \fIstart time\fR (default: current time)" 8
+Specifies the time in seconds since 1970-01-01 \s-1UTC\s0 when the first
+value should be added to the \fB\s-1RRD\s0\fR. \fBrrdtool\fR will not accept
+any data timed before or at the time specified.
+.Sp
+Negative input is treated as current time minus the specified number
+of seconds. See also \s-1AT\s0\-\s-1STYLE\s0 \s-1TIME\s0 \s-1SPECIFICATION\s0 section in the
+\fIrrdfetch\fR documentation for alternative ways to specify time.
+.Ip "\fB--step\fR|\fB\-s\fR \fIstep\fR (default: 300 seconds)" 8
+Specifies the base interval in seconds with which data will be fed
+into the \fB\s-1RRD\s0\fR.
+.Ip "\fB\s-1DS\s0:\fR\fIds-name\fR\fB:\fR\fI\s-1DST\s0\fR\fB:\fR\fIheartbeat\fR\fB:\fR\fImin\fR\fB:\fR\fImax\fR" 8
+A single \fB\s-1RRD\s0\fR can accept input from several data sources (\fB\s-1DS\s0\fR).
+(e.g. Incoming and Outgoing traffic on a specific communication
+line). With the \fB\s-1DS\s0\fR configuration option you must define some basic
+properties of each data source you want to use to feed the \fB\s-1RRD\s0\fR.
+.Sp
+\fIds-name\fR is the name you will use to reference this particular data
+source from an \fB\s-1RRD\s0\fR. A \fIds-name\fR must be 1 to 19 characters long in
+the characters [a-zA\-Z0-9_].
+.Sp
+\fI\s-1DST\s0\fR defines the Data Source Type. It can be one of the following:
+\fB\s-1GAUGE\s0\fR this is for things like temperatures or number of people in a
+room. \fB\s-1COUNTER\s0\fR is for continuous incrementing counters like the
+InOctets counter in a router. The \fB\s-1COUNTER\s0\fR data source assumes that
+the counter never decreases, except when a counter overflows. The update
+function takes the overflow into account. The counter is stored as a
+per-second rate. \fB\s-1DERIVE\s0\fR will store the
+the derivative of the line going from the last to the current value of the
+data source. This can be useful for gauges,
+for example, to measure the rate of people
+entering or leaving a room. \fB\s-1ABSOLUTE\s0\fR is for counters which get reset upon reading.
+.Sp
+\fIheartbeat\fR defines the maximum number of seconds that may pass
+between two updates of this data source before the value of the
+data source is assumed to be \fI*\s-1UNKNOWN\s0*\fR.
+.Sp
+\fImin\fR and \fImax\fR are optional entries defining the expected range of
+the data supplied by this data source. If \fImin\fR and/or \fImax\fR are
+defined, any value outside the defined range will be regarded as
+\fI*\s-1UNKNOWN\s0*\fR. If you do not know or care about min and max, set them
+to U for unknown. Note that min and max always refere to the processed values
+of the \s-1DS\s0. For a traffic-\fB\s-1COUNTER\s0\fR type \s-1DS\s0 this would be the max and min
+data-rate expected from the device.
+.Ip "\fB\s-1RRA\s0:\fR\fI\s-1CF\s0\fR\fB:\fR\fIxff\fR\fB:\fR\fIsteps\fR\fB:\fR\fIrows\fR" 8
+The purpose of an \fB\s-1RRD\s0\fR is to store data in the round robin archives
+(\fB\s-1RRA\s0\fR). An archive consists of a number of data values from all the
+defined data-sources (\fB\s-1DS\s0\fR) and is defined with an \fB\s-1RRA\s0\fR line.
+.Sp
+When data is entered into an \fB\s-1RRD\s0\fR, it is first fit into time slots of
+the length defined with the \fB\-s\fR option becoming a \fIprimary data point\fR.
+.Sp
+The data is also consolidated with the consolidation function (\fI\s-1CF\s0\fR)
+of the archive. The following consolidation functions are defined:
+\fB\s-1AVERAGE\s0\fR, \fB\s-1MIN\s0\fR, \fB\s-1MAX\s0\fR, \fB\s-1LAST\s0\fR.
+.Sp
+\fIxff\fR The xfiles factor defines what part of a consolidation interval may
+be made up from \fI*\s-1UNKNOWN\s0*\fR data while the consolidated value is sill
+regarded as known.
+.Sp
+\fIsteps\fR defines how many of these \fIprimary data points\fR are used to
+build a \fIconsolidated data point\fR which then goes into the archive.
+.Sp
+\fIrows\fR defines how many generations of data values are kept in an \fB\s-1RRA\s0\fR.
+.SH "EXAMPLE"
+\f(CWrrdtool create temperature.rrd --step 300 DS:temp:GAUGE:600:-273:5000
+RRA:AVERAGE:0.5:1:1200 RRA:MIN:0.5:12:2400 RRA:MAX:0.5:12:2400
+RRA:AVERAGE:0.5:12:2400\fR
+.PP
+This sets up an \fBRRD\fR called \fItemperature.rrd\fR which accepts one
+temperature value every 300 seconds. If no new data is supplied for
+more than 600 seconds, the temperature becomes \fI*UNKNOWN*\fR. The
+minimum acceptable value is \-273 and the maximum is 5000.
+.PP
+A few archives areas are also defined. The first stores the
+temperatures supplied for 100 hours (1200 * 300 seconds = 100
+hours). The second RRA stores the minimum temperature recorded over
+every hour (12 * 300 seconds = 1 hour), for 100 days (2400 hours). The
+third and the fourth RRA's do the same with the for the maximum and
+average temperature, respectively.
+.SH "AUTHOR"
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
+.rn }` ''
+.IX Title "RRDCREATE 1"
+.IX Name "rrdtool create - Set up a new Round Robin Database"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Item "\fIfilename\fR"
+
+.IX Item "\fB--start\fR|\fB\-b\fR \fIstart time\fR (default: current time)"
+
+.IX Item "\fB--step\fR|\fB\-s\fR \fIstep\fR (default: 300 seconds)"
+
+.IX Item "\fB\s-1DS\s0:\fR\fIds-name\fR\fB:\fR\fI\s-1DST\s0\fR\fB:\fR\fIheartbeat\fR\fB:\fR\fImin\fR\fB:\fR\fImax\fR"
+
+.IX Item "\fB\s-1RRA\s0:\fR\fI\s-1CF\s0\fR\fB:\fR\fIxff\fR\fB:\fR\fIsteps\fR\fB:\fR\fIrows\fR"
+
+.IX Header "EXAMPLE"
+
+.IX Header "AUTHOR"
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.html Sat Jul 13 18:46:09 2002
@@ -0,0 +1,594 @@
+ <HTML>
+ <HEAD>
+ <TITLE>graph - Create a graph based on data from one or several RRD
+
+</TITLE>
+ </HEAD>
+
+ <BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+ <LI><A HREF="#NAME">NAME</A>
+ <LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+ <LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+ <LI><A HREF="#NOTE">NOTE</A>
+ <LI><A HREF="#NOTE_2">NOTE 2</A>
+ <LI><A HREF="#NOTE_3">NOTE 3</A>
+ <LI><A HREF="#EXAMPLE">EXAMPLE</A>
+ <LI><A HREF="#AUTHOR">AUTHOR</A>
+ <LI><A HREF="#REFERENCES">REFERENCES</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME
+
+</A></H1>
+rrdtool graph - Create a graph based on data from one or several RRD
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS
+
+</A></H1>
+<STRONG>rrdtool</STRONG> <STRONG>graph</STRONG> <EM>filename</EM>
+
+[<STRONG>-s</STRONG>|<STRONG>--start</STRONG> <EM>seconds</EM>]
+
+[<STRONG>-e</STRONG>|<STRONG>--end</STRONG> <EM>seconds</EM>]
+
+[<STRONG>-x</STRONG>|<STRONG>--x-grid</STRONG> <EM>x-axis grid and label</EM>]
+
+[<STRONG>-y</STRONG>|<STRONG>--y-grid</STRONG> <EM>y-axis grid and label</EM>]
+
+[<STRONG>-v</STRONG>|<STRONG>--vertical-label</STRONG> <EM>text</EM>]
+
+[<STRONG>-w</STRONG>|<STRONG>--width</STRONG> <EM>pixels</EM>]
+
+[<STRONG>-h</STRONG>|<STRONG>--height</STRONG> <EM>pixels</EM>]
+
+[<STRONG>-i</STRONG>|<STRONG>--interlaced</STRONG>]
+
+[<STRONG>-o</STRONG>|<STRONG>--logarithmic</STRONG>]
+
+[<STRONG>-u</STRONG>|<STRONG>--upper-limit</STRONG> <EM>value</EM>]
+
+[<STRONG>-l</STRONG>|<STRONG>--lower-limit</STRONG> <EM>value</EM>]
+
+[<STRONG>-r</STRONG>|<STRONG>--rigid</STRONG>]
+
+[<STRONG>-b</STRONG>|<STRONG>--base</STRONG> <EM>value</EM>]
+
+[<STRONG>-c</STRONG>|<STRONG>--color</STRONG> <EM>COLORTAG</EM><STRONG>#</STRONG><EM>rrggbb</EM>]
+
+[<STRONG>-t</STRONG>|<STRONG>--title</STRONG> <EM>title</EM>]
+
+[<STRONG>DEF:</STRONG><EM>vname</EM><STRONG>=</STRONG><EM>rrd</EM><STRONG>:</STRONG><EM>ds-name</EM><STRONG>:</STRONG><EM>CF</EM>]
+
+[<STRONG>CDEF:</STRONG><EM>vname</EM><STRONG>=</STRONG><EM>rpn-expression</EM>]
+
+[<STRONG>PRINT:</STRONG><EM>vname</EM><STRONG>:</STRONG><EM>CF</EM><STRONG>:</STRONG><EM>format</EM>]
+
+[<STRONG>GPRINT:</STRONG><EM>vname</EM><STRONG>:</STRONG><EM>CF</EM><STRONG>:</STRONG><EM>format</EM>]
+
+[<STRONG>COMMENT:</STRONG><EM>text</EM>]
+
+[<STRONG>HRULE:</STRONG><EM>value</EM><STRONG>#</STRONG><EM>rrggbb</EM>[<STRONG>:</STRONG><EM>legend</EM>]]
+
+[<STRONG>VRULE:</STRONG><EM>time</EM><STRONG>#</STRONG><EM>rrggbb</EM>[<STRONG>:</STRONG><EM>legend</EM>]]
+
+[<STRONG>LINE</STRONG>{<STRONG>1</STRONG>|<STRONG>2</STRONG>|<STRONG>3</STRONG>}<STRONG>:</STRONG><EM>vname</EM>[<STRONG>#</STRONG><EM>rrggbb</EM>[<STRONG>:</STRONG><EM>legend</EM>]]]
+
+[<STRONG>AREA:</STRONG><EM>vname</EM>[<STRONG>#</STRONG><EM>rrggbb</EM>[<STRONG>:</STRONG><EM>legend</EM>]]]
+
+[<STRONG>STACK:</STRONG><EM>vname</EM>[<STRONG>#</STRONG><EM>rrggbb</EM>[<STRONG>:</STRONG><EM>legend</EM>]]]
+
+
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION
+
+</A></H1>
+The <STRONG>graph</STRONG> functions main purpose is to create graphical representations of the data
+stored in one or several <STRONG>RRD</STRONG>s. Apart from generating graphs, it can also extract numerical reports.
+
+
+<P>
+
+<DL>
+<DT><STRONG><A NAME="item_filename">filename
+
+</A></STRONG><DD>
+The name of the graph to generate. Since <STRONG>rrdtool</STRONG> outputs GIF's, it's recommended that the filename end in <EM>.gif</EM>.
+<STRONG>rrdtool</STRONG> does not enforce this, however. If the <EM>filename</EM>
+is et to '-' the gif file will be written to standard out. All other output
+will get supressd.
+
+
+<P>
+
+If no graph functions are called, the graph will not be created.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__s_start">-s|--start seconds (default -24*3600)
+
+</A></STRONG><DD>
+The time when the graph should begin. Time in seconds since epoch
+(1970-01-01) is required. Negative numbers are relative to the end time. By
+default one day worth of data will be graphed. See also AT-STYLE TIME
+SPECIFICATION section in the <EM>rrdfetch</EM>
+documentation for alternative ways to specify start time.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__e_end">-e|--end seconds (default current time)
+
+</A></STRONG><DD>
+The time when the graph should end. Time in seconds since epoch. See also
+AT-STYLE TIME SPECIFICATION section in the <EM>rrdfetch</EM>
+documentation for alternative ways to specify end time.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__x_x_grid">-x|--x-grid x-axis grid and label (default autoconfigure)
+
+</A></STRONG><DD>
+The x-axis label is quite complex to configure. So if you don't have very
+special needs, you can relay on the autoconfiguration to get this right.
+
+
+<P>
+
+The x-axis label is configured, using the following format:
+
+
+<P>
+
+<EM>GTM</EM><STRONG>:</STRONG><EM>GST</EM><STRONG>:</STRONG><EM>MTM</EM><STRONG>:</STRONG><EM>MST</EM><STRONG>:</STRONG><EM>LTM</EM>:<EM>LST</EM><STRONG>:</STRONG><EM>LPR</EM><STRONG>:</STRONG><EM>LFM</EM>
+
+
+
+
+<P>
+
+You have to configure three elements making up the x-axis labels and grid.
+The base grid (<EM>G??</EM>), the major grid (<EM>M??</EM>) and the labels (<EM>L??</EM>). The configuration is based on the idea that you first specify a well
+known amount of time (<EM>?TM</EM>) and then say how many times it has to pass between each grid line or
+label (<EM>?ST</EM>). For the label you have to define two additional items: The precision of
+the label in seconds (<EM>LPR</EM>) and the strftime format used to generate the text of the label (<EM>LFM</EM>).
+
+
+<P>
+
+The <EM>?TM</EM> elements must be one of the following keywords: <STRONG>SECOND</STRONG>,
+<STRONG>MINUTE</STRONG>, <STRONG>HOUR</STRONG>, <STRONG>DAY</STRONG>, <STRONG>WEEK</STRONG>, <STRONG>MONTH</STRONG> or <STRONG>YEAR</STRONG>.
+
+
+<P>
+
+If you wanted a graph with a base grid every 10 minutes and a major one
+every hour, with labels every hour you would use the following x-axis
+definition.
+
+
+<P>
+
+<CODE>MINUTE:10:HOUR:1:HOUR:1:0:%X</CODE>
+
+
+
+
+<P>
+
+The precision in this example is 0 because the <CODE>%X</CODE> format is
+exact. If the label was the name of the day, we would have had a precision
+of 24 hours, because when you say something like 'Monday' you mean the
+whole day and not Monday morning 00:00. Thus the label should be positioned
+at noon. By defining a precision of 24 hours or rather 86400 seconds, you
+make sure that this happens.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__y_y_grid">-y--y-grid grid step:label factor (default autoconfigure)
+
+</A></STRONG><DD>
+Makes vertical grid lines appear at <EM>grid step</EM> interval. Every
+<EM>label factor</EM> gridstep, a major grid line is printed, along with label showing the value
+of the grid line.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__v_vertical_label">-v|--vertical-label text
+
+</A></STRONG><DD>
+vertical label on the left side of the graph. This is normally used to
+specify the units used.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__w_width">-w|--width pixels (default 400 pixel)
+
+</A></STRONG><DD>
+Width of the drawing area within the graph. This affects the size of the
+gif.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__h_height">-h|--height pixels (default 100 pixel)
+
+</A></STRONG><DD>
+Width of the drawing area within the graph. This affects the size of the
+gif.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__i_interlaced">-i|--interlaced (default: false)
+
+</A></STRONG><DD>
+If you set this option, then the resulting GIF will be interlaced. Most web
+browsers display these incrementally as they load. If you do not use this
+option, the GIFs default to being progressive scanned. The only effect of
+this option is to control the format of the GIF on disk. It makes no
+changes to the layout or contents of the graph.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__u_upper_limit">-u|--upper-limit value (default autoconfigure)
+
+</A></STRONG><DD>
+The maximum value to be graphed. By default This will be autoconfigured
+from the data you select with the graphing functions.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__l_lower_limit">-l|--lower-limit value (default autoconfigure)
+
+</A></STRONG><DD>
+The minimum value to be graphed. By default This will be autoconfigured
+from the data you select with the graphing functions.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__r_rigid">-r|--rigid
+
+</A></STRONG><DD>
+rigid boundaries mode. Normally rrdgraph will automatically expand the
+lower and upper limit if the graph contains a value outside the valid
+range. With the r option you can disable this behavior
+
+
+<P>
+
+<DT><STRONG><A NAME="item__b_base">-b|--base value
+
+</A></STRONG><DD>
+if you are graphing memmory (and NOT network traffic) this switch should be
+set to 1024 so that one Kb is 1024 byte. For traffic measurement, 1 kb/s is
+1000 b/s.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__o_logarithmic">-o|--logarithmic
+
+</A></STRONG><DD>
+logarithmic y-axis scaling
+
+
+<P>
+
+<DT><STRONG><A NAME="item__c_color">-c|--color COLORTAG#rrggbb (default colors)
+
+</A></STRONG><DD>
+override the colors for the standard elements of the graph. The <EM>COLORTAG</EM>
+must be one of the following symbolic names: <STRONG>BACK</STRONG> ground, <STRONG>CANVAS</STRONG>,
+<STRONG>SHADEA</STRONG> left/top border, <STRONG>SHADEB</STRONG> right/bottom border, <STRONG>GRID</STRONG>, <STRONG>MGRID</STRONG>
+major grid, <STRONG>FONT</STRONG>, <STRONG>FRAME</STRONG> and axis of the graph or <STRONG>ARROW</STRONG>. This option can be called multiple times to set several colors.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__t_title">-t|--title text (default no title)
+
+</A></STRONG><DD>
+Define a title to be written into the graph
+
+
+<P>
+
+<DT><STRONG><A NAME="item_DEF">DEF:vname=rrd:ds-name:CF
+
+</A></STRONG><DD>
+Define virtual name for a data source. This name can then be used in the
+functions explained below. The DEF call automatically chooses an <STRONG>RRA</STRONG> which provides data in a resolution appropriate for the size of the graph
+to be drawn. Ideally this means that one data point from the <STRONG>RRA</STRONG> should be represented by one pixel in the graph. If the resolution of the <STRONG>RRA</STRONG> is higher than the resolution of the graph, the data in the RRA will be
+consolidated according to the consolidation function (<EM>CF</EM>) chosen.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_CDEF">CDEF:vname=rpn-expression
+
+</A></STRONG><DD>
+Create a new virtual data source by evaluating a mathematical expression,
+specified in Reverse Polish Notation (RPN). If you have ever used a
+traditional HP calculator you already know RPN. The idea behind RPN
+notation is, that you have a stack and push your data onto this stack. When
+ever you execute an operation, it takes as many data values from the stack
+as needed. The pushing of data is implicit, so when ever you specify a
+number or a variable, it gets pushed automatically.
+
+
+<P>
+
+If this is all a big load of incomprehensible words for you, maybe an
+example helps (a more complete explanation is given in [1]): The expression
+vname+3/2 becomes vname,3,2,/,+ in RPN. First the three values get pushed
+onto the stack (which now contains (the current value of) vname, a 3 and a
+2). Then the / operator pops two values from the stack (3 and 2), divides
+the first argument by the second (3/2) and pushes the result (1.5) back
+onto the stack. Then the + operator pops two values (vname and 1.5) from
+the stack; both values are added up and the result gets pushes back onto
+the stack. In the end there is only one value left on the stack: The result
+of the expression.
+
+
+<P>
+
+The <EM>rpn-expression</EM> in the <STRONG>CDEF</STRONG> function takes both, constant values as well as <EM>vname</EM> variables. The following operators can be used on these values:
+
+
+<P>
+
+<DL>
+<DT><STRONG><A NAME="item__">+, -, *, /
+
+</A></STRONG><DD>
+pops two values from the stack applies the selected operator and pushes the
+result back onto the stack.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_SIN">SIN, COS, LOG, EXP
+
+</A></STRONG><DD>
+pops one value from the stack, applies the selected function and pushes the
+result back onto the stack.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_LT">LT, LE, GT, GE, EQ
+
+</A></STRONG><DD>
+pops two values from the stack, compares them according to the selected
+condition and pushes either 1 back onto the stack if the condition is true
+and 0 if the condition was not true.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_IF">IF
+
+</A></STRONG><DD>
+pops three values from the stack. If the last value is not 0, the second
+value will be pushed back onto the stack, otherwise the first value is
+pushed back.
+
+
+<P>
+
+If the stack contains the values A, B, C, D, E are presently on the stack,
+the IF operator will pop the values E D and C of the stack. It will look at
+C and if it is not 0 it will push D back onto the stack, otherwise E will
+be sent back to the stack.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_UN">UN
+
+</A></STRONG><DD>
+Pops one value of the stack, if it is <EM>*UNKNOWN*</EM>, 1 will be pushed back otherwise 0.
+
+
+<P>
+
+</DL>
+Please note that you may only use <EM>vname</EM> variables that you previously defined by either <STRONG>DEF</STRONG> or <STRONG>CDEF</STRONG>. Furthermore, as of this writing (version 0.99.25), you must use at least
+one <EM>vname</EM>
+per expression, that is ``CDEF:fourtytwo=2,40,+'' will yield an error
+message but not a <EM>vname</EM> fourtytwo that's always equal to 42.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_PRINT">PRINT:vname:CF:format
+
+</A></STRONG><DD>
+Calculate the chosen consolidation function <EM>CF</EM> over the data-source variable <EM>vname</EM> and <CODE>printf</CODE> the result to stdout using <EM>format</EM>.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_GPRINT">GPRINT:vname:CF:format
+
+</A></STRONG><DD>
+Same as <STRONG>PRINT</STRONG> but the result is printed into the graph below the legend.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_COMMENT">COMMENT:text
+
+</A></STRONG><DD>
+Like <STRONG>GPRINT</STRONG> but the <EM>text</EM> is simply printed into the graph.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_HRULE">HRULE:value#rrggbb[:legend]
+
+</A></STRONG><DD>
+Draw a horizontal rule into the graph and optionally add a legend
+
+
+<P>
+
+<DT><STRONG><A NAME="item_VRULE">VRULE:time#rrggbb[:legend]
+
+</A></STRONG><DD>
+Draw a vertical rule into the graph and optionally add a legend
+
+
+<P>
+
+<DT><STRONG><A NAME="item_LINE">LINE{1|2|3}:vname[#rrggbb[:legend]]
+
+</A></STRONG><DD>
+Plot for the requested data, using the color specified. Write a legend into
+the graph. The 3 possible keywords <STRONG>LINE1</STRONG>, <STRONG>LINE2</STRONG>, and <STRONG>LINE3</STRONG>
+generate increasingly wide lines. If no color is defined, the drawing is
+done 'blind' this is useful in connection with the
+<STRONG>STACK</STRONG> function when you want to ADD the values of two data-sources without
+showing it in the graph.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_AREA">AREA:vname[#rrggbb[:legend]]
+
+</A></STRONG><DD>
+Does the same as <STRONG>LINE?</STRONG>, but the area between 0 and the graph will be filled with the color
+specified.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_STACK">STACK:vname[#rrggbb[:legend]]
+
+</A></STRONG><DD>
+Does the same as <STRONG>LINE?</STRONG>, but the graph gets stacked on top of the previous
+<STRONG>LINE?</STRONG>, <STRONG>AREA</STRONG> or <STRONG>STACK</STRONG> graph. Depending on the type of the previous graph, the <STRONG>STACK</STRONG> will be either a <STRONG>LINE?</STRONG> or an <STRONG>AREA</STRONG>. This obviously implies that the first <STRONG>STACK</STRONG> must be preceeded by an
+<STRONG>AREA</STRONG> or <STRONG>LINE?</STRONG> -- you need something to stack something onto in the first place ;)
+
+
+<P>
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="NOTE">NOTE
+
+</A></H1>
+In a ':' in a <EM>legend</EM> argument will mark the end of the legend. To enter a ':' into a legend, the
+colon must be escaped with a backslash '\:'. Beware, that many environments
+look for backslashes themselves, so it may be necessary to write two
+backslashes so that one is passed onto rrd_graph.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="NOTE_2">NOTE 2
+
+</A></H1>
+The text printed below the actual graph can be formated by appending
+special escaped charactes at the end of a text. When ever such a character
+occurs, all pending text is pushed onto the grah acording to the character
+specified.
+
+
+<P>
+
+Valid characters are: <STRONG>j</STRONG> for justified, <STRONG>l</STRONG> for left aligned, <STRONG>r</STRONG>
+for right aligned and <STRONG>c</STRONG> for centered. In the next section there is an example showing how to use
+centered formating.
+
+
+<P>
+
+A special case is COMMENT:\s this inserts some additional vertical space
+before placing the next row of legends.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="NOTE_3">NOTE 3
+
+</A></H1>
+Whenever rrd_graph gets called, it prints a line telling the size of the
+gif it has just created to STDOUT. This line looks like this: XSIZExYSIZE.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="EXAMPLE">EXAMPLE
+
+</A></H1>
+<PRE> rrdtool graph demo.gif --title="Demo Graph" \
+ DEF:cel=demo.rrd:exhaust:AVERAGE \
+ "CDEF:far=cel,32,-,0.55555,*" \
+ LINE2:cel#00a000:"D. Celsius" \
+ LINE2:far#ff0000:"D. Fahrenheit\c"
+</PRE>
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR
+
+</A></H1>
+Tobias Oetiker <A
+HREF="MAILTO:<oetiker at ee.ethz.ch>"><oetiker at ee.ethz.ch></A>
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="REFERENCES">REFERENCES
+
+</A></H1>
+[1] <A
+HREF="http://www.dotpoint.com/xnumber/rpn_or_adl.htm">http://www.dotpoint.com/xnumber/rpn_or_adl.htm</A>
+
+
+
+<P>
+
+</DL>
+ </BODY>
+
+ </HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.html Sat Jul 13 18:46:09 2002
@@ -0,0 +1,1698 @@
+ <HTML>
+ <HEAD>
+ <TITLE>rrdtutorial - Alex van den Bogaerdts RRD Tool tutorial
+
+</TITLE>
+ </HEAD>
+
+ <BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+ <LI><A HREF="#NAME">NAME</A>
+ <LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+ <LI><A HREF="#TUTORIAL">TUTORIAL</A>
+ <UL>
+
+ <LI><A HREF="#Important">Important</A>
+ <LI><A HREF="#What_is_RRDtool_">What is RRDtool ?</A>
+ <LI><A HREF="#What_data_can_be_put_into_an_RDD">What data can be put into an RDD ?</A>
+ <LI><A HREF="#What_can_I_do_with_this_tool_">What can I do with this tool ?</A>
+ <LI><A HREF="#What_if_I_still_have_problems_af">What if I still have problems after reading this document ?</A>
+ <LI><A HREF="#How_will_you_help_me_">How will you help me ?</A>
+ <LI><A HREF="#Your_first_Round_Robin_Database">Your first Round Robin Database</A>
+ <LI><A HREF="#What_has_been_created_">What has been created ?</A>
+ <LI><A HREF="#It_is_time_to_create_some_graphi">It is time to create some graphics</A>
+ <LI><A HREF="#Graphics_with_some_math">Graphics with some math</A>
+ <LI><A HREF="#Graphics_Magic">Graphics Magic</A>
+ <LI><A HREF="#Updates_in_Reality">Updates in Reality</A>
+ <LI><A HREF="#Some_words_on_SNMP">Some words on SNMP</A>
+ <LI><A HREF="#A_Real_World_Example">A Real World Example</A>
+ <LI><A HREF="#Consolidation_Functions">Consolidation Functions</A>
+ <LI><A HREF="#Let_s_review_what_you_now_should">Let's review what you now should know.</A>
+ <LI><A HREF="#Data_Source_Types">Data Source Types</A>
+ <LI><A HREF="#RRD_Tool_under_the_Microscope">RRD Tool under the Microscope</A>
+ <LI><A HREF="#Counter_Wraps">Counter Wraps</A>
+ <LI><A HREF="#Data_Resampling">Data Resampling</A>
+ </UL>
+
+ <LI><A HREF="#WRAPUP">WRAPUP</A>
+ <LI><A HREF="#MAILINGLIST">MAILINGLIST</A>
+ <LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+ <LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME
+
+</A></H1>
+rrdtutorial - Alex van den Bogaerdts RRD Tool tutorial
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION
+
+</A></H1>
+RRDtool is written by Tobias Oetiker <A
+HREF="MAILTO:<oetiker at ee.ethz.ch>"><oetiker at ee.ethz.ch></A> with
+contributions from many people all around the world. This document is
+written by Alex van den Bogaerdt <A
+HREF="MAILTO:<alex at ergens.op.het.net>"><alex at ergens.op.het.net></A> to help
+you understand what RRDtool is and what it can do for you.
+
+
+<P>
+
+The documentation provided with RRDtool can be too technical for some
+people and here we help you to understand the basics in order to prepare
+you to read the documentation yourself. It also explains the general things
+about statistics with a focus on networking.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="TUTORIAL">TUTORIAL
+
+</A></H1>
+<P>
+<HR>
+<H2><A NAME="Important">Important
+
+</A></H2>
+We first have to do some uninteresting reading folks, don't skip this part!
+Later on, in the examples, you need to know the basics.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="What_is_RRDtool_">What is RRDtool ?
+
+</A></H2>
+RRDtool means Round Robin Database tool. Round robin is a technique that
+works with a fixed amount of data, and a pointer to the current element.
+Think of a circle with some dots plotted on the edge, these dots are the
+places where data can be stored. Draw an arrow from the center of the
+circle to one of the dots, this is the pointer. When the current data is
+read or written, the pointer moves to the next element. As we are on a
+circle there is no beginning nor an end, you can go on and on. After a
+while, all the available places will be used and the process automatically
+reuses old locations. RRDtool works with with Round Robin Databases (RRDs).
+It stores and retrieves data from them.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="What_data_can_be_put_into_an_RDD">What data can be put into an RDD ?
+
+</A></H2>
+You name it, it will probably fit. You should be able to measure some value
+at several points in time and provide this to RRDtool. If you can do this,
+RRDtool will probably be able to store it.
+
+
+<P>
+
+Many examples talk about SNMP which is an acronym for Simple Network
+Management Protocol. The ``simple'' is about the protocol, it does not mean
+it is simple to manage a network. After working your way through this
+document, you will know enough to be able to understand what people are
+talking about. For now, just assume SNMP is a way to talk to devices and
+ask those devices about counters they keep. It is the value from those
+counters that are kept in the RRD.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="What_can_I_do_with_this_tool_">What can I do with this tool ?
+
+</A></H2>
+RRDtool originated from MRTG (multi router traffic grapher) which itself
+came from a tiny little script to monitor the performance of a connection
+to the Internet. Since then, MRTG has also been used for several other
+purposes including temperature, speed, voltage, number of printouts and
+many other things. Most likely you will start to use the RRDtool to store
+and process data collected via SNMP. The data will most likely be bytes (or
+bits) transfered from and to a network or a computer. RRDtool lets you
+create a database, store data in it, retrieve that data and create graphs
+in GIF format for display on a web browser. Those GIF images are dependant
+on the data you collected and could be, for instance, an overview of the
+average network usage, or rather the peaks that occurred. It can also be
+used to display tidal waves, solar radiation, power consumption, number of
+visitors at an exibition, noise levels near an airport, temperature on your
+favorite holiday location, temperature in the fridge and whatever you
+imagination can come up with. You need a sensor to measure the data and be
+able to feed the numbers to RRDtool. Many devices have such a sensor.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="What_if_I_still_have_problems_af">What if I still have problems after reading this document ?
+
+</A></H2>
+More exact, after re-reading this document :) It all depends on the kind of
+problems you have. If you are unable to compile the sources and you have a
+fairly common OS, it will probably not be the fault of RRDtool. There may
+be precompiled versions around on the Internet. If they come from trusted
+sources, get one of those. If on the other hand the program works but does
+not give you the expected results, it will be a problem with configuring
+it. Review your configuration and compare it with the examples that follow.
+
+
+<P>
+
+There is a mailing list and an archive of it. Read the list for a few weeks
+and search the archive. It is considered rude to just ask a question
+without reading the list, your problem may already have been solved for
+somebody else and you will be helped without writing a new a message at all
+... This is true for most, if not all, mailing lists and not only for this
+particular list! Look in the documentation that came with RRDtool for the
+location and usage of the list.
+
+
+<P>
+
+I suggest you take a moment to subscribe to the mailing list right now by
+sending an email to <A
+HREF="MAILTO:<rrdtool-users-request at list.ee.ethz.ch>"><rrdtool-users-request at list.ee.ethz.ch></A>
+with a subject of ``subscribe''. If you ever want to leave this list, you
+write an email to the same address but now with a subject of
+``unsubscribe''.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="How_will_you_help_me_">How will you help me ?
+
+</A></H2>
+By giving you some detailed descriptions with detailed examples. It is
+assumed that following the instructions in the order presented will build
+up enough knowledge of the program to experiment for yourself. If it
+doesn't work the first time, don't give up. Reread the stuff that you did
+understand, you may have missed something. By following the examples you
+get some hands-on experience and, even more important, some background
+information of how it works.
+
+
+<P>
+
+You will need to know something about hexadecimal numbers. If you don't
+then start with reading ``bin_dec_hex'' before you continue here.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="Your_first_Round_Robin_Database">Your first Round Robin Database
+
+</A></H2>
+In my opinion the best way to learn something is to actually do it. Why not
+start right now? We will create a database, put some values in it and
+extract this data again. It is expected that you get the same results when
+you try these examples yourself so do that. We will start with some easy
+stuff and compare a car with a router, or compare kilometers (miles if you
+wish) with bits and bytes. It's all the same: Some number over some time.
+
+
+<P>
+
+Assume we have a device that transfers bytes to and from the Internet. This
+device keeps a counter that starts at zero when it is turned on, increasing
+with every byte that is transfered. This counter will have a maximum value,
+if that value is reached and an extra byte is counted, the counter starts
+all over at zero. This is the same as many counters in the world such as
+the mileage counter in a car. Most discussions about networking talk about
+bits per second so lets get used to that right away. Assume a byte is eight
+bits and start to think in bits not bytes. The counter however still counts
+bytes ! In the SNMP world most of the counters are 32 bits. That means they
+are counting from 0 to 4294967295. We will use these values in the
+examples. The device, when asked, returns the current value of the counter.
+We know the time that has passes since we last asked so we now know how
+many bytes have been transfered <CODE>***on</CODE> average*** per second.
+This is not very hard to calculate. First in words, then in calculi:
+
+
+<P>
+
+<OL>
+<LI><STRONG><A NAME="item_">
+
+</A></STRONG>
+Take the current counter, subtract the previous value from it.
+
+
+<P>
+
+<LI><STRONG><A NAME="item_">
+
+</A></STRONG>
+Do the same with the current time and the previous time.
+
+
+<P>
+
+<LI><STRONG><A NAME="item_">
+
+</A></STRONG>
+Divide the outcome of (1) by the outcome of (2), the result is the amount
+of bytes per second. Multiply by eight to get the number of bits per second
+(bps).
+
+
+<P>
+
+<PRE> bps = (counter_now - counter_before) / (time_now - time_before) * 8
+</PRE>
+
+<P>
+
+</OL>
+For some people it may help to translate this to a automobile example: Do
+not try this example, and if you do, don't blame me for the results.
+
+
+<P>
+
+People who are not used to think in kilometers per hour can translate most
+into miles per hour by dividing km by 1.6 (close enough). I will use the
+following abbreviations:
+
+
+<P>
+
+<PRE> M: meter
+ KM: kilometer (= 1000 meters).
+ H: hour
+ S: second
+ KM/H: kilometers per hour
+ M/S: meters per second
+</PRE>
+
+<P>
+
+You're driving a car. At 12:05 you read the counter in the dashboard and it
+tells you that the car has moved 12345 KM until that moment. At 12:10 you
+look again, it reads 12357 KM. This means you have traveled 12 KM in five
+minutes. A scientist would translate that into meters per second and this
+makes a nice comparison towards the problem of (bytes per five minutes)
+versus (bits per second).
+
+
+<P>
+
+We traveled 12 kilometers which is 12000 meters. We did that in five
+minutes which translates into 300 seconds. Our speed is 12000M / 300S
+equals 40 M/S.
+
+
+<P>
+
+We could also calculate the speed in KM/H: twelve times five minutes is an
+hour so we have to multiply 12 KM by 12 to get 144 KM/H. For our native
+English speaking friends: this is ninety MPH and therefore not recommended
+to try for yourself where I live :)
+
+
+<P>
+
+Remember: these numbers are averages and there is no way to figure out from
+the numbers we got that you drove at a constant speed.
+
+
+<P>
+
+I hope you understand that there is no difference in calculating M/S or
+bps, only the way we collect the data is different. Even the K from kilo is
+the same as in networking terms k also means 1000.
+
+
+<P>
+
+We will now create a database where we can keep all these interesting
+numbers. The method used to start the program may differ slightly from OS
+to OS but I assume you can figure it out if it works different on your OS.
+Make sure you do not overwrite any file on your system when executing the
+following command (so: first look if it's safe!) and type the whole line as
+one long line (I had to split it for readability) and skip all of the '\'
+characters.
+
+
+<P>
+
+<PRE> rrdtool create test.rrd \
+ --start 920804400 \
+ DS:speed:COUNTER:600:U:U \
+ RRA:AVERAGE:0.5:1:24 \
+ RRA:AVERAGE:0.5:6:10
+</PRE>
+
+<P>
+
+(So enter: <CODE>rrdtool create test.rrd --start 920804400 DS ...</CODE>)
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="What_has_been_created_">What has been created ?
+
+</A></H2>
+We created the round robin database called test (test.rrd) which starts at
+noon the day I started (7th of march, 1999) writing this document. It holds
+one data source (DS) named ``speed'' that gets built from a counter. This
+counter is read every five minutes (default) In the same database two round
+robin archives (RRAs) are kept, one averages the data every time it is read
+(so: there's nothing to average) and keeps 24 samples (24 times 5 minutes
+is 2 hours). The other averages 6 values (half hour) and contains 10 of
+such averages (so: 5 hours) The remaining options will be discussed later
+on. Chances are that you are not in the same part of the world as I am.
+This means your time zone is different. In all examples where I talk about
+time, the hours may be wrong for you. This has little effect on the results
+of the examples, just correct the hours while reading.
+
+
+<P>
+
+We now have to fill our database with some numbers. We'll pretend to have
+read the following numbers:
+
+
+<P>
+
+<PRE> 12:05 12345 KM
+ 12:10 12357 KM
+ 12:15 12363 KM
+ 12:20 12363 KM
+ 12:25 12363 KM
+ 12:30 12373 KM
+ 12:35 12383 KM
+ 12:40 12393 KM
+ 12:45 12399 KM
+ 12:50 12405 KM
+ 12:55 12411 KM
+ 13:00 12415 KM
+ 13:05 12420 KM
+ 13:10 12422 KM
+ 13:15 12423 KM
+</PRE>
+
+<P>
+
+We fill the database as follows:
+
+
+<P>
+
+<PRE> rrdtool update test.rrd 920804700:12345 920805000:12357 920805300:12363
+ rrdtool update test.rrd 920805600:12363 920805900:12363 920806200:12373
+ rrdtool update test.rrd 920806500:12383 920806800:12393 920807100:12399
+ rrdtool update test.rrd 920807400:12405 920807700:12411 920808000:12415
+ rrdtool update test.rrd 920808300:12420 920808600:12422 920808900:12423
+</PRE>
+
+<P>
+
+This reads: update our test database with the following numbers
+
+
+<P>
+
+<PRE> time 920804700, value 12345
+ time 920805000, value 12357
+</PRE>
+
+<P>
+
+etcetera.
+
+
+<P>
+
+As you can see, it is possible to feed more than one value into the
+database in one command. I had to stop at three for readability but the
+real maximum will be OS dependent.
+
+
+<P>
+
+The time value may look strange to you, it is written in seconds since the
+first of January, 1970, midnight. Don't worry about this yet, just notice
+that there is a difference of 300 in between all values.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="It_is_time_to_create_some_graphi">It is time to create some graphics
+
+</A></H2>
+Try the following command:
+
+
+<P>
+
+<PRE> rrdtool graph speed.gif \
+ --start 920804400 --end 920808000 \
+ DEF:myspeed=test.rrd:speed:AVERAGE \
+ LINE2:myspeed#FF0000
+</PRE>
+
+<P>
+
+This will create speed.gif which starts at 12:00 and ends at 13:00. There
+is a definition of variable myspeed, it is the data from RRA ``speed'' out
+of database ``test.rrd''. The line drawn is 2 pixels high, and comes from
+variable myspeed. The color is red. You'll notice that the start of the
+graph is not at 12:00 but at 12:05 and this is because we have insufficient
+data to tell the average before that time. This will only happen when you
+miss some samples, this will not happen a lot, hopefully.
+
+
+<P>
+
+If this has worked: Congratulations. If not, check what went wrong.
+
+
+<P>
+
+The colors are built up from red, green and blue. For each of the
+components, you specify how much to use in hexadecimal where 00 means not
+included and FF means fully included. The color white is a mixture of red,
+green and blue: FFFFFF The color black is all colors off: 000000 (Please,
+no discussions if black and white can be called colors)
+
+
+<P>
+
+<PRE> red #FF0000
+ green #00FF00
+ blue #0000FF
+ purple #FF00FF (mixed red with blue)
+ gray #555555 (one third of all components)
+</PRE>
+
+<P>
+
+The GIF you just created can be displayed using a web browser or other
+software you like. I can not provide you with an example of that, because
+there are too many different setups, possibilities etc.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="Graphics_with_some_math">Graphics with some math
+
+</A></H2>
+When looking at the image, you notice that the horizontal axis displays
+12:10, 12:20, 12:30, 12:40 and 12:50. The two remaining times (12:00 and
+13:00) would not be displayed nicely so they are skipped. The vertical axis
+displays the range we entered. We provided kilometers and when divided by
+300 seconds, we get very small numbers. To be exact, the first value was 12
+(12357-12345) and divided by 300 this makes 0.04 RRDtool displays this as
+40 m which means 40 mili (so: NOT meters). What we did wrong was that we
+should have measured in meters, this would have been
+(12357000-12345000)/300 = 12000/300 = 40.
+
+
+<P>
+
+Let's correct that. We could recreate our database and store the correct
+data but there is another way: do some calculations while creating the gif
+file !
+
+
+<P>
+
+<PRE> rrdtool graph speed2.gif \
+ --start 920804400 --end 920808000 \
+ --vertical-label m/s \
+ DEF:myspeed=test.rrd:speed:AVERAGE \
+ CDEF:realspeed=myspeed,1000,* \
+ LINE2:realspeed#FF0000
+</PRE>
+
+<P>
+
+After viewing this GIF, you notice the ``m'' has disappeared. This it what
+the correct result would be. Also, a label has been added to the image.
+Apart from the things mentioned above, the GIF should be the same.
+
+
+<P>
+
+The calculations are done with the CDEF part. What it says is: take the
+data source myspeed and the number 1000, multiply those. The calculations
+are done using Reverse Polish Notation. It is an easy way of performing
+calculations after you understand it. You will, eventually but for now
+assume it is correct what I write and just keep to the examples in this
+file. Read the documentation that came with RRDtool (look in rrdgraph.doc)
+when you're ready for it.
+
+
+<P>
+
+Hang on! If we can multiply values with 1000, it should also be possible to
+display kilometers per hour from the same data ! What do we need to do ? If
+we have meters per second, we can make this meters per hour by multiplying
+the value with 3600 (there go 3600 seconds in one hour). To get kilometers
+per hour, we need to divide by 1000. We end up with: value * 3600 / 1000 =
+value * 3.6 . Remember we also have to correct our mistake, so it is value
+* 3600 for us.
+
+
+<P>
+
+Now let's create this GIF, and add some more magic ...
+
+
+<P>
+
+<PRE> rrdtool graph speed3.gif \
+ --start 920804400 --end 920808000 \
+ --vertical-label km/h \
+ DEF:myspeed=test.rrd:speed:AVERAGE \
+ CDEF:kmh=myspeed,3600,* \
+ CDEF:fast=kmh,100,GT,kmh,0,IF \
+ CDEF:good=kmh,100,GT,0,kmh,IF \
+ HRULE:100#0000FF:"Maximum allowed" \
+ AREA:good#00FF00:"Good speed" \
+ AREA:fast#FF0000:"Too fast"
+</PRE>
+
+<P>
+
+This looks much better. Speed in KM/H and even an extra line with the
+maximum allowed speed (on the road I travel at). I also changed the colors
+used to display speed and changed it from a line into an area.
+
+
+<P>
+
+The calculations are more complex now. For the ``good'' speed they are:
+
+
+<P>
+
+<UL>
+<LI><STRONG></STRONG>
+Check if kmh is greater than 100 ( kmh,100 ) GT
+
+
+<P>
+
+<LI><STRONG></STRONG>
+If so, return 0, else kmh ((( kmh,100 ) GT ), 0, kmh) IF
+
+
+<P>
+
+</UL>
+For the other speed:
+
+
+<P>
+
+<UL>
+<LI><STRONG></STRONG>
+Check if kmh is greater than 100 ( kmh,100 ) GT
+
+
+<P>
+
+<LI><STRONG></STRONG>
+If so, return kmh, else return 0 ((( kmh,100) GT ), kmh, 0) IF
+
+
+<P>
+
+</UL>
+<P>
+<HR>
+<H2><A NAME="Graphics_Magic">Graphics Magic
+
+</A></H2>
+I like to believe there are virtually no limits about what RRDtool can do.
+I will not explain how it works, but look at the following GIF:
+
+
+<P>
+
+<PRE> rrdtool graph speed4.gif \
+ --start 920804400 --end 920808000 \
+ --vertical-label km/h \
+ DEF:myspeed=test.rrd:speed:AVERAGE \
+ CDEF:kmh=myspeed,3600,* \
+ CDEF:fast=kmh,100,GT,100,0,IF \
+ CDEF:over=kmh,100,GT,kmh,100,-,0,IF \
+ CDEF:good=kmh,0,kmh,100,GT,IF \
+ HRULE:100#0000FF:"Maximum allowed" \
+ AREA:good#00FF00:"Good speed" \
+ AREA:fast#550000:"Too fast" \
+ STACK:over#FF0000:"Over speed"
+</PRE>
+
+<P>
+
+Let's create a quick and dirty HTML page to view three GIFs:
+
+
+<P>
+
+<PRE> <HTML><HEAD><TITLE>Speed</TITLE></HEAD><BODY>
+ <IMG src="speed2.gif" alt="Speed in meters per second">
+ <BR>
+ <IMG src="speed3.gif" alt="Speed in kilometers per hour">
+ <BR>
+ <IMG src="speed4.gif" alt="Traveled too fast?">
+ </BODY></HTML>
+</PRE>
+
+<P>
+
+Name the file ``speed.html'' or similar, and view it.
+
+
+<P>
+
+Now, all you have to do is measure the values regularly and update the
+database. Every time you create these three GIFs and reload the page and
+the GIFs (better reread these last three words!) you know how fast you
+traveled.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="Updates_in_Reality">Updates in Reality
+
+</A></H2>
+You already looked at the ``update'' tool. It took one or more parameters
+in the form of ``<time>:<value>''. You'll be glad to know that
+you can get the current time by filling in a ``N'' as the time. If you
+wish, you can also use the ``time'' function in perl. The shortest example
+in this doc :)
+
+
+<P>
+
+<PRE> perl -e 'print time, "\n" '
+</PRE>
+
+<P>
+
+How you can run a program on regular intervals is OS specific, so I just
+give you an example script in a sort of pseudo code: (Do not try this with
+our test database, it is used in further examples)
+
+
+<P>
+
+<PRE> Get the value, put it in variable "$speed"
+ rrdtool update speed.rrd N:$speed
+</PRE>
+
+<P>
+
+This is all. Run this script every five minutes. When you need to know what
+the graphics look like, run the examples above. You could put them in a
+script. After running that script, view index.html
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="Some_words_on_SNMP">Some words on SNMP
+
+</A></H2>
+I can imagine very few people will be able to get real data from their car
+every five minutes, all other people will have to settle for some other
+kind of counter. You could measure the number of pages printed by the
+laser-jet printer, the coffee made by the coffee machine, a device that
+counts the electricity used, whatever. Just as long as it is an
+incrementing counter that you can measure regularly, you can graph it
+against time as we did. Most people will use the counter that keeps track
+of octets (bytes) transfered by a routing device so we have to do just
+that. We will start with a description of how to collect data. Some people
+will make a remark that there are tools who can do this data collection for
+you. They are right! However, I feel it is important that you understand
+they are not necessary. If you have to look why things went wrong, you need
+to know how the stuff works.
+
+
+<P>
+
+One tool used in the example has been talked about very briefly in the
+beginning of this document, it is called SNMP. It is a way of talking to
+equipment. The tool I use below is called ``snmpget'' and this is how it
+works:
+
+
+<P>
+
+<PRE> snmpget device password OID
+</PRE>
+
+<P>
+
+For device you substitute the name of your device, for password you use the
+``community'' as it is called. For most devices ``public'' will do but this
+can be disabled, altered or protected for privacy and security reasons. You
+will need to find this out as there is no way I can tell what you ( ...your
+device... ) are keeping a secret from me.
+
+
+<P>
+
+Then there is this third parameter, called OID. When you start to learn
+about SNMP it looks very confusing. It isn't all that difficult when you
+look at the Management Information Base or in short: the MIB. It is an
+upside-down tree, with a single node as the root and from there a number of
+branches. These branches end up in another node, they branch out, etc. All
+the branches have a name and they form the path that we follow all the way
+down. The branches that we follow are named: iso, org, dod, internet, mgmt
+and mib-2. These names can also be written down as numbers and are 1 3 6 1
+2 1.
+
+
+<P>
+
+<PRE> iso.org.dod.internet.mgmt.mib-2 (1.3.6.1.2.1)
+</PRE>
+
+<P>
+
+From there, we are especially interested in the branch ``interfaces'' which
+has number 2 (so: 1.3.6.1.2.1.2 or 1.3.6.1.2.1.interfaces).
+
+
+<P>
+
+The SNMP programs that I know can take above path as a default, so I could
+walk to interfaces without writing it in full. To do that, the path has to
+be written as interfaces, without a leading dot. I could also use the long
+form, then I need to start with a dot.
+
+
+<P>
+
+I can intermix numbers and names as I like. 1.3.6.1.2.1 is the same as
+iso.org.dod.1.2.1 and 1.3.6.internet.2.mib-2 For interfaces I could write
+``interfaces'', 2, or a long version by prefixing it with
+``.1.3.6.1.2.1.''. Just try what works for you and do read the manual for
+the version of snmpget you are using.
+
+
+<P>
+
+First, we have to get some SNMP program. First look if there is a
+pre-compiled package available for your OS. This is the preferred way. If
+not, you will have to get yourself the sources and compile those. The
+Internet is full of sources, programs etc. Find information using a search
+engine or whatever you prefer. You are on your own here, sorry.
+
+
+<P>
+
+Assume you got the program. First try to collect some data that is
+available on most systems. Remember: there is a short name for the part of
+the tree that interests us most in the world we live in ! I will use the
+short version as I think this document is large enough as it is. If that
+doesn't work for you, prefix with .1.3.6.1.2.1 and try again. Also, Read
+The Fine Manual. Skip the parts you cannot understand yet, you should be
+able to find out how to start the program and use it.
+
+
+<P>
+
+<PRE> snmpget myrouter public system.sysdescr.0
+</PRE>
+
+<P>
+
+The device should answer with a description of itself, perhaps empty. Until
+you got a valid answer from a device, perhaps using a different
+``password'', or a different device, there is no point in continuing.
+
+
+<P>
+
+<PRE> snmpget myrouter public interfaces.ifnumber.0
+</PRE>
+
+<P>
+
+Hopefully you get a number as a result, the number of interfaces. If so,
+you can carry on and try a different program called ``snmpwalk''.
+
+
+<P>
+
+<PRE> snmpwalk myrouter public interfaces.iftable.ifentry.ifdescr
+</PRE>
+
+<P>
+
+If it returns with a list of interfaces, you're almost there. Here's an
+example: [user at host /home/alex]$ snmpwalk cisco public 2.2.1.2
+
+
+<P>
+
+<PRE> interfaces.ifTable.ifEntry.ifDescr.1 = "BRI0: B-Channel 1"
+ interfaces.ifTable.ifEntry.ifDescr.2 = "BRI0: B-Channel 2"
+ interfaces.ifTable.ifEntry.ifDescr.3 = "BRI0" Hex: 42 52 49 30
+ interfaces.ifTable.ifEntry.ifDescr.4 = "Ethernet0"
+ interfaces.ifTable.ifEntry.ifDescr.5 = "Loopback0"
+</PRE>
+
+<P>
+
+On this cisco equipment, I would like to monitor the ``Ethernet0''
+interface and see that it is number four. I try:
+
+
+<P>
+
+<PRE> [user at host /home/alex]$ snmpget cisco public 2.2.1.10.4 2.2.1.16.4
+</PRE>
+
+<P>
+
+<PRE> interfaces.ifTable.ifEntry.ifInOctets.4 = 2290729126
+ interfaces.ifTable.ifEntry.ifOutOctets.4 = 1256486519
+</PRE>
+
+<P>
+
+So now I have two OIDs to monitor and they are (in full, this time):
+
+
+<P>
+
+<PRE> 1.3.6.1.2.1.2.2.1.10
+</PRE>
+
+<P>
+
+and
+
+
+<P>
+
+<PRE> 1.3.6.1.2.1.2.2.1.16
+</PRE>
+
+<P>
+
+both with an interface number of 4.
+
+
+<P>
+
+Don't get fooled, this wasn't my first try. It took some time for me too to
+understand what all these numbers mean, it does help a lot when they get
+translated into descriptive text... At least, when people are talking about
+MIBs and OIDs you know what it's all about. Do not forget the interface
+number (0 if it is not interface dependent) and try snmpwalk if you don't
+get an answer from snmpget.
+
+
+<P>
+
+If you understand above part, and get numbers from your device, it is time
+to continue with the following. If not, then go back.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="A_Real_World_Example">A Real World Example
+
+</A></H2>
+Let the fun begin. First, create a new database. It contains data from two
+counters, called input and output. The data is put into archives that
+average it. They take 1, 6, 24 or 288 samples at a time. They also go into
+archives that keep the maximum numbers. This will be explained later on.
+The time in-between samples is 300 seconds, a good starting point, which is
+the same as five minutes.
+
+
+<P>
+
+<PRE> 1 sample averaged stays 1 period of 5 minutes
+ 6 samples averaged become one average on 30 minutes
+ 24 samples averaged become one average on 2 hours
+ 288 samples averaged become one average on 1 day
+</PRE>
+
+<P>
+
+<PRE> There are 600 samples of five minutes, together just over two days
+ There are 600 samples of 30 minutes, almost two weeks
+ There are 600 samples of 2 hours, 50 hour or almost two months
+ There are 732 samples of 1 day, just over two years
+</PRE>
+
+<P>
+
+For people used to MRTG that even have read the manuals, these numbers
+should look familiar...
+
+
+<P>
+
+<PRE> rrdtool create myrouter.rrd \
+ DS:input:COUNTER:600:U:U \
+ DS:output:COUNTER:600:U:U \
+ RRA:AVERAGE:0.5:1:600 \
+ RRA:AVERAGE:0.5:6:600 \
+ RRA:AVERAGE:0.5:24:600 \
+ RRA:AVERAGE:0.5:288:732 \
+ RRA:MAX:0.5:1:600 \
+ RRA:MAX:0.5:6:600 \
+ RRA:MAX:0.5:24:600 \
+ RRA:MAX:0.5:288:732
+</PRE>
+
+<P>
+
+Next thing to do is collect data and store it. Here is an example. It is
+written partially in pseudo code so you will have to find out what to do
+exactly on your OS to make it work.
+
+
+<P>
+
+<PRE> while not the end of the universe
+ do
+ get result of
+ snmpget router community 2.2.1.10.4
+ into variable $in
+ get result of
+ snmpget router community 2.2.1.16.4
+ into variable $out
+</PRE>
+
+<P>
+
+<PRE> rrdtool update myrouter.rrd N:$in:$out
+</PRE>
+
+<P>
+
+<PRE> wait for 5 minutes
+ done
+</PRE>
+
+<P>
+
+Then, after collecting data for a day, try to create an image using:
+
+
+<P>
+
+<PRE> rrdtool graph myrouter-day.gif --start -86400 \
+ DEF:inoctets=myrouter.rrd:input:AVERAGE \
+ DEF:outoctets=myrouter.rrd:output:AVERAGE \
+ AREA:inoctets#00FF00:"In traffic" \
+ LINE1:outoctets#0000FF:"Out traffic"
+</PRE>
+
+<P>
+
+This should produce a picture with one day worth of traffic. One day is 24
+hours of 60 minutes of 60 seconds: 24*60*60=86400, we start at now minus
+86400 seconds. We DEFine inoctets and outoctets as the average values from
+the database myrouter.rrd and draw an area for the ``in'' traffic and a
+line for the ``out'' traffic.
+
+
+<P>
+
+View the image and keep logging for a few more days. If you like, you could
+try the examples from the test database and see if you can play around with
+the options and calculations.
+
+
+<P>
+
+Suggestion:
+
+
+<P>
+
+Display in bytes per second and in bits per second. Make the ethernet
+graphics go red if they are over four megabits per second.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="Consolidation_Functions">Consolidation Functions
+
+</A></H2>
+A few paragraphs back I mentioned the possibility of keeping the maximum
+values instead of the average values. Let's go into this a bit more.
+
+
+<P>
+
+Recall all the stuff about the speed of the car. Suppose we drove at 144
+KM/H during 5 minutes and then were stopped by the police for 25 minutes.
+At the end of the lecture we would take our laptop and create+view the
+image taken from the database. If we look at the second RRA we did create,
+we would have the average from 6 samples. The samples measured would be
+144+0+0+0+0+0=144, divided by 30 minutes, corrected for the error by 1000,
+translated into KM/H, with a result of 24 KM/H. I would still get a ticket
+but not for speeding anymore :)
+
+
+<P>
+
+Obviously, in this case, we shouldn't look at the averages. In some cases
+they are handy. If you want to know how much KM you had traveled, the
+picture would be the right one to look at. On the other hand, for the speed
+that we traveled at, the maximum number seen is much more valuable. (later
+we will see more types)
+
+
+<P>
+
+It is the same for data. If you want to know the amount, look at the
+averages. If you want to know the rate, look at the maximum. Over time,
+they will grow apart more and more. In the last database we have created,
+there are two archives that keep data per day. The archive that keeps
+averages will show low numbers, the archive that shows maxima will have
+higher numbers. For my car this would translate in averages per day of
+96/24=4 KM/H (as I travel about 94 kilometers on a day) during week days,
+and maximum of 120 KM/H on weekdays (my top speed that I reach every day).
+
+
+<P>
+
+Big difference. Do not look at the second graph to estimate the distances
+that I travel and do not look at the first graph to estimate my speed. This
+will work if the samples are close together, as they are in five minutes,
+but not if you average.
+
+
+<P>
+
+On some days, I go for a long ride. If I go across Europe and travel for
+over 12 hours, the first graph will rise to about 60 KM/H. The second one
+will show 180 KM/H. This means that I traveled a distance of 60 KM/H times
+24 H = 1440 KM. I did this with a higher speed and a maximum around 180
+KM/H. This doesn't mean that I traveled for 8 hours at a constant speed of
+180 KM/H ! This is a real example: go with the flow through Germany and
+stop a few times for gas and coffee. Drive slowly through Austria and the
+Netherlands. Be careful in the mountains and villages. If you would look at
+the graphs created from the five-minute averages you would get a totally
+different picture. You would see the same values on the average and maximum
+graphs (provided I measured every 300 seconds). You would be able to see
+when I stopped, when I was in top gear, when I drove over fast motor-ways
+etc. The granularity of the data is much higher, so you can see more.
+However, this takes 12 samples per hour, or 288 values per day, so it would
+be too much to keep for a long period of time. Therefore we average it,
+eventually to one value per day. From this one value, we cannot see much
+detail.
+
+
+<P>
+
+Make sure you understand the last few paragraphs. There is no value in only
+a line and a few axis, you need to know what they mean and interpret the
+data in a good way. This is true for all data.
+
+
+<P>
+
+The biggest mistake you can make is to use the collected data for something
+that it is not suitable for. You would be better off if you would not have
+the graphics at all in that case.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="Let_s_review_what_you_now_should">Let's review what you now should know.
+
+</A></H2>
+You now know how to create a database. You can put the numbers in it, get
+them out again by creating an image, do math on the data from the database
+and view the outcome instead of the raw data. You know about the difference
+between averages and maxima, and when to use which (or at least you have an
+idea).
+
+
+<P>
+
+RRDtool can do more than what we have learned up to now. Before you
+continue with the rest of this doc, I recommend that you reread from the
+start and try some modifications on the examples. Make sure you fully
+understand everything. It will be worth the effort and helps you not only
+with the rest of this doc but also in your day to day monitoring long after
+you read this introduction.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="Data_Source_Types">Data Source Types
+
+</A></H2>
+All right, you feel like continuing. Welcome back and get ready for an
+increased speed in the examples and explanation.
+
+
+<P>
+
+You know that in order to view a counter over time, you have to take two
+numbers and divide the difference of them between the time lapsed. This
+makes sense for the examples I gave you but there are other possibilities.
+For instance, I'm able to retrieve the temperature from my router in three
+places namely the inlet, the so called hot-spot and the exhaust. If I take
+the difference of the two samples and divide that by 300 (seconds) there
+would not be very much to display ... If there would be anything to display
+it would be the fluctuations in the temperature and if they produce
+noticeable results when divided by 300, I'd better look for a new computer
+room.
+
+
+<P>
+
+So, what can we do ? RRDtool can also store the values you measure directly
+as they are (this is not entirely true but close enough). The graphs we
+make look much better, they will show a rather constant value. I know when
+the router is busy (it works -> it uses more electricity -> it
+generates more heat -> the temperature rises). I know when the doors are
+left open (the room is cooled -> the warm air from the rest of the
+building flows into the computer room -> the inlet temperature rises)
+etc. The data type we use when creating the database before was counter, we
+now have a different data type and thus a different name for it. It is
+called GAUGE. There are more such data types:
+
+
+<P>
+
+<PRE> - COUNTER we already know this one
+ - GAUGE we just learned this one
+ - DERIVE
+ - ABSOLUTE
+</PRE>
+
+<P>
+
+The two new types are DERIVE and ABSOLUTE. Absolute can be used like
+counter with one difference: RRDtool assumes the counter is reset when it's
+read. That is: its delta is known without calculation by RRDtool whereas
+RRDtool needs to calculate it for the counter type. Example: our first
+example (12345, 12357, 12363, 12363) would read: unknown, 12, 6, 0. The
+rest of the calculations stay the same. The other one, derive, is like
+counter. Unlike counter, it can also decrease so it can have a negative
+delta. Again, the rest of the calculations stay the same.
+
+
+<P>
+
+Let's try them all:
+
+
+<P>
+
+<PRE> rrdtool create all.rrd --start 978300900 \
+ DS:a:COUNTER:600:U:U \
+ DS:b:GAUGE:600:U:U \
+ DS:c:DERIVE:600:U:U \
+ DS:d:ABSOLUTE:600:U:U \
+ RRA:AVERAGE:0.5:1:10
+ rrdtool update all.rrd \
+ 978301200:300:1:600:300 \
+ 978301500:600:3:1200:600 \
+ 978301800:900:5:1800:900 \
+ 978302100:1200:3:2400:1200 \
+ 978302400:1500:1:2400:1500 \
+ 978302700:1800:2:1800:1800 \
+ 978303000:2100:4:0:2100 \
+ 978303300:2400:6:600:2400 \
+ 978303600:2700:4:600:2700 \
+ 978303900:3000:2:1200:3000
+ rrdtool graph all1.gif -s 978300600 -e 978304200 -h 400 \
+ DEF:linea=all.rrd:a:AVERAGE LINE3:linea#FF0000:"Line A" \
+ DEF:lineb=all.rrd:b:AVERAGE LINE3:lineb#00FF00:"Line B" \
+ DEF:linec=all.rrd:c:AVERAGE LINE3:linec#0000FF:"Line C" \
+ DEF:lined=all.rrd:d:AVERAGE LINE3:lined#000000:"Line D"
+</PRE>
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="RRD_Tool_under_the_Microscope">RRD Tool under the Microscope
+
+</A></H2>
+<UL>
+<LI><STRONG></STRONG>
+Line A is a counter so it should continuously increment and RRDtool should
+calculate the differences. Also, RRDtool needs to divide the difference by
+the amount of time lapsed. This should end up as a straight line at 1 (the
+deltas are 300, the time is 300).
+
+
+<P>
+
+<LI><STRONG></STRONG>
+Line B is of type gauge. These are ``real'' values so they should match
+what we put in: a sort of a wave.
+
+
+<P>
+
+<LI><STRONG></STRONG>
+Line C is derive. It should be a counter that can decrease. It does so
+between 2400 and 0, with 1800 in-between.
+
+
+<P>
+
+<LI><STRONG></STRONG>
+Line D is of type absolute. This is like counter but it works on values
+without calculating the difference. The numbers are the same and as you can
+see (hopefully) this has a different result.
+
+
+<P>
+
+</UL>
+This translates in the following values, starting at 23:10 and ending at
+00:10 the next day (where U means unknown/unplotted):
+
+
+<P>
+
+<PRE> - Line A: u u 1 1 1 1 1 1 1 1 1 u
+ - Line B: u 1 3 5 3 1 2 4 6 4 2 u
+ - Line C: u u 2 2 2 0 -2 -6 -2 0 2 u
+ - Line D: u 1 2 3 4 5 6 7 8 9 10 u
+</PRE>
+
+<P>
+
+If your GIF shows all this, you know you have typed the data correct, the
+RRDtool executable is working properly, your viewer doesn't fool you and
+you successfully entered the year 2000 :) You could try the same example
+four times, each time with only one of the lines.
+
+
+<P>
+
+Let's go over the data again:
+
+
+<P>
+
+<UL>
+<LI><STRONG></STRONG>
+Line A: 300,600,900 and so on. The counter delta is a constant 300 and so
+it the time delta. A number divided by itself is always 1 (except when
+dividing by zero which is undefined/illegal). Why is it that the first
+point is unknown ? We do know what we put into the database ? True ! But we
+didn't have a value to calculate the delta from so we don't know where we
+started. It would be wrong to assume we started at zero so we don't !
+
+
+<P>
+
+<LI><STRONG></STRONG>
+Line B: There is nothing to calculate. The numbers are as is.
+
+
+<P>
+
+<LI><STRONG></STRONG>
+Line C: Again, the start-out value is unknown. The same story is valid like
+for line A. In this case the deltas are not constant so the line is not. If
+we would put the same numbers in the database as we did for line A, we
+would have gotten the same line. Unlike type counter, this type can
+decrease and I hope to show you later on why there is a difference.
+
+
+<P>
+
+<LI><STRONG></STRONG>
+Line D: Here the device calculates the deltas. Therefore we DO know the
+first delta and it is plotted. We had the same input as with line A but the
+meaning of this input is different. Therefore the line is different. In
+this case the deltas increase each time with 300. The time delta stays at a
+constant 300 and therefore the division of the two gives increasing
+results.
+
+
+<P>
+
+</UL>
+<P>
+<HR>
+<H2><A NAME="Counter_Wraps">Counter Wraps
+
+</A></H2>
+There are a few more basics to show. Some important options are still to be
+covered and we haven't look at counter wraps yet. First the counter wrap:
+In our car we notice that our counter shows 999987. We travel 20 KM and the
+counter should go to 1000007. Unfortunately, there are only six digits on
+our counter so it really shows 000007. If we would plot that on a type
+DERIVE, it would mean that the counter was set back 999980 KM. It wasn't,
+and there has to be some protection for this. This protection is only
+available for type COUNTER which should be used for this kind of counter
+anyways. How does it work ? Type counter should never decrease and
+therefore RRDtool must assume it wrapped if it does decrease ! If the delta
+is negative, this can be compensated for by adding the maximum value of the
+counter + 1. For our car this would be:
+
+
+<P>
+
+<PRE> Delta = 7 - 999987 = -999980 (instead of 1000007-999987=20)
+</PRE>
+
+<P>
+
+<PRE> Real delta = -999980 + 999999 + 1 = 20
+</PRE>
+
+<P>
+
+At the moment of writing this document, RRDtool knows of counters that are
+either 32 bits or 64 bits of size. These counters can handle the following
+different values:
+
+
+<P>
+
+<PRE> - 32 bits: 0 .. 4294967295
+ - 64 bits: 0 .. 18446744073709551615
+</PRE>
+
+<P>
+
+If these numbers look strange to you, you would like to view them in their
+hexadecimal form:
+
+
+<P>
+
+<PRE> - 32 bits: 0 .. FFFFFFFF
+ - 64 bits: 0 .. FFFFFFFFFFFFFFFF
+</PRE>
+
+<P>
+
+RRDtool handles both counters the same. If an overflow occurs and the delta
+would be negative, RRDtool first adds the maximum of a small counter + 1 to
+the delta. If the delta is still negative, it had to be the large counter
+that wrapped. Add the maximum possible value of the large counter + 1 and
+subtract the falsely added small value. There is a risk in this: suppose
+the large counter wrapped while adding a huge delta, it could happen in
+theory that adding the smaller value would make the delta positive. In this
+unlikely case the results would not be correct. The increase should be
+nearly as high as the maximum counter value for that to happen so chances
+are you would have several other problems as well and this particular
+problem would not even be worth thinking about. Even though I did include
+an example of it so you can judge that for yourself.
+
+
+<P>
+
+The next section gives you some numerical examples for counter-wraps. Try
+to do the calculations yourself or just believe me if your calculator can't
+handle the numbers :)
+
+
+<P>
+
+Correction numbers:
+
+
+<P>
+
+<PRE> - 32 bits: (4294967295+1) = 4294967296
+ - 64 bits: (18446744073709551615+1)-correction1 = 18446744069414584320
+</PRE>
+
+<P>
+
+<PRE> Before: 4294967200
+ Increase: 100
+ Should become: 4294967300
+ But really is: 4
+ Delta: -4294967196
+ Correction1: -4294967196 +4294967296 = 100
+</PRE>
+
+<P>
+
+<PRE> Before: 18446744073709551000
+ Increase: 800
+ Should become: 18446744073709551800
+ But really is: 184
+ Delta: -18446744073709550816
+ Correction1: -18446744073709550816 +4294967296 = -18446744069414583520
+ Correction2: -18446744069414583520 +18446744069414584320 = 800
+</PRE>
+
+<P>
+
+<PRE> Before: 18446744073709551615 ( maximum value )
+ Increase: 18446744069414584320 ( absurd increase, minimum for
+ Should become: 36893488143124135935 this example to work )
+ But really is: 18446744069414584319
+ Delta: -4294967296
+ Correction1: -4294967296 + 4294967296 = 0
+ (not negative -> no correction2)
+</PRE>
+
+<P>
+
+<PRE> Before: 18446744073709551615 ( maximum value )
+ Increase: 18446744069414584319 ( one less increase )
+ Should become: 36893488143124135934
+ But really is: 18446744069414584318
+ Delta: -4294967297
+ Correction1: -4294967297 +4294967296 = -1
+ Correction2: -1 +18446744069414584320 = 18446744069414584319
+</PRE>
+
+<P>
+
+As you can see from the last two examples, you need strange numbers for
+RRDtool to fail (provided it's bug free of course) so this should not
+happen. However, SNMP or whatever method you choose to collect the data
+might also fail and it is not uncommon to get wrong numbers occasionally.
+We can't prevent all errors but there are some things we could do. RRDtool
+create takes two special parameters for this. They define the minimum and
+maximum allowed value. Until now, we made them ``U'' for Unknown. You may
+(not: must) provide values for one or both of them and if RRDtool receives
+values that are outside these limits, it will ignore them. For a
+thermometer in degrees Celsius, the absolute minimum is just under -273.
+For my router, I can assume this minimum is much higher so I would say it
+is 10. The maximum temperature for my router I would state as 80. Any
+higher and the device would be out of order. For my car, I would never
+expect negative numbers and also I would not expect numbers to be higher
+than 230. Anything else, and there must have been an error. Remember: the
+opposite is not true, if the numbers pass this check it doesn't mean that
+they are correct. Always judge the graph with a healthy dose of paranoia if
+it looks weird.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="Data_Resampling">Data Resampling
+
+</A></H2>
+One important feature of RRDtool has not been explained yet: It is
+virtually impossible to collect the data and feed it into RRDtool on exact
+intervals. RRDtool therefore interpolates the data so it is on exact
+intervals. If you do not know what this means or how it works, then here's
+the help you seek:
+
+
+<P>
+
+Suppose a counter increases with exactly one for every second. You want to
+measure it in 300 seconds intervals. You should retrieve values that are
+exactly 300 apart. However, due to various circumstances you are a few
+seconds late and the interval is 303. The delta will also be 303 in that
+case. Obviously RRDtool should not put 303 in the database and make you
+believe that the counter increased 303 in 300 seconds. This is where
+RRDtool interpolates: it alters the 303 value as if it would have been
+stored earlier and it will be 300 in 300 seconds. Next time you are at
+exactly the right time. This means that the current interval is 297 seconds
+and also the counter increased with 297. Again RRDtool alters the value and
+stores 300 as it should be.
+
+
+<P>
+
+<PRE> in the RDD in real
+</PRE>
+
+<P>
+
+<PRE> time+000: 0 delta="U" time+000: 0 delta="U"
+ time+300: 300 delta=300 time+300: 300 delta=300
+ time+600: 600 delta=300 time+603: 603 delta=303
+ time+900: 900 delta=300 time+900: 900 delta=297
+</PRE>
+
+<P>
+
+Let's create two identical databases. I've chosen the time range 920805000
+to 920805900 as this goes very well with the example numbers.
+
+
+<P>
+
+<PRE> rrdtool create seconds1.rrd \
+ --start 920804700 \
+ DS:seconds:COUNTER:600:U:U \
+ RRA:AVERAGE:0.5:1:24
+</PRE>
+
+<P>
+
+<PRE> for Unix: cp seconds1.rrd seconds2.rrd
+ for Dos: copy seconds1.rrd seconds2.rrd
+ for vms: how would I know :)
+</PRE>
+
+<P>
+
+<PRE> rrdtool update seconds1.rrd \
+ 920805000:000 920805300:300 920805600:600 920805900:900
+ rrdtool update seconds2.rrd \
+ 920805000:000 920805300:300 920805603:603 920805900:900
+</PRE>
+
+<P>
+
+<PRE> rrdtool graph seconds1.gif \
+ --start 920804700 --end 920806200 \
+ --height 200 \
+ --upper-limit 1.05 --lower-limit 0.95 --rigid \
+ DEF:seconds=seconds1.rrd:seconds:AVERAGE \
+ CDEF:unknown=seconds,UN \
+ LINE2:seconds#0000FF \
+ AREA:unknown#FF0000
+ rrdtool graph seconds2.gif \
+ --start 920804700 --end 920806200 \
+ --height 200 \
+ --upper-limit 1.05 --lower-limit 0.95 --rigid \
+ DEF:seconds=seconds2.rrd:seconds:AVERAGE \
+ CDEF:unknown=seconds,UN \
+ LINE2:seconds#0000FF \
+ AREA:unknown#FF0000
+</PRE>
+
+<P>
+
+Both graphs should show the same.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="WRAPUP">WRAPUP
+
+</A></H1>
+It's time to wrap up this document. You now know all the basics to be able
+to work with RRDtool and to read the documentation available. There is
+plenty more to discover about RRDtool and you will find more and more uses
+for the program. You could create easy graphics using just the examples
+provided and using only RRDtool. You could also use the front ends that are
+available.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="MAILINGLIST">MAILINGLIST
+
+</A></H1>
+Remember to subscribe to the mailing-list. Even if you are not answering
+the mails that come by, it helps both you and the rest. A lot of the stuff
+that I know about MRTG (and therefore about RRDtool) I've learned while
+just reading the list without posting to it. I did not need to ask the
+basic questions as they are answered in the FAQ (so: read that too) and in
+various mails by other users. With thousands of users all over the world,
+there will always be people who ask questions that you can answer because
+you read this and other documentation and they didn't.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO
+
+</A></H1>
+The RRD Tool manpages
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR
+
+</A></H1>
+I hope you enjoyed the examples and their descriptions. If you do, help
+other people by pointing them to this document when they are asking basic
+questions. They will not only get their answer but at the same time learn a
+whole lot more.
+
+
+<P>
+
+Alex van den Bogaerdt <A
+HREF="MAILTO:<alex at ergens.op.het.net>"><alex at ergens.op.het.net></A>
+
+
+<P>
+
+</DL>
+ </BODY>
+
+ </HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.html Sat Jul 13 18:46:09 2002
@@ -0,0 +1,79 @@
+ <HTML>
+ <HEAD>
+ <TITLE>last - Return the date of the last data sample in an B<RRD>
+
+</TITLE>
+ </HEAD>
+
+ <BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+ <LI><A HREF="#NAME">NAME</A>
+ <LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+ <LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+ <LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME
+
+</A></H1>
+rrdtool last - Return the date of the last data sample in an <STRONG>RRD</STRONG>
+
+
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS
+
+</A></H1>
+<STRONG>rrdtool</STRONG> <STRONG>last</STRONG> <EM>filename</EM>
+
+
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION
+
+</A></H1>
+The <STRONG>last</STRONG> function returns the UNIX timestamp when the RRD was last updated.
+
+
+<P>
+
+<DL>
+<DT><STRONG><A NAME="item_filename">filename
+
+</A></STRONG><DD>
+The name of the <STRONG>RRD</STRONG> that contains the data.
+
+
+<P>
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR
+
+</A></H1>
+Russ Wright <A HREF="MAILTO:<rwwright at home.com>"><rwwright at home.com></A>
+
+
+<P>
+
+</DL>
+ </BODY>
+
+ </HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.txt
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.txt (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.txt Sat Jul 13 18:46:10 2002
@@ -0,0 +1,264 @@
+
+
+
+RRDFETCH(1) rrdtool RRDFETCH(1)
+
+
+NNNNAAAAMMMMEEEE
+ rrdtool fetch - fetch data from an rrd.
+
+SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
+ rrrrrrrrddddttttoooooooollll ffffeeeettttcccchhhh _f_i_l_e_n_a_m_e _C_F [--------rrrreeeessssoooolllluuuuttttiiiioooonnnn|----rrrr _r_e_s_o_l_u_t_i_o_n]
+ [--------ssssttttaaaarrrrtttt|----ssss _s_t_a_r_t] [--------eeeennnndddd|----eeee _e_n_d]
+
+DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
+ The ffffeeeettttcccchhhh function is normally used internally by the
+ graph function, to get data from RRRRRRRRDDDDs. ffffeeeettttcccchhhh will analyze
+ the RRRRRRRRDDDD and will try to retrieve the data in the
+ resolution requested. The data fetched is printed to
+ stdout. _*_U_N_K_N_O_W_N_* data is often represented by the string
+ "NaN" depending on your OSs printf function.
+
+ _f_i_l_e_n_a_m_e
+ the name of the RRRRRRRRDDDD you want to fetch the data
+ from.
+
+ _C_F which consolidation function should have been
+ applied to the data you want to fetch?
+ (AVERAGE,MIN,MAX,LAST)
+
+ --------rrrreeeessssoooolllluuuuttttiiiioooonnnn|----rrrr _r_e_s_o_l_u_t_i_o_n (default is the highest
+ resolution)
+ what interval should the values have (seconds per
+ value). rrrrrrrrddddffffeeeettttcccchhhh will try to match your request,
+ but it will return data even if no absolute match
+ is possible.
+
+ --------ssssttttaaaarrrrtttt|----ssss _s_t_a_r_t (default -24*3600)
+ when should the data begin. A time in seconds
+ since epoch (1970-01-01) is required. Negative
+ numbers are relative to the end time. By default
+ one day worth of data will be fetched. See also
+ AT-STYLE TIME SPECIFICATION section for
+ alternative ways to specify start time.
+
+ --------eeeennnndddd|----eeee _e_n_d (default current time)
+ when should the data end. Time in seconds since
+ epoch. See also AT-STYLE TIME SPECIFICATION
+ section for alternative ways to specify end time.
+
+ AAAATTTT----SSSSTTTTYYYYLLLLEEEE TTTTIIIIMMMMEEEE SSSSPPPPEEEECCCCIIIIFFFFIIIICCCCAAAATTTTIIIIOOOONNNN
+
+ The rrdtool does also understand at-style time
+ specification. The specification is called "at-style"
+ after unix command _a_t(1) that has moderately complex ways
+ to specify time to run your job at. The at-style
+ specification consists of two parts: TTTTIIIIMMMMEEEE RRRREEEEFFFFEEEERRRREEEENNNNCCCCEEEE
+ specification and TTTTIIIIMMMMEEEE OOOOFFFFFFFFSSSSEEEETTTT specification.
+
+
+
+
+
+
+21/Apr/99 19990426.22 1
+
+
+
+
+
+RRDFETCH(1) rrdtool RRDFETCH(1)
+
+
+ TTTTIIIIMMMMEEEE RRRREEEEFFFFEEEERRRREEEENNNNCCCCEEEE SSSSPPPPEEEECCCCIIIIFFFFIIIICCCCAAAATTTTIIIIOOOONNNN
+
+ Time reference specification is used, well,... to
+ establish a reference moment in time (for time offset to
+ be applied to). When present, it should come first, when
+ omitted, it defaults to nnnnoooowwww. On its own part, time
+ reference consists of _t_i_m_e_-_o_f_-_d_a_y reference (which should
+ come first, if present) and _d_a_y reference.
+
+ _T_i_m_e_-_o_f_-_d_a_y can be specified as HHHHHHHH::::MMMMMMMM, HHHHHHHH....MMMMMMMM, HHHHHHHHMMMMMMMM, or
+ just HHHHHHHH, you can suffix it with aaaammmm or ppppmmmm or use 24-hours
+ clock. The few special times of day are understood as
+ well, these include mmmmiiiiddddnnnniiiigggghhhhtttt (00:00), nnnnoooooooonnnn (12:00) and
+ british tttteeeeaaaattttiiiimmmmeeee (16:00).
+
+ The _d_a_y can be specified as _m_o_n_t_h_-_n_a_m_e _d_a_y_-_o_f_-_t_h_e_-_m_o_n_t_h
+ and optional 2- or 4-digit _y_e_a_r number (e.g. March 8
+ 1999). Alternatively, you can use _d_a_y_-_o_f_-_w_e_e_k_-_n_a_m_e (e.g.
+ Monday), or one of the words: yyyyeeeesssstttteeeerrrrddddaaaayyyy, ttttooooddddaaaayyyy, ttttoooommmmoooorrrrrrrroooowwww.
+ You can also specify _d_a_y as a full date in several
+ numerical formats; these include: MMMMMMMM////DDDDDDDD////[[[[YYYYYYYY]]]]YYYYYYYY,
+ DDDDDDDD....MMMMMMMM....[[[[YYYYYYYY]]]]YYYYYYYY, DDDDDDDDMMMMMMMM[[[[YYYYYYYY]]]]YYYYYYYY (_N_O_T_E_1: this is different from
+ the original _a_t(1) behavior, which interprets a single-
+ number date as MMDD[YY]YY) _N_O_T_E_2: if you specify _d_a_y this
+ way, the _t_i_m_e_-_o_f_-_d_a_y is REQUIRED to be present in front of
+ it.
+
+ Finally, you can use words nnnnoooowwww, ssssttttaaaarrrrtttt, or eeeennnndddd as your time
+ reference. NNNNoooowwww refers to the current moment (and is also a
+ default time reference). SSSSttttaaaarrrrtttt (eeeennnndddd) can be used to
+ specify time relative to the start (end) time for those
+ tools that use these categories (rrdfetch, rrdgraph).
+
+ Month and weekday names can be used in their naturally
+ abbreviated form (e.g., Dec for December, Sun for Sunday,
+ etc.). The words nnnnoooowwww, ssssttttaaaarrrrtttt, eeeennnndddd can be abbreviated to nnnn,
+ ssss, eeee.
+
+ TTTTIIIIMMMMEEEE OOOOFFFFFFFFSSSSEEEETTTT SSSSPPPPEEEECCCCIIIIFFFFIIIICCCCAAAATTTTIIIIOOOONNNN
+
+ Time offset specification is used to add (or substract)
+ certain time interval to (from) the time reference moment.
+ It consists of _s_i_g_n (++++ or ----) and _a_m_o_u_n_t. The following
+ time units can be used to specify the _a_m_o_u_n_t: yyyyeeeeaaaarrrrssss,
+ mmmmoooonnnntttthhhhssss, wwwweeeeeeeekkkkssss, ddddaaaayyyyssss, hhhhoooouuuurrrrssss, mmmmiiiinnnnuuuutttteeeessss, sssseeeeccccoooonnnnddddssss, these can be
+ used in singular or plural form, and abbreviated naturally
+ or to a single letter (e.g. +3days, -1wk, -3y). Several
+ time units can be combined together (e.g., -5mon1w2d), as
+ well as several time offsets can be concatenated (e.g.,
+ -5h45min = -5h-45min = -6h+15min = -7h+1h30m-15min, etc.)
+
+ _N_O_T_E_3: If you specify time offset in days, weeks, months,
+ or years, you will end with the time offset that may vary
+ depending on you time reference, because all those time
+
+
+
+21/Apr/99 19990426.22 2
+
+
+
+
+
+RRDFETCH(1) rrdtool RRDFETCH(1)
+
+
+ units have no single well defined time interval value
+ (1 year contains either 365 or 366 days, 1 month is 28 to
+ 31 days long, and even 1 day may be not equal to 24 hours
+ twice a year, when DST-related clock adjustments take
+ place). To cope with this, when you use days, weeks,
+ months, or years as your time offset units your time
+ reference date is adjusted accordingly without taking too
+ much further effort to ensure anything about it (in the
+ hope that _m_k_t_i_m_e(3) will take care of this later). This
+ may lead to some surprising (or even invalid!) results,
+ e.g. 'May 31 -1month' = 'Apr 31' (meaningless) = 'May 1'
+ (after _m_k_t_i_m_e(3) normalization); in the EET timezone
+ '3:30am Mar 29 1999 -1 day' yields '3:30am Mar 28 1999'
+ (Sunday) which is invalid time/date combination (because
+ of 3am -> 4am DST forward clock ajustment, see the below
+ example). On the other hand, hours, minutes, and seconds
+ are well defined time intervals, and these are guaranteed
+ to always produce time offsets exactly as specified (e.g.
+ for EET timezone, '8:00 Mar 27 1999 +2 days' =
+ '8:00 Mar 29 1999', but since there is 1-hour DST forward
+ clock adjustment takes place around 3:00 Mar 28 1999, the
+ actual time interval between 8:00 Mar 27 1999 and
+ 8:00 Mar 29 1999 equals 47 hours; on the other hand,
+ '8:00 Mar 27 1999 +48 hours' = '9:00 Mar 29 1999', as
+ expected)
+
+ _N_O_T_E_4: The single-letter abbreviation for both mmmmoooonnnntttthhhhssss and
+ mmmmiiiinnnnuuuutttteeeessss is mmmm. To disambiguiate, the parser tries to read
+ your mind :) by applying the following two heuristics:
+
+ 1 If mmmm is used in context of (i.e. right after the)
+ years, months, weeks, or days it is assumed to mean
+ mmmmoooonnnntttthhhhssss, while in the context of hours, minutes, and
+ seconds it means minutes. (e.g., in -1y6m or +3w1m mmmm
+ means mmmmoooonnnntttthhhhssss, while in -3h20m or +5s2m mmmm means mmmmiiiinnnnuuuutttteeeessss)
+
+ 2 Out of context (i.e. right after the ++++ or ---- sign) the
+ meaning of mmmm is guessed from the number it directly
+ follows. Currently, if the number absolute value is
+ below 25 it is assumed that mmmm means mmmmoooonnnntttthhhhssss, otherwise
+ it is treated as mmmmiiiinnnnuuuutttteeeessss. (e.g., -25m == -25 minutes,
+ while +24m == +24 months)
+
+ _F_i_n_a_l _N_O_T_E_S: Time specification is case-insensitive.
+ Whitespace can be inserted freely or omitted altogether,
+ there are, however, cases when whitespace is required
+ (e.g., 'midnight Thu'). In this case you should either
+ quote the whole phrase to prevent it from bieng taken
+ apart by your shell or use '_' (underscore) or ',' (comma)
+ which also count as whitespace (e.g., midnight_Thu or
+ midnight,Thu)
+
+
+
+
+
+
+21/Apr/99 19990426.22 3
+
+
+
+
+
+RRDFETCH(1) rrdtool RRDFETCH(1)
+
+
+ TTTTIIIIMMMMEEEE SSSSPPPPEEEECCCCIIIIFFFFIIIICCCCAAAATTTTIIIIOOOONNNN EEEEXXXXAAAAMMMMPPPPLLLLEEEESSSS
+
+ _O_c_t _1_2 -- October 12 this year
+
+ _-_1_m_o_n_t_h or _-_1_m -- current time of day, only a month before
+ (may yield surprises, see the NOTE3 above)
+
+ _n_o_o_n _y_e_s_t_e_r_d_a_y _-_3_h_o_u_r_s -- yesterday morning; can be put
+ also as _9_a_m_-_1_d_a_y
+
+ _2_3_:_5_9 _3_1_._1_2_._1_9_9_9 -- 1 minute to the year 2000
+
+ _1_2_a_m _0_1_0_1_0_1 -- start of the new millenium
+
+ _e_n_d_-_3_w_e_e_k_s or _e_-_3_w -- 3 weeks before end time (may be used
+ as start time specification)
+
+ _s_t_a_r_t_+_6_h_o_u_r_s or _s_+_6_h -- 6 hours after start time (may be
+ used as end time specification)
+
+AAAAUUUUTTTTHHHHOOOORRRR
+ Tobias Oetiker <oetiker at ee.ethz.ch>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+21/Apr/99 19990426.22 4
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.html Sat Jul 13 18:46:10 2002
@@ -0,0 +1,84 @@
+ <HTML>
+ <HEAD>
+ <TITLE>dump - dump the contents of an B<RRD> in human readable form
+
+</TITLE>
+ </HEAD>
+
+ <BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+ <LI><A HREF="#NAME">NAME</A>
+ <LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+ <LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+ <LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME
+
+</A></H1>
+rrdtool dump - dump the contents of an <STRONG>RRD</STRONG> in human readable form
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS
+
+</A></H1>
+<STRONG>rrdtool</STRONG> <STRONG>dump</STRONG> <EM>filename</EM> [<STRONG>--full</STRONG>|<STRONG>-f</STRONG>]
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION
+
+</A></H1>
+The <STRONG>dump</STRONG> function prints the contents of an <STRONG>RRD</STRONG> in human readable form.
+
+
+<P>
+
+<DL>
+<DT><STRONG><A NAME="item_filename">filename
+
+</A></STRONG><DD>
+The name of the <STRONG>RRD</STRONG> you want to dump.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__full_f">--full|-f
+
+</A></STRONG><DD>
+By default only the headers of the <STRONG>RRD</STRONG> are printed. With this option you get the actual data as well.
+
+
+<P>
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR
+
+</A></H1>
+Tobias Oetiker <A
+HREF="MAILTO:<oetiker at ee.ethz.ch>"><oetiker at ee.ethz.ch></A>
+
+
+<P>
+
+</DL>
+ </BODY>
+
+ </HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.pod
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.pod (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.pod Sat Jul 13 18:46:10 2002
@@ -0,0 +1,187 @@
+=head1 NAME
+
+rrdtool fetch - fetch data from an rrd.
+
+=head1 SYNOPSIS
+
+B<rrdtool> B<fetch> I<filename> I<CF>
+S<[B<--resolution>|B<-r> I<resolution>]>
+S<[B<--start>|B<-s> I<start>]>
+S<[B<--end>|B<-e> I<end>]>
+
+=head1 DESCRIPTION
+
+The B<fetch> function is normally used internally by the graph function,
+to get data from B<RRD>s. B<fetch> will analyze the B<RRD> and
+will try to retrieve the data in the resolution requested.
+The data fetched is printed to stdout. I<*UNKNOWN*> data is often
+represented by the string "NaN" depending on your OSs printf
+function.
+
+=over 8
+
+=item I<filename>
+
+the name of the B<RRD> you want to fetch the data from.
+
+=item I<CF>
+
+which consolidation function should have been applied to the data you
+want to fetch? (AVERAGE,MIN,MAX,LAST)
+
+=item B<--resolution>|B<-r> I<resolution> (default is the highest resolution)
+
+what interval should the values have (seconds per value). B<rrdfetch> will try
+to match your request, but it will return data even if no absolute
+match is possible.
+
+=item B<--start>|B<-s> I<start> (default -24*3600)
+
+when should the data begin. A time in seconds since epoch (1970-01-01)
+is required. Negative numbers are relative to the end time. By default
+one day worth of data will be fetched. See also AT-STYLE TIME SPECIFICATION
+section for alternative ways to specify start time.
+
+=item B<--end>|B<-e> I<end> (default current time)
+
+when should the data end. Time in seconds since epoch. See also
+AT-STYLE TIME SPECIFICATION section for alternative ways to specify
+end time.
+
+=back
+
+=head2 AT-STYLE TIME SPECIFICATION
+
+The rrdtool does also understand at-style time specification.
+The specification is called "at-style" after unix command at(1)
+that has moderately complex ways to specify time to run your job at.
+The at-style specification consists of two parts: B<TIME REFERENCE>
+specification and B<TIME OFFSET> specification.
+
+=head2 TIME REFERENCE SPECIFICATION
+
+Time reference specification is used, well,... to establish a reference
+moment in time (for time offset to be applied to). When present,
+it should come first, when omitted, it defaults to B<now>. On its own part,
+time reference consists of I<time-of-day> reference (which should come
+first, if present) and I<day> reference.
+
+I<Time-of-day> can be specified as B<HH:MM>, B<HH.MM>, B<HHMM>,
+or just B<HH>, you can suffix it with B<am> or B<pm> or use
+24-hours clock. The few special times of day are understood as well,
+these include B<midnight> (00:00), B<noon> (12:00) and british
+B<teatime> (16:00).
+
+The I<day> can be specified as I<month-name> I<day-of-the-month>
+and optional 2- or 4-digit I<year> number (e.g. March 8 1999).
+Alternatively, you can use I<day-of-week-name> (e.g. Monday),
+or one of the words: B<yesterday>, B<today>, B<tomorrow>.
+You can also specify I<day> as a full date in several numerical formats;
+these include: B<MM/DD/[YY]YY>, B<DD.MM.[YY]YY>, B<DDMM[YY]YY>
+(I<NOTE1>: this is different from the original at(1) behavior,
+which interprets a single-number date as MMDD[YY]YY)
+I<NOTE2>: if you specify I<day> this way, the I<time-of-day> is REQUIRED
+to be present in front of it.
+
+Finally, you can use words B<now>, B<start>, or B<end> as your time
+reference. B<Now> refers to the current moment (and is also a default
+time reference). B<Start> (B<end>) can be used to specify time
+relative to the start (end) time for those tools that use these
+categories (rrdfetch, rrdgraph).
+
+Month and weekday names can be used in their naturally abbreviated form
+(e.g., Dec for December, Sun for Sunday, etc.). The words B<now>,
+B<start>, B<end> can be abbreviated to B<n>, B<s>, B<e>.
+
+=head2 TIME OFFSET SPECIFICATION
+
+Time offset specification is used to add (or substract) certain time
+interval to (from) the time reference moment. It consists of I<sign>
+(S<B<+> or B<->>) and I<amount>. The following time units can be used
+to specify the I<amount>: B<years>, B<months>, B<weeks>, B<days>,
+B<hours>, B<minutes>, B<seconds>, these can be used in singular
+or plural form, and abbreviated naturally or to a single letter
+(e.g. +3days, -1wk, -3y). Several time units can be combined
+together (e.g., -5mon1w2d), as well as several time offsets can be
+concatenated (e.g., -5h45min = -5h-45min = -6h+15min = -7h+1h30m-15min, etc.)
+
+I<NOTE3>: If you specify time offset in days, weeks, months, or years,
+you will end with the time offset that may vary depending on you time
+reference, because all those time units have no single well defined
+time interval value (S<1 year> contains either 365 or 366 days, S<1 month>
+is 28 to 31 days long, and even S<1 day> may be not equal to 24 hours
+twice a year, when DST-related clock adjustments take place).
+To cope with this, when you use days, weeks, months, or years
+as your time offset units your time reference date is adjusted
+accordingly without taking too much further effort to ensure anything
+about it (in the hope that mktime(3) will take care of this later).
+This may lead to some surprising (or even invalid!) results,
+e.g. S<'May 31 -1month'> = S<'Apr 31'> (meaningless) = S<'May 1'>
+(after mktime(3) normalization); in the EET timezone
+'3:30am Mar 29 1999 -1 day' yields '3:30am Mar 28 1999' (Sunday)
+which is invalid time/date combination (because of 3am -> 4am DST
+forward clock ajustment, see the below example).
+On the other hand, hours, minutes, and seconds are well defined time
+intervals, and these are guaranteed to always produce time offsets
+exactly as specified (e.g. for EET timezone, S<'8:00 Mar 27 1999 +2 days'> =
+S<'8:00 Mar 29 1999'>, but since there is 1-hour DST forward clock adjustment
+takes place around S<3:00 Mar 28 1999>, the actual time interval between
+S<8:00 Mar 27 1999> and S<8:00 Mar 29 1999> equals 47 hours; on the other hand,
+S<'8:00 Mar 27 1999 +48 hours'> = S<'9:00 Mar 29 1999'>, as expected)
+
+I<NOTE4>: The single-letter abbreviation for both B<months> and B<minutes>
+is B<m>. To disambiguiate, the parser tries to read your S<mind :)>
+by applying the following two heuristics:
+
+=over 3
+
+=item 1
+
+If B<m> is used in context of (i.e. right after the) years,
+months, weeks, or days it is assumed to mean B<months>, while
+in the context of hours, minutes, and seconds it means minutes.
+(e.g., in -1y6m or +3w1m B<m> means B<months>, while in
+-3h20m or +5s2m B<m> means B<minutes>)
+
+=item 2
+
+Out of context (i.e. right after the B<+> or B<-> sign) the
+meaning of B<m> is guessed from the number it directly follows.
+Currently, if the number absolute value is below 25 it is assumed
+that B<m> means B<months>, otherwise it is treated as B<minutes>.
+(e.g., -25m == -25 minutes, while +24m == +24 months)
+
+=back
+
+I<Final NOTES>: Time specification is case-insensitive.
+Whitespace can be inserted freely or omitted altogether,
+there are, however, cases when whitespace is required
+(e.g., S<'midnight Thu'>). In this case you should either quote the
+whole phrase to prevent it from bieng taken apart by your shell or use
+'_' (underscore) or ',' (comma) which also count as whitespace
+(e.g., midnight_Thu or midnight,Thu)
+
+
+=head2 TIME SPECIFICATION EXAMPLES
+
+I<Oct 12> -- October 12 this year
+
+I<-1month> or I<-1m> -- current time of day, only a month before
+(may yield surprises, see the NOTE3 above)
+
+I<noon yesterday -3hours> -- yesterday morning; can be put also as I<9am-1day>
+
+I<23:59 31.12.1999> -- 1 minute to the year 2000
+
+I<12am 010101> -- start of the new millenium
+
+I<end-3weeks> or I<e-3w> -- 3 weeks before end time
+(may be used as start time specification)
+
+I<start+6hours> or I<s+6h> -- 6 hours after start time
+(may be used as end time specification)
+
+=head1 AUTHOR
+
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.1
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.1 (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtune.1 Sat Jul 13 18:46:10 2002
@@ -0,0 +1,260 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+''' \*(L" and \*(R", except that they are used on ".xx" lines,
+''' such as .IP and .SH, which do another additional levels of
+''' double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH RRDTUNE 1 "19990426.22" "14/Jan/99" "rrdtool"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+rrdtool tune \- Modify some basic properties of a Round Robin Database
+.SH "SYNOPSIS"
+\fBrrdtool\fR \fBtune\fR \fIfilename\fR
+[\fB--heartbeat\fR|\fB\-h\fR\ \fIds-name\fR:\fIheartbeat\fR]
+[\fB--minimum\fR|\fB\-i\fR\ \fIds-name\fR:\fImin\fR]
+[\fB--maximum\fR|\fB\-a\fR\ \fIds-name\fR:\fImax\fR]
+[\fB--data-source-type\fR|\fB\-d\fR\ \fIds-name\fR:\fIDST\fR]
+[\fB--data-source-rename\fR|\fB\-r\fR\ \fIold-name\fR:\fInew-name\fR]
+.SH "DESCRIPTION"
+The tune option allows you to alter some of the basic configuration
+values stored in the header area of a Round Robin Database (\fBRRD\fR).
+All these tunable parameters together decide when data fed into an
+\fBRRD\fR is to be regarded as invalid. Invalid data is entered into the
+database as *UNKNOWN*.
+.PP
+The main application of the \fBtune\fR function is to relax the
+validation rules on an \fBRRD\fR. This allows to fill a new \fBRRD\fR with
+data available in larger intervals than what you would normally want
+to permit.
+.Ip "\fIfilename\fR" 8
+The name of the \fB\s-1RRD\s0\fR you want to tune.
+.Ip "\fB--heartbeat\fR|\fB\-h\fR\ \fIds-name\fR:\fIheartbeat\fR" 8
+modify the \fIheartbeat\fR of a data source. By setting this to a high
+value the rrd will accept things like one value per day ...
+.Ip "\fB--minimum\fR|\fB\-i\fR\ \fIds-name\fR:\fImin\fR" 8
+alter the minimum value acceptable as input from the data source.
+Setting \fImin\fR to \*(L'U\*(R' will disable this limit.
+.Ip "\fB--maximum\fR|\fB\-a\fR\ \fIds-name\fR:\fImax\fR" 8
+alter the maximum value acceptable as input from the data source.
+Setting \fImax\fR to \*(L'U\*(R' will disable this limit.
+.Ip "\fB--data-source-type\fR|\fB\-d\fR\ \fIds-name\fR:\fI\s-1DST\s0\fR" 8
+alter the type \fB\s-1DST\s0\fR of a data source.
+.Ip "[\fB--data-source-rename\fR|\fB\-r\fR\ \fIold-name\fR:\fInew-name\fR]" 8
+rename a data source
+.SH "EXAMPLE"
+\f(CWrrdtool tune data.rrd -h in:100000 -h in:100000 -h in:100000\fR
+.PP
+Set the minimum required heartbeat for data sources \*(L'in\*(R', \*(L'out\*(R'
+and \*(L'through\*(R' to 10000 seconds which is a little over one day in data.rrd.
+This would allow to feed old data from mrtg-2.0 right into
+rrdtool without generating *UNKNOWN* entries.
+.SH "AUTHOR"
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
+.rn }` ''
+.IX Title "RRDTUNE 1"
+.IX Name "rrdtool tune - Modify some basic properties of a Round Robin Database"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Item "\fIfilename\fR"
+
+.IX Item "\fB--heartbeat\fR|\fB\-h\fR\ \fIds-name\fR:\fIheartbeat\fR"
+
+.IX Item "\fB--minimum\fR|\fB\-i\fR\ \fIds-name\fR:\fImin\fR"
+
+.IX Item "\fB--maximum\fR|\fB\-a\fR\ \fIds-name\fR:\fImax\fR"
+
+.IX Item "\fB--data-source-type\fR|\fB\-d\fR\ \fIds-name\fR:\fI\s-1DST\s0\fR"
+
+.IX Item "[\fB--data-source-rename\fR|\fB\-r\fR\ \fIold-name\fR:\fInew-name\fR]"
+
+.IX Header "EXAMPLE"
+
+.IX Header "AUTHOR"
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.1
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.1 (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/bin_dec_hex.1 Sat Jul 13 18:46:10 2002
@@ -0,0 +1,573 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+''' \*(L" and \*(R", except that they are used on ".xx" lines,
+''' such as .IP and .SH, which do another additional levels of
+''' double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH BIN_DEC_HEX 1 "19990504.23" "4/May/99" "rrdtool"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+Binary Decimal Hexadecimal \- How does it wok
+.SH "DESCRIPTION"
+Most people use the decimal numbering system. This system uses ten
+symbols to represent numbers. When those ten symbols are used up, they
+start all over again and increment the position just before this. The
+digit 0 is only shown if it is the only symbol in the sequence, or if
+it is not the first one.
+.PP
+If this sounds as crypto to you, this is what I've said in numbers:
+.PP
+.Vb 14
+\& 0
+\& 1
+\& 2
+\& 3
+\& 4
+\& 5
+\& 6
+\& 7
+\& 8
+\& 9
+\& 10
+\& 11
+\& 12
+\& 13
+.Ve
+and so on.
+.PP
+Each time the digit nine should be incremented, it is reset to 0 and the
+position before is incremented. Then number 9 can be seen as \*(L"00009\*(R" and
+when we should increment 9, we reset it to zero and increment the digit
+just before the 9 so the number becomes \*(L"00010\*(R". For zero's we write a
+space if it is not the only digit (so: number 0) and if it is the first
+digit: \*(L"00010\*(R" \-> \*(L" 0010\*(R" \-> \*(L" 010\*(R" \-> \*(L" 10\*(R". It is not \*(L" 1 \*(L".
+.PP
+This was pretty basic, you already knew this. Why did I tell it ?
+Well, computers do not represent numbers with 10 different digits. They
+know of only two different symbols, being 0 and 1. Apply the same rules
+to this set of digits and you get the binary numbering system:
+.PP
+.Vb 14
+\& 0
+\& 1
+\& 10
+\& 11
+\& 100
+\& 101
+\& 110
+\& 111
+\& 1000
+\& 1001
+\& 1010
+\& 1011
+\& 1100
+\& 1101
+.Ve
+and so on.
+.PP
+If you count the number of rows, you'll see that these are again 14
+different numbers. The numbers are the same and mean the same. It is
+only a different representation. This means that you have to know the
+representation used, or as it is called the numbering system or base.
+Normally if we do not speak about the numbering system used, we're
+using the decimal system. If we are talking about another numbering
+system, we'll have to make that clear. There are a few wide-spread
+methods to do so. One common form is to write \fI1010\fR\|(2) which means that
+you wrote down a number in the binary form. It is the number ten.
+If you would write 1010 it means the number one thousand and ten.
+.PP
+In books, another form is most used. It uses subscript (little chars,
+more or less in between two rows). You can leave out the parentheses
+in that case and write down the number in normal characters followed
+with a little two just behind it.
+.PP
+The numbering system used is also called the base. We talk of the number
+1100 base 2, the number 12 base 10.
+.PP
+For the binary system, is is common to write leading zero's. The numbers
+are written down in series of four, eight or sixteen depending on the
+context.
+.PP
+We can use the binary form when talking to computers (...programming...)
+but the numbers will have large representations. The number 65535 would
+be written down as \fI1111111111111111\fR\|(2) which is 16 times the digit 1.
+This is difficult and prone to errors. Therefore we normally would use
+another base, called hexadecimal. It uses 16 different symbols. First
+the symbols from the decimal system are used, thereafter we continue
+with the alfabetic characters. We get 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A,
+B, C, D, E and F. This system is choosen because the hexadecimal form
+can be converted into the binary system very easy (and back).
+.PP
+There is yet another system in use, called the octal system. This was
+more common in the old days but not anymore. You will find it in use
+on some places so get used to it. The same story applies, but now with
+only eight different symbols.
+.PP
+.Vb 4
+\& Binary (2)
+\& Octal (8)
+\& Decimal (10)
+\& Hexadecimal (16)
+.Ve
+.Vb 23
+\& (2) (8) (10) (16)
+\& 00000 0 0 0
+\& 00001 1 1 1
+\& 00010 2 2 2
+\& 00011 3 3 3
+\& 00100 4 4 4
+\& 00101 5 5 5
+\& 00110 6 6 6
+\& 00111 7 7 7
+\& 01000 10 8 8
+\& 01001 11 9 9
+\& 01010 12 10 A
+\& 01011 13 11 B
+\& 01100 14 12 C
+\& 01101 15 13 D
+\& 01110 16 14 E
+\& 01111 17 15 F
+\& 10000 20 16 10
+\& 10001 21 17 11
+\& 10010 22 18 12
+\& 10011 23 19 13
+\& 10100 24 20 14
+\& 10101 25 21 15
+.Ve
+Most computers used nowadays are using bytes of eight bits. This means
+that they store eight bits at a time. You can see why the octal system
+is not the most preferred for that: You'd need three digits to represent
+the eight bits and this means that you'd have to use one complete digit
+to represent only two bits (2+3+3=8). This is a waste. For hexadecimal
+digits, you need only two digits which are used completely:
+.PP
+.Vb 2
+\& (2) (8) (10) (16)
+\& 11111111 377 255 FF
+.Ve
+You can see why binary and hexadecimal can be converted quickly:
+For each hexadecimal digit there are exactly four binary digits.
+Take a binary number. Each time take four digits from the right and make
+a hexadecimal digit from it (see the table above). Stop when there are
+no more digits.
+Other way around: Take a hexadecimal number. For each digit, write down
+its binary equivalent.
+.PP
+Computers (or rather the parsers running on them) would have a hard time
+converting a number like \fI1234\fR\|(16). Therefore hexadecimal numbers get a
+prefix. This prefix depends on the language you're writing in. Some of
+the prefixes are \*(L"0x\*(R" for C, \*(L"$\*(R" for pascal, \*(L"#\*(R" for HTML.
+It is common to assume that if a number starts with a zero, it is octal.
+It does not matter what is used as long as you know what it is.
+I will use \*(L"0x\*(R" for hexadecimal, \*(L"%\*(R" for binary and \*(L"0\*(R" for octal.
+The following numbers are all the same, just the way they are written is
+different: 021 0x11 17 \f(CW%00010001\fR
+.PP
+To do arithmetics and conversions you need to understand one more thing.
+It is something you already know but perhaps you do not \*(L"see\*(R" it yet:
+.PP
+If you write down 1234, (so it is decimal) you are talking about the
+number one thousand, two hundred and thirty four. In sort of a formula:
+.PP
+.Vb 4
+\& 1 * 1000 = 1000
+\& 2 * 100 = 200
+\& 3 * 10 = 30
+\& 4 * 1 = 4
+.Ve
+This can also be written as:
+.PP
+.Vb 4
+\& 1 * 10^3
+\& 2 * 10^2
+\& 3 * 10^1
+\& 4 * 10^0
+.Ve
+where ^ means \*(L"to the power of\*(R".
+.PP
+We are using the base 10, and the positions 0,1,2 and 3.
+The right-most position should NOT be multiplied with 10. The second
+from the right should be multiplied one time with 10. The third from
+the right is multiplied with 10 two times. This continues for whatever
+positions are used.
+.PP
+It is the same in all other representations:
+.PP
+0x1234 will be
+.PP
+.Vb 4
+\& 1 * 16^3
+\& 2 * 16^2
+\& 3 * 16^1
+\& 4 * 16^0
+.Ve
+01234 would be
+.PP
+.Vb 4
+\& 1 * 8^3
+\& 2 * 8^2
+\& 3 * 8^1
+\& 4 * 8^0
+.Ve
+This example can not be done for binary as that system can only use two
+symbols. Another example:
+.PP
+%1010 would be
+.PP
+.Vb 4
+\& 1 * 2^3
+\& 0 * 2^2
+\& 1 * 2^1
+\& 0 * 2^0
+.Ve
+It would have been more easy to convert it to its hexadecimal form and
+just translate \f(CW%1010\fR into 0xA. After a while you get used to it. You will
+not need to do any calculations anymore but just know that 0xA means 10.
+.PP
+To convert a decimal number into a hexadecimal one you could use the next
+method. It will take some time to be able to do the estimates but it will
+be more and more easy when you use the system more frequent. Another way
+is presented to you thereafter.
+.PP
+First you will need to know how many positions will be used in the other
+system. To do so, you need to know the maximum numbers. Well, that's not
+so hard as it looks. In decimal, the maximum number that you can form
+with two digits is \*(L"99\*(R". The maximum for three: \*(L"999\*(R". The next number
+would need an extra position. Reverse this idea and you will see that
+the number can be found by taking 10^3 (10*10*10 is 1000) minus 1 or
+10^2 minus one.
+.PP
+This can be done for hexadecimal too:
+.PP
+.Vb 4
+\& 16^4 = 0x10000 = 65536
+\& 16^3 = 0x1000 = 4096
+\& 16^2 = 0x100 = 256
+\& 16^1 = 0x10 = 16
+.Ve
+If a number is smaller than 65536 it will thus fit in four positions.
+If the number is bigger than 4095, you will need to use position 4.
+How many times can you take 4096 from the number without going below
+zero is the first digit you write down. This will always be a number
+from 1 to 15 (0x1 to 0xF). Do the same for the other positions.
+.PP
+Number is 41029. It is smaller than 16^4 but bigger than 16^3-1. This
+means that we have to use four positions.
+We can subtract 16^3 from 41029 ten times without going below zero.
+The leftmost digit will be \*(L"A\*(R" so we have 0xA????.
+The number is reduced to 41029 \- 10*4096 = 41029-40960 = 69.
+69 is smaller than 16^3 but not bigger than 16^2-1. The second digit
+is therefore \*(L"0\*(R" and we know 0xA0??.
+69 is smaller than 16^2 and bigger than 16^1-1. We can subtract 16^1
+(which is just plain 16) four times and write down \*(L"4\*(R" to get 0xA04?.
+Take 64 from 69 (69 \- 4*16) and the last digit is 5 --> 0xA045.
+.PP
+The other method builds the number from the right. Take again 41029.
+Divide by 16 and do not use fractions (only whole numbers).
+.PP
+.Vb 4
+\& 41029 / 16 is 2564 with a remainder of 5. Write down 5.
+\& 2564 / 16 is 160 with a remainder of 4. Write the 4 before the 5.
+\& 160 / 16 is 10 with no remainder. Prepend 45 with 0.
+\& 10 / 16 is below one. End here and prepend 0xA. End up with 0xA045.
+.Ve
+Which method to use is up to you. Use whatever works for you. Personally
+I use them both without being able to tell what method I use in each
+case, it just depends on the number, I think. Fact is, some numbers
+will occur frequently while programming, if the number is close then
+I will use the first method (like 32770, translate into 32768 + 2 and
+just know that it is 0x8000 + 0x2 = 0x8002).
+.PP
+For binary the same approach can be used. The base is 2 and not 16,
+and the number of positions will grow rapidly. Using the second method
+has the advantage that you can see very simple if you should write down
+a zero or a one: if you divide by two the remainder will be zero if it
+was an even number and one if it was an odd number:
+
+ 41029 / 2 = 20514 remainder 1
+ 20514 / 2 = 10257 remainder 0
+ 10257 / 2 = 5128 remainder 1
+ 5128 / 2 = 2564 remainder 0
+ 2564 / 2 = 1282 remainder 0
+ 1282 / 2 = 641 remainder 0
+ 641 / 2 = 320 remainder 1
+ 320 / 2 = 160 remainder 0
+ 160 / 2 = 80 remainder 0
+ 80 / 2 = 40 remainder 0
+ 40 / 2 = 20 remainder 0
+ 20 / 2 = 10 remainder 0
+ 10 / 2 = 5 remainder 0
+ 5 / 2 = 2 remainder 1
+ 2 / 2 = 1 remainder 0
+ 1 / 2 below 0 remainder 1
+.PP
+Write down the results from right to left: \f(CW%1010000001000101\fR
+.PP
+Group by four:
+.PP
+.Vb 4
+\& %1010000001000101
+\& %101000000100 0101
+\& %10100000 0100 0101
+\& %1010 0000 0100 0101
+.Ve
+Convert into hexadecimal: 0xA045
+.PP
+Group \f(CW%1010000001000101\fR by three and convert into octal:
+.PP
+.Vb 8
+\& %1010000001000101
+\& %1010000001000 101
+\& %1010000001 000 101
+\& %1010000 001 000 101
+\& %1010 000 001 000 101
+\& %1 010 000 001 000 101
+\& %001 010 000 001 000 101
+\& 1 2 0 1 0 5 --> 0120105
+.Ve
+.Vb 3
+\& So: %1010000001000101 = 0120105 = 0xA045 = 41029
+\& Or: 1010000001000101(2) = 120105(8) = A045(16) = 41029(10)
+\& Or: 1010000001000101(2) = 120105(8) = A045(16) = 41029
+.Ve
+At first while adding numbers, you'll convert them to their decimal
+form and then back into their original form after doing the addition.
+If you use the other numbering system often, you will see that you'll
+be able to do arithmetics in the base that is used.
+In any representation it is the same, add the numbers on the right,
+write down the rightmost digit from the result, remember the other
+digits and use them in the next round. Continue with the second digits
+from the right and so on:
+.PP
+.Vb 1
+\& %1010 + %0111 --> 10 + 7 --> 17 --> %00010001
+.Ve
+will become
+.PP
+.Vb 10
+\& %1010
+\& %0111 +
+\& ||||
+\& |||+-- add 0 + 1, result is 1, nothing to remember
+\& ||+--- add 1 + 1, result is %10, write down 0 and remember 1
+\& |+---- add 0 + 1 + 1(remembered), result = 0, remember 1
+\& +----- add 1 + 0 + 1(remembered), result = 0, remember 1
+\& nothing to add, 1 remembered, result = 1
+\& --------
+\& %10001 is the result, I like to write it as %00010001
+.Ve
+For low values, try to do the calculations yourself, check them with
+a calculator. The more you do the calculations yourself, the more you
+find that you didn't make mistakes. In the end, you'll do calcula in
+other bases as easy as you do in decimal.
+.PP
+When the numbers get bigger, you'll have to realise that a computer is
+not called a computer just to have a nice name. There are many different
+calculators available. Use them. For unix you could use \*(L"bc\*(R" which is
+called so as it is short for Binary Calculator. It calculates not only
+in decimal, but in all bases you'll ever use (among them Binary).
+.PP
+For people on Windows:
+Start the calculator (start->programs->accessories->calculator)
+and if necessary click view->scientific. You now have a scientific
+calculator and can compute in binary or hexadecimal.
+.SH "AUTHOR"
+I hope you enjoyed the examples and their descriptions. If you do, help
+other people by pointing them to this document when they are asking
+basic questions. They will not only get their answer but at the same
+time learn a whole lot more.
+.PP
+Alex van den Bogaerdt
+<alex at ergens.op.het.net>
+
+.rn }` ''
+.IX Title "BIN_DEC_HEX 1"
+.IX Name "Binary Decimal Hexadecimal - How does it wok"
+
+.IX Header "NAME"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "AUTHOR"
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.txt
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.txt (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.txt Sat Jul 13 18:46:10 2002
@@ -0,0 +1,528 @@
+
+
+
+RRDGRAPH(1) rrdtool RRDGRAPH(1)
+
+
+NNNNAAAAMMMMEEEE
+ rrdtool graph - Create a graph based on data from one or
+ several RRD
+
+SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
+ rrrrrrrrddddttttoooooooollll ggggrrrraaaapppphhhh _f_i_l_e_n_a_m_e [----ssss|--------ssssttttaaaarrrrtttt _s_e_c_o_n_d_s]
+ [----eeee|--------eeeennnndddd _s_e_c_o_n_d_s] [----xxxx|--------xxxx----ggggrrrriiiidddd _x_-_a_x_i_s _g_r_i_d _a_n_d _l_a_b_e_l]
+ [----yyyy|--------yyyy----ggggrrrriiiidddd _y_-_a_x_i_s _g_r_i_d _a_n_d _l_a_b_e_l]
+ [----vvvv|--------vvvveeeerrrrttttiiiiccccaaaallll----llllaaaabbbbeeeellll _t_e_x_t] [----wwww|--------wwwwiiiiddddtttthhhh _p_i_x_e_l_s]
+ [----hhhh|--------hhhheeeeiiiigggghhhhtttt _p_i_x_e_l_s] [----iiii|--------iiiinnnntttteeeerrrrllllaaaacccceeeedddd] [----oooo|--------llllooooggggaaaarrrriiiitttthhhhmmmmiiiicccc]
+ [----uuuu|--------uuuuppppppppeeeerrrr----lllliiiimmmmiiiitttt _v_a_l_u_e] [----llll|--------lllloooowwwweeeerrrr----lllliiiimmmmiiiitttt _v_a_l_u_e]
+ [----rrrr|--------rrrriiiiggggiiiidddd] [----bbbb|--------bbbbaaaasssseeee _v_a_l_u_e]
+ [----cccc|--------ccccoooolllloooorrrr _C_O_L_O_R_T_A_G####_r_r_g_g_b_b] [----tttt|--------ttttiiiittttlllleeee _t_i_t_l_e]
+ [DDDDEEEEFFFF::::_v_n_a_m_e====_r_r_d::::_d_s_-_n_a_m_e::::_C_F] [CCCCDDDDEEEEFFFF::::_v_n_a_m_e====_r_p_n_-_e_x_p_r_e_s_s_i_o_n]
+ [PPPPRRRRIIIINNNNTTTT::::_v_n_a_m_e::::_C_F::::_f_o_r_m_a_t] [GGGGPPPPRRRRIIIINNNNTTTT::::_v_n_a_m_e::::_C_F::::_f_o_r_m_a_t]
+ [CCCCOOOOMMMMMMMMEEEENNNNTTTT::::_t_e_x_t] [HHHHRRRRUUUULLLLEEEE::::_v_a_l_u_e####_r_r_g_g_b_b[::::_l_e_g_e_n_d]]
+ [VVVVRRRRUUUULLLLEEEE::::_t_i_m_e####_r_r_g_g_b_b[::::_l_e_g_e_n_d]]
+ [LLLLIIIINNNNEEEE{1111|2222|3333}::::_v_n_a_m_e[####_r_r_g_g_b_b[::::_l_e_g_e_n_d]]]
+ [AAAARRRREEEEAAAA::::_v_n_a_m_e[####_r_r_g_g_b_b[::::_l_e_g_e_n_d]]]
+ [SSSSTTTTAAAACCCCKKKK::::_v_n_a_m_e[####_r_r_g_g_b_b[::::_l_e_g_e_n_d]]]
+
+DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
+ The ggggrrrraaaapppphhhh functions main purpose is to create graphical
+ representations of the data stored in one or several RRRRRRRRDDDDs.
+ Apart from generating graphs, it can also extract
+ numerical reports.
+
+ _f_i_l_e_n_a_m_e
+ The name of the graph to generate. Since rrrrrrrrddddttttoooooooollll
+ outputs GIF's, it's recommended that the filename
+ end in _._g_i_f. rrrrrrrrddddttttoooooooollll does not enforce this,
+ however. If the _f_i_l_e_n_a_m_e is et to '-' the gif
+ file will be written to standard out. All other
+ output will get supressd.
+
+ If no graph functions are called, the graph will
+ not be created.
+
+ ----ssss|--------ssssttttaaaarrrrtttt _s_e_c_o_n_d_s (default -24*3600)
+ The time when the graph should begin. Time in
+ seconds since epoch (1970-01-01) is required.
+ Negative numbers are relative to the end time. By
+ default one day worth of data will be graphed.
+ See also AT-STYLE TIME SPECIFICATION section in
+ the _r_r_d_f_e_t_c_h documentation for alternative ways to
+ specify start time.
+
+ ----eeee|--------eeeennnndddd _s_e_c_o_n_d_s (default current time)
+ The time when the graph should end. Time in
+ seconds since epoch. See also AT-STYLE TIME
+ SPECIFICATION section in the _r_r_d_f_e_t_c_h
+ documentation for alternative ways to specify end
+ time.
+
+
+
+
+4/May/99 19990504.23 1
+
+
+
+
+
+RRDGRAPH(1) rrdtool RRDGRAPH(1)
+
+
+ ----xxxx|--------xxxx----ggggrrrriiiidddd _x_-_a_x_i_s _g_r_i_d _a_n_d _l_a_b_e_l (default autoconfigure)
+ The x-axis label is quite complex to configure. So
+ if you don't have very special needs, you can
+ relay on the autoconfiguration to get this right.
+
+ The x-axis label is configured, using the
+ following format:
+
+ _G_T_M::::_G_S_T::::_M_T_M::::_M_S_T::::_L_T_M:_L_S_T::::_L_P_R::::_L_F_M
+
+ You have to configure three elements making up the
+ x-axis labels and grid. The base grid (_G_?_?), the
+ major grid (_M_?_?) and the labels (_L_?_?). The
+ configuration is based on the idea that you first
+ specify a well known amount of time (_?_T_M) and then
+ say how many times it has to pass between each
+ grid line or label (_?_S_T). For the label you have
+ to define two additional items: The precision of
+ the label in seconds (_L_P_R) and the strftime format
+ used to generate the text of the label (_L_F_M).
+
+ The _?_T_M elements must be one of the following
+ keywords: SSSSEEEECCCCOOOONNNNDDDD, MMMMIIIINNNNUUUUTTTTEEEE, HHHHOOOOUUUURRRR, DDDDAAAAYYYY, WWWWEEEEEEEEKKKK, MMMMOOOONNNNTTTTHHHH
+ or YYYYEEEEAAAARRRR.
+
+ If you wanted a graph with a base grid every 10
+ minutes and a major one every hour, with labels
+ every hour you would use the following x-axis
+ definition.
+
+ MINUTE:10:HOUR:1:HOUR:1:0:%X
+
+ The precision in this example is 0 because the %X
+ format is exact. If the label was the name of the
+ day, we would have had a precision of 24 hours,
+ because when you say something like 'Monday' you
+ mean the whole day and not Monday morning 00:00.
+ Thus the label should be positioned at noon. By
+ defining a precision of 24 hours or rather 86400
+ seconds, you make sure that this happens.
+
+ ----yyyy--------yyyy----ggggrrrriiiidddd _g_r_i_d _s_t_e_p:_l_a_b_e_l _f_a_c_t_o_r (default autoconfigure)
+ Makes vertical grid lines appear at _g_r_i_d _s_t_e_p
+ interval. Every _l_a_b_e_l _f_a_c_t_o_r gridstep, a major
+ grid line is printed, along with label showing the
+ value of the grid line.
+
+ ----vvvv|--------vvvveeeerrrrttttiiiiccccaaaallll----llllaaaabbbbeeeellll _t_e_x_t
+ vertical label on the left side of the graph. This
+ is normally used to specify the units used.
+
+ ----wwww|--------wwwwiiiiddddtttthhhh _p_i_x_e_l_s (default 400 pixel)
+ Width of the drawing area within the graph. This
+ affects the size of the gif.
+
+
+
+4/May/99 19990504.23 2
+
+
+
+
+
+RRDGRAPH(1) rrdtool RRDGRAPH(1)
+
+
+ ----hhhh|--------hhhheeeeiiiigggghhhhtttt _p_i_x_e_l_s (default 100 pixel)
+ Width of the drawing area within the graph. This
+ affects the size of the gif.
+
+ ----iiii|--------iiiinnnntttteeeerrrrllllaaaacccceeeedddd (default: false)
+ If you set this option, then the resulting GIF
+ will be interlaced. Most web browsers display
+ these incrementally as they load. If you do not
+ use this option, the GIFs default to being
+ progressive scanned. The only effect of this
+ option is to control the format of the GIF on
+ disk. It makes no changes to the layout or
+ contents of the graph.
+
+ ----uuuu|--------uuuuppppppppeeeerrrr----lllliiiimmmmiiiitttt _v_a_l_u_e (default autoconfigure)
+ The maximum value to be graphed. By default This
+ will be autoconfigured from the data you select
+ with the graphing functions.
+
+ ----llll|--------lllloooowwwweeeerrrr----lllliiiimmmmiiiitttt _v_a_l_u_e (default autoconfigure)
+ The minimum value to be graphed. By default This
+ will be autoconfigured from the data you select
+ with the graphing functions.
+
+ ----rrrr|--------rrrriiiiggggiiiidddd
+ rigid boundaries mode. Normally rrdgraph will
+ automatically expand the lower and upper limit if
+ the graph contains a value outside the valid
+ range. With the r option you can disable this
+ behavior
+
+ ----bbbb|--------bbbbaaaasssseeee _v_a_l_u_e
+ if you are graphing memmory (and NOT network
+ traffic) this switch should be set to 1024 so that
+ one Kb is 1024 byte. For traffic measurement, 1
+ kb/s is 1000 b/s.
+
+ ----oooo|--------llllooooggggaaaarrrriiiitttthhhhmmmmiiiicccc
+ logarithmic y-axis scaling
+
+ ----cccc|--------ccccoooolllloooorrrr _C_O_L_O_R_T_A_G####_r_r_g_g_b_b (default colors)
+ override the colors for the standard elements of
+ the graph. The _C_O_L_O_R_T_A_G must be one of the
+ following symbolic names: BBBBAAAACCCCKKKK ground, CCCCAAAANNNNVVVVAAAASSSS,
+ SSSSHHHHAAAADDDDEEEEAAAA left/top border, SSSSHHHHAAAADDDDEEEEBBBB right/bottom
+ border, GGGGRRRRIIIIDDDD, MMMMGGGGRRRRIIIIDDDD major grid, FFFFOOOONNNNTTTT, FFFFRRRRAAAAMMMMEEEE and
+ axis of the graph or AAAARRRRRRRROOOOWWWW. This option can be
+ called multiple times to set several colors.
+
+ ----tttt|--------ttttiiiittttlllleeee _t_e_x_t (default no title)
+ Define a title to be written into the graph
+
+ DDDDEEEEFFFF::::_v_n_a_m_e====_r_r_d::::_d_s_-_n_a_m_e::::_C_F
+ Define virtual name for a data source. This name
+
+
+
+4/May/99 19990504.23 3
+
+
+
+
+
+RRDGRAPH(1) rrdtool RRDGRAPH(1)
+
+
+ can then be used in the functions explained below.
+ The DEF call automatically chooses an RRRRRRRRAAAA which
+ provides data in a resolution appropriate for the
+ size of the graph to be drawn. Ideally this means
+ that one data point from the RRRRRRRRAAAA should be
+ represented by one pixel in the graph. If the
+ resolution of the RRRRRRRRAAAA is higher than the
+ resolution of the graph, the data in the RRA will
+ be consolidated according to the consolidation
+ function (_C_F) chosen.
+
+ CCCCDDDDEEEEFFFF::::_v_n_a_m_e====_r_p_n_-_e_x_p_r_e_s_s_i_o_n
+ Create a new virtual data source by evaluating a
+ mathematical expression, specified in Reverse
+ Polish Notation (RPN). If you have ever used a
+ traditional HP calculator you already know RPN.
+ The idea behind RPN notation is, that you have a
+ stack and push your data onto this stack. When
+ ever you execute an operation, it takes as many
+ data values from the stack as needed. The pushing
+ of data is implicit, so when ever you specify a
+ number or a variable, it gets pushed
+ automatically.
+
+ If this is all a big load of incomprehensible
+ words for you, maybe an example helps (a more
+ complete explanation is given in [1]): The
+ expression vname+3/2 becomes vname,3,2,/,+ in RPN.
+ First the three values get pushed onto the stack
+ (which now contains (the current value of) vname,
+ a 3 and a 2). Then the / operator pops two values
+ from the stack (3 and 2), divides the first
+ argument by the second (3/2) and pushes the result
+ (1.5) back onto the stack. Then the + operator
+ pops two values (vname and 1.5) from the stack;
+ both values are added up and the result gets
+ pushes back onto the stack. In the end there is
+ only one value left on the stack: The result of
+ the expression.
+
+ The _r_p_n_-_e_x_p_r_e_s_s_i_o_n in the CCCCDDDDEEEEFFFF function takes
+ both, constant values as well as _v_n_a_m_e variables.
+ The following operators can be used on these
+ values:
+
+ +, -, *, / pops two values from the stack applies the
+ selected operator and pushes the result
+ back onto the stack.
+
+ SIN, COS, LOG, EXP
+ pops one value from the stack, applies the
+ selected function and pushes the result
+ back onto the stack.
+
+
+
+
+4/May/99 19990504.23 4
+
+
+
+
+
+RRDGRAPH(1) rrdtool RRDGRAPH(1)
+
+
+ LT, LE, GT, GE, EQ
+ pops two values from the stack, compares
+ them according to the selected condition
+ and pushes either 1 back onto the stack if
+ the condition is true and 0 if the
+ condition was not true.
+
+ IF pops three values from the stack. If the
+ last value is not 0, the second value will
+ be pushed back onto the stack, otherwise
+ the first value is pushed back.
+
+ If the stack contains the values A, B, C,
+ D, E are presently on the stack, the IF
+ operator will pop the values E D and C of
+ the stack. It will look at C and if it is
+ not 0 it will push D back onto the stack,
+ otherwise E will be sent back to the
+ stack.
+
+ UN Pops one value of the stack, if it is
+ _*_U_N_K_N_O_W_N_*, 1 will be pushed back otherwise
+ 0.
+
+ Please note that you may only use _v_n_a_m_e
+ variables that you previously defined by
+ either DDDDEEEEFFFF or CCCCDDDDEEEEFFFF. Furthermore, as of
+ this writing (version 0.99.25), you must
+ use at least one _v_n_a_m_e per expression,
+ that is "CDEF:fourtytwo=2,40,+" will yield
+ an error message but not a _v_n_a_m_e fourtytwo
+ that's always equal to 42.
+
+ PPPPRRRRIIIINNNNTTTT::::_v_n_a_m_e::::_C_F::::_f_o_r_m_a_t
+ Calculate the chosen consolidation function _C_F
+ over the data-source variable _v_n_a_m_e and printf the
+ result to stdout using _f_o_r_m_a_t.
+
+ GGGGPPPPRRRRIIIINNNNTTTT::::_v_n_a_m_e::::_C_F::::_f_o_r_m_a_t
+ Same as PPPPRRRRIIIINNNNTTTT but the result is printed into the
+ graph below the legend.
+
+ CCCCOOOOMMMMMMMMEEEENNNNTTTT::::_t_e_x_t
+ Like GGGGPPPPRRRRIIIINNNNTTTT but the _t_e_x_t is simply printed into
+ the graph.
+
+ HHHHRRRRUUUULLLLEEEE::::_v_a_l_u_e####_r_r_g_g_b_b[::::_l_e_g_e_n_d]
+ Draw a horizontal rule into the graph and
+ optionally add a legend
+
+ VVVVRRRRUUUULLLLEEEE::::_t_i_m_e####_r_r_g_g_b_b[::::_l_e_g_e_n_d]
+ Draw a vertical rule into the graph and optionally
+ add a legend
+
+
+
+
+4/May/99 19990504.23 5
+
+
+
+
+
+RRDGRAPH(1) rrdtool RRDGRAPH(1)
+
+
+ LLLLIIIINNNNEEEE{1111|2222|3333}::::_v_n_a_m_e[####_r_r_g_g_b_b[::::_l_e_g_e_n_d]]
+ Plot for the requested data, using the color
+ specified. Write a legend into the graph. The 3
+ possible keywords LLLLIIIINNNNEEEE1111, LLLLIIIINNNNEEEE2222, and LLLLIIIINNNNEEEE3333 generate
+ increasingly wide lines. If no color is defined,
+ the drawing is done 'blind' this is useful in
+ connection with the SSSSTTTTAAAACCCCKKKK function when you want
+ to ADD the values of two data-sources without
+ showing it in the graph.
+
+ AAAARRRREEEEAAAA:_v_n_a_m_e[####_r_r_g_g_b_b[::::_l_e_g_e_n_d]]
+ Does the same as LLLLIIIINNNNEEEE????, but the area between 0 and
+ the graph will be filled with the color specified.
+
+ SSSSTTTTAAAACCCCKKKK:_v_n_a_m_e[####_r_r_g_g_b_b[::::_l_e_g_e_n_d]]
+ Does the same as LLLLIIIINNNNEEEE????, but the graph gets stacked
+ on top of the previous LLLLIIIINNNNEEEE????, AAAARRRREEEEAAAA or SSSSTTTTAAAACCCCKKKK graph.
+ Depending on the type of the previous graph, the
+ SSSSTTTTAAAACCCCKKKK will be either a LLLLIIIINNNNEEEE???? or an AAAARRRREEEEAAAA. This
+ obviously implies that the first SSSSTTTTAAAACCCCKKKK must be
+ preceeded by an AAAARRRREEEEAAAA or LLLLIIIINNNNEEEE???? -- you need
+ something to stack something onto in the first
+ place ;)
+
+NNNNOOOOTTTTEEEE
+ In a ':' in a _l_e_g_e_n_d argument will mark the end of the
+ legend. To enter a ':' into a legend, the colon must be
+ escaped with a backslash '\:'. Beware, that many
+ environments look for backslashes themselves, so it may be
+ necessary to write two backslashes so that one is passed
+ onto rrd_graph.
+
+NNNNOOOOTTTTEEEE 2222
+ The text printed below the actual graph can be formated by
+ appending special escaped charactes at the end of a text.
+ When ever such a character occurs, all pending text is
+ pushed onto the grah acording to the character specified.
+
+ Valid characters are: jjjj for justified, llll for left aligned,
+ rrrr for right aligned and cccc for centered. In the next
+ section there is an example showing how to use centered
+ formating.
+
+ A special case is COMMENT:\s this inserts some additional
+ vertical space before placing the next row of legends.
+
+NNNNOOOOTTTTEEEE 3333
+ Whenever rrd_graph gets called, it prints a line telling
+ the size of the gif it has just created to STDOUT. This
+ line looks like this: XSIZExYSIZE.
+
+EEEEXXXXAAAAMMMMPPPPLLLLEEEE
+
+
+
+
+
+4/May/99 19990504.23 6
+
+
+
+
+
+RRDGRAPH(1) rrdtool RRDGRAPH(1)
+
+
+ rrdtool graph demo.gif --title="Demo Graph" \
+ DEF:cel=demo.rrd:exhaust:AVERAGE \
+ "CDEF:far=cel,32,-,0.55555,*" \
+ LINE2:cel#00a000:"D. Celsius" \
+ LINE2:far#ff0000:"D. Fahrenheit\c"
+
+
+AAAAUUUUTTTTHHHHOOOORRRR
+ Tobias Oetiker <oetiker at ee.ethz.ch>
+
+RRRREEEEFFFFEEEERRRREEEENNNNCCCCEEEESSSS
+ [1] http://www.dotpoint.com/xnumber/rpn_or_adl.htm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4/May/99 19990504.23 7
+
+
+
+
+
+RRDGRAPH(1) rrdtool RRDGRAPH(1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4/May/99 19990504.23 8
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.html Sat Jul 13 18:46:11 2002
@@ -0,0 +1,297 @@
+ <HTML>
+ <HEAD>
+ <TITLE>rrdtool - round robin database tool
+
+</TITLE>
+ </HEAD>
+
+ <BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+ <LI><A HREF="#NAME">NAME</A>
+ <LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+ <LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+ <UL>
+
+ <LI><A HREF="#OVERVIEW">OVERVIEW</A>
+ <LI><A HREF="#FUNCTIONS">FUNCTIONS</A>
+ <LI><A HREF="#HOW_DOES_RRDTOOL_WORK_">HOW DOES RRDTOOL WORK?</A>
+ <LI><A HREF="#REMOTE_CONTROL">REMOTE CONTROL</A>
+ </UL>
+
+ <LI><A HREF="#SEE_ALSO">SEE ALSO</A>
+ <LI><A HREF="#BUGS">BUGS</A>
+ <LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME
+
+</A></H1>
+rrdtool - round robin database tool
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS
+
+</A></H1>
+<STRONG>rrdtool</STRONG> <STRONG>-</STRONG> | <EM>function</EM>
+
+
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION
+
+</A></H1>
+<P>
+<HR>
+<H2><A NAME="OVERVIEW">OVERVIEW
+
+</A></H2>
+It is pretty easy to gather status information from all sorts of things,
+ranging from the temperature in your office to the number of octets which
+have passed through the FDDI interface of your router. But it is not so
+trivial to store this data in a efficient and systematic manner. This is
+where <STRONG>rrdtool</STRONG> kicks in. It lets you
+<EM>log and analyze</EM> the data you gather from all kinds of data-sources (<STRONG>DS</STRONG>). The data analysis part of rrdtool is based on the ability to quickly
+generate graphical representations of the data values collected over a
+definable time period.
+
+
+<P>
+
+In this man page you will find general information on the design and
+functionality of the Round Robin Database Tool (rrdtool). For a more
+detailed description of how to use the individual functions of the
+<STRONG>rrdtool</STRONG> check the corresponding man page.
+
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="FUNCTIONS">FUNCTIONS
+
+</A></H2>
+While the man pages talk of command line switches you have to set in order
+to make <STRONG>rrdtool</STRONG> work it is important to note that the <STRONG>rrdtool</STRONG> can be 'remote controlled' through a set of pipes. This saves a
+considerable amount of startup time when you plan to make <STRONG>rrdtool</STRONG> do a lot of things quickly. Check the section on <A HREF="#Remote_Control">Remote Control</A> further down.
+
+
+<P>
+
+<DL>
+<DT><STRONG><A NAME="item_create">create
+
+</A></STRONG><DD>
+Set up a new Round Robin Database (RRD). Check rrdcreate
+
+
+<P>
+
+<DT><STRONG><A NAME="item_update">update
+
+</A></STRONG><DD>
+Store new data values into an RRD. Check rrdupdate
+
+
+<P>
+
+<DT><STRONG><A NAME="item_graph">graph
+
+</A></STRONG><DD>
+Create a graph from data stored in one or several RRD. Apart from
+generating graphs, data can also be extracted to stdout. Check rrdgraph
+
+
+<P>
+
+<DT><STRONG><A NAME="item_dump">dump
+
+</A></STRONG><DD>
+Dump the contents of an RRD in plain ASCII. This is manly used for
+debugging. Check rrddump
+
+
+<P>
+
+<DT><STRONG><A NAME="item_fetch">fetch
+
+</A></STRONG><DD>
+Get data for a certain time period from a RRD. The graph function uses
+fetch to retrieve its data from an rrd. Check rrdfetch
+
+
+<P>
+
+<DT><STRONG><A NAME="item_tune">tune
+
+</A></STRONG><DD>
+Alter setup of an RRD
+
+
+<P>
+
+<DT><STRONG><A NAME="item_last">last
+
+</A></STRONG><DD>
+Find last update time of an RRD
+
+
+<P>
+
+</DL>
+<P>
+<HR>
+<H2><A NAME="HOW_DOES_RRDTOOL_WORK_">HOW DOES RRDTOOL WORK?
+
+</A></H2>
+<DL>
+<DT><STRONG><A NAME="item_Data">Data acquisition
+
+</A></STRONG><DD>
+When monitoring the state of a system, it is convenient to have the data
+available at a constant interval. Unfortunately you may not always be able
+to fetch data at exactly the time you want to. Therefore <STRONG>rrdtool</STRONG> lets you update the logfile at any time you want. It will automatically
+interpolate the value of the data-source (<STRONG>DS</STRONG>) at the latest official time-slot and write this value to the log. The
+value you have supplied is stored as well and is also taken into account
+when interpolating the next log entry.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_Consolidation">Consolidation
+
+</A></STRONG><DD>
+You may log data at a 1 minute interval, but you are also be interested to
+know the development of the data over the last year. You could do this by
+simply storing the data in 1 minute interval, for one year. While this
+would take considerable disk space it would also take a lot of time to
+analyze the data when you wanted to create a graph covering the whole year. <STRONG>rrdtool</STRONG> offers a solution to this of this problem through its data consolidation
+feature. When setting up an Round Robin Database (<STRONG>RRD</STRONG>), you can define at which interval this consolidation should occur, and
+what consolidation function (<STRONG>CF</STRONG>) (average, minimum, maximum, total, last) should be used to build the
+consolidated values (see rrdcreate). You can define any number of different
+consolidation setups within one <STRONG>RRD</STRONG>. They will all be maintained on the fly when new data is loaded into the <STRONG>RRD</STRONG>.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_Round">Round Robin Archives
+
+</A></STRONG><DD>
+Data values of the same consolidation setup are stored into Round Robin
+Archives (<STRONG>RRA</STRONG>). This is a very efficient manner to store data for a certain amount of
+time, while using a known amount of storage space.
+
+
+<P>
+
+It works like this: If you want to store 1000 values in 5 minute interval, <STRONG>rrdtool</STRONG> will allocate space for 1000 data values and a header area. In the header
+it will store a pointer telling which one of the values in the storage area
+was last written to. New values are written to the Round Robin Archive in a
+... you guess it ... round robin manner. This automatically limits the
+history to the last 1000 values. Because you can define several <STRONG>RRA</STRONG>s within a single <STRONG>RRD</STRONG>, you can setup another one, storing 750 data values at a 2 hour interval
+and thus keeping a log for the last two months although at a lower
+resolution.
+
+
+<P>
+
+The use of <STRONG>RRA</STRONG>s guarantees that the <STRONG>RRD</STRONG> does not grow over time and that old data is automatically eliminated. By
+using the consolidation feature, you can still keep data for a very long
+time, while gradually reducing the resolution of the data along the time
+axis. Using different consolidation functions (<STRONG>CF</STRONG>) allows you to store exactly the type of information that actually
+interests you. (Maximum one minute traffic on the LAN, minimum temperature
+of the wine cellar, total minutes down time ...)
+
+
+<P>
+
+<DT><STRONG><A NAME="item_Unknown">Unknown Data
+
+</A></STRONG><DD>
+As mentioned earlier, the <STRONG>RRD</STRONG> stores data at a constant interval. Now it may happen that no new data is
+available when a value has to be written to the <STRONG>RRD</STRONG>. Data acquisition may not be possible for one reason or an other. The <STRONG>rrdtool</STRONG> handles these situations by storing an <EM>*UNKNOWN*</EM> value into the database. The value '<EM>*UNKNOWN*</EM>' is supported through all the functions of the database. When
+consolidating the amount of <EM>*UNKNOWN*</EM> data is accumulated and when a new consolidated value is ready to be
+written to its Round Robin Archive (<STRONG>RRA</STRONG>) a validity check is performed to make sure that the percentage of unknown
+data in the new value is below a configurable level. If so, an <EM>*UNKNOWN*</EM> value will be written to the <STRONG>RRA</STRONG>.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_Graphing">Graphing
+
+</A></STRONG><DD>
+The <STRONG>rrdtool</STRONG> also allows one to generate reports in numerical and graphical form based
+on the data stored in one or several
+<STRONG>RRD</STRONG>s. The graphing feature is fully configurable. Size, color and contents of
+the graph can be defined freely. Check rrdgraph for more information on
+this.
+
+
+<P>
+
+</DL>
+<P>
+<HR>
+<H2><A NAME="REMOTE_CONTROL">REMOTE CONTROL
+
+</A></H2>
+When you start <STRONG>rrdtool</STRONG> with the command line option '<STRONG>-</STRONG>', it waits for input via standard in. With this feature you can improve
+performance by attaching <STRONG>rrdtool</STRONG> to another process (mrtg is one example) through a set of pipes. Over the
+pipes <STRONG>rrdtool</STRONG> accepts the same arguments as on the command line. When a command is
+completed, rrdtool will print the string '<CODE>OK</CODE>', followed by timing information of the form <STRONG>u:</STRONG><EM>usertime</EM> <STRONG>s:</STRONG><EM>systemtime</EM> both values are running totals of seconds since rrdtool was started. If an
+error occurs, a line of the form '<CODE>ERROR:</CODE> <EM>Description of error</EM>' will be printed. <STRONG>rrdtool</STRONG>
+will not abort if possible, but follow the ERROR line with an OK line.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SEE_ALSO">SEE ALSO
+
+</A></H1>
+rrdcreate, rrdupdate, rrdgraph, rrddump, rrdfetch, rrdtune, rrdlast
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="BUGS">BUGS
+
+</A></H1>
+There must be plenty ... this is alpha code ;-) ...
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR
+
+</A></H1>
+Tobias Oetiker <A
+HREF="MAILTO:<oetiker at ee.ethz.ch>"><oetiker at ee.ethz.ch></A>
+
+
+<P>
+
+</DL>
+ </BODY>
+
+ </HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.txt
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.txt (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.txt Sat Jul 13 18:46:11 2002
@@ -0,0 +1,66 @@
+
+
+
+RRDLAST(1) rrdtool RRDLAST(1)
+
+
+NNNNAAAAMMMMEEEE
+ rrdtool last - Return the date of the last data sample in
+ an RRRRRRRRDDDD
+
+SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
+ rrrrrrrrddddttttoooooooollll llllaaaasssstttt _f_i_l_e_n_a_m_e
+
+DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
+ The llllaaaasssstttt function returns the UNIX timestamp when the RRD
+ was last updated.
+
+ _f_i_l_e_n_a_m_e
+ The name of the RRRRRRRRDDDD that contains the data.
+
+AAAAUUUUTTTTHHHHOOOORRRR
+ Russ Wright <rwwright at home.com>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+24/Oct/98 19990426.22 1
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.txt
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.txt (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.txt Sat Jul 13 18:46:11 2002
@@ -0,0 +1,1518 @@
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+NNNNAAAAMMMMEEEE
+ rrdtutorial - Alex van den Bogaerdts RRD Tool tutorial
+
+DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
+ RRDtool is written by Tobias Oetiker <oetiker at ee.ethz.ch>
+ with contributions from many people all around the world.
+ This document is written by Alex van den Bogaerdt
+ <alex at ergens.op.het.net> to help you understand what
+ RRDtool is and what it can do for you.
+
+ The documentation provided with RRDtool can be too
+ technical for some people and here we help you to
+ understand the basics in order to prepare you to read the
+ documentation yourself. It also explains the general
+ things about statistics with a focus on networking.
+
+TTTTUUUUTTTTOOOORRRRIIIIAAAALLLL
+ IIIImmmmppppoooorrrrttttaaaannnntttt
+
+ We first have to do some uninteresting reading folks,
+ don't skip this part! Later on, in the examples, you need
+ to know the basics.
+
+ WWWWhhhhaaaatttt iiiissss RRRRRRRRDDDDttttoooooooollll ????
+
+ RRDtool means Round Robin Database tool. Round robin is a
+ technique that works with a fixed amount of data, and a
+ pointer to the current element. Think of a circle with
+ some dots plotted on the edge, these dots are the places
+ where data can be stored. Draw an arrow from the center of
+ the circle to one of the dots, this is the pointer. When
+ the current data is read or written, the pointer moves to
+ the next element. As we are on a circle there is no
+ beginning nor an end, you can go on and on. After a while,
+ all the available places will be used and the process
+ automatically reuses old locations. RRDtool works with
+ with Round Robin Databases (RRDs). It stores and retrieves
+ data from them.
+
+ WWWWhhhhaaaatttt ddddaaaattttaaaa ccccaaaannnn bbbbeeee ppppuuuutttt iiiinnnnttttoooo aaaannnn RRRRDDDDDDDD ????
+
+ You name it, it will probably fit. You should be able to
+ measure some value at several points in time and provide
+ this to RRDtool. If you can do this, RRDtool will probably
+ be able to store it.
+
+ Many examples talk about SNMP which is an acronym for
+ Simple Network Management Protocol. The "simple" is about
+ the protocol, it does not mean it is simple to manage a
+ network. After working your way through this document, you
+ will know enough to be able to understand what people are
+ talking about. For now, just assume SNMP is a way to talk
+ to devices and ask those devices about counters they keep.
+ It is the value from those counters that are kept in the
+
+
+
+10/May/99 19990510.19 1
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ RRD.
+
+ WWWWhhhhaaaatttt ccccaaaannnn IIII ddddoooo wwwwiiiitttthhhh tttthhhhiiiissss ttttoooooooollll ????
+
+ RRDtool originated from MRTG (multi router traffic
+ grapher) which itself came from a tiny little script to
+ monitor the performance of a connection to the Internet.
+ Since then, MRTG has also been used for several other
+ purposes including temperature, speed, voltage, number of
+ printouts and many other things. Most likely you will
+ start to use the RRDtool to store and process data
+ collected via SNMP. The data will most likely be bytes (or
+ bits) transfered from and to a network or a computer.
+ RRDtool lets you create a database, store data in it,
+ retrieve that data and create graphs in GIF format for
+ display on a web browser. Those GIF images are dependant
+ on the data you collected and could be, for instance, an
+ overview of the average network usage, or rather the peaks
+ that occurred. It can also be used to display tidal
+ waves, solar radiation, power consumption, number of
+ visitors at an exibition, noise levels near an airport,
+ temperature on your favorite holiday location, temperature
+ in the fridge and whatever you imagination can come up
+ with. You need a sensor to measure the data and be able to
+ feed the numbers to RRDtool. Many devices have such a
+ sensor.
+
+ WWWWhhhhaaaatttt iiiiffff IIII ssssttttiiiillllllll hhhhaaaavvvveeee pppprrrroooobbbblllleeeemmmmssss aaaafffftttteeeerrrr rrrreeeeaaaaddddiiiinnnngggg tttthhhhiiiissss ddddooooccccuuuummmmeeeennnntttt
+ ????
+
+ More exact, after re-reading this document :) It all
+ depends on the kind of problems you have. If you are
+ unable to compile the sources and you have a fairly common
+ OS, it will probably not be the fault of RRDtool. There
+ may be precompiled versions around on the Internet. If
+ they come from trusted sources, get one of those. If on
+ the other hand the program works but does not give you the
+ expected results, it will be a problem with configuring
+ it. Review your configuration and compare it with the
+ examples that follow.
+
+ There is a mailing list and an archive of it. Read the
+ list for a few weeks and search the archive. It is
+ considered rude to just ask a question without reading the
+ list, your problem may already have been solved for
+ somebody else and you will be helped without writing a new
+ a message at all ... This is true for most, if not all,
+ mailing lists and not only for this particular list! Look
+ in the documentation that came with RRDtool for the
+ location and usage of the list.
+
+ I suggest you take a moment to subscribe to the mailing
+ list right now by sending an email to <rrdtool-users-
+ request at list.ee.ethz.ch> with a subject of "subscribe". If
+
+
+
+10/May/99 19990510.19 2
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ you ever want to leave this list, you write an email to
+ the same address but now with a subject of "unsubscribe".
+
+ HHHHoooowwww wwwwiiiillllllll yyyyoooouuuu hhhheeeellllpppp mmmmeeee ????
+
+ By giving you some detailed descriptions with detailed
+ examples. It is assumed that following the instructions
+ in the order presented will build up enough knowledge of
+ the program to experiment for yourself. If it doesn't
+ work the first time, don't give up. Reread the stuff that
+ you did understand, you may have missed something. By
+ following the examples you get some hands-on experience
+ and, even more important, some background information of
+ how it works.
+
+ You will need to know something about hexadecimal numbers.
+ If you don't then start with reading "bin_dec_hex" before
+ you continue here.
+
+ YYYYoooouuuurrrr ffffiiiirrrrsssstttt RRRRoooouuuunnnndddd RRRRoooobbbbiiiinnnn DDDDaaaattttaaaabbbbaaaasssseeee
+
+ In my opinion the best way to learn something is to
+ actually do it. Why not start right now? We will create a
+ database, put some values in it and extract this data
+ again. It is expected that you get the same results when
+ you try these examples yourself so do that. We will start
+ with some easy stuff and compare a car with a router, or
+ compare kilometers (miles if you wish) with bits and
+ bytes. It's all the same: Some number over some time.
+
+ Assume we have a device that transfers bytes to and from
+ the Internet. This device keeps a counter that starts at
+ zero when it is turned on, increasing with every byte that
+ is transfered. This counter will have a maximum value, if
+ that value is reached and an extra byte is counted, the
+ counter starts all over at zero. This is the same as many
+ counters in the world such as the mileage counter in a
+ car. Most discussions about networking talk about bits
+ per second so lets get used to that right away. Assume a
+ byte is eight bits and start to think in bits not bytes.
+ The counter however still counts bytes ! In the SNMP
+ world most of the counters are 32 bits. That means they
+ are counting from 0 to 4294967295. We will use these
+ values in the examples. The device, when asked, returns
+ the current value of the counter. We know the time that
+ has passes since we last asked so we now know how many
+ bytes have been transfered ***on average*** per second.
+ This is not very hard to calculate. First in words, then
+ in calculi:
+
+ 1. Take the current counter, subtract the previous value
+ from it.
+
+
+
+
+
+10/May/99 19990510.19 3
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ 2. Do the same with the current time and the previous
+ time.
+
+ 3. Divide the outcome of (1) by the outcome of (2), the
+ result is the amount of bytes per second. Multiply by
+ eight to get the number of bits per second (bps).
+
+ bps = (counter_now - counter_before) / (time_now - time_before) * 8
+
+
+ For some people it may help to translate this to a
+ automobile example: Do not try this example, and if you
+ do, don't blame me for the results.
+
+ People who are not used to think in kilometers per hour
+ can translate most into miles per hour by dividing km by
+ 1.6 (close enough). I will use the following
+ abbreviations:
+
+ M: meter
+ KM: kilometer (= 1000 meters).
+ H: hour
+ S: second
+ KM/H: kilometers per hour
+ M/S: meters per second
+
+ You're driving a car. At 12:05 you read the counter in the
+ dashboard and it tells you that the car has moved 12345 KM
+ until that moment. At 12:10 you look again, it reads
+ 12357 KM. This means you have traveled 12 KM in five
+ minutes. A scientist would translate that into meters per
+ second and this makes a nice comparison towards the
+ problem of (bytes per five minutes) versus (bits per
+ second).
+
+ We traveled 12 kilometers which is 12000 meters. We did
+ that in five minutes which translates into 300 seconds.
+ Our speed is 12000M / 300S equals 40 M/S.
+
+ We could also calculate the speed in KM/H: twelve times
+ five minutes is an hour so we have to multiply 12 KM by 12
+ to get 144 KM/H. For our native English speaking friends:
+ this is ninety MPH and therefore not recommended to try
+ for yourself where I live :)
+
+ Remember: these numbers are averages and there is no way
+ to figure out from the numbers we got that you drove at a
+ constant speed.
+
+ I hope you understand that there is no difference in
+ calculating M/S or bps, only the way we collect the data
+ is different. Even the K from kilo is the same as in
+ networking terms k also means 1000.
+
+
+
+
+10/May/99 19990510.19 4
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ We will now create a database where we can keep all these
+ interesting numbers. The method used to start the program
+ may differ slightly from OS to OS but I assume you can
+ figure it out if it works different on your OS. Make sure
+ you do not overwrite any file on your system when
+ executing the following command (so: first look if it's
+ safe!) and type the whole line as one long line (I had to
+ split it for readability) and skip all of the '\'
+ characters.
+
+ rrdtool create test.rrd \
+ --start 920804400 \
+ DS:speed:COUNTER:600:U:U \
+ RRA:AVERAGE:0.5:1:24 \
+ RRA:AVERAGE:0.5:6:10
+
+ (So enter: rrdtool create test.rrd --start 920804400 DS
+ ...)
+
+ WWWWhhhhaaaatttt hhhhaaaassss bbbbeeeeeeeennnn ccccrrrreeeeaaaatttteeeedddd ????
+
+ We created the round robin database called test (test.rrd)
+ which starts at noon the day I started (7th of march,
+ 1999) writing this document. It holds one data source (DS)
+ named "speed" that gets built from a counter. This counter
+ is read every five minutes (default) In the same database
+ two round robin archives (RRAs) are kept, one averages the
+ data every time it is read (so: there's nothing to
+ average) and keeps 24 samples (24 times 5 minutes is 2
+ hours). The other averages 6 values (half hour) and
+ contains 10 of such averages (so: 5 hours) The remaining
+ options will be discussed later on. Chances are that you
+ are not in the same part of the world as I am. This means
+ your time zone is different. In all examples where I talk
+ about time, the hours may be wrong for you. This has
+ little effect on the results of the examples, just correct
+ the hours while reading.
+
+ We now have to fill our database with some numbers. We'll
+ pretend to have read the following numbers:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+10/May/99 19990510.19 5
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ 12:05 12345 KM
+ 12:10 12357 KM
+ 12:15 12363 KM
+ 12:20 12363 KM
+ 12:25 12363 KM
+ 12:30 12373 KM
+ 12:35 12383 KM
+ 12:40 12393 KM
+ 12:45 12399 KM
+ 12:50 12405 KM
+ 12:55 12411 KM
+ 13:00 12415 KM
+ 13:05 12420 KM
+ 13:10 12422 KM
+ 13:15 12423 KM
+
+ We fill the database as follows:
+
+ rrdtool update test.rrd 920804700:12345 920805000:12357 920805300:12363
+ rrdtool update test.rrd 920805600:12363 920805900:12363 920806200:12373
+ rrdtool update test.rrd 920806500:12383 920806800:12393 920807100:12399
+ rrdtool update test.rrd 920807400:12405 920807700:12411 920808000:12415
+ rrdtool update test.rrd 920808300:12420 920808600:12422 920808900:12423
+
+ This reads: update our test database with the following
+ numbers
+
+ time 920804700, value 12345
+ time 920805000, value 12357
+
+ etcetera.
+
+ As you can see, it is possible to feed more than one value
+ into the database in one command. I had to stop at three
+ for readability but the real maximum will be OS dependent.
+
+ The time value may look strange to you, it is written in
+ seconds since the first of January, 1970, midnight. Don't
+ worry about this yet, just notice that there is a
+ difference of 300 in between all values.
+
+ IIIItttt iiiissss ttttiiiimmmmeeee ttttoooo ccccrrrreeeeaaaatttteeee ssssoooommmmeeee ggggrrrraaaapppphhhhiiiiccccssss
+
+ Try the following command:
+
+ rrdtool graph speed.gif \
+ --start 920804400 --end 920808000 \
+ DEF:myspeed=test.rrd:speed:AVERAGE \
+ LINE2:myspeed#FF0000
+
+ This will create speed.gif which starts at 12:00 and ends
+ at 13:00. There is a definition of variable myspeed, it
+ is the data from RRA "speed" out of database "test.rrd".
+ The line drawn is 2 pixels high, and comes from variable
+
+
+
+10/May/99 19990510.19 6
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ myspeed. The color is red. You'll notice that the start
+ of the graph is not at 12:00 but at 12:05 and this is
+ because we have insufficient data to tell the average
+ before that time. This will only happen when you miss some
+ samples, this will not happen a lot, hopefully.
+
+ If this has worked: Congratulations. If not, check what
+ went wrong.
+
+ The colors are built up from red, green and blue. For each
+ of the components, you specify how much to use in
+ hexadecimal where 00 means not included and FF means fully
+ included. The color white is a mixture of red, green and
+ blue: FFFFFF The color black is all colors off: 000000
+ (Please, no discussions if black and white can be called
+ colors)
+
+ red #FF0000
+ green #00FF00
+ blue #0000FF
+ purple #FF00FF (mixed red with blue)
+ gray #555555 (one third of all components)
+
+ The GIF you just created can be displayed using a web
+ browser or other software you like. I can not provide you
+ with an example of that, because there are too many
+ different setups, possibilities etc.
+
+ GGGGrrrraaaapppphhhhiiiiccccssss wwwwiiiitttthhhh ssssoooommmmeeee mmmmaaaatttthhhh
+
+ When looking at the image, you notice that the horizontal
+ axis displays 12:10, 12:20, 12:30, 12:40 and 12:50. The
+ two remaining times (12:00 and 13:00) would not be
+ displayed nicely so they are skipped. The vertical axis
+ displays the range we entered. We provided kilometers and
+ when divided by 300 seconds, we get very small numbers. To
+ be exact, the first value was 12 (12357-12345) and divided
+ by 300 this makes 0.04 RRDtool displays this as 40 m which
+ means 40 mili (so: NOT meters). What we did wrong was
+ that we should have measured in meters, this would have
+ been (12357000-12345000)/300 = 12000/300 = 40.
+
+ Let's correct that. We could recreate our database and
+ store the correct data but there is another way: do some
+ calculations while creating the gif file !
+
+ rrdtool graph speed2.gif \
+ --start 920804400 --end 920808000 \
+ --vertical-label m/s \
+ DEF:myspeed=test.rrd:speed:AVERAGE \
+ CDEF:realspeed=myspeed,1000,* \
+ LINE2:realspeed#FF0000
+
+ After viewing this GIF, you notice the "m" has
+
+
+
+10/May/99 19990510.19 7
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ disappeared. This it what the correct result would be.
+ Also, a label has been added to the image. Apart from the
+ things mentioned above, the GIF should be the same.
+
+ The calculations are done with the CDEF part. What it says
+ is: take the data source myspeed and the number 1000,
+ multiply those. The calculations are done using Reverse
+ Polish Notation. It is an easy way of performing
+ calculations after you understand it. You will, eventually
+ but for now assume it is correct what I write and just
+ keep to the examples in this file. Read the documentation
+ that came with RRDtool (look in rrdgraph.doc) when you're
+ ready for it.
+
+ Hang on! If we can multiply values with 1000, it should
+ also be possible to display kilometers per hour from the
+ same data ! What do we need to do ? If we have meters per
+ second, we can make this meters per hour by multiplying
+ the value with 3600 (there go 3600 seconds in one hour).
+ To get kilometers per hour, we need to divide by 1000. We
+ end up with: value * 3600 / 1000 = value * 3.6 . Remember
+ we also have to correct our mistake, so it is value * 3600
+ for us.
+
+ Now let's create this GIF, and add some more magic ...
+
+ rrdtool graph speed3.gif \
+ --start 920804400 --end 920808000 \
+ --vertical-label km/h \
+ DEF:myspeed=test.rrd:speed:AVERAGE \
+ CDEF:kmh=myspeed,3600,* \
+ CDEF:fast=kmh,100,GT,kmh,0,IF \
+ CDEF:good=kmh,100,GT,0,kmh,IF \
+ HRULE:100#0000FF:"Maximum allowed" \
+ AREA:good#00FF00:"Good speed" \
+ AREA:fast#FF0000:"Too fast"
+
+ This looks much better. Speed in KM/H and even an extra
+ line with the maximum allowed speed (on the road I travel
+ at). I also changed the colors used to display speed and
+ changed it from a line into an area.
+
+ The calculations are more complex now. For the "good"
+ speed they are:
+
+ +o Check if kmh is greater than 100 ( kmh,100 ) GT
+
+ +o If so, return 0, else kmh ((( kmh,100 ) GT ),
+ 0, kmh) IF
+
+ For the other speed:
+
+ +o Check if kmh is greater than 100 ( kmh,100 ) GT
+
+
+
+
+10/May/99 19990510.19 8
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ +o If so, return kmh, else return 0 ((( kmh,100) GT ),
+ kmh, 0) IF
+
+ GGGGrrrraaaapppphhhhiiiiccccssss MMMMaaaaggggiiiicccc
+
+ I like to believe there are virtually no limits about what
+ RRDtool can do. I will not explain how it works, but look
+ at the following GIF:
+
+ rrdtool graph speed4.gif \
+ --start 920804400 --end 920808000 \
+ --vertical-label km/h \
+ DEF:myspeed=test.rrd:speed:AVERAGE \
+ CDEF:kmh=myspeed,3600,* \
+ CDEF:fast=kmh,100,GT,100,0,IF \
+ CDEF:over=kmh,100,GT,kmh,100,-,0,IF \
+ CDEF:good=kmh,0,kmh,100,GT,IF \
+ HRULE:100#0000FF:"Maximum allowed" \
+ AREA:good#00FF00:"Good speed" \
+ AREA:fast#550000:"Too fast" \
+ STACK:over#FF0000:"Over speed"
+
+ Let's create a quick and dirty HTML page to view three
+ GIFs:
+
+ <HTML><HEAD><TITLE>Speed</TITLE></HEAD><BODY>
+ <IMG src="speed2.gif" alt="Speed in meters per second">
+ <BR>
+ <IMG src="speed3.gif" alt="Speed in kilometers per hour">
+ <BR>
+ <IMG src="speed4.gif" alt="Traveled too fast?">
+ </BODY></HTML>
+
+ Name the file "speed.html" or similar, and view it.
+
+ Now, all you have to do is measure the values regularly
+ and update the database. Every time you create these three
+ GIFs and reload the page and the GIFs (better reread these
+ last three words!) you know how fast you traveled.
+
+ UUUUppppddddaaaatttteeeessss iiiinnnn RRRReeeeaaaalllliiiittttyyyy
+
+ You already looked at the "update" tool. It took one or
+ more parameters in the form of "<time>:<value>". You'll be
+ glad to know that you can get the current time by filling
+ in a "N" as the time. If you wish, you can also use the
+ "time" function in perl. The shortest example in this doc
+ :)
+
+ perl -e 'print time, "\n" '
+
+ How you can run a program on regular intervals is OS
+ specific, so I just give you an example script in a sort
+ of pseudo code: (Do not try this with our test database,
+
+
+
+10/May/99 19990510.19 9
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ it is used in further examples)
+
+ Get the value, put it in variable "$speed"
+ rrdtool update speed.rrd N:$speed
+
+ This is all. Run this script every five minutes. When you
+ need to know what the graphics look like, run the examples
+ above. You could put them in a script. After running that
+ script, view index.html
+
+ SSSSoooommmmeeee wwwwoooorrrrddddssss oooonnnn SSSSNNNNMMMMPPPP
+
+ I can imagine very few people will be able to get real
+ data from their car every five minutes, all other people
+ will have to settle for some other kind of counter. You
+ could measure the number of pages printed by the laser-jet
+ printer, the coffee made by the coffee machine, a device
+ that counts the electricity used, whatever. Just as long
+ as it is an incrementing counter that you can measure
+ regularly, you can graph it against time as we did. Most
+ people will use the counter that keeps track of octets
+ (bytes) transfered by a routing device so we have to do
+ just that. We will start with a description of how to
+ collect data. Some people will make a remark that there
+ are tools who can do this data collection for you. They
+ are right! However, I feel it is important that you
+ understand they are not necessary. If you have to look why
+ things went wrong, you need to know how the stuff works.
+
+ One tool used in the example has been talked about very
+ briefly in the beginning of this document, it is called
+ SNMP. It is a way of talking to equipment. The tool I use
+ below is called "snmpget" and this is how it works:
+
+ snmpget device password OID
+
+ For device you substitute the name of your device, for
+ password you use the "community" as it is called. For most
+ devices "public" will do but this can be disabled, altered
+ or protected for privacy and security reasons. You will
+ need to find this out as there is no way I can tell what
+ you ( ...your device... ) are keeping a secret from me.
+
+ Then there is this third parameter, called OID. When you
+ start to learn about SNMP it looks very confusing. It
+ isn't all that difficult when you look at the Management
+ Information Base or in short: the MIB. It is an upside-
+ down tree, with a single node as the root and from there a
+ number of branches. These branches end up in another node,
+ they branch out, etc. All the branches have a name and
+ they form the path that we follow all the way down. The
+ branches that we follow are named: iso, org, dod,
+ internet, mgmt and mib-2. These names can also be written
+ down as numbers and are 1 3 6 1 2 1.
+
+
+
+10/May/99 19990510.19 10
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ iso.org.dod.internet.mgmt.mib-2 (1.3.6.1.2.1)
+
+ From there, we are especially interested in the branch
+ "interfaces" which has number 2 (so: 1.3.6.1.2.1.2 or
+ 1.3.6.1.2.1.interfaces).
+
+ The SNMP programs that I know can take above path as a
+ default, so I could walk to interfaces without writing it
+ in full. To do that, the path has to be written as
+ interfaces, without a leading dot. I could also use the
+ long form, then I need to start with a dot.
+
+ I can intermix numbers and names as I like. 1.3.6.1.2.1
+ is the same as iso.org.dod.1.2.1 and
+ 1.3.6.internet.2.mib-2 For interfaces I could write
+ "interfaces", 2, or a long version by prefixing it with
+ ".1.3.6.1.2.1.". Just try what works for you and do read
+ the manual for the version of snmpget you are using.
+
+ First, we have to get some SNMP program. First look if
+ there is a pre-compiled package available for your OS.
+ This is the preferred way. If not, you will have to get
+ yourself the sources and compile those. The Internet is
+ full of sources, programs etc. Find information using a
+ search engine or whatever you prefer. You are on your own
+ here, sorry.
+
+ Assume you got the program. First try to collect some data
+ that is available on most systems. Remember: there is a
+ short name for the part of the tree that interests us most
+ in the world we live in ! I will use the short version as
+ I think this document is large enough as it is. If that
+ doesn't work for you, prefix with .1.3.6.1.2.1 and try
+ again. Also, Read The Fine Manual. Skip the parts you
+ cannot understand yet, you should be able to find out how
+ to start the program and use it.
+
+ snmpget myrouter public system.sysdescr.0
+
+ The device should answer with a description of itself,
+ perhaps empty. Until you got a valid answer from a
+ device, perhaps using a different "password", or a
+ different device, there is no point in continuing.
+
+ snmpget myrouter public interfaces.ifnumber.0
+
+ Hopefully you get a number as a result, the number of
+ interfaces. If so, you can carry on and try a different
+ program called "snmpwalk".
+
+ snmpwalk myrouter public interfaces.iftable.ifentry.ifdescr
+
+ If it returns with a list of interfaces, you're almost
+ there. Here's an example:
+
+
+
+10/May/99 19990510.19 11
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ [user at host /home/alex]$ snmpwalk cisco public 2.2.1.2
+
+ interfaces.ifTable.ifEntry.ifDescr.1 = "BRI0: B-Channel 1"
+ interfaces.ifTable.ifEntry.ifDescr.2 = "BRI0: B-Channel 2"
+ interfaces.ifTable.ifEntry.ifDescr.3 = "BRI0" Hex: 42 52 49 30
+ interfaces.ifTable.ifEntry.ifDescr.4 = "Ethernet0"
+ interfaces.ifTable.ifEntry.ifDescr.5 = "Loopback0"
+
+ On this cisco equipment, I would like to monitor the
+ "Ethernet0" interface and see that it is number four. I
+ try:
+
+ [user at host /home/alex]$ snmpget cisco public 2.2.1.10.4 2.2.1.16.4
+
+ interfaces.ifTable.ifEntry.ifInOctets.4 = 2290729126
+ interfaces.ifTable.ifEntry.ifOutOctets.4 = 1256486519
+
+ So now I have two OIDs to monitor and they are (in full,
+ this time):
+
+ 1.3.6.1.2.1.2.2.1.10
+
+ and
+
+ 1.3.6.1.2.1.2.2.1.16
+
+ both with an interface number of 4.
+
+ Don't get fooled, this wasn't my first try. It took some
+ time for me too to understand what all these numbers mean,
+ it does help a lot when they get translated into
+ descriptive text... At least, when people are talking
+ about MIBs and OIDs you know what it's all about. Do not
+ forget the interface number (0 if it is not interface
+ dependent) and try snmpwalk if you don't get an answer
+ from snmpget.
+
+ If you understand above part, and get numbers from your
+ device, it is time to continue with the following. If not,
+ then go back.
+
+ AAAA RRRReeeeaaaallll WWWWoooorrrrlllldddd EEEExxxxaaaammmmpppplllleeee
+
+ Let the fun begin. First, create a new database. It
+ contains data from two counters, called input and output.
+ The data is put into archives that average it. They take
+ 1, 6, 24 or 288 samples at a time. They also go into
+ archives that keep the maximum numbers. This will be
+ explained later on. The time in-between samples is 300
+ seconds, a good starting point, which is the same as five
+ minutes.
+
+
+
+
+
+
+10/May/99 19990510.19 12
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ 1 sample averaged stays 1 period of 5 minutes
+ 6 samples averaged become one average on 30 minutes
+ 24 samples averaged become one average on 2 hours
+ 288 samples averaged become one average on 1 day
+
+ There are 600 samples of five minutes, together just over two days
+ There are 600 samples of 30 minutes, almost two weeks
+ There are 600 samples of 2 hours, 50 hour or almost two months
+ There are 732 samples of 1 day, just over two years
+
+ For people used to MRTG that even have read the manuals,
+ these numbers should look familiar...
+
+ rrdtool create myrouter.rrd \
+ DS:input:COUNTER:600:U:U \
+ DS:output:COUNTER:600:U:U \
+ RRA:AVERAGE:0.5:1:600 \
+ RRA:AVERAGE:0.5:6:600 \
+ RRA:AVERAGE:0.5:24:600 \
+ RRA:AVERAGE:0.5:288:732 \
+ RRA:MAX:0.5:1:600 \
+ RRA:MAX:0.5:6:600 \
+ RRA:MAX:0.5:24:600 \
+ RRA:MAX:0.5:288:732
+
+ Next thing to do is collect data and store it. Here is an
+ example. It is written partially in pseudo code so you
+ will have to find out what to do exactly on your OS to
+ make it work.
+
+ while not the end of the universe
+ do
+ get result of
+ snmpget router community 2.2.1.10.4
+ into variable $in
+ get result of
+ snmpget router community 2.2.1.16.4
+ into variable $out
+
+ rrdtool update myrouter.rrd N:$in:$out
+
+ wait for 5 minutes
+ done
+
+ Then, after collecting data for a day, try to create an
+ image using:
+
+ rrdtool graph myrouter-day.gif --start -86400 \
+ DEF:inoctets=myrouter.rrd:input:AVERAGE \
+ DEF:outoctets=myrouter.rrd:output:AVERAGE \
+ AREA:inoctets#00FF00:"In traffic" \
+ LINE1:outoctets#0000FF:"Out traffic"
+
+ This should produce a picture with one day worth of
+
+
+
+10/May/99 19990510.19 13
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ traffic. One day is 24 hours of 60 minutes of 60 seconds:
+ 24*60*60=86400, we start at now minus 86400 seconds. We
+ DEFine inoctets and outoctets as the average values from
+ the database myrouter.rrd and draw an area for the "in"
+ traffic and a line for the "out" traffic.
+
+ View the image and keep logging for a few more days. If
+ you like, you could try the examples from the test
+ database and see if you can play around with the options
+ and calculations.
+
+ Suggestion:
+
+ Display in bytes per second and in bits per second. Make
+ the ethernet graphics go red if they are over four
+ megabits per second.
+
+ CCCCoooonnnnssssoooolllliiiiddddaaaattttiiiioooonnnn FFFFuuuunnnnccccttttiiiioooonnnnssss
+
+ A few paragraphs back I mentioned the possibility of
+ keeping the maximum values instead of the average values.
+ Let's go into this a bit more.
+
+ Recall all the stuff about the speed of the car. Suppose
+ we drove at 144 KM/H during 5 minutes and then were
+ stopped by the police for 25 minutes. At the end of the
+ lecture we would take our laptop and create+view the image
+ taken from the database. If we look at the second RRA we
+ did create, we would have the average from 6 samples. The
+ samples measured would be 144+0+0+0+0+0=144, divided by 30
+ minutes, corrected for the error by 1000, translated into
+ KM/H, with a result of 24 KM/H. I would still get a
+ ticket but not for speeding anymore :)
+
+ Obviously, in this case, we shouldn't look at the
+ averages. In some cases they are handy. If you want to
+ know how much KM you had traveled, the picture would be
+ the right one to look at. On the other hand, for the speed
+ that we traveled at, the maximum number seen is much more
+ valuable. (later we will see more types)
+
+ It is the same for data. If you want to know the amount,
+ look at the averages. If you want to know the rate, look
+ at the maximum. Over time, they will grow apart more and
+ more. In the last database we have created, there are two
+ archives that keep data per day. The archive that keeps
+ averages will show low numbers, the archive that shows
+ maxima will have higher numbers. For my car this would
+ translate in averages per day of 96/24=4 KM/H (as I travel
+ about 94 kilometers on a day) during week days, and
+ maximum of 120 KM/H on weekdays (my top speed that I reach
+ every day).
+
+ Big difference. Do not look at the second graph to
+
+
+
+10/May/99 19990510.19 14
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ estimate the distances that I travel and do not look at
+ the first graph to estimate my speed. This will work if
+ the samples are close together, as they are in five
+ minutes, but not if you average.
+
+ On some days, I go for a long ride. If I go across Europe
+ and travel for over 12 hours, the first graph will rise to
+ about 60 KM/H. The second one will show 180 KM/H. This
+ means that I traveled a distance of 60 KM/H times 24 H =
+ 1440 KM. I did this with a higher speed and a maximum
+ around 180 KM/H. This doesn't mean that I traveled for 8
+ hours at a constant speed of 180 KM/H ! This is a real
+ example: go with the flow through Germany and stop a few
+ times for gas and coffee. Drive slowly through Austria and
+ the Netherlands. Be careful in the mountains and villages.
+ If you would look at the graphs created from the five-
+ minute averages you would get a totally different picture.
+ You would see the same values on the average and maximum
+ graphs (provided I measured every 300 seconds). You would
+ be able to see when I stopped, when I was in top gear,
+ when I drove over fast motor-ways etc. The granularity of
+ the data is much higher, so you can see more. However,
+ this takes 12 samples per hour, or 288 values per day, so
+ it would be too much to keep for a long period of time.
+ Therefore we average it, eventually to one value per day.
+ From this one value, we cannot see much detail.
+
+ Make sure you understand the last few paragraphs. There is
+ no value in only a line and a few axis, you need to know
+ what they mean and interpret the data in a good way. This
+ is true for all data.
+
+ The biggest mistake you can make is to use the collected
+ data for something that it is not suitable for. You would
+ be better off if you would not have the graphics at all in
+ that case.
+
+ LLLLeeeetttt''''ssss rrrreeeevvvviiiieeeewwww wwwwhhhhaaaatttt yyyyoooouuuu nnnnoooowwww sssshhhhoooouuuulllldddd kkkknnnnoooowwww....
+
+ You now know how to create a database. You can put the
+ numbers in it, get them out again by creating an image, do
+ math on the data from the database and view the outcome
+ instead of the raw data. You know about the difference
+ between averages and maxima, and when to use which (or at
+ least you have an idea).
+
+ RRDtool can do more than what we have learned up to now.
+ Before you continue with the rest of this doc, I recommend
+ that you reread from the start and try some modifications
+ on the examples. Make sure you fully understand
+ everything. It will be worth the effort and helps you not
+ only with the rest of this doc but also in your day to day
+ monitoring long after you read this introduction.
+
+
+
+
+10/May/99 19990510.19 15
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ DDDDaaaattttaaaa SSSSoooouuuurrrrcccceeee TTTTyyyyppppeeeessss
+
+ All right, you feel like continuing. Welcome back and get
+ ready for an increased speed in the examples and
+ explanation.
+
+ You know that in order to view a counter over time, you
+ have to take two numbers and divide the difference of them
+ between the time lapsed. This makes sense for the examples
+ I gave you but there are other possibilities. For
+ instance, I'm able to retrieve the temperature from my
+ router in three places namely the inlet, the so called
+ hot-spot and the exhaust. If I take the difference of the
+ two samples and divide that by 300 (seconds) there would
+ not be very much to display ... If there would be anything
+ to display it would be the fluctuations in the temperature
+ and if they produce noticeable results when divided by
+ 300, I'd better look for a new computer room.
+
+ So, what can we do ? RRDtool can also store the values
+ you measure directly as they are (this is not entirely
+ true but close enough). The graphs we make look much
+ better, they will show a rather constant value. I know
+ when the router is busy (it works -> it uses more
+ electricity -> it generates more heat -> the temperature
+ rises). I know when the doors are left open (the room is
+ cooled -> the warm air from the rest of the building flows
+ into the computer room -> the inlet temperature rises)
+ etc. The data type we use when creating the database
+ before was counter, we now have a different data type and
+ thus a different name for it. It is called GAUGE. There
+ are more such data types:
+
+ - COUNTER we already know this one
+ - GAUGE we just learned this one
+ - DERIVE
+ - ABSOLUTE
+
+ The two new types are DERIVE and ABSOLUTE. Absolute can be
+ used like counter with one difference: RRDtool assumes the
+ counter is reset when it's read. That is: its delta is
+ known without calculation by RRDtool whereas RRDtool needs
+ to calculate it for the counter type. Example: our first
+ example (12345, 12357, 12363, 12363) would read: unknown,
+ 12, 6, 0. The rest of the calculations stay the same. The
+ other one, derive, is like counter. Unlike counter, it can
+ also decrease so it can have a negative delta. Again, the
+ rest of the calculations stay the same.
+
+ Let's try them all:
+
+
+
+
+
+
+
+10/May/99 19990510.19 16
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ rrdtool create all.rrd --start 978300900 \
+ DS:a:COUNTER:600:U:U \
+ DS:b:GAUGE:600:U:U \
+ DS:c:DERIVE:600:U:U \
+ DS:d:ABSOLUTE:600:U:U \
+ RRA:AVERAGE:0.5:1:10
+ rrdtool update all.rrd \
+ 978301200:300:1:600:300 \
+ 978301500:600:3:1200:600 \
+ 978301800:900:5:1800:900 \
+ 978302100:1200:3:2400:1200 \
+ 978302400:1500:1:2400:1500 \
+ 978302700:1800:2:1800:1800 \
+ 978303000:2100:4:0:2100 \
+ 978303300:2400:6:600:2400 \
+ 978303600:2700:4:600:2700 \
+ 978303900:3000:2:1200:3000
+ rrdtool graph all1.gif -s 978300600 -e 978304200 -h 400 \
+ DEF:linea=all.rrd:a:AVERAGE LINE3:linea#FF0000:"Line A" \
+ DEF:lineb=all.rrd:b:AVERAGE LINE3:lineb#00FF00:"Line B" \
+ DEF:linec=all.rrd:c:AVERAGE LINE3:linec#0000FF:"Line C" \
+ DEF:lined=all.rrd:d:AVERAGE LINE3:lined#000000:"Line D"
+
+
+ RRRRRRRRDDDD TTTToooooooollll uuuunnnnddddeeeerrrr tttthhhheeee MMMMiiiiccccrrrroooossssccccooooppppeeee
+
+
+ +o Line A is a counter so it should continuously increment
+ and RRDtool should calculate the differences. Also,
+ RRDtool needs to divide the difference by the amount of
+ time lapsed. This should end up as a straight line at 1
+ (the deltas are 300, the time is 300).
+
+ +o Line B is of type gauge. These are "real" values so they
+ should match what we put in: a sort of a wave.
+
+ +o Line C is derive. It should be a counter that can
+ decrease. It does so between 2400 and 0, with 1800 in-
+ between.
+
+ +o Line D is of type absolute. This is like counter but it
+ works on values without calculating the difference. The
+ numbers are the same and as you can see (hopefully) this
+ has a different result.
+
+ This translates in the following values, starting at 23:10
+ and ending at 00:10 the next day (where U means
+ unknown/unplotted):
+
+ - Line A: u u 1 1 1 1 1 1 1 1 1 u
+ - Line B: u 1 3 5 3 1 2 4 6 4 2 u
+ - Line C: u u 2 2 2 0 -2 -6 -2 0 2 u
+ - Line D: u 1 2 3 4 5 6 7 8 9 10 u
+
+
+
+
+10/May/99 19990510.19 17
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ If your GIF shows all this, you know you have typed the
+ data correct, the RRDtool executable is working properly,
+ your viewer doesn't fool you and you successfully entered
+ the year 2000 :) You could try the same example four
+ times, each time with only one of the lines.
+
+ Let's go over the data again:
+
+ +o Line A: 300,600,900 and so on. The counter delta is a
+ constant 300 and so it the time delta. A number divided
+ by itself is always 1 (except when dividing by zero
+ which is undefined/illegal). Why is it that the first
+ point is unknown ? We do know what we put into the
+ database ? True ! But we didn't have a value to
+ calculate the delta from so we don't know where we
+ started. It would be wrong to assume we started at zero
+ so we don't !
+
+ +o Line B: There is nothing to calculate. The numbers are
+ as is.
+
+ +o Line C: Again, the start-out value is unknown. The same
+ story is valid like for line A. In this case the deltas
+ are not constant so the line is not. If we would put the
+ same numbers in the database as we did for line A, we
+ would have gotten the same line. Unlike type counter,
+ this type can decrease and I hope to show you later on
+ why there is a difference.
+
+ +o Line D: Here the device calculates the deltas. Therefore
+ we DO know the first delta and it is plotted. We had the
+ same input as with line A but the meaning of this input
+ is different. Therefore the line is different. In this
+ case the deltas increase each time with 300. The time
+ delta stays at a constant 300 and therefore the division
+ of the two gives increasing results.
+
+ CCCCoooouuuunnnntttteeeerrrr WWWWrrrraaaappppssss
+
+ There are a few more basics to show. Some important
+ options are still to be covered and we haven't look at
+ counter wraps yet. First the counter wrap: In our car we
+ notice that our counter shows 999987. We travel 20 KM and
+ the counter should go to 1000007. Unfortunately, there are
+ only six digits on our counter so it really shows 000007.
+ If we would plot that on a type DERIVE, it would mean that
+ the counter was set back 999980 KM. It wasn't, and there
+ has to be some protection for this. This protection is
+ only available for type COUNTER which should be used for
+ this kind of counter anyways. How does it work ? Type
+ counter should never decrease and therefore RRDtool must
+ assume it wrapped if it does decrease ! If the delta is
+ negative, this can be compensated for by adding the
+ maximum value of the counter + 1. For our car this would
+
+
+
+10/May/99 19990510.19 18
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ be:
+
+ Delta = 7 - 999987 = -999980 (instead of 1000007-999987=20)
+
+ Real delta = -999980 + 999999 + 1 = 20
+
+ At the moment of writing this document, RRDtool knows of
+ counters that are either 32 bits or 64 bits of size. These
+ counters can handle the following different values:
+
+ - 32 bits: 0 .. 4294967295
+ - 64 bits: 0 .. 18446744073709551615
+
+ If these numbers look strange to you, you would like to
+ view them in their hexadecimal form:
+
+ - 32 bits: 0 .. FFFFFFFF
+ - 64 bits: 0 .. FFFFFFFFFFFFFFFF
+
+ RRDtool handles both counters the same. If an overflow
+ occurs and the delta would be negative, RRDtool first adds
+ the maximum of a small counter + 1 to the delta. If the
+ delta is still negative, it had to be the large counter
+ that wrapped. Add the maximum possible value of the large
+ counter + 1 and subtract the falsely added small value.
+ There is a risk in this: suppose the large counter wrapped
+ while adding a huge delta, it could happen in theory that
+ adding the smaller value would make the delta positive. In
+ this unlikely case the results would not be correct. The
+ increase should be nearly as high as the maximum counter
+ value for that to happen so chances are you would have
+ several other problems as well and this particular problem
+ would not even be worth thinking about. Even though I did
+ include an example of it so you can judge that for
+ yourself.
+
+ The next section gives you some numerical examples for
+ counter-wraps. Try to do the calculations yourself or
+ just believe me if your calculator can't handle the
+ numbers :)
+
+ Correction numbers:
+
+ - 32 bits: (4294967295+1) = 4294967296
+ - 64 bits: (18446744073709551615+1)-correction1 = 18446744069414584320
+
+ Before: 4294967200
+ Increase: 100
+ Should become: 4294967300
+ But really is: 4
+ Delta: -4294967196
+ Correction1: -4294967196 +4294967296 = 100
+
+
+
+
+
+10/May/99 19990510.19 19
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ Before: 18446744073709551000
+ Increase: 800
+ Should become: 18446744073709551800
+ But really is: 184
+ Delta: -18446744073709550816
+ Correction1: -18446744073709550816 +4294967296 = -18446744069414583520
+ Correction2: -18446744069414583520 +18446744069414584320 = 800
+
+ Before: 18446744073709551615 ( maximum value )
+ Increase: 18446744069414584320 ( absurd increase, minimum for
+ Should become: 36893488143124135935 this example to work )
+ But really is: 18446744069414584319
+ Delta: -4294967296
+ Correction1: -4294967296 + 4294967296 = 0
+ (not negative -> no correction2)
+
+ Before: 18446744073709551615 ( maximum value )
+ Increase: 18446744069414584319 ( one less increase )
+ Should become: 36893488143124135934
+ But really is: 18446744069414584318
+ Delta: -4294967297
+ Correction1: -4294967297 +4294967296 = -1
+ Correction2: -1 +18446744069414584320 = 18446744069414584319
+
+ As you can see from the last two examples, you need
+ strange numbers for RRDtool to fail (provided it's bug
+ free of course) so this should not happen. However, SNMP
+ or whatever method you choose to collect the data might
+ also fail and it is not uncommon to get wrong numbers
+ occasionally. We can't prevent all errors but there are
+ some things we could do. RRDtool create takes two special
+ parameters for this. They define the minimum and maximum
+ allowed value. Until now, we made them "U" for Unknown.
+ You may (not: must) provide values for one or both of them
+ and if RRDtool receives values that are outside these
+ limits, it will ignore them. For a thermometer in degrees
+ Celsius, the absolute minimum is just under -273. For my
+ router, I can assume this minimum is much higher so I
+ would say it is 10. The maximum temperature for my router
+ I would state as 80. Any higher and the device would be
+ out of order. For my car, I would never expect negative
+ numbers and also I would not expect numbers to be higher
+ than 230. Anything else, and there must have been an
+ error. Remember: the opposite is not true, if the numbers
+ pass this check it doesn't mean that they are correct.
+ Always judge the graph with a healthy dose of paranoia if
+ it looks weird.
+
+ DDDDaaaattttaaaa RRRReeeessssaaaammmmpppplllliiiinnnngggg
+
+ One important feature of RRDtool has not been explained
+ yet: It is virtually impossible to collect the data and
+ feed it into RRDtool on exact intervals. RRDtool therefore
+ interpolates the data so it is on exact intervals. If you
+
+
+
+10/May/99 19990510.19 20
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ do not know what this means or how it works, then here's
+ the help you seek:
+
+ Suppose a counter increases with exactly one for every
+ second. You want to measure it in 300 seconds intervals.
+ You should retrieve values that are exactly 300 apart.
+ However, due to various circumstances you are a few
+ seconds late and the interval is 303. The delta will also
+ be 303 in that case. Obviously RRDtool should not put 303
+ in the database and make you believe that the counter
+ increased 303 in 300 seconds. This is where RRDtool
+ interpolates: it alters the 303 value as if it would have
+ been stored earlier and it will be 300 in 300 seconds.
+ Next time you are at exactly the right time. This means
+ that the current interval is 297 seconds and also the
+ counter increased with 297. Again RRDtool alters the value
+ and stores 300 as it should be.
+
+ in the RDD in real
+
+ time+000: 0 delta="U" time+000: 0 delta="U"
+ time+300: 300 delta=300 time+300: 300 delta=300
+ time+600: 600 delta=300 time+603: 603 delta=303
+ time+900: 900 delta=300 time+900: 900 delta=297
+
+ Let's create two identical databases. I've chosen the time
+ range 920805000 to 920805900 as this goes very well with
+ the example numbers.
+
+ rrdtool create seconds1.rrd \
+ --start 920804700 \
+ DS:seconds:COUNTER:600:U:U \
+ RRA:AVERAGE:0.5:1:24
+
+ for Unix: cp seconds1.rrd seconds2.rrd
+ for Dos: copy seconds1.rrd seconds2.rrd
+ for vms: how would I know :)
+
+ rrdtool update seconds1.rrd \
+ 920805000:000 920805300:300 920805600:600 920805900:900
+ rrdtool update seconds2.rrd \
+ 920805000:000 920805300:300 920805603:603 920805900:900
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+10/May/99 19990510.19 21
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+ rrdtool graph seconds1.gif \
+ --start 920804700 --end 920806200 \
+ --height 200 \
+ --upper-limit 1.05 --lower-limit 0.95 --rigid \
+ DEF:seconds=seconds1.rrd:seconds:AVERAGE \
+ CDEF:unknown=seconds,UN \
+ LINE2:seconds#0000FF \
+ AREA:unknown#FF0000
+ rrdtool graph seconds2.gif \
+ --start 920804700 --end 920806200 \
+ --height 200 \
+ --upper-limit 1.05 --lower-limit 0.95 --rigid \
+ DEF:seconds=seconds2.rrd:seconds:AVERAGE \
+ CDEF:unknown=seconds,UN \
+ LINE2:seconds#0000FF \
+ AREA:unknown#FF0000
+
+ Both graphs should show the same.
+
+WWWWRRRRAAAAPPPPUUUUPPPP
+ It's time to wrap up this document. You now know all the
+ basics to be able to work with RRDtool and to read the
+ documentation available. There is plenty more to discover
+ about RRDtool and you will find more and more uses for the
+ program. You could create easy graphics using just the
+ examples provided and using only RRDtool. You could also
+ use the front ends that are available.
+
+MMMMAAAAIIIILLLLIIIINNNNGGGGLLLLIIIISSSSTTTT
+ Remember to subscribe to the mailing-list. Even if you are
+ not answering the mails that come by, it helps both you
+ and the rest. A lot of the stuff that I know about MRTG
+ (and therefore about RRDtool) I've learned while just
+ reading the list without posting to it. I did not need to
+ ask the basic questions as they are answered in the FAQ
+ (so: read that too) and in various mails by other users.
+ With thousands of users all over the world, there will
+ always be people who ask questions that you can answer
+ because you read this and other documentation and they
+ didn't.
+
+SSSSEEEEEEEE AAAALLLLSSSSOOOO
+ The RRD Tool manpages
+
+AAAAUUUUTTTTHHHHOOOORRRR
+ I hope you enjoyed the examples and their descriptions. If
+ you do, help other people by pointing them to this
+ document when they are asking basic questions. They will
+ not only get their answer but at the same time learn a
+ whole lot more.
+
+ Alex van den Bogaerdt <alex at ergens.op.het.net>
+
+
+
+
+
+10/May/99 19990510.19 22
+
+
+
+
+
+RRDTUTORIAL(1) rrdtool RRDTUTORIAL(1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+10/May/99 19990510.19 23
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.pod
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.pod (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.pod Sat Jul 13 18:46:12 2002
@@ -0,0 +1,340 @@
+=head1 NAME
+
+rrdtool graph - Create a graph based on data from one or several RRD
+
+=head1 SYNOPSIS
+
+B<rrdtool> B<graph> I<filename>
+S<[B<-s>|B<--start> I<seconds>]>
+S<[B<-e>|B<--end> I<seconds>]>
+S<[B<-x>|B<--x-grid> I<x-axis grid and label>]>
+S<[B<-y>|B<--y-grid> I<y-axis grid and label>]>
+S<[B<-v>|B<--vertical-label> I<text>]>
+S<[B<-w>|B<--width> I<pixels>]>
+S<[B<-h>|B<--height> I<pixels>]>
+S<[B<-i>|B<--interlaced>]>
+S<[B<-o>|B<--logarithmic>]>
+S<[B<-u>|B<--upper-limit> I<value>]>
+S<[B<-l>|B<--lower-limit> I<value>]>
+S<[B<-r>|B<--rigid>]>
+S<[B<-b>|B<--base> I<value>]>
+S<[B<-c>|B<--color> I<COLORTAG>B<#>I<rrggbb>]>
+S<[B<-t>|B<--title> I<title>]>
+S<[B<DEF:>I<vname>B<=>I<rrd>B<:>I<ds-name>B<:>I<CF>]>
+S<[B<CDEF:>I<vname>B<=>I<rpn-expression>]>
+S<[B<PRINT:>I<vname>B<:>I<CF>B<:>I<format>]>
+S<[B<GPRINT:>I<vname>B<:>I<CF>B<:>I<format>]>
+S<[B<COMMENT:>I<text>]>
+S<[B<HRULE:>I<value>B<#>I<rrggbb>[B<:>I<legend>]]>
+S<[B<VRULE:>I<time>B<#>I<rrggbb>[B<:>I<legend>]]>
+S<[B<LINE>{B<1>|B<2>|B<3>}B<:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]]>
+S<[B<AREA:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]]>
+S<[B<STACK:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]]>
+
+=head1 DESCRIPTION
+
+The B<graph> functions main purpose is to create graphical
+representations of the data stored in one or several B<RRD>s. Apart
+from generating graphs, it can also extract numerical reports.
+
+=over 8
+
+=item I<filename>
+
+The name of the graph to generate. Since B<rrdtool> outputs
+GIF's, it's recommended that the filename end in F<.gif>.
+B<rrdtool> does not enforce this, however. If the I<filename>
+is et to '-' the gif file will be written to standard out. All
+other output will get supressd.
+
+If no graph functions are called, the graph will not be created.
+
+=item B<-s>|B<--start> I<seconds> (default -24*3600)
+
+The time when the graph should begin. Time in seconds since
+epoch (1970-01-01) is required. Negative numbers are relative to the
+end time. By default one day worth of data will be graphed.
+See also AT-STYLE TIME SPECIFICATION section in the I<rrdfetch>
+documentation for alternative ways to specify start time.
+
+=item B<-e>|B<--end> I<seconds> (default current time)
+
+The time when the graph should end. Time in seconds since epoch.
+See also AT-STYLE TIME SPECIFICATION section in the I<rrdfetch>
+documentation for alternative ways to specify end time.
+
+=item B<-x>|B<--x-grid> I<x-axis grid and label> (default autoconfigure)
+
+The x-axis label is quite complex to configure. So if you don't have
+very special needs, you can relay on the autoconfiguration to get this
+right.
+
+The x-axis label is configured, using the following format:
+
+I<GTM>B<:>I<GST>B<:>I<MTM>B<:>I<MST>B<:>I<LTM>:I<LST>B<:>I<LPR>B<:>I<LFM>
+
+You have to configure three elements making up the x-axis labels and
+grid. The base grid (I<G??>), the major grid (I<M??>) and the labels
+(I<L??>). The configuration is based on the idea that you first
+specify a well known amount of time (I<?TM>) and then say how many
+times it has to pass between each grid line or label (I<?ST>). For the
+label you have to define two additional items: The precision of the
+label in seconds (I<LPR>) and the strftime format used to generate the
+text of the label (I<LFM>).
+
+The I<?TM> elements must be one of the following keywords: B<SECOND>,
+B<MINUTE>, B<HOUR>, B<DAY>, B<WEEK>, B<MONTH> or B<YEAR>.
+
+If you wanted a graph with a base grid every 10 minutes and a major
+one every hour, with labels every hour you would use the following
+x-axis definition.
+
+C<MINUTE:10:HOUR:1:HOUR:1:0:%X>
+
+The precision in this example is 0 because the %X format is exact. If
+the label was the name of the day, we would have had a precision of 24
+hours, because when you say something like 'Monday' you mean the whole
+day and not Monday morning 00:00. Thus the label should be positioned
+at noon. By defining a precision of 24 hours or rather 86400 seconds,
+you make sure that this happens.
+
+=item B<-y>B<--y-grid> I<grid step>:I<label factor> (default autoconfigure)
+
+Makes vertical grid lines appear at I<grid step> interval. Every
+I<label factor> gridstep, a major grid line is printed, along with
+label showing the value of the grid line.
+
+=item B<-v>|B<--vertical-label> I<text>
+
+vertical label on the left side of the graph. This is normally used to
+specify the units used.
+
+=item B<-w>|B<--width> I<pixels> (default 400 pixel)
+
+Width of the drawing area within the graph. This affects the size of the
+gif.
+
+=item B<-h>|B<--height> I<pixels> (default 100 pixel)
+
+Width of the drawing area within the graph. This affects the size of the
+gif.
+
+=item B<-i>|B<--interlaced> (default: false)
+
+If you set this option, then the resulting GIF will be interlaced.
+Most web browsers display these incrementally as they load. If
+you do not use this option, the GIFs default to being progressive
+scanned. The only effect of this option is to control the format
+of the GIF on disk. It makes no changes to the layout or contents
+of the graph.
+
+=item B<-u>|B<--upper-limit> I<value> (default autoconfigure)
+
+The maximum value to be graphed. By default This will be
+autoconfigured from the data you select with the graphing functions.
+
+=item B<-l>|B<--lower-limit> I<value> (default autoconfigure)
+
+The minimum value to be graphed. By default This will be
+autoconfigured from the data you select with the graphing functions.
+
+=item B<-r>|B<--rigid>
+
+rigid boundaries mode. Normally rrdgraph will automatically expand the
+lower and upper limit if the graph contains a value outside the valid
+range. With the r option you can disable this behavior
+
+=item B<-b>|B<--base> I<value>
+
+if you are graphing memmory (and NOT network traffic) this switch
+should be set to 1024 so that one Kb is 1024 byte. For traffic
+measurement, 1 kb/s is 1000 b/s.
+
+=item B<-o>|B<--logarithmic>
+
+logarithmic y-axis scaling
+
+=item B<-c>|B<--color> I<COLORTAG>B<#>I<rrggbb> (default colors)
+
+override the colors for the standard elements of the graph. The I<COLORTAG>
+must be one of the following symbolic names: B<BACK> ground, B<CANVAS>,
+B<SHADEA> left/top border, B<SHADEB> right/bottom border, B<GRID>, B<MGRID>
+major grid, B<FONT>, B<FRAME> and axis of the graph or B<ARROW>. This option
+can be called multiple times to set several colors.
+
+=item B<-t>|B<--title> I<text> (default no title)
+
+Define a title to be written into the graph
+
+=item B<DEF:>I<vname>B<=>I<rrd>B<:>I<ds-name>B<:>I<CF>
+
+Define virtual name for a data source. This name can then be used
+in the functions explained below. The
+DEF call automatically chooses an B<RRA> which provides data in a
+resolution appropriate for the size of the graph to be drawn. Ideally
+this means that one data point from the B<RRA> should be represented
+by one pixel in the graph. If the resolution of the B<RRA> is higher
+than the resolution of the graph, the data in the RRA will be
+consolidated according to the consolidation function (I<CF>) chosen.
+
+=item B<CDEF:>I<vname>B<=>I<rpn-expression>
+
+Create a new virtual data source by evaluating a mathematical expression,
+specified in Reverse Polish Notation (RPN). If you have ever used a traditional
+HP calculator you already know RPN. The idea behind RPN notation is,
+that you have a stack and push your data onto this stack. When ever
+you execute an operation, it takes as many data values from the stack
+as needed. The pushing of data is implicit, so when ever you specify a number
+or a variable, it gets pushed automatically.
+
+If this is all a big load of
+incomprehensible words for you, maybe an example helps (a more
+complete explanation is given in [1]):
+The expression
+vname+3/2 becomes vname,3,2,/,+ in RPN. First the three values get
+pushed onto the stack (which now contains (the current value of)
+vname, a 3 and a 2).
+Then the / operator pops two values from the stack (3 and 2), divides
+the first argument by the second (3/2) and pushes the result (1.5)
+back onto the stack. Then the + operator pops two values (vname and
+1.5) from the stack; both values are added up and the result gets
+pushes back onto the stack. In the end there is only one value left on
+the stack: The result of the expression.
+
+The I<rpn-expression> in the B<CDEF> function takes both, constant values
+as well as I<vname> variables. The following operators can be used on these
+values:
+
+=over 8
+
+=item +, -, *, /
+
+pops two values from the stack applies the selected operator and pushes
+the result back onto the stack.
+
+=item SIN, COS, LOG, EXP
+
+pops one value from the stack, applies the selected function and pushes
+the result back onto the stack.
+
+=item LT, LE, GT, GE, EQ
+
+pops two values from the stack, compares them according to the selected
+condition and pushes either 1 back onto the stack if the condition is true
+and 0 if the condition was not true.
+
+
+
+=item IF
+
+pops three values from the stack. If the last value is not 0, the
+second value will be pushed back onto the stack, otherwise the
+first value is pushed back.
+
+If the stack contains the values A, B, C, D, E are presently on the
+stack, the IF operator will pop the values E D and C of the stack. It will
+look at C and if it is not 0 it will push D back onto the stack, otherwise
+E will be sent back to the stack.
+
+=item UN
+
+Pops one value of the stack, if it is I<*UNKNOWN*>, 1 will be pushed
+back otherwise 0.
+
+=back
+
+Please note that you may only use I<vname> variables that you
+previously defined by either B<DEF> or B<CDEF>. Furthermore, as of
+this writing (version 0.99.25), you must use at least one I<vname>
+per expression, that is "CDEF:fourtytwo=2,40,+" will yield an error
+message but not a I<vname> fourtytwo that's always equal to 42.
+
+=item B<PRINT:>I<vname>B<:>I<CF>B<:>I<format>
+
+Calculate the chosen consolidation function I<CF> over the data-source
+variable I<vname> and C<printf> the
+result to stdout using I<format>.
+
+=item B<GPRINT:>I<vname>B<:>I<CF>B<:>I<format>
+
+Same as B<PRINT> but the result is printed into the graph below the legend.
+
+=item B<COMMENT:>I<text>
+
+Like B<GPRINT> but the I<text> is simply printed into the graph.
+
+=item B<HRULE:>I<value>B<#>I<rrggbb>[B<:>I<legend>]
+
+Draw a horizontal rule into the graph and optionally add a legend
+
+=item B<VRULE:>I<time>B<#>I<rrggbb>[B<:>I<legend>]
+
+Draw a vertical rule into the graph and optionally add a legend
+
+=item B<LINE>{B<1>|B<2>|B<3>}B<:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]
+
+Plot for the requested data, using the color specified. Write a legend
+into the graph. The 3 possible keywords B<LINE1>, B<LINE2>, and B<LINE3>
+generate increasingly wide lines. If no color is defined,
+the drawing is done 'blind' this is useful in connection with the
+B<STACK> function when you want to ADD the values of two
+data-sources without showing it in the graph.
+
+=item B<AREA>:I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]
+
+Does the same as B<LINE?>, but the area between 0 and
+the graph will be filled with the color specified.
+
+=item B<STACK>:I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]
+
+Does the same as B<LINE?>, but the graph gets stacked on top of the previous
+B<LINE?>, B<AREA> or B<STACK> graph. Depending on the type of the
+previous graph, the B<STACK> will be either a B<LINE?> or an B<AREA>.
+This obviously implies that the first B<STACK> must be preceeded by an
+B<AREA> or B<LINE?> -- you need something to stack something onto in
+the first place ;)
+
+=back
+
+=head1 NOTE
+
+In a ':' in a I<legend> argument will mark the end of the legend. To
+enter a ':' into a legend, the colon must be escaped with a backslash '\:'.
+Beware, that many environments look for backslashes themselves, so it may
+be necessary to write two backslashes so that one is passed onto rrd_graph.
+
+=head1 NOTE 2
+
+The text printed below the actual graph can be formated by appending special
+escaped charactes at the end of a text. When ever such a character occurs,
+all pending text is pushed onto the grah acording to the character specified.
+
+Valid characters are: B<j> for justified, B<l> for left aligned, B<r>
+for right aligned and B<c> for centered. In the next section there is an example
+showing how to use centered formating.
+
+A special case is COMMENT:\s this inserts some additional vertical space before
+placing the next row of legends.
+
+=head1 NOTE 3
+
+Whenever rrd_graph gets called, it prints a line telling the size of
+the gif it has just created to STDOUT. This line looks like this: XSIZExYSIZE.
+
+=head1 EXAMPLE
+
+ rrdtool graph demo.gif --title="Demo Graph" \
+ DEF:cel=demo.rrd:exhaust:AVERAGE \
+ "CDEF:far=cel,32,-,0.55555,*" \
+ LINE2:cel#00a000:"D. Celsius" \
+ LINE2:far#ff0000:"D. Fahrenheit\c"
+
+=head1 AUTHOR
+
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
+=head1 REFERENCES
+
+[1] http://www.dotpoint.com/xnumber/rpn_or_adl.htm
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.txt
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.txt (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.txt Sat Jul 13 18:46:12 2002
@@ -0,0 +1,66 @@
+
+
+
+RRDDUMP(1) rrdtool RRDDUMP(1)
+
+
+NNNNAAAAMMMMEEEE
+ rrdtool dump - dump the contents of an RRRRRRRRDDDD in human
+ readable form
+
+SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
+ rrrrrrrrddddttttoooooooollll dddduuuummmmpppp _f_i_l_e_n_a_m_e [--------ffffuuuullllllll|----ffff]
+
+DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
+ The dddduuuummmmpppp function prints the contents of an RRRRRRRRDDDD in human
+ readable form.
+
+ _f_i_l_e_n_a_m_e
+ The name of the RRRRRRRRDDDD you want to dump.
+
+ --------ffffuuuullllllll|----ffff
+ By default only the headers of the RRRRRRRRDDDD are
+ printed. With this option you get the actual data
+ as well.
+
+AAAAUUUUTTTTHHHHOOOORRRR
+ Tobias Oetiker <oetiker at ee.ethz.ch>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+29/Mar/98 19990426.22 1
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.pod
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.pod (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.pod Sat Jul 13 18:46:12 2002
@@ -0,0 +1,27 @@
+=head1 NAME
+
+rrdtool last - Return the date of the last data sample in an B<RRD>
+
+=head1 SYNOPSIS
+
+B<rrdtool> B<last> I<filename>
+
+=head1 DESCRIPTION
+
+The B<last> function returns the UNIX timestamp when the RRD was last
+updated.
+
+=over 8
+
+=item I<filename>
+
+The name of the B<RRD> that contains the data.
+
+=back
+
+=head1 AUTHOR
+
+Russ Wright <rwwright at home.com>
+
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.pod
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.pod (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.pod Sat Jul 13 18:46:12 2002
@@ -0,0 +1,1078 @@
+=head1 NAME
+
+rrdtutorial - Alex van den Bogaerdts RRD Tool tutorial
+
+=head1 DESCRIPTION
+
+RRDtool is written by Tobias Oetiker <oetiker at ee.ethz.ch> with
+contributions from many people all around the world. This document is
+written by Alex van den Bogaerdt <alex at ergens.op.het.net> to help you
+understand what RRDtool is and what it can do for you.
+
+The documentation provided with RRDtool can be too technical for some
+people and here we help you to understand the basics in order to
+prepare you to read the documentation yourself. It also explains the
+general things about statistics with a focus on networking.
+
+=head1 TUTORIAL
+
+=head2 Important
+
+We first have to do some uninteresting reading folks, don't skip this
+part! Later on, in the examples, you need to know the basics.
+
+=head2 What is RRDtool ?
+
+RRDtool means Round Robin Database tool.
+Round robin is a technique that works with a fixed amount of data, and a
+pointer to the current element. Think of a circle with some dots plotted
+on the edge, these dots are the places where data can be stored. Draw an
+arrow from the center of the circle to one of the dots, this is the pointer.
+When the current data is read or written, the pointer moves to the next
+element. As we are on a circle there is no beginning nor an end, you can
+go on and on. After a while, all the available places will be used and
+the process automatically reuses old locations.
+RRDtool works with with Round Robin Databases (RRDs). It stores and retrieves
+data from them.
+
+=head2 What data can be put into an RDD ?
+
+You name it, it will probably fit. You should be able to measure some value
+at several points in time and provide this to RRDtool. If you can do this,
+RRDtool will probably be able to store it.
+
+Many examples talk about SNMP which is an acronym for
+Simple Network Management Protocol. The "simple" is about the protocol,
+it does not mean it is simple to manage a network. After working your
+way through this document, you will know enough to be able to understand
+what people are talking about. For now, just assume SNMP is a way to
+talk to devices and ask those devices about counters they keep.
+It is the value from those counters that are kept in the RRD.
+
+=head2 What can I do with this tool ?
+
+RRDtool originated from MRTG (multi router traffic grapher) which itself
+came from a tiny little script to monitor the performance of a connection
+to the Internet. Since then, MRTG has also been used for several other
+purposes including temperature, speed, voltage, number of printouts and
+many other things. Most likely you will start to use the RRDtool to store
+and process data collected via SNMP. The data will most likely be bytes
+(or bits) transfered from and to a network or a computer.
+RRDtool lets you create a database, store data in it, retrieve that data
+and create graphs in GIF format for display on a web browser. Those GIF
+images are dependant on the data you collected and could be, for instance,
+an overview of the average network usage, or rather the peaks that occurred.
+It can also be used to display tidal waves, solar radiation, power
+consumption, number of visitors at an exibition, noise levels near an
+airport, temperature on your favorite holiday location, temperature in the
+fridge and whatever you imagination can come up with. You need a sensor to
+measure the data and be able to feed the numbers to RRDtool. Many devices
+have such a sensor.
+
+=head2 What if I still have problems after reading this document ?
+
+More exact, after re-reading this document :)
+It all depends on the kind of problems you have. If you are unable to
+compile the sources and you have a fairly common OS, it will probably
+not be the fault of RRDtool. There may be precompiled versions around
+on the Internet. If they come from trusted sources, get one of those.
+If on the other hand the program works but does not give you the
+expected results, it will be a problem with configuring it. Review
+your configuration and compare it with the examples that follow.
+
+There is a mailing list and an archive of it. Read the list for a few
+weeks and search the archive. It is considered rude to just ask
+a question without reading the list, your problem may already have been
+solved for somebody else and you will be helped without writing a new
+a message at all ... This is true for most, if not all, mailing lists
+and not only for this particular list! Look in the documentation that
+came with RRDtool for the location and usage of the list.
+
+I suggest you take a moment to subscribe to the mailing list right now
+by sending an email to <rrdtool-users-request at list.ee.ethz.ch> with a
+subject of "subscribe". If you ever want to leave this list, you write
+an email to the same address but now with a subject of "unsubscribe".
+
+=head2 How will you help me ?
+
+By giving you some detailed descriptions with detailed examples.
+It is assumed that following the instructions in the order presented
+will build up enough knowledge of the program to experiment for yourself.
+If it doesn't work the first time, don't give up. Reread the stuff that
+you did understand, you may have missed something.
+By following the examples you get some hands-on experience and, even
+more important, some background information of how it works.
+
+You will need to know something about hexadecimal numbers. If you don't
+then start with reading "bin_dec_hex" before you continue here.
+
+=head2 Your first Round Robin Database
+
+In my opinion the best way to learn something is to actually do it.
+Why not start right now? We will create a database, put some values in
+it and extract this data again. It is expected that you get the same
+results when you try these examples yourself so do that.
+We will start with some easy stuff and compare a car with a router,
+or compare kilometers (miles if you wish) with bits and bytes. It's
+all the same: Some number over some time.
+
+Assume we have a device that transfers bytes to and from the Internet.
+This device keeps a counter that starts at zero when it is turned on,
+increasing with every byte that is transfered. This counter will have
+a maximum value, if that value is reached and an extra byte is counted,
+the counter starts all over at zero. This is the same as many counters
+in the world such as the mileage counter in a car.
+Most discussions about networking talk about bits per second so lets
+get used to that right away. Assume a byte is eight bits and start to
+think in bits not bytes. The counter however still counts bytes !
+In the SNMP world most of the counters are 32 bits. That means they are
+counting from 0 to 4294967295. We will use these values in the examples.
+The device, when asked, returns the current value of the counter. We
+know the time that has passes since we last asked so we now know how
+many bytes have been transfered ***on average*** per second. This is
+not very hard to calculate. First in words, then in calculi:
+
+=over 3
+
+=item 1.
+
+Take the current counter, subtract the previous value from it.
+
+=item 2.
+
+Do the same with the current time and the previous time.
+
+=item 3.
+
+Divide the outcome of (1) by the outcome of (2), the result is
+the amount of bytes per second. Multiply by eight to get the
+number of bits per second (bps).
+
+ bps = (counter_now - counter_before) / (time_now - time_before) * 8
+
+=back
+
+For some people it may help to translate this to a automobile example:
+Do not try this example, and if you do, don't blame me for the results.
+
+People who are not used to think in kilometers per hour can translate
+most into miles per hour by dividing km by 1.6 (close enough).
+I will use the following abbreviations:
+
+ M: meter
+ KM: kilometer (= 1000 meters).
+ H: hour
+ S: second
+ KM/H: kilometers per hour
+ M/S: meters per second
+
+You're driving a car. At 12:05 you read the counter in the dashboard
+and it tells you that the car has moved 12345 KM until that moment.
+At 12:10 you look again, it reads 12357 KM. This means you have
+traveled 12 KM in five minutes. A scientist would translate that
+into meters per second and this makes a nice comparison towards the
+problem of (bytes per five minutes) versus (bits per second).
+
+We traveled 12 kilometers which is 12000 meters. We did that in five
+minutes which translates into 300 seconds. Our speed is 12000M / 300S
+equals 40 M/S.
+
+We could also calculate the speed in KM/H: twelve times five minutes
+is an hour so we have to multiply 12 KM by 12 to get 144 KM/H.
+For our native English speaking friends: this is ninety MPH and
+therefore not recommended to try for yourself where I live :)
+
+Remember: these numbers are averages and there is no way to figure out
+from the numbers we got that you drove at a constant speed.
+
+I hope you understand that there is no difference in calculating M/S or
+bps, only the way we collect the data is different. Even the K from kilo
+is the same as in networking terms k also means 1000.
+
+We will now create a database where we can keep all these interesting
+numbers. The method used to start the program may differ slightly from
+OS to OS but I assume you can figure it out if it works different on
+your OS. Make sure you do not overwrite any file on your system when
+executing the following command (so: first look if it's safe!) and type
+the whole line as one long line (I had to split it for readability)
+and skip all of the '\' characters.
+
+ rrdtool create test.rrd \
+ --start 920804400 \
+ DS:speed:COUNTER:600:U:U \
+ RRA:AVERAGE:0.5:1:24 \
+ RRA:AVERAGE:0.5:6:10
+
+(So enter: C<rrdtool create test.rrd --start 920804400 DS ...>)
+
+=head2 What has been created ?
+
+We created the round robin database called test (test.rrd)
+which starts at noon the day I started (7th of march, 1999) writing
+this document. It holds one data source (DS) named "speed" that gets
+built from a counter. This counter is read every five minutes (default)
+In the same database two round robin archives (RRAs) are kept, one
+averages the data every time it is read (so: there's nothing to average)
+and keeps 24 samples (24 times 5 minutes is 2 hours). The other averages
+6 values (half hour) and contains 10 of such averages (so: 5 hours)
+The remaining options will be discussed later on.
+Chances are that you are not in the same part of the world as I am.
+This means your time zone is different. In all examples where I talk
+about time, the hours may be wrong for you. This has little effect on
+the results of the examples, just correct the hours while reading.
+
+We now have to fill our database with some numbers. We'll pretend to
+have read the following numbers:
+
+ 12:05 12345 KM
+ 12:10 12357 KM
+ 12:15 12363 KM
+ 12:20 12363 KM
+ 12:25 12363 KM
+ 12:30 12373 KM
+ 12:35 12383 KM
+ 12:40 12393 KM
+ 12:45 12399 KM
+ 12:50 12405 KM
+ 12:55 12411 KM
+ 13:00 12415 KM
+ 13:05 12420 KM
+ 13:10 12422 KM
+ 13:15 12423 KM
+
+We fill the database as follows:
+
+ rrdtool update test.rrd 920804700:12345 920805000:12357 920805300:12363
+ rrdtool update test.rrd 920805600:12363 920805900:12363 920806200:12373
+ rrdtool update test.rrd 920806500:12383 920806800:12393 920807100:12399
+ rrdtool update test.rrd 920807400:12405 920807700:12411 920808000:12415
+ rrdtool update test.rrd 920808300:12420 920808600:12422 920808900:12423
+
+This reads: update our test database with the following numbers
+
+ time 920804700, value 12345
+ time 920805000, value 12357
+
+etcetera.
+
+As you can see, it is possible to feed more than one value into the
+database in one command. I had to stop at three for readability but
+the real maximum will be OS dependent.
+
+The time value may look strange to you, it is written in seconds since
+the first of January, 1970, midnight. Don't worry about this yet, just
+notice that there is a difference of 300 in between all values.
+
+=head2 It is time to create some graphics
+
+Try the following command:
+
+ rrdtool graph speed.gif \
+ --start 920804400 --end 920808000 \
+ DEF:myspeed=test.rrd:speed:AVERAGE \
+ LINE2:myspeed#FF0000
+
+This will create speed.gif which starts at 12:00 and ends at 13:00.
+There is a definition of variable myspeed, it is the data from RRA
+"speed" out of database "test.rrd". The line drawn is 2 pixels high,
+and comes from variable myspeed. The color is red.
+You'll notice that the start of the graph is not at 12:00 but at 12:05
+and this is because we have insufficient data to tell the average before
+that time. This will only happen when you miss some samples, this will
+not happen a lot, hopefully.
+
+If this has worked: Congratulations. If not, check what went wrong.
+
+
+The colors are built up from red, green and blue. For each of the
+components, you specify how much to use in hexadecimal where 00 means
+not included and FF means fully included.
+The color white is a mixture of red, green and blue: FFFFFF
+The color black is all colors off: 000000
+(Please, no discussions if black and white can be called colors)
+
+ red #FF0000
+ green #00FF00
+ blue #0000FF
+ purple #FF00FF (mixed red with blue)
+ gray #555555 (one third of all components)
+
+
+
+The GIF you just created can be displayed using a web browser or other
+software you like. I can not provide you with an example of that,
+because there are too many different setups, possibilities etc.
+
+=head2 Graphics with some math
+
+When looking at the image, you notice that the horizontal axis displays
+12:10, 12:20, 12:30, 12:40 and 12:50. The two remaining times (12:00 and
+13:00) would not be displayed nicely so they are skipped.
+The vertical axis displays the range we entered. We provided kilometers
+and when divided by 300 seconds, we get very small numbers. To be exact,
+the first value was 12 (12357-12345) and divided by 300 this makes 0.04
+RRDtool displays this as 40 m which means 40 mili (so: NOT meters).
+What we did wrong was that we should have measured in meters, this would
+have been (12357000-12345000)/300 = 12000/300 = 40.
+
+Let's correct that. We could recreate our database and store the correct
+data but there is another way: do some calculations while creating the
+gif file !
+
+ rrdtool graph speed2.gif \
+ --start 920804400 --end 920808000 \
+ --vertical-label m/s \
+ DEF:myspeed=test.rrd:speed:AVERAGE \
+ CDEF:realspeed=myspeed,1000,* \
+ LINE2:realspeed#FF0000
+
+After viewing this GIF, you notice the "m" has disappeared. This it what
+the correct result would be. Also, a label has been added to the image.
+Apart from the things mentioned above, the GIF should be the same.
+
+The calculations are done with the CDEF part. What it says is: take the
+data source myspeed and the number 1000, multiply those. The calculations
+are done using Reverse Polish Notation. It is an easy way of performing
+calculations after you understand it. You will, eventually but for now
+assume it is correct what I write and just keep to the examples in this
+file. Read the documentation that came with RRDtool (look in rrdgraph.doc)
+when you're ready for it.
+
+Hang on! If we can multiply values with 1000, it should also be possible
+to display kilometers per hour from the same data !
+What do we need to do ? If we have meters per second, we can make this
+meters per hour by multiplying the value with 3600 (there go 3600 seconds
+in one hour). To get kilometers per hour, we need to divide by 1000.
+We end up with: value * 3600 / 1000 = value * 3.6 . Remember we also have
+to correct our mistake, so it is value * 3600 for us.
+
+Now let's create this GIF, and add some more magic ...
+
+ rrdtool graph speed3.gif \
+ --start 920804400 --end 920808000 \
+ --vertical-label km/h \
+ DEF:myspeed=test.rrd:speed:AVERAGE \
+ CDEF:kmh=myspeed,3600,* \
+ CDEF:fast=kmh,100,GT,kmh,0,IF \
+ CDEF:good=kmh,100,GT,0,kmh,IF \
+ HRULE:100#0000FF:"Maximum allowed" \
+ AREA:good#00FF00:"Good speed" \
+ AREA:fast#FF0000:"Too fast"
+
+This looks much better. Speed in KM/H and even an extra line with the
+maximum allowed speed (on the road I travel at). I also changed the
+colors used to display speed and changed it from a line into an area.
+
+The calculations are more complex now. For the "good" speed they are:
+
+=over 2
+
+=item *
+
+Check if kmh is greater than 100 ( kmh,100 ) GT
+
+=item *
+
+If so, return 0, else kmh ((( kmh,100 ) GT ), 0, kmh) IF
+
+=back
+
+For the other speed:
+
+=over 2
+
+=item *
+
+Check if kmh is greater than 100 ( kmh,100 ) GT
+
+=item *
+
+If so, return kmh, else return 0 ((( kmh,100) GT ), kmh, 0) IF
+
+=back
+
+=head2 Graphics Magic
+
+I like to believe there are virtually no limits about what RRDtool
+can do. I will not explain how it works, but look at the following
+GIF:
+
+ rrdtool graph speed4.gif \
+ --start 920804400 --end 920808000 \
+ --vertical-label km/h \
+ DEF:myspeed=test.rrd:speed:AVERAGE \
+ CDEF:kmh=myspeed,3600,* \
+ CDEF:fast=kmh,100,GT,100,0,IF \
+ CDEF:over=kmh,100,GT,kmh,100,-,0,IF \
+ CDEF:good=kmh,0,kmh,100,GT,IF \
+ HRULE:100#0000FF:"Maximum allowed" \
+ AREA:good#00FF00:"Good speed" \
+ AREA:fast#550000:"Too fast" \
+ STACK:over#FF0000:"Over speed"
+
+Let's create a quick and dirty HTML page to view three GIFs:
+
+ <HTML><HEAD><TITLE>Speed</TITLE></HEAD><BODY>
+ <IMG src="speed2.gif" alt="Speed in meters per second">
+ <BR>
+ <IMG src="speed3.gif" alt="Speed in kilometers per hour">
+ <BR>
+ <IMG src="speed4.gif" alt="Traveled too fast?">
+ </BODY></HTML>
+
+Name the file "speed.html" or similar, and view it.
+
+Now, all you have to do is measure the values regularly and update the
+database. Every time you create these three GIFs and reload the page
+and the GIFs (better reread these last three words!) you know how fast
+you traveled.
+
+=head2 Updates in Reality
+
+You already looked at the "update" tool. It took one or more parameters
+in the form of "<time>:<value>". You'll be glad to know that you can
+get the current time by filling in a "N" as the time.
+If you wish, you can also use the "time" function in perl.
+The shortest example in this doc :)
+
+ perl -e 'print time, "\n" '
+
+How you can run a program on regular intervals is OS specific, so I just
+give you an example script in a sort of pseudo code:
+(Do not try this with our test database, it is used in further examples)
+
+ Get the value, put it in variable "$speed"
+ rrdtool update speed.rrd N:$speed
+
+This is all. Run this script every five minutes. When you need to know
+what the graphics look like, run the examples above. You could put them
+in a script. After running that script, view index.html
+
+=head2 Some words on SNMP
+
+I can imagine very few people will be able to get real data from their
+car every five minutes, all other people will have to settle for some
+other kind of counter. You could measure the number of pages printed by
+the laser-jet printer, the coffee made by the coffee machine, a device
+that counts the electricity used, whatever. Just as long as it is an
+incrementing counter that you can measure regularly, you can graph it
+against time as we did. Most people will use the counter that keeps track
+of octets (bytes) transfered by a routing device so we have to do just
+that. We will start with a description of how to collect data.
+Some people will make a remark that there are tools who can do this data
+collection for you. They are right! However, I feel it is important that
+you understand they are not necessary. If you have to look why things
+went wrong, you need to know how the stuff works.
+
+One tool used in the example has been talked about very briefly in the
+beginning of this document, it is called SNMP. It is a way of talking to
+equipment. The tool I use below is called "snmpget" and this is how it
+works:
+
+ snmpget device password OID
+
+For device you substitute the name of your device, for password you
+use the "community" as it is called. For most devices "public" will do
+but this can be disabled, altered or protected for privacy and security
+reasons. You will need to find this out as there is no way I can tell
+what you ( ...your device... ) are keeping a secret from me.
+
+Then there is this third parameter, called OID.
+When you start to learn about SNMP it looks very confusing. It isn't
+all that difficult when you look at the Management Information Base
+or in short: the MIB. It is an upside-down tree, with a single node
+as the root and from there a number of branches. These branches end
+up in another node, they branch out, etc. All the branches have a name
+and they form the path that we follow all the way down. The branches
+that we follow are named: iso, org, dod, internet, mgmt and mib-2.
+These names can also be written down as numbers and are 1 3 6 1 2 1.
+
+ iso.org.dod.internet.mgmt.mib-2 (1.3.6.1.2.1)
+
+From there, we are especially interested in the branch "interfaces"
+which has number 2 (so: 1.3.6.1.2.1.2 or 1.3.6.1.2.1.interfaces).
+
+The SNMP programs that I know can take above path as a default, so
+I could walk to interfaces without writing it in full. To do that,
+the path has to be written as interfaces, without a leading dot.
+I could also use the long form, then I need to start with a dot.
+
+I can intermix numbers and names as I like. 1.3.6.1.2.1 is the same
+as iso.org.dod.1.2.1 and 1.3.6.internet.2.mib-2
+For interfaces I could write "interfaces", 2, or a long version by
+prefixing it with ".1.3.6.1.2.1.". Just try what works for you and
+do read the manual for the version of snmpget you are using.
+
+First, we have to get some SNMP program. First look if there is a
+pre-compiled package available for your OS. This is the preferred way.
+If not, you will have to get yourself the sources and compile those.
+The Internet is full of sources, programs etc. Find information using
+a search engine or whatever you prefer. You are on your own here, sorry.
+
+Assume you got the program. First try to collect some data that is
+available on most systems. Remember: there is a short name for the
+part of the tree that interests us most in the world we live in !
+I will use the short version as I think this document is large enough
+as it is. If that doesn't work for you, prefix with .1.3.6.1.2.1 and
+try again. Also, Read The Fine Manual. Skip the parts you cannot
+understand yet, you should be able to find out how to start the
+program and use it.
+
+ snmpget myrouter public system.sysdescr.0
+
+The device should answer with a description of itself, perhaps empty.
+Until you got a valid answer from a device, perhaps using a different
+"password", or a different device, there is no point in continuing.
+
+ snmpget myrouter public interfaces.ifnumber.0
+
+Hopefully you get a number as a result, the number of interfaces.
+If so, you can carry on and try a different program called "snmpwalk".
+
+ snmpwalk myrouter public interfaces.iftable.ifentry.ifdescr
+
+If it returns with a list of interfaces, you're almost there.
+Here's an example:
+ [user at host /home/alex]$ snmpwalk cisco public 2.2.1.2
+
+ interfaces.ifTable.ifEntry.ifDescr.1 = "BRI0: B-Channel 1"
+ interfaces.ifTable.ifEntry.ifDescr.2 = "BRI0: B-Channel 2"
+ interfaces.ifTable.ifEntry.ifDescr.3 = "BRI0" Hex: 42 52 49 30
+ interfaces.ifTable.ifEntry.ifDescr.4 = "Ethernet0"
+ interfaces.ifTable.ifEntry.ifDescr.5 = "Loopback0"
+
+On this cisco equipment, I would like to monitor the "Ethernet0"
+interface and see that it is number four. I try:
+
+ [user at host /home/alex]$ snmpget cisco public 2.2.1.10.4 2.2.1.16.4
+
+ interfaces.ifTable.ifEntry.ifInOctets.4 = 2290729126
+ interfaces.ifTable.ifEntry.ifOutOctets.4 = 1256486519
+
+So now I have two OIDs to monitor and they are (in full, this time):
+
+ 1.3.6.1.2.1.2.2.1.10
+
+and
+
+ 1.3.6.1.2.1.2.2.1.16
+
+both with an interface number of 4.
+
+Don't get fooled, this wasn't my first try. It took some time for me too
+to understand what all these numbers mean, it does help a lot when they
+get translated into descriptive text... At least, when people are talking
+about MIBs and OIDs you know what it's all about.
+Do not forget the interface number (0 if it is not interface dependent)
+and try snmpwalk if you don't get an answer from snmpget.
+
+If you understand above part, and get numbers from your device, it is
+time to continue with the following. If not, then go back.
+
+=head2 A Real World Example
+
+Let the fun begin. First, create a new database. It contains data from
+two counters, called input and output. The data is put into archives
+that average it. They take 1, 6, 24 or 288 samples at a time.
+They also go into archives that keep the maximum numbers. This will be
+explained later on. The time in-between samples is 300 seconds, a good
+starting point, which is the same as five minutes.
+
+ 1 sample averaged stays 1 period of 5 minutes
+ 6 samples averaged become one average on 30 minutes
+ 24 samples averaged become one average on 2 hours
+ 288 samples averaged become one average on 1 day
+
+ There are 600 samples of five minutes, together just over two days
+ There are 600 samples of 30 minutes, almost two weeks
+ There are 600 samples of 2 hours, 50 hour or almost two months
+ There are 732 samples of 1 day, just over two years
+
+For people used to MRTG that even have read the manuals, these numbers
+should look familiar...
+
+ rrdtool create myrouter.rrd \
+ DS:input:COUNTER:600:U:U \
+ DS:output:COUNTER:600:U:U \
+ RRA:AVERAGE:0.5:1:600 \
+ RRA:AVERAGE:0.5:6:600 \
+ RRA:AVERAGE:0.5:24:600 \
+ RRA:AVERAGE:0.5:288:732 \
+ RRA:MAX:0.5:1:600 \
+ RRA:MAX:0.5:6:600 \
+ RRA:MAX:0.5:24:600 \
+ RRA:MAX:0.5:288:732
+
+Next thing to do is collect data and store it. Here is an example.
+It is written partially in pseudo code so you will have to find out what
+to do exactly on your OS to make it work.
+
+ while not the end of the universe
+ do
+ get result of
+ snmpget router community 2.2.1.10.4
+ into variable $in
+ get result of
+ snmpget router community 2.2.1.16.4
+ into variable $out
+
+ rrdtool update myrouter.rrd N:$in:$out
+
+ wait for 5 minutes
+ done
+
+Then, after collecting data for a day, try to create an image using:
+
+ rrdtool graph myrouter-day.gif --start -86400 \
+ DEF:inoctets=myrouter.rrd:input:AVERAGE \
+ DEF:outoctets=myrouter.rrd:output:AVERAGE \
+ AREA:inoctets#00FF00:"In traffic" \
+ LINE1:outoctets#0000FF:"Out traffic"
+
+This should produce a picture with one day worth of traffic.
+One day is 24 hours of 60 minutes of 60 seconds: 24*60*60=86400, we
+start at now minus 86400 seconds. We DEFine inoctets and outoctets
+as the average values from the database myrouter.rrd and draw an area
+for the "in" traffic and a line for the "out" traffic.
+
+View the image and keep logging for a few more days.
+If you like, you could try the examples from the test database and
+see if you can play around with the options and calculations.
+
+Suggestion:
+
+Display in bytes per second and in bits per second. Make the ethernet
+graphics go red if they are over four megabits per second.
+
+=head2 Consolidation Functions
+
+A few paragraphs back I mentioned the possibility of keeping
+the maximum values instead of the average values. Let's go
+into this a bit more.
+
+
+Recall all the stuff about the speed of the car. Suppose we drove at 144
+KM/H during 5 minutes and then were stopped by the police for 25 minutes.
+At the end of the lecture we would take our laptop and create+view the
+image taken from the database. If we look at the second RRA we did
+create, we would have the average from 6 samples. The samples measured
+would be 144+0+0+0+0+0=144, divided by 30 minutes, corrected for the
+error by 1000, translated into KM/H, with a result of 24 KM/H.
+I would still get a ticket but not for speeding anymore :)
+
+Obviously, in this case, we shouldn't look at the averages. In some
+cases they are handy. If you want to know how much KM you had traveled,
+the picture would be the right one to look at. On the other hand, for
+the speed that we traveled at, the maximum number seen is much more
+valuable. (later we will see more types)
+
+It is the same for data. If you want to know the amount, look at the
+averages. If you want to know the rate, look at the maximum.
+Over time, they will grow apart more and more. In the last database
+we have created, there are two archives that keep data per day. The
+archive that keeps averages will show low numbers, the archive that
+shows maxima will have higher numbers.
+For my car this would translate in averages per day of 96/24=4 KM/H
+(as I travel about 94 kilometers on a day) during week days, and
+maximum of 120 KM/H on weekdays (my top speed that I reach every day).
+
+Big difference. Do not look at the second graph to estimate the
+distances that I travel and do not look at the first graph to
+estimate my speed. This will work if the samples are close together,
+as they are in five minutes, but not if you average.
+
+On some days, I go for a long ride. If I go across Europe and travel
+for over 12 hours, the first graph will rise to about 60 KM/H. The
+second one will show 180 KM/H. This means that I traveled a distance
+of 60 KM/H times 24 H = 1440 KM. I did this with a higher speed and
+a maximum around 180 KM/H. This doesn't mean that I traveled for 8
+hours at a constant speed of 180 KM/H !
+This is a real example: go with the flow through Germany and stop
+a few times for gas and coffee. Drive slowly through Austria and the
+Netherlands. Be careful in the mountains and villages. If you would
+look at the graphs created from the five-minute averages you would
+get a totally different picture. You would see the same values on the
+average and maximum graphs (provided I measured every 300 seconds).
+You would be able to see when I stopped, when I was in top gear, when
+I drove over fast motor-ways etc. The granularity of the data is much
+higher, so you can see more. However, this takes 12 samples per hour,
+or 288 values per day, so it would be too much to keep for a long
+period of time. Therefore we average it, eventually to one value per
+day. From this one value, we cannot see much detail.
+
+Make sure you understand the last few paragraphs. There is no value
+in only a line and a few axis, you need to know what they mean and
+interpret the data in a good way. This is true for all data.
+
+The biggest mistake you can make is to use the collected data for
+something that it is not suitable for. You would be better off if
+you would not have the graphics at all in that case.
+
+
+=head2 Let's review what you now should know.
+
+You now know how to create a database. You can put the numbers in it,
+get them out again by creating an image, do math on the data from the
+database and view the outcome instead of the raw data.
+You know about the difference between averages and maxima, and when
+to use which (or at least you have an idea).
+
+RRDtool can do more than what we have learned up to now. Before you
+continue with the rest of this doc, I recommend that you reread from
+the start and try some modifications on the examples. Make sure you
+fully understand everything. It will be worth the effort and helps
+you not only with the rest of this doc but also in your day to day
+monitoring long after you read this introduction.
+
+=head2 Data Source Types
+
+All right, you feel like continuing. Welcome back and get ready
+for an increased speed in the examples and explanation.
+
+You know that in order to view a counter over time, you have to
+take two numbers and divide the difference of them between the
+time lapsed. This makes sense for the examples I gave you but there
+are other possibilities. For instance, I'm able to retrieve the
+temperature from my router in three places namely the inlet, the
+so called hot-spot and the exhaust. If I take the difference of
+the two samples and divide that by 300 (seconds) there would not be very
+much to display ... If there would be anything to display it would
+be the fluctuations in the temperature and if they produce noticeable
+results when divided by 300, I'd better look for a new computer room.
+
+So, what can we do ? RRDtool can also store the values you measure
+directly as they are (this is not entirely true but close enough). The
+graphs we make look much better, they will show a rather constant
+value. I know when the router is busy (it
+works -> it uses more electricity -> it generates more heat -> the
+temperature rises). I know when the doors are left open (the room is
+cooled -> the warm air from the rest of the building flows into the
+computer room -> the inlet temperature rises) etc. The data type we
+use when creating the database before was counter, we now have a
+different data type and thus a different name for it. It is called
+GAUGE. There are more such data types:
+
+ - COUNTER we already know this one
+ - GAUGE we just learned this one
+ - DERIVE
+ - ABSOLUTE
+
+The two new types are DERIVE and ABSOLUTE. Absolute can be used like
+counter with one difference: RRDtool assumes the counter is reset when
+it's read. That is: its delta is known without calculation by RRDtool
+whereas RRDtool needs to calculate it for the counter type.
+Example: our first example (12345, 12357, 12363, 12363) would read:
+unknown, 12, 6, 0. The rest of the calculations stay the same.
+The other one, derive, is like counter. Unlike counter, it can also
+decrease so it can have a negative delta. Again, the rest of the
+calculations stay the same.
+
+Let's try them all:
+
+ rrdtool create all.rrd --start 978300900 \
+ DS:a:COUNTER:600:U:U \
+ DS:b:GAUGE:600:U:U \
+ DS:c:DERIVE:600:U:U \
+ DS:d:ABSOLUTE:600:U:U \
+ RRA:AVERAGE:0.5:1:10
+ rrdtool update all.rrd \
+ 978301200:300:1:600:300 \
+ 978301500:600:3:1200:600 \
+ 978301800:900:5:1800:900 \
+ 978302100:1200:3:2400:1200 \
+ 978302400:1500:1:2400:1500 \
+ 978302700:1800:2:1800:1800 \
+ 978303000:2100:4:0:2100 \
+ 978303300:2400:6:600:2400 \
+ 978303600:2700:4:600:2700 \
+ 978303900:3000:2:1200:3000
+ rrdtool graph all1.gif -s 978300600 -e 978304200 -h 400 \
+ DEF:linea=all.rrd:a:AVERAGE LINE3:linea#FF0000:"Line A" \
+ DEF:lineb=all.rrd:b:AVERAGE LINE3:lineb#00FF00:"Line B" \
+ DEF:linec=all.rrd:c:AVERAGE LINE3:linec#0000FF:"Line C" \
+ DEF:lined=all.rrd:d:AVERAGE LINE3:lined#000000:"Line D"
+
+=head2 RRD Tool under the Microscope
+
+=over 2
+
+=item *
+
+Line A is a counter so it should continuously increment and RRDtool
+should calculate the differences. Also, RRDtool needs to divide the
+difference by the amount of time lapsed. This should end up as a
+straight line at 1 (the deltas are 300, the time is 300).
+
+=item *
+
+Line B is of type gauge. These are "real" values so they should match
+what we put in: a sort of a wave.
+
+=item *
+
+Line C is derive. It should be a counter that can decrease. It does
+so between 2400 and 0, with 1800 in-between.
+
+=item *
+
+Line D is of type absolute. This is like counter but it works on
+values without calculating the difference. The numbers are the same
+and as you can see (hopefully) this has a different result.
+
+=back
+
+This translates in the following values, starting at 23:10 and ending
+at 00:10 the next day (where U means unknown/unplotted):
+
+ - Line A: u u 1 1 1 1 1 1 1 1 1 u
+ - Line B: u 1 3 5 3 1 2 4 6 4 2 u
+ - Line C: u u 2 2 2 0 -2 -6 -2 0 2 u
+ - Line D: u 1 2 3 4 5 6 7 8 9 10 u
+
+If your GIF shows all this, you know you have typed the data correct,
+the RRDtool executable is working properly, your viewer doesn't fool you
+and you successfully entered the year 2000 :)
+You could try the same example four times, each time with only one of
+the lines.
+
+Let's go over the data again:
+
+=over 2
+
+=item *
+
+Line A: 300,600,900 and so on. The counter delta is a constant 300 and
+so it the time delta. A number divided by itself is always 1 (except
+when dividing by zero which is undefined/illegal).
+Why is it that the first point is unknown ? We do know what we put into
+the database ? True ! But we didn't have a value to calculate the delta
+from so we don't know where we started. It would be wrong to assume we
+started at zero so we don't !
+
+=item *
+
+Line B: There is nothing to calculate. The numbers are as is.
+
+=item *
+
+Line C: Again, the start-out value is unknown. The same story is valid
+like for line A. In this case the deltas are not constant so the line
+is not. If we would put the same numbers in the database as we did for
+line A, we would have gotten the same line. Unlike type counter,
+this type can decrease and I hope to show you later on why
+there is a difference.
+
+=item *
+
+Line D: Here the device calculates the deltas. Therefore we DO know the
+first delta and it is plotted. We had the same input as with line A but
+the meaning of this input is different. Therefore the line is different.
+In this case the deltas increase each time with 300. The time delta
+stays at a constant 300 and therefore the division of the two gives
+increasing results.
+
+=back
+
+=head2 Counter Wraps
+
+There are a few more basics to show. Some important options are still to
+be covered and we haven't look at counter wraps yet. First the counter wrap:
+In our car we notice that our counter shows 999987. We travel 20 KM and
+the counter should go to 1000007. Unfortunately, there are only six digits
+on our counter so it really shows 000007. If we would plot that on a type
+DERIVE, it would mean that the counter was set back 999980 KM. It wasn't,
+and there has to be some protection for this. This protection is only
+available for type COUNTER which should be used for this kind of counter
+anyways. How does it work ? Type counter should never decrease and
+therefore RRDtool must assume it wrapped if it does decrease !
+If the delta is negative, this can be compensated for by adding the
+maximum value of the counter + 1. For our car this would be:
+
+ Delta = 7 - 999987 = -999980 (instead of 1000007-999987=20)
+
+ Real delta = -999980 + 999999 + 1 = 20
+
+At the moment of writing this document, RRDtool knows of counters that
+are either 32 bits or 64 bits of size. These counters can handle the
+following different values:
+
+ - 32 bits: 0 .. 4294967295
+ - 64 bits: 0 .. 18446744073709551615
+
+If these numbers look strange to you, you would like to view them in
+their hexadecimal form:
+
+ - 32 bits: 0 .. FFFFFFFF
+ - 64 bits: 0 .. FFFFFFFFFFFFFFFF
+
+RRDtool handles both counters the same. If an overflow occurs and
+the delta would be negative, RRDtool first adds the maximum of a small
+counter + 1 to the delta. If the delta is still negative, it had to be
+the large counter that wrapped. Add the maximum possible value of the
+large counter + 1 and subtract the falsely added small value.
+There is a risk in this: suppose the large counter wrapped while adding
+a huge delta, it could happen in theory that adding the smaller value
+would make the delta positive. In this unlikely case the results would
+not be correct. The increase should be nearly as high as the maximum
+counter value for that to happen so chances are you would have several
+other problems as well and this particular problem would not even be
+worth thinking about. Even though I did include an example of it so you
+can judge that for yourself.
+
+The next section gives you some numerical examples for counter-wraps.
+Try to do the calculations yourself or just believe me if your calculator
+can't handle the numbers :)
+
+Correction numbers:
+
+ - 32 bits: (4294967295+1) = 4294967296
+ - 64 bits: (18446744073709551615+1)-correction1 = 18446744069414584320
+
+ Before: 4294967200
+ Increase: 100
+ Should become: 4294967300
+ But really is: 4
+ Delta: -4294967196
+ Correction1: -4294967196 +4294967296 = 100
+
+ Before: 18446744073709551000
+ Increase: 800
+ Should become: 18446744073709551800
+ But really is: 184
+ Delta: -18446744073709550816
+ Correction1: -18446744073709550816 +4294967296 = -18446744069414583520
+ Correction2: -18446744069414583520 +18446744069414584320 = 800
+
+ Before: 18446744073709551615 ( maximum value )
+ Increase: 18446744069414584320 ( absurd increase, minimum for
+ Should become: 36893488143124135935 this example to work )
+ But really is: 18446744069414584319
+ Delta: -4294967296
+ Correction1: -4294967296 + 4294967296 = 0
+ (not negative -> no correction2)
+
+ Before: 18446744073709551615 ( maximum value )
+ Increase: 18446744069414584319 ( one less increase )
+ Should become: 36893488143124135934
+ But really is: 18446744069414584318
+ Delta: -4294967297
+ Correction1: -4294967297 +4294967296 = -1
+ Correction2: -1 +18446744069414584320 = 18446744069414584319
+
+As you can see from the last two examples, you need strange numbers
+for RRDtool to fail (provided it's bug free of course) so this should
+not happen. However, SNMP or whatever method you choose to collect the
+data might also fail and it is not uncommon to get wrong numbers
+occasionally. We can't prevent all errors but there are some things we
+could do. RRDtool create takes two special parameters for this. They define
+the minimum and maximum allowed value. Until now, we made them "U"
+for Unknown. You may (not: must) provide values for one or both of them
+and if RRDtool receives values that are outside these limits, it will ignore
+them. For a thermometer in degrees Celsius, the absolute minimum is
+just under -273. For my router, I can assume this minimum is much higher
+so I would say it is 10. The maximum temperature for my router I would
+state as 80. Any higher and the device would be out of order.
+For my car, I would never expect negative numbers and also I would not
+expect numbers to be higher than 230. Anything else, and there must have
+been an error. Remember: the opposite is not true, if the numbers pass
+this check it doesn't mean that they are correct. Always judge the
+graph with a healthy dose of paranoia if it looks weird.
+
+=head2 Data Resampling
+
+One important feature of RRDtool has not been explained yet:
+It is virtually impossible to collect the data and feed it into RRDtool
+on exact intervals. RRDtool therefore interpolates the data so it is on
+exact intervals. If you do not know what this means or how it works,
+then here's the help you seek:
+
+Suppose a counter increases with exactly one for every second. You want
+to measure it in 300 seconds intervals. You should retrieve values
+that are exactly 300 apart. However, due to various circumstances you
+are a few seconds late and the interval is 303. The delta will also be
+303 in that case. Obviously RRDtool should not put 303 in the database
+and make you believe that the counter increased 303 in 300 seconds.
+This is where RRDtool interpolates: it alters the 303 value as if it
+would have been stored earlier and it will be 300 in 300 seconds.
+Next time you are at exactly the right time. This means that the current
+interval is 297 seconds and also the counter increased with 297. Again
+RRDtool alters the value and stores 300 as it should be.
+
+ in the RDD in real
+
+ time+000: 0 delta="U" time+000: 0 delta="U"
+ time+300: 300 delta=300 time+300: 300 delta=300
+ time+600: 600 delta=300 time+603: 603 delta=303
+ time+900: 900 delta=300 time+900: 900 delta=297
+
+Let's create two identical databases. I've chosen the time range 920805000
+to 920805900 as this goes very well with the example numbers.
+
+ rrdtool create seconds1.rrd \
+ --start 920804700 \
+ DS:seconds:COUNTER:600:U:U \
+ RRA:AVERAGE:0.5:1:24
+
+ for Unix: cp seconds1.rrd seconds2.rrd
+ for Dos: copy seconds1.rrd seconds2.rrd
+ for vms: how would I know :)
+
+ rrdtool update seconds1.rrd \
+ 920805000:000 920805300:300 920805600:600 920805900:900
+ rrdtool update seconds2.rrd \
+ 920805000:000 920805300:300 920805603:603 920805900:900
+
+ rrdtool graph seconds1.gif \
+ --start 920804700 --end 920806200 \
+ --height 200 \
+ --upper-limit 1.05 --lower-limit 0.95 --rigid \
+ DEF:seconds=seconds1.rrd:seconds:AVERAGE \
+ CDEF:unknown=seconds,UN \
+ LINE2:seconds#0000FF \
+ AREA:unknown#FF0000
+ rrdtool graph seconds2.gif \
+ --start 920804700 --end 920806200 \
+ --height 200 \
+ --upper-limit 1.05 --lower-limit 0.95 --rigid \
+ DEF:seconds=seconds2.rrd:seconds:AVERAGE \
+ CDEF:unknown=seconds,UN \
+ LINE2:seconds#0000FF \
+ AREA:unknown#FF0000
+
+Both graphs should show the same.
+
+=head1 WRAPUP
+
+It's time to wrap up this document. You now know all the basics to be
+able to work with RRDtool and to read the documentation available.
+There is plenty more to discover about RRDtool and you will find more and
+more uses for the program. You could create easy graphics using just the
+examples provided and using only RRDtool. You could also use the front
+ends that are available.
+
+=head1 MAILINGLIST
+
+Remember to subscribe to the mailing-list. Even if you are not answering
+the mails that come by, it helps both you and the rest. A lot of the stuff
+that I know about MRTG (and therefore about RRDtool) I've learned while
+just reading the list without posting to it. I did not need to ask the
+basic questions as they are answered in the FAQ (so: read that too) and
+in various mails by other users.
+With thousands of users all over the world, there will always be people
+who ask questions that you can answer because you read this and other
+documentation and they didn't.
+
+=head1 SEE ALSO
+
+The RRD Tool manpages
+
+=head1 AUTHOR
+
+I hope you enjoyed the examples and their descriptions. If you do, help
+other people by pointing them to this document when they are asking
+basic questions. They will not only get their answer but at the same
+time learn a whole lot more.
+
+Alex van den Bogaerdt
+<alex at ergens.op.het.net>
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.pod
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.pod (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.pod Sat Jul 13 18:46:12 2002
@@ -0,0 +1,30 @@
+=head1 NAME
+
+rrdtool dump - dump the contents of an B<RRD> in human readable form
+
+=head1 SYNOPSIS
+
+B<rrdtool> B<dump> I<filename> [B<--full>|B<-f>]
+
+=head1 DESCRIPTION
+
+The B<dump> function prints the contents of an B<RRD> in human
+readable form.
+
+=over 8
+
+=item I<filename>
+
+The name of the B<RRD> you want to dump.
+
+=item B<--full>|B<-f>
+
+By default only the headers of the B<RRD> are printed. With this
+option you get the actual data as well.
+
+=back
+
+=head1 AUTHOR
+
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.1
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.1 (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdfetch.1 Sat Jul 13 18:46:13 2002
@@ -0,0 +1,372 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+''' \*(L" and \*(R", except that they are used on ".xx" lines,
+''' such as .IP and .SH, which do another additional levels of
+''' double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH RRDFETCH 1 "19990426.22" "21/Apr/99" "rrdtool"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+rrdtool fetch \- fetch data from an rrd.
+.SH "SYNOPSIS"
+\fBrrdtool\fR \fBfetch\fR \fIfilename\fR \fICF\fR
+[\fB--resolution\fR|\fB\-r\fR\ \fIresolution\fR]
+[\fB--start\fR|\fB\-s\fR\ \fIstart\fR]
+[\fB--end\fR|\fB\-e\fR\ \fIend\fR]
+.SH "DESCRIPTION"
+The \fBfetch\fR function is normally used internally by the graph function,
+to get data from \fBRRD\fRs. \fBfetch\fR will analyze the \fBRRD\fR and
+will try to retrieve the data in the resolution requested.
+The data fetched is printed to stdout. \fI*UNKNOWN*\fR data is often
+represented by the string \*(L"NaN\*(R" depending on your OSs printf
+function.
+.Ip "\fIfilename\fR " 8
+the name of the \fB\s-1RRD\s0\fR you want to fetch the data from.
+.Ip "\fI\s-1CF\s0\fR " 8
+which consolidation function should have been applied to the data you
+want to fetch? (\s-1AVERAGE\s0,\s-1MIN\s0,\s-1MAX\s0,\s-1LAST\s0)
+.Ip "\fB--resolution\fR|\fB\-r\fR \fIresolution\fR (default is the highest resolution)" 8
+what interval should the values have (seconds per value). \fBrrdfetch\fR will try
+to match your request, but it will return data even if no absolute
+match is possible.
+.Ip "\fB--start\fR|\fB\-s\fR \fIstart\fR (default \-24*3600)" 8
+when should the data begin. A time in seconds since epoch (1970-01-01)
+is required. Negative numbers are relative to the end time. By default
+one day worth of data will be fetched. See also \s-1AT\s0\-\s-1STYLE\s0 \s-1TIME\s0 \s-1SPECIFICATION\s0
+section for alternative ways to specify start time.
+.Ip "\fB--end\fR|\fB\-e\fR \fIend\fR (default current time)" 8
+when should the data end. Time in seconds since epoch. See also
+\s-1AT\s0\-\s-1STYLE\s0 \s-1TIME\s0 \s-1SPECIFICATION\s0 section for alternative ways to specify
+end time.
+.Sh "\s-1AT\s0\-\s-1STYLE\s0 \s-1TIME\s0 \s-1SPECIFICATION\s0"
+The rrdtool does also understand at-style time specification.
+The specification is called \*(L"at-style\*(R" after unix command \fIat\fR\|(1)
+that has moderately complex ways to specify time to run your job at.
+The at-style specification consists of two parts: \fB\s-1TIME\s0 \s-1REFERENCE\s0\fR
+specification and \fB\s-1TIME\s0 \s-1OFFSET\s0\fR specification.
+.Sh "\s-1TIME\s0 \s-1REFERENCE\s0 \s-1SPECIFICATION\s0"
+Time reference specification is used, well,... to establish a reference
+moment in time (for time offset to be applied to). When present,
+it should come first, when omitted, it defaults to \fBnow\fR. On its own part,
+time reference consists of \fItime-of-day\fR reference (which should come
+first, if present) and \fIday\fR reference.
+.PP
+\fITime-of-day\fR can be specified as \fB\s-1HH:MM\s0\fR, \fB\s-1HH\s0.\s-1MM\s0\fR, \fB\s-1HHMM\s0\fR,
+or just \fB\s-1HH\s0\fR, you can suffix it with \fBam\fR or \fBpm\fR or use
+24-hours clock. The few special times of day are understood as well,
+these include \fBmidnight\fR (00:00), \fBnoon\fR (12:00) and british
+\fBteatime\fR (16:00).
+.PP
+The \fIday\fR can be specified as \fImonth-name\fR \fIday-of-the-month\fR
+and optional 2- or 4-digit \fIyear\fR number (e.g. March 8 1999).
+Alternatively, you can use \fIday-of-week-name\fR (e.g. Monday),
+or one of the words: \fByesterday\fR, \fBtoday\fR, \fBtomorrow\fR.
+You can also specify \fIday\fR as a full date in several numerical formats;
+these include: \fB\s-1MM/DD\s0/[\s-1YY\s0]\s-1YY\s0\fR, \fB\s-1DD\s0.\s-1MM\s0.[\s-1YY\s0]\s-1YY\s0\fR, \fB\s-1DDMM\s0[\s-1YY\s0]\s-1YY\s0\fR
+(\fI\s-1NOTE1\s0\fR: this is different from the original \fIat\fR\|(1) behavior,
+which interprets a single-number date as \s-1MMDD\s0[\s-1YY\s0]\s-1YY\s0)
+\fI\s-1NOTE2\s0\fR: if you specify \fIday\fR this way, the \fItime-of-day\fR is \s-1REQUIRED\s0
+to be present in front of it.
+.PP
+Finally, you can use words \fBnow\fR, \fBstart\fR, or \fBend\fR as your time
+reference. \fBNow\fR refers to the current moment (and is also a default
+time reference). \fBStart\fR (\fBend\fR) can be used to specify time
+relative to the start (end) time for those tools that use these
+categories (rrdfetch, rrdgraph).
+.PP
+Month and weekday names can be used in their naturally abbreviated form
+(e.g., Dec for December, Sun for Sunday, etc.). The words \fBnow\fR,
+\fBstart\fR, \fBend\fR can be abbreviated to \fBn\fR, \fBs\fR, \fBe\fR.
+.Sh "\s-1TIME\s0 \s-1OFFSET\s0 \s-1SPECIFICATION\s0"
+Time offset specification is used to add (or substract) certain time
+interval to (from) the time reference moment. It consists of \fIsign\fR
+(\fB+\fR\ or\ \fB\-\fR) and \fIamount\fR. The following time units can be used
+to specify the \fIamount\fR: \fByears\fR, \fBmonths\fR, \fBweeks\fR, \fBdays\fR,
+\fBhours\fR, \fBminutes\fR, \fBseconds\fR, these can be used in singular
+or plural form, and abbreviated naturally or to a single letter
+(e.g. +3days, \-1wk, \-3y). Several time units can be combined
+together (e.g., \-5mon1w2d), as well as several time offsets can be
+concatenated (e.g., \-5h45min = \-5h-45min = \-6h+15min = \-7h+1h30m-15min, etc.)
+.PP
+\fI\s-1NOTE3\s0\fR: If you specify time offset in days, weeks, months, or years,
+you will end with the time offset that may vary depending on you time
+reference, because all those time units have no single well defined
+time interval value (1\ year contains either 365 or 366 days, 1\ month
+is 28 to 31 days long, and even 1\ day may be not equal to 24 hours
+twice a year, when \s-1DST\s0\-related clock adjustments take place).
+To cope with this, when you use days, weeks, months, or years
+as your time offset units your time reference date is adjusted
+accordingly without taking too much further effort to ensure anything
+about it (in the hope that \fImktime\fR\|(3) will take care of this later).
+This may lead to some surprising (or even invalid!) results,
+e.g. \*(L'May\ 31\ \-1month\*(R' = \*(L'Apr\ 31\*(R' (meaningless) = \*(L'May\ 1\*(R'
+(after \fImktime\fR\|(3) normalization); in the \s-1EET\s0 timezone
+\&'3:30am Mar 29 1999 \-1 day\*(R' yields \*(L'3:30am Mar 28 1999\*(R' (Sunday)
+which is invalid time/date combination (because of 3am \-> 4am \s-1DST\s0
+forward clock ajustment, see the below example).
+On the other hand, hours, minutes, and seconds are well defined time
+intervals, and these are guaranteed to always produce time offsets
+exactly as specified (e.g. for \s-1EET\s0 timezone, \*(L'8:00\ Mar\ 27\ 1999\ +2\ days\*(R' =
+\&'8:00\ Mar\ 29\ 1999\*(R', but since there is 1-hour \s-1DST\s0 forward clock adjustment
+takes place around 3:00\ Mar\ 28\ 1999, the actual time interval between
+8:00\ Mar\ 27\ 1999 and 8:00\ Mar\ 29\ 1999 equals 47 hours; on the other hand,
+\&'8:00\ Mar\ 27\ 1999\ +48\ hours\*(R' = \*(L'9:00\ Mar\ 29\ 1999\*(R', as expected)
+.PP
+\fI\s-1NOTE4\s0\fR: The single-letter abbreviation for both \fBmonths\fR and \fBminutes\fR
+is \fBm\fR. To disambiguiate, the parser tries to read your mind\ :)
+by applying the following two heuristics:
+.Ip "1" 3
+If \fBm\fR is used in context of (i.e. right after the) years,
+months, weeks, or days it is assumed to mean \fBmonths\fR, while
+in the context of hours, minutes, and seconds it means minutes.
+(e.g., in \-1y6m or +3w1m \fBm\fR means \fBmonths\fR, while in
+\-3h20m or +5s2m \fBm\fR means \fBminutes\fR)
+.Ip "2" 3
+Out of context (i.e. right after the \fB+\fR or \fB\-\fR sign) the
+meaning of \fBm\fR is guessed from the number it directly follows.
+Currently, if the number absolute value is below 25 it is assumed
+that \fBm\fR means \fBmonths\fR, otherwise it is treated as \fBminutes\fR.
+(e.g., \-25m == \-25 minutes, while +24m == +24 months)
+.PP
+\fIFinal \s-1NOTES\s0\fR: Time specification is case-insensitive.
+Whitespace can be inserted freely or omitted altogether,
+there are, however, cases when whitespace is required
+(e.g., \*(L'midnight\ Thu'). In this case you should either quote the
+whole phrase to prevent it from bieng taken apart by your shell or use
+\&'_\*(R' (underscore) or \*(L',\*(R' (comma) which also count as whitespace
+(e.g., midnight_Thu or midnight,Thu)
+.Sh "\s-1TIME\s0 \s-1SPECIFICATION\s0 \s-1EXAMPLES\s0"
+\fIOct 12\fR -- October 12 this year
+.PP
+\fI\-1month\fR or \fI\-1m\fR -- current time of day, only a month before
+(may yield surprises, see the \s-1NOTE3\s0 above)
+.PP
+\fInoon yesterday \-3hours\fR -- yesterday morning; can be put also as \fI9am-1day\fR
+.PP
+\fI23:59 31.12.1999\fR -- 1 minute to the year 2000
+.PP
+\fI12am 010101\fR -- start of the new millenium
+.PP
+\fIend-3weeks\fR or \fIe-3w\fR -- 3 weeks before end time
+(may be used as start time specification)
+.PP
+\fIstart+6hours\fR or \fIs+6h\fR -- 6 hours after start time
+(may be used as end time specification)
+.SH "AUTHOR"
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
+.rn }` ''
+.IX Title "RRDFETCH 1"
+.IX Name "rrdtool fetch - fetch data from an rrd."
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Item "\fIfilename\fR "
+
+.IX Item "\fI\s-1CF\s0\fR "
+
+.IX Item "\fB--resolution\fR|\fB\-r\fR \fIresolution\fR (default is the highest resolution)"
+
+.IX Item "\fB--start\fR|\fB\-s\fR \fIstart\fR (default \-24*3600)"
+
+.IX Item "\fB--end\fR|\fB\-e\fR \fIend\fR (default current time)"
+
+.IX Subsection "\s-1AT\s0\-\s-1STYLE\s0 \s-1TIME\s0 \s-1SPECIFICATION\s0"
+
+.IX Subsection "\s-1TIME\s0 \s-1REFERENCE\s0 \s-1SPECIFICATION\s0"
+
+.IX Subsection "\s-1TIME\s0 \s-1OFFSET\s0 \s-1SPECIFICATION\s0"
+
+.IX Item "1"
+
+.IX Item "2"
+
+.IX Subsection "\s-1TIME\s0 \s-1SPECIFICATION\s0 \s-1EXAMPLES\s0"
+
+.IX Header "AUTHOR"
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.txt
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.txt (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.txt Sat Jul 13 18:46:13 2002
@@ -0,0 +1,264 @@
+
+
+
+RRDTOOL(1) rrdtool RRDTOOL(1)
+
+
+NNNNAAAAMMMMEEEE
+ rrdtool - round robin database tool
+
+SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
+ rrrrrrrrddddttttoooooooollll ---- | _f_u_n_c_t_i_o_n
+
+DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
+ OOOOVVVVEEEERRRRVVVVIIIIEEEEWWWW
+
+ It is pretty easy to gather status information from all
+ sorts of things, ranging from the temperature in your
+ office to the number of octets which have passed through
+ the FDDI interface of your router. But it is not so
+ trivial to store this data in a efficient and systematic
+ manner. This is where rrrrrrrrddddttttoooooooollll kicks in. It lets you _l_o_g
+ _a_n_d _a_n_a_l_y_z_e the data you gather from all kinds of data-
+ sources (DDDDSSSS). The data analysis part of rrdtool is based
+ on the ability to quickly generate graphical
+ representations of the data values collected over a
+ definable time period.
+
+ In this man page you will find general information on the
+ design and functionality of the Round Robin Database Tool
+ (rrdtool). For a more detailed description of how to use
+ the individual functions of the rrrrrrrrddddttttoooooooollll check the
+ corresponding man page.
+
+ FFFFUUUUNNNNCCCCTTTTIIIIOOOONNNNSSSS
+
+ While the man pages talk of command line switches you have
+ to set in order to make rrrrrrrrddddttttoooooooollll work it is important to
+ note that the rrrrrrrrddddttttoooooooollll can be 'remote controlled' through a
+ set of pipes. This saves a considerable amount of startup
+ time when you plan to make rrrrrrrrddddttttoooooooollll do a lot of things
+ quickly. Check the section on the section on _R_e_m_o_t_e
+ _C_o_n_t_r_o_l further down.
+
+ ccccrrrreeeeaaaatttteeee Set up a new Round Robin Database (RRD). Check
+ rrdcreate
+
+ uuuuppppddddaaaatttteeee Store new data values into an RRD. Check rrdupdate
+
+ ggggrrrraaaapppphhhh Create a graph from data stored in one or several
+ RRD. Apart from generating graphs, data can also
+ be extracted to stdout. Check rrdgraph
+
+ dddduuuummmmpppp Dump the contents of an RRD in plain ASCII. This
+ is manly used for debugging. Check rrddump
+
+ ffffeeeettttcccchhhh Get data for a certain time period from a RRD. The
+ graph function uses fetch to retrieve its data
+ from an rrd. Check rrdfetch
+
+
+
+
+
+12/Feb/99 19990426.22 1
+
+
+
+
+
+RRDTOOL(1) rrdtool RRDTOOL(1)
+
+
+ ttttuuuunnnneeee Alter setup of an RRD
+
+ llllaaaasssstttt Find last update time of an RRD
+
+ HHHHOOOOWWWW DDDDOOOOEEEESSSS RRRRRRRRDDDDTTTTOOOOOOOOLLLL WWWWOOOORRRRKKKK????
+
+
+ Data acquisition
+ When monitoring the state of a system, it is
+ convenient to have the data available at a
+ constant interval. Unfortunately you may not
+ always be able to fetch data at exactly the time
+ you want to. Therefore rrrrrrrrddddttttoooooooollll lets you update the
+ logfile at any time you want. It will
+ automatically interpolate the value of the data-
+ source (DDDDSSSS) at the latest official time-slot and
+ write this value to the log. The value you have
+ supplied is stored as well and is also taken into
+ account when interpolating the next log entry.
+
+ Consolidation
+ You may log data at a 1 minute interval, but you
+ are also be interested to know the development of
+ the data over the last year. You could do this by
+ simply storing the data in 1 minute interval, for
+ one year. While this would take considerable disk
+ space it would also take a lot of time to analyze
+ the data when you wanted to create a graph
+ covering the whole year. rrrrrrrrddddttttoooooooollll offers a solution
+ to this of this problem through its data
+ consolidation feature. When setting up an Round
+ Robin Database (RRRRRRRRDDDD), you can define at which
+ interval this consolidation should occur, and what
+ consolidation function (CCCCFFFF) (average, minimum,
+ maximum, total, last) should be used to build the
+ consolidated values (see rrdcreate). You can
+ define any number of different consolidation
+ setups within one RRRRRRRRDDDD. They will all be maintained
+ on the fly when new data is loaded into the RRRRRRRRDDDD.
+
+ Round Robin Archives
+ Data values of the same consolidation setup are
+ stored into Round Robin Archives (RRRRRRRRAAAA). This is a
+ very efficient manner to store data for a certain
+ amount of time, while using a known amount of
+ storage space.
+
+ It works like this: If you want to store 1000
+ values in 5 minute interval, rrrrrrrrddddttttoooooooollll will allocate
+ space for 1000 data values and a header area. In
+ the header it will store a pointer telling which
+ one of the values in the storage area was last
+ written to. New values are written to the Round
+ Robin Archive in a ... you guess it ... round
+
+
+
+12/Feb/99 19990426.22 2
+
+
+
+
+
+RRDTOOL(1) rrdtool RRDTOOL(1)
+
+
+ robin manner. This automatically limits the
+ history to the last 1000 values. Because you can
+ define several RRRRRRRRAAAAs within a single RRRRRRRRDDDD, you can
+ setup another one, storing 750 data values at a 2
+ hour interval and thus keeping a log for the last
+ two months although at a lower resolution.
+
+ The use of RRRRRRRRAAAAs guarantees that the RRRRRRRRDDDD does not
+ grow over time and that old data is automatically
+ eliminated. By using the consolidation feature,
+ you can still keep data for a very long time,
+ while gradually reducing the resolution of the
+ data along the time axis. Using different
+ consolidation functions (CCCCFFFF) allows you to store
+ exactly the type of information that actually
+ interests you. (Maximum one minute traffic on the
+ LAN, minimum temperature of the wine cellar, total
+ minutes down time ...)
+
+ Unknown Data
+ As mentioned earlier, the RRRRRRRRDDDD stores data at a
+ constant interval. Now it may happen that no new
+ data is available when a value has to be written
+ to the RRRRRRRRDDDD. Data acquisition may not be possible
+ for one reason or an other. The rrrrrrrrddddttttoooooooollll handles
+ these situations by storing an _*_U_N_K_N_O_W_N_* value
+ into the database. The value '_*_U_N_K_N_O_W_N_*' is
+ supported through all the functions of the
+ database. When consolidating the amount of
+ _*_U_N_K_N_O_W_N_* data is accumulated and when a new
+ consolidated value is ready to be written to its
+ Round Robin Archive (RRRRRRRRAAAA) a validity check is
+ performed to make sure that the percentage of
+ unknown data in the new value is below a
+ configurable level. If so, an _*_U_N_K_N_O_W_N_* value will
+ be written to the RRRRRRRRAAAA.
+
+ Graphing
+ The rrrrrrrrddddttttoooooooollll also allows one to generate reports in
+ numerical and graphical form based on the data
+ stored in one or several RRRRRRRRDDDDs. The graphing
+ feature is fully configurable. Size, color and
+ contents of the graph can be defined freely. Check
+ rrdgraph for more information on this.
+
+ RRRREEEEMMMMOOOOTTTTEEEE CCCCOOOONNNNTTTTRRRROOOOLLLL
+
+ When you start rrrrrrrrddddttttoooooooollll with the command line option '----',
+ it waits for input via standard in. With this feature you
+ can improve performance by attaching rrrrrrrrddddttttoooooooollll to another
+ process (mrtg is one example) through a set of pipes. Over
+ the pipes rrrrrrrrddddttttoooooooollll accepts the same arguments as on the
+ command line. When a command is completed, rrdtool will
+ print the string 'OK', followed by timing information of
+
+
+
+12/Feb/99 19990426.22 3
+
+
+
+
+
+RRDTOOL(1) rrdtool RRDTOOL(1)
+
+
+ the form uuuu::::_u_s_e_r_t_i_m_e ssss::::_s_y_s_t_e_m_t_i_m_e both values are running
+ totals of seconds since rrdtool was started. If an error
+ occurs, a line of the form 'ERROR: _D_e_s_c_r_i_p_t_i_o_n _o_f _e_r_r_o_r'
+ will be printed. rrrrrrrrddddttttoooooooollll will not abort if possible, but
+ follow the ERROR line with an OK line.
+
+SSSSEEEEEEEE AAAALLLLSSSSOOOO
+ rrdcreate, rrdupdate, rrdgraph, rrddump, rrdfetch,
+ rrdtune, rrdlast
+
+BBBBUUUUGGGGSSSS
+ There must be plenty ... this is alpha code ;-) ...
+
+AAAAUUUUTTTTHHHHOOOORRRR
+ Tobias Oetiker <oetiker at ee.ethz.ch>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12/Feb/99 19990426.22 4
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.pod
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.pod (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtool.pod Sat Jul 13 18:46:13 2002
@@ -0,0 +1,179 @@
+=head1 NAME
+
+rrdtool - round robin database tool
+
+=head1 SYNOPSIS
+
+B<rrdtool> B<-> | I<function>
+
+=head1 DESCRIPTION
+
+=head2 OVERVIEW
+
+It is pretty easy to gather status information from all sorts of
+things, ranging from the temperature in your office to the number of
+octets which have passed through the FDDI interface of your
+router. But it is not so trivial to store this data in a efficient and
+systematic manner. This is where B<rrdtool> kicks in. It lets you
+I<log and analyze> the data you gather from all kinds of data-sources
+(B<DS>). The data analysis part of rrdtool is based on the ability to
+quickly generate graphical representations of the data values
+collected over a definable time period.
+
+In this man page you will find general information on the design and
+functionality of the Round Robin Database Tool (rrdtool). For a more
+detailed description of how to use the individual functions of the
+B<rrdtool> check the corresponding man page.
+
+=head2 FUNCTIONS
+
+While the man pages talk of command line switches you have to set in order to
+make B<rrdtool> work it is important to note that the B<rrdtool> can be
+'remote controlled' through a set of pipes. This saves a considerable
+amount of startup time when you plan to make B<rrdtool> do a lot of
+things quickly. Check the section on L<"Remote Control"> further down.
+
+=over 8
+
+=item B<create>
+
+Set up a new Round Robin Database (RRD). Check rrdcreate
+
+=item B<update>
+
+Store new data values into an RRD. Check rrdupdate
+
+=item B<graph>
+
+Create a graph from data stored in one or several RRD. Apart from
+generating graphs, data can also be extracted to stdout. Check rrdgraph
+
+=item B<dump>
+
+Dump the contents of an RRD in plain ASCII. This is manly used for
+debugging. Check rrddump
+
+=item B<fetch>
+
+Get data for a certain time period from a RRD. The graph function
+uses fetch to retrieve its data from an rrd. Check rrdfetch
+
+=item B<tune>
+
+Alter setup of an RRD
+
+=item B<last>
+
+Find last update time of an RRD
+
+=back
+
+=head2 HOW DOES RRDTOOL WORK?
+
+=over 8
+
+=item Data acquisition
+
+When monitoring the state of a system, it is convenient to have the
+data available at a constant interval. Unfortunately you may not
+always be able to fetch data at exactly the time you want
+to. Therefore B<rrdtool> lets you update the logfile at any time you
+want. It will automatically interpolate the value of the data-source
+(B<DS>) at the latest official time-slot and write this value to the
+log. The value you have supplied is stored as well and is also taken
+into account when interpolating the next log entry.
+
+=item Consolidation
+
+You may log data at a 1 minute interval, but you are also be
+interested to know the development of the data over the last year. You
+could do this by simply storing the data in 1 minute interval, for one
+year. While this would take considerable disk space it would also take
+a lot of time to analyze the data when you wanted to create a graph
+covering the whole year. B<rrdtool> offers a solution to this of this
+problem through its data consolidation feature. When setting up
+an Round Robin Database (B<RRD>), you can define at which interval
+this consolidation should occur, and what consolidation function
+(B<CF>) (average, minimum, maximum, total, last) should be used to
+build the consolidated values (see rrdcreate). You can define any
+number of different consolidation setups within one B<RRD>. They will
+all be maintained on the fly when new data is loaded into the B<RRD>.
+
+=item Round Robin Archives
+
+Data values of the same consolidation setup are stored into Round
+Robin Archives (B<RRA>). This is a very efficient manner to store data
+for a certain amount of time, while using a known amount of storage
+space.
+
+It works like this: If you want to store 1000 values in 5 minute
+interval, B<rrdtool> will allocate space for 1000 data values and a
+header area. In the header it will store a pointer telling
+which one of the values in the storage area was last written to. New
+values are written to the Round Robin Archive in a ... you guess it
+... round robin manner. This automatically limits the history to the last
+1000 values. Because you can define several B<RRA>s within a single B<RRD>,
+you can setup another one, storing 750 data values at a 2 hour interval
+and thus keeping a log for the last two months although at a lower
+resolution.
+
+The use of B<RRA>s guarantees that the B<RRD> does not grow over
+time and that old data is automatically eliminated. By using the
+consolidation feature, you can still keep data for a very long time,
+while gradually reducing the resolution of the data along the time
+axis. Using different consolidation functions (B<CF>) allows you to
+store exactly the type of information that actually interests
+you. (Maximum one minute traffic on the LAN, minimum temperature of
+the wine cellar, total minutes down time ...)
+
+=item Unknown Data
+
+As mentioned earlier, the B<RRD> stores data at a constant
+interval. Now it may happen that no new data is available when a
+value has to be written to the B<RRD>. Data acquisition may not be
+possible for one reason or an other. The B<rrdtool> handles these
+situations by storing an I<*UNKNOWN*> value into the database. The
+value 'I<*UNKNOWN*>' is supported through all the functions of the
+database. When consolidating the amount of I<*UNKNOWN*> data is
+accumulated and when a new consolidated value is ready to be written
+to its Round Robin Archive (B<RRA>) a validity check is performed to
+make sure that the percentage of unknown data in the new value is
+below a configurable level. If so, an I<*UNKNOWN*> value will be
+written to the B<RRA>.
+
+=item Graphing
+
+The B<rrdtool> also allows one to generate reports in numerical and
+graphical form based on the data stored in one or several
+B<RRD>s. The graphing feature is fully configurable. Size, color and
+contents of the graph can be defined freely. Check rrdgraph
+for more information on this.
+
+=back
+
+=head2 REMOTE CONTROL
+
+When you start B<rrdtool> with the command line option 'B<->', it waits
+for input via standard in. With this feature you can improve
+performance by attaching B<rrdtool> to another process (mrtg is one
+example) through a set of pipes. Over the pipes B<rrdtool> accepts the
+same arguments as on the command line. When a command is completed,
+rrdtool will print the string 'C<OK>', followed by timing information of
+the form B<u:>I<usertime> B<s:>I<systemtime> both values are running
+totals of seconds since rrdtool was started. If an error occurs, a line
+of the form 'C<ERROR:> I<Description of error>' will be printed. B<rrdtool>
+will not abort if possible, but follow the ERROR line with an OK line.
+
+
+=head1 SEE ALSO
+
+rrdcreate, rrdupdate, rrdgraph, rrddump, rrdfetch, rrdtune, rrdlast
+
+=head1 BUGS
+
+There must be plenty ... this is alpha code ;-) ...
+
+=head1 AUTHOR
+
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDp.3
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDp.3 (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDp.3 Sat Jul 13 18:46:13 2002
@@ -0,0 +1,283 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+''' \*(L" and \*(R", except that they are used on ".xx" lines,
+''' such as .IP and .SH, which do another additional levels of
+''' double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH RRDp 3 "19990512.01" "12/May/99" "rrdtool"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+RRDp \- Attach rrdtool from within a perl script via a set of pipes;
+.SH "SYNOPSIS"
+use \fBRRDp\fR
+.PP
+\fBRRDp::start\fR \fIpath to rrdtool executable\fR
+.PP
+\fBRRDp::cmd\fR \fIrrdtool commandline\fR
+.PP
+$answer = \fBRRD::read\fR
+.PP
+$status = \fBRRD::end\fR
+.PP
+\fB$RRDp::user\fR, \fB$RRDp::sys\fR, \fB$RRDp::real\fR
+.SH "DESCRIPTION"
+With this module you can safely communicate with the rrdtool.
+.PP
+After every \fBRRDp::cmd\fR you have to issue an \fBRRDp::read\fR command to get
+\fBrrdtool\fRs answer to your command. The answer is returned as a pointer,
+in order to speed things up. If the last command did not return any
+data, \fBRRDp::read\fR will return an undefined variable.
+.PP
+If you import the PERFORMANCE variables into your namespace,
+you can access rrdtools internal performance measurements.
+.Ip "use \fBRRDp\fR" 8
+Load the RRDp::pipe module.
+.Ip "\fBRRDp::start\fR \fIpath to rrdtool executable\fR" 8
+start rrdtool. The argument must be the path to the rrdtool executable
+.Ip "\fBRRDp::cmd\fR \fIrrdtool commandline\fR" 8
+pass commands on to rrdtool. check the rrdtool documentation for
+more info on the rrdtool commands.
+.Ip "$answer = \fBRRDp::read\fR" 8
+read rrdtools response to your command. Note that the \f(CW$answer\fR variable will
+only contain a pointer to the returned data. The reason for this is, that
+rrdtool can potentially return quite excessive amounts of data
+and we don't want to copy this around in memory. So when you want to
+access the contents of \f(CW$answer\fR you have to use $$answer which dereferences
+the variable.
+.Ip "$status = \fBRRDp::end\fR" 8
+terminates rrdtool and returns rrdtools status ...
+.Ip "\fB$RRDp::user\fR, \fB$RRDp::sys\fR, \fB$RRDp::real\fR" 8
+these variables will contain totals of the user time, system time and
+real time as seen by rrdtool. User time is the time rrdtool is
+running, System time is the time spend in system calls and real time
+is the total time rrdtool has been running.
+.Sp
+The difference between user + system and real is the time spent
+waiting for things like the hard disk and new input from the perl
+script.
+.SH "EXAMPLE"
+.PP
+.Vb 8
+\& use RRDp;
+\& RRDp::start "/usr/local/bin/rrdtool";
+\& RRDp::cmd qw(create demo.rrd --step 100
+\& DS:in:GAUGE:100:U:U
+\& RRA:AVERAGE:0.5:1:10);
+\& $answer = RRDp::read;
+\& print $$answer;
+\& ($usertime,$systemtime,$realtime) = ($RRDp::user,$RRDp::sys,$RRDp::real);
+.Ve
+.SH "SEE ALSO"
+For more information on how to use rrdtool, check the manpages.
+.SH "AUTHOR"
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
+.rn }` ''
+.IX Title "RRDp 3"
+.IX Name "RRDp - Attach rrdtool from within a perl script via a set of pipes;"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Item "use \fBRRDp\fR"
+
+.IX Item "\fBRRDp::start\fR \fIpath to rrdtool executable\fR"
+
+.IX Item "\fBRRDp::cmd\fR \fIrrdtool commandline\fR"
+
+.IX Item "$answer = \fBRRDp::read\fR"
+
+.IX Item "$status = \fBRRDp::end\fR"
+
+.IX Item "\fB$RRDp::user\fR, \fB$RRDp::sys\fR, \fB$RRDp::real\fR"
+
+.IX Header "EXAMPLE"
+
+.IX Header "SEE ALSO"
+
+.IX Header "AUTHOR"
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.txt
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.txt (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.txt Sat Jul 13 18:46:13 2002
@@ -0,0 +1,132 @@
+
+
+
+RRDUPDATE(1) rrdtool RRDUPDATE(1)
+
+
+NNNNAAAAMMMMEEEE
+ rrdtool update - Store a new set of values into the rrd
+
+SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
+ rrrrrrrrddddttttoooooooollll uuuuppppddddaaaatttteeee _f_i_l_e_n_a_m_e [--------tttteeeemmmmppppllllaaaatttteeee|----tttt _d_s_-_n_a_m_e[::::_d_s_-
+ _n_a_m_e]...] NNNN|_t_i_m_e_s_t_a_m_p::::_v_a_l_u_e[::::_v_a_l_u_e...]
+ [_t_i_m_e_s_t_a_m_p::::_v_a_l_u_e[::::_v_a_l_u_e...] ...]
+
+DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
+ The uuuuppppddddaaaatttteeee function feeds new data values into an RRRRRRRRDDDD. The
+ data gets time aligned according to the properties of the
+ RRRRRRRRDDDD to which the data is written.
+
+ _f_i_l_e_n_a_m_e
+ The name of the RRRRRRRRDDDD you want to update.
+
+ --------tttteeeemmmmppppllllaaaatttteeee|----tttt _d_s_-_n_a_m_e[::::_d_s_-_n_a_m_e]...
+ by default, the update function expects the data
+ input in the order, the data sources are defined
+ in the RRD. This is not very error resistant, as
+ you might be sending the wrong data into a RRD.
+
+ The template switch alows you to specify which
+ data sources you are going to update and in which
+ order. If the datasources specified in the
+ template are not available in the rrd file, the
+ update process will abort with an error message.
+
+ NNNN|_t_i_m_e_s_t_a_m_p::::_v_a_l_u_e[::::_v_a_l_u_e...]
+ The data used for updating the RRD was acquired at
+ a certain time. This time can either be defined in
+ seconds since 1970-01-01. Or by using the letter
+ 'N' the update time is set to be the current time.
+ Negative time values are subtracted from the
+ current time. Getting the timing right to the
+ second is especially important when you are
+ working with data-sources of type CCCCOOOOUUUUNNNNTTTTEEEERRRR, DDDDEEEERRRRIIIIVVVVEEEE
+ or AAAABBBBSSSSOOOOLLLLUUUUTTTTEEEE.
+
+ The remaining elements of the argument are DS
+ updates. The order of this list is the same as the
+ order the datasources were defined in the rra. If
+ there is no data for a certain data-source, the
+ letter UUUU (eg. N:0.1:U:1) can be defined.
+
+ The format of the value acquired from the
+ datasource is dependent of the datasource type
+ chosen. Normally it will be numeric, but the data
+ acquisition modules my impose their very own
+ parsing of this parameter as long as the colon (::::)
+ remains the datasource value separator.
+
+EEEEXXXXAAAAMMMMPPPPLLLLEEEE
+ rrdtool update demo1.rrd N:3.44:3.15:U:23
+
+
+
+7/Mar/99 19990426.22 1
+
+
+
+
+
+RRDUPDATE(1) rrdtool RRDUPDATE(1)
+
+
+ Update the database file demo1.rrd with 3 known and one
+ _*_U_N_K_N_O_W_N_* value. Use the current time as the update time.
+
+ rrdtool update demo2.rrd 887457267:U 887457521:22
+ 88745790:2.7
+
+ Update the database file demo2.rrd which expects data from
+ a single data-source, three times. First with an _*_U_N_K_N_O_W_N_*
+ value then with two normal readings. The update interval
+ seems to be around 300 seconds.
+
+AAAAUUUUTTTTHHHHOOOORRRR
+ Tobias Oetiker <oetiker at ee.ethz.ch>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7/Mar/99 19990426.22 2
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.1
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.1 (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdgraph.1 Sat Jul 13 18:46:14 2002
@@ -0,0 +1,526 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+''' \*(L" and \*(R", except that they are used on ".xx" lines,
+''' such as .IP and .SH, which do another additional levels of
+''' double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH RRDGRAPH 1 "19990504.23" "4/May/99" "rrdtool"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+rrdtool graph \- Create a graph based on data from one or several RRD
+.SH "SYNOPSIS"
+\fBrrdtool\fR \fBgraph\fR \fIfilename\fR
+[\fB\-s\fR|\fB--start\fR\ \fIseconds\fR]
+[\fB\-e\fR|\fB--end\fR\ \fIseconds\fR]
+[\fB\-x\fR|\fB--x-grid\fR\ \fIx-axis\ grid\ and\ label\fR]
+[\fB\-y\fR|\fB--y-grid\fR\ \fIy-axis\ grid\ and\ label\fR]
+[\fB\-v\fR|\fB--vertical-label\fR\ \fItext\fR]
+[\fB\-w\fR|\fB--width\fR\ \fIpixels\fR]
+[\fB\-h\fR|\fB--height\fR\ \fIpixels\fR]
+[\fB\-i\fR|\fB--interlaced\fR]
+[\fB\-o\fR|\fB--logarithmic\fR]
+[\fB\-u\fR|\fB--upper-limit\fR\ \fIvalue\fR]
+[\fB\-l\fR|\fB--lower-limit\fR\ \fIvalue\fR]
+[\fB\-r\fR|\fB--rigid\fR]
+[\fB\-b\fR|\fB--base\fR\ \fIvalue\fR]
+[\fB\-c\fR|\fB--color\fR\ \fICOLORTAG\fR\fB#\fR\fIrrggbb\fR]
+[\fB\-t\fR|\fB--title\fR\ \fItitle\fR]
+[\fBDEF:\fR\fIvname\fR\fB=\fR\fIrrd\fR\fB:\fR\fIds-name\fR\fB:\fR\fICF\fR]
+[\fBCDEF:\fR\fIvname\fR\fB=\fR\fIrpn-expression\fR]
+[\fBPRINT:\fR\fIvname\fR\fB:\fR\fICF\fR\fB:\fR\fIformat\fR]
+[\fBGPRINT:\fR\fIvname\fR\fB:\fR\fICF\fR\fB:\fR\fIformat\fR]
+[\fBCOMMENT:\fR\fItext\fR]
+[\fBHRULE:\fR\fIvalue\fR\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]]
+[\fBVRULE:\fR\fItime\fR\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]]
+[\fBLINE\fR{\fB1\fR|\fB2\fR|\fB3\fR}\fB:\fR\fIvname\fR[\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]]]
+[\fBAREA:\fR\fIvname\fR[\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]]]
+[\fBSTACK:\fR\fIvname\fR[\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]]]
+.SH "DESCRIPTION"
+The \fBgraph\fR functions main purpose is to create graphical
+representations of the data stored in one or several \fBRRD\fRs. Apart
+from generating graphs, it can also extract numerical reports.
+.Ip "\fIfilename\fR " 8
+The name of the graph to generate. Since \fBrrdtool\fR outputs
+\s-1GIF\s0's, it's recommended that the filename end in \fI.gif\fR.
+\fBrrdtool\fR does not enforce this, however. If the \fIfilename\fR
+is et to \*(L'\-\*(R' the gif file will be written to standard out. All
+other output will get supressd.
+.Sp
+If no graph functions are called, the graph will not be created.
+.Ip "\fB\-s\fR|\fB--start\fR \fIseconds\fR (default \-24*3600)" 8
+The time when the graph should begin. Time in seconds since
+epoch (1970-01-01) is required. Negative numbers are relative to the
+end time. By default one day worth of data will be graphed.
+See also \s-1AT\s0\-\s-1STYLE\s0 \s-1TIME\s0 \s-1SPECIFICATION\s0 section in the \fIrrdfetch\fR
+documentation for alternative ways to specify start time.
+.Ip "\fB\-e\fR|\fB--end\fR \fIseconds\fR (default current time)" 8
+The time when the graph should end. Time in seconds since epoch.
+See also \s-1AT\s0\-\s-1STYLE\s0 \s-1TIME\s0 \s-1SPECIFICATION\s0 section in the \fIrrdfetch\fR
+documentation for alternative ways to specify end time.
+.Ip "\fB\-x\fR|\fB--x-grid\fR \fIx-axis grid and label\fR (default autoconfigure)" 8
+The x-axis label is quite complex to configure. So if you don't have
+very special needs, you can relay on the autoconfiguration to get this
+right.
+.Sp
+The x-axis label is configured, using the following format:
+.Sp
+\fI\s-1GTM\s0\fR\fB:\fR\fI\s-1GST\s0\fR\fB:\fR\fI\s-1MTM\s0\fR\fB:\fR\fI\s-1MST\s0\fR\fB:\fR\fI\s-1LTM\s0\fR:\fI\s-1LST\s0\fR\fB:\fR\fI\s-1LPR\s0\fR\fB:\fR\fI\s-1LFM\s0\fR
+.Sp
+You have to configure three elements making up the x-axis labels and
+grid. The base grid (\fIG??\fR), the major grid (\fIM??\fR) and the labels
+(\fIL??\fR). The configuration is based on the idea that you first
+specify a well known amount of time (\fI?\s-1TM\s0\fR) and then say how many
+times it has to pass between each grid line or label (\fI?\s-1ST\s0\fR). For the
+label you have to define two additional items: The precision of the
+label in seconds (\fI\s-1LPR\s0\fR) and the strftime format used to generate the
+text of the label (\fI\s-1LFM\s0\fR).
+.Sp
+The \fI?\s-1TM\s0\fR elements must be one of the following keywords: \fB\s-1SECOND\s0\fR,
+\fB\s-1MINUTE\s0\fR, \fB\s-1HOUR\s0\fR, \fB\s-1DAY\s0\fR, \fB\s-1WEEK\s0\fR, \fB\s-1MONTH\s0\fR or \fB\s-1YEAR\s0\fR.
+.Sp
+If you wanted a graph with a base grid every 10 minutes and a major
+one every hour, with labels every hour you would use the following
+x-axis definition.
+.Sp
+\f(CWMINUTE:10:HOUR:1:HOUR:1:0:%X\fR
+.Sp
+The precision in this example is 0 because the \f(CW%X\fR format is exact. If
+the label was the name of the day, we would have had a precision of 24
+hours, because when you say something like \*(L'Monday\*(R' you mean the whole
+day and not Monday morning 00:00. Thus the label should be positioned
+at noon. By defining a precision of 24 hours or rather 86400 seconds,
+you make sure that this happens.
+.Ip "\fB\-y\fR\fB--y-grid\fR \fIgrid step\fR:\fIlabel factor\fR (default autoconfigure)" 8
+Makes vertical grid lines appear at \fIgrid step\fR interval. Every
+\fIlabel factor\fR gridstep, a major grid line is printed, along with
+label showing the value of the grid line.
+.Ip "\fB\-v\fR|\fB--vertical-label\fR \fItext\fR" 8
+vertical label on the left side of the graph. This is normally used to
+specify the units used.
+.Ip "\fB\-w\fR|\fB--width\fR \fIpixels\fR (default 400 pixel)" 8
+Width of the drawing area within the graph. This affects the size of the
+gif.
+.Ip "\fB\-h\fR|\fB--height\fR \fIpixels\fR (default 100 pixel)" 8
+Width of the drawing area within the graph. This affects the size of the
+gif.
+.Ip "\fB\-i\fR|\fB--interlaced\fR (default: false)" 8
+If you set this option, then the resulting \s-1GIF\s0 will be interlaced.
+Most web browsers display these incrementally as they load. If
+you do not use this option, the GIFs default to being progressive
+scanned. The only effect of this option is to control the format
+of the \s-1GIF\s0 on disk. It makes no changes to the layout or contents
+of the graph.
+.Ip "\fB\-u\fR|\fB--upper-limit\fR \fIvalue\fR (default autoconfigure)" 8
+The maximum value to be graphed. By default This will be
+autoconfigured from the data you select with the graphing functions.
+.Ip "\fB\-l\fR|\fB--lower-limit\fR \fIvalue\fR (default autoconfigure)" 8
+The minimum value to be graphed. By default This will be
+autoconfigured from the data you select with the graphing functions.
+.Ip "\fB\-r\fR|\fB--rigid\fR" 8
+rigid boundaries mode. Normally rrdgraph will automatically expand the
+lower and upper limit if the graph contains a value outside the valid
+range. With the r option you can disable this behavior
+.Ip "\fB\-b\fR|\fB--base\fR \fIvalue\fR" 8
+if you are graphing memmory (and \s-1NOT\s0 network traffic) this switch
+should be set to 1024 so that one Kb is 1024 byte. For traffic
+measurement, 1 kb/s is 1000 b/s.
+.Ip "\fB\-o\fR|\fB--logarithmic\fR" 8
+logarithmic y-axis scaling
+.Ip "\fB\-c\fR|\fB--color\fR \fI\s-1COLORTAG\s0\fR\fB#\fR\fIrrggbb\fR (default colors)" 8
+override the colors for the standard elements of the graph. The \fI\s-1COLORTAG\s0\fR
+must be one of the following symbolic names: \fB\s-1BACK\s0\fR ground, \fB\s-1CANVAS\s0\fR,
+\fB\s-1SHADEA\s0\fR left/top border, \fB\s-1SHADEB\s0\fR right/bottom border, \fB\s-1GRID\s0\fR, \fB\s-1MGRID\s0\fR
+major grid, \fB\s-1FONT\s0\fR, \fB\s-1FRAME\s0\fR and axis of the graph or \fB\s-1ARROW\s0\fR. This option
+can be called multiple times to set several colors.
+.Ip "\fB\-t\fR|\fB--title\fR \fItext\fR (default no title)" 8
+Define a title to be written into the graph
+.Ip "\fB\s-1DEF\s0:\fR\fIvname\fR\fB=\fR\fIrrd\fR\fB:\fR\fIds-name\fR\fB:\fR\fI\s-1CF\s0\fR" 8
+Define virtual name for a data source. This name can then be used
+in the functions explained below. The
+\s-1DEF\s0 call automatically chooses an \fB\s-1RRA\s0\fR which provides data in a
+resolution appropriate for the size of the graph to be drawn. Ideally
+this means that one data point from the \fB\s-1RRA\s0\fR should be represented
+by one pixel in the graph. If the resolution of the \fB\s-1RRA\s0\fR is higher
+than the resolution of the graph, the data in the \s-1RRA\s0 will be
+consolidated according to the consolidation function (\fI\s-1CF\s0\fR) chosen.
+.Ip "\fB\s-1CDEF\s0:\fR\fIvname\fR\fB=\fR\fIrpn-expression\fR" 8
+Create a new virtual data source by evaluating a mathematical expression,
+specified in Reverse Polish Notation (\s-1RPN\s0). If you have ever used a traditional
+\s-1HP\s0 calculator you already know \s-1RPN\s0. The idea behind \s-1RPN\s0 notation is,
+that you have a stack and push your data onto this stack. When ever
+you execute an operation, it takes as many data values from the stack
+as needed. The pushing of data is implicit, so when ever you specify a number
+or a variable, it gets pushed automatically.
+.Sp
+If this is all a big load of
+incomprehensible words for you, maybe an example helps (a more
+complete explanation is given in [1]):
+The expression
+vname+3/2 becomes vname,3,2,/,+ in \s-1RPN\s0. First the three values get
+pushed onto the stack (which now contains (the current value of)
+vname, a 3 and a 2).
+Then the / operator pops two values from the stack (3 and 2), divides
+the first argument by the second (3/2) and pushes the result (1.5)
+back onto the stack. Then the + operator pops two values (vname and
+1.5) from the stack; both values are added up and the result gets
+pushes back onto the stack. In the end there is only one value left on
+the stack: The result of the expression.
+.Sp
+The \fIrpn-expression\fR in the \fB\s-1CDEF\s0\fR function takes both, constant values
+as well as \fIvname\fR variables. The following operators can be used on these
+values:
+.Ip "+, \-, *, /" 16
+pops two values from the stack applies the selected operator and pushes
+the result back onto the stack.
+.Ip "\s-1SIN\s0, \s-1COS\s0, \s-1LOG\s0, \s-1EXP\s0" 16
+pops one value from the stack, applies the selected function and pushes
+the result back onto the stack.
+.Ip "\s-1LT\s0, \s-1LE\s0, \s-1GT\s0, \s-1GE\s0, \s-1EQ\s0" 16
+pops two values from the stack, compares them according to the selected
+condition and pushes either 1 back onto the stack if the condition is true
+and 0 if the condition was not true.
+.Ip "\s-1IF\s0" 16
+pops three values from the stack. If the last value is not 0, the
+second value will be pushed back onto the stack, otherwise the
+first value is pushed back.
+.Sp
+If the stack contains the values A, B, C, D, E are presently on the
+stack, the \s-1IF\s0 operator will pop the values E D and C of the stack. It will
+look at C and if it is not 0 it will push D back onto the stack, otherwise
+E will be sent back to the stack.
+.Ip "\s-1UN\s0" 16
+Pops one value of the stack, if it is \fI*\s-1UNKNOWN\s0*\fR, 1 will be pushed
+back otherwise 0.
+.Sp
+Please note that you may only use \fIvname\fR variables that you
+previously defined by either \fB\s-1DEF\s0\fR or \fB\s-1CDEF\s0\fR. Furthermore, as of
+this writing (version 0.99.25), you must use at least one \fIvname\fR
+per expression, that is \*(L"\s-1CDEF:\s0fourtytwo=2,40,+\*(R" will yield an error
+message but not a \fIvname\fR fourtytwo that's always equal to 42.
+.Ip "\fB\s-1PRINT\s0:\fR\fIvname\fR\fB:\fR\fI\s-1CF\s0\fR\fB:\fR\fIformat\fR" 8
+Calculate the chosen consolidation function \fI\s-1CF\s0\fR over the data-source
+variable \fIvname\fR and \f(CWprintf\fR the
+result to stdout using \fIformat\fR.
+.Ip "\fB\s-1GPRINT\s0:\fR\fIvname\fR\fB:\fR\fI\s-1CF\s0\fR\fB:\fR\fIformat\fR" 8
+Same as \fB\s-1PRINT\s0\fR but the result is printed into the graph below the legend.
+.Ip "\fB\s-1COMMENT\s0:\fR\fItext\fR" 8
+Like \fB\s-1GPRINT\s0\fR but the \fItext\fR is simply printed into the graph.
+.Ip "\fB\s-1HRULE\s0:\fR\fIvalue\fR\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]" 8
+Draw a horizontal rule into the graph and optionally add a legend
+.Ip "\fB\s-1VRULE\s0:\fR\fItime\fR\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]" 8
+Draw a vertical rule into the graph and optionally add a legend
+.Ip "\fB\s-1LINE\s0\fR{\fB1\fR|\fB2\fR|\fB3\fR}\fB:\fR\fIvname\fR[\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]]" 8
+Plot for the requested data, using the color specified. Write a legend
+into the graph. The 3 possible keywords \fB\s-1LINE1\s0\fR, \fB\s-1LINE2\s0\fR, and \fB\s-1LINE3\s0\fR
+generate increasingly wide lines. If no color is defined,
+the drawing is done \*(L'blind\*(R' this is useful in connection with the
+\fB\s-1STACK\s0\fR function when you want to \s-1ADD\s0 the values of two
+data-sources without showing it in the graph.
+.Ip "\fB\s-1AREA\s0\fR:\fIvname\fR[\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]]" 8
+Does the same as \fB\s-1LINE\s0?\fR, but the area between 0 and
+the graph will be filled with the color specified.
+.Ip "\fB\s-1STACK\s0\fR:\fIvname\fR[\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]]" 8
+Does the same as \fB\s-1LINE\s0?\fR, but the graph gets stacked on top of the previous
+\fB\s-1LINE\s0?\fR, \fB\s-1AREA\s0\fR or \fB\s-1STACK\s0\fR graph. Depending on the type of the
+previous graph, the \fB\s-1STACK\s0\fR will be either a \fB\s-1LINE\s0?\fR or an \fB\s-1AREA\s0\fR.
+This obviously implies that the first \fB\s-1STACK\s0\fR must be preceeded by an
+\fB\s-1AREA\s0\fR or \fB\s-1LINE\s0?\fR -- you need something to stack something onto in
+the first place ;)
+.SH "NOTE"
+In a \*(L':\*(R' in a \fIlegend\fR argument will mark the end of the legend. To
+enter a \*(L':\*(R' into a legend, the colon must be escaped with a backslash \*(L'\e:\*(R'.
+Beware, that many environments look for backslashes themselves, so it may
+be necessary to write two backslashes so that one is passed onto rrd_graph.
+.SH "NOTE 2"
+The text printed below the actual graph can be formated by appending special
+escaped charactes at the end of a text. When ever such a character occurs,
+all pending text is pushed onto the grah acording to the character specified.
+.PP
+Valid characters are: \fBj\fR for justified, \fBl\fR for left aligned, \fBr\fR
+for right aligned and \fBc\fR for centered. In the next section there is an example
+showing how to use centered formating.
+.PP
+A special case is COMMENT:\es this inserts some additional vertical space before
+placing the next row of legends.
+.SH "NOTE 3"
+Whenever rrd_graph gets called, it prints a line telling the size of
+the gif it has just created to STDOUT. This line looks like this: XSIZExYSIZE.
+.SH "EXAMPLE"
+.PP
+.Vb 5
+\& rrdtool graph demo.gif --title="Demo Graph" \e
+\& DEF:cel=demo.rrd:exhaust:AVERAGE \e
+\& "CDEF:far=cel,32,-,0.55555,*" \e
+\& LINE2:cel#00a000:"D. Celsius" \e
+\& LINE2:far#ff0000:"D. Fahrenheit\ec"
+.Ve
+.SH "AUTHOR"
+Tobias Oetiker <oetiker at ee.ethz.ch>
+.SH "REFERENCES"
+[1] http://www.dotpoint.com/xnumber/rpn_or_adl.htm
+
+.rn }` ''
+.IX Title "RRDGRAPH 1"
+.IX Name "rrdtool graph - Create a graph based on data from one or several RRD"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Item "\fIfilename\fR "
+
+.IX Item "\fB\-s\fR|\fB--start\fR \fIseconds\fR (default \-24*3600)"
+
+.IX Item "\fB\-e\fR|\fB--end\fR \fIseconds\fR (default current time)"
+
+.IX Item "\fB\-x\fR|\fB--x-grid\fR \fIx-axis grid and label\fR (default autoconfigure)"
+
+.IX Item "\fB\-y\fR\fB--y-grid\fR \fIgrid step\fR:\fIlabel factor\fR (default autoconfigure)"
+
+.IX Item "\fB\-v\fR|\fB--vertical-label\fR \fItext\fR"
+
+.IX Item "\fB\-w\fR|\fB--width\fR \fIpixels\fR (default 400 pixel)"
+
+.IX Item "\fB\-h\fR|\fB--height\fR \fIpixels\fR (default 100 pixel)"
+
+.IX Item "\fB\-i\fR|\fB--interlaced\fR (default: false)"
+
+.IX Item "\fB\-u\fR|\fB--upper-limit\fR \fIvalue\fR (default autoconfigure)"
+
+.IX Item "\fB\-l\fR|\fB--lower-limit\fR \fIvalue\fR (default autoconfigure)"
+
+.IX Item "\fB\-r\fR|\fB--rigid\fR"
+
+.IX Item "\fB\-b\fR|\fB--base\fR \fIvalue\fR"
+
+.IX Item "\fB\-o\fR|\fB--logarithmic\fR"
+
+.IX Item "\fB\-c\fR|\fB--color\fR \fI\s-1COLORTAG\s0\fR\fB#\fR\fIrrggbb\fR (default colors)"
+
+.IX Item "\fB\-t\fR|\fB--title\fR \fItext\fR (default no title)"
+
+.IX Item "\fB\s-1DEF\s0:\fR\fIvname\fR\fB=\fR\fIrrd\fR\fB:\fR\fIds-name\fR\fB:\fR\fI\s-1CF\s0\fR"
+
+.IX Item "\fB\s-1CDEF\s0:\fR\fIvname\fR\fB=\fR\fIrpn-expression\fR"
+
+.IX Item "+, \-, *, /"
+
+.IX Item "\s-1SIN\s0, \s-1COS\s0, \s-1LOG\s0, \s-1EXP\s0"
+
+.IX Item "\s-1LT\s0, \s-1LE\s0, \s-1GT\s0, \s-1GE\s0, \s-1EQ\s0"
+
+.IX Item "\s-1IF\s0"
+
+.IX Item "\s-1UN\s0"
+
+.IX Item "\fB\s-1PRINT\s0:\fR\fIvname\fR\fB:\fR\fI\s-1CF\s0\fR\fB:\fR\fIformat\fR"
+
+.IX Item "\fB\s-1GPRINT\s0:\fR\fIvname\fR\fB:\fR\fI\s-1CF\s0\fR\fB:\fR\fIformat\fR"
+
+.IX Item "\fB\s-1COMMENT\s0:\fR\fItext\fR"
+
+.IX Item "\fB\s-1HRULE\s0:\fR\fIvalue\fR\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]"
+
+.IX Item "\fB\s-1VRULE\s0:\fR\fItime\fR\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]"
+
+.IX Item "\fB\s-1LINE\s0\fR{\fB1\fR|\fB2\fR|\fB3\fR}\fB:\fR\fIvname\fR[\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]]"
+
+.IX Item "\fB\s-1AREA\s0\fR:\fIvname\fR[\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]]"
+
+.IX Item "\fB\s-1STACK\s0\fR:\fIvname\fR[\fB#\fR\fIrrggbb\fR[\fB:\fR\fIlegend\fR]]"
+
+.IX Header "NOTE"
+
+.IX Header "NOTE 2"
+
+.IX Header "NOTE 3"
+
+.IX Header "EXAMPLE"
+
+.IX Header "AUTHOR"
+
+.IX Header "REFERENCES"
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.1
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.1 (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdlast.1 Sat Jul 13 18:46:14 2002
@@ -0,0 +1,215 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+''' \*(L" and \*(R", except that they are used on ".xx" lines,
+''' such as .IP and .SH, which do another additional levels of
+''' double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH RRDLAST 1 "19990426.22" "24/Oct/98" "rrdtool"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+rrdtool last \- Return the date of the last data sample in an \fBRRD\fR
+.SH "SYNOPSIS"
+\fBrrdtool\fR \fBlast\fR \fIfilename\fR
+.SH "DESCRIPTION"
+The \fBlast\fR function returns the UNIX timestamp when the RRD was last
+updated.
+.Ip "\fIfilename\fR" 8
+The name of the \fB\s-1RRD\s0\fR that contains the data.
+.SH "AUTHOR"
+Russ Wright <rwwright at home.com>
+
+.rn }` ''
+.IX Title "RRDLAST 1"
+.IX Name "rrdtool last - Return the date of the last data sample in an B<RRD>"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Item "\fIfilename\fR"
+
+.IX Header "AUTHOR"
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.1
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.1 (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdtutorial.1 Sat Jul 13 18:46:14 2002
@@ -0,0 +1,1300 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+''' \*(L" and \*(R", except that they are used on ".xx" lines,
+''' such as .IP and .SH, which do another additional levels of
+''' double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH RRDTUTORIAL 1 "19990510.19" "10/May/99" "rrdtool"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+rrdtutorial \- Alex van den Bogaerdts RRD Tool tutorial
+.SH "DESCRIPTION"
+RRDtool is written by Tobias Oetiker <oetiker at ee.ethz.ch> with
+contributions from many people all around the world. This document is
+written by Alex van den Bogaerdt <alex at ergens.op.het.net> to help you
+understand what RRDtool is and what it can do for you.
+.PP
+The documentation provided with RRDtool can be too technical for some
+people and here we help you to understand the basics in order to
+prepare you to read the documentation yourself. It also explains the
+general things about statistics with a focus on networking.
+.SH "TUTORIAL"
+.Sh "Important"
+We first have to do some uninteresting reading folks, don't skip this
+part! Later on, in the examples, you need to know the basics.
+.Sh "What is RRDtool ?"
+RRDtool means Round Robin Database tool.
+Round robin is a technique that works with a fixed amount of data, and a
+pointer to the current element. Think of a circle with some dots plotted
+on the edge, these dots are the places where data can be stored. Draw an
+arrow from the center of the circle to one of the dots, this is the pointer.
+When the current data is read or written, the pointer moves to the next
+element. As we are on a circle there is no beginning nor an end, you can
+go on and on. After a while, all the available places will be used and
+the process automatically reuses old locations.
+RRDtool works with with Round Robin Databases (RRDs). It stores and retrieves
+data from them.
+.Sh "What data can be put into an \s-1RDD\s0 ?"
+You name it, it will probably fit. You should be able to measure some value
+at several points in time and provide this to RRDtool. If you can do this,
+RRDtool will probably be able to store it.
+.PP
+Many examples talk about \s-1SNMP\s0 which is an acronym for
+Simple Network Management Protocol. The \*(L"simple\*(R" is about the protocol,
+it does not mean it is simple to manage a network. After working your
+way through this document, you will know enough to be able to understand
+what people are talking about. For now, just assume \s-1SNMP\s0 is a way to
+talk to devices and ask those devices about counters they keep.
+It is the value from those counters that are kept in the \s-1RRD\s0.
+.Sh "What can I do with this tool ?"
+RRDtool originated from \s-1MRTG\s0 (multi router traffic grapher) which itself
+came from a tiny little script to monitor the performance of a connection
+to the Internet. Since then, \s-1MRTG\s0 has also been used for several other
+purposes including temperature, speed, voltage, number of printouts and
+many other things. Most likely you will start to use the RRDtool to store
+and process data collected via \s-1SNMP\s0. The data will most likely be bytes
+(or bits) transfered from and to a network or a computer.
+RRDtool lets you create a database, store data in it, retrieve that data
+and create graphs in \s-1GIF\s0 format for display on a web browser. Those \s-1GIF\s0
+images are dependant on the data you collected and could be, for instance,
+an overview of the average network usage, or rather the peaks that occurred.
+It can also be used to display tidal waves, solar radiation, power
+consumption, number of visitors at an exibition, noise levels near an
+airport, temperature on your favorite holiday location, temperature in the
+fridge and whatever you imagination can come up with. You need a sensor to
+measure the data and be able to feed the numbers to RRDtool. Many devices
+have such a sensor.
+.Sh "What if I still have problems after reading this document ?"
+More exact, after re-reading this document :)
+It all depends on the kind of problems you have. If you are unable to
+compile the sources and you have a fairly common \s-1OS\s0, it will probably
+not be the fault of RRDtool. There may be precompiled versions around
+on the Internet. If they come from trusted sources, get one of those.
+If on the other hand the program works but does not give you the
+expected results, it will be a problem with configuring it. Review
+your configuration and compare it with the examples that follow.
+.PP
+There is a mailing list and an archive of it. Read the list for a few
+weeks and search the archive. It is considered rude to just ask
+a question without reading the list, your problem may already have been
+solved for somebody else and you will be helped without writing a new
+a message at all ... This is true for most, if not all, mailing lists
+and not only for this particular list! Look in the documentation that
+came with RRDtool for the location and usage of the list.
+.PP
+I suggest you take a moment to subscribe to the mailing list right now
+by sending an email to <rrdtool-users-request at list.ee.ethz.ch> with a
+subject of \*(L"subscribe\*(R". If you ever want to leave this list, you write
+an email to the same address but now with a subject of \*(L"unsubscribe\*(R".
+.Sh "How will you help me ?"
+By giving you some detailed descriptions with detailed examples.
+It is assumed that following the instructions in the order presented
+will build up enough knowledge of the program to experiment for yourself.
+If it doesn't work the first time, don't give up. Reread the stuff that
+you did understand, you may have missed something.
+By following the examples you get some hands-on experience and, even
+more important, some background information of how it works.
+.PP
+You will need to know something about hexadecimal numbers. If you don't
+then start with reading \*(L"bin_dec_hex\*(R" before you continue here.
+.Sh "Your first Round Robin Database"
+In my opinion the best way to learn something is to actually do it.
+Why not start right now? We will create a database, put some values in
+it and extract this data again. It is expected that you get the same
+results when you try these examples yourself so do that.
+We will start with some easy stuff and compare a car with a router,
+or compare kilometers (miles if you wish) with bits and bytes. It's
+all the same: Some number over some time.
+.PP
+Assume we have a device that transfers bytes to and from the Internet.
+This device keeps a counter that starts at zero when it is turned on,
+increasing with every byte that is transfered. This counter will have
+a maximum value, if that value is reached and an extra byte is counted,
+the counter starts all over at zero. This is the same as many counters
+in the world such as the mileage counter in a car.
+Most discussions about networking talk about bits per second so lets
+get used to that right away. Assume a byte is eight bits and start to
+think in bits not bytes. The counter however still counts bytes !
+In the \s-1SNMP\s0 world most of the counters are 32 bits. That means they are
+counting from 0 to 4294967295. We will use these values in the examples.
+The device, when asked, returns the current value of the counter. We
+know the time that has passes since we last asked so we now know how
+many bytes have been transfered ***on average*** per second. This is
+not very hard to calculate. First in words, then in calculi:
+.Ip "1." 3
+Take the current counter, subtract the previous value from it.
+.Ip "2." 3
+Do the same with the current time and the previous time.
+.Ip "3." 3
+Divide the outcome of (1) by the outcome of (2), the result is
+the amount of bytes per second. Multiply by eight to get the
+number of bits per second (bps).
+.Sp
+.Vb 1
+\& bps = (counter_now - counter_before) / (time_now - time_before) * 8
+.Ve
+.PP
+For some people it may help to translate this to a automobile example:
+Do not try this example, and if you do, don't blame me for the results.
+.PP
+People who are not used to think in kilometers per hour can translate
+most into miles per hour by dividing km by 1.6 (close enough).
+I will use the following abbreviations:
+.PP
+.Vb 6
+\& M: meter
+\& KM: kilometer (= 1000 meters).
+\& H: hour
+\& S: second
+\& KM/H: kilometers per hour
+\& M/S: meters per second
+.Ve
+You're driving a car. At 12:05 you read the counter in the dashboard
+and it tells you that the car has moved 12345 \s-1KM\s0 until that moment.
+At 12:10 you look again, it reads 12357 \s-1KM\s0. This means you have
+traveled 12 \s-1KM\s0 in five minutes. A scientist would translate that
+into meters per second and this makes a nice comparison towards the
+problem of (bytes per five minutes) versus (bits per second).
+.PP
+We traveled 12 kilometers which is 12000 meters. We did that in five
+minutes which translates into 300 seconds. Our speed is 12000M / 300S
+equals 40 M/S.
+.PP
+We could also calculate the speed in \s-1KM/H\s0: twelve times five minutes
+is an hour so we have to multiply 12 \s-1KM\s0 by 12 to get 144 \s-1KM/H\s0.
+For our native English speaking friends: this is ninety \s-1MPH\s0 and
+therefore not recommended to try for yourself where I live :)
+.PP
+Remember: these numbers are averages and there is no way to figure out
+from the numbers we got that you drove at a constant speed.
+.PP
+I hope you understand that there is no difference in calculating M/S or
+bps, only the way we collect the data is different. Even the K from kilo
+is the same as in networking terms k also means 1000.
+.PP
+We will now create a database where we can keep all these interesting
+numbers. The method used to start the program may differ slightly from
+\s-1OS\s0 to \s-1OS\s0 but I assume you can figure it out if it works different on
+your \s-1OS\s0. Make sure you do not overwrite any file on your system when
+executing the following command (so: first look if it's safe!) and type
+the whole line as one long line (I had to split it for readability)
+and skip all of the \*(L'\e\*(R' characters.
+.PP
+.Vb 5
+\& rrdtool create test.rrd \e
+\& --start 920804400 \e
+\& DS:speed:COUNTER:600:U:U \e
+\& RRA:AVERAGE:0.5:1:24 \e
+\& RRA:AVERAGE:0.5:6:10
+.Ve
+(So enter: \f(CWrrdtool create test.rrd --start 920804400 DS ...\fR)
+.Sh "What has been created ?"
+We created the round robin database called test (test.rrd)
+which starts at noon the day I started (7th of march, 1999) writing
+this document. It holds one data source (\s-1DS\s0) named \*(L"speed\*(R" that gets
+built from a counter. This counter is read every five minutes (default)
+In the same database two round robin archives (RRAs) are kept, one
+averages the data every time it is read (so: there's nothing to average)
+and keeps 24 samples (24 times 5 minutes is 2 hours). The other averages
+6 values (half hour) and contains 10 of such averages (so: 5 hours)
+The remaining options will be discussed later on.
+Chances are that you are not in the same part of the world as I am.
+This means your time zone is different. In all examples where I talk
+about time, the hours may be wrong for you. This has little effect on
+the results of the examples, just correct the hours while reading.
+.PP
+We now have to fill our database with some numbers. We'll pretend to
+have read the following numbers:
+.PP
+.Vb 15
+\& 12:05 12345 KM
+\& 12:10 12357 KM
+\& 12:15 12363 KM
+\& 12:20 12363 KM
+\& 12:25 12363 KM
+\& 12:30 12373 KM
+\& 12:35 12383 KM
+\& 12:40 12393 KM
+\& 12:45 12399 KM
+\& 12:50 12405 KM
+\& 12:55 12411 KM
+\& 13:00 12415 KM
+\& 13:05 12420 KM
+\& 13:10 12422 KM
+\& 13:15 12423 KM
+.Ve
+We fill the database as follows:
+.PP
+.Vb 5
+\& rrdtool update test.rrd 920804700:12345 920805000:12357 920805300:12363
+\& rrdtool update test.rrd 920805600:12363 920805900:12363 920806200:12373
+\& rrdtool update test.rrd 920806500:12383 920806800:12393 920807100:12399
+\& rrdtool update test.rrd 920807400:12405 920807700:12411 920808000:12415
+\& rrdtool update test.rrd 920808300:12420 920808600:12422 920808900:12423
+.Ve
+This reads: update our test database with the following numbers
+.PP
+.Vb 2
+\& time 920804700, value 12345
+\& time 920805000, value 12357
+.Ve
+etcetera.
+.PP
+As you can see, it is possible to feed more than one value into the
+database in one command. I had to stop at three for readability but
+the real maximum will be \s-1OS\s0 dependent.
+.PP
+The time value may look strange to you, it is written in seconds since
+the first of January, 1970, midnight. Don't worry about this yet, just
+notice that there is a difference of 300 in between all values.
+.Sh "It is time to create some graphics"
+Try the following command:
+.PP
+.Vb 4
+\& rrdtool graph speed.gif \e
+\& --start 920804400 --end 920808000 \e
+\& DEF:myspeed=test.rrd:speed:AVERAGE \e
+\& LINE2:myspeed#FF0000
+.Ve
+This will create speed.gif which starts at 12:00 and ends at 13:00.
+There is a definition of variable myspeed, it is the data from \s-1RRA\s0
+\*(L"speed\*(R" out of database \*(L"test.rrd\*(R". The line drawn is 2 pixels high,
+and comes from variable myspeed. The color is red.
+You'll notice that the start of the graph is not at 12:00 but at 12:05
+and this is because we have insufficient data to tell the average before
+that time. This will only happen when you miss some samples, this will
+not happen a lot, hopefully.
+.PP
+If this has worked: Congratulations. If not, check what went wrong.
+.PP
+The colors are built up from red, green and blue. For each of the
+components, you specify how much to use in hexadecimal where 00 means
+not included and \s-1FF\s0 means fully included.
+The color white is a mixture of red, green and blue: \s-1FFFFFF\s0
+The color black is all colors off: 000000
+(Please, no discussions if black and white can be called colors)
+.PP
+.Vb 5
+\& red #FF0000
+\& green #00FF00
+\& blue #0000FF
+\& purple #FF00FF (mixed red with blue)
+\& gray #555555 (one third of all components)
+.Ve
+The \s-1GIF\s0 you just created can be displayed using a web browser or other
+software you like. I can not provide you with an example of that,
+because there are too many different setups, possibilities etc.
+.Sh "Graphics with some math"
+When looking at the image, you notice that the horizontal axis displays
+12:10, 12:20, 12:30, 12:40 and 12:50. The two remaining times (12:00 and
+13:00) would not be displayed nicely so they are skipped.
+The vertical axis displays the range we entered. We provided kilometers
+and when divided by 300 seconds, we get very small numbers. To be exact,
+the first value was 12 (12357-12345) and divided by 300 this makes 0.04
+RRDtool displays this as 40 m which means 40 mili (so: \s-1NOT\s0 meters).
+What we did wrong was that we should have measured in meters, this would
+have been (12357000-12345000)/300 = 12000/300 = 40.
+.PP
+Let's correct that. We could recreate our database and store the correct
+data but there is another way: do some calculations while creating the
+gif file !
+.PP
+.Vb 6
+\& rrdtool graph speed2.gif \e
+\& --start 920804400 --end 920808000 \e
+\& --vertical-label m/s \e
+\& DEF:myspeed=test.rrd:speed:AVERAGE \e
+\& CDEF:realspeed=myspeed,1000,* \e
+\& LINE2:realspeed#FF0000
+.Ve
+After viewing this \s-1GIF\s0, you notice the \*(L"m\*(R" has disappeared. This it what
+the correct result would be. Also, a label has been added to the image.
+Apart from the things mentioned above, the \s-1GIF\s0 should be the same.
+.PP
+The calculations are done with the \s-1CDEF\s0 part. What it says is: take the
+data source myspeed and the number 1000, multiply those. The calculations
+are done using Reverse Polish Notation. It is an easy way of performing
+calculations after you understand it. You will, eventually but for now
+assume it is correct what I write and just keep to the examples in this
+file. Read the documentation that came with RRDtool (look in rrdgraph.doc)
+when you're ready for it.
+.PP
+Hang on! If we can multiply values with 1000, it should also be possible
+to display kilometers per hour from the same data !
+What do we need to do ? If we have meters per second, we can make this
+meters per hour by multiplying the value with 3600 (there go 3600 seconds
+in one hour). To get kilometers per hour, we need to divide by 1000.
+We end up with: value * 3600 / 1000 = value * 3.6 . Remember we also have
+to correct our mistake, so it is value * 3600 for us.
+.PP
+Now let's create this \s-1GIF\s0, and add some more magic ...
+.PP
+.Vb 10
+\& rrdtool graph speed3.gif \e
+\& --start 920804400 --end 920808000 \e
+\& --vertical-label km/h \e
+\& DEF:myspeed=test.rrd:speed:AVERAGE \e
+\& CDEF:kmh=myspeed,3600,* \e
+\& CDEF:fast=kmh,100,GT,kmh,0,IF \e
+\& CDEF:good=kmh,100,GT,0,kmh,IF \e
+\& HRULE:100#0000FF:"Maximum allowed" \e
+\& AREA:good#00FF00:"Good speed" \e
+\& AREA:fast#FF0000:"Too fast"
+.Ve
+This looks much better. Speed in \s-1KM/H\s0 and even an extra line with the
+maximum allowed speed (on the road I travel at). I also changed the
+colors used to display speed and changed it from a line into an area.
+.PP
+The calculations are more complex now. For the \*(L"good\*(R" speed they are:
+.Ip "\(bu" 2
+Check if kmh is greater than 100 ( kmh,100 ) \s-1GT\s0
+.Ip "\(bu" 2
+If so, return 0, else kmh ((( kmh,100 ) \s-1GT\s0 ), 0, kmh) \s-1IF\s0
+.PP
+For the other speed:
+.Ip "\(bu" 2
+Check if kmh is greater than 100 ( kmh,100 ) \s-1GT\s0
+.Ip "\(bu" 2
+If so, return kmh, else return 0 ((( kmh,100) \s-1GT\s0 ), kmh, 0) \s-1IF\s0
+.Sh "Graphics Magic"
+I like to believe there are virtually no limits about what RRDtool
+can do. I will not explain how it works, but look at the following
+\s-1GIF\s0:
+.PP
+.Vb 12
+\& rrdtool graph speed4.gif \e
+\& --start 920804400 --end 920808000 \e
+\& --vertical-label km/h \e
+\& DEF:myspeed=test.rrd:speed:AVERAGE \e
+\& CDEF:kmh=myspeed,3600,* \e
+\& CDEF:fast=kmh,100,GT,100,0,IF \e
+\& CDEF:over=kmh,100,GT,kmh,100,-,0,IF \e
+\& CDEF:good=kmh,0,kmh,100,GT,IF \e
+\& HRULE:100#0000FF:"Maximum allowed" \e
+\& AREA:good#00FF00:"Good speed" \e
+\& AREA:fast#550000:"Too fast" \e
+\& STACK:over#FF0000:"Over speed"
+.Ve
+Let's create a quick and dirty \s-1HTML\s0 page to view three GIFs:
+.PP
+.Vb 7
+\& <HTML><HEAD><TITLE>Speed</TITLE></HEAD><BODY>
+\& <IMG src="speed2.gif" alt="Speed in meters per second">
+\& <BR>
+\& <IMG src="speed3.gif" alt="Speed in kilometers per hour">
+\& <BR>
+\& <IMG src="speed4.gif" alt="Traveled too fast?">
+\& </BODY></HTML>
+.Ve
+Name the file \*(L"speed.html\*(R" or similar, and view it.
+.PP
+Now, all you have to do is measure the values regularly and update the
+database. Every time you create these three GIFs and reload the page
+and the GIFs (better reread these last three words!) you know how fast
+you traveled.
+.Sh "Updates in Reality"
+You already looked at the \*(L"update\*(R" tool. It took one or more parameters
+in the form of \*(L"<time>:<value>\*(R". You'll be glad to know that you can
+get the current time by filling in a \*(L"N\*(R" as the time.
+If you wish, you can also use the \*(L"time\*(R" function in perl.
+The shortest example in this doc :)
+.PP
+.Vb 1
+\& perl -e 'print time, "\en" '
+.Ve
+How you can run a program on regular intervals is \s-1OS\s0 specific, so I just
+give you an example script in a sort of pseudo code:
+(Do not try this with our test database, it is used in further examples)
+.PP
+.Vb 2
+\& Get the value, put it in variable "$speed"
+\& rrdtool update speed.rrd N:$speed
+.Ve
+This is all. Run this script every five minutes. When you need to know
+what the graphics look like, run the examples above. You could put them
+in a script. After running that script, view index.html
+.Sh "Some words on \s-1SNMP\s0"
+I can imagine very few people will be able to get real data from their
+car every five minutes, all other people will have to settle for some
+other kind of counter. You could measure the number of pages printed by
+the laser-jet printer, the coffee made by the coffee machine, a device
+that counts the electricity used, whatever. Just as long as it is an
+incrementing counter that you can measure regularly, you can graph it
+against time as we did. Most people will use the counter that keeps track
+of octets (bytes) transfered by a routing device so we have to do just
+that. We will start with a description of how to collect data.
+Some people will make a remark that there are tools who can do this data
+collection for you. They are right! However, I feel it is important that
+you understand they are not necessary. If you have to look why things
+went wrong, you need to know how the stuff works.
+.PP
+One tool used in the example has been talked about very briefly in the
+beginning of this document, it is called \s-1SNMP\s0. It is a way of talking to
+equipment. The tool I use below is called \*(L"snmpget\*(R" and this is how it
+works:
+.PP
+.Vb 1
+\& snmpget device password OID
+.Ve
+For device you substitute the name of your device, for password you
+use the \*(L"community\*(R" as it is called. For most devices \*(L"public\*(R" will do
+but this can be disabled, altered or protected for privacy and security
+reasons. You will need to find this out as there is no way I can tell
+what you ( ...your device... ) are keeping a secret from me.
+.PP
+Then there is this third parameter, called \s-1OID\s0.
+When you start to learn about \s-1SNMP\s0 it looks very confusing. It isn't
+all that difficult when you look at the Management Information Base
+or in short: the \s-1MIB\s0. It is an upside-down tree, with a single node
+as the root and from there a number of branches. These branches end
+up in another node, they branch out, etc. All the branches have a name
+and they form the path that we follow all the way down. The branches
+that we follow are named: iso, org, dod, internet, mgmt and mib-2.
+These names can also be written down as numbers and are 1 3 6 1 2 1.
+.PP
+.Vb 1
+\& iso.org.dod.internet.mgmt.mib-2 (1.3.6.1.2.1)
+.Ve
+From there, we are especially interested in the branch \*(L"interfaces\*(R"
+which has number 2 (so: 1.3.6.1.2.1.2 or 1.3.6.1.2.1.interfaces).
+.PP
+The \s-1SNMP\s0 programs that I know can take above path as a default, so
+I could walk to interfaces without writing it in full. To do that,
+the path has to be written as interfaces, without a leading dot.
+I could also use the long form, then I need to start with a dot.
+.PP
+I can intermix numbers and names as I like. 1.3.6.1.2.1 is the same
+as iso.org.dod.1.2.1 and 1.3.6.internet.2.mib-2
+For interfaces I could write \*(L"interfaces\*(R", 2, or a long version by
+prefixing it with \*(L".1.3.6.1.2.1.\*(R". Just try what works for you and
+do read the manual for the version of snmpget you are using.
+.PP
+First, we have to get some \s-1SNMP\s0 program. First look if there is a
+pre-compiled package available for your \s-1OS\s0. This is the preferred way.
+If not, you will have to get yourself the sources and compile those.
+The Internet is full of sources, programs etc. Find information using
+a search engine or whatever you prefer. You are on your own here, sorry.
+.PP
+Assume you got the program. First try to collect some data that is
+available on most systems. Remember: there is a short name for the
+part of the tree that interests us most in the world we live in !
+I will use the short version as I think this document is large enough
+as it is. If that doesn't work for you, prefix with .1.3.6.1.2.1 and
+try again. Also, Read The Fine Manual. Skip the parts you cannot
+understand yet, you should be able to find out how to start the
+program and use it.
+.PP
+.Vb 1
+\& snmpget myrouter public system.sysdescr.0
+.Ve
+The device should answer with a description of itself, perhaps empty.
+Until you got a valid answer from a device, perhaps using a different
+\*(L"password\*(R", or a different device, there is no point in continuing.
+.PP
+.Vb 1
+\& snmpget myrouter public interfaces.ifnumber.0
+.Ve
+Hopefully you get a number as a result, the number of interfaces.
+If so, you can carry on and try a different program called \*(L"snmpwalk\*(R".
+.PP
+.Vb 1
+\& snmpwalk myrouter public interfaces.iftable.ifentry.ifdescr
+.Ve
+If it returns with a list of interfaces, you're almost there.
+Here's an example:
+ [user at host /home/alex]$ snmpwalk cisco public 2.2.1.2
+.PP
+.Vb 5
+\& interfaces.ifTable.ifEntry.ifDescr.1 = "BRI0: B-Channel 1"
+\& interfaces.ifTable.ifEntry.ifDescr.2 = "BRI0: B-Channel 2"
+\& interfaces.ifTable.ifEntry.ifDescr.3 = "BRI0" Hex: 42 52 49 30
+\& interfaces.ifTable.ifEntry.ifDescr.4 = "Ethernet0"
+\& interfaces.ifTable.ifEntry.ifDescr.5 = "Loopback0"
+.Ve
+On this cisco equipment, I would like to monitor the \*(L"Ethernet0\*(R"
+interface and see that it is number four. I try:
+.PP
+.Vb 1
+\& [user at host /home/alex]$ snmpget cisco public 2.2.1.10.4 2.2.1.16.4
+.Ve
+.Vb 2
+\& interfaces.ifTable.ifEntry.ifInOctets.4 = 2290729126
+\& interfaces.ifTable.ifEntry.ifOutOctets.4 = 1256486519
+.Ve
+So now I have two OIDs to monitor and they are (in full, this time):
+.PP
+.Vb 1
+\& 1.3.6.1.2.1.2.2.1.10
+.Ve
+and
+.PP
+.Vb 1
+\& 1.3.6.1.2.1.2.2.1.16
+.Ve
+both with an interface number of 4.
+.PP
+Don't get fooled, this wasn't my first try. It took some time for me too
+to understand what all these numbers mean, it does help a lot when they
+get translated into descriptive text... At least, when people are talking
+about MIBs and OIDs you know what it's all about.
+Do not forget the interface number (0 if it is not interface dependent)
+and try snmpwalk if you don't get an answer from snmpget.
+.PP
+If you understand above part, and get numbers from your device, it is
+time to continue with the following. If not, then go back.
+.Sh "A Real World Example"
+Let the fun begin. First, create a new database. It contains data from
+two counters, called input and output. The data is put into archives
+that average it. They take 1, 6, 24 or 288 samples at a time.
+They also go into archives that keep the maximum numbers. This will be
+explained later on. The time in-between samples is 300 seconds, a good
+starting point, which is the same as five minutes.
+.PP
+.Vb 4
+\& 1 sample averaged stays 1 period of 5 minutes
+\& 6 samples averaged become one average on 30 minutes
+\& 24 samples averaged become one average on 2 hours
+\& 288 samples averaged become one average on 1 day
+.Ve
+.Vb 4
+\& There are 600 samples of five minutes, together just over two days
+\& There are 600 samples of 30 minutes, almost two weeks
+\& There are 600 samples of 2 hours, 50 hour or almost two months
+\& There are 732 samples of 1 day, just over two years
+.Ve
+For people used to \s-1MRTG\s0 that even have read the manuals, these numbers
+should look familiar...
+.PP
+.Vb 11
+\& rrdtool create myrouter.rrd \e
+\& DS:input:COUNTER:600:U:U \e
+\& DS:output:COUNTER:600:U:U \e
+\& RRA:AVERAGE:0.5:1:600 \e
+\& RRA:AVERAGE:0.5:6:600 \e
+\& RRA:AVERAGE:0.5:24:600 \e
+\& RRA:AVERAGE:0.5:288:732 \e
+\& RRA:MAX:0.5:1:600 \e
+\& RRA:MAX:0.5:6:600 \e
+\& RRA:MAX:0.5:24:600 \e
+\& RRA:MAX:0.5:288:732
+.Ve
+Next thing to do is collect data and store it. Here is an example.
+It is written partially in pseudo code so you will have to find out what
+to do exactly on your \s-1OS\s0 to make it work.
+.PP
+.Vb 8
+\& while not the end of the universe
+\& do
+\& get result of
+\& snmpget router community 2.2.1.10.4
+\& into variable $in
+\& get result of
+\& snmpget router community 2.2.1.16.4
+\& into variable $out
+.Ve
+.Vb 1
+\& rrdtool update myrouter.rrd N:$in:$out
+.Ve
+.Vb 2
+\& wait for 5 minutes
+\& done
+.Ve
+Then, after collecting data for a day, try to create an image using:
+.PP
+.Vb 5
+\& rrdtool graph myrouter-day.gif --start -86400 \e
+\& DEF:inoctets=myrouter.rrd:input:AVERAGE \e
+\& DEF:outoctets=myrouter.rrd:output:AVERAGE \e
+\& AREA:inoctets#00FF00:"In traffic" \e
+\& LINE1:outoctets#0000FF:"Out traffic"
+.Ve
+This should produce a picture with one day worth of traffic.
+One day is 24 hours of 60 minutes of 60 seconds: 24*60*60=86400, we
+start at now minus 86400 seconds. We DEFine inoctets and outoctets
+as the average values from the database myrouter.rrd and draw an area
+for the \*(L"in\*(R" traffic and a line for the \*(L"out\*(R" traffic.
+.PP
+View the image and keep logging for a few more days.
+If you like, you could try the examples from the test database and
+see if you can play around with the options and calculations.
+.PP
+Suggestion:
+.PP
+Display in bytes per second and in bits per second. Make the ethernet
+graphics go red if they are over four megabits per second.
+.Sh "Consolidation Functions"
+A few paragraphs back I mentioned the possibility of keeping
+the maximum values instead of the average values. Let's go
+into this a bit more.
+.PP
+Recall all the stuff about the speed of the car. Suppose we drove at 144
+\s-1KM/H\s0 during 5 minutes and then were stopped by the police for 25 minutes.
+At the end of the lecture we would take our laptop and create+view the
+image taken from the database. If we look at the second \s-1RRA\s0 we did
+create, we would have the average from 6 samples. The samples measured
+would be 144+0+0+0+0+0=144, divided by 30 minutes, corrected for the
+error by 1000, translated into \s-1KM/H\s0, with a result of 24 \s-1KM/H\s0.
+I would still get a ticket but not for speeding anymore :)
+.PP
+Obviously, in this case, we shouldn't look at the averages. In some
+cases they are handy. If you want to know how much \s-1KM\s0 you had traveled,
+the picture would be the right one to look at. On the other hand, for
+the speed that we traveled at, the maximum number seen is much more
+valuable. (later we will see more types)
+.PP
+It is the same for data. If you want to know the amount, look at the
+averages. If you want to know the rate, look at the maximum.
+Over time, they will grow apart more and more. In the last database
+we have created, there are two archives that keep data per day. The
+archive that keeps averages will show low numbers, the archive that
+shows maxima will have higher numbers.
+For my car this would translate in averages per day of 96/24=4 \s-1KM/H\s0
+(as I travel about 94 kilometers on a day) during week days, and
+maximum of 120 \s-1KM/H\s0 on weekdays (my top speed that I reach every day).
+.PP
+Big difference. Do not look at the second graph to estimate the
+distances that I travel and do not look at the first graph to
+estimate my speed. This will work if the samples are close together,
+as they are in five minutes, but not if you average.
+.PP
+On some days, I go for a long ride. If I go across Europe and travel
+for over 12 hours, the first graph will rise to about 60 \s-1KM/H\s0. The
+second one will show 180 \s-1KM/H\s0. This means that I traveled a distance
+of 60 \s-1KM/H\s0 times 24 H = 1440 \s-1KM\s0. I did this with a higher speed and
+a maximum around 180 \s-1KM/H\s0. This doesn't mean that I traveled for 8
+hours at a constant speed of 180 \s-1KM/H\s0 !
+This is a real example: go with the flow through Germany and stop
+a few times for gas and coffee. Drive slowly through Austria and the
+Netherlands. Be careful in the mountains and villages. If you would
+look at the graphs created from the five-minute averages you would
+get a totally different picture. You would see the same values on the
+average and maximum graphs (provided I measured every 300 seconds).
+You would be able to see when I stopped, when I was in top gear, when
+I drove over fast motor-ways etc. The granularity of the data is much
+higher, so you can see more. However, this takes 12 samples per hour,
+or 288 values per day, so it would be too much to keep for a long
+period of time. Therefore we average it, eventually to one value per
+day. From this one value, we cannot see much detail.
+.PP
+Make sure you understand the last few paragraphs. There is no value
+in only a line and a few axis, you need to know what they mean and
+interpret the data in a good way. This is true for all data.
+.PP
+The biggest mistake you can make is to use the collected data for
+something that it is not suitable for. You would be better off if
+you would not have the graphics at all in that case.
+.Sh "Let's review what you now should know."
+You now know how to create a database. You can put the numbers in it,
+get them out again by creating an image, do math on the data from the
+database and view the outcome instead of the raw data.
+You know about the difference between averages and maxima, and when
+to use which (or at least you have an idea).
+.PP
+RRDtool can do more than what we have learned up to now. Before you
+continue with the rest of this doc, I recommend that you reread from
+the start and try some modifications on the examples. Make sure you
+fully understand everything. It will be worth the effort and helps
+you not only with the rest of this doc but also in your day to day
+monitoring long after you read this introduction.
+.Sh "Data Source Types"
+All right, you feel like continuing. Welcome back and get ready
+for an increased speed in the examples and explanation.
+.PP
+You know that in order to view a counter over time, you have to
+take two numbers and divide the difference of them between the
+time lapsed. This makes sense for the examples I gave you but there
+are other possibilities. For instance, I'm able to retrieve the
+temperature from my router in three places namely the inlet, the
+so called hot-spot and the exhaust. If I take the difference of
+the two samples and divide that by 300 (seconds) there would not be very
+much to display ... If there would be anything to display it would
+be the fluctuations in the temperature and if they produce noticeable
+results when divided by 300, I'd better look for a new computer room.
+.PP
+So, what can we do ? RRDtool can also store the values you measure
+directly as they are (this is not entirely true but close enough). The
+graphs we make look much better, they will show a rather constant
+value. I know when the router is busy (it
+works \-> it uses more electricity \-> it generates more heat \-> the
+temperature rises). I know when the doors are left open (the room is
+cooled \-> the warm air from the rest of the building flows into the
+computer room \-> the inlet temperature rises) etc. The data type we
+use when creating the database before was counter, we now have a
+different data type and thus a different name for it. It is called
+\s-1GAUGE\s0. There are more such data types:
+.PP
+.Vb 4
+\& - COUNTER we already know this one
+\& - GAUGE we just learned this one
+\& - DERIVE
+\& - ABSOLUTE
+.Ve
+The two new types are \s-1DERIVE\s0 and \s-1ABSOLUTE\s0. Absolute can be used like
+counter with one difference: RRDtool assumes the counter is reset when
+it's read. That is: its delta is known without calculation by RRDtool
+whereas RRDtool needs to calculate it for the counter type.
+Example: our first example (12345, 12357, 12363, 12363) would read:
+unknown, 12, 6, 0. The rest of the calculations stay the same.
+The other one, derive, is like counter. Unlike counter, it can also
+decrease so it can have a negative delta. Again, the rest of the
+calculations stay the same.
+.PP
+Let's try them all:
+.PP
+.Vb 22
+\& rrdtool create all.rrd --start 978300900 \e
+\& DS:a:COUNTER:600:U:U \e
+\& DS:b:GAUGE:600:U:U \e
+\& DS:c:DERIVE:600:U:U \e
+\& DS:d:ABSOLUTE:600:U:U \e
+\& RRA:AVERAGE:0.5:1:10
+\& rrdtool update all.rrd \e
+\& 978301200:300:1:600:300 \e
+\& 978301500:600:3:1200:600 \e
+\& 978301800:900:5:1800:900 \e
+\& 978302100:1200:3:2400:1200 \e
+\& 978302400:1500:1:2400:1500 \e
+\& 978302700:1800:2:1800:1800 \e
+\& 978303000:2100:4:0:2100 \e
+\& 978303300:2400:6:600:2400 \e
+\& 978303600:2700:4:600:2700 \e
+\& 978303900:3000:2:1200:3000
+\& rrdtool graph all1.gif -s 978300600 -e 978304200 -h 400 \e
+\& DEF:linea=all.rrd:a:AVERAGE LINE3:linea#FF0000:"Line A" \e
+\& DEF:lineb=all.rrd:b:AVERAGE LINE3:lineb#00FF00:"Line B" \e
+\& DEF:linec=all.rrd:c:AVERAGE LINE3:linec#0000FF:"Line C" \e
+\& DEF:lined=all.rrd:d:AVERAGE LINE3:lined#000000:"Line D"
+.Ve
+.Sh "\s-1RRD\s0 Tool under the Microscope"
+.Ip "\(bu" 2
+Line A is a counter so it should continuously increment and RRDtool
+should calculate the differences. Also, RRDtool needs to divide the
+difference by the amount of time lapsed. This should end up as a
+straight line at 1 (the deltas are 300, the time is 300).
+.Ip "\(bu" 2
+Line B is of type gauge. These are \*(L"real\*(R" values so they should match
+what we put in: a sort of a wave.
+.Ip "\(bu" 2
+Line C is derive. It should be a counter that can decrease. It does
+so between 2400 and 0, with 1800 in-between.
+.Ip "\(bu" 2
+Line D is of type absolute. This is like counter but it works on
+values without calculating the difference. The numbers are the same
+and as you can see (hopefully) this has a different result.
+.PP
+This translates in the following values, starting at 23:10 and ending
+at 00:10 the next day (where U means unknown/unplotted):
+.PP
+.Vb 4
+\& - Line A: u u 1 1 1 1 1 1 1 1 1 u
+\& - Line B: u 1 3 5 3 1 2 4 6 4 2 u
+\& - Line C: u u 2 2 2 0 -2 -6 -2 0 2 u
+\& - Line D: u 1 2 3 4 5 6 7 8 9 10 u
+.Ve
+If your \s-1GIF\s0 shows all this, you know you have typed the data correct,
+the RRDtool executable is working properly, your viewer doesn't fool you
+and you successfully entered the year 2000 :)
+You could try the same example four times, each time with only one of
+the lines.
+.PP
+Let's go over the data again:
+.Ip "\(bu" 2
+Line A: 300,600,900 and so on. The counter delta is a constant 300 and
+so it the time delta. A number divided by itself is always 1 (except
+when dividing by zero which is undefined/illegal).
+Why is it that the first point is unknown ? We do know what we put into
+the database ? True ! But we didn't have a value to calculate the delta
+from so we don't know where we started. It would be wrong to assume we
+started at zero so we don't !
+.Ip "\(bu" 2
+Line B: There is nothing to calculate. The numbers are as is.
+.Ip "\(bu" 2
+Line C: Again, the start-out value is unknown. The same story is valid
+like for line A. In this case the deltas are not constant so the line
+is not. If we would put the same numbers in the database as we did for
+line A, we would have gotten the same line. Unlike type counter,
+this type can decrease and I hope to show you later on why
+there is a difference.
+.Ip "\(bu" 2
+Line D: Here the device calculates the deltas. Therefore we \s-1DO\s0 know the
+first delta and it is plotted. We had the same input as with line A but
+the meaning of this input is different. Therefore the line is different.
+In this case the deltas increase each time with 300. The time delta
+stays at a constant 300 and therefore the division of the two gives
+increasing results.
+.Sh "Counter Wraps"
+There are a few more basics to show. Some important options are still to
+be covered and we haven't look at counter wraps yet. First the counter wrap:
+In our car we notice that our counter shows 999987. We travel 20 \s-1KM\s0 and
+the counter should go to 1000007. Unfortunately, there are only six digits
+on our counter so it really shows 000007. If we would plot that on a type
+\s-1DERIVE\s0, it would mean that the counter was set back 999980 \s-1KM\s0. It wasn't,
+and there has to be some protection for this. This protection is only
+available for type \s-1COUNTER\s0 which should be used for this kind of counter
+anyways. How does it work ? Type counter should never decrease and
+therefore RRDtool must assume it wrapped if it does decrease !
+If the delta is negative, this can be compensated for by adding the
+maximum value of the counter + 1. For our car this would be:
+.PP
+.Vb 1
+\& Delta = 7 - 999987 = -999980 (instead of 1000007-999987=20)
+.Ve
+.Vb 1
+\& Real delta = -999980 + 999999 + 1 = 20
+.Ve
+At the moment of writing this document, RRDtool knows of counters that
+are either 32 bits or 64 bits of size. These counters can handle the
+following different values:
+.PP
+.Vb 2
+\& - 32 bits: 0 .. 4294967295
+\& - 64 bits: 0 .. 18446744073709551615
+.Ve
+If these numbers look strange to you, you would like to view them in
+their hexadecimal form:
+.PP
+.Vb 2
+\& - 32 bits: 0 .. FFFFFFFF
+\& - 64 bits: 0 .. FFFFFFFFFFFFFFFF
+.Ve
+RRDtool handles both counters the same. If an overflow occurs and
+the delta would be negative, RRDtool first adds the maximum of a small
+counter + 1 to the delta. If the delta is still negative, it had to be
+the large counter that wrapped. Add the maximum possible value of the
+large counter + 1 and subtract the falsely added small value.
+There is a risk in this: suppose the large counter wrapped while adding
+a huge delta, it could happen in theory that adding the smaller value
+would make the delta positive. In this unlikely case the results would
+not be correct. The increase should be nearly as high as the maximum
+counter value for that to happen so chances are you would have several
+other problems as well and this particular problem would not even be
+worth thinking about. Even though I did include an example of it so you
+can judge that for yourself.
+.PP
+The next section gives you some numerical examples for counter-wraps.
+Try to do the calculations yourself or just believe me if your calculator
+can't handle the numbers :)
+.PP
+Correction numbers:
+.PP
+.Vb 2
+\& - 32 bits: (4294967295+1) = 4294967296
+\& - 64 bits: (18446744073709551615+1)-correction1 = 18446744069414584320
+.Ve
+.Vb 6
+\& Before: 4294967200
+\& Increase: 100
+\& Should become: 4294967300
+\& But really is: 4
+\& Delta: -4294967196
+\& Correction1: -4294967196 +4294967296 = 100
+.Ve
+.Vb 7
+\& Before: 18446744073709551000
+\& Increase: 800
+\& Should become: 18446744073709551800
+\& But really is: 184
+\& Delta: -18446744073709550816
+\& Correction1: -18446744073709550816 +4294967296 = -18446744069414583520
+\& Correction2: -18446744069414583520 +18446744069414584320 = 800
+.Ve
+.Vb 7
+\& Before: 18446744073709551615 ( maximum value )
+\& Increase: 18446744069414584320 ( absurd increase, minimum for
+\& Should become: 36893488143124135935 this example to work )
+\& But really is: 18446744069414584319
+\& Delta: -4294967296
+\& Correction1: -4294967296 + 4294967296 = 0
+\& (not negative -> no correction2)
+.Ve
+.Vb 7
+\& Before: 18446744073709551615 ( maximum value )
+\& Increase: 18446744069414584319 ( one less increase )
+\& Should become: 36893488143124135934
+\& But really is: 18446744069414584318
+\& Delta: -4294967297
+\& Correction1: -4294967297 +4294967296 = -1
+\& Correction2: -1 +18446744069414584320 = 18446744069414584319
+.Ve
+As you can see from the last two examples, you need strange numbers
+for RRDtool to fail (provided it's bug free of course) so this should
+not happen. However, \s-1SNMP\s0 or whatever method you choose to collect the
+data might also fail and it is not uncommon to get wrong numbers
+occasionally. We can't prevent all errors but there are some things we
+could do. RRDtool create takes two special parameters for this. They define
+the minimum and maximum allowed value. Until now, we made them \*(L"U\*(R"
+for Unknown. You may (not: must) provide values for one or both of them
+and if RRDtool receives values that are outside these limits, it will ignore
+them. For a thermometer in degrees Celsius, the absolute minimum is
+just under \-273. For my router, I can assume this minimum is much higher
+so I would say it is 10. The maximum temperature for my router I would
+state as 80. Any higher and the device would be out of order.
+For my car, I would never expect negative numbers and also I would not
+expect numbers to be higher than 230. Anything else, and there must have
+been an error. Remember: the opposite is not true, if the numbers pass
+this check it doesn't mean that they are correct. Always judge the
+graph with a healthy dose of paranoia if it looks weird.
+.Sh "Data Resampling"
+One important feature of RRDtool has not been explained yet:
+It is virtually impossible to collect the data and feed it into RRDtool
+on exact intervals. RRDtool therefore interpolates the data so it is on
+exact intervals. If you do not know what this means or how it works,
+then here's the help you seek:
+.PP
+Suppose a counter increases with exactly one for every second. You want
+to measure it in 300 seconds intervals. You should retrieve values
+that are exactly 300 apart. However, due to various circumstances you
+are a few seconds late and the interval is 303. The delta will also be
+303 in that case. Obviously RRDtool should not put 303 in the database
+and make you believe that the counter increased 303 in 300 seconds.
+This is where RRDtool interpolates: it alters the 303 value as if it
+would have been stored earlier and it will be 300 in 300 seconds.
+Next time you are at exactly the right time. This means that the current
+interval is 297 seconds and also the counter increased with 297. Again
+RRDtool alters the value and stores 300 as it should be.
+.PP
+.Vb 1
+\& in the RDD in real
+.Ve
+.Vb 4
+\& time+000: 0 delta="U" time+000: 0 delta="U"
+\& time+300: 300 delta=300 time+300: 300 delta=300
+\& time+600: 600 delta=300 time+603: 603 delta=303
+\& time+900: 900 delta=300 time+900: 900 delta=297
+.Ve
+Let's create two identical databases. I've chosen the time range 920805000
+to 920805900 as this goes very well with the example numbers.
+.PP
+.Vb 4
+\& rrdtool create seconds1.rrd \e
+\& --start 920804700 \e
+\& DS:seconds:COUNTER:600:U:U \e
+\& RRA:AVERAGE:0.5:1:24
+.Ve
+.Vb 3
+\& for Unix: cp seconds1.rrd seconds2.rrd
+\& for Dos: copy seconds1.rrd seconds2.rrd
+\& for vms: how would I know :)
+.Ve
+.Vb 4
+\& rrdtool update seconds1.rrd \e
+\& 920805000:000 920805300:300 920805600:600 920805900:900
+\& rrdtool update seconds2.rrd \e
+\& 920805000:000 920805300:300 920805603:603 920805900:900
+.Ve
+.Vb 16
+\& rrdtool graph seconds1.gif \e
+\& --start 920804700 --end 920806200 \e
+\& --height 200 \e
+\& --upper-limit 1.05 --lower-limit 0.95 --rigid \e
+\& DEF:seconds=seconds1.rrd:seconds:AVERAGE \e
+\& CDEF:unknown=seconds,UN \e
+\& LINE2:seconds#0000FF \e
+\& AREA:unknown#FF0000
+\& rrdtool graph seconds2.gif \e
+\& --start 920804700 --end 920806200 \e
+\& --height 200 \e
+\& --upper-limit 1.05 --lower-limit 0.95 --rigid \e
+\& DEF:seconds=seconds2.rrd:seconds:AVERAGE \e
+\& CDEF:unknown=seconds,UN \e
+\& LINE2:seconds#0000FF \e
+\& AREA:unknown#FF0000
+.Ve
+Both graphs should show the same.
+.SH "WRAPUP"
+It's time to wrap up this document. You now know all the basics to be
+able to work with RRDtool and to read the documentation available.
+There is plenty more to discover about RRDtool and you will find more and
+more uses for the program. You could create easy graphics using just the
+examples provided and using only RRDtool. You could also use the front
+ends that are available.
+.SH "MAILINGLIST"
+Remember to subscribe to the mailing-list. Even if you are not answering
+the mails that come by, it helps both you and the rest. A lot of the stuff
+that I know about MRTG (and therefore about RRDtool) I've learned while
+just reading the list without posting to it. I did not need to ask the
+basic questions as they are answered in the FAQ (so: read that too) and
+in various mails by other users.
+With thousands of users all over the world, there will always be people
+who ask questions that you can answer because you read this and other
+documentation and they didn't.
+.SH "SEE ALSO"
+The RRD Tool manpages
+.SH "AUTHOR"
+I hope you enjoyed the examples and their descriptions. If you do, help
+other people by pointing them to this document when they are asking
+basic questions. They will not only get their answer but at the same
+time learn a whole lot more.
+.PP
+Alex van den Bogaerdt
+<alex at ergens.op.het.net>
+
+.rn }` ''
+.IX Title "RRDTUTORIAL 1"
+.IX Name "rrdtutorial - Alex van den Bogaerdts RRD Tool tutorial"
+
+.IX Header "NAME"
+
+.IX Header "DESCRIPTION"
+
+.IX Header "TUTORIAL"
+
+.IX Subsection "Important"
+
+.IX Subsection "What is RRDtool ?"
+
+.IX Subsection "What data can be put into an \s-1RDD\s0 ?"
+
+.IX Subsection "What can I do with this tool ?"
+
+.IX Subsection "What if I still have problems after reading this document ?"
+
+.IX Subsection "How will you help me ?"
+
+.IX Subsection "Your first Round Robin Database"
+
+.IX Item "1."
+
+.IX Item "2."
+
+.IX Item "3."
+
+.IX Subsection "What has been created ?"
+
+.IX Subsection "It is time to create some graphics"
+
+.IX Subsection "Graphics with some math"
+
+.IX Item "\(bu"
+
+.IX Item "\(bu"
+
+.IX Item "\(bu"
+
+.IX Item "\(bu"
+
+.IX Subsection "Graphics Magic"
+
+.IX Subsection "Updates in Reality"
+
+.IX Subsection "Some words on \s-1SNMP\s0"
+
+.IX Subsection "A Real World Example"
+
+.IX Subsection "Consolidation Functions"
+
+.IX Subsection "Let's review what you now should know."
+
+.IX Subsection "Data Source Types"
+
+.IX Subsection "\s-1RRD\s0 Tool under the Microscope"
+
+.IX Item "\(bu"
+
+.IX Item "\(bu"
+
+.IX Item "\(bu"
+
+.IX Item "\(bu"
+
+.IX Item "\(bu"
+
+.IX Item "\(bu"
+
+.IX Item "\(bu"
+
+.IX Item "\(bu"
+
+.IX Subsection "Counter Wraps"
+
+.IX Subsection "Data Resampling"
+
+.IX Header "WRAPUP"
+
+.IX Header "MAILINGLIST"
+
+.IX Header "SEE ALSO"
+
+.IX Header "AUTHOR"
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDs.3
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDs.3 (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDs.3 Sat Jul 13 18:46:14 2002
@@ -0,0 +1,290 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+''' \*(L" and \*(R", except that they are used on ".xx" lines,
+''' such as .IP and .SH, which do another additional levels of
+''' double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH RRDs 3 "19990512.01" "12/May/99" "rrdtool"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+RRDs \- Access rrdtool as a shared module
+.SH "SYNOPSIS"
+.PP
+.Vb 8
+\& use RRDs::ext
+\& RRDs::error
+\& RRDs::last ...
+\& RRDs::create ...
+\& RRDs::update ...
+\& RRDs::graph ...
+\& RRDs::fetch ...
+\& RRDs::tune ...
+.Ve
+.SH "DESCRIPTION"
+.Sh "Calling Sequence"
+This module accesses rrdtool functionality directly from within perl. The
+arguments to the functions listed in the \s-1SYNOPSIS\s0 are explained in the regular
+rrdtool documentation. The commandline call
+.PP
+.Vb 1
+\& rrdtool update mydemo.rrd N:12:13
+.Ve
+gets turned into
+.PP
+.Vb 1
+\& RRDs::update qw(mydemo.rrd N:12:13);
+.Ve
+.Sh "Error Handling"
+The \s-1RRD\s0 functions will not abort your program even when they can not make
+sense out of the arguments you fed them. There are two ways to determine if
+an error has occured.
+.PP
+First the every function will return the value \-1 if an error occured.
+Second, the function RRDs::error can be called to get the error message
+from the last function call. If RRDs::error does not return an error
+then the previous function has completed its task succesfully.
+.PP
+.Vb 3
+\& RRDs::update qw(mydemo.rrd N:12:13);
+\& my $ERR=RRDs::error;
+\& die "ERROR while updating mydemo.rrd: $ERR\en" if $ERR;
+.Ve
+.Sh "Return Values"
+The functions RRDs::last, RRDs::graph and RRDs::fetchgive return their
+findigs.
+.PP
+RRDs::last returns a single \s-1INTEGER\s0 representing the last update time.
+.PP
+.Vb 1
+\& $lastupdate = RRDs::last ...
+.Ve
+RRDs::graph returns an pointer to an \s-1ARRAY\s0 containing the x-size and y-size of the
+created gif and results of the \s-1PRINT\s0 arguments.
+.PP
+.Vb 3
+\& ($averages,$xsize,$ysize) = RRDs::graph ...
+\& print "Gifsize: ${xsize}x${ysize}\en";
+\& print "Averages: ", (join ", ", @averages);
+.Ve
+RRDs::fetch is the most complex of the pack regarding return values. There are
+4 values. Two normal integers, a pointer to an array and a pointer to a
+array of pointers.
+.PP
+.Vb 13
+\& my ($start,$step,$names,$data) = RRDs::fetch ...
+\& print "Start: ".localtime($start)."\en";
+\& print "Stepsize: $step seconds\en";
+\& print "Column Names: ".join (", ", @$names)."\en";
+\& print "Date:\en";
+\& foreach my $line (@$array){
+\& print "".localtime($start)," ";
+\& $start += $step;
+\& foreach my $val (@$line) {
+\& printf "%12.1f", $val;
+\& }
+\& print "\en";
+\& }
+.Ve
+See the examples directory for more ways to use this extension.
+.SH "AUTHOR"
+Tobias Oetiker <oeitker at ee.ethy.ch>
+
+.rn }` ''
+.IX Title "RRDs 3"
+.IX Name "RRDs - Access rrdtool as a shared module"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Subsection "Calling Sequence"
+
+.IX Subsection "Error Handling"
+
+.IX Subsection "Return Values"
+
+.IX Header "AUTHOR"
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.pod
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.pod (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdupdate.pod Sat Jul 13 18:46:14 2002
@@ -0,0 +1,73 @@
+=head1 NAME
+
+rrdtool update - Store a new set of values into the rrd
+
+=head1 SYNOPSIS
+
+B<rrdtool> B<update> I<filename>
+S<[B<--template>|B<-t> I<ds-name>[B<:>I<ds-name>]...]>
+S<B<N>|I<timestamp>B<:>I<value>[B<:>I<value>...]>
+S<[I<timestamp>B<:>I<value>[B<:>I<value>...] ...]>
+
+=head1 DESCRIPTION
+
+The B<update> function feeds new data values into an B<RRD>. The
+data gets time aligned according to the properties of the B<RRD> to
+which the data is written.
+
+=over 8
+
+=item I<filename>
+
+The name of the B<RRD> you want to update.
+
+=item B<--template>|B<-t> I<ds-name>[B<:>I<ds-name>]...
+
+by default, the update function expects the data input in the order,
+the data sources are defined in the RRD. This is not very error
+resistant, as you might be sending the wrong data into a RRD.
+
+The template switch alows you to specify which data sources you are
+going to update and in which order. If the datasources specified in
+the template are not available in the rrd file, the update process
+will abort with an error message.
+
+=item B<N>|I<timestamp>B<:>I<value>[B<:>I<value>...]
+
+The data used for updating the RRD was acquired at a certain time. This
+time can either be defined in seconds since 1970-01-01. Or by using the
+letter 'N' the update time is set to be the current time. Negative time
+values are subtracted from the current time.
+Getting the timing right to the second is especially
+important when you are working with data-sources of type B<COUNTER>,
+B<DERIVE> or B<ABSOLUTE>.
+
+The remaining elements of the argument are DS updates. The order of this list is
+the same as the order the datasources were defined in the rra.
+If there is no data for a certain data-source, the letter
+B<U> (eg. N:0.1:U:1) can be defined.
+
+The format of the value acquired from the datasource is dependent of the
+datasource type chosen. Normally it will be numeric, but the data acquisition
+modules my impose their very own parsing of this parameter as long as the colon
+(B<:>) remains the datasource value separator.
+
+=back
+
+=head1 EXAMPLE
+
+C<rrdtool update demo1.rrd N:3.44:3.15:U:23>
+
+Update the database file demo1.rrd with 3 known and one I<*UNKNOWN*>
+value. Use the current time as the update time.
+
+C<rrdtool update demo2.rrd 887457267:U 887457521:22 88745790:2.7>
+
+Update the database file demo2.rrd which expects data from a single
+data-source, three times. First with an I<*UNKNOWN*> value then with two
+normal readings. The update interval seems to be around 300 seconds.
+
+=head1 AUTHOR
+
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.1
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.1 (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrddump.1 Sat Jul 13 18:46:14 2002
@@ -0,0 +1,220 @@
+.rn '' }`
+''' $RCSfile$$Revision$$Date$
+'''
+''' $Log$
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.ie n \{\
+.ds -- \(*W-
+.ds PI pi
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of
+''' \*(L" and \*(R", except that they are used on ".xx" lines,
+''' such as .IP and .SH, which do another additional levels of
+''' double-quote interpretation
+.ds M" """
+.ds S" """
+.ds N" """""
+.ds T" """""
+.ds L' '
+.ds R' '
+.ds M' '
+.ds S' '
+.ds N' '
+.ds T' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds M" ``
+.ds S" ''
+.ds N" ``
+.ds T" ''
+.ds L' `
+.ds R' '
+.ds M' `
+.ds S' '
+.ds N' `
+.ds T' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH RRDDUMP 1 "19990426.22" "29/Mar/98" "rrdtool"
+.UC
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+rrdtool dump \- dump the contents of an \fBRRD\fR in human readable form
+.SH "SYNOPSIS"
+\fBrrdtool\fR \fBdump\fR \fIfilename\fR [\fB--full\fR|\fB\-f\fR]
+.SH "DESCRIPTION"
+The \fBdump\fR function prints the contents of an \fBRRD\fR in human
+readable form.
+.Ip "\fIfilename\fR" 8
+The name of the \fB\s-1RRD\s0\fR you want to dump.
+.Ip "\fB--full\fR|\fB\-f\fR " 8
+By default only the headers of the \fB\s-1RRD\s0\fR are printed. With this
+option you get the actual data as well.
+.SH "AUTHOR"
+Tobias Oetiker <oetiker at ee.ethz.ch>
+
+.rn }` ''
+.IX Title "RRDDUMP 1"
+.IX Name "rrdtool dump - dump the contents of an B<RRD> in human readable form"
+
+.IX Header "NAME"
+
+.IX Header "SYNOPSIS"
+
+.IX Header "DESCRIPTION"
+
+.IX Item "\fIfilename\fR"
+
+.IX Item "\fB--full\fR|\fB\-f\fR "
+
+.IX Header "AUTHOR"
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDs.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDs.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/RRDs.html Sat Jul 13 18:46:15 2002
@@ -0,0 +1,192 @@
+ <HTML>
+ <HEAD>
+ <TITLE>RRDs - Access rrdtool as a shared module
+
+</TITLE>
+ </HEAD>
+
+ <BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+ <LI><A HREF="#NAME">NAME</A>
+ <LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+ <LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+ <UL>
+
+ <LI><A HREF="#Calling_Sequence">Calling Sequence</A>
+ <LI><A HREF="#Error_Handling">Error Handling</A>
+ <LI><A HREF="#Return_Values">Return Values</A>
+ </UL>
+
+ <LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME
+
+</A></H1>
+RRDs - Access rrdtool as a shared module
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS
+
+</A></H1>
+<PRE> use RRDs::ext
+ RRDs::error
+ RRDs::last ...
+ RRDs::create ...
+ RRDs::update ...
+ RRDs::graph ...
+ RRDs::fetch ...
+ RRDs::tune ...
+</PRE>
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION
+
+</A></H1>
+<P>
+<HR>
+<H2><A NAME="Calling_Sequence">Calling Sequence
+
+</A></H2>
+This module accesses rrdtool functionality directly from within perl. The
+arguments to the functions listed in the SYNOPSIS are explained in the
+regular rrdtool documentation. The commandline call
+
+
+<P>
+
+<PRE> rrdtool update mydemo.rrd N:12:13
+</PRE>
+
+<P>
+
+gets turned into
+
+
+<P>
+
+<PRE> RRDs::update qw(mydemo.rrd N:12:13);
+</PRE>
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="Error_Handling">Error Handling
+
+</A></H2>
+The RRD functions will not abort your program even when they can not make
+sense out of the arguments you fed them. There are two ways to determine if
+an error has occured.
+
+
+<P>
+
+First the every function will return the value -1 if an error occured.
+Second, the function RRDs::error can be called to get the error message
+from the last function call. If RRDs::error does not return an error then
+the previous function has completed its task succesfully.
+
+
+<P>
+
+<PRE> RRDs::update qw(mydemo.rrd N:12:13);
+ my $ERR=RRDs::error;
+ die "ERROR while updating mydemo.rrd: $ERR\n" if $ERR;
+</PRE>
+
+<P>
+
+<P>
+<HR>
+<H2><A NAME="Return_Values">Return Values
+
+</A></H2>
+The functions RRDs::last, RRDs::graph and RRDs::fetchgive return their
+findigs.
+
+
+<P>
+
+RRDs::last returns a single INTEGER representing the last update time.
+
+
+<P>
+
+<PRE> $lastupdate = RRDs::last ...
+</PRE>
+
+<P>
+
+RRDs::graph returns an pointer to an ARRAY containing the x-size and y-size
+of the created gif and results of the PRINT arguments.
+
+
+<P>
+
+<PRE> ($averages,$xsize,$ysize) = RRDs::graph ...
+ print "Gifsize: ${xsize}x${ysize}\n";
+ print "Averages: ", (join ", ", @averages);
+</PRE>
+
+<P>
+
+RRDs::fetch is the most complex of the pack regarding return values. There
+are 4 values. Two normal integers, a pointer to an array and a pointer to a
+array of pointers.
+
+
+<P>
+
+<PRE> my ($start,$step,$names,$data) = RRDs::fetch ...
+ print "Start: ".localtime($start)."\n";
+ print "Stepsize: $step seconds\n";
+ print "Column Names: ".join (", ", @$names)."\n";
+ print "Date:\n";
+ foreach my $line (@$array){
+ print "".localtime($start)," ";
+ $start += $step;
+ foreach my $val (@$line) {
+ printf "%12.1f", $val;
+ }
+ print "\n";
+ }
+</PRE>
+
+<P>
+
+See the examples directory for more ways to use this extension.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR
+
+</A></H1>
+Tobias Oetiker <A
+HREF="MAILTO:<oeitker at ee.ethy.ch>"><oeitker at ee.ethy.ch></A>
+
+
+<P>
+
+</DL>
+ </BODY>
+
+ </HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/doc/rrdcreate.html Sat Jul 13 18:46:15 2002
@@ -0,0 +1,217 @@
+ <HTML>
+ <HEAD>
+ <TITLE>create - Set up a new Round Robin Database
+
+</TITLE>
+ </HEAD>
+
+ <BODY>
+
+<!-- INDEX BEGIN -->
+<!--
+
+<UL>
+
+ <LI><A HREF="#NAME">NAME</A>
+ <LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
+ <LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
+ <LI><A HREF="#EXAMPLE">EXAMPLE</A>
+ <LI><A HREF="#AUTHOR">AUTHOR</A>
+</UL>
+-->
+<!-- INDEX END -->
+
+<P>
+<H1><A NAME="NAME">NAME
+
+</A></H1>
+rrdtool create - Set up a new Round Robin Database
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="SYNOPSIS">SYNOPSIS
+
+</A></H1>
+<STRONG>rrdtool</STRONG> <STRONG>create</STRONG> <EM>filename</EM>
+
+[<STRONG>--start</STRONG>|<STRONG>-b</STRONG> <EM>start time</EM>]
+
+[<STRONG>--step</STRONG>|<STRONG>-s</STRONG> <EM>step</EM>]
+
+[<STRONG>DS:</STRONG><EM>ds-name</EM><STRONG>:</STRONG><EM>DST</EM><STRONG>:</STRONG><EM>heartbeat</EM><STRONG>:</STRONG><EM>min</EM><STRONG>:</STRONG><EM>max</EM>]
+
+[<STRONG>RRA:</STRONG><EM>CF</EM><STRONG>:</STRONG><EM>xff</EM><STRONG>:</STRONG><EM>steps</EM><STRONG>:</STRONG><EM>rows</EM>]
+
+
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="DESCRIPTION">DESCRIPTION
+
+</A></H1>
+The create function of the rrd tool lets you set up new Round Robin
+Database (<STRONG>RRD</STRONG>) files. The file is created at its final, full size and filled with <EM>*UNKNOWN*</EM> data.
+
+
+<P>
+
+<DL>
+<DT><STRONG><A NAME="item_filename">filename
+
+</A></STRONG><DD>
+The name of the <STRONG>RRD</STRONG> you want to create. <STRONG>RRD</STRONG> files should end with the extension <EM>.rrd</EM>. However, <STRONG>rrdtool</STRONG> will accept any filename.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__start_b">--start|-b start time (default: current time)
+
+</A></STRONG><DD>
+Specifies the time in seconds since 1970-01-01 UTC when the first value
+should be added to the <STRONG>RRD</STRONG>. <STRONG>rrdtool</STRONG> will not accept any data timed before or at the time specified.
+
+
+<P>
+
+Negative input is treated as current time minus the specified number of
+seconds. See also AT-STYLE TIME SPECIFICATION section in the
+<EM>rrdfetch</EM> documentation for alternative ways to specify time.
+
+
+<P>
+
+<DT><STRONG><A NAME="item__step_s">--step|-s step (default: 300 seconds)
+
+</A></STRONG><DD>
+Specifies the base interval in seconds with which data will be fed into the <STRONG>RRD</STRONG>.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_DS">DS:ds-name:DST:heartbeat:min:max
+
+</A></STRONG><DD>
+A single <STRONG>RRD</STRONG> can accept input from several data sources (<STRONG>DS</STRONG>). (e.g. Incoming and Outgoing traffic on a specific communication line).
+With the <STRONG>DS</STRONG> configuration option you must define some basic properties of each data
+source you want to use to feed the <STRONG>RRD</STRONG>.
+
+
+<P>
+
+<EM>ds-name</EM> is the name you will use to reference this particular data source from an <STRONG>RRD</STRONG>. A <EM>ds-name</EM> must be 1 to 19 characters long in the characters [a-zA-Z0-9_].
+
+
+<P>
+
+<EM>DST</EM> defines the Data Source Type. It can be one of the following:
+<STRONG>GAUGE</STRONG> this is for things like temperatures or number of people in a room. <STRONG>COUNTER</STRONG> is for continuous incrementing counters like the InOctets counter in a
+router. The <STRONG>COUNTER</STRONG> data source assumes that the counter never decreases, except when a counter
+overflows. The update function takes the overflow into account. The counter
+is stored as a per-second rate. <STRONG>DERIVE</STRONG> will store the the derivative of the line going from the last to the
+current value of the data source. This can be useful for gauges, for
+example, to measure the rate of people entering or leaving a room. <STRONG>ABSOLUTE</STRONG> is for counters which get reset upon reading.
+
+
+<P>
+
+<EM>heartbeat</EM> defines the maximum number of seconds that may pass between two updates of
+this data source before the value of the data source is assumed to be <EM>*UNKNOWN*</EM>.
+
+
+<P>
+
+<EM>min</EM> and <EM>max</EM> are optional entries defining the expected range of the data supplied by
+this data source. If <EM>min</EM> and/or <EM>max</EM> are defined, any value outside the defined range will be regarded as
+<EM>*UNKNOWN*</EM>. If you do not know or care about min and max, set them to U for unknown.
+Note that min and max always refere to the processed values of the DS. For
+a traffic-<STRONG>COUNTER</STRONG> type DS this would be the max and min data-rate expected from the device.
+
+
+<P>
+
+<DT><STRONG><A NAME="item_RRA">RRA:CF:xff:steps:rows
+
+</A></STRONG><DD>
+The purpose of an <STRONG>RRD</STRONG> is to store data in the round robin archives (<STRONG>RRA</STRONG>). An archive consists of a number of data values from all the defined
+data-sources (<STRONG>DS</STRONG>) and is defined with an <STRONG>RRA</STRONG> line.
+
+
+<P>
+
+When data is entered into an <STRONG>RRD</STRONG>, it is first fit into time slots of the length defined with the <STRONG>-s</STRONG> option becoming a <EM>primary data point</EM>.
+
+
+<P>
+
+The data is also consolidated with the consolidation function (<EM>CF</EM>) of the archive. The following consolidation functions are defined:
+<STRONG>AVERAGE</STRONG>, <STRONG>MIN</STRONG>, <STRONG>MAX</STRONG>, <STRONG>LAST</STRONG>.
+
+
+<P>
+
+<EM>xff</EM> The xfiles factor defines what part of a consolidation interval may be made
+up from <EM>*UNKNOWN*</EM> data while the consolidated value is sill regarded as known.
+
+
+<P>
+
+<EM>steps</EM> defines how many of these <EM>primary data points</EM> are used to build a <EM>consolidated data point</EM> which then goes into the archive.
+
+
+<P>
+
+<EM>rows</EM> defines how many generations of data values are kept in an <STRONG>RRA</STRONG>.
+
+
+<P>
+
+</DL>
+<P>
+<HR>
+<H1><A NAME="EXAMPLE">EXAMPLE
+
+</A></H1>
+<CODE>rrdtool create temperature.rrd --step 300 DS:temp:GAUGE:600:-273:5000
+RRA:AVERAGE:0.5:1:1200 RRA:MIN:0.5:12:2400 RRA:MAX:0.5:12:2400
+RRA:AVERAGE:0.5:12:2400</CODE>
+
+
+
+
+<P>
+
+This sets up an <STRONG>RRD</STRONG> called <EM>temperature.rrd</EM> which accepts one temperature value every 300 seconds. If no new data is
+supplied for more than 600 seconds, the temperature becomes <EM>*UNKNOWN*</EM>. The minimum acceptable value is -273 and the maximum is 5000.
+
+
+<P>
+
+A few archives areas are also defined. The first stores the temperatures
+supplied for 100 hours (1200 * 300 seconds = 100 hours). The second RRA
+stores the minimum temperature recorded over every hour (12 * 300 seconds =
+1 hour), for 100 days (2400 hours). The third and the fourth RRA's do the
+same with the for the maximum and average temperature, respectively.
+
+
+<P>
+
+<P>
+<HR>
+<H1><A NAME="AUTHOR">AUTHOR
+
+</A></H1>
+Tobias Oetiker <A
+HREF="MAILTO:<oetiker at ee.ethz.ch>"><oetiker at ee.ethz.ch></A>
+
+<P>
+
+</DL>
+ </BODY>
+
+ </HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/t/base.t
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/t/base.t (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/t/base.t Sat Jul 13 18:46:15 2002
@@ -0,0 +1,161 @@
+#! /usr/bin/perl
+
+BEGIN { $| = 1; print "1..5\n"; }
+END {
+ print "not ok 1\n" unless $loaded;
+ unlink "demo.rrd";
+}
+
+sub ok
+{
+ my($what, $result) = @_ ;
+ $ok_count++;
+ print "not " unless $result;
+ print "ok $ok_count $what\n";
+}
+
+use strict;
+use vars qw(@ISA $loaded);
+
+use RRDs;
+$loaded = 1;
+my $ok_count = 1;
+
+ok("loading",1);
+
+######################### End of black magic.
+
+my $STEP = 100;
+my $RUNS = 500;
+my $GRUNS = 4;
+my $RRD1 = "demo1.rrd";
+my $RRD2 = "demo2.rrd";
+my $GIF1 = "demo1.gif";
+my $GIF2 = "demo2.gif";
+my $time = 30*int(time/30);
+my $START = $time-$RUNS*$STEP;
+
+my @options = ("-b", $START, "-s", $STEP,
+ "DS:a:GAUGE:2000:U:U",
+ "DS:b:GAUGE:200:U:U",
+ "DS:c:GAUGE:200:U:U",
+ "DS:d:GAUGE:200:U:U",
+ "DS:e:DERIVE:200:U:U",
+ "RRA:AVERAGE:0.5:1:5000",
+ "RRA:AVERAGE:0.5:10:500");
+
+print "* Creating RRD $RRD1 starting at $time.\n\n";
+RRDs::create $RRD1, @options;
+
+my $ERROR = RRDs::error;
+ok("create", !$ERROR); # 2
+if ($ERROR) {
+ die "$0: unable to create `$RRD1': $ERROR\n";
+}
+
+print "* Creating RRD $RRD2 starting at $time.\n\n";
+RRDs::create $RRD2, @options;
+
+$ERROR= RRDs::error;
+ok("creat",!$ERROR); # 3
+if ($ERROR) {
+ die "$0: unable to create `$RRD2': $ERROR\n";
+}
+
+my $last = RRDs::last $RRD1;
+if ($ERROR = RRDs::error) {
+ die "$0: unable to get last `$RRD1': $ERROR\n";
+}
+ok("last", $last == $START); # 4
+
+$last = RRDs::last $RRD2;
+if ($ERROR = RRDs::error) {
+ die "$0: unable to get last `$RRD2': $ERROR\n";
+}
+ok("last 2", $last == $START); # 5
+
+print "* Filling $RRD1 and $RRD2 with $RUNS*5 values. One moment please ...\n";
+print "* If you are running over NFS this will take *MUCH* longer\n\n";
+
+srand(int($time / 100));
+
+ at options = ();
+
+my $counter = 1e7;
+for (my $t=$START+1;
+ $t<$START+$STEP*$RUNS;
+ $t+=$STEP+int((rand()-0.5)*7)){
+ $counter += 2500*sin($t/2000)*$STEP;
+ my $data = (1000+500*sin($t/1000)).":".
+ (1000+900*sin($t/2330)).":".
+ (2000*cos($t/1550)).":".
+ (3220*sin($t/3420)).":$counter";
+ push(@options, "$t:$data");
+ RRDs::update $RRD1, "$t:$data";
+ if ($ERROR = RRDs::error) {
+ die "$0: unable to update `$RRD1': $ERROR\n";
+ }
+}
+
+RRDs::update $RRD2, @options;
+
+if ($ERROR = RRDs::error) {
+ die "$0: unable to update `$RRD2': $ERROR\n";
+}
+
+print "* Creating $GRUNS graphs: $GIF1 & $GIF2\n\n";
+my $now = $time;
+for (my $i=0;$i<$GRUNS;$i++) {
+ my @rrd_gifs = ($RRD1, $GIF1, $RRD2, $GIF2);
+ while (@rrd_gifs) {
+ my $RRD = shift(@rrd_gifs);
+ my $GIF = shift(@rrd_gifs);
+ my ($graphret,$xs,$ys) = RRDs::graph $GIF, "--title", 'Test GRAPH',
+ "--vertical-label", 'Dummy Units', "--start", (-$RUNS*$STEP),
+ "DEF:alpha=$RRD:a:AVERAGE",
+ "DEF:beta=$RRD:b:AVERAGE",
+ "DEF:gamma=$RRD:c:AVERAGE",
+ "DEF:delta=$RRD:d:AVERAGE",
+ "DEF:epsilon=$RRD:e:AVERAGE",
+ "CDEF:calc=alpha,beta,+,2,/",
+ "AREA:alpha#0022e9:Short",
+ "STACK:beta#00b871:Demo Text",
+ "LINE1:gamma#ff0000:Line 1",
+ "LINE2:delta#888800:Line 2",
+ "LINE3:calc#00ff44:Line 3",
+ "LINE3:epsilon#000000:Line 4",
+ "HRULE:1500#ff8800:Horizontal Line at 1500",
+ "PRINT:alpha:AVERAGE:Average Alpha %1.2f",
+ "PRINT:alpha:MIN:Min Alpha %1.2f",
+ "PRINT:alpha:MAX:Max Alpha %1.2f",
+ "GPRINT:calc:AVERAGE:Average calc %1.2f",
+ "GPRINT:calc:MAX:Max calc %1.2f",
+ "GPRINT:calc:MIN:Min calc %1.2f",
+ "VRULE:".($now-3600)."#008877:60 Minutes ago",
+ "VRULE:".($now-7200)."#008877:120 Minutes ago";
+
+ if ($ERROR = RRDs::error) {
+ print "ERROR: $ERROR\n";
+ } else {
+ print "GIF Size: ${xs}x${ys}\n";
+ print "Graph Return:\n",(join "\n", @$graphret),"\n\n";
+ }
+ }
+}
+
+
+
+my ($start,$step,$names,$array) = RRDs::fetch $RRD1, "AVERAGE";
+$ERROR = RRDs::error;
+print "ERROR: $ERROR\n" if $ERROR ;
+print "start=$start, step=$step\n";
+print " ";
+map {printf("%12s",$_)} @$names ;
+foreach my $line (@$array){
+ print "".localtime($start)," ";
+ $start += $step;
+ foreach my $val (@$line) {
+ printf "%12.1f", $val;
+ }
+ print "\n";
+}
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/RRDs.xs
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/RRDs.xs (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/RRDs.xs Sat Jul 13 18:46:15 2002
@@ -0,0 +1,174 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "../src/rrd_tool.h"
+
+#define rrdcode(name) \
+ argv = (char **) malloc((items+1)*sizeof(char *));\
+ argv[0] = "dummy";\
+ for (i = 0; i < items; i++) argv[i+1] = (char *) SvPV(ST(i),na);\
+ optind=0; opterr=0; \
+ rrd_clear_error();\
+ RETVAL=name(items+1,argv); free(argv);\
+ if (rrd_get_error() != NULL) XSRETURN_UNDEF;
+
+
+#ifdef WIN32
+ #define free free
+ #define malloc malloc
+ #define realloc realloc
+#endif /*WIN32*/
+
+
+MODULE = RRDs PACKAGE = RRDs PREFIX = rrd_
+
+SV*
+rrd_error()
+ CODE:
+ if (! rrd_test_error()) XSRETURN_UNDEF;
+ RETVAL = newSVpv(rrd_get_error(),0);
+ OUTPUT:
+ RETVAL
+
+
+int
+rrd_last(...)
+ PROTOTYPE: @
+ PREINIT:
+ int i;
+ char **argv;
+ CODE:
+ rrdcode(rrd_last);
+ OUTPUT:
+ RETVAL
+
+
+int
+rrd_create(...)
+ PROTOTYPE: @
+ PREINIT:
+ int i;
+ char **argv;
+ CODE:
+ rrdcode(rrd_create);
+ RETVAL = 1;
+ OUTPUT:
+ RETVAL
+
+
+int
+rrd_update(...)
+ PROTOTYPE: @
+ PREINIT:
+ int i;
+ char **argv;
+ CODE:
+ rrdcode(rrd_update);
+ RETVAL = 1;
+ OUTPUT:
+ RETVAL
+
+
+void
+rrd_graph(...)
+ PROTOTYPE: @
+ PREINIT:
+ char **calcpr;
+ int i,xsize,ysize;
+ char **argv;
+ AV *retar;
+ PPCODE:
+ calcpr = NULL;
+ argv = (char **) malloc((items+1)*sizeof(char *));
+ argv[0] = "dummy";
+ for (i = 0; i < items; i++) argv[i+1] = (char *) SvPV(ST(i),na);
+ optind=0; opterr=0;
+ rrd_clear_error();
+ rrd_graph(items+1,argv,&calcpr,&xsize,&ysize); free(argv);
+
+ if (rrd_test_error()) {
+ if(calcpr)
+ for(i=0;calcpr[i];i++)
+ free(calcpr[i]);
+ XSRETURN_UNDEF;
+ }
+ retar=newAV();
+ if(calcpr){
+ for(i=0;calcpr[i];i++){
+ av_push(retar,newSVpv(calcpr[i],0));
+ free(calcpr[i]);
+ }
+ free(calcpr);
+ }
+ EXTEND(sp,4);
+ PUSHs(sv_2mortal(newRV_inc((SV*)retar)));
+ PUSHs(sv_2mortal(newSViv(xsize)));
+ PUSHs(sv_2mortal(newSViv(ysize)));
+
+void
+rrd_fetch(...)
+ PROTOTYPE: @
+ PREINIT:
+ time_t start,end;
+ unsigned long step, ds_cnt,i,ii;
+ rrd_value_t *data,*datai;
+ char **argv;
+ char **ds_namv;
+ AV *retar,*line,*names;
+ PPCODE:
+ argv = (char **) malloc((items+1)*sizeof(char *));
+ argv[0] = "dummy";
+ for (i = 0; i < items; i++) argv[i+1] = (char *) SvPV(ST(i),na);
+ optind=0; opterr=0;
+ rrd_clear_error();
+ rrd_fetch(items+1,argv,&start,&end,&step,&ds_cnt,&ds_namv,&data);
+ if (rrd_test_error()) XSRETURN_UNDEF;
+ free(argv);
+ /* convert the ds_namv into perl format */
+ names=newAV();
+ for (ii = 0; ii < ds_cnt; ii++){
+ av_push(names,newSVpv(ds_namv[ii],0));
+ free(ds_namv[ii]);
+ }
+ free(ds_namv);
+ /* convert the data array into perl format */
+ datai=data;
+ retar=newAV();
+ for (i = start; i <= end; i += step){
+ line = newAV();
+ for (ii = 0; ii < ds_cnt; ii++)
+ av_push(line,newSVnv(*(datai++)));
+ av_push(retar,newRV_noinc((SV*)line));
+ }
+ free(data);
+ EXTEND(sp,5);
+ PUSHs(sv_2mortal(newSViv(start)));
+ PUSHs(sv_2mortal(newSViv(step)));
+ PUSHs(sv_2mortal(newRV_inc((SV*)names)));
+ PUSHs(sv_2mortal(newRV_inc((SV*)retar)));
+
+int
+rrd_tune(...)
+ PROTOTYPE: @
+ PREINIT:
+ int i;
+ char **argv;
+ CODE:
+ rrdcode(rrd_tune);
+ RETVAL = 1;
+ OUTPUT:
+ RETVAL
+
+
+
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/RRDs.pm
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/RRDs.pm (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/RRDs.pm Sat Jul 13 18:46:15 2002
@@ -0,0 +1,101 @@
+package RRDs;
+
+use strict;
+use vars qw(@ISA $VERSION);
+
+ at ISA = qw(DynaLoader);
+
+require DynaLoader;
+
+$VERSION = 0.99029 ;
+
+bootstrap RRDs $VERSION;
+
+1;
+__END__
+
+=head1 NAME
+
+RRDs - Access rrdtool as a shared module
+
+=head1 SYNOPSIS
+
+ use RRDs::ext
+ RRDs::error
+ RRDs::last ...
+ RRDs::create ...
+ RRDs::update ...
+ RRDs::graph ...
+ RRDs::fetch ...
+ RRDs::tune ...
+
+=head1 DESCRIPTION
+
+=head2 Calling Sequence
+
+This module accesses rrdtool functionality directly from within perl. The
+arguments to the functions listed in the SYNOPSIS are explained in the regular
+rrdtool documentation. The commandline call
+
+ rrdtool update mydemo.rrd N:12:13
+
+gets turned into
+
+ RRDs::update qw(mydemo.rrd N:12:13);
+
+=head2 Error Handling
+
+The RRD functions will not abort your program even when they can not make
+sense out of the arguments you fed them. There are two ways to determine if
+an error has occured.
+
+First the every function will return the value -1 if an error occured.
+Second, the function RRDs::error can be called to get the error message
+from the last function call. If RRDs::error does not return an error
+then the previous function has completed its task succesfully.
+
+ RRDs::update qw(mydemo.rrd N:12:13);
+ my $ERR=RRDs::error;
+ die "ERROR while updating mydemo.rrd: $ERR\n" if $ERR;
+
+=head2 Return Values
+
+The functions RRDs::last, RRDs::graph and RRDs::fetchgive return their
+findigs.
+
+RRDs::last returns a single INTEGER representing the last update time.
+
+ $lastupdate = RRDs::last ...
+
+RRDs::graph returns an pointer to an ARRAY containing the x-size and y-size of the
+created gif and results of the PRINT arguments.
+
+ ($averages,$xsize,$ysize) = RRDs::graph ...
+ print "Gifsize: ${xsize}x${ysize}\n";
+ print "Averages: ", (join ", ", @averages);
+
+RRDs::fetch is the most complex of the pack regarding return values. There are
+4 values. Two normal integers, a pointer to an array and a pointer to a
+array of pointers.
+
+ my ($start,$step,$names,$data) = RRDs::fetch ...
+ print "Start: ".localtime($start)."\n";
+ print "Stepsize: $step seconds\n";
+ print "Column Names: ".join (", ", @$names)."\n";
+ print "Date:\n";
+ foreach my $line (@$array){
+ print "".localtime($start)," ";
+ $start += $step;
+ foreach my $val (@$line) {
+ printf "%12.1f", $val;
+ }
+ print "\n";
+ }
+
+See the examples directory for more ways to use this extension.
+
+=head1 AUTHOR
+
+Tobias Oetiker <oeitker at ee.ethy.ch>
+
+=cut
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/MANIFEST
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/MANIFEST (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/MANIFEST Sat Jul 13 18:46:15 2002
@@ -0,0 +1,6 @@
+MANIFEST
+README
+Makefile.PL
+RRDs.pm
+RRDs.xs
+t/base.t
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/Makefile.PL
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/Makefile.PL (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/Makefile.PL Sat Jul 13 18:46:16 2002
@@ -0,0 +1,13 @@
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+ 'NAME' => 'RRDs',
+ 'VERSION_FROM' => 'RRDs.pm', # finds $VERSION
+ 'OPTIMIZE' => '-g',
+ 'INC' => '-I../src/',
+ # where to look for the necessary libraries
+ # Perl will figure out which one is valid
+ 'LIBS' => [ '-L../src -lrrd -L../gd1.2 -lgd -lm' ],
+ 'realclean' => {FILES => 't/demo?.rrd t/demo?.gif' }
+);
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/README
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/README (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/README Sat Jul 13 18:46:16 2002
@@ -0,0 +1,12 @@
+These are the Perl bindings for rrdtool as a shared library. To compile do
+the following:
+
+perl Makefile.PL
+make test
+
+(win32 users try perl ntmake.pl)
+
+* if dynamic linking does not work, try
+
+perl Makefile.PL LINKTYPE=static
+make test
Added: trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/examples/shared-demo.pl.in
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/examples/shared-demo.pl.in (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/perl-shared/examples/shared-demo.pl.in Sat Jul 13 18:46:16 2002
@@ -0,0 +1,169 @@
+#! @PERL@
+
+BEGIN { unshift @INC , "../blib/lib", "../blib/arch/auto/RRDs" }
+
+END {
+ print "not ok 1\n" unless $loaded;
+ unlink "demo.rrd";
+}
+
+sub ok
+{
+ my($what, $result) = @_ ;
+ $ok_count++;
+ print "not " unless $result;
+ print "ok $ok_count $what\n";
+}
+
+use strict;
+use vars qw(@ISA $loaded);
+
+use RRDs;
+$loaded = 1;
+my $ok_count = 1;
+
+ok("loading",1);
+
+######################### End of black magic.
+
+my $STEP = 100;
+my $RUNS = 500;
+my $GRUNS = 4;
+my $RRD1 = "demo1.rrd";
+my $RRD2 = "demo2.rrd";
+my $GIF1 = "demo1.gif";
+my $GIF2 = "demo2.gif";
+my $time = 30*int(time/30);
+my $START = $time-$RUNS*$STEP;
+
+my @options = ("-b", $START, "-s", $STEP,
+ "DS:a:GAUGE:2000:U:U",
+ "DS:b:GAUGE:200:U:U",
+ "DS:c:GAUGE:200:U:U",
+ "DS:d:GAUGE:200:U:U",
+ "DS:e:DERIVE:200:U:U",
+ "RRA:AVERAGE:0.5:1:5000",
+ "RRA:AVERAGE:0.5:10:500");
+
+print "* Creating RRD $RRD1 starting at $time.\n\n";
+RRDs::create $RRD1, @options;
+
+my $ERROR = RRDs::error;
+ok("create", !$ERROR); # 2
+if ($ERROR) {
+ die "$0: unable to create `$RRD1': $ERROR\n";
+}
+
+print "* Creating RRD $RRD2 starting at $time.\n\n";
+RRDs::create $RRD2, @options;
+
+$ERROR= RRDs::error;
+ok("creat",!$ERROR); # 3
+if ($ERROR) {
+ die "$0: unable to create `$RRD2': $ERROR\n";
+}
+
+my $last = RRDs::last $RRD1;
+if ($ERROR = RRDs::error) {
+ die "$0: unable to get last `$RRD1': $ERROR\n";
+}
+ok("last", $last == $START); # 4
+
+$last = RRDs::last $RRD2;
+if ($ERROR = RRDs::error) {
+ die "$0: unable to get last `$RRD2': $ERROR\n";
+}
+ok("last 2", $last == $START); # 5
+
+print "* Filling $RRD1 and $RRD2 with $RUNS*5 values. One moment please ...\n";
+print "* If you are running over NFS this will take *MUCH* longer\n\n";
+
+srand(int($time / 100));
+
+ at options = ();
+
+my $counter = 1e7;
+for (my $t=$START+1;
+ $t<$START+$STEP*$RUNS;
+ $t+=$STEP+int((rand()-0.5)*7)){
+ $counter += 2500*sin($t/2000)*$STEP;
+ my $data = (1000+500*sin($t/1000)).":".
+ (1000+900*sin($t/2330)).":".
+ (2000*cos($t/1550)).":".
+ (3220*sin($t/3420)).":$counter";
+ push(@options, "$t:$data");
+ RRDs::update $RRD1, "$t:$data";
+ if ($ERROR = RRDs::error) {
+ die "$0: unable to update `$RRD1': $ERROR\n";
+ }
+}
+
+RRDs::update $RRD2, @options;
+
+if ($ERROR = RRDs::error) {
+ die "$0: unable to update `$RRD2': $ERROR\n";
+}
+
+print "* Creating $GRUNS graphs: $GIF1 & $GIF2\n\n";
+my $now = $time;
+for (my $i=0;$i<$GRUNS;$i++) {
+ my @rrd_gifs = ($RRD1, $GIF1, $RRD2, $GIF2);
+ while (@rrd_gifs) {
+ my $RRD = shift(@rrd_gifs);
+ my $GIF = shift(@rrd_gifs);
+ my ($graphret,$xs,$ys) = RRDs::graph $GIF, "--title", 'Test GRAPH',
+ '--base', '1024',
+ "--vertical-label", 'Dummy Units', "--start", (-$RUNS*$STEP),
+ "--end", $time,
+ "DEF:alpha=$RRD:a:AVERAGE",
+ "DEF:beta=$RRD:b:AVERAGE",
+ "DEF:gamma=$RRD:c:AVERAGE",
+ "DEF:delta=$RRD:d:AVERAGE",
+ "DEF:epsilon=$RRD:e:AVERAGE",
+ "CDEF:calc=alpha,beta,+,2,/,100,*,102,/",
+ "AREA:alpha#0022e9:Short",
+ "STACK:beta#00b871:Demo Text",
+ "STACK:beta#0ad871:Demo Text 2",
+ "LINE1:gamma#ff0000:Line 1",
+ "LINE2:delta#888800:Line 2",
+ "LINE3:calc#00ff44:Line 3",
+ "LINE3:epsilon#000000:Line 4",
+ "HRULE:1500#ff8800:Horizontal Line at 1500",
+ "PRINT:alpha:AVERAGE:Average Alpha %1.2f",
+ "PRINT:alpha:MIN:Min Alpha %1.2f",
+ "PRINT:alpha:MAX:Max Alpha %1.2f",
+ "GPRINT:calc:AVERAGE:Average calc %1.2f",
+ "GPRINT:calc:MAX:Max calc %1.2f",
+ "GPRINT:calc:MIN:Min calc %1.2f",
+ "VRULE:".($now-3600)."#008877:60 Minutes ago",
+ "VRULE:".($now-7200)."#008877:120 Minutes ago";
+
+ if ($ERROR = RRDs::error) {
+ print "ERROR: $ERROR\n";
+ } else {
+ print "GIF Size: ${xs}x${ys}\n";
+ print "Graph Return:\n",(join "\n", @$graphret),"\n\n";
+ }
+ }
+}
+
+
+
+my ($start,$step,$names,$array) = RRDs::fetch $RRD1, "AVERAGE";
+$ERROR = RRDs::error;
+print "ERROR: $ERROR\n" if $ERROR ;
+print "start=$start, step=$step\n";
+print " ";
+map {printf("%12s",$_)} @$names ;
+print "\n";
+foreach my $line (@$array){
+ print "".localtime($start)," ";
+ $start += $step;
+ foreach my $val (@$line) {
+ printf "%12.1f", $val;
+ }
+ print "\n";
+}
+
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/MANIFEST
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/MANIFEST (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/MANIFEST Sat Jul 13 18:46:16 2002
@@ -0,0 +1,123 @@
+CHANGES
+CONTRIBUTORS
+COPYING
+COPYRIGHT
+MANIFEST
+Makefile.dist
+Makefile.in
+README
+TODO
+install-sh
+config.h.in
+configure
+configure.in
+contrib
+perl-shared/README
+perl-shared/Makefile.PL
+perl-shared/RRDs.pm
+perl-shared/RRDs.xs
+perl-shared/MANIFEST
+perl-shared/t/base.t
+perl-shared/examples/shared-demo.pl.in
+perl-piped/README
+perl-piped/Makefile.PL
+perl-piped/RRDp.pm
+perl-piped/MANIFEST
+perl-piped/t/base.t
+perl-piped/examples/piped-demo.pl.in
+doc/GNUmakefile.in
+doc/RRDp.3
+doc/RRDp.html
+doc/RRDs.3
+doc/RRDs.html
+doc/RRDp.html
+doc/RRDs.html
+doc/bin_dec_hex.1
+doc/bin_dec_hex.html
+doc/bin_dec_hex.pod
+doc/bin_dec_hex.txt
+doc/rrdcreate.1
+doc/rrdcreate.html
+doc/rrdcreate.pod
+doc/rrdcreate.txt
+doc/rrddump.1
+doc/rrddump.html
+doc/rrddump.pod
+doc/rrddump.txt
+doc/rrdfetch.1
+doc/rrdfetch.html
+doc/rrdfetch.pod
+doc/rrdfetch.txt
+doc/rrdgraph.1
+doc/rrdgraph.html
+doc/rrdgraph.pod
+doc/rrdgraph.txt
+doc/rrdintro.pod
+doc/rrdlast.1
+doc/rrdlast.html
+doc/rrdlast.pod
+doc/rrdlast.txt
+doc/rrdtool.1
+doc/rrdtool.html
+doc/rrdtool.pod
+doc/rrdtool.txt
+doc/rrdtune.1
+doc/rrdtune.html
+doc/rrdtune.pod
+doc/rrdtune.txt
+doc/rrdtutorial.1
+doc/rrdtutorial.html
+doc/rrdtutorial.pod
+doc/rrdtutorial.txt
+doc/rrdupdate.1
+doc/rrdupdate.html
+doc/rrdupdate.pod
+doc/rrdupdate.txt
+gd1.2/Makefile.in
+gd1.2/README
+gd1.2/demoin.gif
+gd1.2/gd.c
+gd1.2/gd.dsp
+gd1.2/gd.dsw
+gd1.2/gd.h
+gd1.2/gddemo.c
+gd1.2/gdfontg.c
+gd1.2/gdfontg.h
+gd1.2/gdfontl.c
+gd1.2/gdfontl.h
+gd1.2/gdfontmb.c
+gd1.2/gdfontmb.h
+gd1.2/gdfonts.c
+gd1.2/gdfonts.h
+gd1.2/gdfontt.c
+gd1.2/gdfontt.h
+gd1.2/giftogd.c
+gd1.2/index.html
+gd1.2/mathmake.c
+gd1.2/mtables.c
+gd1.2/webgif.c
+src/Makefile.in
+src/rrd_diff.c
+src/getopt.c
+src/getopt.h
+src/getopt1.c
+src/ntconfig.h
+src/rrd.dsp
+src/rrd.dsw
+src/rrd_create.c
+src/rrd_dump.c
+src/rrd_error.c
+src/rrd_fetch.c
+src/rrd_format.c
+src/rrd_format.h
+src/rrd_graph.c
+src/rrd_open.c
+src/rrd_last.c
+src/rrd_tool.c
+src/rrd_tool.h
+src/rrd_tune.c
+src/rrd_update.c
+src/parsetime.c
+src/parsetime.h
+src/rrdtool.dsp
+src/rrdtool.dsw
Added: trunk/orca/packages/rrdtool-0.99.29.1/CHANGES
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/CHANGES (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/CHANGES Sat Jul 13 18:46:17 2002
@@ -0,0 +1,847 @@
+0.99.29b
+0) from blair .. fix for Makefile.in
+
+0.99.29
+From: Blair
+0) Prevent Makefile from rebuilding the perl modules on every run
+
+0.99.28
+From: Blair
+0) fixed filedescriptor leak in rrd_graph
+From: Alan Lichty <alan_lichty at eli.net>
+0) fixes for rrdintroduction
+1) contrib/log2rrd for mrtg *.log file to *.rrd conversion
+From: Tobi
+0) fixed data_fetch bug ... I did not set the requested
+ data resolution properly ... the data resolution returned
+ by rrd_fetch was more or less random ...
+
+0.99.27
+From: Tobi
+0) fixed the - file-name to really work.
+1) The rrdintro is now in the doc tree.
+
+0.99.26
+From: Tobi and Jeremy
+0) fixed documentaion GNUMakefile
+From: Kai Siering <kai.siering at mediaways.net>
+0) Updated rrdgraph.pod ...
+From: Tobi with inspiration from Kai
+0) if rrdgraph get - as a filename, its output will go to standard out
+1) ****INCOMPATIBLE***** the IF operator was not taking its argments in the
+ correct order ... I have put an example into the manpage to show how
+ it should be done and how it is now done ...
+From: Alex van den Bogaerdt <alex at ergens.op.het.net>
+0) Contributed two tutorial, make sure you visit
+ bin_dec_hex.man and rrdtutorial.man in the doc directory.
+
+0.99.25
+From: Blair Zajac <bzajac at geostaff.com>
+0) do not set PATH in top Makefile ...
+From: Tobi
+0) added better IEEE test to configure
+
+0.99.24
+From: Jeremy Fischer <jeremy at kiva.net>
+0) install functionality for Makefile
+From: Tobi
+0) removed TOTAL function ...
+
+0.99.23
+* fixed cache bug in configure script ... CFLAGS_EXTRA were disregarded in
+ the second run ... found by Douglas Brunk
+
+0.99.22
+* From Russ Wright <rwwright at home.com>
+0) use PIC instead of pic
+* From Tobi
+0) fixed a memory leak in rrd_graph (p_data was not fully freed)
+ purify is a cool tool indeed :-)
+
+0.99.21
+* From Tobi
+0) Checking for IEEE math in configure ... find out if -ieee helps
+1) rrdtool checks its base arguments with strcmp
+2) errors get sent to stderr when called from the command line
+3) various documentation problems
+4) fixed display bug discovered by Alex van den Bogaerdt
+ the graph display was off by one step
+5) fixed infinite loop which occurs when trying to paint a grid line
+ at 2:00 am on a day when day light saving time gets activated ... (now
+ guess what happens today :-)
+
+* From Blair
+0) Fewer spelling errors for CHANGES file ... thanks !
+1) some additional memory cleanup so that rrdfiles do not contain
+ random date in unused areas ...
+
+0.99.20
+* From Oleg Cherevko <olwi at icyb.kiev.ua>
+0) Allowed uppercase letters in DEF and CDEF names for rrd_graph (note
+ that you now can produce conflicts when using strings which match
+ the name of an rpn function call
+1) make at style time code understand long weekday names
+2) corrected documentation about the length of ds names (it 19 chars and not 9)
+
+* From Tobi
+0) Switched to calloc in rrd_create, to prevent from arbitrary strings
+ showing up in the rrdfiles
+1) Made the two graphs produced by the perl-shared example code match by
+ specifying the end time in addition to the start time ... There is still
+ a potential difference between the gifs, because there seem to be some
+ random entries in the color map, which do not define colors for any pixels
+ actually in the graph. If you convert the graphs to PNM format they are
+ completely the same
+
+0.99.19
+* From Tobi
+0) Fixed example in rrd_create man-page
+1) Fixed rpn parser to properly track through the expressions ...
+2) Fixed stacking code so that it is possible to stack the same variable several times.
+3) Added --base switch to rrd_graph which allows to switch the scaling base to 1024
+ this takes care of situations where you want to graph memory instead of
+ traffic
+
+0.99.18
+* From Oleg Cherevko <olwi at icyb.kiev.ua>
+0) Removed vsnprintf from parsetime for portability reasons ...
+
+0.99.17
+* From Tobi
+0) added the missing files from Olegs at patch ... now the thing
+ compiles again ...
+1) massively enhanced the number of functions accepted in the
+ CDEF arguments of rrd_graph. Things like if, less than, larger or equal,
+ is unknown and more are available. Check the rrd_graph documentation for
+ more info on this ...
+
+0.99.16
+* From Oleg Cherevko <olwi at icyb.kiev.ua>
+0) The rrdtool function HandleInputLine never checks the return values of the
+ rrd_fetch() and rrd_graph() calls.
+1) Added AT-STYLE TIME SPECIFICATION. This allows to specify the time
+ using a more user-friendly format than all just seconds since 1970.
+ See the rrdfetch manpage for a long description of these features ...
+0.99.15
+* From Blair
+1) Uses CFLAGS to compile RRDs.o with the same optimization
+ flags.
+2) Remove some extra ;'s
+3) Spelling fixes.
+
+0.99.14
+* From Tobi
+0) rrd_graph now returns the gif image size. The commandline version just
+ prints XSIZExYSIZE after being called and the perl version returns
+ the size as two additional return values from the graph call.
+
+ PLEASE NOTE THIS mAY BREAK SCRIPTS ANALYZING THE DATA RETURNED BY
+ RRD_GRAPH ...
+
+1) added perl-piped/ perl-shared/ to make all building
+
+0.99.13
+* From: Oleg Cherevko <olwi at icyb.kiev.ua>
+0) fixed typo in the prt_fctn code of rrd_graph ..
+
+0.99.12
+* From Tobi:
+0) New graph function COMMENT added. It prints simple text into the legend.
+ No evaluation occurs
+1) New graph legend feature added. The legend area formating can now be
+ influenced by adding special escaped characters to the end of some
+ of the legend entries. Whenever such an entry is processed, the placement
+ of the pending legend items is done as defined the special character.
+ See NOTE 2 at the end of the rrdgraph manual for details.
+
+0.99.11
+* From Tobi:
+0) added --template switch to rrd_update. This allows to specify which
+ datasources you intend to update. It provides some protection against
+ updating the wrong datasources.
+
+0.99.10
+* From Tobi:
+0) added missing : in optarg template of rrd_create
+
+0.99.9
+* From Tobi:
+1) removed rrd_format2.h this was not used ...
+2) renamed diff to rrd_diff and added ranlib step to library
+ creation ... this is all for the benefit of FreeBSD
+* From: Andrew Turner <turner at mint.net>
+1) added new consolidation functions LAST and TOTAL
+
+0.99.8 Thu Feb 4 1999
+* From Tobi:
+1) Removed compiler waring from rrd_graph.c (blair, I went to default all
+ the way ...)
+2) revisited configure.in ... made gcc option test work properly
+
+0.99.7 Mon Feb 1 1999
+* From Tobi
+1) removed kill command from the end of RRDp.pm
+2) fixed rrdtune ... ds selector did not work ...
+3) removed warnings from diff.c
+4) fixed default -start time when creating new rrds ...
+ this was 1.1.1970 instead of NOW ...
+
+0.99.6 Fri Jan 29 1999
+* From Tobi
+1) more ... don't compare with nan fixes ... this time in rrd_update
+2) on request from Russ Wright made VRULE and HRULE being painted on top
+ of the grid
+
+* From Blair
+1) real decimal version numbers for perl modules
+2) better argument checking for rrd_update
+
+0.99.5 was only available to 30 minutes ...
+
+0.99.4 Thu Jan 28 1999
+* From Tobi
+1) Happy BSD patch ... it seems that RRDTOOL will work on BSD once
+ there are no compares with NAN ... I have altered one if in rrd_create.
+ lets see if this helps
+
+0.99.3 Wed Jan 27 1999
+* From Tobi
+1) ran with electric fence ... found bugs in RPN processing, and in data
+ fetch (related to DS naming)
+2) removed superfluous im_free calls which were in fact causing segfaults by
+ trying to release memory which was already released ...
+
+0.99.2 Tue Jan 26 1999
+* From Tobi trying to find the cores reported by Jesper Skriver
+ changed rrd_create to use DNAN instead of unknown. Maybe we have
+ a problem with the representation of UNKNOWN as NAN on FreeBSD ...
+ We should not get floating point exceptions because of this or should we ?
+
+* From Blair
+ 1) Spelling mistakes in the pod files.
+ 2) Updated 0.99.0 to 0.99.1 in the RRDs.pm and RRDp.pm files.
+ 3) Updated the rrdcreate.pod file to accurately reflect the
+ correct options to rrd_create().
+ 4) Allow uppercase characters in the ds-name in rrd_create.
+
+0.99.1 Fri Jan 22 1999
+
+* Fixed notice in gifs
+* Fixed color selection for base elements
+
+Thu Jan 14 1999
+*****************************************************************************
+* BIG CHANGE ... The new format is in place .....
+* drop your old files ... everything is new now .....
+*****************************************************************************
+
+* Tobi ... user visible changes are that the data sources do have
+ names now and that the xxf can be set individually for each RRA
+ this means that some command line options had to be changed ...
+ Basically everything which deals with DS selection.
+
+*****************************************************************************
+*****************************************************************************
+*****************************************************************************
+
+Mon Jan 11 1999
+* Tobi
+1) Fixed data_reduce again ... blair pointed out a core dump condition in the
+ perl module ...
+
+Sat Jan 9 1999
+* Tobi
+1) Fixed rounding error in rrd_graph/ytr ... it lead to zero values
+ not being identified correctly ...
+2) applied Philippe fixes for better compilation of the Perl module under NT
+3) new version number for perl module
+4) Fixed AVERAGE calculator in print_calc ... thanks to Sasha Mikheev for the hint
+5) Fixed bug in reduce_data function which killed CDEF under certain circumstances because start
+ was not adjusted according to the new step size ...
+
+Wed Dec 16 1998
+* Tobi
+1) when using the rigid option and the data would be outside the graph, the
+ line gets drawn 2 pixels out side graph ... this is not tested :-)
+ rrd_graph.c ~ line 246 around line 1900 I removed all the sanity checks for
+ the graphics to be inside the valid area ...
+
+* jeff alan
+I'd like to be able to turn off interlaced gifs, since I think they
+look messy when they are coming in. I added an option called
+"interlaced" (abbrev: "i") which will set the graph to interlaced. The
+graphs now default to progressive.
+
+*phillipe
+moved #include "../src/rrd_tool.h" in RRD.xs to etern"C" section
+to make it work on NT ...
+
+
+Sat Nov 21 1998
+* Blair Zajac <bzajac at geostaff.com>
+1) Update the rrd_update function to be able to take multiple
+ timestamp/DATA pairs. When there's a lot of data to dump
+ into an RRD, this will save a lot of time. In one test I
+ ran updating 1000 data points into a single RRD trimmed
+ 40% off the execution time. This reduction is caused by
+ two factors: rrd_update gets called only once and the RRD
+ gets opened and closed only once. The new input to
+ rrd_update still takes the old format, but allows trailing
+ time and DATA: pairs:
+
+ rrdtool update demo.rrd [--time|-t timestamp] DATA:...
+ timestamp DATA:... timestamp DATA:... ....
+
+ This change did a lot of work to rrd_update.c. To see all
+ the changes I would do a diff -ruWb between the previous
+ and this version. This will ignore lines that have had
+ their indentation changed due to the addition of a while
+ loop around the whole update structure.
+
+ The only problem I see is that in the loop where the
+ timestamp/DATA pairs are processed there is a single
+ fwrite call to write some data to the RRD. If some of
+ these succeed and then one fails, should the remaining
+ data that needs to be written at the end of rrd_update
+ still be written to the file or should we just exit
+ and leave the RRD alone. If the first fwrite succeeds and
+ everything else fails, will the RRD still be ok for
+ future updates.
+
+ I've run some comparisons between the RRDs generated by
+ the old rrd_update and this rrd_update and I've found only
+ a few instances where the RRDs differ. The output of
+ rrdtool dump did not differ however and the resulting GIFs
+ looked identical. I would recommend that we be careful
+ with the code for a little bit. I would greatly appreciate
+ it if somebody else could take a look at it. I do think
+ it's important, as that 40% savings in time is very important
+ for how I'm using RRD.
+
+2) Update the POD for rrd_update.
+
+3) Some spelling corrections.
+
+4) Update test.pl to output demo1 and demo2 RRDs and GIFs.
+ Demo1 is created using single timestamp/DATA pair calls
+ to rrd_update while demo2 is updated using one single
+ call. This allows us to compare the output RRDs and GIFs.
+
+5) To allow the comparison of RRDs created and updated using
+ slightly different code, I found a problem where the filler
+ bytes the compiler uses to align doubles and other types
+ in the structs in rrd_format.h would be filled with random
+ data. This would cause simple cmp compares to fail on
+ newly created RRDs. Now rrd_create does a memset to 0 of
+ all newly malloc memory to set these filler bytes to a
+ consistent value.
+
+Wed Nov 18 1998
+* Tobi
+1) rrdtool graph will now consolidate data previous before plotting it, if
+ the resolution of the data is higher than the resolution of the plotting
+ area.
+
+Tue Nov 17 1998
+* Tobi
+1) allow negative --start time in create. This means go back the specified
+ amount of time from NOW ... this is the same as it is supported with other
+ modules ...
+2) make sure we do draw outside the appointed area. With the --rigid
+ option this could be accomplished and would make gdlib work so hard that
+ rrdtool appears to be dead ..
+
+Sat Nov 14 1998
+* Blair Zajac <bzajac at geostaff.com>
+1) 1000 spelling fixes (thanks!)
+2) a new Datasource type called DERIVE. It calculates the derivative between
+ the current and previous value of the datasource.
+ This lets you plot the rate of increase or decrease of a counter
+ value, such as the number of people in a room.
+3) some contents fixes for the pod docs ...
+4) more tests for the binary perl module
+
+Fri Nov 6 1998
+* Blair Zajac <bzajac at geostaff.com>
+ more spelling and other fixes ... especially a few remaining exits were
+ replaced by returns ...
+
+* tobi
+1) fixed the parsing of : in string arguments of rrd_graph. An output string
+ can now contain a : if it is escaped with \ .. a \ has to be escaped as
+ well ... this makes the changes from the 24-oct really work ...
+2) in connection with 1) there were also problems with arguments where the
+ string was blank ...
+
+Tue Nov 3 1998
+* Blair Zajac <bzajac at geostaff.com>
+1) added a missing fclose to rrd_open ...
+
+Mon Nov 2 1998
+* Tobias Oetiker
+1) configurable color for arrow in Graph
+2) added new format definition header to distribution .. this is bound to
+ be integrated ... once I get some time to do it ... (any takers?)
+
+Sat Oct 31 1998
+* Win32 patches from Philipp Simonet <philipp.simonet at swisscom.ch>
+1) New Visual Studio Config files for building WIN32 binaries
+2) Locking enabled under WIN32
+
+* Tobias Oetiker
+1) fixed scaling again ... when there is no data, the graph will show 0..1
+ and not -1..1
+2) Added a little arrow indicating the positive x axis direction
+3) paint x and y axis before the graph, so that it does not hide it
+
+Sat Oct 24 1998
+* Perl and other patches from Blair Zajac <bzajac at geostaff.com>
+1) Have rrd_last return a time_t instead of an int, so the real
+ time from the RRD file is returned.
+2) Fixed an error where rrd.live_head->last_up was returned from
+ rrd_last after rrd was freed.
+3) Make perl/Makefile.PL a little neater.
+4) Add a realclean option to perl/Makefile.PL.
+5) Small formatting change to RRD.xs.
+6) Added a little RRD::last testing code to test.pl and added some
+ more ok's for now and future use for more tests. Changed the code
+ to run under use strict.
+* Tobi O.
+1) removed machine option from rrd_last ... it will now only return
+ the unix time_t when the rrd was last updated ...
+2) allo ':' in graph arguments, if the : is escaped with a \. In perl
+ strings you have to enter two \ because perl interprets them
+ as well: eg "Max\\: %2f"
+
+Fri Oct 23 1998
+* Makefile Patches from Blair Zajac <bzajac at geostaff.com>
+1) Allow the user to do something like make CFLAGS=-O3 and not loose
+ the other important flags, such as -DHAVE_CONFIG_H, etc.
+2) Move all OS and compiler dependent flags into CFLAGS_EXTRA. This
+ changes Makefile.in's and configure.in.
+3) Add realclean targets to all Makefiles.
+4) Have realclean clean up many more things to return the package to
+ a clean state.
+
+Mon Oct 19 1998
+* Fixed rrdcreate.pod ... the example was out of date ...
+
+Sun Oct 18 1998
+* From Jeff: rrd_open will open readonly when ever possible. This
+ allows to graph without write permission ...
+* From Jeff Allan: Removed all remaining \n from the error
+ messages and fixed some spelling
+* From Jeff: Improved handling of cases where no data is
+ found
+* rrd_graph: if minval == maxval pumb max up and pull min down 1%
+ ... by tobi as suggested by allan.
+
+Mon Oct 12 1998
+* This time the diff.c fix for negative numbers
+ and counter wrap detector code are really in ... tobi
+
+Thu Oct 08 1998
+* Added file locking code to rrd_update ... written by Russ Wright.
+ The locking code uses fcntl so I guess it will not work on NT ...
+ any takers ?
+
+* Fixed longstanding bug in diff.c ... now it works even for 0-10
+ Tobi.
+
+* made rrd_graph work even when there is no data to plot ... Russ Wright
+
+* added new last function provided by Russ Wright. This func allows
+ to query an RRD for it's last modification date ...
+
+* added counter overflow patch as suggested by Andres Kroonmaa <andre at ml.ee>
+ to rrd_update. This will only work for 32 bit and 64 bit counters.
+ Are there any others in SNMP land ?
+
+Thu Aug 13 1998
+* raised stacksize in rrd_graphs rpn machine to 30 (otmar)
+* fixed label placement in graph for precisions != 0 (otmar)
+
+Sat June 13 1998
+* added ms devstudio stuff from philippe
+
+Mon June 8 1998
+* WIN32 Portability fixes from Philippe
+
+Sun June 7 1998
+* fixed coredumps with rrd_error ... I was freeing free memory.
+ somehow I had assumed, that free(x) would set x to NULL ...
+ this is not true :-)
+
+Wed June 3 1998
+* fix for PRINT and GPRINT calc in rrd_graph ...
+* fix for STACK function command line parsing ... It must follow
+ directly after a LINE*, AREA or STACK function
+
+Tue June 2 1998
+* lots of fixes from Jost Krieger integrated
+* increased MAX_LENGTH to 10000 in rrd_tool as suggested by simon ...
+
+Tue May 26 1998
+* did some instruction reordering in rrd_graph.c to make
+ a segfault go away which was discovered by David Vickers
+
+Sun May 24 1998
+* cleanup session. In order to improve rrdtools perl integration
+ I have started moving all the printf code out of the individual
+ functions. Now they all return their findings (except rrd_dump)
+ to rrd_tool.c which then prints them.
+
+* the perlmodule got extended to use these new possibilities. The
+ RRD::fetch and RRD::graph return the things they used to print
+ directly to perl. See the test.pl for an example. There is still
+ no documentation though for the perl module
+
+Tue May 12 1998
+* Patch to rrdcreate.pod from Amos Shapira <amos at gezernet.co.il>
+
+Thu May 7 1998
+* debugged memory allocation and access errors in CDEF. Now
+ things should work as advertised ... Thanks to
+ David Vickers <David.Vickers at citec.com.au> for finding the
+ bug ...
+
+Fri May 1 1998
+* finally added the --logarithm switch ... or rather the logic behind it.
+ you can now draw graphs with logarithmic scale in the data axis ...
+
+* fixed some minor drawing bugs ...
+
+Thu Apr 30 1998
+* hp portability patch from "Crawley, Tom" <Tom.Crawley at hi.riotinto.com.au>
+ you should now be able to compile with gcc on hp as well ...
+
+Fri Apr 18 1998
+
+* Patch from Otmar Lendl (O.Lendl at Austria.EU.net) to
+ fix perl coredump ...
+
+* Split the top makefile into Makefile.dist and Makefile
+ Makefile does not contain any gnu only things anymore
+
+* Renamed doc Makefile to GNUmakefile because it contains
+ several GNU only constructs. Lets be straight in this respect
+ and stop pretending it was a Makefile.
+
+Thu Apr 9 1998
+**** INCOMPATIBLE CHANGES ****
+
+* altered PRINT and GPRINT functions ... we really need to give
+ them a consolidation function ... [G]PRINT:<vname>:<cf>:<format>
+ otherwise things are not clear for calculation. You can now
+ define the operation for PRINT and GPRINT independent from the
+ data source consolidation method. This allows to calc things
+ like average maximum, or maximal 5 minute average ... or what ever
+ you choose ...
+
+* options of graph, create and update have changed again. The old style
+ LINE1:..., DS:..., DATA:... arguments are back. I found that this
+ is more logical than doing everything with options. This will be
+ especially helpful for the perl interface
+
+* Completed CDEF/DEF implementation. Now you can create new
+ data sources on the fly by doing some rpn math. Check rrd_demo.pl for
+ an example of CDEF rpn math.
+
+* updated rrdgraph, rrdupdate and rrdcreate man-pages to reflect new
+ command-line options
+
+* updated rrd_demo.pl to work with new command-line options
+ log2rrd.pl and graphrrd.pl are *NOT* updated yet ...
+
+* updated perl test.pl to work with new options ... unfortunately
+ test.pl crashes after generating about 3 graphs ... I guess there is
+ a memory leak, but debugging the core of an shared library perl
+ is quite a problem ... no solution yet ... When I link perl statically
+ to the rrd stuff things work without core ...
+
+Wed Apr 8 1998 -- Wrolf / Russ
+* new scripts log2rrd.pl and graphrrd.pl
+
+Mon Apr 6 1998
+* compete RPN implementation ... things compile ... too tired to
+ test, will do later
+
+Sun Apr 5 1998
+* added -fpic for gcc and -z for hp compilers to generate
+ position independent code which helps when doing shared
+ libraries ...
+
+Thu Apr 2 1998 -- Wrolf
+* Makefile.in fixes
+
+Wed Apr 1 1998
+* Updated docs for rrd graph ... will take the graph functions out of long
+ opts ... as they are not really options ...
+
+Tue Mar 31 1998
+* small Makfile.in fixes ...
+
+Tue Mar 31 1998 -- Wrolf
+* spelling fixes
+
+Mon Mar 30 1998
+* big source split ... its now all neatly separated
+ in subdirectories.
+
+* gd1.2 is now included in the release ...
+
+Mon Mar 30 1998 -- Philippe.Simonet at swisscom.com
+* rrd_open.c use rb+ instead of r+ for fopen
+* ntdemo.pl created to the test rrdtool.exe under NT
+
+Sun Mar 29 1998
+* INCOMPATIBLE CHANGE remaining functions converted to getopt_long
+* started loadable perl module ... its all in the RRD directory
+
+Thu Mar 26 1998 -- jeff.allen at acm.org
+* added some files to make things work under DevStudio
+ not tested yet ...
+
+Tue Mar 24 1998
+* started changing calling sequence rrd_graph.c done
+* updated to much newer getopt ... maybe it has a few potential
+ bugs fixed
+* updated rrdgraph.pod for new calling sequence
+
+Mon Mar 23 1998
+* improved labeling for horizontal grid
+
+Sat Mar 21 1998 -- jeff.allen at acm.org
+* hpux portability improved
+* sunos port
+
+Wed Mar 18 1998
+* added log2rrd.pl to configure.in and Makefile.in
+* about 1'000 spelling fixes from Wrolf applied
+* Fixed help screen in rrd_tune (LINE1 ...)
+* Fixed error in GPRINT and PRINT function of rrd_graph.c (Philippe)
+* added log2rrd.pl by Russ and Wrolf
+
+Sun Mar 15 1998
+* Updated Makefile to produce *.pl.in files from *.pl files on tar and dist
+* Updated Makefile to generate *.html and *.man files from *.pl and *.pm
+* total rewrite of horizontal grid lines I guess now things look more the
+ way they should ...
+* INCOMPATIBLE CHANGE the -y option is now called -v and -y is now
+ equivalent to x in the respect, that it allows to configure the horizontal
+ -grid. (log grid will come soon)
+* implemented title function -t (it was already there but not active)
+* made RRD.pm complain if it is not used correctly
+* updated documentation for RRD.pm
+* INCOMPATIBLE CHANGE ... there are now 3 types of LINE -- LINE1 LINE2 and
+LINE3
+ they are increasing in size.
+* if there are only PRINT commands in a graph command line, no GIF will be
+ created ...
+
+Fri Mar 13 1998
+* fixed some potentially ambiguous else statements (gcc-2.8.1 objected)
+* fixed error in STACK option
+* added documentation for log scale
+* added documentation for y-axis spacing config
+
+Thu Mar 12 1998
+* added rule to configure so that it looks in
+ /usr/local/include/gd for include files
+* added -d option to rrd_tune.c to allow to change
+ the DST of a DS ... (special request from Alan)
+
+Thu Mar 12 1998 -- jeff.allen at acm.org
+* cleaned up rrd_tool.h to make better use of configure
+* tried to separate out Win32 stuff better
+* made calls to strftime fail if it doesn't exist (probably
+ need to ship a substitute, unless this is more portable than it sounds)
+* created config.h.nt, which will probably be useful for porting
+ to NT. We'll see.
+
+Wed Mar 11 1998
+* oops nonblocking was NOT in last release ... sorry ... here it is ..
+* started to create RRD.pm
+* adapted rrd_demo.pl to work with it ...
+
+Mon Mar 9 1998
+* better values for xlab array ...
+* fixed error with rrd_fetch
+ (it was not fetching the right data if the pointer wrapped straight from
+ the beginning)
+* check VRULE and HRULE placement
+* changed linking order -lgd and then -lm as floor from gd is in m
+* made rrd_demo use nonblocking read to get data from pipe
+
+Mon Mar 9 1988 -- Wrolf (how about using diff -u )
+* lots of spelling fixes
+* some linting fixes
+* better Makefile portability
+
+Sun Mar 8 1998
+* added rrd_tune.c and rrdtune.pod ... read the docs ...
+* compiled rrdtool and gdlib with -pg in order to run it
+ under gprof ... the results were, that most time is spent
+ compressing the gif file. As the profiling is only on a function level, I
+ was not able to identify hot spots within the code ...
+* added getrusage and gettimeofday call to rrd_tool.c in order to get
+ better grip on time spent on each function ... the results will be printed
+ after the OK prompt. Adapted rrd_demo.pl accordingly ...
+
+Sun Mar 8 1998 -- jeff.allen at acm.org
+* Fix to first line of rrd_demo.pl. Autoconf docs say that
+ Sequent's unix needs the space. Whatever...
+* cosmetic changes to rrd_demo.pl.in
+* changed getopt.c to suck in rrdtool.h, so that it includes
+ string.h. The comments in getopt.c seem to imply that
+ this can break things, but it clears up a warning for me.
+ What do others think?
+
+Sat Mar 7 1998
+* tried some cool graphs ... the current one produced by rrd_demo.pl
+ looks really freaky ... not that anyone would want to use
+ such a graph, (I guess) but it can be done ...
+* finally rrd_graph does work as described in the manpage
+* many cosmetic changes to the graph
+* use Open2 and select in rrd_demo.pl
+* added OK response to rrd tool
+* integrated simons opt patch ...
+
+Fri Mar 6 1998 -- jeff.allen at acm.org
+* docs in configure.in
+* HP cc and GCC flags discovery (not tested on HP -- Wrolf,
+ please give it a try)
+* improvements to makefile
+* one-line changes to rrd_graph.c and getopt.c to keep Purify and
+ Gcc happy.
+
+Thu Mar 5 1998
+* some more HPUX portability stuff by Wrolf
+* rrd_tool.h cleanup
+* added project files for MS VC++ by Philippe
+* aesthetic tuning on the graph ...
+* text labels below the graph area
+* VRULE and HRULE implemented
+* Debugged argument parsing ... no more segfaults when you give the wrong
+ number of arguments.
+
+Wed Mar 4 1998
+* now rrdgraph is working ... not all methods are implemented yet, but it
+ does produce graphs ... see rrd_demo.pl
+
+Tue Mar 3 1998
+* fixed some further minor problems .... bug fixing goes ahead, but not
+ finished yet ... CODE DOES NOT WORK
+
+* found the 'memory problem' there is a difference between
+ malloc(a-b * sizeof(c)) when I want to do malloc((a-b) * sizeof(c))
+ I love braces ... :-)
+
+Tue Mar 3 1998 -- jeff.allen at acm.org
+* Added configure.in and friends, to simplify configuration.
+
+Sun Mar 1 1998
+* started to make rrd_graph work as advertised. Programming went well,
+ unfortunately debugging is not yet done and not all the functionality
+ is implemented. But I guess if it did not crash, the AREA, LINE and
+ STACK functions should be OK ... I guess there is some memory problem.
+* enhanced Makefile to be able to do the man and html versions
+
+Thu Feb 26 1998
+* fixed pipe mode commandline parsing
+* made rrd_demo.pl work again ... no graphics at the moment
+* altered commandline options for update ... negative numbers were a problem
+* Integrated some patches from Wrolf
+* filename and pod patches from Jeff added
+* changed Makefile structure to make it ready for autoconf/configure ... (jeff)
+* added rrd_getopt for good now it will work the same on all systems.
+ Maybe we should go to gnu_getopt once jeff integrates configure ?
+* made rrd_update work as advertised in the manpage
+
+Wed Feb 25 1998
+* some 'make the compiler happy' patches from Jeff
+* CFLAGS for HP cc from Wrolf
+* included source for getopt in case your system does not have it
+ edit Makefile ...
+
+Sun Feb 22 1998
+* improved/spell-checked pod documentation (Russ)
+* rrd_fetch and rrd_dump work as advertised in the docs
+
+Sat Feb 21 1998
+* stared bringing code in line with documentation. rrd_create.c done
+
+Sun Feb 15 1998
+* created full documentation for rrdtool in pod format
+
+Sun Feb 1 1998
+* fixed seek bug in rrd_update
+* rewrote rrd_tool argument scanner now it does quoting as it should be.
+* rrd_graph ... scaling bug fixes
+* horizontal grid fixed
+* added copyright notice
+* vertical grpd fixed
+* wrote demo app in perl
+* updated TODO and README
+
+Thu Jan 22 1998
+* Russ has debugged my rrd_graph code.
+* Fixed one remaining malloc error
+* improved visual appearance of the graph
+* updated TODO list
+
+Sun Jan 18 1998
+* added Dan and Russ rrd_tool.c ... rrd_main.c is gone
+* current setup assumes gd1.2 to exist in the compile directory
+* things compile again ...
+* rrd_graph is done, but not yet debugged ... so while it compiles,
+ it will not do what it should (I guess )
+* this release is for dan dunn to integrate the new rrd_main.c
+* created TODO and CONTRIBUTORS files
+
+Thu Jan 08 1998
+
+* mrtg DOES NOT COMPILE ... you can leave out rrd_graph and the
+ relevant parts of rrd_main to get it to compile ...
+
+* releasing the code because there were some changes in other modules as
+ well
+* rrd_graph is about 50 percent done ... remaining twist clever
+ horizontal grid ...
+
+Sat Nov 29 1997
+
+* debugged rrd_fetch
+
+Fri Nov 28 1997
+
+* rrd_update a ; after a if prevented CF MAX from working
+
+* rrd_dump fied time in output
+
+* rrd_perf fixed mrhb in demo db
+
+* rrd_fetch created. This function will get the data
+ for the graphs
+
+Thu Nov 27 1997
+
+* rrd_update debugged ... I guess (!) it works now correctly
+
+ note: we always assume that a input value represents the average
+ from the last to the current run
+
+* rrd_fupd created. This is like rrd_update, but it accepts input
+ from a file or stdin ... (this saves us from restarting
+ rrd_update for each file)
+
+* rrd_perf.pl created. It helps to assess the performance you
+ can achieve with an rrd on your system.
+
+
+Sun Nov 23 1997
+
+* rrd_update created ... does not yet work ... but it should !
+* some problem s with the format removed in the process ...
+
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/COPYRIGHT
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/COPYRIGHT (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/COPYRIGHT Sat Jul 13 18:46:17 2002
@@ -0,0 +1,21 @@
+ RRDTOOL - Round Robin Database Tool
+ A tool for fast logging of numerical data graphical display
+ of this data.
+
+ Copyright (c) 1998, 1999 Tobias Oetiker
+ All rights reserved.
+
+ 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., 675
+ Mass Ave, Cambridge, MA 02139, USA.
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/COPYING
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/COPYING (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/COPYING Sat Jul 13 18:46:17 2002
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, 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
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.dsp
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.dsp (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.dsp Sat Jul 13 18:46:17 2002
@@ -0,0 +1,110 @@
+# Microsoft Developer Studio Project File - Name="gd" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=gd - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "gd.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gd.mak" CFG="gd - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gd - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "gd - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gd - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_CTYPE_DISABLE_MACROS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x100c
+# ADD RSC /l 0x100c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "gd - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD B!
ASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_CTYPE_DISABLE_MACROS" /FR /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x100c
+# ADD RSC /l 0x100c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "gd - Win32 Release"
+# Name "gd - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\GD.C
+# End Source File
+# Begin Source File
+
+SOURCE=.\gdfontg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\gdfontl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\GDFONTMB.C
+# End Source File
+# Begin Source File
+
+SOURCE=.\GDFONTS.C
+# End Source File
+# Begin Source File
+
+SOURCE=.\gdfontt.c
+# End Source File
+# End Target
+# End Project
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/demoin.gif
==============================================================================
Binary files trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/demoin.gif (original) and trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/demoin.gif differ
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.h
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.h (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.h Sat Jul 13 18:46:17 2002
@@ -0,0 +1,145 @@
+#ifndef GD_H
+#define GD_H 1
+
+/* gd.h: declarations file for the gifdraw module.
+
+ Written by Tom Boutell, 5/94.
+ Copyright 1994, Cold Spring Harbor Labs.
+ Permission granted to use this code in any fashion provided
+ that this notice is retained and any alterations are
+ labeled as such. It is requested, but not required, that
+ you share extensions to this module with us so that we
+ can incorporate them into new versions. */
+
+/* stdio is needed for file I/O. */
+#include <stdio.h>
+
+/* This can't be changed, it's part of the GIF specification. */
+
+#define gdMaxColors 256
+
+/* Image type. See functions below; you will not need to change
+ the elements directly. Use the provided macros to
+ access sx, sy, the color table, and colorsTotal for
+ read-only purposes. */
+
+typedef struct gdImageStruct {
+ unsigned char ** pixels;
+ int sx;
+ int sy;
+ int colorsTotal;
+ int red[gdMaxColors];
+ int green[gdMaxColors];
+ int blue[gdMaxColors];
+ int open[gdMaxColors];
+ int transparent;
+ int *polyInts;
+ int polyAllocated;
+ struct gdImageStruct *brush;
+ struct gdImageStruct *tile;
+ int brushColorMap[gdMaxColors];
+ int tileColorMap[gdMaxColors];
+ int styleLength;
+ int stylePos;
+ int *style;
+ int interlace;
+} gdImage;
+
+typedef gdImage * gdImagePtr;
+
+typedef struct {
+ /* # of characters in font */
+ int nchars;
+ /* First character is numbered... (usually 32 = space) */
+ int offset;
+ /* Character width and height */
+ int w;
+ int h;
+ /* Font data; array of characters, one row after another.
+ Easily included in code, also easily loaded from
+ data files. */
+ char *data;
+} gdFont;
+
+/* Text functions take these. */
+typedef gdFont *gdFontPtr;
+
+/* For backwards compatibility only. Use gdImageSetStyle()
+ for MUCH more flexible line drawing. Also see
+ gdImageSetBrush(). */
+#define gdDashSize 4
+
+/* Special colors. */
+
+#define gdStyled (-2)
+#define gdBrushed (-3)
+#define gdStyledBrushed (-4)
+#define gdTiled (-5)
+
+/* NOT the same as the transparent color index.
+ This is used in line styles only. */
+#define gdTransparent (-6)
+
+/* Functions to manipulate images. */
+
+gdImagePtr gdImageCreate(int sx, int sy);
+gdImagePtr gdImageCreateFromGif(FILE *fd);
+gdImagePtr gdImageCreateFromGd(FILE *in);
+gdImagePtr gdImageCreateFromXbm(FILE *fd);
+void gdImageDestroy(gdImagePtr im);
+void gdImageSetPixel(gdImagePtr im, int x, int y, int color);
+int gdImageGetPixel(gdImagePtr im, int x, int y);
+void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color);
+/* For backwards compatibility only. Use gdImageSetStyle()
+ for much more flexible line drawing. */
+void gdImageDashedLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color);
+/* Corners specified (not width and height). Upper left first, lower right
+ second. */
+void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color);
+/* Solid bar. Upper left corner first, lower right corner second. */
+void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color);
+int gdImageBoundsSafe(gdImagePtr im, int x, int y);
+void gdImageChar(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color);
+void gdImageCharUp(gdImagePtr im, gdFontPtr f, int x, int y, char c, int color);
+void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, char *s, int color);
+void gdImageStringUp(gdImagePtr im, gdFontPtr f, int x, int y, char *s, int color);
+
+/* Point type for use in polygon drawing. */
+
+typedef struct {
+ int x, y;
+} gdPoint, *gdPointPtr;
+
+void gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c);
+void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c);
+
+int gdImageColorAllocate(gdImagePtr im, int r, int g, int b);
+int gdImageColorClosest(gdImagePtr im, int r, int g, int b);
+int gdImageColorExact(gdImagePtr im, int r, int g, int b);
+void gdImageColorDeallocate(gdImagePtr im, int color);
+void gdImageColorTransparent(gdImagePtr im, int color);
+void gdImageGif(gdImagePtr im, FILE *out);
+void gdImageGd(gdImagePtr im, FILE *out);
+void gdImageArc(gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color);
+void gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color);
+void gdImageFill(gdImagePtr im, int x, int y, int color);
+void gdImageCopy(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h);
+/* Stretches or shrinks to fit, as needed */
+void gdImageCopyResized(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH);
+void gdImageSetBrush(gdImagePtr im, gdImagePtr brush);
+void gdImageSetTile(gdImagePtr im, gdImagePtr tile);
+void gdImageSetStyle(gdImagePtr im, int *style, int noOfPixels);
+/* On or off (1 or 0) */
+void gdImageInterlace(gdImagePtr im, int interlaceArg);
+
+/* Macros to access information about images. READ ONLY. Changing
+ these values will NOT have the desired result. */
+#define gdImageSX(im) ((im)->sx)
+#define gdImageSY(im) ((im)->sy)
+#define gdImageColorsTotal(im) ((im)->colorsTotal)
+#define gdImageRed(im, c) ((im)->red[(c)])
+#define gdImageGreen(im, c) ((im)->green[(c)])
+#define gdImageBlue(im, c) ((im)->blue[(c)])
+#define gdImageGetTransparent(im) ((im)->transparent)
+#define gdImageGetInterlaced(im) ((im)->interlace)
+#endif
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gddemo.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gddemo.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gddemo.c Sat Jul 13 18:46:18 2002
@@ -0,0 +1,113 @@
+#include <stdio.h>
+#include "gd.h"
+#include "gdfontg.h"
+#include "gdfonts.h"
+
+int main(void)
+{
+ /* Input and output files */
+ FILE *in;
+ FILE *out;
+
+ /* Input and output images */
+ gdImagePtr im_in, im_out;
+
+ /* Brush image */
+ gdImagePtr brush;
+
+ /* Color indexes */
+ int white;
+ int blue;
+ int red;
+ int green;
+
+ /* Points for polygon */
+ gdPoint points[3];
+
+ /* Create output image, 128 by 128 pixels. */
+ im_out = gdImageCreate(128, 128);
+
+ /* First color allocated is background. */
+ white = gdImageColorAllocate(im_out, 255, 255, 255);
+
+ /* Set transparent color. */
+ gdImageColorTransparent(im_out, white);
+
+ /* Try to load demoin.gif and paste part of it into the
+ output image. */
+
+ in = fopen("demoin.gif", "rb");
+ if (!in) {
+ fprintf(stderr, "Can't load source image; this demo\n");
+ fprintf(stderr, "is much more impressive if demoin.gif\n");
+ fprintf(stderr, "is available.\n");
+ im_in = 0;
+ } else {
+ im_in = gdImageCreateFromGif(in);
+ fclose(in);
+ /* Now copy, and magnify as we do so */
+ gdImageCopyResized(im_out, im_in,
+ 16, 16, 0, 0, 96, 96, 127, 127);
+ }
+ red = gdImageColorAllocate(im_out, 255, 0, 0);
+ green = gdImageColorAllocate(im_out, 0, 255, 0);
+ blue = gdImageColorAllocate(im_out, 0, 0, 255);
+ /* Rectangle */
+ gdImageLine(im_out, 8, 8, 120, 8, green);
+ gdImageLine(im_out, 120, 8, 120, 120, green);
+ gdImageLine(im_out, 120, 120, 8, 120, green);
+ gdImageLine(im_out, 8, 120, 8, 8, green);
+ /* Circle */
+ gdImageArc(im_out, 64, 64, 30, 10, 0, 360, blue);
+ /* Arc */
+ gdImageArc(im_out, 64, 64, 20, 20, 45, 135, blue);
+ /* Flood fill */
+ gdImageFill(im_out, 4, 4, blue);
+ /* Polygon */
+ points[0].x = 32;
+ points[0].y = 0;
+ points[1].x = 0;
+ points[1].y = 64;
+ points[2].x = 64;
+ points[2].y = 64;
+ gdImageFilledPolygon(im_out, points, 3, green);
+ /* Brush. A fairly wild example also involving a line style! */
+ if (im_in) {
+ int style[8];
+ brush = gdImageCreate(8, 8);
+ gdImageCopyResized(brush, im_in,
+ 0, 0, 0, 0,
+ gdImageSX(brush), gdImageSY(brush),
+ gdImageSX(im_in), gdImageSY(im_in));
+ gdImageSetBrush(im_out, brush);
+ /* With a style, so they won't overprint each other.
+ Normally, they would, yielding a fat-brush effect. */
+ style[0] = 0;
+ style[1] = 0;
+ style[2] = 0;
+ style[3] = 0;
+ style[4] = 0;
+ style[5] = 0;
+ style[6] = 0;
+ style[7] = 1;
+ gdImageSetStyle(im_out, style, 8);
+ /* Draw the styled, brushed line */
+ gdImageLine(im_out, 0, 127, 127, 0, gdStyledBrushed);
+ }
+ /* Text */
+ gdImageString(im_out, gdFontGiant, 16, 16, "hi", red);
+ gdImageStringUp(im_out, gdFontSmall, 32, 32, "hi", red);
+ /* Make output image interlaced (allows "fade in" in some viewers,
+ and in the latest web browsers) */
+ gdImageInterlace(im_out, 1);
+ out = fopen("demoout.gif", "wb");
+ /* Write GIF */
+ gdImageGif(im_out, out);
+ fclose(out);
+ gdImageDestroy(im_out);
+ if (im_in) {
+ gdImageDestroy(im_in);
+ }
+ return 0;
+}
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontmb.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontmb.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontmb.c Sat Jul 13 18:46:18 2002
@@ -0,0 +1,1806 @@
+#include "gdfontmb.h"
+
+char gdFontMediumBoldData[] = {
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,1,1,0,0,
+1,1,1,1,1,1,0,
+0,1,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,1,1,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,1,1,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+1,1,0,1,1,0,0,
+1,1,0,1,1,0,0,
+1,1,1,1,1,0,0,
+1,1,0,1,1,0,0,
+1,1,0,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,1,1,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+1,1,1,1,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,1,1,0,
+0,0,1,1,0,0,0,
+0,0,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,1,1,1,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+0,1,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,1,0,0,
+0,0,1,1,0,1,0,
+0,0,1,1,1,0,0,
+0,0,1,1,0,1,0,
+0,0,1,1,0,1,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,1,1,0,
+0,0,1,1,0,0,0,
+0,0,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,1,0,1,1,0,
+1,1,1,1,1,1,0,
+1,1,0,1,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,1,1,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,0,0,1,0,0,
+0,1,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,1,1,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,0,0,0,0,
+
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+1,1,1,1,0,0,0,
+1,1,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,0,0,0,
+1,1,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,
+0,0,1,1,1,1,1,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,1,1,1,
+0,0,1,1,1,1,1,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,
+
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,1,1,1,
+0,0,1,1,1,1,1,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+1,1,1,1,0,0,0,
+1,1,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,
+0,0,0,1,1,0,0,
+0,1,1,0,0,0,0,
+1,1,0,0,0,0,0,
+0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,0,0,0,
+0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,
+0,0,0,1,1,0,0,
+0,1,1,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+0,1,1,0,1,1,0,
+0,1,1,0,1,1,0,
+0,1,1,0,1,1,0,
+1,1,1,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,1,0,
+0,0,0,0,1,1,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+0,0,1,1,0,0,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+1,1,0,0,0,0,0,
+1,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,1,0,0,
+0,1,1,0,1,1,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+1,1,1,1,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,1,1,0,
+1,0,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,0,1,1,0,
+0,1,1,0,1,1,0,
+0,1,1,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,0,1,0,0,
+0,0,1,0,1,0,0,
+0,1,1,1,1,1,0,
+0,1,1,1,1,1,0,
+0,0,1,0,1,0,0,
+0,1,1,1,1,1,0,
+0,1,1,1,1,1,0,
+0,0,1,0,1,0,0,
+0,0,1,0,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,1,1,0,0,
+1,0,1,1,0,1,0,
+1,0,1,1,0,0,0,
+0,1,1,1,1,0,0,
+0,0,1,1,0,1,0,
+1,0,1,1,0,1,0,
+0,1,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,0,0,1,0,
+1,0,1,0,1,1,0,
+1,1,1,0,1,0,0,
+0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+0,1,0,1,1,1,0,
+1,1,0,1,0,1,0,
+1,0,0,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,0,0,0,
+1,1,0,1,1,0,0,
+1,1,0,1,1,0,0,
+1,1,0,1,1,0,0,
+0,1,1,1,0,0,0,
+1,1,0,1,0,1,0,
+1,1,0,1,1,1,0,
+1,1,0,1,1,0,0,
+0,1,1,1,0,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,1,0,0,
+0,0,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,0,0,1,0,0,
+0,0,1,1,0,0,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+0,0,1,1,0,0,0,
+0,1,0,0,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,1,0,0,
+0,0,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,1,0,0,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,0,0,1,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,1,0,0,0,
+1,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,1,1,1,0,0,
+0,1,1,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,1,1,1,0,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,
+0,0,0,1,1,1,0,
+0,0,1,1,1,1,0,
+0,1,1,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,1,0,0,
+0,0,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,
+0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+1,1,0,0,0,0,0,
+0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,0,0,0,
+0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,
+0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,0,0,0,1,1,0,
+1,0,0,0,1,1,0,
+1,0,1,1,1,1,0,
+1,0,1,0,1,1,0,
+1,0,1,1,1,1,0,
+1,0,0,0,0,0,0,
+1,0,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,1,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,0,1,0,
+1,1,0,0,1,1,0,
+1,1,0,1,1,0,0,
+1,1,1,1,0,0,0,
+1,1,1,0,0,0,0,
+1,1,1,1,0,0,0,
+1,1,0,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,0,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,0,0,0,0,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,0,1,1,0,
+1,1,1,0,1,1,0,
+1,1,1,1,1,1,0,
+1,1,0,1,1,1,0,
+1,1,0,1,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,0,1,1,0,
+1,1,0,1,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,0,0,
+1,1,1,1,0,0,0,
+1,1,0,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,0,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,0,0,1,0,0,
+0,1,0,0,1,0,0,
+0,1,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+1,1,0,0,1,1,0,
+1,0,0,0,0,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,0,0,0,0,1,0,
+1,1,0,0,1,1,0,
+0,1,0,0,1,0,0,
+0,1,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,1,1,1,1,0,0,
+0,1,0,0,1,0,0,
+1,1,0,0,1,1,0,
+1,0,0,0,0,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,1,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,0,0,0,0,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,0,0,0,
+0,1,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,
+0,1,1,1,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,1,1,1,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,1,0,
+1,1,0,0,0,0,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,1,0,0,
+0,1,1,0,1,1,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+1,1,1,1,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,0,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+1,1,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,1,1,0,0,
+1,1,1,1,0,0,0,
+1,1,1,1,0,0,0,
+1,1,0,1,1,0,0,
+1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,1,1,0,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,0,1,1,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,1,1,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,1,1,1,1,0,
+1,1,1,1,1,1,0,
+0,1,0,0,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+0,1,1,1,1,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,1,0,
+0,0,0,0,1,1,0,
+1,1,0,0,1,1,0,
+0,1,1,1,1,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,
+0,0,0,0,1,1,0,
+0,0,0,1,1,0,0,
+0,1,1,0,0,0,0,
+1,1,0,0,0,0,0,
+1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,1,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,
+0,1,1,0,0,0,0,
+0,1,1,0,0,0,0,
+0,0,1,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,1,0,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,
+0,0,0,1,1,0,0,
+0,1,1,1,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,1,1,0,0,1,0,
+1,1,1,1,1,1,0,
+1,0,0,1,1,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+
+0,1,0,1,0,1,0,
+0,0,1,0,1,0,0,
+0,1,0,1,0,1,0,
+0,0,1,0,1,0,0,
+0,1,0,1,0,1,0,
+0,0,1,0,1,0,0,
+0,1,0,1,0,1,0,
+0,0,1,0,1,0,0,
+0,1,0,1,0,1,0,
+0,0,1,0,1,0,0,
+0,1,0,1,0,1,0,
+0,0,1,0,1,0,0,
+0,1,0,1,0,1,0
+};
+
+gdFont gdFontMediumBoldRep = {
+ 128,
+ 0,
+ 7,
+ 13,
+ gdFontMediumBoldData
+};
+
+gdFontPtr gdFontMediumBold = &gdFontMediumBoldRep;
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/Makefile.in
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/Makefile.in (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/Makefile.in Sat Jul 13 18:46:18 2002
@@ -0,0 +1,38 @@
+# things that the GNU standards document suggests all makefiles
+# should have.
+SHELL = /bin/sh
+.SUFFIXES:
+.SUFFIXES: .c .o .pl .pm .pod .html .man
+
+CC=@CC@
+AR=ar
+CFLAGS_EXTRA = @CFLAGS_EXTRA@
+CFLAGS = @CFLAGS@ # -pg
+CFLAGS_ALL = $(CFLAGS) $(CFLAGS_EXTRA)
+LIBS = -L. -lgd -lm
+
+all: libgd.a gddemo giftogd webgif
+
+gddemo: gddemo.o libgd.a gd.h gdfonts.h gdfontl.h
+ $(CC) gddemo.o -o gddemo $(LIBS)
+
+giftogd: giftogd.o libgd.a gd.h
+ $(CC) giftogd.o -o giftogd $(LIBS)
+
+libgd.a: gd.o gdfontt.o gdfonts.o gdfontmb.o gdfontl.o gdfontg.o \
+ gd.h gdfontt.h gdfonts.h gdfontmb.h gdfontl.h gdfontg.h
+ rm -f libgd.a
+ $(AR) rc libgd.a gd.o gdfontt.o gdfonts.o gdfontmb.o \
+ gdfontl.o gdfontg.o
+
+webgif: webgif.o libgd.a gd.h
+ $(CC) webgif.o -o webgif $(LIBS)
+
+clean:
+ -rm -f *.o *.a gddemo giftogd
+
+realclean: clean
+ -rm -f Makefile
+
+.c.o:
+ $(CC) $(CFLAGS_ALL) -c $<
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontl.h
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontl.h (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontl.h Sat Jul 13 18:46:18 2002
@@ -0,0 +1,15 @@
+#ifndef GDFONTL_H
+#define GDFONTL_H 1
+
+/* gdfontl.h: brings in the larger of the two provided fonts.
+ Also link with gdfontl.c. */
+
+#include "gd.h"
+
+/* 8x16 font derived from a public domain font in the X
+ distribution. Only contains the 96 standard ascii characters,
+ sorry. Feel free to improve on this. */
+
+extern gdFontPtr gdFontLarge;
+
+#endif
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/webgif.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/webgif.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/webgif.c Sat Jul 13 18:46:18 2002
@@ -0,0 +1,164 @@
+/* Bring in the gd library functions */
+#include "gd.h"
+
+/* Bring in standard I/O and string manipulation functions */
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char **argv)
+{
+ FILE *in;
+ FILE *out;
+ /* Declare our image pointer */
+ gdImagePtr im = 0;
+ int i;
+ /* We'll clear 'no' once we know the user has made a
+ reasonable request. */
+ int no = 1;
+ /* We'll set 'write' once we know the user's request
+ requires that the image be written back to disk. */
+ int write = 0;
+ /* C programs always get at least one argument; we want at
+ least one more (the image), more in practice. */
+ if (argc < 2) {
+ no = 1;
+ goto usage;
+ }
+ /* The last argument should be the image. Open the file. */
+ in = fopen(argv[argc-1], "rb");
+ if (!in) {
+ fprintf(stderr,
+ "Error: can't open file %s.\n", argv[argc-1]);
+ }
+ /* Now load the image. */
+ im = gdImageCreateFromGif(in);
+ fclose(in);
+ /* If the load failed, it must not be a GIF file. */
+ if (!im) {
+ fprintf(stderr,
+ "Error: %s is not a valid gif file.\n", argv[1]);
+ exit(1);
+ }
+ /* Consider each argument in turn. */
+ for (i=1; (i < (argc-1)); i++) {
+ /* -i turns on and off interlacing. */
+ if (!strcmp(argv[i], "-i")) {
+ if (i == (argc-2)) {
+ fprintf(stderr,
+ "Error: -i specified without y or n.\n");
+ no = 1;
+ goto usage;
+ }
+ if (!strcmp(argv[i+1], "y")) {
+ /* Set interlace. */
+ gdImageInterlace(im, 1);
+ } else if (!strcmp(argv[i+1], "n")) {
+ /* Clear interlace. */
+ gdImageInterlace(im, 0);
+ } else {
+ fprintf(stderr,
+ "Error: -i specified without y or n.\n");
+ no = 1;
+ goto usage;
+ }
+ i++;
+ no = 0;
+ write = 1;
+ } else if (!strcmp(argv[i], "-t")) {
+ /* Set transparent index (or none). */
+ int index;
+ if (i == (argc-2)) {
+ fprintf(stderr,
+ "Error: -t specified without a color table index.\n");
+ no = 1;
+ goto usage;
+ }
+ if (!strcmp(argv[i+1], "none")) {
+ /* -1 means not transparent. */
+ gdImageColorTransparent(im, -1);
+ } else {
+ /* OK, get an integer and set the index. */
+ index = atoi(argv[i+1]);
+ gdImageColorTransparent(im, index);
+ }
+ i++;
+ write = 1;
+ no = 0;
+ } else if (!strcmp(argv[i], "-l")) {
+ /* List the colors in the color table. */
+ int j;
+ /* Tabs used below. */
+ printf("Index Red Green Blue\n");
+ for (j=0; (j < gdImageColorsTotal(im)); j++) {
+ /* Use access macros to learn colors. */
+ printf("%d %d %d %d\n",
+ j,
+ gdImageRed(im, j),
+ gdImageGreen(im, j),
+ gdImageBlue(im, j));
+ }
+ no = 0;
+ } else if (!strcmp(argv[i], "-d")) {
+ /* Output dimensions, etc. */
+ int t;
+ printf("Width: %d Height: %d Colors: %d\n",
+ gdImageSX(im), gdImageSY(im),
+ gdImageColorsTotal(im));
+ t = gdImageGetTransparent(im);
+ if (t != (-1)) {
+ printf("Transparent index: %d\n", t);
+ } else {
+ /* -1 means the image is not transparent. */
+ printf("Transparent index: none\n");
+ }
+ if (gdImageGetInterlaced(im)) {
+ printf("Interlaced: yes\n");
+ } else {
+ printf("Interlaced: no\n");
+ }
+ no = 0;
+ } else {
+ fprintf(stderr, "Unknown argument: %s\n", argv[i]);
+ break;
+ }
+ }
+usage:
+ if (no) {
+ /* If the command failed, output an explanation. */
+ fprintf(stderr,
+ "Usage: webgif [-i y|n ] [-l] [-t index|off ] [-d] gifname.gif\n");
+ fprintf(stderr,
+ "Where -i controls interlace (specify y or n for yes or no),\n");
+ fprintf(stderr,
+ "-l outputs a table of color indexes, -t sets the specified\n");
+ fprintf(stderr,
+ "color index (0-255 or none) to be the transparent color, and\n");
+ fprintf(stderr,
+ "-d reports the dimensions and other characteristics of the image.\n");
+ fprintf(stderr,
+ "Note: you may wish to pipe to \"more\" when using the -l option.\n");
+ }
+ if (write) {
+ /* Open a temporary file. */
+ out = fopen("temp.tmp", "wb");
+ if (!out) {
+ fprintf(stderr,
+ "Unable to write to temp.tmp -- exiting\n");
+ exit(1);
+ }
+ /* Write the new gif. */
+ gdImageGif(im, out);
+ fclose(out);
+ /* Erase the old gif. */
+ unlink(argv[argc-1]);
+ /* Rename the new to the old. */
+ rename("temp.tmp", argv[argc-1]);
+ }
+ /* Delete the image from memory. */
+ if (im) {
+ gdImageDestroy(im);
+ }
+ /* All's well that ends well. */
+ return 0;
+}
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfonts.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfonts.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfonts.c Sat Jul 13 18:46:19 2002
@@ -0,0 +1,1261 @@
+#include "gdfonts.h"
+
+char gdFontSmallData[] = {
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,1,0,1,0,0,
+ 0,1,0,1,0,0,
+ 0,1,0,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,0,1,0,0,
+ 1,1,1,1,1,0,
+ 0,1,0,1,0,0,
+ 0,1,0,1,0,0,
+ 1,1,1,1,1,0,
+ 0,1,0,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,1,0,1,0,
+ 1,0,1,0,0,0,
+ 0,1,1,1,0,0,
+ 0,0,1,0,1,0,
+ 1,0,1,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 1,1,0,0,1,0,
+ 0,0,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,1,0,0,0,0,
+ 1,0,0,1,1,0,
+ 1,0,0,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,0,0,0,0,
+ 1,0,1,0,0,0,
+ 1,0,1,0,0,0,
+ 0,1,0,0,0,0,
+ 1,0,1,0,1,0,
+ 1,0,0,1,0,0,
+ 0,1,1,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,1,1,0,0,0,
+ 0,1,1,0,0,0,
+ 1,1,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,1,0,
+ 0,0,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,1,0,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 0,1,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,1,0,0,0,0,
+ 1,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 1,0,1,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,1,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,1,0,1,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,0,0,0,
+ 0,1,1,0,0,0,
+ 1,1,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,0,0,0,
+ 0,1,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,1,0,
+ 0,0,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,1,0,0,0,0,
+ 1,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,1,1,0,
+ 1,0,1,0,1,0,
+ 1,1,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,1,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,1,0,
+ 0,0,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,1,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,1,0,
+ 0,0,1,1,0,0,
+ 0,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,1,0,0,
+ 0,0,1,1,0,0,
+ 0,1,0,1,0,0,
+ 1,0,0,1,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,1,0,0,
+ 0,0,0,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 1,0,0,0,0,0,
+ 1,1,1,1,0,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,1,1,0,0,
+ 0,1,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,0,1,0,
+ 0,0,0,1,0,0,
+ 0,0,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,1,0,
+ 0,0,0,0,1,0,
+ 0,0,0,1,0,0,
+ 0,1,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,0,0,0,
+ 0,1,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,0,0,0,
+ 0,1,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,0,0,0,
+ 0,1,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,0,0,0,
+ 0,1,1,0,0,0,
+ 1,1,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,1,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,1,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 0,0,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,1,1,1,0,
+ 1,0,1,0,1,0,
+ 1,0,1,1,1,0,
+ 1,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,1,1,1,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,0,0,
+ 0,1,0,0,1,0,
+ 0,1,0,0,1,0,
+ 0,1,0,0,1,0,
+ 0,1,0,0,1,0,
+ 0,1,0,0,1,0,
+ 1,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,1,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,1,1,1,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,1,0,0,
+ 1,0,1,0,0,0,
+ 1,1,0,0,0,0,
+ 1,0,1,0,0,0,
+ 1,0,0,1,0,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,1,0,1,1,0,
+ 1,0,1,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,1,0,0,1,0,
+ 1,0,1,0,1,0,
+ 1,0,0,1,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,1,0,1,0,
+ 1,0,0,1,0,0,
+ 0,1,1,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,1,1,1,0,0,
+ 1,0,1,0,0,0,
+ 1,0,0,1,0,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,0,1,0,0,
+ 0,1,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,1,0,1,0,
+ 1,1,0,1,1,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,1,0,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,0,1,0,
+ 0,0,0,1,0,0,
+ 1,1,1,1,1,0,
+ 0,1,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,1,1,1,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 0,1,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,1,0,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 1,1,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 1,1,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,1,0,1,0,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,1,1,0,0,
+ 0,0,1,1,0,0,
+ 0,0,0,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,1,0,
+ 0,1,1,1,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 0,1,1,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,1,0,
+ 0,1,1,1,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,1,1,0,0,
+ 0,1,0,0,1,0,
+ 0,1,0,0,0,0,
+ 1,1,1,0,0,0,
+ 0,1,0,0,0,0,
+ 0,1,0,0,0,0,
+ 0,1,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,1,0,
+ 0,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,1,0,0,
+ 1,1,1,0,0,0,
+ 1,0,0,1,0,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,0,1,0,0,
+ 1,0,1,0,1,0,
+ 1,0,1,0,1,0,
+ 1,0,1,0,1,0,
+ 1,0,1,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,1,1,0,0,
+ 1,1,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,1,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,1,1,0,0,
+ 1,1,0,0,1,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,1,1,1,1,0,
+ 1,0,0,0,0,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,1,0,
+ 1,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,1,0,1,0,
+ 1,0,1,0,1,0,
+ 0,1,0,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 0,1,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,1,0,1,0,0,
+ 1,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 0,1,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,1,0,0,0,0,
+ 1,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,1,0,0,
+ 0,1,1,1,0,0,
+ 0,1,0,0,0,0,
+ 1,1,1,1,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,1,0,
+ 0,0,0,1,0,0,
+ 0,0,0,1,0,0,
+ 0,0,0,1,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,1,0,0,
+ 0,0,0,1,0,0,
+ 0,0,0,1,0,0,
+ 0,0,0,0,1,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,1,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 0,1,0,0,0,0,
+ 0,1,0,0,0,0,
+ 0,1,0,0,0,0,
+ 0,0,1,0,0,0,
+ 0,1,0,0,0,0,
+ 0,1,0,0,0,0,
+ 0,1,0,0,0,0,
+ 1,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,1,1,0,1,0,
+ 1,0,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,0,0,0,0,0,
+ 1,1,1,1,0,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,0,0,0,1,0,
+ 1,1,1,1,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0,
+ 0,0,0,0,0,0
+};
+
+gdFont gdFontSmallRep = {
+ 96,
+ 32,
+ 6,
+ 12,
+ gdFontSmallData
+};
+
+gdFontPtr gdFontSmall = &gdFontSmallRep;
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.dsw
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.dsw (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.dsw Sat Jul 13 18:46:19 2002
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "gd"=".\gd.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontt.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontt.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontt.c Sat Jul 13 18:46:19 2002
@@ -0,0 +1,1167 @@
+#include "gdfontt.h"
+
+char gdFontTinyData[] = {
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,0,
+0,1,1,1,0,
+1,1,1,1,1,
+0,1,1,1,0,
+0,0,1,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,1,
+0,1,0,1,0,
+0,0,1,0,1,
+0,1,0,1,0,
+0,0,1,0,1,
+0,1,0,1,0,
+0,0,1,0,1,
+
+0,1,0,1,0,
+0,1,0,1,0,
+0,1,1,1,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,0,1,1,1,
+0,0,0,1,0,
+0,0,0,1,0,
+
+1,1,1,0,0,
+1,0,0,0,0,
+1,1,0,0,0,
+1,0,1,1,1,
+1,0,1,0,0,
+0,0,1,1,0,
+0,0,1,0,0,
+0,0,1,0,0,
+
+0,1,1,0,0,
+1,0,0,0,0,
+0,1,1,0,0,
+0,0,0,0,0,
+0,0,1,1,0,
+0,0,1,0,1,
+0,0,1,1,0,
+0,0,1,0,1,
+
+1,0,0,0,0,
+1,0,0,0,0,
+1,0,0,0,0,
+1,1,1,0,0,
+0,0,1,1,1,
+0,0,1,0,0,
+0,0,1,1,0,
+0,0,1,0,0,
+
+0,0,0,0,0,
+0,1,1,1,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,1,1,1,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,0,
+0,1,1,1,0,
+0,0,1,0,0,
+0,0,0,0,0,
+0,1,1,1,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+1,0,0,1,0,
+1,1,0,1,0,
+1,0,1,1,0,
+1,0,0,1,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,1,1,
+
+1,0,1,0,0,
+1,0,1,0,0,
+1,0,1,0,0,
+0,1,0,0,0,
+0,0,1,1,1,
+0,0,0,1,0,
+0,0,0,1,0,
+0,0,0,1,0,
+
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+1,1,1,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+1,1,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,1,1,1,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,1,1,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+1,1,1,1,1,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+
+0,0,0,0,0,
+0,1,1,1,1,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,1,1,1,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,1,1,1,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,1,1,1,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,1,1,1,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,1,1,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+1,1,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+1,1,1,1,1,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+1,1,1,1,1,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+
+0,0,0,0,0,
+0,0,0,1,0,
+0,0,1,0,0,
+0,1,0,0,0,
+0,0,1,0,0,
+0,0,0,1,0,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,0,
+0,0,1,0,0,
+0,0,0,1,0,
+0,0,1,0,0,
+0,1,0,0,0,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+1,1,1,1,1,
+0,1,0,1,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,1,0,
+1,1,1,1,1,
+0,0,1,0,0,
+1,1,1,1,1,
+0,1,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,1,1,0,
+0,1,0,0,1,
+1,1,1,0,0,
+0,1,0,0,0,
+0,1,1,1,0,
+1,1,0,1,1,
+0,1,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,1,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,0,0,0,
+0,0,1,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,1,0,1,0,
+0,1,0,1,0,
+1,1,1,1,1,
+0,1,0,1,0,
+1,1,1,1,1,
+0,1,0,1,0,
+0,1,0,1,0,
+0,0,0,0,0,
+
+0,0,1,0,0,
+0,1,1,1,0,
+1,0,1,0,0,
+0,1,1,1,0,
+0,0,1,0,1,
+0,1,1,1,0,
+0,0,1,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,0,
+0,1,0,1,0,
+0,0,1,0,0,
+0,1,0,1,0,
+0,0,0,1,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,1,0,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,0,1,0,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,0,1,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,0,1,0,0,
+0,1,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,1,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,0,1,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,1,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,1,
+0,0,1,1,0,
+0,1,1,1,1,
+0,0,1,1,0,
+0,1,0,0,1,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+1,1,1,1,1,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,1,1,0,
+0,0,1,0,0,
+0,1,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,1,1,1,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,1,0,0,
+0,1,1,1,0,
+0,0,1,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,1,
+0,0,0,0,1,
+0,0,0,1,0,
+0,0,1,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,0,1,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,0,
+0,1,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,0,0,0,1,
+0,0,1,1,0,
+0,1,0,0,0,
+0,1,1,1,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,0,0,1,0,
+0,0,0,0,1,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,1,0,
+0,0,1,1,0,
+0,1,0,1,0,
+0,1,1,1,1,
+0,0,0,1,0,
+0,0,0,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,1,1,1,
+0,1,0,0,0,
+0,1,1,1,0,
+0,0,0,0,1,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,0,
+0,1,0,1,0,
+0,1,1,0,1,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,1,1,1,
+0,0,0,0,1,
+0,0,0,1,0,
+0,0,0,1,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,0,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,1,0,1,1,
+0,0,1,0,1,
+0,0,0,0,1,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,0,1,1,0,
+0,0,0,0,0,
+0,0,1,1,0,
+0,0,1,1,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,0,1,1,0,
+0,0,0,0,0,
+0,0,1,1,0,
+0,0,1,0,0,
+0,1,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,1,0,
+0,0,1,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,0,1,0,0,
+0,0,0,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,1,1,0,
+0,0,0,0,0,
+0,1,1,1,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,0,
+0,0,1,0,0,
+0,0,0,1,0,
+0,0,0,1,0,
+0,0,1,0,0,
+0,1,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,0,
+0,1,0,1,0,
+0,0,0,1,0,
+0,0,1,0,0,
+0,0,0,0,0,
+0,0,1,0,0,
+0,0,0,0,0,
+
+0,0,1,1,0,
+0,1,0,0,1,
+1,0,0,1,1,
+1,0,1,0,1,
+1,0,1,0,1,
+1,0,0,1,0,
+0,1,0,0,0,
+0,0,1,1,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,1,1,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,1,1,0,
+0,1,0,0,1,
+0,1,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,1,1,1,
+0,1,0,0,0,
+0,1,1,1,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,1,1,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,1,1,1,
+0,1,0,0,0,
+0,1,1,1,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,1,0,0,0,
+0,1,0,1,1,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,1,1,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,1,1,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,1,
+0,0,0,0,1,
+0,0,0,0,1,
+0,0,0,0,1,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,1,
+0,1,0,1,0,
+0,1,1,0,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,1,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,1,
+0,1,1,1,1,
+0,1,1,1,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,1,
+0,1,1,0,1,
+0,1,1,1,1,
+0,1,0,1,1,
+0,1,0,1,1,
+0,1,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,1,1,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,1,0,1,
+0,1,0,1,1,
+0,0,1,1,0,
+0,0,0,0,1,
+
+0,0,0,0,0,
+0,1,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,1,1,0,
+0,1,0,1,1,
+0,1,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,0,1,0,0,
+0,0,0,1,0,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+1,1,1,1,1,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,1,1,1,
+0,1,1,1,1,
+0,1,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+1,0,0,0,1,
+1,0,0,0,1,
+0,1,0,1,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,1,1,1,
+0,0,0,0,1,
+0,0,0,1,0,
+0,0,1,0,0,
+0,1,0,0,0,
+0,1,1,1,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,1,1,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,0,1,0,0,
+0,0,0,1,0,
+0,0,0,0,1,
+0,0,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,1,1,0,
+0,0,0,1,0,
+0,0,0,1,0,
+0,0,0,1,0,
+0,0,0,1,0,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+1,1,1,1,1,
+
+0,0,0,0,0,
+0,1,1,0,0,
+0,1,0,0,0,
+0,0,1,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,1,0,1,
+0,1,0,1,1,
+0,1,0,1,1,
+0,0,1,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,1,
+0,0,0,0,1,
+0,0,1,0,1,
+0,1,0,1,1,
+0,1,0,1,1,
+0,0,1,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,1,1,1,
+0,1,0,0,0,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,1,0,
+0,0,1,0,1,
+0,0,1,0,0,
+0,1,1,1,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,0,1,1,1,
+0,0,0,0,1,
+0,0,1,1,0,
+
+0,0,0,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,0,
+0,0,0,0,0,
+0,1,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,1,0,
+0,0,0,0,0,
+0,0,0,1,0,
+0,0,0,1,0,
+0,0,0,1,0,
+0,1,0,1,0,
+0,0,1,0,0,
+
+0,0,0,0,0,
+0,1,0,0,0,
+0,1,0,0,0,
+0,1,0,0,1,
+0,1,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,1,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,0,1,0,
+1,0,1,0,1,
+1,0,1,0,1,
+1,0,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,1,1,0,
+0,1,0,0,1,
+0,1,1,1,0,
+0,1,0,0,0,
+0,1,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,1,1,1,
+0,1,0,0,1,
+0,0,1,1,1,
+0,0,0,0,1,
+0,0,0,0,1,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,0,1,0,
+0,1,1,0,1,
+0,1,0,0,0,
+0,1,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,1,1,0,
+0,1,1,0,0,
+0,0,0,1,0,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,1,1,1,0,
+0,0,1,0,0,
+0,0,1,0,1,
+0,0,0,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,1,1,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,1,0,1,0,
+0,0,1,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+1,0,0,0,1,
+1,0,1,0,1,
+1,0,1,0,1,
+0,1,1,1,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,0,0,1,
+0,0,1,1,0,
+0,0,1,1,0,
+0,1,0,0,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,0,0,1,
+0,1,0,0,1,
+0,0,1,1,1,
+0,1,0,0,1,
+0,0,1,1,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,1,1,1,1,
+0,0,0,1,0,
+0,0,1,0,0,
+0,1,1,1,1,
+0,0,0,0,0,
+
+0,0,0,1,1,
+0,0,1,0,0,
+0,0,0,1,0,
+0,1,1,0,0,
+0,0,0,1,0,
+0,0,1,0,0,
+0,0,0,1,1,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,1,0,0,
+0,0,0,0,0,
+
+0,1,1,0,0,
+0,0,0,1,0,
+0,0,1,0,0,
+0,0,0,1,1,
+0,0,1,0,0,
+0,0,0,1,0,
+0,1,1,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,1,0,1,
+0,1,0,1,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0,
+0,0,0,0,0
+};
+
+gdFont gdFontTinyRep = {
+ 128,
+ 0,
+ 5,
+ 8,
+ gdFontTinyData
+};
+
+gdFontPtr gdFontTiny = &gdFontTinyRep;
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontmb.h
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontmb.h (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontmb.h Sat Jul 13 18:46:19 2002
@@ -0,0 +1,14 @@
+#ifndef GDFONTMB_H
+#define GDFONTMB_H 1
+
+/* gdfontmb.h: brings in the middle of the provided fonts.
+ Also link with gdfonth.c. */
+
+#include "gd.h"
+
+/* 7x13B font derived from a public domain font in the X
+ distribution. Contains the 127 standard ascii characters. */
+
+extern gdFontPtr gdFontMediumBold;
+
+#endif
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfonts.h
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfonts.h (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfonts.h Sat Jul 13 18:46:19 2002
@@ -0,0 +1,15 @@
+#ifndef GDFONTS_H
+#define GDFONTS_H 1
+
+/* gdfonts.h: brings in the smaller of the two provided fonts.
+ Also link with gdfonts.c. */
+
+#include "gd.h"
+
+/* 6x12 font derived from a public domain font in the X
+ distribution. Only contains the 96 standard ascii characters,
+ sorry. Feel free to improve on this. */
+
+extern gdFontPtr gdFontSmall;
+
+#endif
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontt.h
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontt.h (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontt.h Sat Jul 13 18:46:19 2002
@@ -0,0 +1,14 @@
+#ifndef GDFONTT_H
+#define GDFONTT_H 1
+
+/* gdfontt.h: brings in the tinyest of the provided fonts.
+ Also link with gdfontt.c. */
+
+#include "gd.h"
+
+/* 5x8 font derived from a public domain font in the X
+ distribution. Contains the 127 standard ascii characters. */
+
+extern gdFontPtr gdFontTiny;
+
+#endif
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/README
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/README (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/README Sat Jul 13 18:46:20 2002
@@ -0,0 +1,70 @@
+This is the gd gif-manipulating library, version 1.2. It was
+created to allow graphs, charts and the like to be generated on the
+fly for use on the World wide Web, but is useful for any
+application in which custom .GIFs are useful. It is not a paint
+program; it is a library. If you are looking for a paint program
+for the X Window System, check out David Koblas "xpaint", available
+by anonymous FTP from ftp.netcom.com in pub/ko/koblas. (I'm just a
+fan of Dave's code.)
+
+NOTE TO THE IMPATIENT: the Sun 'cc' compiler shipped
+standard with SunOS 4.1.3 is NOT AN ANSI C COMPILER and
+will not compile gd. Get and use gcc if you don't
+already have it, or use Sun's own commercial-grade
+ANSI C compiler if you prefer to purchase it.
+"What's new in gd 1.2?"
+
+Many bug fixes, ANSI C compliance, several new fonts and more.
+
+"Where's the manual?"
+
+Load gd.html into your web browser. Print it if you like,
+but <em>every single reference to a function is a hyperlink</em>,
+so the manual is especially good when read online! Note
+that the entire manual is one document, so it should be
+reasonably pleasant to read offline when printed.
+
+COPYRIGHT 1994,1995 BY THE QUEST CENTER AT COLD SPRING HARBOR LABS.
+Permission granted for unlimited use, provided that
+Thomas Boutell and the Quest Center at Cold Spring Harbor Labs are given
+credit for the library in the user-visible documentation of
+your software. If you modify gd, we ask that you share the
+modifications with us so they can be added to the
+distribution. See gd.html for details.
+
+gd has been compiled in various forms on all major platforms.
+It is happiest on a machine with 32-bit addressing and
+a proper stack (ie, anything running Unix, VMS, Windows NT
+or any other modern operating system), but is entirely
+usable under DOS and Windows. Note, however, that the
+flood-fill routines are mildly recursive and may fail on machines
+with tiny stack areas. Also, the fonts require a significant
+amount of memory (they are optimized more for speed than
+for size), but they need not be linked by applications that
+do not use them. Otherwise the code is highly
+portable as long as you have an ANSI C compiler.
+
+Full documentation is provided in HTML (World Wide Web) format
+in the file gd.html (part of this distribution). You can access the
+latest version of the file at the URL "http://siva.cshl.org/gd/gd.html".
+If you are unfamiliar with the World Wide Web, consult the Frequently
+Asked Questions posting of the appropriate comp.infosystems.www.browsers
+subgroup for your operating system to obtain
+more information on where to locate a hypertext browser.
+The text-based browser "Lynx" does a particularly good job
+of navigating the manual and will run on nearly anything.
+Netscape works fine too.
+
+If you don't have the patience to consult the manual
+first, build and examine gddemo.c (see the Makefile)
+and run it. It will read in demoin.gif and output
+demoout.gif, which you will want to examine with your
+GIF viewer to see the results.
+
+Tom Boutell, boutell at boutell.com
+
+http://sunsite.unc.edu/boutell/index.html
+
+P.O. Box 20837
+Seattle, WA 98102
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/giftogd.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/giftogd.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/giftogd.c Sat Jul 13 18:46:20 2002
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include "gd.h"
+
+/* A short program which converts a .gif file into a .gd file, for
+ your convenience in creating images on the fly from a
+ basis image that must be loaded quickly. The .gd format
+ is not intended to be a general-purpose format. */
+
+int main(int argc, char **argv)
+{
+ gdImagePtr im;
+ FILE *in, *out;
+ if (argc != 3) {
+ fprintf(stderr, "Usage: giftogd filename.gif filename.gd\n");
+ exit(1);
+ }
+ in = fopen(argv[1], "rb");
+ if (!in) {
+ fprintf(stderr, "Input file does not exist!\n");
+ exit(1);
+ }
+ im = gdImageCreateFromGif(in);
+ fclose(in);
+ if (!im) {
+ fprintf(stderr, "Input is not in GIF format!\n");
+ exit(1);
+ }
+ out = fopen(argv[2], "wb");
+ if (!out) {
+ fprintf(stderr, "Output file cannot be written to!\n");
+ gdImageDestroy(im);
+ exit(1);
+ }
+ gdImageGd(im, out);
+ fclose(out);
+ gdImageDestroy(im);
+}
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/mathmake.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/mathmake.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/mathmake.c Sat Jul 13 18:46:20 2002
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <math.h>
+
+#define scale 1024
+
+int basis[91];
+int cost[360];
+
+main(void) {
+ int i;
+ printf("#define costScale %d\n", scale);
+ printf("int cost[] = {\n ");
+ for (i=0; (i <= 90); i++) {
+ basis[i] = cos((double)i * .0174532925) * scale;
+ }
+ for (i=0; (i < 90); i++) {
+ printf("%d,\n ", cost[i] = basis[i]);
+ }
+ for (i=90; (i < 180); i++) {
+ printf("%d,\n ", cost[i] = -basis[180-i]);
+ }
+ for (i=180; (i < 270); i++) {
+ printf("%d,\n ", cost[i] = -basis[i-180]);
+ }
+ for (i=270; (i < 359); i++) {
+ printf("%d,\n ", cost[i] = basis[360-i]);
+ }
+ printf("%d\n", cost[359] = basis[1]);
+ printf("};\n");
+ printf("#define sintScale %d\n", scale);
+ printf("int sint[] = {\n ");
+ for (i=0; (i<360); i++) {
+ int val;
+ val = cost[(i + 270) % 360];
+ if (i != 359) {
+ printf("%d,\n ", val);
+ } else {
+ printf("%d\n", val);
+ }
+ }
+ printf("};\n");
+}
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/mtables.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/mtables.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/mtables.c Sat Jul 13 18:46:20 2002
@@ -0,0 +1,726 @@
+#define costScale 1024
+int cost[] = {
+ 1024,
+ 1023,
+ 1023,
+ 1022,
+ 1021,
+ 1020,
+ 1018,
+ 1016,
+ 1014,
+ 1011,
+ 1008,
+ 1005,
+ 1001,
+ 997,
+ 993,
+ 989,
+ 984,
+ 979,
+ 973,
+ 968,
+ 962,
+ 955,
+ 949,
+ 942,
+ 935,
+ 928,
+ 920,
+ 912,
+ 904,
+ 895,
+ 886,
+ 877,
+ 868,
+ 858,
+ 848,
+ 838,
+ 828,
+ 817,
+ 806,
+ 795,
+ 784,
+ 772,
+ 760,
+ 748,
+ 736,
+ 724,
+ 711,
+ 698,
+ 685,
+ 671,
+ 658,
+ 644,
+ 630,
+ 616,
+ 601,
+ 587,
+ 572,
+ 557,
+ 542,
+ 527,
+ 512,
+ 496,
+ 480,
+ 464,
+ 448,
+ 432,
+ 416,
+ 400,
+ 383,
+ 366,
+ 350,
+ 333,
+ 316,
+ 299,
+ 282,
+ 265,
+ 247,
+ 230,
+ 212,
+ 195,
+ 177,
+ 160,
+ 142,
+ 124,
+ 107,
+ 89,
+ 71,
+ 53,
+ 35,
+ 17,
+ 0,
+ -17,
+ -35,
+ -53,
+ -71,
+ -89,
+ -107,
+ -124,
+ -142,
+ -160,
+ -177,
+ -195,
+ -212,
+ -230,
+ -247,
+ -265,
+ -282,
+ -299,
+ -316,
+ -333,
+ -350,
+ -366,
+ -383,
+ -400,
+ -416,
+ -432,
+ -448,
+ -464,
+ -480,
+ -496,
+ -512,
+ -527,
+ -542,
+ -557,
+ -572,
+ -587,
+ -601,
+ -616,
+ -630,
+ -644,
+ -658,
+ -671,
+ -685,
+ -698,
+ -711,
+ -724,
+ -736,
+ -748,
+ -760,
+ -772,
+ -784,
+ -795,
+ -806,
+ -817,
+ -828,
+ -838,
+ -848,
+ -858,
+ -868,
+ -877,
+ -886,
+ -895,
+ -904,
+ -912,
+ -920,
+ -928,
+ -935,
+ -942,
+ -949,
+ -955,
+ -962,
+ -968,
+ -973,
+ -979,
+ -984,
+ -989,
+ -993,
+ -997,
+ -1001,
+ -1005,
+ -1008,
+ -1011,
+ -1014,
+ -1016,
+ -1018,
+ -1020,
+ -1021,
+ -1022,
+ -1023,
+ -1023,
+ -1024,
+ -1023,
+ -1023,
+ -1022,
+ -1021,
+ -1020,
+ -1018,
+ -1016,
+ -1014,
+ -1011,
+ -1008,
+ -1005,
+ -1001,
+ -997,
+ -993,
+ -989,
+ -984,
+ -979,
+ -973,
+ -968,
+ -962,
+ -955,
+ -949,
+ -942,
+ -935,
+ -928,
+ -920,
+ -912,
+ -904,
+ -895,
+ -886,
+ -877,
+ -868,
+ -858,
+ -848,
+ -838,
+ -828,
+ -817,
+ -806,
+ -795,
+ -784,
+ -772,
+ -760,
+ -748,
+ -736,
+ -724,
+ -711,
+ -698,
+ -685,
+ -671,
+ -658,
+ -644,
+ -630,
+ -616,
+ -601,
+ -587,
+ -572,
+ -557,
+ -542,
+ -527,
+ -512,
+ -496,
+ -480,
+ -464,
+ -448,
+ -432,
+ -416,
+ -400,
+ -383,
+ -366,
+ -350,
+ -333,
+ -316,
+ -299,
+ -282,
+ -265,
+ -247,
+ -230,
+ -212,
+ -195,
+ -177,
+ -160,
+ -142,
+ -124,
+ -107,
+ -89,
+ -71,
+ -53,
+ -35,
+ -17,
+ 0,
+ 17,
+ 35,
+ 53,
+ 71,
+ 89,
+ 107,
+ 124,
+ 142,
+ 160,
+ 177,
+ 195,
+ 212,
+ 230,
+ 247,
+ 265,
+ 282,
+ 299,
+ 316,
+ 333,
+ 350,
+ 366,
+ 383,
+ 400,
+ 416,
+ 432,
+ 448,
+ 464,
+ 480,
+ 496,
+ 512,
+ 527,
+ 542,
+ 557,
+ 572,
+ 587,
+ 601,
+ 616,
+ 630,
+ 644,
+ 658,
+ 671,
+ 685,
+ 698,
+ 711,
+ 724,
+ 736,
+ 748,
+ 760,
+ 772,
+ 784,
+ 795,
+ 806,
+ 817,
+ 828,
+ 838,
+ 848,
+ 858,
+ 868,
+ 877,
+ 886,
+ 895,
+ 904,
+ 912,
+ 920,
+ 928,
+ 935,
+ 942,
+ 949,
+ 955,
+ 962,
+ 968,
+ 973,
+ 979,
+ 984,
+ 989,
+ 993,
+ 997,
+ 1001,
+ 1005,
+ 1008,
+ 1011,
+ 1014,
+ 1016,
+ 1018,
+ 1020,
+ 1021,
+ 1022,
+ 1023,
+ 1023
+};
+#define sintScale 1024
+int sint[] = {
+ 0,
+ 17,
+ 35,
+ 53,
+ 71,
+ 89,
+ 107,
+ 124,
+ 142,
+ 160,
+ 177,
+ 195,
+ 212,
+ 230,
+ 247,
+ 265,
+ 282,
+ 299,
+ 316,
+ 333,
+ 350,
+ 366,
+ 383,
+ 400,
+ 416,
+ 432,
+ 448,
+ 464,
+ 480,
+ 496,
+ 512,
+ 527,
+ 542,
+ 557,
+ 572,
+ 587,
+ 601,
+ 616,
+ 630,
+ 644,
+ 658,
+ 671,
+ 685,
+ 698,
+ 711,
+ 724,
+ 736,
+ 748,
+ 760,
+ 772,
+ 784,
+ 795,
+ 806,
+ 817,
+ 828,
+ 838,
+ 848,
+ 858,
+ 868,
+ 877,
+ 886,
+ 895,
+ 904,
+ 912,
+ 920,
+ 928,
+ 935,
+ 942,
+ 949,
+ 955,
+ 962,
+ 968,
+ 973,
+ 979,
+ 984,
+ 989,
+ 993,
+ 997,
+ 1001,
+ 1005,
+ 1008,
+ 1011,
+ 1014,
+ 1016,
+ 1018,
+ 1020,
+ 1021,
+ 1022,
+ 1023,
+ 1023,
+ 1024,
+ 1023,
+ 1023,
+ 1022,
+ 1021,
+ 1020,
+ 1018,
+ 1016,
+ 1014,
+ 1011,
+ 1008,
+ 1005,
+ 1001,
+ 997,
+ 993,
+ 989,
+ 984,
+ 979,
+ 973,
+ 968,
+ 962,
+ 955,
+ 949,
+ 942,
+ 935,
+ 928,
+ 920,
+ 912,
+ 904,
+ 895,
+ 886,
+ 877,
+ 868,
+ 858,
+ 848,
+ 838,
+ 828,
+ 817,
+ 806,
+ 795,
+ 784,
+ 772,
+ 760,
+ 748,
+ 736,
+ 724,
+ 711,
+ 698,
+ 685,
+ 671,
+ 658,
+ 644,
+ 630,
+ 616,
+ 601,
+ 587,
+ 572,
+ 557,
+ 542,
+ 527,
+ 512,
+ 496,
+ 480,
+ 464,
+ 448,
+ 432,
+ 416,
+ 400,
+ 383,
+ 366,
+ 350,
+ 333,
+ 316,
+ 299,
+ 282,
+ 265,
+ 247,
+ 230,
+ 212,
+ 195,
+ 177,
+ 160,
+ 142,
+ 124,
+ 107,
+ 89,
+ 71,
+ 53,
+ 35,
+ 17,
+ 0,
+ -17,
+ -35,
+ -53,
+ -71,
+ -89,
+ -107,
+ -124,
+ -142,
+ -160,
+ -177,
+ -195,
+ -212,
+ -230,
+ -247,
+ -265,
+ -282,
+ -299,
+ -316,
+ -333,
+ -350,
+ -366,
+ -383,
+ -400,
+ -416,
+ -432,
+ -448,
+ -464,
+ -480,
+ -496,
+ -512,
+ -527,
+ -542,
+ -557,
+ -572,
+ -587,
+ -601,
+ -616,
+ -630,
+ -644,
+ -658,
+ -671,
+ -685,
+ -698,
+ -711,
+ -724,
+ -736,
+ -748,
+ -760,
+ -772,
+ -784,
+ -795,
+ -806,
+ -817,
+ -828,
+ -838,
+ -848,
+ -858,
+ -868,
+ -877,
+ -886,
+ -895,
+ -904,
+ -912,
+ -920,
+ -928,
+ -935,
+ -942,
+ -949,
+ -955,
+ -962,
+ -968,
+ -973,
+ -979,
+ -984,
+ -989,
+ -993,
+ -997,
+ -1001,
+ -1005,
+ -1008,
+ -1011,
+ -1014,
+ -1016,
+ -1018,
+ -1020,
+ -1021,
+ -1022,
+ -1023,
+ -1023,
+ -1024,
+ -1023,
+ -1023,
+ -1022,
+ -1021,
+ -1020,
+ -1018,
+ -1016,
+ -1014,
+ -1011,
+ -1008,
+ -1005,
+ -1001,
+ -997,
+ -993,
+ -989,
+ -984,
+ -979,
+ -973,
+ -968,
+ -962,
+ -955,
+ -949,
+ -942,
+ -935,
+ -928,
+ -920,
+ -912,
+ -904,
+ -895,
+ -886,
+ -877,
+ -868,
+ -858,
+ -848,
+ -838,
+ -828,
+ -817,
+ -806,
+ -795,
+ -784,
+ -772,
+ -760,
+ -748,
+ -736,
+ -724,
+ -711,
+ -698,
+ -685,
+ -671,
+ -658,
+ -644,
+ -630,
+ -616,
+ -601,
+ -587,
+ -572,
+ -557,
+ -542,
+ -527,
+ -512,
+ -496,
+ -480,
+ -464,
+ -448,
+ -432,
+ -416,
+ -400,
+ -383,
+ -366,
+ -350,
+ -333,
+ -316,
+ -299,
+ -282,
+ -265,
+ -247,
+ -230,
+ -212,
+ -195,
+ -177,
+ -160,
+ -142,
+ -124,
+ -107,
+ -89,
+ -71,
+ -53,
+ -35,
+ -17
+};
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontg.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontg.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontg.c Sat Jul 13 18:46:21 2002
@@ -0,0 +1,2061 @@
+#include "gdfontg.h"
+
+char gdFontGiantData[] = {
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,1,1,1,1,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,1,1,0,1,1,
+0,0,1,1,0,0,1,1,0,
+0,1,1,0,1,1,0,1,1,
+0,0,1,1,0,0,1,1,0,
+0,1,1,0,1,1,0,1,1,
+0,0,1,1,0,0,1,1,0,
+0,1,1,0,1,1,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,1,1,0,0,
+0,1,1,0,0,1,1,0,0,
+0,1,1,1,1,1,1,0,0,
+0,1,1,0,0,1,1,0,0,
+0,1,1,0,0,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,1,1,1,1,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,1,1,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,1,1,1,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,1,1,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,0,0,
+0,1,1,0,0,0,1,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,1,0,0,
+0,0,1,1,1,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,1,1,1,0,
+0,0,0,1,1,0,0,1,1,
+0,0,0,1,1,1,1,1,0,
+0,0,0,1,1,0,0,1,1,
+0,0,0,1,1,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,1,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,1,1,1,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,1,1,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,1,1,0,0,1,1,0,
+0,0,1,1,0,0,1,1,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,1,1,0,0,
+0,1,1,1,0,1,1,0,0,
+0,1,1,1,1,1,1,0,0,
+0,1,1,0,1,1,1,0,0,
+0,1,1,0,0,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,1,1,0,0,
+0,1,1,0,0,1,1,0,0,
+0,1,1,0,0,1,1,0,0,
+0,0,1,1,1,1,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,1,1,1,1,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+1,1,1,1,1,1,0,0,0,
+1,1,1,1,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+1,1,1,1,1,1,0,0,0,
+1,1,1,1,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,1,1,1,
+0,0,0,0,1,1,1,1,1,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,1,1,1,
+0,0,0,0,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,1,1,1,
+0,0,0,0,1,1,1,1,1,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+1,1,1,1,1,1,0,0,0,
+1,1,1,1,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,1,1,1,
+0,0,0,0,1,1,1,0,0,
+0,0,1,1,1,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,0,1,1,1,0,0,0,0,
+0,0,0,0,1,1,1,0,0,
+0,0,0,0,0,0,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,0,0,0,0,0,
+0,0,0,1,1,1,0,0,0,
+0,0,0,0,0,1,1,1,0,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,1,1,1,0,
+0,0,0,1,1,1,0,0,0,
+0,1,1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,1,1,1,1,1,1,1,1,
+0,0,0,1,0,0,1,1,0,
+0,0,0,1,0,0,1,1,0,
+0,0,0,1,0,0,1,1,0,
+0,1,1,1,0,0,1,1,0,
+0,1,1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,1,1,0,
+0,1,1,1,1,1,1,1,1,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,1,1,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,1,1,1,1,1,1,1,1,
+0,0,1,1,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,1,1,0,
+0,0,0,1,1,0,0,1,1,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,1,1,1,1,1,0,0,0,
+0,1,0,1,1,1,1,1,1,
+0,1,1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,0,1,1,0,
+0,0,0,1,1,0,1,1,0,
+0,0,0,1,1,0,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,0,1,1,0,0,
+0,0,1,1,0,1,1,0,0,
+0,1,1,1,1,1,1,1,0,
+0,0,1,1,0,1,1,0,0,
+0,0,1,1,0,1,1,0,0,
+0,1,1,1,1,1,1,1,0,
+0,0,1,1,0,1,1,0,0,
+0,0,1,1,0,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,1,0,0,0,
+0,0,0,1,1,1,1,1,0,
+0,0,1,1,0,1,0,1,1,
+0,0,1,1,0,1,0,0,0,
+0,0,1,1,1,1,0,0,0,
+0,0,0,1,1,1,1,1,0,
+0,0,0,0,0,1,1,1,1,
+0,0,0,0,0,1,0,1,1,
+0,0,1,1,0,1,0,1,1,
+0,0,0,1,1,1,1,1,0,
+0,0,0,0,0,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,1,1,
+0,1,1,1,1,0,1,1,0,
+0,1,1,1,1,0,1,1,0,
+0,0,1,1,0,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,0,1,1,0,
+0,0,1,1,0,1,1,1,1,
+0,0,1,1,0,1,1,1,1,
+0,1,1,0,0,0,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,0,0,0,
+0,1,1,0,0,1,1,0,0,
+0,1,1,0,0,1,1,0,0,
+0,1,1,0,0,1,1,0,0,
+0,0,1,1,1,1,0,0,0,
+0,1,1,0,0,1,1,0,0,
+0,1,1,0,0,1,1,1,1,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,1,1,1,0,
+0,0,1,1,1,1,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,1,1,0,
+0,0,0,0,1,1,1,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,0,0,0,0,
+0,1,1,0,1,0,1,1,0,
+0,0,1,1,1,1,1,0,0,
+0,0,0,1,1,1,0,0,0,
+0,1,1,1,0,1,1,1,0,
+0,0,0,1,1,1,0,0,0,
+0,0,1,1,1,1,1,0,0,
+0,1,1,0,1,0,1,1,0,
+0,0,0,0,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,1,1,1,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,1,1,0,0,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,0,0,1,1,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,1,0,0,0,
+0,0,1,1,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,1,1,1,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,1,1,1,1,0,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,1,1,1,0,
+0,0,0,0,1,1,1,1,0,
+0,0,0,1,1,0,1,1,0,
+0,0,1,1,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,0,
+0,1,1,1,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,1,1,1,0,
+0,0,1,1,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,0,
+0,1,1,1,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,1,1,1,
+0,0,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,1,1,0,
+0,0,1,1,1,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,1,1,1,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,1,1,1,1,1,
+0,1,1,1,1,0,0,1,1,
+0,1,1,1,1,0,1,1,1,
+0,1,1,0,1,1,1,1,1,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,1,1,0,0,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,1,1,1,1,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,0,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,1,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,0,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,1,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,1,1,1,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,1,1,1,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,1,1,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,1,1,1,1,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,1,1,1,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,0,1,1,1,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,1,1,0,0,
+0,1,1,0,1,1,0,0,0,
+0,1,1,1,1,0,0,0,0,
+0,1,1,1,1,0,0,0,0,
+0,1,1,0,1,1,0,0,0,
+0,1,1,0,0,1,1,0,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,1,0,0,1,1,1,
+0,1,1,1,1,1,1,1,1,
+0,1,1,1,1,1,1,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,1,0,0,0,1,1,
+0,1,1,1,1,0,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,0,1,1,1,1,
+0,1,1,0,0,0,1,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,0,1,1,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,1,1,1,1,1,0,
+0,1,1,0,1,1,0,0,0,
+0,1,1,0,0,1,1,0,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,0,0,1,1,0,
+0,0,1,1,0,0,1,1,0,
+0,0,1,1,0,0,1,1,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,1,1,1,1,1,1,
+0,0,1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,0,0,1,1,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,1,1,0,0,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,0,0,1,1,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,1,1,1,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,1,1,1,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,1,1,0,0,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,0,0,0,
+0,0,0,1,1,1,0,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,1,1,1,
+0,0,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,0,
+0,1,1,1,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,1,0,0,0,1,1,
+0,1,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,1,
+0,1,1,0,0,0,1,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,1,1,1,
+0,0,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,1,1,1,1,1,1,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,1,1,0,
+0,0,0,1,1,0,0,1,1,
+0,0,0,1,1,0,0,1,1,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,1,1,1,1,1,1,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,1,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,0,1,1,1,1,1,0,0,
+0,1,1,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,0,
+0,1,1,1,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,0,1,1,1,1,1,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,1,1,1,0,
+0,1,1,1,1,1,0,0,0,
+0,1,1,1,0,0,0,0,0,
+0,1,1,1,1,1,0,0,0,
+0,1,1,0,0,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,0,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,0,
+0,1,1,1,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,0,
+0,1,1,1,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,1,0,0,0,1,1,
+0,1,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+0,1,1,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,1,
+0,1,1,0,0,0,1,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,1,1,1,
+0,0,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+0,0,0,0,0,0,0,1,1,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,1,1,1,1,0,
+0,0,1,1,1,0,0,1,1,
+0,0,1,1,0,0,0,1,1,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,0,0,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,1,1,1,1,1,1,1,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,1,1,0,0,1,1,
+0,0,0,0,1,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,0,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,0,0,1,1,0,
+0,0,1,1,0,0,1,1,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,0,0,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,1,1,1,1,1,1,
+0,0,1,1,0,0,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,0,1,1,
+0,0,1,1,0,0,1,1,0,
+0,0,0,1,1,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,1,1,0,0,
+0,0,1,1,0,0,1,1,0,
+0,1,1,0,0,0,0,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,1,1,0,0,1,1,1,0,
+0,0,1,1,1,1,1,1,0,
+0,0,0,0,0,0,1,1,0,
+0,1,1,0,0,0,1,1,0,
+0,0,1,1,1,1,1,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,1,1,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,1,1,0,0,0,0,0,
+0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,1,1,1,1,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,1,1,1,0,0,0,
+0,0,0,1,1,1,0,0,0,
+0,0,0,0,0,1,1,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,1,1,1,1,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,1,1,1,1,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,0,1,1,1,0,0,
+0,0,0,0,1,1,1,0,0,
+0,0,0,1,1,0,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,0,0,0,1,1,0,0,0,
+0,1,1,1,1,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,1,1,1,0,0,1,1,
+0,1,1,0,1,1,0,1,1,
+0,1,1,0,0,1,1,1,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0
+};
+
+gdFont gdFontGiantRep = {
+ 128,
+ 0,
+ 9,
+ 15,
+ gdFontGiantData
+};
+
+gdFontPtr gdFontGiant = &gdFontGiantRep;
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/index.html
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/index.html (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/index.html Sat Jul 13 18:46:21 2002
@@ -0,0 +1,2184 @@
+<HTML>
+<HEAD>
+<TITLE>gd 1.2</TITLE>
+</HEAD>
+<BODY>
+<H1>gd 1.2</H1>
+<H2>A graphics library for fast GIF creation</H2>
+<H2>Follow this link to the
+<A HREF="http://www.boutell.com/gd/">latest version
+of this document</A>.</H2>
+<H3>Table of Contents</H3>
+<UL>
+<LI><A HREF="#notice">Credits and license terms</A>
+<LI><A HREF="#whatsnew1.2">What's new in version 1.2?</A>
+<LI><A HREF="#whatsnew1.1.1">What's new in version 1.1.1?</A>
+<LI><A HREF="#whatis">What is gd?</A>
+<LI><A HREF="#gdperl">What if I want to use Perl instead of C?</A>
+<LI><A HREF="#gdtcl">What if I want to use Tcl instead of C?</A>
+<LI><A HREF="#gdit">What if I want to use another scripting language?</A>
+<LI><A HREF="#required">What else do I need to use gd?</A>
+<LI><A HREF="#getgd">How do I get gd?</A>
+<LI><A HREF="#buildgd">How do I build gd?</A>
+<LI><A HREF="#basics">gd basics: using gd in your program</A>
+<LI><A HREF="#webgif">webgif: a useful example</A>
+<LI><A HREF="#reference">Function and type reference by category</A>
+<LI><A HREF="#gdformat">About the additional .gd image file format</A>
+<LI><A HREF="#informing"><strong>Please</strong>
+ tell us you're using gd!</A>
+<LI><A HREF="#problems">If you have problems</A>
+<LI><A HREF="#languages">Using gd from tcl</A></LI>
+<LI><A HREF="#index">Alphabetical quick index</A>
+</UL>
+<P><A HREF="http://www.boutell.com/">
+Up to the <EM>boutell.com, Inc. Home Page</EM></A>
+<A NAME="notice"><H3>Credits and license terms</A></H3>
+<P>
+gd 1.2 is copyright 1994, 1995, Quest Protein Database Center,
+Cold Spring Harbor Labs. Permission granted to copy and distribute
+this work provided that this notice remains intact. Credit
+for the library must be given to the Quest Protein Database Center,
+Cold Spring Harbor Labs, in all derived works. This does not
+affect your ownership of the derived work itself, and the intent
+is to assure proper credit for Quest, not to interfere with your
+use of gd. If you have questions, ask. ("Derived works"
+includes all programs that utilize the library. Credit must
+be given in user-visible documentation.)
+<p>
+gd 1.2 was written by Thomas Boutell and is currently
+distributed by boutell.com, Inc.
+<P>
+If you wish to release modifications to gd,
+please clear them first by sending email to
+boutell at boutell.com; if this is not done, any modified version of the gd
+library must be clearly labeled as such.
+<P>
+The Quest Protein Database Center is funded under Grant P41-RR02188 by
+the National Institutes of Health.
+<P>
+Written by <A HREF="http://sunsite.unc.edu/boutell/index.html">
+Thomas Boutell</A>, 2/94 - 8/95.
+<P>
+The GIF compression code is based on that found in the pbmplus
+utilities, which in turn is based on GIFENCOD by David Rowley. See the
+notice below:
+
+<PRE>
+/*
+** Based on GIFENCOD by David Rowley <mgardi at watdscu.waterloo.edu>.A
+** Lempel-Zim compression based on "compress".
+**
+** Modified by Marcel Wijkstra <wijkstra at fwi.uva.nl>
+**
+** Copyright (C) 1989 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+**
+** The Graphics Interchange Format(c) is the Copyright property of
+** CompuServe Incorporated. GIF(sm) is a Service Mark property of
+** CompuServe Incorporated.
+*/
+</PRE>
+<P>
+<A NAME="koblas">
+The GIF decompression is based on that found in the pbmplus
+utilities, which in turn is based on GIFDECOD by David Koblas. See the
+notice below:
+<PRE>
+/* +-------------------------------------------------------------------+ */
+/* | Copyright 1990, 1991, 1993, David Koblas. (koblas at netcom.com) | */
+/* | Permission to use, copy, modify, and distribute this software | */
+/* | and its documentation for any purpose and without fee is hereby | */
+/* | granted, provided that the above copyright notice appear in all | */
+/* | copies and that both that copyright notice and this permission | */
+/* | notice appear in supporting documentation. This software is | */
+/* | provided "as is" without express or implied warranty. | */
+/* +-------------------------------------------------------------------+ */
+</PRE>
+</A>
+<A NAME="whatis"><H3>What is gd?</H3></A>
+<P>
+gd is a graphics library. It allows your code to quickly
+draw images complete with lines, arcs, text, multiple
+colors, cut and paste from other images, and flood fills, and
+write out the result as a .GIF file. This is particularly
+useful in World Wide Web applications, where .GIF is the
+format used for inline images.
+<P>
+gd is not a paint program.
+If you are looking for a paint program, try xpaint by David
+Koblas, available by <A HREF="ftp://ftp.netcom.com/pub/ko/koblas">
+anonymous FTP</A> from ftp.netcom.com in pub/ko/koblas.
+(That package is for the X Window System; for the Mac and the PC, paint
+programs are considerably easier to find.)
+<P>
+gd does not provide for every possible desirable graphics
+operation. It is not necessary or desirable for gd to become
+a kitchen-sink graphics package, but version 1.2 incorporates
+most of the commonly requested features for a 2D package.
+Font support does need improvement, and support for the PNG
+graphics format will arrive in a forthcoming release.
+<P>
+<A NAME="gdperl"><H3>What if I want to use Perl instead of C?</H3></A>
+gd can also be used from Perl, courtesy of
+Lincoln Stein's
+<a href="http://www-genome.wi.mit.edu/ftp/pub/software/WWW/GD.html">
+GD.pm</a> library, which uses gd as the basis for a set of
+Perl 5.x classes. GD.pm is based on gd 1.1.1 but gd 1.2 should
+be compatible.
+<A NAME="gdtcl"><H3>What if I want to use Tcl instead of C?</H3></A>
+gd can also be used from Tcl by way of the
+<a href="http://guraldi.hgp.med.umich.edu/gdtcl.html">gdtcl</a>
+Tcl extension.
+<A NAME="gdit"><H3>What if I want to use another scripting language?</H3></A>
+There are, at the moment, at least three simple interpreters that
+perform gd operations. You can output the desired commands to a simple
+text file from whatever scripting language you prefer to use, then
+invoke the interpreter.
+<p>
+These packages are based on gd 1.1.1 as of this writing but should
+be compatible with gd 1.2 with minimal tweaking.
+<ul>
+<li><a href="http://www.demon.co.uk/3Wiz/gdit/">gdit</a>, by David
+Harvey-George
+<li><a href="http://s27w007.pswfs.gov/tgd/">tgd</a>, by Bradley K. Sherman
+<li><a href="http://www.unimelb.edu.au/fly/fly.html">fly</a>, by Martin Gleeson
+</ul>
+<P><A NAME="whatsnew1.2"><H3>What's new in version 1.2?</H3></A>
+Version 1.2 is another fine-tuning release. The next major release
+will after 1.2 will be version 2.0 and will feature support for
+the new <a href="http://sunsite.unc.edu/boutell/png.html">PNG</a>
+graphics format as well as improved font support. gd 1.2 does
+add several new fonts in the meantime.
+<p>
+Version 1.2 moves gd to ANSI standard C. Non-ANSI C compilers,
+such as the old SunOS 4.1.3 cc compiler, will not work. The use
+of pre-ANSI C led to several long-standing bugs, and the ANSI C
+standard has been with us for nearly ten years now. If your compiler
+does not support ANSI, upgrade to a recent release of your compiler,
+or get gcc, which is free and does support ANSI C.
+<P>
+The provided Unix Makefile has been changed to be a bit
+more broadly compatible, and to acknowledge the changes that
+may be necessary on various systems.
+<P>
+Version 1.2 also includes the following improvements:
+<P>
+<ul>
+<li><a href="#gdImageCopy">gdImageCopy</a> and
+<a href="#gdImageCopyResized">gdImageCopyResized</a> now ignore
+pixels which are transparent in the source image. This is allows
+easy copying of non-square regions, which could previously be
+accomplished only with brushes.
+<li><a href="#gdImageFilledPolygon">gdImageFilledPolygon</a>
+now draws horizontal edges correctly, correcting a
+long-standing bug. In addition, gdImageFilledPolygon copes
+with polygons which have several horizontal segments on
+the same scan line. There can still be a few pixels of
+disagreement between gdImagePolygon and gdImageFilledPolygon
+with regard to the borders of the polygon, however.
+<li>Several new public-domain fonts are included, courtesy of
+Joseph M. Orost at AT&T.
+<li>gd now properly recognizes an existing image with a
+high color slot number transparent.
+<li>Bugs in the <a href="#gdImageCreateFromXbm">gdImageCreateFromXbm</a>
+function have been corrected. Previously the function was incorrect
+for image widths not evenly divisible by eight.
+</ul>
+<P>
+<A NAME="whatsnew1.1.1"><H3>What's new in version 1.1.1?</H3></A>
+A fine-tuning and bug-fixing release.
+<P>
+<A HREF="#gdImageSetStyle">gdImageSetStyle</A> now copies
+the style array to make it easier to take advantage of
+the line styling feature; it is now safe to free the memory
+associated with your style array after setting a style
+(or allocate styles on the stack...). This should not break
+existing code.
+<P>
+<A HREF="#webgif">webgif</A>, a small but powerful GIF-manipulating
+utility program, has been added as an additional code example.
+<P>
+An access macro to determine
+whether an image is interlaced has been added; see
+<A HREF="gdImageGetInterlaced">gdImageGetInterlaced</A>.
+<P>
+A better Unix Makefile, provided by Mark Scott. Note that
+an actual library (libgd.a) is now produced; you will want
+to link with this library in your own gd apps, in the same
+manner that gddemo and giftogd link with it. You no longer
+need to explicitly list the standard font files on the link
+line. No doubt many users have already made this enhancement
+themselves.
+<p>
+<strong>Important:</strong> depending on your system you may
+need to rewrite this Makefile. Basic code-compiling skills
+are expected for the use of this library.
+<P>
+<A HREF="#koblas">David Koblas</A> has been given proper credit
+for the original GIF decoding routine; previously I erroneously
+credited David Rowley with both the encoder and the decoder.
+<P>
+<A HREF="#gdImageFill">gdImageFill</A> no longer crashes when
+attempting to fill a region with the color it already has.
+Also, attempting to fill a region with the special color
+<A HREF="#gdTiled">gdTiled</A> no longer crashes.
+<P>
+However, filling a region with a transparent tile has been
+forbidden (gdImageFill simply draws nothing in this case).
+Otherwise, gd would not know when to stop drawing
+without the use of an additional image to keep track of
+which pixels have been visited.
+<P>
+Invoking <A HREF="#gdImageFillToBorder">gdImageFillToBorder</A>
+with a special border color such as <A HREF="#gdTiled">gdTiled</A>
+now fails, for similar reasons. However, the color
+you are filling <em>with</em> can be <A HREF="#gdTiled">gdTiled</A>,
+even if it is transparent. See the discussion of
+<A HREF="#gdImageFillToBorder">gdImageFillToBorder</A> for
+additional caveats.
+<P>
+Many documentation fixes.
+<P>
+<A NAME="whatsnew1.1"><H3>What's new in version 1.1?</H3></A>
+<P>
+<UL>
+<LI><A HREF="#gdImageFilledPolygon">Polygon fills</A></LI>
+<LI><A HREF="#gdImageSetStyle">Line styling</A></LI>
+<LI><A HREF="#gdImageSetBrush">"Brushing" of lines with a brush image</A></LI>
+<LI><A HREF="#gdImageSetTile">Tiling of polygon, rectangle and flood-fills</A>
+<LI><A HREF="#gdImageInterlace">Interlaced GIFs for gradual fade-in</A></LI>
+</LI>
+<LI>Macros to access <A HREF="#gdImageSX">image size</A>, etc.</LI>
+</UL>
+<P>
+<A NAME="required"><H3>What else do I need to use gd?</H3></A>
+<P>
+To use gd, you will need an ANSI C compiler. Any full-ANSI-standard
+C compiler should be adequate, although those with PCs will need to replace
+the Makefile with one of their own. <strong>The cc compiler released
+with SunOS 4.1.3 is not an ANSI C compiler. Get gcc, which is freely
+available. See the Sun-related newsgroups for more information.</strong>
+<P>
+You will also want a GIF viewer, if you do not already have
+one for your system, since you will need a good way to check the
+results of your work. lview is a good package for
+Windows PCs; xv is a good package for X11. There are
+GIF viewers available for every graphics-capable
+computer out there, so consult newsgroups relevant to
+your particular system.
+<P>
+<A NAME="getgd"><H3>How do I get gd?</H3></A>
+<P>
+You can
+<A HREF="http://www.boutell.com/gd/gd1.2.tar.Z">
+fetch gd as a compressed tar file</A> from www.boutell.com.
+<A NAME="buildgd"><H3>How do I build gd?</H3></A>
+<P>
+In order to build gd, first uncompress and untar the gd.tar file with the
+following commands:
+<P>
+<em>Note:</em> if you have a non-Unix system, you will need
+to acquire versions of "uncompress" and "tar" suitable for
+your system. Both have been ported to PC and Mac
+environments. Consult newsgroups relevant to your
+particular system.
+<PRE>
+uncompress gd1.2.tar.Z
+tar -xf gd1.2.tar
+</PRE>
+This will create the directory "gd1.2" beneath the current
+directory.
+<P>
+cd to this directory and examine the Makefile, which you may need
+to change slightly depending on your installation (or more than
+slightly for a Windows or Mac environment).
+<P>
+Now, to build the demonstration program, just type "make gddemo"
+if you are working in a command-line environment. If all goes well,
+the program "gddemo" will be compiled and linked without incident.
+Depending on your system you may need to edit the Makefile.
+Understanding the basic techniques of compiling and linking
+programs on your system is up to you.
+<P>
+You have now built a demonstration program which shows off
+the capabilities of gd. To see it in action, type
+"gddemo".
+<P>
+gddemo should execute without incident, creating the file
+demoout.gif. (Note there is also a file named demoin.gif,
+which is provided in the package as part of the demonstration.)
+<P>
+Display demoout.gif in your GIF viewer. The image should
+be 128x128 pixels and should contain an image of the
+space shuttle with the word "hi" written in the upper
+left corner twice (once across and once upwards),
+an arc in the middle and an oval intersecting the arc
+(these are somewhat faint).
+<p>
+In addition, a diagonal line made up of tiny space shuttle
+images should appear from the lower left to the upper
+right corner. A blue frame with green interior trim should
+surround the picture.
+<P>
+(If you are missing the demoin.gif file, the other items
+should appear anyway.)
+<P>
+Look at demoin.gif to see the original space shuttle
+image which was scaled and copied into the output image.
+<P>
+<A NAME="basics"><H3>gd basics: using gd in your program</H3></A>
+gd lets you create GIF images on the fly. To use gd in your
+program, include the file gd.h, and link with the libgd.a
+library produced by "make libgd.a", under Unix. You will
+need to adapt the makefile for your needs if you are using
+a non-Unix operating system, but this is very straightforward.
+<P>
+If you want to use the provided fonts, include
+gdfontt.h, gdfonts.h, gdfontmb.h, gdfontl.h and/or gdfontg.h. If you
+are not using the provided Makefile and/or a library-based approach, be
+sure to include the source modules as well in your
+project. (They may be too large for 16-bit memory models,
+that is, 16-bit DOS and Windows.)
+<P>
+Here is a short example program. <strong>(For a more advanced example,
+see gddemo.c, included in the distribution. gddemo.c is NOT the same program;
+it demonstrates additional features!)</strong>
+<P>
+<PRE>
+/* Bring in gd library functions */
+#include "gd.h"
+
+/* Bring in standard I/O so we can output the GIF to a file */
+#include <stdio.h>
+
+int main() {
+ /* Declare the image */
+ <A HREF="#gdImagePtr">gdImagePtr</A> im;
+ /* Declare an output file */
+ FILE *out;
+ /* Declare color indexes */
+ int black;
+ int white;
+
+ /* Allocate the image: 64 pixels across by 64 pixels tall */
+ im = <A HREF="#gdImageCreate">gdImageCreate</A>(64, 64);
+
+ /* Allocate the color black (red, green and blue all minimum).
+ Since this is the first color in a new image, it will
+ be the background color. */
+ black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+
+ /* Allocate the color white (red, green and blue all maximum). */
+ white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+
+ /* Draw a line from the upper left to the lower right,
+ using white color index. */
+ <A HREF="#gdImageLine">gdImageLine</A>(im, 0, 0, 63, 63, white);
+
+ /* Open a file for writing. "wb" means "write binary", important
+ under MSDOS, harmless under Unix. */
+ out = fopen("test.gif", "wb");
+
+ /* Output the image to the disk file. */
+ <A HREF="#gdImageGif">gdImageGif</A>(im, out);
+
+ /* Close the file. */
+ fclose(out);
+
+ /* Destroy the image in memory. */
+ <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+}
+</PRE>
+When executed, this program creates an image, allocates
+two colors (the first color allocated becomes the background
+color), draws a diagonal line (note that 0, 0 is the upper
+left corner), writes the image to a GIF file, and
+destroys the image.
+<P>
+The above example program should
+give you an idea of how the package works.
+gd provides many additional functions, which are listed
+in the following reference chapters, complete with code
+snippets demonstrating each. There is also an
+<A HREF="#index">alphabetical index</A>.
+<H3><A NAME="webgif">Webgif: a more powerful gd example</A></H3>
+Webgif is a simple utility program to manipulate GIFs from the
+command line. It is written for Unix and similar command-line
+systems, but should be easily adapted for other environments.
+Webgif allows you to set transparency and interlacing and
+output interesting information about the GIF in question.
+<P>
+webgif.c is provided in the distribution. Unix users can
+simply type "make webgif" to compile the program. Type
+"webgif" with no arguments to see the available options.
+A discussion of the code follows.
+<PRE>
+/* Bring in the gd library functions */
+#include "gd.h"
+
+/* Bring in standard I/O and string manipulation functions */
+#include <stdio.h>
+#include <string.h>
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ FILE *in;
+ FILE *out;
+ /* Declare our image pointer */
+ <A HREF="#gdImagePtr">gdImagePtr</A> im = 0;
+ int i;
+ /* We'll clear 'no' once we know the user has made a
+ reasonable request. */
+ int no = 1;
+ /* We'll set 'write' once we know the user's request
+ requires that the image be written back to disk. */
+ int write = 0;
+ /* C programs always get at least one argument; we want at
+ least one more (the image), more in practice. */
+ if (argc < 2) {
+ no = 1;
+ goto usage;
+ }
+ /* The last argument should be the image. Open the file. */
+ in = fopen(argv[argc-1], "rb");
+ if (!in) {
+ fprintf(stderr,
+ "Error: can't open file %s.\n", argv[argc-1]);
+ }
+ /* Now load the image. */
+ im = <A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A>(in);
+ fclose(in);
+ /* If the load failed, it must not be a GIF file. */
+ if (!im) {
+ fprintf(stderr,
+ "Error: %s is not a valid gif file.\n", argv[1]);
+ exit(1);
+ }
+ /* Consider each argument in turn. */
+ for (i=1; (i < (argc-1)); i++) {
+ /* -i turns on and off interlacing. */
+ if (!strcmp(argv[i], "-i")) {
+ if (i == (argc-2)) {
+ fprintf(stderr,
+ "Error: -i specified without y or n.\n");
+ no = 1;
+ goto usage;
+ }
+ if (!strcmp(argv[i+1], "y")) {
+ /* Set interlace. */
+ <A HREF="#gdImageInterlace">gdImageInterlace</A>(im, 1);
+ } else if (!strcmp(argv[i+1], "n")) {
+ /* Clear interlace. */
+ <A HREF="#gdImageInterlace">gdImageInterlace</A>(im, 0);
+ } else {
+ fprintf(stderr,
+ "Error: -i specified without y or n.\n");
+ no = 1;
+ goto usage;
+ }
+ i++;
+ no = 0;
+ write = 1;
+ } else if (!strcmp(argv[i], "-t")) {
+ /* Set transparent index (or none). */
+ int index;
+ if (i == (argc-2)) {
+ fprintf(stderr,
+ "Error: -t specified without a color table index.\n");
+ no = 1;
+ goto usage;
+ }
+ if (!strcmp(argv[i+1], "none")) {
+ /* -1 means not transparent. */
+ <A HREF="#gdImageColorTransparent">gdImageColorTransparent</A>(im, -1);
+ } else {
+ /* OK, get an integer and set the index. */
+ index = atoi(argv[i+1]);
+ <A HREF="#gdImageColorTransparent">gdImageColorTransparent</A>(im, index);
+ }
+ i++;
+ write = 1;
+ no = 0;
+ } else if (!strcmp(argv[i], "-l")) {
+ /* List the colors in the color table. */
+ int j;
+ /* Tabs used below. */
+ printf("Index Red Green Blue\n");
+ for (j=0; (j < <A HREF="#gdImageColorsTotal">gdImageColorsTotal</A>(im)); j++) {
+ /* Use access macros to learn colors. */
+ printf("%d %d %d %d\n",
+ j,
+ <A HREF="#gdImageRed">gdImageRed</A>(im, j),
+ <A HREF="#gdImageGreen">gdImageGreen</A>(im, j),
+ <A HREF="#gdImageBlue">gdImageBlue</A>(im, j));
+ }
+ no = 0;
+ } else if (!strcmp(argv[i], "-d")) {
+ /* Output dimensions, etc. */
+ int t;
+ printf("Width: %d Height: %d Colors: %d\n",
+ <A HREF="#gdImageSX">gdImageSX</A>(im), <A HREF="#gdImageSY">gdImageSY</A>(im),
+ <A HREF="#gdImageColorsTotal">gdImageColorsTotal</A>(im));
+ t = <A HREF="#gdImageGetTransparent">gdImageGetTransparent</A>(im);
+ if (t != (-1)) {
+ printf("Transparent index: %d\n", t);
+ } else {
+ /* -1 means the image is not transparent. */
+ printf("Transparent index: none\n");
+ }
+ if (<A HREF="#gdImageGetInterlaced">gdImageGetInterlaced</A>(im)) {
+ printf("Interlaced: yes\n");
+ } else {
+ printf("Interlaced: no\n");
+ }
+ no = 0;
+ } else {
+ fprintf(stderr, "Unknown argument: %s\n", argv[i]);
+ break;
+ }
+ }
+usage:
+ if (no) {
+ /* If the command failed, output an explanation. */
+ fprintf(stderr,
+ "Usage: webgif [-i y|n ] [-l] [-t index|off ] [-d] gifname.gif\n");
+ fprintf(stderr,
+ "Where -i controls interlace (specify y or n for yes or no),\n");
+ fprintf(stderr,
+ "-l outputs a table of color indexes, -t sets the specified\n");
+ fprintf(stderr,
+ "color index (0-255 or none) to be the transparent color, and\n");
+ fprintf(stderr,
+ "-d reports the dimensions and other characteristics of the image.\n");
+ fprintf(stderr,
+ "Note: you may wish to pipe to \"more\" when using the -l option.\n");
+ }
+ if (write) {
+ /* Open a temporary file. */
+ out = fopen("temp.tmp", "wb");
+ if (!out) {
+ fprintf(stderr,
+ "Unable to write to temp.tmp -- exiting\n");
+ exit(1);
+ }
+ /* Write the new gif. */
+ <A HREF="#gdImageGif">gdImageGif</A>(im, out);
+ fclose(out);
+ /* Erase the old gif. */
+ unlink(argv[argc-1]);
+ /* Rename the new to the old. */
+ rename("temp.tmp", argv[argc-1]);
+ }
+ /* Delete the image from memory. */
+ if (im) {
+ <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+ }
+ /* All's well that ends well. */
+ return 0;
+}
+</PRE>
+<H2><A NAME="reference">Function and type reference</A></H2>
+<UL>
+<LI><A HREF="#types">Types</A></LI>
+<LI><A HREF="#creating">Image creation, destruction, loading and saving</A></LI>
+<LI><A HREF="#drawing">Drawing, styling, brushing, tiling and
+filling functions</A></LI>
+<LI><A HREF="#query">Query functions (not color-related)</A></LI>
+<LI><A HREF="#fonts">Font and text-handling functions</A></LI>
+<LI><A HREF="#colors">Color handling functions</A></LI>
+<LI><A HREF="#copying">Copying and resizing functions</A></LI>
+<LI><A HREF="#misc">Miscellaneous Functions</A></LI>
+<LI><A HREF="#constants">Constants</A></LI>
+</UL>
+<H3><A NAME="types">Types</A></H3>
+<DL>
+<DT><A NAME="gdImage"><code>gdImage</code><strong>(TYPE)</strong></A>
+<DD>
+The data structure in which gd stores images. <A HREF="#gdImageCreate">
+gdImageCreate</A> returns
+a pointer to this type, and the other functions expect to receive
+a pointer to this type as their first argument. You may
+read the members <code>sx</code> (size on X axis),
+<code>sy</code> (size on Y axis), <code>colorsTotal</code>
+(total colors), <code>red</code> (red component of colors;
+an array of 256 integers between 0 and 255), <code>green</code>
+(green component of colors, as above), <code>blue</code>
+(blue component of colors, as above), and <code>transparent</code>
+(index of transparent color, -1 if none); please do so
+using the macros provided. Do NOT set the members directly
+from your code; use the functions provided.
+<PRE>
+typedef struct {
+ unsigned char ** pixels;
+ int sx;
+ int sy;
+ int colorsTotal;
+ int red[gdMaxColors];
+ int green[gdMaxColors];
+ int blue[gdMaxColors];
+ int open[gdMaxColors];
+ int transparent;
+} gdImage;
+</PRE>
+<DT><A NAME="gdImagePtr">gdImagePtr</A> <strong>(TYPE)</strong>
+<DD>
+A pointer to an image structure. <A HREF="#gdImageCreate">gdImageCreate</A>
+returns this type, and the other functions expect it as the first
+argument.
+<DT><A NAME="gdFont">gdFont</A> <strong>(TYPE)</strong>
+<DD>
+A font structure. Used to declare the characteristics of a font.
+Plese see the files gdfontl.c and gdfontl.h for an example of the
+proper declaration of this structure. You can provide your
+own font data by providing such a structure and the associated
+pixel array. You can determine the width and height of a single
+character in a font by examining the w and h members of the
+structure. If you will not be creating your own fonts, you will
+not need to concern yourself with the rest of the components of this
+structure.
+<PRE>
+typedef struct {
+ /* # of characters in font */
+ int nchars;
+ /* First character is numbered... (usually 32 = space) */
+ int offset;
+ /* Character width and height */
+ int w;
+ int h;
+ /* Font data; array of characters, one row after another.
+ Easily included in code, also easily loaded from
+ data files. */
+ char *data;
+} gdFont;
+</PRE>
+<DT><A NAME="gdFontPtr">gdFontPtr</A> <strong>(TYPE)</strong>
+<DD>
+A pointer to a font structure. Text-output functions expect these
+as their second argument, following the <A HREF="#gdImagePtr">
+gdImagePtr</A> argument. Two such pointers are declared in the
+provided include files gdfonts.h and gdfontl.h.
+<DT><A NAME="gdPoint">gdPoint</A> <strong>(TYPE)</strong>
+<DD>
+Represents a point in the coordinate space of the image; used
+by <A HREF="#gdImagePolygon">gdImagePolygon</A> and
+<A HREF="#gdImageFilledPolygon">gdImageFilledPolygon</A>.
+<PRE>
+typedef struct {
+ int x, y;
+} gdPoint, *gdPointPtr;
+</PRE>
+<DT><A NAME="gdPointPtr">gdPointPtr</A> <strong>(TYPE)</strong>
+<DD>
+A pointer to a <A HREF="#gdPoint">gdPoint</A> structure; passed
+as an argument to <A HREF="#gdImagePolygon">gdImagePolygon</A>
+and <A HREF="#gdImageFilledPolygon">gdImageFilledPolygon</A>.
+</DL>
+<H3><A NAME="creating">Image creation, destruction, loading and saving</A></H3>
+<DL>
+<DT><A NAME="gdImageCreate">gdImageCreate(sx, sy)</A>
+<strong>(FUNCTION)</strong>
+<DD>
+gdImageCreate is called to create images. Invoke gdImageCreate
+with the x and y dimensions of the desired image. gdImageCreate
+returns a <A HREF="#gdImagePtr">gdImagePtr</A> to the new image, or
+NULL if unable to
+allocate the image. The image must eventually be destroyed
+using <A HREF="#gdImageDestroy">gdImageDestroy()</A>.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+im = gdImageCreate(64, 64);
+/* ... Use the image ... */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageCreateFromGif">gdImageCreateFromGif(FILE *in)</A>
+<strong>(FUNCTION)</strong>
+<DD>
+gdImageCreateFromGif is called to load images from GIF format files.
+Invoke gdImageCreateFromGif with an already opened pointer to a file
+containing the desired image.
+gdImageCreateFromGif
+returns a <A HREF="#gdImagePtr">gdImagePtr</A> to the new image, or NULL
+if unable to load the image (most often because the file is corrupt or
+does not contain a GIF image). gdImageCreateFromGif does <em>not</em>
+close the file. You can inspect the sx and sy members of the
+image to determine its size. The image must eventually be destroyed
+using <A HREF="#gdImageDestroy">gdImageDestroy()</A>.
+<PRE>
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+... inside a function ...
+FILE *in;
+in = fopen("mygif.gif", "rb");
+im = gdImageCreateFromGif(in);
+fclose(in);
+/* ... Use the image ... */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageCreateFromGd">gdImageCreateFromGd(FILE *in)</A>
+<strong>(FUNCTION)</strong>
+<DD>
+gdImageCreateFromGd is called to load images from gd format files.
+Invoke gdImageCreateFromGd
+with an already opened pointer to a file containing the desired image
+in the <A HREF="#gdformat">gd file format</A>, which is specific to
+gd and intended for very fast loading. (It is <em>not</em> intended for
+compression; for compression, use GIF.)
+gdImageCreateFromGd
+returns a <A HREF="#gdImagePtr">gdImagePtr</A> to the new image, or NULL
+if unable to load the image (most often because the file is corrupt or
+does not contain a gd format image). gdImageCreateFromGd does <em>not</em>
+close the file. You can inspect the sx and sy members of the
+image to determine its size. The image must eventually be destroyed
+using <A HREF="#gdImageDestroy">gdImageDestroy()</A>.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+FILE *in;
+in = fopen("mygd.gd", "rb");
+im = gdImageCreateFromGd(in);
+fclose(in);
+/* ... Use the image ... */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageCreateFromXbm">gdImageCreateFromXbm(FILE *in)</A>
+<strong>(FUNCTION)</strong>
+<DD>
+gdImageCreateFromXbm is called to load images from X bitmap format
+files. Invoke gdImageCreateFromXbm
+with an already opened pointer to a file containing the desired image.
+gdImageCreateFromXbm
+returns a <A HREF="#gdImagePtr">gdImagePtr</A> to the new image, or NULL
+if unable to load the image (most often because the file is corrupt or
+does not contain an X bitmap format image). gdImageCreateFromXbm does
+<em>not</em> close the file. You can inspect the sx and sy members of the
+image to determine its size. The image must eventually be destroyed
+using <A HREF="#gdImageDestroy">gdImageDestroy()</A>.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+FILE *in;
+in = fopen("myxbm.xbm", "rb");
+im = gdImageCreateFromXbm(in);
+fclose(in);
+/* ... Use the image ... */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageDestroy">gdImageDestroy(gdImagePtr im)</A> <STRONG>(FUNCTION)</STRONG>
+<DD>gdImageDestroy is used to free the memory associated with
+an image. It is important to invoke gdImageDestroy before
+exiting your program or assigning a new image to
+a <A HREF="#gdImagePtr">gdImagePtr</A> variable.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(10, 10);
+/* ... Use the image ... */
+/* Now destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageGif">
+void gdImageGif(gdImagePtr im, FILE *out)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageGif outputs the specified image to the specified
+file in GIF format. The file must be open for writing. Under MSDOS,
+it is important to use "wb" as opposed to simply "w"
+as the mode when opening the file, and under Unix there
+is no penalty for doing so. gdImageGif does <em>not</em>
+close the file; your code must do so.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black, white;
+FILE *out;
+/* Create the image */
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Allocate background */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Allocate drawing color */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Draw rectangle */
+<A HREF="#gdImageRectangle">gdImageRectangle</A>(im, 0, 0, 99, 99, black);
+/* Open output file in binary mode */
+out = fopen("rect.gif", "wb");
+/* Write GIF */
+gdImageGif(im, out);
+/* Close file */
+fclose(out);
+/* Destroy image */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageGd">
+void gdImageGd(gdImagePtr im, FILE *out)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageGd outputs the specified image to the specified
+file in the <A HREF="#gdformat">gd image format</A>. The file must
+be open for writing. Under MSDOS, it is important to use "wb" as
+opposed to simply "w" as the mode when opening the file, and under
+Unix there is no penalty for doing so. gdImageGif does <em>not</em>
+close the file; your code must do so.
+<P>
+The gd image format is intended for fast reads and writes of
+images your program will need frequently to build other
+images. It is <em>not</em> a compressed format, and is not intended
+for general use.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black, white;
+FILE *out;
+/* Create the image */
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Allocate background */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Allocate drawing color */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Draw rectangle */
+<A HREF="#gdImageRectangle">gdImageRectangle</A>(im, 0, 0, 99, 99, black);
+/* Open output file in binary mode */
+out = fopen("rect.gd", "wb");
+/* Write gd format file */
+gdImageGd(im, out);
+/* Close file */
+fclose(out);
+/* Destroy image */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+</DL>
+<H3><A NAME="drawing">Drawing Functions</A></H3>
+<DL>
+<DT><A NAME="gdImageSetPixel">void gdImageSetPixel(gdImagePtr im, int x, int y, int color)</A> <STRONG>(FUNCTION)</STRONG>
+<DD>gdImageSetPixel sets a pixel to a particular color index. Always use
+this function or one of the other drawing functions to access pixels;
+do not access the pixels of the <A HREF="#gdImage">gdImage</A> structure
+directly.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Set a pixel near the center. */
+gdImageSetPixel(im, 50, 50, white);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageLine">void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageLine is used to draw a line between two endpoints (x1,y1 and x2, y2).
+The line is drawn using the color index specified. Note that the color
+index can be an actual color returned by <A HREF="#gdImageColorAllocate">
+gdImageColorAllocate</A> or one of <A HREF="#gdStyled">gdStyled</A>,
+<A HREF="#gdBrushed">gdBrushed</A> or <A HREF="#gdStyledBrushed">
+gdStyledBrushed</A>.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Draw a line from the upper left corner to the lower right corner. */
+gdImageLine(im, 0, 0, 99, 99, white);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageDashedLine">void gdImageDashedLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageDashedLine is provided <strong>solely for backwards compatibility
+</strong> with gd 1.0. New programs should draw dashed lines using
+the normal <A HREF="#gdImageLine">gdImageLine</A> function and the
+new <A HREF="#gdImageSetStyle">gdImageSetStyle</A> function.
+<P>
+gdImageDashedLine is used to draw a dashed line between two endpoints
+(x1,y1 and x2, y2).
+The line is drawn using the color index specified. The portions of the line
+that are not drawn are left transparent so the background is visible.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Draw a dashed line from the upper left corner to the lower right corner. */
+gdImageDashedLine(im, 0, 0, 99, 99);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImagePolygon">void gdImagePolygon(gdImagePtr im, gdPointPtr points, int pointsTotal, int color)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImagePolygon is used to draw a polygon with the verticies
+(at least 3) specified, using the color index specified.
+See also <A HREF="#gdImageFilledPolygon">gdImageFilledPolygon</A>.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+/* Points of polygon */
+<A HREF="#gdPoint">gdPoint</A> points[3];
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Draw a triangle. */
+points[0].x = 50;
+points[0].y = 0;
+points[1].x = 99;
+points[1].y = 99;
+points[2].x = 0;
+points[2].y = 99;
+gdImagePolygon(im, points, 3, white);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageRectangle">void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageRectangle is used to draw a rectangle with the two corners
+(upper left first, then lower right) specified, using the
+color index specified.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Draw a rectangle occupying the central area. */
+gdImageRectangle(im, 25, 25, 74, 74, white);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageFilledPolygon">void gdImageFilledPolygon(gdImagePtr im, gdPointPtr points, int pointsTotal, int color)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageFilledPolygon is used to fill a polygon with the verticies
+(at least 3) specified, using the color index specified.
+See also <A HREF="#gdImageFilledPolygon">gdImagePolygon</A>.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+int red;
+/* Points of polygon */
+<A HREF="#gdPoint">gdPoint</A> points[3];
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Allocate the color red. */
+red = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 0, 0);
+/* Draw a triangle. */
+points[0].x = 50;
+points[0].y = 0;
+points[1].x = 99;
+points[1].y = 99;
+points[2].x = 0;
+points[2].y = 99;
+/* Paint it in white */
+gdImageFilledPolygon(im, points, 3, white);
+/* Outline it in red; must be done second */
+<A HREF="#gdImagePolygon">gdImagePolygon</A>(im, points, 3, red);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageFilledRectangle">void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageFilledRectangle is used to draw a solid rectangle with the two corners
+(upper left first, then lower right) specified, using the
+color index specified.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">int gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Draw a filled rectangle occupying the central area. */
+gdImageFilledRectangle(im, 25, 25, 74, 74, white);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageArc">void gdImageArc(gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color)</A>
+<STRONG> (FUNCTION)</STRONG>
+<DD>
+gdImageArc is used to draw a partial ellipse centered at the given point,
+with the specified width and height in pixels. The arc begins at
+the position in degrees specified by <code>s</code> and ends at
+the position specified by <code>e</code>. The arc is drawn in
+the color specified by the last argument. A circle can be drawn
+by beginning from 0 degrees and ending at 360 degrees, with
+width and height being equal. e must be greater than s. Values greater
+than 360 are interpreted modulo 360.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 50);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Inscribe an ellipse in the image. */
+gdImageArc(im, 50, 25, 98, 48, 0, 360, white);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageFillToBorder">void gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color)
+<STRONG> (FUNCTION)</STRONG>
+<DD>
+gdImageFillToBorder floods a portion of the image with the specified
+<code>color</code>, beginning at the specified point and stopping at
+the specified <code>border</code> color. For a way of flooding an
+area defined by the color of the starting point, see
+<A HREF="#gdImageFill">gdImageFill</A>.
+<P>
+The border color <em>cannot</em> be a special color
+such as <A HREF="#gdTiled">gdTiled</A>; it must be a proper
+solid color. The fill color can be, however.
+<P>
+Note that gdImageFillToBorder is recursive. It is not the most
+naive implementation possible, and the implementation is
+expected to improve, but there will always be degenerate
+cases in which the stack can become very deep. This can be
+a problem in MSDOS and MS Windows environments. (Of course,
+in a Unix or NT environment with a proper stack, this is
+not a problem at all.)
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+int red;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 50);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Allocate the color red. */
+red = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 0, 0);
+/* Inscribe an ellipse in the image. */
+gdImageArc(im, 50, 25, 98, 48, 0, 360, white);
+/* Flood-fill the ellipse. Fill color is red, border color is
+ white (ellipse). */
+gdImageFillToBorder(im, 50, 50, white, red);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageFill">void gdImageFill(gdImagePtr im, int x, int y, int color)
+<STRONG> (FUNCTION)</STRONG>
+<DD>
+gdImageFill floods a portion of the image with the specified
+<code>color</code>, beginning at the specified point and flooding the
+surrounding region of the same color as the starting point.
+For a way of flooding a region defined by a specific border
+color rather than by its interior color, see
+<A HREF="#gdImageFillToBorder">gdImageFillToBorder</A>.
+<P>
+The fill color can be <A HREF="#gdTiled">gdTiled</A>, resulting
+in a tile fill using another image as the tile. However,
+the tile image cannot be transparent. If the image you wish
+to fill with has a transparent color index, call
+<A HREF="#gdImageTransparent">gdImageTransparent</A> on the
+tile image and set the transparent color index to -1
+to turn off its transparency.
+<P>
+Note that gdImageFill is recursive. It is not the most
+naive implementation possible, and the implementation is
+expected to improve, but there will always be degenerate
+cases in which the stack can become very deep. This can be
+a problem in MSDOS and MS Windows environments. (Of course,
+in a Unix or NT environment with a proper stack, this is
+not a problem at all.)
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+int red;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 50);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Allocate the color red. */
+red = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 0, 0);
+/* Inscribe an ellipse in the image. */
+gdImageArc(im, 50, 25, 98, 48, 0, 360, white);
+/* Flood-fill the ellipse. Fill color is red, and will replace the
+ black interior of the ellipse. */
+gdImageFill(im, 50, 50, red);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageSetBrush">void gdImageSetBrush(gdImagePtr im, gdImagePtr brush)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+A "brush" is an image used to draw wide, shaped strokes in another image. Just
+as a paintbrush is not a single point, a brush image need not be
+a single pixel. <em>Any</em> gd image can be used as a brush, and by
+setting the transparent color index of the brush image with
+<A HREF="#gdImageColorTransparent">gdImageColorTransparent</A>,
+a brush of any shape can be created. All line-drawing functions,
+such as <A HREF="#gdImageLine">gdImageLine</A> and
+<A HREF="#gdImagePolygon">gdImagePolygon</A>, will use the
+current brush if the special "color" <A HREF="#gdBrushed">
+gdBrushed</A> or <A HREF="#gdStyledBrushed">gdStyledBrushed</A>
+is used when calling them.
+<P>
+gdImageSetBrush is used to specify the brush to be used in a
+particular image. You can set any image to be the brush.
+If the brush image does not have the same color map as the
+first image, any colors missing from the first image
+will be allocated. If not enough colors can be allocated,
+the closest colors already available will be used. This
+allows arbitrary GIFs to be used as brush images. It also
+means, however, that you should not set a brush unless you
+will actually use it; if you set a rapid succession of
+different brush images, you can quickly fill your color map,
+and the results will not be optimal.
+<P>
+You need not take any special action when you are finished
+with a brush. As for any other image, if you will not
+be using the brush image for any further purpose,
+you should call <A HREF="#gdImageDestroy">gdImageDestroy</A>.
+You must not use the color <A HREF="#gdBrushed">gdBrushed</A>
+if the current brush has been destroyed; you can of
+course set a new brush to replace it.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im, brush;
+FILE *in;
+int black;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Open the brush GIF. For best results, portions of the
+ brush that should be transparent (ie, not part of the
+ brush shape) should have the transparent color index. */
+in = fopen("star.gif", "rb");
+brush = <A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A>(in);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+gdImageSetBrush(im, brush);
+/* Draw a line from the upper left corner to the lower right corner
+ using the brush. */
+<A HREF="#gdImageLine">gdImageLine</A>(im, 0, 0, 99, 99, <A HREF="#gdBrushed">gdBrushed</A>);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+/* Destroy the brush image */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(brush);
+</PRE>
+<DT><A NAME="gdImageSetTile">void gdImageSetTile(gdImagePtr im, gdImagePtr tile)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+A "tile" is an image used to fill an area with a repeated pattern.
+<em>Any</em> gd image can be used as a tile, and by
+setting the transparent color index of the tile image with
+<A HREF="#gdImageColorTransparent">gdImageColorTransparent</A>,
+a tile that allows certain parts of the underlying area to shine
+through can be created. All region-filling functions,
+such as <A HREF="#gdImageFill">gdImageFill</A> and
+<A HREF="#gdImageFilledPolygon">gdImageFilledPolygon</A>, will use the
+current tile if the special "color" <A HREF="#gdTiled">
+gdTiled</A> is used when calling them.
+<P>
+gdImageSetTile is used to specify the tile to be used in a
+particular image. You can set any image to be the tile.
+If the tile image does not have the same color map as the
+first image, any colors missing from the first image
+will be allocated. If not enough colors can be allocated,
+the closest colors already available will be used. This
+allows arbitrary GIFs to be used as tile images. It also
+means, however, that you should not set a tile unless you
+will actually use it; if you set a rapid succession of
+different tile images, you can quickly fill your color map,
+and the results will not be optimal.
+<P>
+You need not take any special action when you are finished
+with a tile. As for any other image, if you will not
+be using the tile image for any further purpose,
+you should call <A HREF="#gdImageDestroy">gdImageDestroy</A>.
+You must not use the color <A HREF="#gdBrushed">gdTiled</A>
+if the current tile has been destroyed; you can of
+course set a new tile to replace it.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im, tile;
+FILE *in;
+int black;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Open the tile GIF. For best results, portions of the
+ tile that should be transparent (ie, allowing the
+ background to shine through) should have the transparent
+ color index. */
+in = fopen("star.gif", "rb");
+tile = <A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A>(in);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+gdImageSetTile(im, tile);
+/* Fill an area using the tile. */
+<A HREF="#gdImageFilledRectangle">gdImageFilledRectangle</A>(im, 25, 25, 75, 75, <A HREF="#gdTiled">gdTiled</A>);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+/* Destroy the tile image */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(tile);
+</PRE>
+<DT><A NAME="gdImageSetStyle">void gdImageSetStyle(gdImagePtr im, int *style, int styleLength)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+It is often desirable to draw dashed lines, dotted lines, and other
+variations on a broken line. gdImageSetStyle can be used to set
+any desired series of colors, including a special color that
+leaves the background intact, to be repeated during the drawing
+of a line.
+<P>
+To use gdImageSetStyle, create an array of integers and assign
+them the desired series of color values to be repeated.
+You can assign the special color value <A HREF="#gdTransparent">
+gdTransparent</A> to indicate that the existing color should
+be left unchanged for that particular pixel (allowing a dashed
+line to be attractively drawn over an existing image).
+<P>
+Then, to draw a line using the style, use the normal
+<A HREF="#gdImageLine">gdImageLine</A> function with the
+special color value <A HREF="#gdStyled">gdStyled</A>.
+<P>
+As of <A HREF="#whatsnew1.1.1">version 1.1.1</A>, the style
+array is copied when you set the style, so you need not
+be concerned with keeping the array around indefinitely.
+This should not break existing code that assumes styles
+are not copied.
+<P>
+You can also combine styles and brushes to draw the brush
+image at intervals instead of in a continuous stroke.
+When creating a style for use with a brush, the
+style values are interpreted differently: zero (0) indicates
+pixels at which the brush should not be drawn, while one (1)
+indicates pixels at which the brush should be drawn.
+To draw a styled, brushed line, you must use the
+special color value <A HREF="#gdStyledBrushed">
+gdStyledBrushed</A>. For an example of this feature
+in use, see gddemo.c (provided in the distribution).
+<PRE>
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int styleDotted[2], styleDashed[6];
+FILE *in;
+int black;
+int red;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+red = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 0, 0);
+/* Set up dotted style. Leave every other pixel alone. */
+styleDotted[0] = red;
+styleDotted[1] = gdTransparent;
+/* Set up dashed style. Three on, three off. */
+styleDashed[0] = red;
+styleDashed[1] = red;
+styleDashed[2] = red;
+styleDashed[3] = gdTransparent;
+styleDashed[4] = gdTransparent;
+styleDashed[5] = gdTransparent;
+/* Set dotted style. Note that we have to specify how many pixels are
+ in the style! */
+gdImageSetStyle(im, styleDotted, 2);
+/* Draw a line from the upper left corner to the lower right corner. */
+<A HREF="#gdImageLine">gdImageLine</A>(im, 0, 0, 99, 99, <A HREF="#gdStyled">gdStyled</A>);
+/* Now the dashed line. */
+gdImageSetStyle(im, styleDashed, 6);
+<A HREF="#gdImageLine">gdImageLine</A>(im, 0, 99, 0, 99, <A HREF="#gdStyled">gdStyled</A>);
+
+/* ... Do something with the image, such as saving it to a file ... */
+
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+</DL>
+<H3><A NAME="query">Query Functions</A></H3>
+<DL>
+<DT><A NAME="gdImageBlue">
+int gdImageBlue(gdImagePtr im, int color)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageBlue is a macro which returns the blue component of
+the specified color index. Use this macro rather than accessing the
+structure members directly.
+<DT><A NAME="gdImageGetPixel">int gdImageGetPixel(gdImagePtr im, int x, int y)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageGetPixel() retrieves the color index of a particular
+pixel. Always use this function to query pixels;
+do not access the pixels of the <A HREF="#gdImage">gdImage</A> structure
+directly.
+<PRE>
+... inside a function ...
+FILE *in;
+gdImagePtr im;
+int c;
+in = fopen("mygif.gif", "rb");
+im = <A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A>(in);
+fclose(in);
+c = gdImageGetPixel(im, gdImageSX(im) / 2, gdImageSY(im) / 2);
+printf("The value of the center pixel is %d; RGB values are %d,%d,%d\n",
+ c, im->red[c], im->green[c], im->blue[c]);
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageBoundsSafe">
+int gdImageBoundsSafe(gdImagePtr im, int x, int y)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageBoundsSafe returns true (1) if the specified point is within the bounds
+of the image, false (0) if not. This function is intended primarily for
+use by those who wish to add functions to gd. All of the gd drawing
+functions already clip safely to the edges of the image.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+if (gdImageBoundsSafe(im, 50, 50)) {
+ printf("50, 50 is within the image bounds\n");
+} else {
+ printf("50, 50 is outside the image bounds\n");
+}
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageGreen">
+int gdImageGreen(gdImagePtr im, int color)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageGreen is a macro which returns the green component of
+the specified color index. Use this macro rather than accessing the
+structure members directly.
+<DT><A NAME="gdImageRed">
+int gdImageRed(gdImagePtr im, int color)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageRed is a macro which returns the red component of
+the specified color index. Use this macro rather than accessing the
+structure members directly.
+<DT><A NAME="gdImageSX">
+int gdImageSX(gdImagePtr im)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageSX is a macro which returns the width of the image
+in pixels. Use this macro rather than accessing the
+structure members directly.
+<DT><A NAME="gdImageSY">
+int gdImageSY(gdImagePtr im)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageSY is a macro which returns the height of the image
+in pixels. Use this macro rather than accessing the
+structure members directly.
+</DL>
+<H3><A NAME="fonts">Fonts and text-handling functions</A></H3>
+<DL>
+<DT><A NAME="gdImageChar">
+void gdImageChar(gdImagePtr im, gdFontPtr font, int x, int y,
+ int c, int color)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageChar is used to draw single characters on the image.
+(To draw multiple characters, use <A HREF="#gdImageString">
+gdImageString</A>.) The second argument is a
+pointer to a font definition structure; five fonts are
+provided with gd, gdFontTiny, gdFontSmall, gdFontMediumBold,
+gdFontLarge, and gdFontGiant. You must
+include the files "gdfontt.h", "gdfonts.h", "gdfontmb.h",
+"gdfontl.h" and "gdfontg.h" respectively
+and (if you are not using a library-based approach) link with the
+corresponding .c files to use the provided fonts.
+The character specified by the fifth
+argument is drawn from left to right in the specified
+color. (See <A HREF="#gdImageCharUp">gdImageCharUp</A> for a way
+of drawing vertical text.) Pixels not
+set by a particular character retain their previous color.
+<PRE>
+#include "gd.h"
+#include "gdfontl.h"
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Draw a character. */
+gdImageChar(im, gdFontLarge, 0, 0, 'Q', white);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageCharUp">
+void gdImageCharUp(gdImagePtr im, gdFontPtr font, int x, int y,
+int c, int color)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageCharUp is used to draw single characters on the image,
+rotated 90 degrees.
+(To draw multiple characters, use <A HREF="#gdImageStringUp">
+gdImageStringUp</A>.) The second argument is a
+pointer to a font definition structure; five fonts are
+provided with gd, gdFontTiny, gdFontSmall, gdFontMediumBold,
+gdFontLarge, and gdFontGiant. You must
+include the files "gdfontt.h", "gdfonts.h", "gdfontmb.h",
+"gdfontl.h" and "gdfontg.h" respectively
+and (if you are not using a library-based approach) link with the
+corresponding .c files to use the provided fonts. The character specified by
+the fifth argument is drawn
+from bottom to top, rotated at a 90-degree angle, in the specified
+color. (See <A HREF="#gdImageChar">gdImageChar</A> for a way
+of drawing horizontal text.) Pixels not
+set by a particular character retain their previous color.
+<PRE>
+#include "gd.h"
+#include "gdfontl.h"
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Draw a character upwards so it rests against the top of the image. */
+gdImageCharUp(im, gdFontLarge,
+ 0, gdFontLarge->h, 'Q', white);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageString">
+void gdImageString(gdImagePtr im, gdFontPtr font, int x, int y,
+char *s, int color)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageString is used to draw multiple characters on the image.
+(To draw single characters, use <A HREF="#gdImageChar">
+gdImageChar</A>.) The second argument is a
+pointer to a font definition structure; five fonts are
+provided with gd, gdFontTiny, gdFontSmall, gdFontMediumBold,
+gdFontLarge, and gdFontGiant. You must
+include the files "gdfontt.h", "gdfonts.h", "gdfontmb.h",
+"gdfontl.h" and "gdfontg.h" respectively
+and (if you are not using a library-based approach) link with the
+corresponding .c files to use the provided fonts.
+The null-terminated C string specified
+by the fifth argument is drawn from left to right in the specified
+color. (See <A HREF="#gdImageStringUp">gdImageStringUp</A> for a way
+of drawing vertical text.) Pixels not
+set by a particular character retain their previous color.
+<PRE>
+#include "gd.h"
+#include "gdfontl.h"
+#include <string.h>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+/* String to draw. */
+char *s = "Hello.";
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Draw a centered string. */
+gdImageString(im, gdFontLarge,
+ im->w / 2 - (strlen(s) * gdFontLarge->w / 2),
+ im->h / 2 - gdFontLarge->h / 2,
+ s, white);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageStringUp">
+void gdImageStringUp(gdImagePtr im, gdFontPtr font, int x, int y,
+char *s, int color)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageStringUp is used to draw multiple characters on the image,
+rotated 90 degrees.
+(To draw single characters, use <A HREF="#gdImageCharUp">
+gdImageCharUp</A>.) The second argument is a
+pointer to a font definition structure; five fonts are
+provided with gd, gdFontTiny, gdFontSmall, gdFontMediumBold,
+gdFontLarge, and gdFontGiant. You must
+include the files "gdfontt.h", "gdfonts.h", "gdfontmb.h",
+"gdfontl.h" and "gdfontg.h" respectively
+and (if you are not using a library-based approach) link with the
+corresponding .c files to use the provided fonts.The null-terminated C string specified
+by the fifth argument is drawn from bottom to top (rotated
+90 degrees) in the specified color. (See
+<A HREF="#gdImageString">gdImageString</A> for a way
+of drawing horizontal text.) Pixels not
+set by a particular character retain their previous color.
+<PRE>
+#include "gd.h"
+#include "gdfontl.h"
+#include <string.h>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+/* String to draw. */
+char *s = "Hello.";
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
+/* Draw a centered string going upwards. Axes are reversed,
+ and Y axis is decreasing as the string is drawn. */
+gdImageStringUp(im, gdFontLarge,
+ im->w / 2 - gdFontLarge->h / 2,
+ im->h / 2 + (strlen(s) * gdFontLarge->w / 2),
+ s, white);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+</DL>
+<H3><A NAME="colors">Color-handling functions</A></H3>
+<DL>
+<DT><A NAME="gdImageColorAllocate">
+int gdImageColorAllocate(gdImagePtr im, int r, int g, int b)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageColorAllocate finds the first available color index in
+the image specified, sets its RGB values to those requested
+(255 is the maximum for each),
+and returns the index of the new color table entry. When
+creating a new image, the first time you invoke this function,
+you are setting the background color for that image.
+<P>
+In the event that all <A HREF="#gdMaxColors">gdMaxColors</A> colors
+(256) have already been allocated, gdImageColorAllocate will
+return -1 to indicate failure. (This is not uncommon when
+working with existing GIF files that already use 256 colors.)
+Note that gdImageColorAllocate
+does not check for existing colors that match your request;
+see <A HREF="#gdImageColorExact">gdImageColorExact</A>
+and <A HREF="#gdImageColorClosest">gdImageColorClosest</A>
+for ways to locate existing colors that approximate the
+color desired in situations where a new color is not available.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int red;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
+/* Allocate the color red. */
+red = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 0, 0);
+/* Draw a dashed line from the upper left corner to the lower right corner. */
+gdImageDashedLine(im, 0, 0, 99, 99, red);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageColorClosest">
+int gdImageColorClosest(gdImagePtr im, int r, int g, int b)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageColorClosest searches the colors which have been
+defined thus far in the image specified and returns the
+index of the color with RGB values closest to those of the
+request. (Closeness is determined by Euclidian distance,
+which is used to determine the distance in three-dimensional color
+space between colors.)
+<P>
+If no colors have yet been allocated in the image,
+gdImageColorClosest returns -1.
+<P>
+This function is most useful as a backup method for choosing
+a drawing color when an image already contains
+<A HREF="#gdMaxColors">gdMaxColors</A> (256) colors and
+no more can be allocated. (This is not uncommon when
+working with existing GIF files that already use many colors.)
+See <A HREF="#gdImageColorExact">gdImageColorExact</A>
+for a method of locating exact matches only.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+FILE *in;
+int red;
+/* Let's suppose that photo.gif is a scanned photograph with
+ many colors. */
+in = fopen("photo.gif", "rb");
+im = <A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A>(in);
+fclose(in);
+/* Try to allocate red directly */
+red = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 0, 0);
+/* If we fail to allocate red... */
+if (red == (-1)) {
+ /* Find the <em>closest</em> color instead. */
+ red = gdImageColorClosest(im, 255, 0, 0);
+}
+/* Draw a dashed line from the upper left corner to the lower right corner */
+gdImageDashedLine(im, 0, 0, 99, 99, red);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageColorExact">
+int gdImageColorExact(gdImagePtr im, int r, int g, int b)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageColorExact searches the colors which have been
+defined thus far in the image specified and returns the
+index of the first color with RGB values which exactly
+match those of the request. If no allocated color matches the
+request precisely, gdImageColorExact returns -1.
+See <A HREF="#gdImageColorClosest">gdImageColorClosest</A>
+for a way to find the color closest to the color requested.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int red;
+in = fopen("photo.gif", "rb");
+im = <A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A>(in);
+fclose(in);
+/* The image may already contain red; if it does, we'll save a slot
+ in the color table by using that color. */
+/* Try to allocate red directly */
+red = gdImageColorExact(im, 255, 0, 0);
+/* If red isn't already present... */
+if (red == (-1)) {
+ /* Second best: try to allocate it directly. */
+ red = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 0, 0);
+ /* Out of colors, so find the <em>closest</em> color instead. */
+ red = gdImageColorClosest(im, 255, 0, 0);
+}
+/* Draw a dashed line from the upper left corner to the lower right corner */
+gdImageDashedLine(im, 0, 0, 99, 99, red);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageColorsTotal">
+int gdImageColorsTotal(gdImagePtr im)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageColorsTotal is a macro which returns the number of
+colors currently allocated in the image. Use this macro
+to obtain this information; do not access the structure
+directly.
+<DT><A NAME="gdImageColorRed">
+int gdImageColorRed(gdImagePtr im, int c)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageColorRed is a macro which returns the red portion
+of the specified color in the image. Use this macro
+to obtain this information; do not access the structure
+directly.
+<DT><A NAME="gdImageColorGreen">
+int gdImageColorGreen(gdImagePtr im, int c)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageColorGreen is a macro which returns the green portion
+of the specified color in the image. Use this macro
+to obtain this information; do not access the structure
+directly.
+<DT><A NAME="gdImageColorBlue">
+int gdImageColorBlue(gdImagePtr im, int c)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageColorBlue is a macro which returns the green portion
+of the specified color in the image. Use this macro
+to obtain this information; do not access the structure
+directly.
+<DT><A NAME="gdImageGetInterlaced">
+int gdImageGetInterlaced(gdImagePtr im)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageGetInterlaced is a macro which returns true (1)
+if the image is interlaced, false (0) if not.
+Use this macro to obtain this information; do not
+access the structure directly.
+See <A NAME="gdImageInterlace">gdImageInterlace</A> for
+a means of interlacing images.
+<DT><A NAME="gdImageGetTransparent">
+int gdImageGetTransparent(gdImagePtr im)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageGetTransparent is a macro which returns the
+current transparent color index in the image.
+If there is no transparent color, gdImageGetTransparent
+returns -1. Use this macro to obtain this information; do not
+access the structure directly.
+<DT><A NAME="gdImageColorDeallocate">
+void gdImageColorDeallocate(gdImagePtr im, int color)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageColorDeallocate marks the specified color as being
+available for reuse. It does not attempt to determine whether
+the color index is still in use in the image. After a call
+to this function, the next call to
+<A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>
+for the same image will set new RGB values for that
+color index, changing the color of any pixels which
+have that index as a result. If multiple calls to
+gdImageColorDeallocate are made consecutively, the lowest-numbered
+index among them will be reused by the next
+<A HREF="#gdImageColorAllocate"> gdImageColorAllocate</A> call.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int red, blue;
+in = fopen("photo.gif", "rb");
+im = <A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A>(in);
+fclose(in);
+/* Look for red in the color table. */
+red = gdImageColorExact(im, 255, 0, 0);
+/* If red is present... */
+if (red != (-1)) {
+ /* Deallocate it. */
+ gdImageColorDeallocate(im, red);
+ /* Allocate blue, reusing slot in table.
+ Existing red pixels will change color. */
+ blue = gdImageColorAllocate(im, 0, 0, 255);
+}
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageColorTransparent">
+void gdImageColorTransparent(gdImagePtr im, int color)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageColorTransparent sets the transparent color index
+for the specified image to the specified index. To indicate
+that there should be <em>no</em> transparent color, invoke
+gdImageColorTransparent with a color index of -1.
+<P>
+The color index used should be an index
+allocated by <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>,
+whether explicitly invoked by your code or implicitly
+invoked by loading an image.
+In order to ensure that your image has a reasonable appearance
+when viewed by users who do not have transparent background
+capabilities, be sure to give reasonable RGB values to the
+color you allocate for use as a transparent color,
+<em>even though it will be transparent on systems
+that support transparency</em>.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+FILE *in, *out;
+in = fopen("photo.gif", "rb");
+im = <A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A>(in);
+fclose(in);
+/* Look for black in the color table and make it transparent. */
+black = <A HREF="#gdImageColorExact">gdImageColorExact</A>(im, 0, 0, 0);
+/* If black is present... */
+if (black != (-1)) {
+ /* Make it transparent */
+ gdImageColorTransparent(im, black);
+}
+/* Save the newly-transparent image back to the file */
+out = fopen("photo.gif", "wb");
+<A HREF="#gdImageGif">gdImageGif</A>(im, out);
+fclose(out);
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+</DL>
+<H3><A NAME="copying">Copying and resizing functions</A></H3>
+<DL>
+<DT><A NAME="gdImageCopy">void gdImageCopy(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h)
+<STRONG> (FUNCTION)</STRONG>
+<DD>
+gdImageCopy is used to copy a rectangular portion of one image to
+another image. (For a way of stretching or shrinking the image
+in the process, see <A HREF="#gdImageCopyResized">
+gdImageCopyResized</A>.)
+<P>
+The <code>dst</code> argument is the destination image to which the
+region will be copied. The <code>src</code> argument is the source
+image from which the region is copied. The <code>dstX</code>
+and <code>dstY</code> arguments specify the point in the destination
+image to which the region will be copied. The <code>srcX</code>
+and <code>srcY</code> arguments specify the upper left corner
+of the region in the source image. The <code>w</code>
+and <code>h</code> arguments specify the width and height
+of the region.
+<P>
+When you copy a region from one location in an image to another
+location in the same image, gdImageCopy will perform as expected
+unless the regions overlap, in which case the result is
+unpredictable.
+<P>
+<strong>Important note on copying between images:</strong> since
+different images do
+not necessarily have the same color tables, pixels are not simply set to the
+same color index values to copy them. gdImageCopy will attempt
+to find an identical RGB value in the destination image for
+each pixel in the copied portion of the source image by
+invoking <A HREF="#gdImageColorExact">gdImageColorExact</A>. If
+such a value is not found, gdImageCopy will attempt to
+allocate colors as needed using <A HREF="#gdImageColorAllocate">
+gdImageColorAllocate</A>. If both of these methods fail,
+gdImageCopy will invoke <A HREF="#gdImageColorClosest">
+gdImageColorClosest</A> to find the color in the destination
+image which most closely approximates the color of the
+pixel being copied.
+<PRE>
+... Inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im_in;
+<A HREF="#gdImagePtr">gdImagePtr</A> im_out;
+int x, y;
+FILE *in;
+FILE *out;
+/* Load a small gif to tile the larger one with */
+in = fopen("small.gif", "rb");
+im_in = <A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A>(in);
+fclose(in);
+/* Make the output image four times as large on both axes */
+im_out = <A HREF="#gdImageCreate">gdImageCreate</A>(im_in->sx * 4, im_in->sy * 4);
+/* Now tile the larger image using the smaller one */
+for (y = 0; (y < 4); y++) {
+ for (x = 0; (x < 4); x++) {
+ gdImageCopy(im_out, im_in,
+ x * im_in->sx, y * im_in->sy,
+ 0, 0,
+ im_in->sx, im_in->sy);
+ }
+}
+out = fopen("tiled.gif", "wb");
+<A HREF="#gdImageGif">gdImageGif</A>(im_out, out);
+fclose(out);
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im_in);
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im_out);
+</PRE>
+<DT><A NAME="gdImageCopyResized">void gdImageCopyResized(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int destW, int destH, int srcW, int srcH)
+<STRONG> (FUNCTION)</STRONG>
+<DD>
+gdImageCopyResized is used to copy a rectangular portion of one image to
+another image. The X and Y dimensions of the original region and the
+destination region can vary, resulting in stretching or shrinking of
+the region as appropriate. (For a simpler version of this function
+which does not deal with resizing, see <A HREF="#gdImageCopy">
+gdImageCopy</A>.)
+<P>
+The <code>dst</code> argument is the destination image to which the
+region will be copied. The <code>src</code> argument is the source
+image from which the region is copied. The <code>dstX</code>
+and <code>dstY</code> arguments specify the point in the destination
+image to which the region will be copied. The <code>srcX</code>
+and <code>srcY</code> arguments specify the upper left corner
+of the region in the source image. The <code>dstW</code>
+and <code>dstH</code> arguments specify the width and height
+of the destination region. The <code>srcW</code>
+and <code>srcH</code> arguments specify the width and height
+of the source region and can differ from the destination size,
+allowing a region to be scaled during the copying process.
+<P>
+When you copy a region from one location in an image to another
+location in the same image, gdImageCopy will perform as expected
+unless the regions overlap, in which case the result is
+unpredictable. If this presents a problem, create a scratch image
+in which to keep intermediate results.
+<P>
+<strong>Important note on copying between images:</strong> since images
+do not necessarily have the same color tables, pixels are not simply set
+to the same color index values to copy them. gdImageCopy will attempt
+to find an identical RGB value in the destination image for
+each pixel in the copied portion of the source image by
+invoking <A HREF="#gdImageColorExact">gdImageColorExact</A>. If
+such a value is not found, gdImageCopy will attempt to
+allocate colors as needed using <A HREF="#gdImageColorAllocate">
+gdImageColorAllocate</A>. If both of these methods fail,
+gdImageCopy will invoke <A HREF="#gdImageColorClosest">
+gdImageColorClosest</A> to find the color in the destination
+image which most closely approximates the color of the
+pixel being copied.
+<PRE>
+... Inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im_in;
+<A HREF="#gdImagePtr">gdImagePtr</A> im_out;
+int x, y;
+FILE *in;
+FILE *out;
+/* Load a small gif to expand in the larger one */
+in = fopen("small.gif", "rb");
+im_in = <A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A>(in);
+fclose(in);
+/* Make the output image four times as large on both axes */
+im_out = <A HREF="#gdImageCreate">gdImageCreate</A>(im_in->sx * 4, im_in->sy * 4);
+/* Now copy the smaller image, but four times larger */
+gdImageCopyResized(im_out, im_in, 0, 0, 0, 0,
+ im_out->sx, im_out->sy,
+ im_in->sx, im_in->sy);
+out = fopen("large.gif", "wb");
+<A HREF="#gdImageGif">gdImageGif</A>(im_out, out);
+fclose(out);
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im_in);
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im_out);
+</PRE>
+</DL>
+<H3><A NAME="misc">Miscellaneous Functions</A></H3>
+<DL>
+<DT><A NAME="gdImageInterlace">gdImageInterlace(gdImagePtr im, int interlace)</A> <strong>(FUNCTION)</strong>
+<DD>
+gdImageInterlace is used to determine whether an image should be stored
+in a linear fashion, in which lines will appear on the display from
+first to last, or in an interlaced fashion, in which the image
+will "fade in" over several passes. By default, images are not
+interlaced.
+<P>
+A nonzero value for the interlace argument turns on interlace;
+a zero value turns it off. Note that interlace has no effect
+on other functions, and has no meaning unless you save the
+image in GIF format; the gd and xbm formats do not support
+interlace.
+<P>
+When a GIF is loaded with <A HREF="#gdImageCreateFromGif">gdImageCreateFromGif
+</A>, interlace will be set according to the setting in the GIF file.
+<P>
+Note that many GIF viewers and web browsers do <em>not</em> support
+interlace. However, the interlaced GIF should still display; it
+will simply appear all at once, just as other images do.
+<PRE>
+gdImagePtr im;
+FILE *out;
+/* ... Create or load the image... */
+
+/* Now turn on interlace */
+gdImageInterlace(im, 1);
+/* And open an output file */
+out = fopen("test.gif", "wb");
+/* And save the image */
+<A HREF="#gdImageGif">gdImageGif</A>(im, out);
+fclose(out);
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+</DL>
+<H3><A NAME="constants">Constants</A></H3>
+<DL>
+<DT><A NAME="gdBrushed">gdBrushed</A> <strong>(CONSTANT)</strong>
+<DD>
+Used in place of a color when invoking a line-drawing
+function such as <A HREF="#gdImageLine">gdImageLine</A>
+or <A HREF="#gdImageRectangle">gdImageRectangle</A>.
+When gdBrushed is used as the color, the brush
+image set with <A HREF="#gdImageSetBrush">gdImageSetBrush</A>
+is drawn in place of each pixel of the line (the brush is
+usually larger than one pixel, creating the effect
+of a wide paintbrush). See also
+<A HREF="#gdStyledBrushed">gdStyledBrushed</A> for a way
+to draw broken lines with a series of distinct copies of an image.
+<DT><A NAME="gdMaxColors"><code>gdMaxColors</code><strong>(CONSTANT)</strong>
+<DD>
+The constant 256. This is the maximum number of colors in a GIF file
+according to the GIF standard, and is also the maximum number of
+colors in a gd image.
+<DT><A NAME="gdStyled">gdStyled</A> <strong>(CONSTANT)</strong>
+<DD>
+Used in place of a color when invoking a line-drawing
+function such as <A HREF="#gdImageLine">gdImageLine</A>
+or <A HREF="#gdImageRectangle">gdImageRectangle</A>.
+When gdStyled is used as the color, the colors of the pixels are
+drawn successively from the style that has been
+set with <A HREF="#gdImageSetStyle">gdImageSetStyle</A>.
+If the color of a pixel is equal to
+<A HREF="#gdTransparent">gdTransparent</A>, that pixel
+is not altered. (This mechanism is completely unrelated
+to the "transparent color" of the image itself; see
+<A HREF="#gdImageColorTransparent">gdImageColorTransparent</A>
+gdImageColorTransparent for that mechanism.) See also
+<A NAME="#gdStyledBrushed"> gdStyledBrushed</A>.
+<DT><A NAME="gdStyledBrushed">gdStyledBrushed</A> <strong>(CONSTANT)</strong>
+<DD>
+Used in place of a color when invoking a line-drawing
+function such as <A HREF="#gdImageLine">gdImageLine</A>
+or <A HREF="#gdImageRectangle">gdImageRectangle</A>.
+When gdStyledBrushed is used as the color, the brush
+image set with <A HREF="#gdImageSetBrush">gdImageSetBrush</A>
+is drawn at each pixel of the line, providing that the
+style set with <A HREF="#gdImageSetStyle">gdImageSetStyle</A>
+contains a nonzero value (OR gdTransparent, which
+does not equal zero but is supported for consistency)
+for the current pixel. (Pixels are drawn successively from the style as the
+line is drawn, returning to the beginning when the
+available pixels in the style are exhausted.) Note that
+this differs from the behavior of <A HREF="#gdStyled">gdStyled</A>,
+in which the values in the style are used as actual
+pixel colors, except for gdTransparent.
+<DT><A NAME="gdDashSize">gdDashSize</A> <strong>(CONSTANT)</strong>
+<DD>
+The length of a dash in a dashed line. Defined to be 4 for
+backwards compatibility with programs that use
+<A NAME="gdImageDashedLine">gdImageDashedLine</A>. New
+programs should use <A NAME="gdImageSetStyle">
+gdImageSetStyle</A> and call the standard
+<A NAME="gdImageLine">gdImageLine</A> function
+with the special "color" <A NAME="gdStyled">
+gdStyled</A> or <A NAME="gdStyledBrushed">gdStyledBrushed</A>.
+<DT><A NAME="gdTiled">gdTiled</A> <strong>(CONSTANT)</strong>
+<DD>
+Used in place of a normal color in <A HREF="#gdImageFilledRectangle">
+gdImageFilledRectangle</A>, <A HREF="#gdImageFilledPolygon">
+gdImageFilledPolygon</A>,
+<A HREF="#gdImageFill">gdImageFill</A>, and <A HREF="#gdImageFillToBorder">
+gdImageFillToBorder</A>. gdTiled selects a pixel from the
+tile image set with <A HREF="#gdImageSetTile">gdImageSetTile</A>
+in such a way as to ensure that the filled area will be
+tiled with copies of the tile image. See the discussions of
+<A HREF="#gdImageFill">gdImageFill</A> and
+<A HREF="#gdImageFillToBorder">gdImageFillToBorder</A> for special
+restrictions regarding those functions.
+<DT><A NAME="gdTransparent">gdTransparent</A> <strong>(CONSTANT)</strong>
+<DD>
+Used in place of a normal color in a style to be set with
+<A HREF="#gdImageSetStyle">gdImageSetStyle</A>.
+gdTransparent is <strong>not</strong> the transparent
+color index of the image; for that functionality please
+see <A HREF="gdImageColorTransparent">gdImageColorTransparent</A>.
+</DL>
+<A NAME="gdformat"><H3>About the additional .gd image file format</H3></A>
+In addition to reading and writing the GIF format and reading the
+X Bitmap format, gd has the capability to read and write its
+own ".gd" format. This format is <em>not</em> intended for
+general purpose use and should never be used to distribute
+images. It is not a compressed format. Its purpose is solely to
+allow very fast loading of images your program needs often in
+order to build other images for output. If you are experiencing
+performance problems when loading large, fixed GIF images your
+program needs to produce its output images, you may wish
+to examine the functions <A HREF="#gdImageCreateFromGd">
+gdImageCreateFromGd</A> and <A HREF="#gdImageGd">gdImageGd</A>,
+which read and write .gd format images.
+<P>
+The program "giftogd.c" is provided as a simple way of converting
+.gif files to .gd format. I emphasize again that you will not
+need to use this format unless you have a need for high-speed loading
+of a few frequently-used images in your program.
+<A NAME="informing"><H3>Please tell us you're using gd!</H3>
+When you contact us and let us know you are using gd,
+you help us justify the time spent in maintaining and improving
+it. So please let us know. If the results are publicly
+visible on the web, a URL is a wonderful thing to receive, but
+if it's not a publicly visible project, a simple note is just
+as welcome.
+<A NAME="languages"><H3>Using gd with TCL</H3></A>
+If you prefer TCL to C, you can use gd from your tcl program
+thanks to the <A HREF="http://guraldi.hgp.med.umich.edu/gdtcl.html">
+TCL gd extension</A> by Spencer W. Thomas, available at the link
+above or by anonymous FTP to guraldi.hgp.med.umich.edu
+in the directory pub/gdtcl.shar.
+<A NAME="problems"><H3>If you have problems</H3></A>
+If you have any difficulties with gd, feel free to contact
+the author, <A HREF="http://sunsite.unc.edu/boutell/index.html">
+Thomas Boutell</A>. Be sure to read this manual
+carefully first.
+<H3><A NAME="index">Alphabetical quick index</A></H3>
+<A HREF="#gdBrushed">gdBrushed</A> |
+<A HREF="#gdDashSize">gdDashSize</A> |
+<A HREF="#gdFont">gdFont</A> |
+<A HREF="#gdFontPtr">gdFontPtr</A> |
+<A HREF="#gdImage">gdImage</A> |
+<A HREF="#gdImageArc">gdImageArc</A> |
+<A HREF="#gdImageBlue">gdImageBlue</A> |
+<A HREF="#gdImageBoundsSafe">gdImageBoundsSafe</A> |
+<A HREF="#gdImageChar">gdImageChar</A> |
+<A HREF="#gdImageCharUp">gdImageCharUp</A> |
+<A HREF="#gdImageColorAllocate">gdImageColorAllocate</A> |
+<A HREF="#gdImageColorClosest">gdImageColorClosest</A> |
+<A HREF="#gdImageColorDeallocate">gdImageColorDeallocate</A> |
+<A HREF="#gdImageColorExact">gdImageColorExact</A> |
+<A HREF="#gdImageColorTransparent">gdImageColorTransparent</A> |
+<A HREF="#gdImageCopy">gdImageCopy</A> |
+<A HREF="#gdImageCopyResized">gdImageCopyResized</A> |
+<A HREF="#gdImageCreate">gdImageCreate</A> |
+<A HREF="#gdImageCreateFromGd">gdImageCreateFromGd</A> |
+<A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A> |
+<A HREF="#gdImageCreateFromXbm">gdImageCreateFromXbm</A> |
+<A HREF="#gdImageDashedLine">gdImageDashedLine</A> |
+<A HREF="#gdImageDestroy">gdImageDestroy</A> |
+<A HREF="#gdImageFill">gdImageFill</A> |
+<A HREF="#gdImageFillToBorder">gdImageFillToBorder</A> |
+<A HREF="#gdImageFilledRectangle">gdImageFilledRectangle</A> |
+<A HREF="#gdImageGd">gdImageGd</A> |
+<A HREF="#gdImageGetInterlaced">gdImageGetInterlaced</A> |
+<A HREF="#gdImageGetPixel">gdImageGetPixel</A> |
+<A HREF="#gdImageGetTransparent">gdImageGetTransparent</A> |
+<A HREF="#gdImageGif">gdImageGif</A> |
+<A HREF="#gdImageGreen">gdImageGreen</A> |
+<A HREF="#gdImageInterlace">gdImageInterlace</A> |
+<A HREF="#gdImageLine">gdImageLine</A> |
+<A HREF="#gdImageFilledPolygon">gdImageFilledPolygon</A> |
+<A HREF="#gdImagePolygon">gdImagePolygon</A> |
+<A HREF="#gdImagePtr">gdImagePtr</A> |
+<A HREF="#gdImageRectangle">gdImageRectangle</A> |
+<A HREF="#gdImageRed">gdImageRed</A> |
+<A HREF="#gdImageSetBrush">gdImageSetBrush</A> |
+<A HREF="#gdImageSetPixel">gdImageSetPixel</A> |
+<A HREF="#gdImageSetStyle">gdImageSetStyle</A> |
+<A HREF="#gdImageSetTile">gdImageSetTile</A> |
+<A HREF="#gdImageString">gdImageString</A> |
+<A HREF="#gdImageStringUp">gdImageStringUp</A> |
+<A HREF="#gdMaxColors">gdMaxColors</A> |
+<A HREF="#gdPoint">gdPoint</A> |
+<A HREF="#gdStyled">gdStyled</A> |
+<A HREF="#gdStyledBrushed">gdStyledBrushed</A> |
+<A HREF="#gdTiled">gdTiled</A> |
+<A HREF="#gdTransparent">gdTransparent</A>
+<P>
+<em><A HREF="http://sunsite.unc.edu/boutell/index.html">
+Thomas Boutell, boutell at netcom.com</A></em>
+</BODY>
+</HTML>
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gd.c Sat Jul 13 18:46:22 2002
@@ -0,0 +1,2536 @@
+#include <malloc.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "gd.h"
+#include "mtables.c"
+
+static void gdImageBrushApply(gdImagePtr im, int x, int y);
+static void gdImageTileApply(gdImagePtr im, int x, int y);
+
+gdImagePtr gdImageCreate(int sx, int sy)
+{
+ int i;
+ gdImagePtr im;
+ im = (gdImage *) malloc(sizeof(gdImage));
+ im->pixels = (unsigned char **) malloc(sizeof(unsigned char *) * sx);
+ im->polyInts = 0;
+ im->polyAllocated = 0;
+ im->brush = 0;
+ im->tile = 0;
+ im->style = 0;
+ for (i=0; (i<sx); i++) {
+ im->pixels[i] = (unsigned char *) calloc(
+ sy, sizeof(unsigned char));
+ }
+ im->sx = sx;
+ im->sy = sy;
+ im->colorsTotal = 0;
+ im->transparent = (-1);
+ im->interlace = 0;
+ return im;
+}
+
+void gdImageDestroy(gdImagePtr im)
+{
+ int i;
+ for (i=0; (i<im->sx); i++) {
+ free(im->pixels[i]);
+ }
+ free(im->pixels);
+ if (im->polyInts) {
+ free(im->polyInts);
+ }
+ if (im->style) {
+ free(im->style);
+ }
+ free(im);
+}
+
+int gdImageColorClosest(gdImagePtr im, int r, int g, int b)
+{
+ int i;
+ long rd, gd, bd;
+ int ct = (-1);
+ long mindist = 0;
+ for (i=0; (i<(im->colorsTotal)); i++) {
+ long dist;
+ if (im->open[i]) {
+ continue;
+ }
+ rd = (im->red[i] - r);
+ gd = (im->green[i] - g);
+ bd = (im->blue[i] - b);
+ dist = rd * rd + gd * gd + bd * bd;
+ if ((i == 0) || (dist < mindist)) {
+ mindist = dist;
+ ct = i;
+ }
+ }
+ return ct;
+}
+
+int gdImageColorExact(gdImagePtr im, int r, int g, int b)
+{
+ int i;
+ for (i=0; (i<(im->colorsTotal)); i++) {
+ if (im->open[i]) {
+ continue;
+ }
+ if ((im->red[i] == r) &&
+ (im->green[i] == g) &&
+ (im->blue[i] == b)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int gdImageColorAllocate(gdImagePtr im, int r, int g, int b)
+{
+ int i;
+ int ct = (-1);
+ for (i=0; (i<(im->colorsTotal)); i++) {
+ if (im->open[i]) {
+ ct = i;
+ break;
+ }
+ }
+ if (ct == (-1)) {
+ ct = im->colorsTotal;
+ if (ct == gdMaxColors) {
+ return -1;
+ }
+ im->colorsTotal++;
+ }
+ im->red[ct] = r;
+ im->green[ct] = g;
+ im->blue[ct] = b;
+ im->open[ct] = 0;
+ return ct;
+}
+
+void gdImageColorDeallocate(gdImagePtr im, int color)
+{
+ /* Mark it open. */
+ im->open[color] = 1;
+}
+
+void gdImageColorTransparent(gdImagePtr im, int color)
+{
+ im->transparent = color;
+}
+
+void gdImageSetPixel(gdImagePtr im, int x, int y, int color)
+{
+ int p;
+ switch(color) {
+ case gdStyled:
+ if (!im->style) {
+ /* Refuse to draw if no style is set. */
+ return;
+ } else {
+ p = im->style[im->stylePos++];
+ }
+ if (p != (gdTransparent)) {
+ gdImageSetPixel(im, x, y, p);
+ }
+ im->stylePos = im->stylePos % im->styleLength;
+ break;
+ case gdStyledBrushed:
+ if (!im->style) {
+ /* Refuse to draw if no style is set. */
+ return;
+ }
+ p = im->style[im->stylePos++];
+ if ((p != gdTransparent) && (p != 0)) {
+ gdImageSetPixel(im, x, y, gdBrushed);
+ }
+ im->stylePos = im->stylePos % im->styleLength;
+ break;
+ case gdBrushed:
+ gdImageBrushApply(im, x, y);
+ break;
+ case gdTiled:
+ gdImageTileApply(im, x, y);
+ break;
+ default:
+ if (gdImageBoundsSafe(im, x, y)) {
+ im->pixels[x][y] = color;
+ }
+ break;
+ }
+}
+
+static void gdImageBrushApply(gdImagePtr im, int x, int y)
+{
+ int lx, ly;
+ int hy;
+ int hx;
+ int x1, y1, x2, y2;
+ int srcx, srcy;
+ if (!im->brush) {
+ return;
+ }
+ hy = gdImageSY(im->brush)/2;
+ y1 = y - hy;
+ y2 = y1 + gdImageSY(im->brush);
+ hx = gdImageSX(im->brush)/2;
+ x1 = x - hx;
+ x2 = x1 + gdImageSX(im->brush);
+ srcy = 0;
+ for (ly = y1; (ly < y2); ly++) {
+ srcx = 0;
+ for (lx = x1; (lx < x2); lx++) {
+ int p;
+ p = gdImageGetPixel(im->brush, srcx, srcy);
+ /* Allow for non-square brushes! */
+ if (p != gdImageGetTransparent(im->brush)) {
+ gdImageSetPixel(im, lx, ly,
+ im->brushColorMap[p]);
+ }
+ srcx++;
+ }
+ srcy++;
+ }
+}
+
+static void gdImageTileApply(gdImagePtr im, int x, int y)
+{
+ int srcx, srcy;
+ int p;
+ if (!im->tile) {
+ return;
+ }
+ srcx = x % gdImageSX(im->tile);
+ srcy = y % gdImageSY(im->tile);
+ p = gdImageGetPixel(im->tile, srcx, srcy);
+ /* Allow for transparency */
+ if (p != gdImageGetTransparent(im->tile)) {
+ gdImageSetPixel(im, x, y,
+ im->tileColorMap[p]);
+ }
+}
+
+int gdImageGetPixel(gdImagePtr im, int x, int y)
+{
+ if (gdImageBoundsSafe(im, x, y)) {
+ return im->pixels[x][y];
+ } else {
+ return 0;
+ }
+}
+
+/* Bresenham as presented in Foley & Van Dam */
+
+void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+{
+ int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
+ dx = abs(x2-x1);
+ dy = abs(y2-y1);
+ if (dy <= dx) {
+ d = 2*dy - dx;
+ incr1 = 2*dy;
+ incr2 = 2 * (dy - dx);
+ if (x1 > x2) {
+ x = x2;
+ y = y2;
+ ydirflag = (-1);
+ xend = x1;
+ } else {
+ x = x1;
+ y = y1;
+ ydirflag = 1;
+ xend = x2;
+ }
+ gdImageSetPixel(im, x, y, color);
+ if (((y2 - y1) * ydirflag) > 0) {
+ while (x < xend) {
+ x++;
+ if (d <0) {
+ d+=incr1;
+ } else {
+ y++;
+ d+=incr2;
+ }
+ gdImageSetPixel(im, x, y, color);
+ }
+ } else {
+ while (x < xend) {
+ x++;
+ if (d <0) {
+ d+=incr1;
+ } else {
+ y--;
+ d+=incr2;
+ }
+ gdImageSetPixel(im, x, y, color);
+ }
+ }
+ } else {
+ d = 2*dx - dy;
+ incr1 = 2*dx;
+ incr2 = 2 * (dx - dy);
+ if (y1 > y2) {
+ y = y2;
+ x = x2;
+ yend = y1;
+ xdirflag = (-1);
+ } else {
+ y = y1;
+ x = x1;
+ yend = y2;
+ xdirflag = 1;
+ }
+ gdImageSetPixel(im, x, y, color);
+ if (((x2 - x1) * xdirflag) > 0) {
+ while (y < yend) {
+ y++;
+ if (d <0) {
+ d+=incr1;
+ } else {
+ x++;
+ d+=incr2;
+ }
+ gdImageSetPixel(im, x, y, color);
+ }
+ } else {
+ while (y < yend) {
+ y++;
+ if (d <0) {
+ d+=incr1;
+ } else {
+ x--;
+ d+=incr2;
+ }
+ gdImageSetPixel(im, x, y, color);
+ }
+ }
+ }
+}
+
+/* As above, plus dashing */
+
+#define dashedSet \
+ { \
+ dashStep++; \
+ if (dashStep == gdDashSize) { \
+ dashStep = 0; \
+ on = !on; \
+ } \
+ if (on) { \
+ gdImageSetPixel(im, x, y, color); \
+ } \
+ }
+
+void gdImageDashedLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+{
+ int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
+ int dashStep = 0;
+ int on = 1;
+ dx = abs(x2-x1);
+ dy = abs(y2-y1);
+ if (dy <= dx) {
+ d = 2*dy - dx;
+ incr1 = 2*dy;
+ incr2 = 2 * (dy - dx);
+ if (x1 > x2) {
+ x = x2;
+ y = y2;
+ ydirflag = (-1);
+ xend = x1;
+ } else {
+ x = x1;
+ y = y1;
+ ydirflag = 1;
+ xend = x2;
+ }
+ dashedSet;
+ if (((y2 - y1) * ydirflag) > 0) {
+ while (x < xend) {
+ x++;
+ if (d <0) {
+ d+=incr1;
+ } else {
+ y++;
+ d+=incr2;
+ }
+ dashedSet;
+ }
+ } else {
+ while (x < xend) {
+ x++;
+ if (d <0) {
+ d+=incr1;
+ } else {
+ y--;
+ d+=incr2;
+ }
+ dashedSet;
+ }
+ }
+ } else {
+ d = 2*dx - dy;
+ incr1 = 2*dx;
+ incr2 = 2 * (dx - dy);
+ if (y1 > y2) {
+ y = y2;
+ x = x2;
+ yend = y1;
+ xdirflag = (-1);
+ } else {
+ y = y1;
+ x = x1;
+ yend = y2;
+ xdirflag = 1;
+ }
+ dashedSet;
+ if (((x2 - x1) * xdirflag) > 0) {
+ while (y < yend) {
+ y++;
+ if (d <0) {
+ d+=incr1;
+ } else {
+ x++;
+ d+=incr2;
+ }
+ dashedSet;
+ }
+ } else {
+ while (y < yend) {
+ y++;
+ if (d <0) {
+ d+=incr1;
+ } else {
+ x--;
+ d+=incr2;
+ }
+ dashedSet;
+ }
+ }
+ }
+}
+
+int gdImageBoundsSafe(gdImagePtr im, int x, int y)
+{
+ return (!(((y < 0) || (y >= im->sy)) ||
+ ((x < 0) || (x >= im->sx))));
+}
+
+void gdImageChar(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
+{
+ int cx, cy;
+ int px, py;
+ int fline;
+ cx = 0;
+ cy = 0;
+ if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
+ return;
+ }
+ fline = (c - f->offset) * f->h * f->w;
+ for (py = y; (py < (y + f->h)); py++) {
+ for (px = x; (px < (x + f->w)); px++) {
+ if (f->data[fline + cy * f->w + cx]) {
+ gdImageSetPixel(im, px, py, color);
+ }
+ cx++;
+ }
+ cx = 0;
+ cy++;
+ }
+}
+
+void gdImageCharUp(gdImagePtr im, gdFontPtr f, int x, int y, char c, int color)
+{
+ int cx, cy;
+ int px, py;
+ int fline;
+ cx = 0;
+ cy = 0;
+ if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
+ return;
+ }
+ fline = (c - f->offset) * f->h * f->w;
+ for (py = y; (py > (y - f->w)); py--) {
+ for (px = x; (px < (x + f->h)); px++) {
+ if (f->data[fline + cy * f->w + cx]) {
+ gdImageSetPixel(im, px, py, color);
+ }
+ cy++;
+ }
+ cy = 0;
+ cx++;
+ }
+}
+
+void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, char *s, int color)
+{
+ int i;
+ int l;
+ l = strlen(s);
+ for (i=0; (i<l); i++) {
+ gdImageChar(im, f, x, y, s[i], color);
+ x += f->w;
+ }
+}
+
+void gdImageStringUp(gdImagePtr im, gdFontPtr f, int x, int y, char *s, int color)
+{
+ int i;
+ int l;
+ l = strlen(s);
+ for (i=0; (i<l); i++) {
+ gdImageCharUp(im, f, x, y, s[i], color);
+ y -= f->w;
+ }
+}
+
+/* s and e are integers modulo 360 (degrees), with 0 degrees
+ being the rightmost extreme and degrees changing clockwise.
+ cx and cy are the center in pixels; w and h are the horizontal
+ and vertical diameter in pixels. Nice interface, but slow, since
+ I don't yet use Bresenham (I'm using an inefficient but
+ simple solution with too much work going on in it; generalizing
+ Bresenham to ellipses and partial arcs of ellipses is non-trivial,
+ at least for me) and there are other inefficiencies (small circles
+ do far too much work). */
+
+void gdImageArc(gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color)
+{
+ int i;
+ int lx = 0, ly = 0;
+ int w2, h2;
+ w2 = w/2;
+ h2 = h/2;
+ while (e < s) {
+ e += 360;
+ }
+ for (i=s; (i <= e); i++) {
+ int x, y;
+ x = ((long)cost[i % 360] * (long)w2 / costScale) + cx;
+ y = ((long)sint[i % 360] * (long)h2 / sintScale) + cy;
+ if (i != s) {
+ gdImageLine(im, lx, ly, x, y, color);
+ }
+ lx = x;
+ ly = y;
+ }
+}
+
+
+#if 0
+ /* Bresenham octant code, which I should use eventually */
+ int x, y, d;
+ x = 0;
+ y = w;
+ d = 3-2*w;
+ while (x < y) {
+ gdImageSetPixel(im, cx+x, cy+y, color);
+ if (d < 0) {
+ d += 4 * x + 6;
+ } else {
+ d += 4 * (x - y) + 10;
+ y--;
+ }
+ x++;
+ }
+ if (x == y) {
+ gdImageSetPixel(im, cx+x, cy+y, color);
+ }
+#endif
+
+void gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color)
+{
+ int lastBorder;
+ /* Seek left */
+ int leftLimit, rightLimit;
+ int i;
+ leftLimit = (-1);
+ if (border < 0) {
+ /* Refuse to fill to a non-solid border */
+ return;
+ }
+ for (i = x; (i >= 0); i--) {
+ if (gdImageGetPixel(im, i, y) == border) {
+ break;
+ }
+ gdImageSetPixel(im, i, y, color);
+ leftLimit = i;
+ }
+ if (leftLimit == (-1)) {
+ return;
+ }
+ /* Seek right */
+ rightLimit = x;
+ for (i = (x+1); (i < im->sx); i++) {
+ if (gdImageGetPixel(im, i, y) == border) {
+ break;
+ }
+ gdImageSetPixel(im, i, y, color);
+ rightLimit = i;
+ }
+ /* Look at lines above and below and start paints */
+ /* Above */
+ if (y > 0) {
+ lastBorder = 1;
+ for (i = leftLimit; (i <= rightLimit); i++) {
+ int c;
+ c = gdImageGetPixel(im, i, y-1);
+ if (lastBorder) {
+ if ((c != border) && (c != color)) {
+ gdImageFillToBorder(im, i, y-1,
+ border, color);
+ lastBorder = 0;
+ }
+ } else if ((c == border) || (c == color)) {
+ lastBorder = 1;
+ }
+ }
+ }
+ /* Below */
+ if (y < ((im->sy) - 1)) {
+ lastBorder = 1;
+ for (i = leftLimit; (i <= rightLimit); i++) {
+ int c;
+ c = gdImageGetPixel(im, i, y+1);
+ if (lastBorder) {
+ if ((c != border) && (c != color)) {
+ gdImageFillToBorder(im, i, y+1,
+ border, color);
+ lastBorder = 0;
+ }
+ } else if ((c == border) || (c == color)) {
+ lastBorder = 1;
+ }
+ }
+ }
+}
+
+void gdImageFill(gdImagePtr im, int x, int y, int color)
+{
+ int lastBorder;
+ int old;
+ int leftLimit, rightLimit;
+ int i;
+ old = gdImageGetPixel(im, x, y);
+ if (color == gdTiled) {
+ /* Tile fill -- got to watch out! */
+ int p, tileColor;
+ int srcx, srcy;
+ if (!im->tile) {
+ return;
+ }
+ /* Refuse to flood-fill with a transparent pattern --
+ I can't do it without allocating another image */
+ if (gdImageGetTransparent(im->tile) != (-1)) {
+ return;
+ }
+ srcx = x % gdImageSX(im->tile);
+ srcy = y % gdImageSY(im->tile);
+ p = gdImageGetPixel(im->tile, srcx, srcy);
+ tileColor = im->tileColorMap[p];
+ if (old == tileColor) {
+ /* Nothing to be done */
+ return;
+ }
+ } else {
+ if (old == color) {
+ /* Nothing to be done */
+ return;
+ }
+ }
+ /* Seek left */
+ leftLimit = (-1);
+ for (i = x; (i >= 0); i--) {
+ if (gdImageGetPixel(im, i, y) != old) {
+ break;
+ }
+ gdImageSetPixel(im, i, y, color);
+ leftLimit = i;
+ }
+ if (leftLimit == (-1)) {
+ return;
+ }
+ /* Seek right */
+ rightLimit = x;
+ for (i = (x+1); (i < im->sx); i++) {
+ if (gdImageGetPixel(im, i, y) != old) {
+ break;
+ }
+ gdImageSetPixel(im, i, y, color);
+ rightLimit = i;
+ }
+ /* Look at lines above and below and start paints */
+ /* Above */
+ if (y > 0) {
+ lastBorder = 1;
+ for (i = leftLimit; (i <= rightLimit); i++) {
+ int c;
+ c = gdImageGetPixel(im, i, y-1);
+ if (lastBorder) {
+ if (c == old) {
+ gdImageFill(im, i, y-1, color);
+ lastBorder = 0;
+ }
+ } else if (c != old) {
+ lastBorder = 1;
+ }
+ }
+ }
+ /* Below */
+ if (y < ((im->sy) - 1)) {
+ lastBorder = 1;
+ for (i = leftLimit; (i <= rightLimit); i++) {
+ int c;
+ c = gdImageGetPixel(im, i, y+1);
+ if (lastBorder) {
+ if (c == old) {
+ gdImageFill(im, i, y+1, color);
+ lastBorder = 0;
+ }
+ } else if (c != old) {
+ lastBorder = 1;
+ }
+ }
+ }
+}
+
+#ifdef TEST_CODE
+void gdImageDump(gdImagePtr im)
+{
+ int i, j;
+ for (i=0; (i < im->sy); i++) {
+ for (j=0; (j < im->sx); j++) {
+ printf("%d", im->pixels[j][i]);
+ }
+ printf("\n");
+ }
+}
+#endif
+
+/* Code drawn from ppmtogif.c, from the pbmplus package
+**
+** Based on GIFENCOD by David Rowley <mgardi at watdscu.waterloo.edu>. A
+** Lempel-Zim compression based on "compress".
+**
+** Modified by Marcel Wijkstra <wijkstra at fwi.uva.nl>
+**
+** Copyright (C) 1989 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+**
+** The Graphics Interchange Format(c) is the Copyright property of
+** CompuServe Incorporated. GIF(sm) is a Service Mark property of
+** CompuServe Incorporated.
+*/
+
+/*
+ * a code_int must be able to hold 2**GIFBITS values of type int, and also -1
+ */
+typedef int code_int;
+
+#ifdef SIGNED_COMPARE_SLOW
+typedef unsigned long int count_int;
+typedef unsigned short int count_short;
+#else /*SIGNED_COMPARE_SLOW*/
+typedef long int count_int;
+#endif /*SIGNED_COMPARE_SLOW*/
+
+static int colorstobpp(int colors);
+static void BumpPixel (void);
+static int GIFNextPixel (gdImagePtr im);
+static void GIFEncode (FILE *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
+static void Putword (int w, FILE *fp);
+static void compress (int init_bits, FILE *outfile, gdImagePtr im);
+static void output (code_int code);
+static void cl_block (void);
+static void cl_hash (register count_int hsize);
+static void char_init (void);
+static void char_out (int c);
+static void flush_char (void);
+/* Allows for reuse */
+static void init_statics(void);
+
+void gdImageGif(gdImagePtr im, FILE *out)
+{
+ int interlace, transparent, BitsPerPixel;
+ interlace = im->interlace;
+ transparent = im->transparent;
+
+ BitsPerPixel = colorstobpp(im->colorsTotal);
+ /* Clear any old values in statics strewn through the GIF code */
+ init_statics();
+ /* All set, let's do it. */
+ GIFEncode(
+ out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel,
+ im->red, im->green, im->blue, im);
+}
+
+static int
+colorstobpp(int colors)
+{
+ int bpp = 0;
+
+ if ( colors <= 2 )
+ bpp = 1;
+ else if ( colors <= 4 )
+ bpp = 2;
+ else if ( colors <= 8 )
+ bpp = 3;
+ else if ( colors <= 16 )
+ bpp = 4;
+ else if ( colors <= 32 )
+ bpp = 5;
+ else if ( colors <= 64 )
+ bpp = 6;
+ else if ( colors <= 128 )
+ bpp = 7;
+ else if ( colors <= 256 )
+ bpp = 8;
+ return bpp;
+ }
+
+/*****************************************************************************
+ *
+ * GIFENCODE.C - GIF Image compression interface
+ *
+ * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
+ * BitsPerPixel, Red, Green, Blue, gdImagePtr )
+ *
+ *****************************************************************************/
+
+#define TRUE 1
+#define FALSE 0
+
+static int Width, Height;
+static int curx, cury;
+static long CountDown;
+static int Pass = 0;
+static int Interlace;
+
+/*
+ * Bump the 'curx' and 'cury' to point to the next pixel
+ */
+static void
+BumpPixel(void)
+{
+ /*
+ * Bump the current X position
+ */
+ ++curx;
+
+ /*
+ * If we are at the end of a scan line, set curx back to the beginning
+ * If we are interlaced, bump the cury to the appropriate spot,
+ * otherwise, just increment it.
+ */
+ if( curx == Width ) {
+ curx = 0;
+
+ if( !Interlace )
+ ++cury;
+ else {
+ switch( Pass ) {
+
+ case 0:
+ cury += 8;
+ if( cury >= Height ) {
+ ++Pass;
+ cury = 4;
+ }
+ break;
+
+ case 1:
+ cury += 8;
+ if( cury >= Height ) {
+ ++Pass;
+ cury = 2;
+ }
+ break;
+
+ case 2:
+ cury += 4;
+ if( cury >= Height ) {
+ ++Pass;
+ cury = 1;
+ }
+ break;
+
+ case 3:
+ cury += 2;
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * Return the next pixel from the image
+ */
+static int
+GIFNextPixel(gdImagePtr im)
+{
+ int r;
+
+ if( CountDown == 0 )
+ return EOF;
+
+ --CountDown;
+
+ r = gdImageGetPixel(im, curx, cury);
+
+ BumpPixel();
+
+ return r;
+}
+
+/* public */
+
+static void
+GIFEncode(FILE *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
+{
+ int B;
+ int RWidth, RHeight;
+ int LeftOfs, TopOfs;
+ int Resolution;
+ int ColorMapSize;
+ int InitCodeSize;
+ int i;
+
+ Interlace = GInterlace;
+
+ ColorMapSize = 1 << BitsPerPixel;
+
+ RWidth = Width = GWidth;
+ RHeight = Height = GHeight;
+ LeftOfs = TopOfs = 0;
+
+ Resolution = BitsPerPixel;
+
+ /*
+ * Calculate number of bits we are expecting
+ */
+ CountDown = (long)Width * (long)Height;
+
+ /*
+ * Indicate which pass we are on (if interlace)
+ */
+ Pass = 0;
+
+ /*
+ * The initial code size
+ */
+ if( BitsPerPixel <= 1 )
+ InitCodeSize = 2;
+ else
+ InitCodeSize = BitsPerPixel;
+
+ /*
+ * Set up the current x and y position
+ */
+ curx = cury = 0;
+
+ /*
+ * Write the Magic header
+ */
+ fwrite( Transparent < 0 ? "GIF87a" : "GIF89a", 1, 6, fp );
+
+ /*
+ * Write out the screen width and height
+ */
+ Putword( RWidth, fp );
+ Putword( RHeight, fp );
+
+ /*
+ * Indicate that there is a global colour map
+ */
+ B = 0x80; /* Yes, there is a color map */
+
+ /*
+ * OR in the resolution
+ */
+ B |= (Resolution - 1) << 5;
+
+ /*
+ * OR in the Bits per Pixel
+ */
+ B |= (BitsPerPixel - 1);
+
+ /*
+ * Write it out
+ */
+ fputc( B, fp );
+
+ /*
+ * Write out the Background colour
+ */
+ fputc( Background, fp );
+
+ /*
+ * Byte of 0's (future expansion)
+ */
+ fputc( 0, fp );
+
+ /*
+ * Write out the Global Colour Map
+ */
+ for( i=0; i<ColorMapSize; ++i ) {
+ fputc( Red[i], fp );
+ fputc( Green[i], fp );
+ fputc( Blue[i], fp );
+ }
+
+ /*
+ * Write out extension for transparent colour index, if necessary.
+ */
+ if ( Transparent >= 0 ) {
+ fputc( '!', fp );
+ fputc( 0xf9, fp );
+ fputc( 4, fp );
+ fputc( 1, fp );
+ fputc( 0, fp );
+ fputc( 0, fp );
+ fputc( (unsigned char) Transparent, fp );
+ fputc( 0, fp );
+ }
+
+ /*
+ * Write an Image separator
+ */
+ fputc( ',', fp );
+
+ /*
+ * Write the Image header
+ */
+
+ Putword( LeftOfs, fp );
+ Putword( TopOfs, fp );
+ Putword( Width, fp );
+ Putword( Height, fp );
+
+ /*
+ * Write out whether or not the image is interlaced
+ */
+ if( Interlace )
+ fputc( 0x40, fp );
+ else
+ fputc( 0x00, fp );
+
+ /*
+ * Write out the initial code size
+ */
+ fputc( InitCodeSize, fp );
+
+ /*
+ * Go and actually compress the data
+ */
+ compress( InitCodeSize+1, fp, im );
+
+ /*
+ * Write out a Zero-length packet (to end the series)
+ */
+ fputc( 0, fp );
+
+ /*
+ * Write the GIF file terminator
+ */
+ fputc( ';', fp );
+}
+
+/*
+ * Write out a word to the GIF file
+ */
+static void
+Putword(int w, FILE *fp)
+{
+ fputc( w & 0xff, fp );
+ fputc( (w / 256) & 0xff, fp );
+}
+
+
+/***************************************************************************
+ *
+ * GIFCOMPR.C - GIF Image compression routines
+ *
+ * Lempel-Ziv compression based on 'compress'. GIF modifications by
+ * David Rowley (mgardi at watdcsu.waterloo.edu)
+ *
+ ***************************************************************************/
+
+/*
+ * General DEFINEs
+ */
+
+#define GIFBITS 12
+
+#define HSIZE 5003 /* 80% occupancy */
+
+#ifdef NO_UCHAR
+ typedef char char_type;
+#else /*NO_UCHAR*/
+ typedef unsigned char char_type;
+#endif /*NO_UCHAR*/
+
+/*
+ *
+ * GIF Image compression - modified 'compress'
+ *
+ * Based on: compress.c - File compression ala IEEE Computer, June 1984.
+ *
+ * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
+ * Jim McKie (decvax!mcvax!jim)
+ * Steve Davies (decvax!vax135!petsd!peora!srd)
+ * Ken Turkowski (decvax!decwrl!turtlevax!ken)
+ * James A. Woods (decvax!ihnp4!ames!jaw)
+ * Joe Orost (decvax!vax135!petsd!joe)
+ *
+ */
+#include <ctype.h>
+
+#define ARGVAL() (*++(*argv) || (--argc && *++argv))
+
+static int n_bits; /* number of bits/code */
+static int maxbits = GIFBITS; /* user settable max # bits/code */
+static code_int maxcode; /* maximum code, given n_bits */
+static code_int maxmaxcode = (code_int)1 << GIFBITS; /* should NEVER generate this code */
+#ifdef COMPATIBLE /* But wrong! */
+# define MAXCODE(n_bits) ((code_int) 1 << (n_bits) - 1)
+#else /*COMPATIBLE*/
+# define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
+#endif /*COMPATIBLE*/
+
+static count_int htab [HSIZE];
+static unsigned short codetab [HSIZE];
+#define HashTabOf(i) htab[i]
+#define CodeTabOf(i) codetab[i]
+
+static code_int hsize = HSIZE; /* for dynamic table sizing */
+
+/*
+ * To save much memory, we overlay the table used by compress() with those
+ * used by decompress(). The tab_prefix table is the same size and type
+ * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We
+ * get this from the beginning of htab. The output stack uses the rest
+ * of htab, and contains characters. There is plenty of room for any
+ * possible stack (stack used to be 8000 characters).
+ */
+
+#define tab_prefixof(i) CodeTabOf(i)
+#define tab_suffixof(i) ((char_type*)(htab))[i]
+#define de_stack ((char_type*)&tab_suffixof((code_int)1<<GIFBITS))
+
+static code_int free_ent = 0; /* first unused entry */
+
+/*
+ * block compression parameters -- after all codes are used up,
+ * and compression rate changes, start over.
+ */
+static int clear_flg = 0;
+
+static int offset;
+static long int in_count = 1; /* length of input */
+static long int out_count = 0; /* # of codes output (for debugging) */
+
+/*
+ * compress stdin to stdout
+ *
+ * Algorithm: use open addressing double hashing (no chaining) on the
+ * prefix code / next character combination. We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe. Here, the modular division first probe is gives way
+ * to a faster exclusive-or manipulation. Also do block compression with
+ * an adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills. The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor. Late addition: construct the table according to
+ * file size for noticeable speed improvement on small files. Please direct
+ * questions about this implementation to ames!jaw.
+ */
+
+static int g_init_bits;
+static FILE* g_outfile;
+
+static int ClearCode;
+static int EOFCode;
+
+static void
+compress(int init_bits, FILE *outfile, gdImagePtr im)
+{
+ register long fcode;
+ register code_int i /* = 0 */;
+ register int c;
+ register code_int ent;
+ register code_int disp;
+ register code_int hsize_reg;
+ register int hshift;
+
+ /*
+ * Set up the globals: g_init_bits - initial number of bits
+ * g_outfile - pointer to output file
+ */
+ g_init_bits = init_bits;
+ g_outfile = outfile;
+
+ /*
+ * Set up the necessary values
+ */
+ offset = 0;
+ out_count = 0;
+ clear_flg = 0;
+ in_count = 1;
+ maxcode = MAXCODE(n_bits = g_init_bits);
+
+ ClearCode = (1 << (init_bits - 1));
+ EOFCode = ClearCode + 1;
+ free_ent = ClearCode + 2;
+
+ char_init();
+
+ ent = GIFNextPixel( im );
+
+ hshift = 0;
+ for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L )
+ ++hshift;
+ hshift = 8 - hshift; /* set hash code range bound */
+
+ hsize_reg = hsize;
+ cl_hash( (count_int) hsize_reg); /* clear hash table */
+
+ output( (code_int)ClearCode );
+
+#ifdef SIGNED_COMPARE_SLOW
+ while ( (c = GIFNextPixel( im )) != (unsigned) EOF ) {
+#else /*SIGNED_COMPARE_SLOW*/
+ while ( (c = GIFNextPixel( im )) != EOF ) { /* } */
+#endif /*SIGNED_COMPARE_SLOW*/
+
+ ++in_count;
+
+ fcode = (long) (((long) c << maxbits) + ent);
+ i = (((code_int)c << hshift) ^ ent); /* xor hashing */
+
+ if ( HashTabOf (i) == fcode ) {
+ ent = CodeTabOf (i);
+ continue;
+ } else if ( (long)HashTabOf (i) < 0 ) /* empty slot */
+ goto nomatch;
+ disp = hsize_reg - i; /* secondary hash (after G. Knott) */
+ if ( i == 0 )
+ disp = 1;
+probe:
+ if ( (i -= disp) < 0 )
+ i += hsize_reg;
+
+ if ( HashTabOf (i) == fcode ) {
+ ent = CodeTabOf (i);
+ continue;
+ }
+ if ( (long)HashTabOf (i) > 0 )
+ goto probe;
+nomatch:
+ output ( (code_int) ent );
+ ++out_count;
+ ent = c;
+#ifdef SIGNED_COMPARE_SLOW
+ if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
+#else /*SIGNED_COMPARE_SLOW*/
+ if ( free_ent < maxmaxcode ) { /* } */
+#endif /*SIGNED_COMPARE_SLOW*/
+ CodeTabOf (i) = free_ent++; /* code -> hashtable */
+ HashTabOf (i) = fcode;
+ } else
+ cl_block();
+ }
+ /*
+ * Put out the final code.
+ */
+ output( (code_int)ent );
+ ++out_count;
+ output( (code_int) EOFCode );
+}
+
+/*****************************************************************
+ * TAG( output )
+ *
+ * Output the given code.
+ * Inputs:
+ * code: A n_bits-bit integer. If == -1, then EOF. This assumes
+ * that n_bits =< (long)wordsize - 1.
+ * Outputs:
+ * Outputs code to the file.
+ * Assumptions:
+ * Chars are 8 bits long.
+ * Algorithm:
+ * Maintain a GIFBITS character long buffer (so that 8 codes will
+ * fit in it exactly). Use the VAX insv instruction to insert each
+ * code in turn. When the buffer fills up empty it and start over.
+ */
+
+static unsigned long cur_accum = 0;
+static int cur_bits = 0;
+
+static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
+ 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
+ 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+static void
+output(code_int code)
+{
+ cur_accum &= masks[ cur_bits ];
+
+ if( cur_bits > 0 )
+ cur_accum |= ((long)code << cur_bits);
+ else
+ cur_accum = code;
+
+ cur_bits += n_bits;
+
+ while( cur_bits >= 8 ) {
+ char_out( (unsigned int)(cur_accum & 0xff) );
+ cur_accum >>= 8;
+ cur_bits -= 8;
+ }
+
+ /*
+ * If the next entry is going to be too big for the code size,
+ * then increase it, if possible.
+ */
+ if ( free_ent > maxcode || clear_flg ) {
+
+ if( clear_flg ) {
+
+ maxcode = MAXCODE (n_bits = g_init_bits);
+ clear_flg = 0;
+
+ } else {
+
+ ++n_bits;
+ if ( n_bits == maxbits )
+ maxcode = maxmaxcode;
+ else
+ maxcode = MAXCODE(n_bits);
+ }
+ }
+
+ if( code == EOFCode ) {
+ /*
+ * At EOF, write the rest of the buffer.
+ */
+ while( cur_bits > 0 ) {
+ char_out( (unsigned int)(cur_accum & 0xff) );
+ cur_accum >>= 8;
+ cur_bits -= 8;
+ }
+
+ flush_char();
+
+ fflush( g_outfile );
+
+ if( ferror( g_outfile ) )
+ return;
+ }
+}
+
+/*
+ * Clear out the hash table
+ */
+static void
+cl_block (void) /* table clear for block compress */
+{
+
+ cl_hash ( (count_int) hsize );
+ free_ent = ClearCode + 2;
+ clear_flg = 1;
+
+ output( (code_int)ClearCode );
+}
+
+static void
+cl_hash(register count_int hsize) /* reset code table */
+
+{
+
+ register count_int *htab_p = htab+hsize;
+
+ register long i;
+ register long m1 = -1;
+
+ i = hsize - 16;
+ do { /* might use Sys V memset(3) here */
+ *(htab_p-16) = m1;
+ *(htab_p-15) = m1;
+ *(htab_p-14) = m1;
+ *(htab_p-13) = m1;
+ *(htab_p-12) = m1;
+ *(htab_p-11) = m1;
+ *(htab_p-10) = m1;
+ *(htab_p-9) = m1;
+ *(htab_p-8) = m1;
+ *(htab_p-7) = m1;
+ *(htab_p-6) = m1;
+ *(htab_p-5) = m1;
+ *(htab_p-4) = m1;
+ *(htab_p-3) = m1;
+ *(htab_p-2) = m1;
+ *(htab_p-1) = m1;
+ htab_p -= 16;
+ } while ((i -= 16) >= 0);
+
+ for ( i += 16; i > 0; --i )
+ *--htab_p = m1;
+}
+
+/******************************************************************************
+ *
+ * GIF Specific routines
+ *
+ ******************************************************************************/
+
+/*
+ * Number of characters so far in this 'packet'
+ */
+static int a_count;
+
+/*
+ * Set up the 'byte output' routine
+ */
+static void
+char_init(void)
+{
+ a_count = 0;
+}
+
+/*
+ * Define the storage for the packet accumulator
+ */
+static char accum[ 256 ];
+
+/*
+ * Add a character to the end of the current packet, and if it is 254
+ * characters, flush the packet to disk.
+ */
+static void
+char_out(int c)
+{
+ accum[ a_count++ ] = c;
+ if( a_count >= 254 )
+ flush_char();
+}
+
+/*
+ * Flush the packet to disk, and reset the accumulator
+ */
+static void
+flush_char(void)
+{
+ if( a_count > 0 ) {
+ fputc( a_count, g_outfile );
+ fwrite( accum, 1, a_count, g_outfile );
+ a_count = 0;
+ }
+}
+
+static void init_statics(void) {
+ /* Some of these are properly initialized later. What I'm doing
+ here is making sure code that depends on C's initialization
+ of statics doesn't break when the code gets called more
+ than once. */
+ Width = 0;
+ Height = 0;
+ curx = 0;
+ cury = 0;
+ CountDown = 0;
+ Pass = 0;
+ Interlace = 0;
+ a_count = 0;
+ cur_accum = 0;
+ cur_bits = 0;
+ g_init_bits = 0;
+ g_outfile = 0;
+ ClearCode = 0;
+ EOFCode = 0;
+ free_ent = 0;
+ clear_flg = 0;
+ offset = 0;
+ in_count = 1;
+ out_count = 0;
+ hsize = HSIZE;
+ n_bits = 0;
+ maxbits = GIFBITS;
+ maxcode = 0;
+ maxmaxcode = (code_int)1 << GIFBITS;
+}
+
+
+/* +-------------------------------------------------------------------+ */
+/* | Copyright 1990, 1991, 1993, David Koblas. (koblas at netcom.com) | */
+/* | Permission to use, copy, modify, and distribute this software | */
+/* | and its documentation for any purpose and without fee is hereby | */
+/* | granted, provided that the above copyright notice appear in all | */
+/* | copies and that both that copyright notice and this permission | */
+/* | notice appear in supporting documentation. This software is | */
+/* | provided "as is" without express or implied warranty. | */
+/* +-------------------------------------------------------------------+ */
+
+
+#define MAXCOLORMAPSIZE 256
+
+#define TRUE 1
+#define FALSE 0
+
+#define CM_RED 0
+#define CM_GREEN 1
+#define CM_BLUE 2
+
+#define MAX_LWZ_BITS 12
+
+#define INTERLACE 0x40
+#define LOCALCOLORMAP 0x80
+#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
+
+#define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
+
+#define LM_to_uint(a,b) (((b)<<8)|(a))
+
+/* We may eventually want to use this information, but def it out for now */
+#if 0
+static struct {
+ unsigned int Width;
+ unsigned int Height;
+ unsigned char ColorMap[3][MAXCOLORMAPSIZE];
+ unsigned int BitPixel;
+ unsigned int ColorResolution;
+ unsigned int Background;
+ unsigned int AspectRatio;
+} GifScreen;
+#endif
+
+static struct {
+ int transparent;
+ int delayTime;
+ int inputFlag;
+ int disposal;
+} Gif89 = { -1, -1, -1, 0 };
+
+static int ReadColorMap (FILE *fd, int number, unsigned char (*buffer)[256]);
+static int DoExtension (FILE *fd, int label, int *Transparent);
+static int GetDataBlock (FILE *fd, unsigned char *buf);
+static int GetCode (FILE *fd, int code_size, int flag);
+static int LWZReadByte (FILE *fd, int flag, int input_code_size);
+static void ReadImage (gdImagePtr im, FILE *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int ignore);
+
+int ZeroDataBlock;
+
+gdImagePtr
+gdImageCreateFromGif(FILE *fd)
+{
+ int imageNumber;
+ int BitPixel;
+ int ColorResolution;
+ int Background;
+ int AspectRatio;
+ int Transparent = (-1);
+ unsigned char buf[16];
+ unsigned char c;
+ unsigned char ColorMap[3][MAXCOLORMAPSIZE];
+ unsigned char localColorMap[3][MAXCOLORMAPSIZE];
+ int imw, imh;
+ int useGlobalColormap;
+ int bitPixel;
+ int imageCount = 0;
+ char version[4];
+ gdImagePtr im = 0;
+ ZeroDataBlock = FALSE;
+
+ imageNumber = 1;
+ if (! ReadOK(fd,buf,6)) {
+ return 0;
+ }
+ if (strncmp((char *)buf,"GIF",3) != 0) {
+ return 0;
+ }
+ strncpy(version, (char *)buf + 3, 3);
+ version[3] = '\0';
+
+ if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
+ return 0;
+ }
+ if (! ReadOK(fd,buf,7)) {
+ return 0;
+ }
+ BitPixel = 2<<(buf[4]&0x07);
+ ColorResolution = (int) (((buf[4]&0x70)>>3)+1);
+ Background = buf[5];
+ AspectRatio = buf[6];
+
+ if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
+ if (ReadColorMap(fd, BitPixel, ColorMap)) {
+ return 0;
+ }
+ }
+ for (;;) {
+ if (! ReadOK(fd,&c,1)) {
+ return 0;
+ }
+ if (c == ';') { /* GIF terminator */
+ int i;
+ if (imageCount < imageNumber) {
+ return 0;
+ }
+ /* Terminator before any image was declared! */
+ if (!im) {
+ return 0;
+ }
+ /* Check for open colors at the end, so
+ we can reduce colorsTotal and ultimately
+ BitsPerPixel */
+ for (i=((im->colorsTotal-1)); (i>=0); i--) {
+ if (im->open[i]) {
+ im->colorsTotal--;
+ } else {
+ break;
+ }
+ }
+ return im;
+ }
+
+ if (c == '!') { /* Extension */
+ if (! ReadOK(fd,&c,1)) {
+ return 0;
+ }
+ DoExtension(fd, c, &Transparent);
+ continue;
+ }
+
+ if (c != ',') { /* Not a valid start character */
+ continue;
+ }
+
+ ++imageCount;
+
+ if (! ReadOK(fd,buf,9)) {
+ return 0;
+ }
+
+ useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
+
+ bitPixel = 1<<((buf[8]&0x07)+1);
+
+ imw = LM_to_uint(buf[4],buf[5]);
+ imh = LM_to_uint(buf[6],buf[7]);
+ if (!(im = gdImageCreate(imw, imh))) {
+ return 0;
+ }
+ im->interlace = BitSet(buf[8], INTERLACE);
+ if (! useGlobalColormap) {
+ if (ReadColorMap(fd, bitPixel, localColorMap)) {
+ return 0;
+ }
+ ReadImage(im, fd, imw, imh, localColorMap,
+ BitSet(buf[8], INTERLACE),
+ imageCount != imageNumber);
+ } else {
+ ReadImage(im, fd, imw, imh,
+ ColorMap,
+ BitSet(buf[8], INTERLACE),
+ imageCount != imageNumber);
+ }
+ if (Transparent != (-1)) {
+ gdImageColorTransparent(im, Transparent);
+ }
+ }
+}
+
+static int
+ReadColorMap(FILE *fd, int number, unsigned char (*buffer)[256])
+{
+ int i;
+ unsigned char rgb[3];
+
+
+ for (i = 0; i < number; ++i) {
+ if (! ReadOK(fd, rgb, sizeof(rgb))) {
+ return TRUE;
+ }
+ buffer[CM_RED][i] = rgb[0] ;
+ buffer[CM_GREEN][i] = rgb[1] ;
+ buffer[CM_BLUE][i] = rgb[2] ;
+ }
+
+
+ return FALSE;
+}
+
+static int
+DoExtension(FILE *fd, int label, int *Transparent)
+{
+ static unsigned char buf[256];
+
+ switch (label) {
+ case 0xf9: /* Graphic Control Extension */
+ (void) GetDataBlock(fd, (unsigned char*) buf);
+ Gif89.disposal = (buf[0] >> 2) & 0x7;
+ Gif89.inputFlag = (buf[0] >> 1) & 0x1;
+ Gif89.delayTime = LM_to_uint(buf[1],buf[2]);
+ if ((buf[0] & 0x1) != 0)
+ *Transparent = buf[3];
+
+ while (GetDataBlock(fd, (unsigned char*) buf) != 0)
+ ;
+ return FALSE;
+ default:
+ break;
+ }
+ while (GetDataBlock(fd, (unsigned char*) buf) != 0)
+ ;
+
+ return FALSE;
+}
+
+static int
+GetDataBlock(FILE *fd, unsigned char *buf)
+{
+ unsigned char count;
+
+ if (! ReadOK(fd,&count,1)) {
+ return -1;
+ }
+
+ ZeroDataBlock = count == 0;
+
+ if ((count != 0) && (! ReadOK(fd, buf, count))) {
+ return -1;
+ }
+
+ return count;
+}
+
+static int
+GetCode(FILE *fd, int code_size, int flag)
+{
+ static unsigned char buf[280];
+ static int curbit, lastbit, done, last_byte;
+ int i, j, ret;
+ unsigned char count;
+
+ if (flag) {
+ curbit = 0;
+ lastbit = 0;
+ done = FALSE;
+ return 0;
+ }
+
+ if ( (curbit+code_size) >= lastbit) {
+ if (done) {
+ if (curbit >= lastbit) {
+ /* Oh well */
+ }
+ return -1;
+ }
+ buf[0] = buf[last_byte-2];
+ buf[1] = buf[last_byte-1];
+
+ if ((count = GetDataBlock(fd, &buf[2])) == 0)
+ done = TRUE;
+
+ last_byte = 2 + count;
+ curbit = (curbit - lastbit) + 16;
+ lastbit = (2+count)*8 ;
+ }
+
+ ret = 0;
+ for (i = curbit, j = 0; j < code_size; ++i, ++j)
+ ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
+
+ curbit += code_size;
+
+ return ret;
+}
+
+static int
+LWZReadByte(FILE *fd, int flag, int input_code_size)
+{
+ static int fresh = FALSE;
+ int code, incode;
+ static int code_size, set_code_size;
+ static int max_code, max_code_size;
+ static int firstcode, oldcode;
+ static int clear_code, end_code;
+ static int table[2][(1<< MAX_LWZ_BITS)];
+ static int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
+ register int i;
+
+ if (flag) {
+ set_code_size = input_code_size;
+ code_size = set_code_size+1;
+ clear_code = 1 << set_code_size ;
+ end_code = clear_code + 1;
+ max_code_size = 2*clear_code;
+ max_code = clear_code+2;
+
+ GetCode(fd, 0, TRUE);
+
+ fresh = TRUE;
+
+ for (i = 0; i < clear_code; ++i) {
+ table[0][i] = 0;
+ table[1][i] = i;
+ }
+ for (; i < (1<<MAX_LWZ_BITS); ++i)
+ table[0][i] = table[1][0] = 0;
+
+ sp = stack;
+
+ return 0;
+ } else if (fresh) {
+ fresh = FALSE;
+ do {
+ firstcode = oldcode =
+ GetCode(fd, code_size, FALSE);
+ } while (firstcode == clear_code);
+ return firstcode;
+ }
+
+ if (sp > stack)
+ return *--sp;
+
+ while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
+ if (code == clear_code) {
+ for (i = 0; i < clear_code; ++i) {
+ table[0][i] = 0;
+ table[1][i] = i;
+ }
+ for (; i < (1<<MAX_LWZ_BITS); ++i)
+ table[0][i] = table[1][i] = 0;
+ code_size = set_code_size+1;
+ max_code_size = 2*clear_code;
+ max_code = clear_code+2;
+ sp = stack;
+ firstcode = oldcode =
+ GetCode(fd, code_size, FALSE);
+ return firstcode;
+ } else if (code == end_code) {
+ int count;
+ unsigned char buf[260];
+
+ if (ZeroDataBlock)
+ return -2;
+
+ while ((count = GetDataBlock(fd, buf)) > 0)
+ ;
+
+ if (count != 0)
+ return -2;
+ }
+
+ incode = code;
+
+ if (code >= max_code) {
+ *sp++ = firstcode;
+ code = oldcode;
+ }
+
+ while (code >= clear_code) {
+ *sp++ = table[1][code];
+ if (code == table[0][code]) {
+ /* Oh well */
+ }
+ code = table[0][code];
+ }
+
+ *sp++ = firstcode = table[1][code];
+
+ if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
+ table[0][code] = oldcode;
+ table[1][code] = firstcode;
+ ++max_code;
+ if ((max_code >= max_code_size) &&
+ (max_code_size < (1<<MAX_LWZ_BITS))) {
+ max_code_size *= 2;
+ ++code_size;
+ }
+ }
+
+ oldcode = incode;
+
+ if (sp > stack)
+ return *--sp;
+ }
+ return code;
+}
+
+static void
+ReadImage(gdImagePtr im, FILE *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int ignore)
+{
+ unsigned char c;
+ int v;
+ int xpos = 0, ypos = 0, pass = 0;
+ int i;
+ /* Stash the color map into the image */
+ for (i=0; (i<gdMaxColors); i++) {
+ im->red[i] = cmap[CM_RED][i];
+ im->green[i] = cmap[CM_GREEN][i];
+ im->blue[i] = cmap[CM_BLUE][i];
+ im->open[i] = 1;
+ }
+ /* Many (perhaps most) of these colors will remain marked open. */
+ im->colorsTotal = gdMaxColors;
+ /*
+ ** Initialize the Compression routines
+ */
+ if (! ReadOK(fd,&c,1)) {
+ return;
+ }
+ if (LWZReadByte(fd, TRUE, c) < 0) {
+ return;
+ }
+
+ /*
+ ** If this is an "uninteresting picture" ignore it.
+ */
+ if (ignore) {
+ while (LWZReadByte(fd, FALSE, c) >= 0)
+ ;
+ return;
+ }
+
+ while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
+ /* This how we recognize which colors are actually used. */
+ if (im->open[v]) {
+ im->open[v] = 0;
+ }
+ gdImageSetPixel(im, xpos, ypos, v);
+ ++xpos;
+ if (xpos == len) {
+ xpos = 0;
+ if (interlace) {
+ switch (pass) {
+ case 0:
+ case 1:
+ ypos += 8; break;
+ case 2:
+ ypos += 4; break;
+ case 3:
+ ypos += 2; break;
+ }
+
+ if (ypos >= height) {
+ ++pass;
+ switch (pass) {
+ case 1:
+ ypos = 4; break;
+ case 2:
+ ypos = 2; break;
+ case 3:
+ ypos = 1; break;
+ default:
+ goto fini;
+ }
+ }
+ } else {
+ ++ypos;
+ }
+ }
+ if (ypos >= height)
+ break;
+ }
+
+fini:
+ if (LWZReadByte(fd,FALSE,c)>=0) {
+ /* Ignore extra */
+ }
+}
+
+void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+{
+ gdImageLine(im, x1, y1, x2, y1, color);
+ gdImageLine(im, x1, y2, x2, y2, color);
+ gdImageLine(im, x1, y1, x1, y2, color);
+ gdImageLine(im, x2, y1, x2, y2, color);
+}
+
+void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+{
+ int x, y;
+ for (y=y1; (y<=y2); y++) {
+ for (x=x1; (x<=x2); x++) {
+ gdImageSetPixel(im, x, y, color);
+ }
+ }
+}
+
+void gdImageCopy(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h)
+{
+ int c;
+ int x, y;
+ int tox, toy;
+ int i;
+ int colorMap[gdMaxColors];
+ for (i=0; (i<gdMaxColors); i++) {
+ colorMap[i] = (-1);
+ }
+ toy = dstY;
+ for (y=srcY; (y < (srcY + h)); y++) {
+ tox = dstX;
+ for (x=srcX; (x < (srcX + w)); x++) {
+ int nc;
+ c = gdImageGetPixel(src, x, y);
+ /* Added 7/24/95: support transparent copies */
+ if (gdImageGetTransparent(src) == c) {
+ tox++;
+ continue;
+ }
+ /* Have we established a mapping for this color? */
+ if (colorMap[c] == (-1)) {
+ /* If it's the same image, mapping is trivial */
+ if (dst == src) {
+ nc = c;
+ } else {
+ /* First look for an exact match */
+ nc = gdImageColorExact(dst,
+ src->red[c], src->green[c],
+ src->blue[c]);
+ }
+ if (nc == (-1)) {
+ /* No, so try to allocate it */
+ nc = gdImageColorAllocate(dst,
+ src->red[c], src->green[c],
+ src->blue[c]);
+ /* If we're out of colors, go for the
+ closest color */
+ if (nc == (-1)) {
+ nc = gdImageColorClosest(dst,
+ src->red[c], src->green[c],
+ src->blue[c]);
+ }
+ }
+ colorMap[c] = nc;
+ }
+ gdImageSetPixel(dst, tox, toy, colorMap[c]);
+ tox++;
+ }
+ toy++;
+ }
+}
+
+void gdImageCopyResized(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)
+{
+ int c;
+ int x, y;
+ int tox, toy;
+ int ydest;
+ int i;
+ int colorMap[gdMaxColors];
+ /* Stretch vectors */
+ int *stx;
+ int *sty;
+ /* We only need to use floating point to determine the correct
+ stretch vector for one line's worth. */
+ double accum;
+ stx = (int *) malloc(sizeof(int) * srcW);
+ sty = (int *) malloc(sizeof(int) * srcH);
+ accum = 0;
+ for (i=0; (i < srcW); i++) {
+ int got;
+ accum += (double)dstW/(double)srcW;
+ got = floor(accum);
+ stx[i] = got;
+ accum -= got;
+ }
+ accum = 0;
+ for (i=0; (i < srcH); i++) {
+ int got;
+ accum += (double)dstH/(double)srcH;
+ got = floor(accum);
+ sty[i] = got;
+ accum -= got;
+ }
+ for (i=0; (i<gdMaxColors); i++) {
+ colorMap[i] = (-1);
+ }
+ toy = dstY;
+ for (y=srcY; (y < (srcY + srcH)); y++) {
+ for (ydest=0; (ydest < sty[y-srcY]); ydest++) {
+ tox = dstX;
+ for (x=srcX; (x < (srcX + srcW)); x++) {
+ int nc;
+ if (!stx[x - srcX]) {
+ continue;
+ }
+ c = gdImageGetPixel(src, x, y);
+ /* Added 7/24/95: support transparent copies */
+ if (gdImageGetTransparent(src) == c) {
+ tox += stx[x-srcX];
+ continue;
+ }
+ /* Have we established a mapping for this color? */
+ if (colorMap[c] == (-1)) {
+ /* If it's the same image, mapping is trivial */
+ if (dst == src) {
+ nc = c;
+ } else {
+ /* First look for an exact match */
+ nc = gdImageColorExact(dst,
+ src->red[c], src->green[c],
+ src->blue[c]);
+ }
+ if (nc == (-1)) {
+ /* No, so try to allocate it */
+ nc = gdImageColorAllocate(dst,
+ src->red[c], src->green[c],
+ src->blue[c]);
+ /* If we're out of colors, go for the
+ closest color */
+ if (nc == (-1)) {
+ nc = gdImageColorClosest(dst,
+ src->red[c], src->green[c],
+ src->blue[c]);
+ }
+ }
+ colorMap[c] = nc;
+ }
+ for (i=0; (i < stx[x - srcX]); i++) {
+ gdImageSetPixel(dst, tox, toy, colorMap[c]);
+ tox++;
+ }
+ }
+ toy++;
+ }
+ }
+ free(stx);
+ free(sty);
+}
+
+int gdGetWord(int *result, FILE *in)
+{
+ int r;
+ r = getc(in);
+ if (r == EOF) {
+ return 0;
+ }
+ *result = r << 8;
+ r = getc(in);
+ if (r == EOF) {
+ return 0;
+ }
+ *result += r;
+ return 1;
+}
+
+void gdPutWord(int w, FILE *out)
+{
+ putc((unsigned char)(w >> 8), out);
+ putc((unsigned char)(w & 0xFF), out);
+}
+
+int gdGetByte(int *result, FILE *in)
+{
+ int r;
+ r = getc(in);
+ if (r == EOF) {
+ return 0;
+ }
+ *result = r;
+ return 1;
+}
+
+gdImagePtr gdImageCreateFromGd(FILE *in)
+{
+ int sx, sy;
+ int x, y;
+ int i;
+ gdImagePtr im;
+ if (!gdGetWord(&sx, in)) {
+ goto fail1;
+ }
+ if (!gdGetWord(&sy, in)) {
+ goto fail1;
+ }
+ im = gdImageCreate(sx, sy);
+ if (!gdGetByte(&im->colorsTotal, in)) {
+ goto fail2;
+ }
+ if (!gdGetWord(&im->transparent, in)) {
+ goto fail2;
+ }
+ if (im->transparent == 257) {
+ im->transparent = (-1);
+ }
+ for (i=0; (i<gdMaxColors); i++) {
+ if (!gdGetByte(&im->red[i], in)) {
+ goto fail2;
+ }
+ if (!gdGetByte(&im->green[i], in)) {
+ goto fail2;
+ }
+ if (!gdGetByte(&im->blue[i], in)) {
+ goto fail2;
+ }
+ }
+ for (y=0; (y<sy); y++) {
+ for (x=0; (x<sx); x++) {
+ int ch;
+ ch = getc(in);
+ if (ch == EOF) {
+ gdImageDestroy(im);
+ return 0;
+ }
+ im->pixels[x][y] = ch;
+ }
+ }
+ return im;
+fail2:
+ gdImageDestroy(im);
+fail1:
+ return 0;
+}
+
+void gdImageGd(gdImagePtr im, FILE *out)
+{
+ int x, y;
+ int i;
+ int trans;
+ gdPutWord(im->sx, out);
+ gdPutWord(im->sy, out);
+ putc((unsigned char)im->colorsTotal, out);
+ trans = im->transparent;
+ if (trans == (-1)) {
+ trans = 257;
+ }
+ gdPutWord(trans, out);
+ for (i=0; (i<gdMaxColors); i++) {
+ putc((unsigned char)im->red[i], out);
+ putc((unsigned char)im->green[i], out);
+ putc((unsigned char)im->blue[i], out);
+ }
+ for (y=0; (y < im->sy); y++) {
+ for (x=0; (x < im->sx); x++) {
+ putc((unsigned char)im->pixels[x][y], out);
+ }
+ }
+}
+
+gdImagePtr
+gdImageCreateFromXbm(FILE *fd)
+{
+ gdImagePtr im;
+ int bit;
+ int w, h;
+ int bytes;
+ int ch;
+ int i, x, y;
+ char *sp;
+ char s[161];
+ if (!fgets(s, 160, fd)) {
+ return 0;
+ }
+ sp = &s[0];
+ /* Skip #define */
+ sp = strchr(sp, ' ');
+ if (!sp) {
+ return 0;
+ }
+ /* Skip width label */
+ sp++;
+ sp = strchr(sp, ' ');
+ if (!sp) {
+ return 0;
+ }
+ /* Get width */
+ w = atoi(sp + 1);
+ if (!w) {
+ return 0;
+ }
+ if (!fgets(s, 160, fd)) {
+ return 0;
+ }
+ sp = s;
+ /* Skip #define */
+ sp = strchr(sp, ' ');
+ if (!sp) {
+ return 0;
+ }
+ /* Skip height label */
+ sp++;
+ sp = strchr(sp, ' ');
+ if (!sp) {
+ return 0;
+ }
+ /* Get height */
+ h = atoi(sp + 1);
+ if (!h) {
+ return 0;
+ }
+ /* Skip declaration line */
+ if (!fgets(s, 160, fd)) {
+ return 0;
+ }
+ bytes = (w * h / 8) + 1;
+ im = gdImageCreate(w, h);
+ gdImageColorAllocate(im, 255, 255, 255);
+ gdImageColorAllocate(im, 0, 0, 0);
+ x = 0;
+ y = 0;
+ for (i=0; (i < bytes); i++) {
+ char h[3];
+ int b;
+ /* Skip spaces, commas, CRs, 0x */
+ while(1) {
+ ch = getc(fd);
+ if (ch == EOF) {
+ goto fail;
+ }
+ if (ch == 'x') {
+ break;
+ }
+ }
+ /* Get hex value */
+ ch = getc(fd);
+ if (ch == EOF) {
+ goto fail;
+ }
+ h[0] = ch;
+ ch = getc(fd);
+ if (ch == EOF) {
+ goto fail;
+ }
+ h[1] = ch;
+ h[2] = '\0';
+ sscanf(h, "%x", &b);
+ for (bit = 1; (bit <= 128); (bit = bit << 1)) {
+ gdImageSetPixel(im, x++, y, (b & bit) ? 1 : 0);
+ if (x == im->sx) {
+ x = 0;
+ y++;
+ if (y == im->sy) {
+ return im;
+ }
+ /* Fix 8/8/95 */
+ break;
+ }
+ }
+ }
+ /* Shouldn't happen */
+ fprintf(stderr, "Error: bug in gdImageCreateFromXbm!\n");
+ return 0;
+fail:
+ gdImageDestroy(im);
+ return 0;
+}
+
+void gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c)
+{
+ int i;
+ int lx, ly;
+ if (!n) {
+ return;
+ }
+ lx = p->x;
+ ly = p->y;
+ gdImageLine(im, lx, ly, p[n-1].x, p[n-1].y, c);
+ for (i=1; (i < n); i++) {
+ p++;
+ gdImageLine(im, lx, ly, p->x, p->y, c);
+ lx = p->x;
+ ly = p->y;
+ }
+}
+
+int gdCompareInt(const void *a, const void *b);
+
+void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c)
+{
+ int i;
+ int y;
+ int y1, y2;
+ int ints;
+ if (!n) {
+ return;
+ }
+ if (!im->polyAllocated) {
+ im->polyInts = (int *) malloc(sizeof(int) * n);
+ im->polyAllocated = n;
+ }
+ if (im->polyAllocated < n) {
+ while (im->polyAllocated < n) {
+ im->polyAllocated *= 2;
+ }
+ im->polyInts = (int *) realloc(im->polyInts,
+ sizeof(int) * im->polyAllocated);
+ }
+ y1 = p[0].y;
+ y2 = p[0].y;
+ for (i=1; (i < n); i++) {
+ if (p[i].y < y1) {
+ y1 = p[i].y;
+ }
+ if (p[i].y > y2) {
+ y2 = p[i].y;
+ }
+ }
+ for (y=y1; (y <= y2); y++) {
+ int interLast = 0;
+ int dirLast = 0;
+ int interFirst = 1;
+ ints = 0;
+ for (i=0; (i <= n); i++) {
+ int x1, x2;
+ int y1, y2;
+ int dir;
+ int ind1, ind2;
+ int lastInd1 = 0;
+ if ((i == n) || (!i)) {
+ ind1 = n-1;
+ ind2 = 0;
+ } else {
+ ind1 = i-1;
+ ind2 = i;
+ }
+ y1 = p[ind1].y;
+ y2 = p[ind2].y;
+ if (y1 < y2) {
+ y1 = p[ind1].y;
+ y2 = p[ind2].y;
+ x1 = p[ind1].x;
+ x2 = p[ind2].x;
+ dir = -1;
+ } else if (y1 > y2) {
+ y2 = p[ind1].y;
+ y1 = p[ind2].y;
+ x2 = p[ind1].x;
+ x1 = p[ind2].x;
+ dir = 1;
+ } else {
+ /* Horizontal; just draw it */
+ gdImageLine(im,
+ p[ind1].x, y1,
+ p[ind2].x, y1,
+ c);
+ continue;
+ }
+ if ((y >= y1) && (y <= y2)) {
+ int inter =
+ (y-y1) * (x2-x1) / (y2-y1) + x1;
+ /* Only count intersections once
+ except at maxima and minima. Also,
+ if two consecutive intersections are
+ endpoints of the same horizontal line
+ that is not at a maxima or minima,
+ discard the leftmost of the two. */
+ if (!interFirst) {
+ if ((p[ind1].y == p[lastInd1].y) &&
+ (p[ind1].x != p[lastInd1].x)) {
+ if (dir == dirLast) {
+ if (inter > interLast) {
+ /* Replace the old one */
+ im->polyInts[ints] = inter;
+ } else {
+ /* Discard this one */
+ }
+ continue;
+ }
+ }
+ if (inter == interLast) {
+ if (dir == dirLast) {
+ continue;
+ }
+ }
+ }
+ if (i > 0) {
+ im->polyInts[ints++] = inter;
+ }
+ lastInd1 = i;
+ dirLast = dir;
+ interLast = inter;
+ interFirst = 0;
+ }
+ }
+ qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
+ for (i=0; (i < (ints-1)); i+=2) {
+ gdImageLine(im, im->polyInts[i], y,
+ im->polyInts[i+1], y, c);
+ }
+ }
+}
+
+int gdCompareInt(const void *a, const void *b)
+{
+ return (*(const int *)a) - (*(const int *)b);
+}
+
+void gdImageSetStyle(gdImagePtr im, int *style, int noOfPixels)
+{
+ if (im->style) {
+ free(im->style);
+ }
+ im->style = (int *)
+ malloc(sizeof(int) * noOfPixels);
+ memcpy(im->style, style, sizeof(int) * noOfPixels);
+ im->styleLength = noOfPixels;
+ im->stylePos = 0;
+}
+
+void gdImageSetBrush(gdImagePtr im, gdImagePtr brush)
+{
+ int i;
+ im->brush = brush;
+ for (i=0; (i < gdImageColorsTotal(brush)); i++) {
+ int index;
+ index = gdImageColorExact(im,
+ gdImageRed(brush, i),
+ gdImageGreen(brush, i),
+ gdImageBlue(brush, i));
+ if (index == (-1)) {
+ index = gdImageColorAllocate(im,
+ gdImageRed(brush, i),
+ gdImageGreen(brush, i),
+ gdImageBlue(brush, i));
+ if (index == (-1)) {
+ index = gdImageColorClosest(im,
+ gdImageRed(brush, i),
+ gdImageGreen(brush, i),
+ gdImageBlue(brush, i));
+ }
+ }
+ im->brushColorMap[i] = index;
+ }
+}
+
+void gdImageSetTile(gdImagePtr im, gdImagePtr tile)
+{
+ int i;
+ im->tile = tile;
+ for (i=0; (i < gdImageColorsTotal(tile)); i++) {
+ int index;
+ index = gdImageColorExact(im,
+ gdImageRed(tile, i),
+ gdImageGreen(tile, i),
+ gdImageBlue(tile, i));
+ if (index == (-1)) {
+ index = gdImageColorAllocate(im,
+ gdImageRed(tile, i),
+ gdImageGreen(tile, i),
+ gdImageBlue(tile, i));
+ if (index == (-1)) {
+ index = gdImageColorClosest(im,
+ gdImageRed(tile, i),
+ gdImageGreen(tile, i),
+ gdImageBlue(tile, i));
+ }
+ }
+ im->tileColorMap[i] = index;
+ }
+}
+
+void gdImageInterlace(gdImagePtr im, int interlaceArg)
+{
+ im->interlace = interlaceArg;
+}
+
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontg.h
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontg.h (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontg.h Sat Jul 13 18:46:22 2002
@@ -0,0 +1,14 @@
+#ifndef GDFONTG_H
+#define GDFONTG_H 1
+
+/* gdfontg.h: brings in the largest of the provided fonts.
+ Also link with gdfontg.c. */
+
+#include "gd.h"
+
+/* 9x15B font derived from a public domain font in the X
+ distribution. Contains the 127 standard ascii characters. */
+
+extern gdFontPtr gdFontGiant;
+
+#endif
Added: trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontl.c
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontl.c (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/gd1.2/gdfontl.c Sat Jul 13 18:46:22 2002
@@ -0,0 +1,1645 @@
+#include "gdfontl.h"
+
+char gdFontLargeData[] = {
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+
+ 0,1,1,0,1,1,0,0,
+ 0,1,1,0,1,1,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,1,0,
+ 0,0,0,1,0,0,1,0,
+ 0,0,0,1,0,0,1,0,
+ 0,1,1,1,1,1,1,1,
+ 0,0,1,0,0,1,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,1,0,0,1,0,0,
+ 1,1,1,1,1,1,1,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,1,0,1,0,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,1,1,0,
+ 1,0,0,1,0,0,0,0,
+ 0,1,0,1,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,1,0,1,0,0,
+ 0,0,0,1,0,0,1,0,
+ 1,1,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,1,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+
+ 0,0,0,0,0,0,1,0,
+ 0,1,1,0,0,0,1,0,
+ 1,0,0,1,0,1,0,0,
+ 1,0,0,1,0,1,0,0,
+ 1,0,0,1,0,1,0,0,
+ 1,0,0,1,1,0,0,0,
+ 0,1,1,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,1,1,0,0,
+ 0,0,1,1,0,0,1,0,
+ 0,1,0,1,0,0,1,0,
+ 0,1,0,1,0,0,1,0,
+ 0,1,0,1,0,0,1,0,
+ 1,0,0,0,1,1,0,0,
+ 1,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,0,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,1,1,1,0,
+ 0,1,0,1,0,1,0,0,
+ 0,1,0,1,0,1,0,0,
+ 1,0,0,1,0,1,0,0,
+ 1,0,0,0,1,0,0,0,
+ 1,0,0,0,1,1,0,0,
+ 0,1,1,1,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 1,1,1,0,0,0,0,0,
+ 1,1,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 1,1,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,0,1,0,
+
+ 1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 1,0,0,1,0,0,1,0,
+ 1,1,0,1,0,1,1,0,
+ 0,0,1,1,1,0,0,0,
+ 1,1,0,1,0,1,1,0,
+ 1,0,0,1,0,0,1,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,0,0,0,0,0,
+ 1,1,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 1,1,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 1,1,1,0,0,0,0,0,
+ 1,1,1,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,1,1,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,1,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,1,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 1,0,0,0,1,0,0,0,
+ 1,0,0,0,1,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,1,1,1,0,0,0,
+ 1,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 1,1,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,1,1,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,1,1,1,0,0,0,
+ 1,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,1,0,
+ 0,0,1,1,1,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,1,0,0,0,0,
+
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,0,1,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,1,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,1,1,0,1,0,
+ 1,0,1,0,0,1,1,0,
+ 1,0,1,0,0,0,1,0,
+ 1,0,1,0,0,0,1,0,
+ 1,0,1,0,0,0,1,0,
+ 1,0,1,0,0,1,1,0,
+ 1,0,0,1,1,0,1,0,
+ 1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,1,1,1,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,1,0,0,0,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 1,1,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,1,0,
+ 0,1,0,0,0,1,1,0,
+ 0,1,0,0,0,0,1,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,1,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 1,1,1,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,1,0,1,0,
+ 0,0,1,0,0,1,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,1,1,1,1,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,1,0,0,1,1,0,
+ 0,0,0,1,1,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,0,0,1,1,1,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,1,1,1,1,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 1,1,1,0,0,1,1,1,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,1,1,1,1,1,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,0,0,1,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,1,1,0,0,0,0,
+ 0,1,0,1,0,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 1,1,1,0,0,0,1,1,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,1,0,0,0,1,1,0,
+ 1,0,1,0,1,0,1,0,
+ 1,0,1,0,1,0,1,0,
+ 1,0,1,0,1,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,1,0,0,0,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,0,0,0,0,1,1,1,
+ 1,1,0,0,0,0,1,0,
+ 1,0,1,0,0,0,1,0,
+ 1,0,1,0,0,0,1,0,
+ 1,0,1,0,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,0,1,0,1,0,
+ 1,0,0,0,1,0,1,0,
+ 1,0,0,0,1,0,1,0,
+ 1,0,0,0,0,1,1,0,
+ 1,1,0,0,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 1,1,1,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,1,1,1,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,1,1,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 1,1,1,0,0,0,1,1,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,0,1,0,0,
+ 0,1,0,0,1,1,0,0,
+ 1,0,0,0,0,1,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 0,1,1,0,0,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,1,0,0,0,1,0,0,
+ 1,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,0,0,1,1,1,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,0,0,0,1,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,0,0,0,1,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,1,0,1,0,1,0,
+ 1,0,1,0,1,0,1,0,
+ 1,0,1,0,1,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,0,1,1,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,1,0,0,0,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,0,0,0,1,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 1,0,0,0,0,1,0,0,
+ 1,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,1,1,1,1,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,1,1,1,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+
+ 1,1,1,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 1,1,1,1,0,0,0,0,
+
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+
+ 0,0,1,1,0,0,0,0,
+ 0,0,1,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,1,1,1,1,1,0,
+ 0,1,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,1,1,0,
+ 0,1,1,1,1,0,1,1,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,1,0,
+ 0,1,0,0,0,1,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,1,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,1,0,0,
+ 1,0,0,0,0,1,0,0,
+ 1,0,0,0,0,1,0,0,
+ 1,0,0,0,0,1,0,0,
+ 1,0,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,1,1,1,1,1,1,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,1,1,0,
+ 0,0,0,1,0,0,0,1,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,1,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,1,1,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,1,1,1,0,0,0,
+ 1,0,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,1,1,1,1,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,1,1,1,0,0,
+ 0,1,1,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 1,1,1,0,0,1,1,1,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 1,1,1,1,1,1,1,1,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,1,1,0,
+ 0,0,0,0,0,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 1,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,1,0,0,0,
+ 0,1,0,1,1,0,0,0,
+ 0,1,1,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 1,1,1,0,0,0,1,1,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 1,1,1,1,1,1,1,1,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,0,1,1,0,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,1,0,1,1,0,1,1,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,0,1,1,1,0,0,
+ 0,1,1,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 1,1,1,0,0,1,1,1,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,1,1,1,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+ 1,1,1,1,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,1,1,0,
+ 0,1,0,0,0,1,0,0,
+ 1,0,0,0,0,1,0,0,
+ 1,0,0,0,0,1,0,0,
+ 1,0,0,0,0,1,0,0,
+ 1,0,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,0,0,1,0,0,
+ 0,0,0,1,1,1,1,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,0,1,1,0,0,
+ 0,0,1,1,0,0,1,0,
+ 0,0,1,0,0,0,1,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 1,1,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,1,1,0,1,0,
+ 0,1,0,0,0,1,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,0,0,
+ 0,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,1,0,0,0,0,1,0,
+ 1,0,1,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 1,1,1,1,1,1,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,1,0,
+ 0,0,1,0,0,0,1,0,
+ 0,0,0,1,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,0,0,0,1,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 0,1,0,0,0,1,1,0,
+ 0,0,1,1,1,0,0,1,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,0,0,0,1,1,0,
+ 1,0,0,0,0,0,1,0,
+ 1,0,0,0,0,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,0,1,0,0,1,0,
+ 1,0,1,0,1,0,1,0,
+ 1,0,1,0,1,0,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,0,1,1,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,0,1,0,1,0,0,0,
+ 0,1,0,0,0,1,0,0,
+ 1,1,1,0,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 1,1,1,0,0,1,1,1,
+ 0,1,0,0,0,0,1,0,
+ 0,0,1,0,0,0,1,0,
+ 0,0,1,0,0,1,0,0,
+ 0,0,0,1,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 1,0,0,1,0,0,0,0,
+ 1,0,1,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,1,1,1,1,1,1,0,
+ 0,1,0,0,0,1,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,1,0,
+ 0,1,0,0,0,0,1,0,
+ 1,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,1,1,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,1,1,0,
+
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+
+ 1,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,0,0,1,0,0,0,
+ 0,0,0,1,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,
+ 1,1,0,0,0,0,0,0,
+
+ 0,1,1,0,0,0,0,0,
+ 1,0,0,1,0,0,1,0,
+ 0,0,0,0,1,1,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0
+};
+
+gdFont gdFontLargeRep = {
+ 96,
+ 32,
+ 8,
+ 16,
+ gdFontLargeData
+};
+
+gdFontPtr gdFontLarge = &gdFontLargeRep;
Added: trunk/orca/packages/rrdtool-0.99.29.1/install-sh
==============================================================================
--- trunk/orca/packages/rrdtool-0.99.29.1/install-sh (original)
+++ trunk/orca/packages/rrdtool-0.99.29.1/install-sh Sat Jul 13 18:46:23 2002
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# 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. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# 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 $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
Added: trunk/orca/packages/Math-Interpolate-1.02/t/02interp.t
==============================================================================
--- trunk/orca/packages/Math-Interpolate-1.02/t/02interp.t (original)
+++ trunk/orca/packages/Math-Interpolate-1.02/t/02interp.t Sat Jul 13 18:46:23 2002
@@ -0,0 +1,2137 @@
+# Before `make' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+use strict;
+use vars qw($loaded);
+
+BEGIN { $| = 1; print "1..10032\n"; }
+END {print "not ok 1\n" unless $loaded; }
+
+my $ok_count = 1;
+sub ok {
+ my $ok = shift;
+ $ok or print "not ";
+ print "ok $ok_count\n";
+ ++$ok_count;
+ $ok;
+}
+
+use Math::Interpolate qw(derivatives constant_interpolate
+ linear_interpolate robust_interpolate);
+
+# If we got here, then the package being tested was loaded.
+$loaded = 1;
+ok(1); # 1
+
+# Open the data filehandle for the answers.
+no strict 'refs';
+my $data_fh = \*{"::DATA"};
+use strict;
+
+sub Compare {
+ my ($a, $b) = @_;
+ if ($a == 0) {
+ return $a == $b;
+ }
+ abs(($a - $b)/$a) <= 1.0e-6;
+}
+
+# Check the derivates from two points.
+my @dy = derivatives([1, 2], [10, 20]);
+ok( $dy[0] == 10 ); # 2
+ok( $dy[1] == 10 ); # 3
+
+# Check the derivative generating code.
+my @x = ( 5, 7, 8, 12, 15);
+my @y = (-10, -9, 10, 10, 12);
+ at dy = derivatives(\@x, \@y);
+foreach my $result_dy ( @dy ) {
+ my $answer_dy = <$data_fh>;
+ ok( Compare($result_dy, $answer_dy) ); # 4-8
+}
+
+# Skip a line in __DATA__.
+<$data_fh>;
+
+# Calculate the derivates for a reversed @y.
+ at dy = derivatives(\@x, [reverse @y]);
+foreach my $result_dy ( @dy ) {
+ my $answer_dy = <$data_fh>;
+ ok( Compare($result_dy, $answer_dy) ); # 9-13
+}
+
+# Skip one line in __DATA__
+<$data_fh>;
+
+# Check the extrapolation code.
+ok( linear_interpolate(1, [2, 3], [10, 15]) == 5 ); # 14
+
+# Check the constant interpolation code.
+ok( constant_interpolate(0, \@x, \@y) == -10 ); # 15
+ok( constant_interpolate(6, \@x, \@y) == -10 ); # 16
+ok( constant_interpolate(7, \@x, \@y) == -9 ); # 17
+ok( constant_interpolate(7.5, \@x, \@y) == -9 ); # 18
+ok( constant_interpolate(8, \@x, \@y) == 10 ); # 19
+ok( constant_interpolate(12, \@x, \@y) == 10 ); # 20
+ok( constant_interpolate(15, \@x, \@y) == 12 ); # 21
+ok( constant_interpolate(99, \@x, \@y) == 12 ); # 22
+
+# Set the derivates to some odd values and calulate the resulting
+# interpolated curve.
+ at dy = (-2, 2, -2, 2, -2);
+
+# Calculate the linear and robust interpolated curve letting the
+# robust_interpolate calculate the derivatives.
+my $i = 0;
+while (1) {
+ my $x = $x[0] + 0.01*($i++);
+ last unless $x <= $x[-1];
+ my ($l_y, $l_dy) = linear_interpolate($x, \@x, \@y);
+ my ($r_y, $r_dy) = robust_interpolate($x, \@x, \@y);
+# print "$x\t$l_y\t$l_dy\t$r_y\t$r_dy\n";
+ my @answers = split ' ', <$data_fh>;
+ ok( Compare($x, $answers[0]) );
+ ok( Compare($l_y, $answers[1]) );
+ ok( Compare($l_dy, $answers[2]) );
+ ok( Compare($r_y, $answers[3]) );
+ ok( Compare($r_dy, $answers[4]) );
+}
+
+# Skip one line in __DATA__
+<$data_fh>;
+
+# Calculate the linear and robust interpolated curve using the derivates
+# we set ourselves.
+$i = 0;
+while (1) {
+ my $x = $x[0] + 0.01*($i++);
+ last unless $x <= $x[-1];
+ my ($l_y, $l_dy) = linear_interpolate($x, \@x, \@y);
+ my ($r_y, $r_dy) = robust_interpolate($x, \@x, \@y, \@dy);
+# print "$x\t$l_y\t$l_dy\t$r_y\t$r_dy\n";
+ my @answers = split ' ', <$data_fh>;
+ ok( Compare($x, $answers[0]) );
+ ok( Compare($l_y, $answers[1]) );
+ ok( Compare($l_dy, $answers[2]) );
+ ok( Compare($r_y, $answers[3]) );
+ ok( Compare($r_dy, $answers[4]) );
+}
+
+exit 0;
+
+__DATA__
+0.398796498905908
+0.626886145404664
+0.207650273224044
+0.32
+1.01333333333333
+
+-1.8
+-0.2
+-0.0498687664041995
+-0.484201537147737
+-0.229472859102489
+
+5 -10 0.5 -10 0.5
+5.01 -9.995 0.5 -9.99600799496208 0.399604917959649
+5.02 -9.99 0.5 -9.99200789343858 0.40041579768342
+5.03 -9.985 0.5 -9.98799967077286 0.401229148073759
+5.04 -9.98 0.5 -9.98398330220806 0.402044979178022
+5.05 -9.975 0.5 -9.9799587628866 0.402863301094697
+5.06 -9.97 0.5 -9.97592602784963 0.4036841239737
+5.07 -9.965 0.5 -9.97188507203658 0.404507458016712
+5.08 -9.96 0.5 -9.96783587028458 0.405333313477472
+5.09 -9.955 0.5 -9.96377839732796 0.406161700662117
+5.1 -9.95 0.5 -9.95971262779774 0.406992629929495
+5.11 -9.945 0.5 -9.95563853622106 0.40782611169148
+5.12 -9.94 0.5 -9.95155609702071 0.408662156413317
+5.13 -9.935 0.5 -9.94746528451454 0.409500774613936
+5.14 -9.93 0.5 -9.94336607291493 0.410341976866288
+5.15 -9.925 0.5 -9.93925843632829 0.411185773797675
+5.16 -9.92 0.5 -9.93514234875445 0.412032176090095
+5.17 -9.915 0.5 -9.93101778408617 0.412881194480565
+5.18 -9.91 0.5 -9.92688471610854 0.413732839761476
+5.19 -9.905 0.5 -9.92274311849848 0.414587122780925
+5.2 -9.9 0.5 -9.91859296482412 0.415444054443069
+5.21 -9.895 0.5 -9.91443422854428 0.41630364570847
+5.22 -9.89 0.5 -9.91026688300789 0.417165907594438
+5.23 -9.885 0.5 -9.90609090145341 0.4180308511754
+5.24 -9.88 0.5 -9.9019062570083 0.41889848758324
+5.25 -9.875 0.5 -9.89771292268837 0.419768828007662
+5.26 -9.87 0.5 -9.89351087139727 0.420641883696559
+5.27 -9.865 0.5 -9.88930007592587 0.421517665956364
+5.28 -9.86 0.5 -9.88508050895169 0.422396186152424
+5.29 -9.855 0.5 -9.8808521430383 0.423277455709367
+5.3 -9.85 0.5 -9.8766149506347 0.424161486111471
+5.31 -9.845 0.5 -9.87236890407477 0.425048288903038
+5.32 -9.84 0.5 -9.86811397557666 0.425937875688782
+5.33 -9.835 0.5 -9.86385013724214 0.426830258134188
+5.34 -9.83 0.5 -9.85957736105603 0.427725447965914
+5.35 -9.825 0.5 -9.85529561888558 0.428623456972164
+5.36 -9.82 0.5 -9.85100488247985 0.429524297003081
+5.37 -9.815 0.5 -9.84670512346907 0.430427979971142
+5.38 -9.81 0.5 -9.84239631336406 0.431334517851538
+5.39 -9.805 0.5 -9.83807842355554 0.432243922682589
+5.4 -9.8 0.5 -9.83375142531357 0.433156206566129
+5.41 -9.795 0.5 -9.82941528978683 0.434071381667914
+5.42 -9.79 0.5 -9.82506998800206 0.434989460218031
+5.43 -9.785 0.5 -9.82071549086334 0.4359104545113
+5.44 -9.78 0.5 -9.81635176915149 0.436834376907692
+5.45 -9.775 0.5 -9.81197879352343 0.437761239832736
+5.46 -9.77 0.5 -9.80759653451145 0.438691055777947
+5.47 -9.765 0.5 -9.80320496252262 0.439623837301235
+5.48 -9.76 0.5 -9.79880404783809 0.440559597027343
+5.49 -9.755 0.5 -9.79439376061243 0.441498347648259
+5.5 -9.75 0.5 -9.78997407087295 0.442440101923655
+5.51 -9.745 0.5 -9.78554494851902 0.443384872681326
+5.52 -9.74 0.5 -9.7811063633214 0.444332672817612
+5.53 -9.735 0.5 -9.77665828492153 0.445283515297851
+5.54 -9.73 0.5 -9.77220068283085 0.446237413156815
+5.55 -9.725 0.5 -9.76773352643012 0.447194379499161
+5.56 -9.72 0.5 -9.76325678496868 0.44815442749988
+5.57 -9.715 0.5 -9.75877042756379 0.449117570404749
+5.58 -9.71 0.5 -9.75427442319986 0.450083821530787
+5.59 -9.705 0.5 -9.74976874072781 0.451053194266722
+5.6 -9.7 0.5 -9.7452533488643 0.452025702073445
+5.61 -9.695 0.5 -9.740728216191 0.453001358484484
+5.62 -9.69 0.5 -9.73619331115391 0.453980177106477
+5.63 -9.685 0.5 -9.73164860206258 0.454962171619634
+5.64 -9.68 0.5 -9.72709405708938 0.455947355778233
+5.65 -9.675 0.5 -9.72252964426877 0.456935743411083
+5.66 -9.67 0.5 -9.71795533149657 0.457927348422026
+5.67 -9.665 0.5 -9.71337108652915 0.458922184790416
+5.68 -9.66 0.5 -9.70877687698273 0.459920266571611
+5.69 -9.655 0.5 -9.70417267033258 0.460921607897476
+5.7 -9.65 0.5 -9.69955843391228 0.461926222976879
+5.71 -9.645 0.5 -9.69493413491292 0.462934126096195
+5.72 -9.64 0.5 -9.69029974038235 0.463945331619818
+5.73 -9.635 0.5 -9.68565521722437 0.464959853990662
+5.74 -9.63 0.5 -9.68100053219798 0.465977707730693
+5.75 -9.625 0.5 -9.67633565191653 0.466998907441434
+5.76 -9.62 0.5 -9.67166054284698 0.468023467804496
+5.77 -9.615 0.5 -9.66697517130907 0.469051403582108
+5.78 -9.61 0.5 -9.66227950347449 0.47008272961764
+5.79 -9.605 0.5 -9.65757350536611 0.471117460836144
+5.8 -9.6 0.5 -9.65285714285714 0.472155612244897
+5.81 -9.595 0.5 -9.64813038167029 0.473197198933944
+5.82 -9.59 0.5 -9.64339318737696 0.474242236076634
+5.83 -9.585 0.5 -9.6386455253964 0.475290738930196
+5.84 -9.58 0.5 -9.63388736099486 0.476342722836274
+5.85 -9.575 0.5 -9.62911865928475 0.477398203221499
+5.86 -9.57 0.5 -9.6243393852238 0.478457195598057
+5.87 -9.565 0.5 -9.61954950361417 0.479519715564248
+5.88 -9.56 0.5 -9.61474897910161 0.480585778805069
+5.89 -9.555 0.5 -9.60993777617459 0.481655401092796
+5.9 -9.55 0.5 -9.60511585916341 0.482728598287553
+5.91 -9.545 0.5 -9.60028319223933 0.483805386337917
+5.92 -9.54 0.5 -9.59543973941368 0.484885781281499
+5.93 -9.535 0.5 -9.59058546453697 0.485969799245545
+5.94 -9.53 0.5 -9.58572033129799 0.487057456447538
+5.95 -9.525 0.5 -9.58084430322288 0.488148769195805
+5.96 -9.52 0.5 -9.57595734367426 0.489243753890125
+5.97 -9.515 0.5 -9.57105941585029 0.490342427022351
+5.98 -9.51 0.5 -9.56615048278375 0.491444805177024
+5.99 -9.505 0.5 -9.56123050734109 0.492550905032007
+6 -9.5 0.5 -9.55629945222155 0.493660743359108
+6.01 -9.495 0.5 -9.55135727995613 0.494774337024718
+6.02 -9.49 0.5 -9.54640395290673 0.495891702990457
+6.03 -9.485 0.5 -9.54143943326514 0.497012858313811
+6.04 -9.48 0.5 -9.53646368305209 0.498137820148792
+6.05 -9.475 0.5 -9.5314766641163 0.499266605746587
+6.06 -9.47 0.5 -9.52647833813346 0.500399232456223
+6.07 -9.465 0.5 -9.52146866660532 0.501535717725233
+6.08 -9.46 0.5 -9.51644761085862 0.502676079100329
+6.09 -9.455 0.5 -9.51141513204415 0.503820334228076
+6.1 -9.45 0.5 -9.50637119113573 0.50496850085558
+6.11 -9.445 0.5 -9.50131574892922 0.506120596831168
+6.12 -9.44 0.5 -9.49624876604146 0.50727664010509
+6.13 -9.435 0.5 -9.49117020290929 0.508436648730215
+6.14 -9.43 0.5 -9.48608001978851 0.509600640862733
+6.15 -9.425 0.5 -9.48097817675282 0.510768634762871
+6.16 -9.42 0.5 -9.47586463369282 0.511940648795605
+6.17 -9.415 0.5 -9.47073935031491 0.51311670143138
+6.18 -9.41 0.5 -9.46560228614027 0.514296811246846
+6.19 -9.405 0.5 -9.46045340050378 0.515480996925584
+6.2 -9.4 0.5 -9.45529265255293 0.516669277258847
+6.21 -9.395 0.5 -9.45012000124677 0.517861671146306
+6.22 -9.39 0.5 -9.4449354053548 0.519058197596805
+6.23 -9.385 0.5 -9.4397388234559 0.520258875729113
+6.24 -9.38 0.5 -9.43453021393719 0.521463724772688
+6.25 -9.375 0.5 -9.42930953499295 0.522672764068454
+6.26 -9.37 0.5 -9.42407674462349 0.523886013069568
+6.27 -9.365 0.5 -9.418831800634 0.525103491342211
+6.28 -9.36 0.5 -9.41357466063348 0.526325218566369
+6.29 -9.355 0.5 -9.40830528203354 0.527551214536632
+6.3 -9.35 0.5 -9.40302362204724 0.528781499162998
+6.31 -9.345 0.5 -9.39772963768801 0.530016092471678
+6.32 -9.34 0.5 -9.39242328576841 0.531255014605913
+6.33 -9.335 0.5 -9.38710452289895 0.532498285826793
+6.34 -9.33 0.5 -9.38177330548699 0.533745926514085
+6.35 -9.325 0.5 -9.37642958973547 0.534997957167077
+6.36 -9.32 0.5 -9.37107333164172 0.536254398405406
+6.37 -9.315 0.5 -9.36570448699628 0.53751527096992
+6.38 -9.31 0.5 -9.3603230113817 0.538780595723524
+6.39 -9.305 0.5 -9.35492886017125 0.540050393652048
+6.4 -9.3 0.5 -9.34952198852772 0.541324685865118
+6.41 -9.295 0.5 -9.34410235140223 0.542603493597031
+6.42 -9.29 0.5 -9.33866990353287 0.54388683820764
+6.43 -9.285 0.5 -9.33322459944354 0.545174741183246
+6.44 -9.28 0.5 -9.32776639344262 0.546467224137497
+6.45 -9.275 0.5 -9.32229523962173 0.547764308812296
+6.46 -9.27 0.5 -9.31681109185442 0.549066017078716
+6.47 -9.265 0.5 -9.31131390379486 0.55037237093792
+6.48 -9.26 0.5 -9.30580362887659 0.551683392522089
+6.49 -9.255 0.5 -9.30028022031114 0.552999104095364
+6.5 -9.25 0.5 -9.29474363108675 0.55431952805479
+6.51 -9.245 0.5 -9.289193813967 0.555644686931266
+6.52 -9.24 0.5 -9.28363072148953 0.556974603390508
+6.53 -9.235 0.5 -9.27805430596459 0.55830930023402
+6.54 -9.23 0.5 -9.27246451947379 0.559648800400071
+6.55 -9.225 0.5 -9.26686131386861 0.560993126964675
+6.56 -9.22 0.5 -9.26124464076913 0.562342303142595
+6.57 -9.215 0.5 -9.25561445156255 0.563696352288334
+6.58 -9.21 0.5 -9.24997069740184 0.565055297897155
+6.59 -9.205 0.5 -9.24431332920429 0.566419163606093
+6.6 -9.2 0.5 -9.23864229765013 0.56778797319499
+6.61 -9.195 0.5 -9.23295755318106 0.569161750587527
+6.62 -9.19 0.5 -9.22725904599882 0.570540519852266
+6.63 -9.185 0.5 -9.22154672606374 0.571924305203713
+6.64 -9.18 0.5 -9.21582054309327 0.573313131003374
+6.65 -9.175 0.5 -9.2100804465605 0.574707021760834
+6.66 -9.17 0.5 -9.20432638569268 0.576106002134824
+6.67 -9.165 0.5 -9.19855830946973 0.577510096934333
+6.68 -9.16 0.5 -9.19277616662273 0.578919331119691
+6.69 -9.155 0.5 -9.18697990563236 0.580333729803684
+6.7 -9.15 0.5 -9.18116947472745 0.581753318252674
+6.71 -9.145 0.5 -9.17534482188337 0.583178121887723
+6.72 -9.14 0.5 -9.16950589482051 0.584608166285738
+6.73 -9.135 0.5 -9.16365264100269 0.586043477180611
+6.74 -9.13 0.5 -9.15778500763561 0.587484080464386
+6.75 -9.125 0.5 -9.15190294166528 0.588930002188415
+6.76 -9.12 0.5 -9.14600638977636 0.590381268564547
+6.77 -9.115 0.5 -9.14009529839059 0.591837905966306
+6.78 -9.11 0.5 -9.13416961366518 0.5932999409301
+6.79 -9.105 0.5 -9.12822928149113 0.594767400156424
+6.8 -9.1 0.5 -9.12227424749164 0.596240310511068
+6.81 -9.095 0.5 -9.11630445702039 0.597718699026371
+6.82 -9.09 0.5 -9.11031985515993 0.599202592902443
+6.83 -9.085 0.5 -9.10432038671993 0.600692019508418
+6.84 -9.08 0.5 -9.09830599623555 0.602187006383722
+6.85 -9.075 0.5 -9.09227662796567 0.60368758123934
+6.86 -9.07 0.5 -9.08623222589123 0.605193771959109
+6.87 -9.065 0.5 -9.08017273371344 0.606705606601
+6.88 -9.06 0.5 -9.07409809485205 0.60822311339844
+6.89 -9.055 0.5 -9.0680082524436 0.609746320761615
+6.9 -9.05 0.5 -9.06190314933965 0.611275257278812
+6.91 -9.045 0.5 -9.05578272810497 0.61280995171775
+6.92 -9.04 0.5 -9.04964693101575 0.614350433026944
+6.93 -9.035 0.5 -9.04349570005779 0.615896730337067
+6.94 -9.03 0.5 -9.03732897692465 0.617448872962319
+6.95 -9.025 0.5 -9.03114670301585 0.619006890401819
+6.96 -9.02 0.5 -9.02494881943497 0.62057081234102
+6.97 -9.015 0.5 -9.0187352669878 0.622140668653108
+6.98 -9.01 0.5 -9.01250598618047 0.623716489400433
+6.99 -9.005 0.5 -9.00626091721752 0.625298304835947
+7 -9 19 -9 19
+7.01 -8.81 19 -8.98829572635871 1.71041442503272
+7.02 -8.62000000000001 19 -8.96586282638561 2.77260823807361
+7.03 -8.43 19 -8.93291473999276 3.8134485317473
+7.04 -8.24 19 -8.88966509772637 4.83291623199987
+7.05 -8.05 19 -8.83632772097965 5.83099224347547
+7.06 -7.85999999999999 19 -8.77311662220603 6.80765744948759
+7.07 -7.66999999999999 19 -8.70024600513255 7.76289271199009
+7.08 -7.48 19 -8.61793026497366 8.6966788715492
+7.09 -7.29 19 -8.52638398864517 9.60899674731436
+7.1 -7.10000000000001 19 -8.42582195497862 10.4998271369897
+7.11 -6.91000000000001 19 -8.31645913493586 11.3691508168051
+7.12 -6.72 19 -8.1985106918239 12.2169485414876
+7.13 -6.53 19 -8.07219198151016 13.0432010442322
+7.14 -6.33999999999999 19 -7.93771855263786 13.8478890366733
+7.15 -6.14999999999999 19 -7.79530614684182 14.6309932088554
+7.16 -5.96 19 -7.64517069896446 15.3924942292045
+7.17 -5.77 19 -7.48752833727218 16.1323727444987
+7.18 -5.58000000000001 19 -7.32259538367193 16.8506093798391
+7.19 -5.39000000000001 19 -7.15058835392818 17.5471847386211
+7.2 -5.2 19 -6.97172395788008 18.2220794025045
+7.21 -5.01 19 -6.78621909965901 18.8752739313849
+7.22 -4.81999999999999 19 -6.59429087790628 19.5067488633643
+7.23 -4.62999999999999 19 -6.39615658599136 20.1164847147213
+7.24 -4.44 19 -6.19203371223009 20.7044619798823
+7.25 -4.25 19 -5.98213994010346 21.2706611313918
+7.26 -4.06 19 -5.76669314847655 21.8150626198832
+7.27 -3.87000000000001 19 -5.54591141181778 22.3376468740488
+7.28 -3.68 19 -5.32001300041846 22.8383943006108
+7.29 -3.49 19 -5.08921638061271 23.3172852842911
+7.3 -3.29999999999999 19 -4.85374021499748 23.7743001877824
+7.31 -3.10999999999999 19 -4.61380336265312 24.2094193517177
+7.32 -2.91999999999999 19 -4.36962487936405 24.6226230946412
+7.33 -2.73 19 -4.1214240178398 25.0138917129781
+7.34 -2.54 19 -3.8694202279364 25.3832054810051
+7.35 -2.35000000000001 19 -3.61383315687795 25.7305446508202
+7.36 -2.16000000000001 19 -3.35488264947861 26.0558894523129
+7.37 -1.97 19 -3.09278874836478 26.3592200931343
+7.38 -1.78 19 -2.82777169419773 26.6405167586669
+7.39 -1.58999999999999 19 -2.56005192589629 26.8997596119948
+7.4 -1.39999999999999 19 -2.28985008086017 27.1369287938732
+7.41 -1.21 19 -2.0173869951932 27.3520044226985
+7.42 -1.02 19 -1.7428837039272 27.5449665944782
+7.43 -0.830000000000005 19 -1.46656144124601 27.7157953828003
+7.44 -0.640000000000009 19 -1.18864164070977 27.8644708388033
+7.45 -0.449999999999996 19 -0.90934593547963 27.9909729911454
+7.46 -0.260000000000002 19 -0.628896158542725 28.0952818459748
+7.47 -0.0699999999999878 19 -0.3475143429373 28.1773773868985
+7.48 0.120000000000008 19 -0.0654227219784622 28.2372395749524
+7.49 0.310000000000004 19 0.217156270516131 28.2748483485702
+7.5 0.5 19 0.5 28.2901836235535
+7.51 0.689999999999996 19 0.782885630971388 28.2832252930402
+7.52 0.879999999999992 19 1.06559012674648 28.2539532274749
+7.53 1.07 19 1.34789024923232 28.2023472745773
+7.54 1.26 19 1.62956255869934 28.1283872593117
+7.55 1.45000000000001 19 1.9103834135538 28.0320529838564
+7.56 1.64000000000001 19 2.19012897010959 27.9133242275722
+7.57 1.83000000000001 19 2.46857518236006 27.7721807469723
+7.58 2.02 19 2.7454978017493 27.6086022756906
+7.59 2.21 19 3.02067237694321 27.4225685244508
+7.6 2.39999999999999 19 3.29387425360027 27.2140591810358
+7.61 2.58999999999999 19 3.56487857414192 26.9830539102559
+7.62 2.78 19 3.83346027752277 26.729532353918
+7.63 2.97 19 4.09939409900024 26.4534741307944
+7.64 3.16000000000001 19 4.3624545699043 26.1548588365912
+7.65 3.35000000000001 19 4.62241601740641 25.8336660439174
+7.66 3.54 19 4.87905256428858 25.489875302253
+7.67 3.73 19 5.1321381287118 25.1234661379182
+7.68 3.91999999999999 19 5.38144642398437 24.7344180540413
+7.69 4.10999999999999 19 5.62675095832975 24.3227105305276
+7.7 4.3 19 5.86782503465423 23.8883230240275
+7.71 4.49 19 6.10444175031416 23.4312349679053
+7.72 4.68000000000001 19 6.33637399688302 22.9514257722068
+7.73 4.87000000000001 19 6.56339445991797 22.4488748236286
+7.74 5.06 19 6.7852756187263 21.9235614854853
+7.75 5.25 19 7.00178974613139 21.3754650976783
+7.76 5.44 19 7.21270890823844 20.8045649766635
+7.77 5.62999999999999 19 7.41780496419984 20.2108404154197
+7.78 5.82 19 7.61684956598026 19.5942706834167
+7.79 6.01 19 7.80961415812136 18.9548350265828
+7.8 6.20000000000001 19 7.9958699775063 18.292512667273
+7.81 6.39000000000001 19 8.17538805312371 17.607282804237
+7.82 6.58000000000001 19 8.34793920583161 16.8991246125867
+7.83 6.77 19 8.51329404812083 16.1680172437642
+7.84 6.96 19 8.67122298387808 15.4139398255092
+7.85 7.14999999999999 19 8.82149620814889 14.6368714618271
+7.86 7.33999999999999 19 8.96388370689997 13.8367912329564
+7.87 7.53 19 9.0981552567815 13.0136781953359
+7.88 7.72 19 9.22408042488887 12.167511381573
+7.89 7.91000000000001 19 9.34142856852429 11.2982698004104
+7.9 8.10000000000001 19 9.4499688349579 10.4059324366938
+7.91 8.29 19 9.5494701611887 9.49047825133934
+7.92 8.48 19 9.63970127370506 8.55188618130064
+7.93 8.66999999999999 19 9.72043068824496 7.59013513953625
+7.94 8.85999999999999 19 9.79142670955581 6.60520401497679
+7.95 9.05 19 9.85245743115409 5.59707167249198
+7.96 9.24 19 9.9032907350845 4.56571695285806
+7.97 9.43000000000001 19 9.94369429167894 3.51111867272424
+7.98 9.62000000000001 19 9.97343555931498 2.4332556245804
+7.99 9.81 19 9.99228178417419 1.33210657672334
+8 10 0 10 0
+8.01 10 0 10.0020627654738 0.204904212620628
+8.02 10 0 10.0040981121231 0.202166513215011
+8.03 10 0 10.0061061237069 0.199437204453212
+8.04 10 0 10.0080868842795 0.196716315910997
+8.05 10 0 10.0100404781915 0.194003877294554
+8.06 10 0 10.0119669900913 0.191299918441194
+8.07 10 0 10.0138665049261 0.188604469320039
+8.08 10 0 10.0157391079438 0.185917560032725
+8.09 10 0 10.0175848846936 0.183239220814103
+8.1 10 0 10.0194039210282 0.180569482032951
+8.11 10 0 10.0211963031041 0.177908374192683
+8.12 10 0 10.0229621173839 0.175255927932067
+8.13 10 0 10.0247014506372 0.172612174025947
+8.14 10 0 10.026414389942 0.169977143385968
+8.15 10 0 10.028101022686 0.167350867061308
+8.16 10 0 10.0297614365682 0.164733376239409
+8.17 10 0 10.0313957196002 0.162124702246723
+8.18 10 0 10.0330039601074 0.159524876549449
+8.19 10 0 10.0345862467308 0.156933930754287
+8.2 10 0 10.036142668428 0.15435189660919
+8.21 10 0 10.0376733144748 0.15177880600412
+8.22 10 0 10.0391782744666 0.149214690971815
+8.23 10 0 10.04065763832 0.146659583688552
+8.24 10 0 10.042111496274 0.144113516474925
+8.25 10 0 10.0435399388913 0.141576521796618
+8.26 10 0 10.0449430570604 0.139048632265191
+8.27 10 0 10.0463209419963 0.136529880638858
+8.28 10 0 10.0476736852425 0.134020299823294
+8.29 10 0 10.0490013786723 0.131519922872425
+8.3 10 0 10.0503041144902 0.129028782989221
+8.31 10 0 10.0515819852335 0.126546913526522
+8.32 10 0 10.0528350837738 0.124074347987833
+8.33 10 0 10.0540635033185 0.121611120028153
+8.34 10 0 10.0552673374123 0.119157263454792
+8.35 10 0 10.0564466799387 0.116712812228201
+8.36 10 0 10.0576016251217 0.114277800462804
+8.37 10 0 10.058732267527 0.111852262427838
+8.38 10 0 10.0598387020641 0.109436232548198
+8.39 10 0 10.0609210239871 0.107029745405279
+8.4 10 0 10.0619793288971 0.104632835737841
+8.41 10 0 10.0630137127431 0.102245538442861
+8.42 10 0 10.064024271824 0.0998678885764025
+8.43 10 0 10.0650111027901 0.0974999213544854
+8.44 10 0 10.0659743026445 0.0951416721539625
+8.45 10 0 10.066913968745 0.0927931765134019
+8.46 10 0 10.0678301988056 0.0904544701339747
+8.47 10 0 10.0687230908981 0.0881255888803498
+8.48 10 0 10.0695927434537 0.0858065687815914
+8.49 10 0 10.0704392552649 0.0834974460320651
+8.5 10 0 10.0712627254867 0.0811982569923489
+8.51 10 0 10.0720632536388 0.0789090381901494
+8.52 10 0 10.0728409396069 0.0766298263212254
+8.53 10 0 10.0735958836445 0.0743606582503152
+8.54 10 0 10.0743281863747 0.072101571012073
+8.55 10 0 10.0750379487916 0.0698526018120074
+8.56 10 0 10.0757252722623 0.0676137880274305
+8.57 10 0 10.0763902585286 0.0653851672084085
+8.58 10 0 10.0770330097087 0.0631667770787226
+8.59 10 0 10.0776536282988 0.060958655536833
+8.6 10 0 10.078252217175 0.058760840656851
+8.61 10 0 10.078828879595 0.0565733706895169
+8.62 10 0 10.0793837191999 0.0543962840631837
+8.63 10 0 10.0799168400161 0.0522296193848085
+8.64 10 0 10.0804283464567 0.0500734154409483
+8.65 10 0 10.0809183433239 0.047927711198765
+8.66 10 0 10.0813869358101 0.0457925458070344
+8.67 10 0 10.0818342295006 0.0436679585971634
+8.68 10 0 10.0822603303744 0.0415539890842131
+8.69 10 0 10.0826653448069 0.0394506769679289
+8.7 10 0 10.0830493795713 0.0373580621337774
+8.71 10 0 10.0834125418407 0.0352761846539897
+8.72 10 0 10.0837549391898 0.0332050847886124
+8.73 10 0 10.0840766795967 0.0311448029865642
+8.74 10 0 10.0843778714452 0.0290953798867004
+8.75 10 0 10.0846586235262 0.0270568563188844
+8.76 10 0 10.08491904504 0.0250292733050659
+8.77 10 0 10.0851592455982 0.0230126720603673
+8.78 10 0 10.0853793352251 0.0210070939941711
+8.79 10 0 10.0855794243606 0.0190125807112316
+8.8 10 0 10.0857596238613 0.0170291740127653
+8.81 10 0 10.0859200450028 0.0150569158975823
+8.82 10 0 10.0860607994818 0.0130958485631967
+8.83 10 0 10.086181999418 0.0111460144069571
+8.84 10 0 10.0862837573559 0.00920745602718892
+8.85 10 0 10.0863661862671 0.00728021622433391
+8.86 10 0 10.0864293995523 0.00536433800210349
+8.87 10 0 10.0864735110431 0.00345986456863818
+8.88 10 0 10.0864986350043 0.00156683933767525
+8.89 10 0 10.0865048861359 -0.000314694070277437
+8.9 10 0 10.086492379575 -0.00218469182675679
+8.91 10 0 10.0864612308983 -0.00404310989415498
+8.92 10 0 10.0864115561236 -0.00588990402452021
+8.93 10 0 10.0863434717124 -0.00772502975834998
+8.94 10 0 10.086257094572 -0.0095484424233761
+8.95 10 0 10.0861525420571 -0.0113600971333419
+8.96 10 0 10.0860299319728 -0.0131599487867708
+8.97 10 0 10.0858893825759 -0.0149479520657267
+8.98 10 0 10.0857310125778 -0.0167240614345665
+8.99 10 0 10.0855549411461 -0.0184882311386835
+9 10 0 10.0853612879072 -0.0202404152032429
+9.01 10 0 10.0851501729481 -0.0219805674319088
+9.02 10 0 10.0849217168193 -0.0237086414055614
+9.03 10 0 10.0846760405363 -0.0254245904810079
+9.04 10 0 10.0844132655822 -0.0271283677896817
+9.05 10 0 10.0841335139101 -0.0288199262363363
+9.06 10 0 10.0838369079448 -0.0304992184977261
+9.07 10 0 10.0835235705859 -0.0321661970212827
+9.08 10 0 10.0831936252094 -0.0338208140237789
+9.09 10 0 10.0828471956705 -0.0354630214899848
+9.1 10 0 10.0824844063055 -0.0370927711713154
+9.11 10 0 10.0821053819346 -0.0387100145844677
+9.12 10 0 10.0817102478638 -0.0403147030100496
+9.13 10 0 10.0812991298875 -0.0419067874911983
+9.14 10 0 10.080872154291 -0.0434862188321913
+9.15 10 0 10.0804294478528 -0.0450529475970449
+9.16 10 0 10.0799711378466 -0.046606924108106
+9.17 10 0 10.0794973520445 -0.0481480984446325
+9.18 10 0 10.0790082187188 -0.0496764204413645
+9.19 10 0 10.0785038666448 -0.0511918396870861
+9.2 10 0 10.0779844251031 -0.0526943055231759
+9.21 10 0 10.077450023882 -0.05418376704215
+9.22 10 0 10.0769007932804 -0.0556601730861919
+9.23 10 0 10.0763368641099 -0.0571234722456754
+9.24 10 0 10.0757583676973 -0.0585736128576743
+9.25 10 0 10.0751654358876 -0.0600105430044644
+9.26 10 0 10.074558201046 -0.0614342105120137
+9.27 10 0 10.0739367960609 -0.0628445629484624
+9.28 10 0 10.0733013543462 -0.0642415476225923
+9.29 10 0 10.0726520098441 -0.0656251115822853
+9.3 10 0 10.0719888970276 -0.0669952016129755
+9.31 10 0 10.0713121509032 -0.0683517642360786
+9.32 10 0 10.0706219070134 -0.0696947457074267
+9.33 10 0 10.0699183014396 -0.07102409201568
+9.34 10 0 10.0692014708045 -0.0723397488807312
+9.35 10 0 10.0684715522752 -0.0736416617521029
+9.36 10 0 10.0677286835655 -0.0749297758073216
+9.37 10 0 10.0669730029388 -0.0762040359503002
+9.38 10 0 10.0662046492108 -0.0774643868096853
+9.39 10 0 10.0654237617523 -0.0787107727372166
+9.4 10 0 10.0646304804922 -0.0799431378060552
+9.41 10 0 10.0638249459197 -0.0811614258091122
+9.42 10 0 10.0630072990878 -0.0823655802573613
+9.43 10 0 10.0621776816156 -0.0835555443781397
+9.44 10 0 10.0613362356915 -0.0847312611134376
+9.45 10 0 10.0604831040758 -0.085892673118175
+9.46 10 0 10.0596184301037 -0.0870397227584677
+9.47 10 0 10.0587423576882 -0.088172352109879
+9.48 10 0 10.0578550313231 -0.0892905029556614
+9.49 10 0 10.0569565960858 -0.0903941167849835
+9.5 10 0 10.0560471976401 -0.0914831347911463
+9.51 10 0 10.0551269822397 -0.0925574978697858
+9.52 10 0 10.0541960967305 -0.0936171466170632
+9.53 10 0 10.0532546885541 -0.0946620213278421
+9.54 10 0 10.0523029057507 -0.0956920619938527
+9.55 10 0 10.051340896962 -0.0967072083018434
+9.56 10 0 10.0503688114345 -0.0977073996317184
+9.57 10 0 10.0493867990224 -0.0986925750546629
+9.58 10 0 10.0483950101906 -0.0996626733312545
+9.59 10 0 10.0473935960181 -0.100617632909561
+9.6 10 0 10.0463827082009 -0.101557391923224
+9.61 10 0 10.0453624990554 -0.102481888189532
+9.62 10 0 10.0443331215212 -0.103391059207474
+9.63 10 0 10.0432947291648 -0.104284842155785
+9.64 10 0 10.0422474761821 -0.105163173890971
+9.65 10 0 10.0411915174025 -0.106025990945329
+9.66 10 0 10.0401270082914 -0.106873229524944
+9.67 10 0 10.039054104954 -0.107704825507675
+9.68 10 0 10.0379729641381 -0.108520714441127
+9.69 10 0 10.0368837432379 -0.109320831540607
+9.7 10 0 10.0357866002971 -0.110105111687069
+9.71 10 0 10.0346816940121 -0.110873489425035
+9.72 10 0 10.0335691837359 -0.111625898960516
+9.73 10 0 10.0324492294807 -0.112362274158899
+9.74 10 0 10.031321991922 -0.113082548542837
+9.75 10 0 10.0301876324019 -0.113786655290109
+9.76 10 0 10.0290463129322 -0.114474527231477
+9.77 10 0 10.0278981961983 -0.115146096848517
+9.78 10 0 10.0267434455625 -0.115801296271437
+9.79 10 0 10.0255822250676 -0.116440057276886
+9.8 10 0 10.0244146994403 -0.117062311285737
+9.81 10 0 10.0232410340949 -0.117667989360859
+9.82 10 0 10.0220613951371 -0.118257022204875
+9.83 10 0 10.0208759493671 -0.118829340157896
+9.84 10 0 10.0196848642836 -0.119384873195245
+9.85 10 0 10.0184883080875 -0.119923550925165
+9.86 10 0 10.0172864496853 -0.120445302586501
+9.87 10 0 10.0160794586931 -0.120950057046381
+9.88 10 0 10.01486750544 -0.121437742797857
+9.89 10 0 10.0136507609724 -0.121908287957556
+9.9 10 0 10.012429397057 -0.122361620263289
+9.91 10 0 10.0112035861854 -0.12279766707166
+9.92 10 0 10.0099735015773 -0.123216355355644
+9.93 10 0 10.0087393171847 -0.123617611702159
+9.94 10 0 10.0075012076957 -0.124001362309611
+9.95 10 0 10.0062593485382 -0.124367532985424
+9.96 10 0 10.0050139158843 -0.124716049143553
+9.97 10 0 10.0037650866536 -0.12504683580198
+9.98 10 0 10.0025130385178 -0.125359817580181
+9.99 10 0 10.0012579499042 -0.12565491869659
+10 10 0 10 -0.125932062966031
+10.01 10 0 9.9987393687563 -0.126191173797138
+10.02 10 0 9.99747623689214 -0.126432174189749
+10.03 10 0 9.99621078589862 -0.126654986732295
+10.04 10 0 9.99494319804303 -0.126859533599146
+10.05 10 0 9.99367365637299 -0.127045736547963
+10.06 10 0 9.99240234472063 -0.127213516917009
+10.07 10 0 9.99112944770681 -0.127362795622451
+10.08 10 0 9.98985515074537 -0.127493493155642
+10.09 10 0 9.98857964004735 -0.127605529580375
+10.1 10 0 9.9873031026253 -0.127698824530125
+10.11 10 0 9.98602572629761 -0.127773297205264
+10.12 10 0 9.98474769969284 -0.127828866370256
+10.13 10 0 9.98346921225411 -0.127865450350835
+10.14 10 0 9.98219045424345 -0.127882967031158
+10.15 10 0 9.9809116167463 -0.127881333850934
+10.16 10 0 9.97963289167594 -0.127860467802537
+10.17 10 0 9.97835447177795 -0.127820285428094
+10.18 10 0 9.97707655063478 -0.127760702816551
+10.19 10 0 9.97579932267025 -0.127681635600716
+10.2 10 0 9.97452298315415 -0.127582998954281
+10.21 10 0 9.97324772820684 -0.127464707588819
+10.22 10 0 9.9719737548039 -0.127326675750765
+10.23 10 0 9.97070126078076 -0.127168817218361
+10.24 10 0 9.96943044483744 -0.12699104529859
+10.25 10 0 9.96816150654325 -0.126793272824081
+10.26 10 0 9.96689464634157 -0.126575412149992
+10.27 10 0 9.96563006555461 -0.126337375150863
+10.28 10 0 9.96436796638828 -0.126079073217457
+10.29 10 0 9.96310855193698 -0.125800417253565
+10.3 10 0 9.96185202618854 -0.125501317672791
+10.31 10 0 9.96059859402912 -0.125181684395315
+10.32 10 0 9.95934846124816 -0.124841426844625
+10.33 10 0 9.95810183454334 -0.12448045394423
+10.34 10 0 9.95685892152565 -0.124098674114341
+10.35 10 0 9.95561993072438 -0.123695995268533
+10.36 10 0 9.95438507159226 -0.123272324810375
+10.37 10 0 9.95315455451052 -0.12282756963004
+10.38 10 0 9.9519285907941 -0.122361636100882
+10.39 10 0 9.95070739269677 -0.121874430075993
+10.4 10 0 9.94949117341641 -0.121365856884728
+10.41 10 0 9.94828014710023 -0.120835821329205
+10.42 10 0 9.94707452885007 -0.120284227680776
+10.43 10 0 9.94587453472774 -0.119710979676478
+10.44 10 0 9.94468038176034 -0.119115980515443
+10.45 10 0 9.9434922879457 -0.11849913285529
+10.46 10 0 9.94231047225779 -0.117860338808486
+10.47 10 0 9.94113515465221 -0.117199499938681
+10.48 10 0 9.93996655607167 -0.116516517257003
+10.49 10 0 9.93880489845153 -0.115811291218344
+10.5 10 0 9.93765040472544 -0.115083721717594
+10.51 10 0 9.93650329883089 -0.114333708085864
+10.52 10 0 9.93536380571489 -0.113561149086668
+10.53 10 0 9.93423215133968 -0.112765942912078
+10.54 10 0 9.93310856268844 -0.111947987178853
+10.55 10 0 9.9319932677711 -0.111107178924527
+10.56 10 0 9.93088649563011 -0.110243414603477
+10.57 10 0 9.9297884763463 -0.109356590082955
+10.58 10 0 9.9286994410448 -0.108446600639084
+10.59 10 0 9.92761962190093 -0.107513340952833
+10.6 10 0 9.92654925214621 -0.10655670510595
+10.61 10 0 9.92548856607435 -0.105576586576863
+10.62 10 0 9.92443779904731 -0.10457287823656
+10.63 10 0 9.92339718750139 -0.103545472344419
+10.64 10 0 9.92236696895338 -0.102494260544019
+10.65 10 0 9.92134738200672 -0.101419133858908
+10.66 10 0 9.92033866635775 -0.100319982688341
+10.67 10 0 9.91934106280193 -0.0991966968029864
+10.68 10 0 9.91835481324021 -0.0980491653405918
+10.69 10 0 9.9173801606853 -0.0968772768016188
+10.7 10 0 9.91641734926816 -0.0956809190448425
+10.71 10 0 9.91546662424435 -0.0944599792829138
+10.72 10 0 9.91452823200057 -0.0932143440778898
+10.73 10 0 9.91360242006118 -0.091943899336719
+10.74 10 0 9.91268943709473 -0.0906485303067041
+10.75 10 0 9.91178953292065 -0.0893281215709139
+10.76 10 0 9.91090295851587 -0.0879825570435668
+10.77 10 0 9.91002996602154 -0.0866117199653732
+10.78 10 0 9.90917080874978 -0.0852154928988429
+10.79 10 0 9.90832574119052 -0.0837937577235498
+10.8 10 0 9.90749501901829 -0.0823463956313615
+10.81 10 0 9.90667889909921 -0.0808732871216298
+10.82 10 0 9.90587763949783 -0.0793743119963399
+10.83 10 0 9.90509149948425 -0.0778493493552235
+10.84 10 0 9.90432073954106 -0.0762982775908262
+10.85 10 0 9.9035656213705 -0.0747209743835402
+10.86 10 0 9.90282640790158 -0.0731173166965934
+10.87 10 0 9.90210336329728 -0.0714871807709962
+10.88 10 0 9.90139675296183 -0.0698304421204525
+10.89 10 0 9.90070684354794 -0.0681469755262188
+10.9 10 0 9.90003390296422 -0.0664366550319311
+10.91 10 0 9.89937820038255 -0.0646993539383826
+10.92 10 0 9.89874000624552 -0.0629349447982605
+10.93 10 0 9.89811959227399 -0.061143299410841
+10.94 10 0 9.89751723147458 -0.0593242888166347
+10.95 10 0 9.89693319814734 -0.0574777832919947
+10.96 10 0 9.8963677678934 -0.0556036523436732
+10.97 10 0 9.89582121762268 -0.0537017647033419
+10.98 10 0 9.89529382556171 -0.0517719883220511
+10.99 10 0 9.89478587126141 -0.0498141903646643
+11 10 0 9.89429763560501 -0.0478282372042251
+11.01 10 0 9.89382940081599 -0.0458139944162913
+11.02 10 0 9.89338145046611 -0.0437713267732153
+11.03 10 0 9.89295406948341 -0.0417000982383777
+11.04 10 0 9.89254754416039 -0.0396001719603763
+11.05 10 0 9.89216216216216 -0.0374714102671569
+11.06 10 0 9.89179821253467 -0.0353136746601062
+11.07 10 0 9.89145598571302 -0.033126825808086
+11.08 10 0 9.8911357735298 -0.0309107235414248
+11.09 10 0 9.89083786922352 -0.0286652268458502
+11.1 10 0 9.8905625674471 -0.0263901938563768
+11.11 10 0 9.89031016427635 -0.0240854818511404
+11.12 10 0 9.89008095721865 -0.0217509472451775
+11.13 10 0 9.88987524522154 -0.0193864455841594
+11.14 10 0 9.88969332868148 -0.0169918315380612
+11.15 10 0 9.88953550945267 -0.0145669588947887
+11.16 10 0 9.88940209085581 -0.0121116805537442
+11.17 10 0 9.88929337768714 -0.00962584851933949
+11.18 10 0 9.8892096762273 -0.00710931389445635
+11.19 10 0 9.88915129425046 -0.00456192687384342
+11.2 10 0 9.88911854103343 -0.00198353673746563
+11.21 10 0 9.8891117273648 0.000626008156209702
+11.22 10 0 9.88913116555421 0.00326686037697991
+11.23 10 0 9.88917716944168 0.00593917342973734
+11.24 10 0 9.88925005440696 0.00864310176134909
+11.25 10 0 9.88935013737905 0.0113788007676095
+11.26 10 0 9.88947773684563 0.0141464268002403
+11.27 10 0 9.88963317286275 0.0169461371739573
+11.28 10 0 9.88981676706442 0.0197780901735972
+11.29 10 0 9.8900288426724 0.0226424450613011
+11.3 10 0 9.89026972450599 0.0255393620837724
+11.31 10 0 9.89053973899188 0.0284690024795831
+11.32 10 0 9.89083921417417 0.031431528486554
+11.33 10 0 9.89116847972435 0.0344271033491903
+11.34 10 0 9.89152786695142 0.037455891326193
+11.35 10 0 9.89191770881208 0.0405180576980254
+11.36 10 0 9.89233833992095 0.04361376877455
+11.37 10 0 9.89279009656096 0.0467431919027344
+11.38 10 0 9.8932733166937 0.0499064954744146
+11.39 10 0 9.89378833996995 0.0531038489341435
+11.4 10 0 9.89433550774024 0.0563354227870906
+11.41 10 0 9.89491516306546 0.0596013886070217
+11.42 10 0 9.89552765072765 0.0629019190443448
+11.43 10 0 9.89617331724074 0.0662371878342288
+11.44 10 0 9.89685251086148 0.0696073698047876
+11.45 10 0 9.89756558160041 0.0730126408853481
+11.46 10 0 9.89831288123289 0.0764531781147811
+11.47 10 0 9.89909476331027 0.079929159649907
+11.48 10 0 9.89991158317106 0.0834407647739837
+11.49 10 0 9.90076369795231 0.0869881739052541
+11.5 10 0 9.90165146660094 0.0905715686055906
+11.51 10 0 9.90257524988524 0.0941911315891987
+11.52 10 0 9.90353541040645 0.0978470467314056
+11.53 10 0 9.90453231261042 0.101539499077528
+11.54 10 0 9.9055663227993 0.10526867485181
+11.55 10 0 9.90663780914345 0.109034761466459
+11.56 10 0 9.90774714169333 0.112837947530741
+11.57 10 0 9.90889469239148 0.116678422860176
+11.58 10 0 9.91008083508471 0.120556378485798
+11.59 10 0 9.91130594553623 0.124472006663515
+11.6 10 0 9.91257040143799 0.128425500883544
+11.61 10 0 9.91387458242302 0.132417055879932
+11.62 10 0 9.91521887007799 0.136446867640162
+11.63 10 0 9.91660364795573 0.140515133414844
+11.64 10 0 9.91802930158794 0.144622051727511
+11.65 10 0 9.91949621849795 0.148767822384469
+11.66 10 0 9.92100478821363 0.15295264648477
+11.67 10 0 9.92255540228032 0.157176726430258
+11.68 10 0 9.92414845427395 0.161440265935713
+11.69 10 0 9.92578433981421 0.165743470039074
+11.7 10 0 9.92746345657782 0.170086545111779
+11.71 10 0 9.92918620431191 0.174469698869179
+11.72 10 0 9.93095298484756 0.178893140381053
+11.73 10 0 9.93276420211335 0.183357080082224
+11.74 10 0 9.93462026214905 0.187861729783258
+11.75 10 0 9.93652157311951 0.192407302681285
+11.76 10 0 9.93846854532849 0.196994013370897
+11.77 10 0 9.94046159123275 0.201622077855157
+11.78 10 0 9.94250112545616 0.206291713556705
+11.79 10 0 9.94458756480396 0.211003139328966
+11.8 10 0 9.94672132827713 0.215756575467471
+11.81 10 0 9.94890283708687 0.220552243721271
+11.82 10 0 9.95113251466916 0.225390367304457
+11.83 10 0 9.95341078669952 0.230271170907799
+11.84 10 0 9.95573808110781 0.235194880710471
+11.85 10 0 9.95811482809316 0.240161724391913
+11.86 10 0 9.96054146013905 0.24517193114378
+11.87 10 0 9.96301841202849 0.250225731682015
+11.88 10 0 9.96554612085931 0.255323358259018
+11.89 10 0 9.96812502605963 0.260465044675966
+11.9 10 0 9.97075556940333 0.265651026295195
+11.91 10 0 9.97343819502582 0.270881540052744
+11.92 10 0 9.97617334943975 0.276156824470995
+11.93 10 0 9.978961481551 0.281477119671431
+11.94 10 0 9.98180304267471 0.286842667387519
+11.95 10 0 9.98469848655148 0.292253710977719
+11.96 10 0 9.98764826936365 0.297710495438605
+11.97 10 0 9.9906528497518 0.303213267418114
+11.98 10 0 9.99371268883127 0.308762275228927
+11.99 10 0 9.99682825020893 0.314357768861958
+12 10 0.666666666666667 10 0.666666666666667
+12.01 10.0066666666667 0.666666666666667 10.0032115555556 0.322311111111111
+12.02 10.0133333333333 0.666666666666667 10.0064462222222 0.324622222222223
+12.03 10.02 0.666666666666667 10.009704 0.326933333333334
+12.04 10.0266666666667 0.666666666666667 10.0129848888889 0.329244444444444
+12.05 10.0333333333333 0.666666666666667 10.0162888888889 0.331555555555555
+12.06 10.04 0.666666666666667 10.019616 0.333866666666667
+12.07 10.0466666666667 0.666666666666667 10.0229662222222 0.336177777777778
+12.08 10.0533333333333 0.666666666666667 10.0263395555556 0.338488888888888
+12.09 10.06 0.666666666666667 10.029736 0.3408
+12.1 10.0666666666667 0.666666666666667 10.0331555555556 0.343111111111112
+12.11 10.0733333333333 0.666666666666667 10.0365982222222 0.345422222222222
+12.12 10.08 0.666666666666667 10.040064 0.347733333333333
+12.13 10.0866666666667 0.666666666666667 10.0435528888889 0.350044444444445
+12.14 10.0933333333333 0.666666666666667 10.0470648888889 0.352355555555556
+12.15 10.1 0.666666666666667 10.0506 0.354666666666666
+12.16 10.1066666666667 0.666666666666667 10.0541582222222 0.356977777777778
+12.17 10.1133333333333 0.666666666666667 10.0577395555556 0.359288888888889
+12.18 10.12 0.666666666666667 10.061344 0.361599999999999
+12.19 10.1266666666667 0.666666666666667 10.0649715555556 0.363911111111111
+12.2 10.1333333333333 0.666666666666667 10.0686222222222 0.366222222222222
+12.21 10.14 0.666666666666667 10.072296 0.368533333333334
+12.22 10.1466666666667 0.666666666666667 10.0759928888889 0.370844444444445
+12.23 10.1533333333333 0.666666666666667 10.0797128888889 0.373155555555556
+12.24 10.16 0.666666666666667 10.083456 0.375466666666667
+12.25 10.1666666666667 0.666666666666667 10.0872222222222 0.377777777777777
+12.26 10.1733333333333 0.666666666666667 10.0910115555556 0.380088888888889
+12.27 10.18 0.666666666666667 10.094824 0.3824
+12.28 10.1866666666667 0.666666666666667 10.0986595555556 0.384711111111111
+12.29 10.1933333333333 0.666666666666667 10.1025182222222 0.387022222222222
+12.3 10.2 0.666666666666667 10.1064 0.389333333333334
+12.31 10.2066666666667 0.666666666666667 10.1103048888889 0.391644444444445
+12.32 10.2133333333333 0.666666666666667 10.1142328888889 0.393955555555556
+12.33 10.22 0.666666666666667 10.118184 0.396266666666666
+12.34 10.2266666666667 0.666666666666667 10.1221582222222 0.398577777777777
+12.35 10.2333333333333 0.666666666666667 10.1261555555556 0.400888888888889
+12.36 10.24 0.666666666666667 10.130176 0.4032
+12.37 10.2466666666667 0.666666666666667 10.1342195555556 0.405511111111111
+12.38 10.2533333333333 0.666666666666667 10.1382862222222 0.407822222222222
+12.39 10.26 0.666666666666667 10.142376 0.410133333333333
+12.4 10.2666666666667 0.666666666666667 10.1464888888889 0.412444444444445
+12.41 10.2733333333333 0.666666666666667 10.1506248888889 0.414755555555556
+12.42 10.28 0.666666666666667 10.154784 0.417066666666667
+12.43 10.2866666666667 0.666666666666667 10.1589662222222 0.419377777777778
+12.44 10.2933333333333 0.666666666666667 10.1631715555556 0.421688888888889
+12.45 10.3 0.666666666666667 10.1674 0.423999999999999
+12.46 10.3066666666667 0.666666666666667 10.1716515555556 0.426311111111111
+12.47 10.3133333333333 0.666666666666667 10.1759262222222 0.428622222222222
+12.48 10.32 0.666666666666667 10.180224 0.430933333333333
+12.49 10.3266666666667 0.666666666666667 10.1845448888889 0.433244444444444
+12.5 10.3333333333333 0.666666666666667 10.1888888888889 0.435555555555556
+12.51 10.34 0.666666666666667 10.193256 0.437866666666667
+12.52 10.3466666666667 0.666666666666667 10.1976462222222 0.440177777777778
+12.53 10.3533333333333 0.666666666666667 10.2020595555556 0.442488888888889
+12.54 10.36 0.666666666666667 10.206496 0.444799999999999
+12.55 10.3666666666667 0.666666666666667 10.2109555555556 0.447111111111111
+12.56 10.3733333333333 0.666666666666667 10.2154382222222 0.449422222222222
+12.57 10.38 0.666666666666667 10.219944 0.451733333333334
+12.58 10.3866666666667 0.666666666666667 10.2244728888889 0.454044444444444
+12.59 10.3933333333333 0.666666666666667 10.2290248888889 0.456355555555555
+12.6 10.4 0.666666666666667 10.2336 0.458666666666667
+12.61 10.4066666666667 0.666666666666667 10.2381982222222 0.460977777777778
+12.62 10.4133333333333 0.666666666666667 10.2428195555556 0.46328888888889
+12.63 10.42 0.666666666666667 10.247464 0.4656
+12.64 10.4266666666667 0.666666666666667 10.2521315555556 0.467911111111111
+12.65 10.4333333333333 0.666666666666667 10.2568222222222 0.470222222222222
+12.66 10.44 0.666666666666667 10.261536 0.472533333333333
+12.67 10.4466666666667 0.666666666666667 10.2662728888889 0.474844444444445
+12.68 10.4533333333333 0.666666666666667 10.2710328888889 0.477155555555556
+12.69 10.46 0.666666666666667 10.275816 0.479466666666667
+12.7 10.4666666666667 0.666666666666667 10.2806222222222 0.481777777777778
+12.71 10.4733333333333 0.666666666666667 10.2854515555556 0.48408888888889
+12.72 10.48 0.666666666666667 10.290304 0.486399999999999
+12.73 10.4866666666667 0.666666666666667 10.2951795555556 0.488711111111111
+12.74 10.4933333333333 0.666666666666667 10.3000782222222 0.491022222222222
+12.75 10.5 0.666666666666667 10.305 0.493333333333333
+12.76 10.5066666666667 0.666666666666667 10.3099448888889 0.495644444444444
+12.77 10.5133333333333 0.666666666666667 10.3149128888889 0.497955555555556
+12.78 10.52 0.666666666666667 10.319904 0.500266666666667
+12.79 10.5266666666667 0.666666666666667 10.3249182222222 0.502577777777777
+12.8 10.5333333333333 0.666666666666667 10.3299555555556 0.504888888888889
+12.81 10.54 0.666666666666667 10.335016 0.507200000000001
+12.82 10.5466666666667 0.666666666666667 10.3400995555556 0.509511111111111
+12.83 10.5533333333333 0.666666666666667 10.3452062222222 0.511822222222223
+12.84 10.56 0.666666666666667 10.350336 0.514133333333333
+12.85 10.5666666666667 0.666666666666667 10.3554888888889 0.516444444444445
+12.86 10.5733333333333 0.666666666666667 10.3606648888889 0.518755555555555
+12.87 10.58 0.666666666666667 10.365864 0.521066666666667
+12.88 10.5866666666667 0.666666666666667 10.3710862222222 0.523377777777778
+12.89 10.5933333333333 0.666666666666667 10.3763315555556 0.525688888888889
+12.9 10.6 0.666666666666667 10.3816 0.528
+12.91 10.6066666666667 0.666666666666667 10.3868915555556 0.530311111111111
+12.92 10.6133333333333 0.666666666666667 10.3922062222222 0.532622222222223
+12.93 10.62 0.666666666666667 10.397544 0.534933333333333
+12.94 10.6266666666667 0.666666666666667 10.4029048888889 0.537244444444445
+12.95 10.6333333333333 0.666666666666667 10.4082888888889 0.539555555555555
+12.96 10.64 0.666666666666667 10.413696 0.541866666666667
+12.97 10.6466666666667 0.666666666666667 10.4191262222222 0.544177777777778
+12.98 10.6533333333333 0.666666666666667 10.4245795555556 0.546488888888889
+12.99 10.66 0.666666666666667 10.430056 0.5488
+13 10.6666666666667 0.666666666666667 10.4355555555556 0.551111111111111
+13.01 10.6733333333333 0.666666666666667 10.4410782222222 0.553422222222222
+13.02 10.68 0.666666666666667 10.446624 0.555733333333334
+13.03 10.6866666666667 0.666666666666667 10.4521928888889 0.558044444444444
+13.04 10.6933333333333 0.666666666666667 10.4577848888889 0.560355555555556
+13.05 10.7 0.666666666666667 10.4634 0.562666666666667
+13.06 10.7066666666667 0.666666666666667 10.4690382222222 0.564977777777778
+13.07 10.7133333333333 0.666666666666667 10.4746995555556 0.567288888888889
+13.08 10.72 0.666666666666667 10.480384 0.569600000000001
+13.09 10.7266666666667 0.666666666666667 10.4860915555556 0.571911111111111
+13.1 10.7333333333333 0.666666666666667 10.4918222222222 0.574222222222222
+13.11 10.74 0.666666666666667 10.497576 0.576533333333333
+13.12 10.7466666666667 0.666666666666667 10.5033528888889 0.578844444444445
+13.13 10.7533333333333 0.666666666666667 10.5091528888889 0.581155555555555
+13.14 10.76 0.666666666666667 10.514976 0.583466666666667
+13.15 10.7666666666667 0.666666666666667 10.5208222222222 0.585777777777778
+13.16 10.7733333333333 0.666666666666667 10.5266915555556 0.588088888888889
+13.17 10.78 0.666666666666667 10.532584 0.5904
+13.18 10.7866666666667 0.666666666666667 10.5384995555556 0.592711111111112
+13.19 10.7933333333333 0.666666666666667 10.5444382222222 0.595022222222222
+13.2 10.8 0.666666666666667 10.5504 0.597333333333333
+13.21 10.8066666666667 0.666666666666667 10.5563848888889 0.599644444444445
+13.22 10.8133333333333 0.666666666666667 10.5623928888889 0.601955555555556
+13.23 10.82 0.666666666666667 10.568424 0.604266666666667
+13.24 10.8266666666667 0.666666666666667 10.5744782222222 0.606577777777778
+13.25 10.8333333333333 0.666666666666667 10.5805555555556 0.608888888888889
+13.26 10.84 0.666666666666667 10.586656 0.6112
+13.27 10.8466666666667 0.666666666666667 10.5927795555556 0.613511111111111
+13.28 10.8533333333333 0.666666666666667 10.5989262222222 0.615822222222222
+13.29 10.86 0.666666666666667 10.605096 0.618133333333333
+13.3 10.8666666666667 0.666666666666667 10.6112888888889 0.620444444444445
+13.31 10.8733333333333 0.666666666666667 10.6175048888889 0.622755555555556
+13.32 10.88 0.666666666666667 10.623744 0.625066666666667
+13.33 10.8866666666667 0.666666666666667 10.6300062222222 0.627377777777778
+13.34 10.8933333333333 0.666666666666667 10.6362915555556 0.629688888888889
+13.35 10.9 0.666666666666667 10.6426 0.632
+13.36 10.9066666666667 0.666666666666667 10.6489315555556 0.634311111111111
+13.37 10.9133333333333 0.666666666666667 10.6552862222222 0.636622222222223
+13.38 10.92 0.666666666666667 10.661664 0.638933333333333
+13.39 10.9266666666667 0.666666666666667 10.6680648888889 0.641244444444444
+13.4 10.9333333333333 0.666666666666667 10.6744888888889 0.643555555555556
+13.41 10.94 0.666666666666667 10.680936 0.645866666666666
+13.42 10.9466666666667 0.666666666666667 10.6874062222222 0.648177777777778
+13.43 10.9533333333333 0.666666666666667 10.6938995555556 0.650488888888889
+13.44 10.96 0.666666666666667 10.700416 0.6528
+13.45 10.9666666666667 0.666666666666667 10.7069555555556 0.655111111111111
+13.46 10.9733333333333 0.666666666666667 10.7135182222222 0.657422222222223
+13.47 10.98 0.666666666666667 10.720104 0.659733333333334
+13.48 10.9866666666667 0.666666666666667 10.7267128888889 0.662044444444445
+13.49 10.9933333333333 0.666666666666667 10.7333448888889 0.664355555555555
+13.5 11 0.666666666666667 10.74 0.666666666666667
+13.51 11.0066666666667 0.666666666666667 10.7466782222222 0.668977777777777
+13.52 11.0133333333333 0.666666666666667 10.7533795555556 0.671288888888889
+13.53 11.02 0.666666666666667 10.760104 0.6736
+13.54 11.0266666666667 0.666666666666667 10.7668515555556 0.675911111111111
+13.55 11.0333333333333 0.666666666666667 10.7736222222222 0.678222222222222
+13.56 11.04 0.666666666666667 10.780416 0.680533333333334
+13.57 11.0466666666667 0.666666666666667 10.7872328888889 0.682844444444444
+13.58 11.0533333333333 0.666666666666667 10.7940728888889 0.685155555555556
+13.59 11.06 0.666666666666667 10.800936 0.687466666666667
+13.6 11.0666666666667 0.666666666666667 10.8078222222222 0.689777777777778
+13.61 11.0733333333333 0.666666666666667 10.8147315555556 0.692088888888888
+13.62 11.08 0.666666666666667 10.821664 0.6944
+13.63 11.0866666666667 0.666666666666667 10.8286195555556 0.696711111111111
+13.64 11.0933333333333 0.666666666666667 10.8355982222222 0.699022222222222
+13.65 11.1 0.666666666666667 10.8426 0.701333333333334
+13.66 11.1066666666667 0.666666666666667 10.8496248888889 0.703644444444444
+13.67 11.1133333333333 0.666666666666667 10.8566728888889 0.705955555555555
+13.68 11.12 0.666666666666667 10.863744 0.708266666666667
+13.69 11.1266666666667 0.666666666666667 10.8708382222222 0.710577777777778
+13.7 11.1333333333333 0.666666666666667 10.8779555555556 0.712888888888889
+13.71 11.14 0.666666666666667 10.885096 0.715200000000001
+13.72 11.1466666666667 0.666666666666667 10.8922595555556 0.717511111111111
+13.73 11.1533333333333 0.666666666666667 10.8994462222222 0.719822222222222
+13.74 11.16 0.666666666666667 10.906656 0.722133333333333
+13.75 11.1666666666667 0.666666666666667 10.9138888888889 0.724444444444445
+13.76 11.1733333333333 0.666666666666667 10.9211448888889 0.726755555555555
+13.77 11.18 0.666666666666667 10.928424 0.729066666666667
+13.78 11.1866666666667 0.666666666666667 10.9357262222222 0.731377777777778
+13.79 11.1933333333333 0.666666666666667 10.9430515555556 0.733688888888889
+13.8 11.2 0.666666666666667 10.9504 0.736
+13.81 11.2066666666667 0.666666666666667 10.9577715555556 0.738311111111112
+13.82 11.2133333333333 0.666666666666667 10.9651662222222 0.740622222222222
+13.83 11.22 0.666666666666667 10.972584 0.742933333333334
+13.84 11.2266666666667 0.666666666666667 10.9800248888889 0.745244444444445
+13.85 11.2333333333333 0.666666666666667 10.9874888888889 0.747555555555556
+13.86 11.24 0.666666666666667 10.994976 0.749866666666666
+13.87 11.2466666666667 0.666666666666667 11.0024862222222 0.752177777777778
+13.88 11.2533333333333 0.666666666666667 11.0100195555556 0.754488888888889
+13.89 11.26 0.666666666666667 11.017576 0.7568
+13.9 11.2666666666667 0.666666666666667 11.0251555555556 0.759111111111111
+13.91 11.2733333333333 0.666666666666667 11.0327582222222 0.761422222222222
+13.92 11.28 0.666666666666667 11.040384 0.763733333333333
+13.93 11.2866666666667 0.666666666666667 11.0480328888889 0.766044444444445
+13.94 11.2933333333333 0.666666666666667 11.0557048888889 0.768355555555555
+13.95 11.3 0.666666666666667 11.0634 0.770666666666667
+13.96 11.3066666666667 0.666666666666667 11.0711182222222 0.772977777777778
+13.97 11.3133333333333 0.666666666666667 11.0788595555556 0.775288888888889
+13.98 11.32 0.666666666666667 11.086624 0.7776
+13.99 11.3266666666667 0.666666666666667 11.0944115555556 0.779911111111111
+14 11.3333333333333 0.666666666666667 11.1022222222222 0.782222222222222
+14.01 11.34 0.666666666666667 11.110056 0.784533333333333
+14.02 11.3466666666667 0.666666666666667 11.1179128888889 0.786844444444444
+14.03 11.3533333333333 0.666666666666667 11.1257928888889 0.789155555555555
+14.04 11.36 0.666666666666667 11.133696 0.791466666666666
+14.05 11.3666666666667 0.666666666666667 11.1416222222222 0.793777777777778
+14.06 11.3733333333333 0.666666666666667 11.1495715555556 0.796088888888889
+14.07 11.38 0.666666666666667 11.157544 0.7984
+14.08 11.3866666666667 0.666666666666667 11.1655395555556 0.800711111111111
+14.09 11.3933333333333 0.666666666666667 11.1735582222222 0.803022222222223
+14.1 11.4 0.666666666666667 11.1816 0.805333333333333
+14.11 11.4066666666667 0.666666666666667 11.1896648888889 0.807644444444444
+14.12 11.4133333333333 0.666666666666667 11.1977528888889 0.809955555555556
+14.13 11.42 0.666666666666667 11.205864 0.812266666666667
+14.14 11.4266666666667 0.666666666666667 11.2139982222222 0.814577777777777
+14.15 11.4333333333333 0.666666666666667 11.2221555555556 0.816888888888889
+14.16 11.44 0.666666666666667 11.230336 0.8192
+14.17 11.4466666666667 0.666666666666667 11.2385395555556 0.821511111111111
+14.18 11.4533333333333 0.666666666666667 11.2467662222222 0.823822222222222
+14.19 11.46 0.666666666666667 11.255016 0.826133333333334
+14.2 11.4666666666667 0.666666666666667 11.2632888888889 0.828444444444444
+14.21 11.4733333333333 0.666666666666667 11.2715848888889 0.830755555555556
+14.22 11.48 0.666666666666667 11.279904 0.833066666666667
+14.23 11.4866666666667 0.666666666666667 11.2882462222222 0.835377777777778
+14.24 11.4933333333333 0.666666666666667 11.2966115555556 0.837688888888888
+14.25 11.5 0.666666666666667 11.305 0.84
+14.26 11.5066666666667 0.666666666666667 11.3134115555556 0.842311111111111
+14.27 11.5133333333333 0.666666666666667 11.3218462222222 0.844622222222222
+14.28 11.52 0.666666666666667 11.330304 0.846933333333333
+14.29 11.5266666666667 0.666666666666667 11.3387848888889 0.849244444444444
+14.3 11.5333333333333 0.666666666666667 11.3472888888889 0.851555555555555
+14.31 11.54 0.666666666666667 11.355816 0.853866666666667
+14.32 11.5466666666667 0.666666666666667 11.3643662222222 0.856177777777778
+14.33 11.5533333333333 0.666666666666667 11.3729395555556 0.858488888888889
+14.34 11.56 0.666666666666667 11.381536 0.860799999999999
+14.35 11.5666666666667 0.666666666666667 11.3901555555556 0.863111111111111
+14.36 11.5733333333333 0.666666666666667 11.3987982222222 0.865422222222223
+14.37 11.58 0.666666666666667 11.407464 0.867733333333334
+14.38 11.5866666666667 0.666666666666667 11.4161528888889 0.870044444444445
+14.39 11.5933333333333 0.666666666666667 11.4248648888889 0.872355555555556
+14.4 11.6 0.666666666666667 11.4336 0.874666666666667
+14.41 11.6066666666667 0.666666666666667 11.4423582222222 0.876977777777777
+14.42 11.6133333333333 0.666666666666667 11.4511395555556 0.879288888888889
+14.43 11.62 0.666666666666667 11.459944 0.8816
+14.44 11.6266666666667 0.666666666666667 11.4687715555556 0.883911111111111
+14.45 11.6333333333333 0.666666666666667 11.4776222222222 0.886222222222222
+14.46 11.64 0.666666666666667 11.486496 0.888533333333334
+14.47 11.6466666666667 0.666666666666667 11.4953928888889 0.890844444444445
+14.48 11.6533333333333 0.666666666666667 11.5043128888889 0.893155555555556
+14.49 11.66 0.666666666666667 11.513256 0.895466666666667
+14.5 11.6666666666667 0.666666666666667 11.5222222222222 0.897777777777778
+14.51 11.6733333333333 0.666666666666667 11.5312115555556 0.900088888888888
+14.52 11.68 0.666666666666667 11.540224 0.9024
+14.53 11.6866666666667 0.666666666666667 11.5492595555556 0.904711111111111
+14.54 11.6933333333333 0.666666666666667 11.5583182222222 0.907022222222223
+14.55 11.7 0.666666666666667 11.5674 0.909333333333333
+14.56 11.7066666666667 0.666666666666667 11.5765048888889 0.911644444444445
+14.57 11.7133333333333 0.666666666666667 11.5856328888889 0.913955555555556
+14.58 11.72 0.666666666666667 11.594784 0.916266666666667
+14.59 11.7266666666667 0.666666666666667 11.6039582222222 0.918577777777777
+14.6 11.7333333333333 0.666666666666667 11.6131555555556 0.920888888888889
+14.61 11.74 0.666666666666667 11.622376 0.923199999999999
+14.62 11.7466666666667 0.666666666666667 11.6316195555556 0.925511111111111
+14.63 11.7533333333333 0.666666666666667 11.6408862222222 0.927822222222222
+14.64 11.76 0.666666666666667 11.650176 0.930133333333334
+14.65 11.7666666666667 0.666666666666667 11.6594888888889 0.932444444444444
+14.66 11.7733333333333 0.666666666666667 11.6688248888889 0.934755555555556
+14.67 11.78 0.666666666666667 11.678184 0.937066666666667
+14.68 11.7866666666667 0.666666666666667 11.6875662222222 0.939377777777778
+14.69 11.7933333333333 0.666666666666667 11.6969715555556 0.941688888888888
+14.7 11.8 0.666666666666667 11.7064 0.944
+14.71 11.8066666666667 0.666666666666667 11.7158515555556 0.946311111111111
+14.72 11.8133333333333 0.666666666666667 11.7253262222222 0.948622222222222
+14.73 11.82 0.666666666666667 11.734824 0.950933333333333
+14.74 11.8266666666667 0.666666666666667 11.7443448888889 0.953244444444445
+14.75 11.8333333333333 0.666666666666667 11.7538888888889 0.955555555555555
+14.76 11.84 0.666666666666667 11.763456 0.957866666666667
+14.77 11.8466666666667 0.666666666666667 11.7730462222222 0.960177777777778
+14.78 11.8533333333333 0.666666666666667 11.7826595555556 0.962488888888889
+14.79 11.86 0.666666666666667 11.792296 0.964799999999999
+14.8 11.8666666666667 0.666666666666667 11.8019555555556 0.967111111111111
+14.81 11.8733333333333 0.666666666666667 11.8116382222222 0.969422222222222
+14.82 11.88 0.666666666666667 11.821344 0.971733333333333
+14.83 11.8866666666667 0.666666666666667 11.8310728888889 0.974044444444444
+14.84 11.8933333333333 0.666666666666667 11.8408248888889 0.976355555555556
+14.85 11.9 0.666666666666667 11.8506 0.978666666666666
+14.86 11.9066666666667 0.666666666666667 11.8603982222222 0.980977777777778
+14.87 11.9133333333333 0.666666666666667 11.8702195555556 0.983288888888889
+14.88 11.92 0.666666666666667 11.880064 0.985600000000001
+14.89 11.9266666666667 0.666666666666667 11.8899315555556 0.98791111111111
+14.9 11.9333333333333 0.666666666666667 11.8998222222222 0.990222222222222
+14.91 11.94 0.666666666666667 11.909736 0.992533333333333
+14.92 11.9466666666667 0.666666666666667 11.9196728888889 0.994844444444444
+14.93 11.9533333333333 0.666666666666667 11.9296328888889 0.997155555555555
+14.94 11.96 0.666666666666667 11.939616 0.999466666666667
+14.95 11.9666666666667 0.666666666666667 11.9496222222222 1.00177777777778
+14.96 11.9733333333333 0.666666666666667 11.9596515555556 1.00408888888889
+14.97 11.98 0.666666666666667 11.969704 1.0064
+14.98 11.9866666666667 0.666666666666667 11.9797795555556 1.00871111111111
+14.99 11.9933333333333 0.666666666666667 11.9898782222222 1.01102222222222
+15 12 0.666666666666667 12 0.666666666666667
+
+5 -10 0.5 -10 0.5
+5.01 -9.995 0.5 -10.019792358804 -1.9585407445834
+5.02 -9.99 0.5 -10.0391721854305 -1.91749265383097
+5.03 -9.985 0.5 -10.0581435643564 -1.87685030879325
+5.04 -9.98 0.5 -10.0767105263158 -1.83660837950139
+5.05 -9.975 0.5 -10.0948770491803 -1.79676162321956
+5.06 -9.97 0.5 -10.1126470588235 -1.75730488273741
+5.07 -9.965 0.5 -10.1300244299674 -1.71823308470116
+5.08 -9.96 0.5 -10.147012987013 -1.6795412379828
+5.09 -9.955 0.5 -10.1636165048544 -1.64122443208597
+5.1 -9.95 0.5 -10.1798387096774 -1.60327783558793
+5.11 -9.945 0.5 -10.1956832797428 -1.56569669461647
+5.12 -9.94 0.5 -10.2111538461538 -1.52847633136095
+5.13 -9.935 0.5 -10.2262539936102 -1.49161214261654
+5.14 -9.93 0.5 -10.2409872611465 -1.45509959836099
+5.15 -9.925 0.5 -10.2553571428571 -1.41893424036281
+5.16 -9.92 0.5 -10.2693670886076 -1.38311168082038
+5.17 -9.915 0.5 -10.2830205047319 -1.34762760103096
+5.18 -9.91 0.5 -10.296320754717 -1.312477750089
+5.19 -9.905 0.5 -10.3092711598746 -1.27765794361297
+5.2 -9.9 0.5 -10.321875 -1.2431640625
+5.21 -9.895 0.5 -10.3341355140187 -1.20899205170757
+5.22 -9.89 0.5 -10.3460559006211 -1.17513791906177
+5.23 -9.885 0.5 -10.3576393188855 -1.14159773409119
+5.24 -9.88 0.5 -10.3688888888889 -1.10836762688614
+5.25 -9.875 0.5 -10.3798076923077 -1.07544378698225
+5.26 -9.87 0.5 -10.3903987730061 -1.04282246226806
+5.27 -9.865 0.5 -10.4006651376147 -1.010499957916
+5.28 -9.86 0.5 -10.4106097560976 -0.978472635336108
+5.29 -9.855 0.5 -10.42023556231 -0.946736911151967
+5.3 -9.85 0.5 -10.4295454545455 -0.915289256198347
+5.31 -9.845 0.5 -10.4385422960725 -0.884126194540029
+5.32 -9.84 0.5 -10.4472289156627 -0.853244302511249
+5.33 -9.835 0.5 -10.4556081081081 -0.822640207775343
+5.34 -9.83 0.5 -10.4636826347305 -0.79231058840403
+5.35 -9.825 0.5 -10.4714552238806 -0.762252171975942
+5.36 -9.82 0.5 -10.4789285714286 -0.732461734693877
+5.37 -9.815 0.5 -10.4861053412463 -0.702936100520388
+5.38 -9.81 0.5 -10.4929881656805 -0.673672140331221
+5.39 -9.805 0.5 -10.4995796460177 -0.644666771086225
+5.4 -9.8 0.5 -10.5058823529412 -0.6159169550173
+5.41 -9.795 0.5 -10.5118988269795 -0.587419698832999
+5.42 -9.79 0.5 -10.5176315789474 -0.559172052939366
+5.43 -9.785 0.5 -10.523083090379 -0.531171110676675
+5.44 -9.78 0.5 -10.5282558139535 -0.503414007571659
+5.45 -9.775 0.5 -10.533152173913 -0.475897920604915
+5.46 -9.77 0.5 -10.537774566474 -0.448620067493067
+5.47 -9.765 0.5 -10.5421253602305 -0.421577705985434
+5.48 -9.76 0.5 -10.5462068965517 -0.394768133174791
+5.49 -9.755 0.5 -10.5500214899713 -0.368188684821963
+5.5 -9.75 0.5 -10.5535714285714 -0.341836734693878
+5.51 -9.745 0.5 -10.556858974359 -0.315709693914823
+5.52 -9.74 0.5 -10.5598863636364 -0.28980501033058
+5.53 -9.735 0.5 -10.5626558073654 -0.264120167885144
+5.54 -9.73 0.5 -10.5651694915254 -0.238652686009767
+5.55 -9.725 0.5 -10.5674295774648 -0.213400119024003
+5.56 -9.72 0.5 -10.5694382022472 -0.18836005554854
+5.57 -9.715 0.5 -10.5711974789916 -0.163530117929524
+5.58 -9.71 0.5 -10.5727094972067 -0.138907961674105
+5.59 -9.705 0.5 -10.5739763231198 -0.114491274896998
+5.6 -9.7 0.5 -10.575 -0.0902777777777785
+5.61 -9.695 0.5 -10.5757825484765 -0.0662652220286822
+5.62 -9.69 0.5 -10.5763259668508 -0.0424513903726988
+5.63 -9.685 0.5 -10.576632231405 -0.0188340960316921
+5.64 -9.68 0.5 -10.5767032967033 0.00458881777563031
+5.65 -9.675 0.5 -10.5765410958904 0.0278194783261407
+5.66 -9.67 0.5 -10.5761475409836 0.0508599838753027
+5.67 -9.665 0.5 -10.5755245231608 0.0737124041309979
+5.68 -9.66 0.5 -10.5746739130435 0.0963787807183358
+5.69 -9.655 0.5 -10.5735975609756 0.118861127635668
+5.7 -9.65 0.5 -10.5722972972973 0.141161431701973
+5.71 -9.645 0.5 -10.5707749326146 0.163281652995837
+5.72 -9.64 0.5 -10.5690322580645 0.18522372528616
+5.73 -9.635 0.5 -10.5670710455764 0.206989556454802
+5.74 -9.63 0.5 -10.5648930481283 0.228581028911322
+5.75 -9.625 0.5 -10.5625 0.25
+5.76 -9.62 0.5 -10.5598936170213 0.271248302399275
+5.77 -9.615 0.5 -10.557075596817 0.292327744513786
+5.78 -9.61 0.5 -10.5540476190476 0.313240110859159
+5.79 -9.605 0.5 -10.5508113456464 0.333987162439693
+5.8 -9.6 0.5 -10.5473684210526 0.354570637119113
+5.81 -9.595 0.5 -10.5437204724409 0.374992249984501
+5.82 -9.59 0.5 -10.5398691099476 0.395253693703572
+5.83 -9.585 0.5 -10.535815926893 0.415356638875444
+5.84 -9.58 0.5 -10.5315625 0.435302734375
+5.85 -9.575 0.5 -10.5271103896104 0.45509360769101
+5.86 -9.57 0.5 -10.5224611398964 0.474730865258128
+5.87 -9.565 0.5 -10.5176162790698 0.494216092782886
+5.88 -9.56 0.5 -10.5125773195876 0.513550855563822
+5.89 -9.555 0.5 -10.5073457583548 0.532736698805849
+5.9 -9.55 0.5 -10.5019230769231 0.551775147928995
+5.91 -9.545 0.5 -10.496310741688 0.570667708871606
+5.92 -9.54 0.5 -10.4905102040816 0.589415868388171
+5.93 -9.535 0.5 -10.4845229007634 0.608021094341821
+5.94 -9.53 0.5 -10.4783502538071 0.626484835991652
+5.95 -9.525 0.5 -10.4719936708861 0.644808524274956
+5.96 -9.52 0.5 -10.4654545454545 0.662993572084481
+5.97 -9.515 0.5 -10.458734256927 0.681041374540794
+5.98 -9.51 0.5 -10.4518341708543 0.698953309259868
+5.99 -9.505 0.5 -10.4447556390977 0.716730736615976
+6 -9.5 0.5 -10.4375 0.734375
+6.01 -9.495 0.5 -10.4300685785536 0.751887426073221
+6.02 -9.49 0.5 -10.4224626865672 0.769269325016707
+6.03 -9.485 0.5 -10.4146836228288 0.786521990776374
+6.04 -9.48 0.5 -10.4067326732673 0.803646701303794
+6.05 -9.475 0.5 -10.3986111111111 0.820644718792866
+6.06 -9.47 0.5 -10.3903201970443 0.837517289912398
+6.07 -9.465 0.5 -10.3818611793612 0.854265646034688
+6.08 -9.46 0.5 -10.3732352941176 0.870891003460208
+6.09 -9.455 0.5 -10.3644437652812 0.887394563638429
+6.1 -9.45 0.5 -10.355487804878 0.903777513384889
+6.11 -9.445 0.5 -10.3463686131387 0.920041025094572
+6.12 -9.44 0.5 -10.3370873786408 0.936186256951645
+6.13 -9.435 0.5 -10.3276452784504 0.952214353135681
+6.14 -9.43 0.5 -10.3180434782609 0.968126444024366
+6.15 -9.425 0.5 -10.3082831325301 0.983923646392801
+6.16 -9.42 0.5 -10.2983653846154 0.999607063609468
+6.17 -9.415 0.5 -10.2882913669065 1.01517778582889
+6.18 -9.41 0.5 -10.2780622009569 1.03063689018109
+6.19 -9.405 0.5 -10.2676789976134 1.04598544095784
+6.2 -9.4 0.5 -10.2571428571429 1.06122448979592
+6.21 -9.395 0.5 -10.2464548693587 1.07635507585717
+6.22 -9.39 0.5 -10.2356161137441 1.0913782260057
+6.23 -9.385 0.5 -10.2246276595745 1.10629495498214
+6.24 -9.38 0.5 -10.2134905660377 1.12110626557494
+6.25 -9.375 0.5 -10.2022058823529 1.13581314878893
+6.26 -9.37 0.5 -10.1907746478873 1.15041658401111
+6.27 -9.365 0.5 -10.1791978922717 1.16491753917369
+6.28 -9.36 0.5 -10.167476635514 1.17931697091449
+6.29 -9.355 0.5 -10.1556118881119 1.19361582473471
+6.3 -9.35 0.5 -10.1436046511628 1.20781503515414
+6.31 -9.345 0.5 -10.1314559164733 1.22191552586388
+6.32 -9.34 0.5 -10.1191666666667 1.23591820987654
+6.33 -9.335 0.5 -10.1067378752887 1.24982398967406
+6.34 -9.33 0.5 -10.0941705069124 1.2636337573531
+6.35 -9.325 0.5 -10.0814655172414 1.27734839476813
+6.36 -9.32 0.5 -10.068623853211 1.29096877367225
+6.37 -9.315 0.5 -10.0556464530892 1.30449575585566
+6.38 -9.31 0.5 -10.0425342465753 1.31793019328204
+6.39 -9.305 0.5 -10.0292881548975 1.33127292822266
+6.4 -9.3 0.5 -10.0159090909091 1.34452479338843
+6.41 -9.295 0.5 -10.0023979591837 1.35768661205979
+6.42 -9.29 0.5 -9.9887556561086 1.37075919821461
+6.43 -9.285 0.5 -9.97498306997743 1.38374335665405
+6.44 -9.28 0.5 -9.96108108108108 1.39663988312637
+6.45 -9.275 0.5 -9.94705056179775 1.40944956444893
+6.46 -9.27 0.5 -9.93289237668161 1.42217317862816
+6.47 -9.265 0.5 -9.91860738255034 1.4348114949777
+6.48 -9.26 0.5 -9.90419642857143 1.44736527423469
+6.49 -9.255 0.5 -9.88966035634744 1.45983526867426
+6.5 -9.25 0.5 -9.875 1.47222222222222
+6.51 -9.245 0.5 -9.86021618625277 1.48452687056602
+6.52 -9.24 0.5 -9.84530973451328 1.496749941264
+6.53 -9.235 0.5 -9.83028145695364 1.5088921538529
+6.54 -9.23 0.5 -9.81513215859031 1.52095421995381
+6.55 -9.225 0.5 -9.79986263736264 1.5329368433764
+6.56 -9.22 0.5 -9.78447368421052 1.54484072022161
+6.57 -9.215 0.5 -9.76896608315098 1.55666653898271
+6.58 -9.21 0.5 -9.75334061135371 1.56841498064492
+6.59 -9.205 0.5 -9.73759803921569 1.58008671878337
+6.6 -9.2 0.5 -9.72173913043478 1.59168241965973
+6.61 -9.195 0.5 -9.70576464208243 1.60320274231723
+6.62 -9.19 0.5 -9.68967532467532 1.61464833867431
+6.63 -9.185 0.5 -9.67347192224622 1.62601985361689
+6.64 -9.18 0.5 -9.65715517241379 1.63731792508918
+6.65 -9.175 0.5 -9.64072580645161 1.64854318418314
+6.66 -9.17 0.5 -9.62418454935622 1.65969625522666
+6.67 -9.165 0.5 -9.60753211991435 1.67077775587031
+6.68 -9.16 0.5 -9.59076923076923 1.68178829717291
+6.69 -9.155 0.5 -9.57389658848614 1.69272848368574
+6.7 -9.15 0.5 -9.55691489361702 1.70359891353554
+6.71 -9.145 0.5 -9.53982484076433 1.71440017850623
+6.72 -9.14 0.5 -9.52262711864407 1.72513286411951
+6.73 -9.135 0.5 -9.50532241014799 1.73579754971416
+6.74 -9.13 0.5 -9.48791139240506 1.74639480852427
+6.75 -9.125 0.5 -9.4703947368421 1.75692520775623
+6.76 -9.12 0.5 -9.4527731092437 1.76738930866464
+6.77 -9.115 0.5 -9.43504716981132 1.77778766662711
+6.78 -9.11 0.5 -9.41721757322176 1.78812083121794
+6.79 -9.105 0.5 -9.39928496868476 1.79838934628074
+6.8 -9.1 0.5 -9.38125 1.80859375
+6.81 -9.095 0.5 -9.3631133056133 1.81873457497158
+6.82 -9.09 0.5 -9.3448755186722 1.82881234827224
+6.83 -9.085 0.5 -9.32653726708075 1.83882759152811
+6.84 -9.08 0.5 -9.30809917355372 1.84878082098217
+6.85 -9.075 0.5 -9.2895618556701 1.85867254756084
+6.86 -9.07 0.5 -9.27092592592593 1.86850327693949
+6.87 -9.065 0.5 -9.25219199178645 1.87827350960707
+6.88 -9.06 0.5 -9.23336065573771 1.88798374092986
+6.89 -9.055 0.5 -9.21443251533742 1.8976344612142
+6.9 -9.05 0.5 -9.19540816326531 1.90722615576843
+6.91 -9.045 0.5 -9.17628818737271 1.91675930496389
+6.92 -9.04 0.5 -9.15707317073171 1.92623438429506
+6.93 -9.035 0.5 -9.13776369168357 1.93565186443886
+6.94 -9.03 0.5 -9.11836032388664 1.94501221131309
+6.95 -9.025 0.5 -9.09886363636364 1.95431588613407
+6.96 -9.02 0.5 -9.07927419354839 1.96356334547346
+6.97 -9.015 0.5 -9.05959255533199 1.97275504131428
+6.98 -9.01 0.5 -9.03981927710843 1.98189142110611
+6.99 -9.005 0.5 -9.01995490981964 1.99097292781957
+7 -9 19 -9 19
+7.01 -8.81 19 -8.97524875954199 2.94774832833166
+7.02 -8.62000000000001 19 -8.94109521988528 3.88044068453433
+7.03 -8.43 19 -8.89769051724138 4.79796158673539
+7.04 -8.24 19 -8.84518694817658 5.70019444372811
+7.05 -8.05 19 -8.78373798076923 6.58702154215975
+7.06 -7.85999999999999 19 -8.71349826589595 7.4583240335461
+7.07 -7.66999999999999 19 -8.63462364864865 8.31398192111032
+7.08 -7.48 19 -8.54727117988394 9.15387404644412
+7.09 -7.29 19 -8.45159912790698 9.97787807598701
+7.1 -7.10000000000001 19 -8.34776699029127 10.7858704873221
+7.11 -6.91000000000001 19 -8.23593550583658 11.5777265552847
+7.12 -6.72 19 -8.11626666666666 12.3533203378818
+7.13 -6.53 19 -7.98892373046875 13.1125246620178
+7.14 -6.33999999999999 19 -7.8540712328767 13.8552111090261
+7.15 -6.14999999999999 19 -7.71187499999999 14.58125
+7.16 -5.96 19 -7.56250216110019 15.2905103809234
+7.17 -5.77 19 -7.40612116141732 15.982860007595
+7.18 -5.58000000000001 19 -7.24290177514793 16.6581653303456
+7.19 -5.39000000000001 19 -7.07301511857708 17.316291478542
+7.2 -5.2 19 -6.89663366336633 17.957102244878
+7.21 -5.01 19 -6.71393125 18.5804600694444
+7.22 -4.81999999999999 19 -6.52508310139164 19.1862260235802
+7.23 -4.62999999999999 19 -6.33026583665338 19.7742597934954
+7.24 -4.44 19 -6.12965748502994 20.3444196636667
+7.25 -4.25 19 -5.9234375 20.8965625
+7.26 -4.06 19 -5.7117867735471 21.4305437327561
+7.27 -3.87000000000001 19 -5.49488765060242 21.9462173392364
+7.28 -3.68 19 -5.27292394366197 22.443435826225
+7.29 -3.49 19 -5.04608094758064 22.9220502121813
+7.3 -3.29999999999999 19 -4.81454545454544 23.3819100091828
+7.31 -3.10999999999999 19 -4.57850576923076 23.8228632046092
+7.32 -2.91999999999999 19 -4.33815172413792 24.2447562425684
+7.33 -2.73 19 -4.09367469512195 24.6474340050565
+7.34 -2.54 19 -3.84526761710795 25.0307397928497
+7.35 -2.35000000000001 19 -3.59312500000001 25.3945153061224
+7.36 -2.16000000000001 19 -3.33744294478529 25.7386006247883
+7.37 -1.97 19 -3.07841915983606 26.0628341885582
+7.38 -1.78 19 -2.81625297741273 26.367052776712
+7.39 -1.58999999999999 19 -2.55114537037036 26.6510914875781
+7.4 -1.39999999999999 19 -2.28329896907216 26.9147837177171
+7.41 -1.21 19 -2.01291807851239 27.1579611408032
+7.42 -1.02 19 -1.74020869565218 27.3804536862004
+7.43 -0.830000000000005 19 -1.46537852697096 27.5820895172259
+7.44 -0.640000000000009 19 -1.18863700623702 27.7626950090983
+7.45 -0.449999999999996 19 -0.910195312499994 27.9220947265625
+7.46 -0.260000000000002 19 -0.630266388308979 28.0601114011881
+7.47 -0.0699999999999878 19 -0.349064958158978 28.1765659083349
+7.48 0.120000000000008 19 -0.0668075471697993 28.2712772437799
+7.49 0.310000000000004 19 0.216287500000006 28.3440625
+7.5 0.5 19 0.5 28.3947368421053
+7.51 0.689999999999996 19 0.784107911392399 28.4231134834161
+7.52 0.879999999999992 19 1.06838731501056 28.4290036606788
+7.53 1.07 19 1.3526123940678 28.4122166089127
+7.54 1.26 19 1.63655541401274 28.3725595358838
+7.55 1.45000000000001 19 1.91998670212768 28.3098375961974
+7.56 1.64000000000001 19 2.20267462686569 28.2238538650033
+7.57 1.83000000000001 19 2.48438557692308 28.1144093113083
+7.58 2.02 19 2.76488394004283 27.9813027708871
+7.59 2.21 19 3.04393208154506 27.8243309187865
+7.6 2.39999999999999 19 3.32129032258064 27.6432882414152
+7.61 2.58999999999999 19 3.59671691810343 27.437967008212
+7.62 2.78 19 3.86996803455724 27.2081572428849
+7.63 2.97 19 4.14079772727272 26.9536466942149
+7.64 3.16000000000001 19 4.40895791757051 26.6742208064144
+7.65 3.35000000000001 19 4.67419836956523 26.3696626890359
+7.66 3.54 19 4.93626666666667 26.0397530864198
+7.67 3.73 19 5.19490818777292 25.6842703466753
+7.68 3.91999999999999 19 5.44986608315098 25.3029903901862
+7.69 4.10999999999999 19 5.70088124999999 24.8956866776316
+7.7 4.3 19 5.94769230769231 24.4621301775148
+7.71 4.49 19 6.19003557268722 24.002089333191
+7.72 4.68000000000001 19 6.4276450331126 23.5153300293846
+7.73 4.87000000000001 19 6.66025232300886 23.0016155581878
+7.74 5.06 19 6.8875866962306 22.4607065845301
+7.75 5.25 19 7.109375 21.8923611111111
+7.76 5.44 19 7.3253416481069 21.2963344427855
+7.77 5.62999999999999 19 7.53520859374999 20.6723791503907
+7.78 5.82 19 7.73869530201343 20.0202450340075
+7.79 6.01 19 7.9355187219731 19.3396790856442
+7.8 6.20000000000001 19 8.12539325842698 18.6304254513319
+7.81 6.39000000000001 19 8.30803074324325 17.8922253926223
+7.82 6.58000000000001 19 8.48314040632055 17.1248172474764
+7.83 6.77 19 8.65042884615385 16.3279363905325
+7.84 6.96 19 8.8096 15.5013151927438
+7.85 7.14999999999999 19 8.96035511363636 14.6446829803719
+7.86 7.33999999999999 19 9.10239271070614 13.7577659933272
+7.87 7.53 19 9.23540856164384 12.8402873428411
+7.88 7.72 19 9.35909565217391 11.8919669684609
+7.89 7.91000000000001 19 9.47314415137615 10.9125215943523
+7.9 8.10000000000001 19 9.57724137931035 9.90166468489889
+7.91 8.29 19 9.67107177419355 8.85910639958375
+7.92 8.48 19 9.7543168591224 7.78455354714145
+7.93 8.66999999999999 19 9.82665520833333 6.67770953896608
+7.94 8.85999999999999 19 9.88776241299304 5.53827434176178
+7.95 9.05 19 9.93731104651163 4.36594442942129
+7.96 9.24 19 9.97497062937063 3.16041273411904
+7.97 9.43000000000001 19 10.0004075934579 1.92136859660224
+7.98 9.62000000000001 19 10.0132852459016 0.648497715667776
+7.99 9.81 19 10.0132637323944 -0.658517903193836
+8 10 0 10 0
+8.01 10 0 9.98005 -1.99
+8.02 10 0 9.9602 -1.98
+8.03 10 0 9.94045 -1.97
+8.04 10 0 9.9208 -1.96
+8.05 10 0 9.90125 -1.95
+8.06 10 0 9.8818 -1.94
+8.07 10 0 9.86245 -1.93
+8.08 10 0 9.8432 -1.92
+8.09 10 0 9.82405 -1.91
+8.1 10 0 9.805 -1.9
+8.11 10 0 9.78605 -1.89
+8.12 10 0 9.7672 -1.88
+8.13 10 0 9.74845 -1.87
+8.14 10 0 9.7298 -1.86
+8.15 10 0 9.71125 -1.85
+8.16 10 0 9.6928 -1.84
+8.17 10 0 9.67445 -1.83
+8.18 10 0 9.6562 -1.82
+8.19 10 0 9.63805 -1.81
+8.2 10 0 9.62 -1.8
+8.21 10 0 9.60205 -1.79
+8.22 10 0 9.5842 -1.78
+8.23 10 0 9.56645 -1.77
+8.24 10 0 9.5488 -1.76
+8.25 10 0 9.53125 -1.75
+8.26 10 0 9.5138 -1.74
+8.27 10 0 9.49645 -1.73
+8.28 10 0 9.4792 -1.72
+8.29 10 0 9.46205 -1.71
+8.3 10 0 9.445 -1.7
+8.31 10 0 9.42805 -1.69
+8.32 10 0 9.4112 -1.68
+8.33 10 0 9.39445 -1.67
+8.34 10 0 9.3778 -1.66
+8.35 10 0 9.36125 -1.65
+8.36 10 0 9.3448 -1.64
+8.37 10 0 9.32845 -1.63
+8.38 10 0 9.3122 -1.62
+8.39 10 0 9.29605 -1.61
+8.4 10 0 9.28 -1.6
+8.41 10 0 9.26405 -1.59
+8.42 10 0 9.2482 -1.58
+8.43 10 0 9.23245 -1.57
+8.44 10 0 9.2168 -1.56
+8.45 10 0 9.20125 -1.55
+8.46 10 0 9.1858 -1.54
+8.47 10 0 9.17045 -1.53
+8.48 10 0 9.1552 -1.52
+8.49 10 0 9.14005 -1.51
+8.5 10 0 9.125 -1.5
+8.51 10 0 9.11005 -1.49
+8.52 10 0 9.0952 -1.48
+8.53 10 0 9.08045 -1.47
+8.54 10 0 9.0658 -1.46
+8.55 10 0 9.05125 -1.45
+8.56 10 0 9.0368 -1.44
+8.57 10 0 9.02245 -1.43
+8.58 10 0 9.0082 -1.42
+8.59 10 0 8.99405 -1.41
+8.6 10 0 8.98 -1.4
+8.61 10 0 8.96605 -1.39
+8.62 10 0 8.9522 -1.38
+8.63 10 0 8.93845 -1.37
+8.64 10 0 8.9248 -1.36
+8.65 10 0 8.91125 -1.35
+8.66 10 0 8.8978 -1.34
+8.67 10 0 8.88445 -1.33
+8.68 10 0 8.8712 -1.32
+8.69 10 0 8.85805 -1.31
+8.7 10 0 8.845 -1.3
+8.71 10 0 8.83205 -1.29
+8.72 10 0 8.8192 -1.28
+8.73 10 0 8.80645 -1.27
+8.74 10 0 8.7938 -1.26
+8.75 10 0 8.78125 -1.25
+8.76 10 0 8.7688 -1.24
+8.77 10 0 8.75645 -1.23
+8.78 10 0 8.7442 -1.22
+8.79 10 0 8.73205 -1.21
+8.8 10 0 8.72 -1.2
+8.81 10 0 8.70805 -1.19
+8.82 10 0 8.6962 -1.18
+8.83 10 0 8.68445 -1.17
+8.84 10 0 8.6728 -1.16
+8.85 10 0 8.66125 -1.15
+8.86 10 0 8.6498 -1.14
+8.87 10 0 8.63845 -1.13
+8.88 10 0 8.6272 -1.12
+8.89 10 0 8.61605 -1.11
+8.9 10 0 8.605 -1.1
+8.91 10 0 8.59405 -1.09
+8.92 10 0 8.5832 -1.08
+8.93 10 0 8.57245 -1.07
+8.94 10 0 8.5618 -1.06
+8.95 10 0 8.55125 -1.05
+8.96 10 0 8.5408 -1.04
+8.97 10 0 8.53045 -1.03
+8.98 10 0 8.5202 -1.02
+8.99 10 0 8.51005 -1.01
+9 10 0 8.5 -1
+9.01 10 0 8.49005 -0.99
+9.02 10 0 8.4802 -0.98
+9.03 10 0 8.47045 -0.969999999999999
+9.04 10 0 8.4608 -0.960000000000001
+9.05 10 0 8.45125 -0.949999999999999
+9.06 10 0 8.4418 -0.94
+9.07 10 0 8.43245 -0.93
+9.08 10 0 8.4232 -0.92
+9.09 10 0 8.41405 -0.91
+9.1 10 0 8.405 -0.9
+9.11 10 0 8.39605 -0.890000000000001
+9.12 10 0 8.3872 -0.879999999999999
+9.13 10 0 8.37845 -0.870000000000001
+9.14 10 0 8.3698 -0.859999999999999
+9.15 10 0 8.36125 -0.85
+9.16 10 0 8.3528 -0.84
+9.17 10 0 8.34445 -0.83
+9.18 10 0 8.3362 -0.82
+9.19 10 0 8.32805 -0.809999999999999
+9.2 10 0 8.32 -0.800000000000001
+9.21 10 0 8.31205 -0.789999999999999
+9.22 10 0 8.3042 -0.780000000000001
+9.23 10 0 8.29645 -0.77
+9.24 10 0 8.2888 -0.76
+9.25 10 0 8.28125 -0.75
+9.26 10 0 8.2738 -0.74
+9.27 10 0 8.26645 -0.73
+9.28 10 0 8.2592 -0.719999999999999
+9.29 10 0 8.25205 -0.710000000000001
+9.3 10 0 8.245 -0.699999999999999
+9.31 10 0 8.23805 -0.69
+9.32 10 0 8.2312 -0.68
+9.33 10 0 8.22445 -0.67
+9.34 10 0 8.2178 -0.66
+9.35 10 0 8.21125 -0.649999999999999
+9.36 10 0 8.2048 -0.640000000000001
+9.37 10 0 8.19845 -0.629999999999999
+9.38 10 0 8.1922 -0.620000000000001
+9.39 10 0 8.18605 -0.609999999999999
+9.4 10 0 8.18 -0.6
+9.41 10 0 8.17405 -0.59
+9.42 10 0 8.1682 -0.58
+9.43 10 0 8.16245 -0.57
+9.44 10 0 8.1568 -0.559999999999999
+9.45 10 0 8.15125 -0.550000000000001
+9.46 10 0 8.1458 -0.539999999999999
+9.47 10 0 8.14045 -0.530000000000001
+9.48 10 0 8.1352 -0.52
+9.49 10 0 8.13005 -0.51
+9.5 10 0 8.125 -0.5
+9.51 10 0 8.12005 -0.49
+9.52 10 0 8.1152 -0.48
+9.53 10 0 8.11045 -0.469999999999999
+9.54 10 0 8.1058 -0.460000000000001
+9.55 10 0 8.10125 -0.449999999999999
+9.56 10 0 8.0968 -0.44
+9.57 10 0 8.09245 -0.43
+9.58 10 0 8.0882 -0.42
+9.59 10 0 8.08405 -0.41
+9.6 10 0 8.08 -0.399999999999999
+9.61 10 0 8.07605 -0.390000000000001
+9.62 10 0 8.0722 -0.379999999999999
+9.63 10 0 8.06845 -0.370000000000001
+9.64 10 0 8.0648 -0.359999999999999
+9.65 10 0 8.06125 -0.35
+9.66 10 0 8.0578 -0.34
+9.67 10 0 8.05445 -0.33
+9.68 10 0 8.0512 -0.32
+9.69 10 0 8.04805 -0.309999999999999
+9.7 10 0 8.045 -0.300000000000001
+9.71 10 0 8.04205 -0.289999999999999
+9.72 10 0 8.0392 -0.280000000000001
+9.73 10 0 8.03645 -0.27
+9.74 10 0 8.0338 -0.26
+9.75 10 0 8.03125 -0.25
+9.76 10 0 8.0288 -0.24
+9.77 10 0 8.02645 -0.23
+9.78 10 0 8.0242 -0.219999999999999
+9.79 10 0 8.02205 -0.210000000000001
+9.8 10 0 8.02 -0.199999999999999
+9.81 10 0 8.01805 -0.19
+9.82 10 0 8.0162 -0.18
+9.83 10 0 8.01445 -0.17
+9.84 10 0 8.0128 -0.16
+9.85 10 0 8.01125 -0.149999999999999
+9.86 10 0 8.0098 -0.140000000000001
+9.87 10 0 8.00845 -0.129999999999999
+9.88 10 0 8.0072 -0.120000000000001
+9.89 10 0 8.00605 -0.109999999999999
+9.9 10 0 8.005 -0.0999999999999996
+9.91 10 0 8.00405 -0.0899999999999999
+9.92 10 0 8.0032 -0.0800000000000001
+9.93 10 0 8.00245 -0.0700000000000003
+9.94 10 0 8.0018 -0.0599999999999987
+9.95 10 0 8.00125 -0.0500000000000007
+9.96 10 0 8.0008 -0.0399999999999991
+9.97 10 0 8.00045 -0.0300000000000011
+9.98 10 0 8.0002 -0.0199999999999996
+9.99 10 0 8.00005 -0.00999999999999979
+10 10 0 8 0
+10.01 10 0 8.00005 0.00999999999999979
+10.02 10 0 8.0002 0.0199999999999996
+10.03 10 0 8.00045 0.0300000000000011
+10.04 10 0 8.0008 0.0399999999999991
+10.05 10 0 8.00125 0.0500000000000007
+10.06 10 0 8.0018 0.0600000000000005
+10.07 10 0 8.00245 0.0700000000000003
+10.08 10 0 8.0032 0.0800000000000001
+10.09 10 0 8.00405 0.0899999999999999
+10.1 10 0 8.005 0.100000000000001
+10.11 10 0 8.00605 0.109999999999999
+10.12 10 0 8.0072 0.120000000000001
+10.13 10 0 8.00845 0.129999999999999
+10.14 10 0 8.0098 0.140000000000001
+10.15 10 0 8.01125 0.15
+10.16 10 0 8.0128 0.16
+10.17 10 0 8.01445 0.17
+10.18 10 0 8.0162 0.18
+10.19 10 0 8.01805 0.190000000000001
+10.2 10 0 8.02 0.199999999999999
+10.21 10 0 8.02205 0.210000000000001
+10.22 10 0 8.0242 0.219999999999999
+10.23 10 0 8.02645 0.23
+10.24 10 0 8.0288 0.24
+10.25 10 0 8.03125 0.25
+10.26 10 0 8.0338 0.26
+10.27 10 0 8.03645 0.27
+10.28 10 0 8.0392 0.280000000000001
+10.29 10 0 8.04205 0.289999999999999
+10.3 10 0 8.045 0.300000000000001
+10.31 10 0 8.04805 0.31
+10.32 10 0 8.0512 0.32
+10.33 10 0 8.05445 0.33
+10.34 10 0 8.0578 0.34
+10.35 10 0 8.06125 0.350000000000001
+10.36 10 0 8.0648 0.359999999999999
+10.37 10 0 8.06845 0.370000000000001
+10.38 10 0 8.0722 0.379999999999999
+10.39 10 0 8.07605 0.390000000000001
+10.4 10 0 8.08 0.4
+10.41 10 0 8.08405 0.41
+10.42 10 0 8.0882 0.42
+10.43 10 0 8.09245 0.43
+10.44 10 0 8.0968 0.440000000000001
+10.45 10 0 8.10125 0.449999999999999
+10.46 10 0 8.1058 0.460000000000001
+10.47 10 0 8.11045 0.469999999999999
+10.48 10 0 8.1152 0.48
+10.49 10 0 8.12005 0.49
+10.5 10 0 8.125 0.5
+10.51 10 0 8.13005 0.51
+10.52 10 0 8.1352 0.52
+10.53 10 0 8.14045 0.530000000000001
+10.54 10 0 8.1458 0.539999999999999
+10.55 10 0 8.15125 0.550000000000001
+10.56 10 0 8.1568 0.56
+10.57 10 0 8.16245 0.57
+10.58 10 0 8.1682 0.58
+10.59 10 0 8.17405 0.59
+10.6 10 0 8.18 0.600000000000001
+10.61 10 0 8.18605 0.609999999999999
+10.62 10 0 8.1922 0.620000000000001
+10.63 10 0 8.19845 0.629999999999999
+10.64 10 0 8.2048 0.640000000000001
+10.65 10 0 8.21125 0.65
+10.66 10 0 8.2178 0.66
+10.67 10 0 8.22445 0.67
+10.68 10 0 8.2312 0.68
+10.69 10 0 8.23805 0.690000000000001
+10.7 10 0 8.245 0.699999999999999
+10.71 10 0 8.25205 0.710000000000001
+10.72 10 0 8.2592 0.719999999999999
+10.73 10 0 8.26645 0.73
+10.74 10 0 8.2738 0.74
+10.75 10 0 8.28125 0.75
+10.76 10 0 8.2888 0.76
+10.77 10 0 8.29645 0.77
+10.78 10 0 8.3042 0.780000000000001
+10.79 10 0 8.31205 0.789999999999999
+10.8 10 0 8.32 0.800000000000001
+10.81 10 0 8.32805 0.81
+10.82 10 0 8.3362 0.82
+10.83 10 0 8.34445 0.83
+10.84 10 0 8.3528 0.84
+10.85 10 0 8.36125 0.850000000000001
+10.86 10 0 8.3698 0.859999999999999
+10.87 10 0 8.37845 0.870000000000001
+10.88 10 0 8.3872 0.879999999999999
+10.89 10 0 8.39605 0.890000000000001
+10.9 10 0 8.405 0.9
+10.91 10 0 8.41405 0.91
+10.92 10 0 8.4232 0.92
+10.93 10 0 8.43245 0.93
+10.94 10 0 8.4418 0.940000000000001
+10.95 10 0 8.45125 0.949999999999999
+10.96 10 0 8.4608 0.960000000000001
+10.97 10 0 8.47045 0.969999999999999
+10.98 10 0 8.4802 0.98
+10.99 10 0 8.49005 0.99
+11 10 0 8.5 1
+11.01 10 0 8.51005 1.01
+11.02 10 0 8.5202 1.02
+11.03 10 0 8.53045 1.03
+11.04 10 0 8.5408 1.04
+11.05 10 0 8.55125 1.05
+11.06 10 0 8.5618 1.06
+11.07 10 0 8.57245 1.07
+11.08 10 0 8.5832 1.08
+11.09 10 0 8.59405 1.09
+11.1 10 0 8.605 1.1
+11.11 10 0 8.61605 1.11
+11.12 10 0 8.6272 1.12
+11.13 10 0 8.63845 1.13
+11.14 10 0 8.6498 1.14
+11.15 10 0 8.66125 1.15
+11.16 10 0 8.6728 1.16
+11.17 10 0 8.68445 1.17
+11.18 10 0 8.6962 1.18
+11.19 10 0 8.70805 1.19
+11.2 10 0 8.72 1.2
+11.21 10 0 8.73205 1.21
+11.22 10 0 8.7442 1.22
+11.23 10 0 8.75645 1.23
+11.24 10 0 8.7688 1.24
+11.25 10 0 8.78125 1.25
+11.26 10 0 8.7938 1.26
+11.27 10 0 8.80645 1.27
+11.28 10 0 8.8192 1.28
+11.29 10 0 8.83205 1.29
+11.3 10 0 8.845 1.3
+11.31 10 0 8.85805 1.31
+11.32 10 0 8.8712 1.32
+11.33 10 0 8.88445 1.33
+11.34 10 0 8.8978 1.34
+11.35 10 0 8.91125 1.35
+11.36 10 0 8.9248 1.36
+11.37 10 0 8.93845 1.37
+11.38 10 0 8.9522 1.38
+11.39 10 0 8.96605 1.39
+11.4 10 0 8.98 1.4
+11.41 10 0 8.99405 1.41
+11.42 10 0 9.0082 1.42
+11.43 10 0 9.02245 1.43
+11.44 10 0 9.0368 1.44
+11.45 10 0 9.05125 1.45
+11.46 10 0 9.0658 1.46
+11.47 10 0 9.08045 1.47
+11.48 10 0 9.0952 1.48
+11.49 10 0 9.11005 1.49
+11.5 10 0 9.125 1.5
+11.51 10 0 9.14005 1.51
+11.52 10 0 9.1552 1.52
+11.53 10 0 9.17045 1.53
+11.54 10 0 9.1858 1.54
+11.55 10 0 9.20125 1.55
+11.56 10 0 9.2168 1.56
+11.57 10 0 9.23245 1.57
+11.58 10 0 9.2482 1.58
+11.59 10 0 9.26405 1.59
+11.6 10 0 9.28 1.6
+11.61 10 0 9.29605 1.61
+11.62 10 0 9.3122 1.62
+11.63 10 0 9.32845 1.63
+11.64 10 0 9.3448 1.64
+11.65 10 0 9.36125 1.65
+11.66 10 0 9.3778 1.66
+11.67 10 0 9.39445 1.67
+11.68 10 0 9.4112 1.68
+11.69 10 0 9.42805 1.69
+11.7 10 0 9.445 1.7
+11.71 10 0 9.46205 1.71
+11.72 10 0 9.4792 1.72
+11.73 10 0 9.49645 1.73
+11.74 10 0 9.5138 1.74
+11.75 10 0 9.53125 1.75
+11.76 10 0 9.5488 1.76
+11.77 10 0 9.56645 1.77
+11.78 10 0 9.5842 1.78
+11.79 10 0 9.60205 1.79
+11.8 10 0 9.62 1.8
+11.81 10 0 9.63805 1.81
+11.82 10 0 9.6562 1.82
+11.83 10 0 9.67445 1.83
+11.84 10 0 9.6928 1.84
+11.85 10 0 9.71125 1.85
+11.86 10 0 9.7298 1.86
+11.87 10 0 9.74845 1.87
+11.88 10 0 9.7672 1.88
+11.89 10 0 9.78605 1.89
+11.9 10 0 9.805 1.9
+11.91 10 0 9.82405 1.91
+11.92 10 0 9.8432 1.92
+11.93 10 0 9.86245 1.93
+11.94 10 0 9.8818 1.94
+11.95 10 0 9.90125 1.95
+11.96 10 0 9.9208 1.96
+11.97 10 0 9.94045 1.97
+11.98 10 0 9.9602 1.98
+11.99 10 0 9.98005 1.99
+12 10 0.666666666666667 10 0.666666666666667
+12.01 10.0066666666667 0.666666666666667 10.0199777406789 1.99554441970154
+12.02 10.0133333333333 0.666666666666667 10.0399108138239 1.99106646830945
+12.03 10.02 0.666666666666667 10.0597989949749 1.98656599580819
+12.04 10.0266666666667 0.666666666666667 10.0796420581655 1.98204285092263
+12.05 10.0333333333333 0.666666666666667 10.0994397759104 1.97749688110538
+12.06 10.04 0.666666666666667 10.1191919191919 1.97292793252389
+12.07 10.0466666666667 0.666666666666667 10.138898257448 1.96833585004744
+12.08 10.0533333333333 0.666666666666667 10.1585585585586 1.96372047723399
+12.09 10.06 0.666666666666667 10.1781725888325 1.95908165631683
+12.1 10.0666666666667 0.666666666666667 10.1977401129944 1.95441922819113
+12.11 10.0733333333333 0.666666666666667 10.2172608941709 1.94973303240027
+12.12 10.08 0.666666666666667 10.2367346938776 1.94502290712203
+12.13 10.0866666666667 0.666666666666667 10.2561612720045 1.94028868915466
+12.14 10.0933333333333 0.666666666666667 10.2755403868032 1.9355302139027
+12.15 10.1 0.666666666666667 10.2948717948718 1.9307473153627
+12.16 10.1066666666667 0.666666666666667 10.3141552511416 1.92593982610871
+12.17 10.1133333333333 0.666666666666667 10.3333905088622 1.92110757727768
+12.18 10.12 0.666666666666667 10.3525773195876 1.91625039855458
+12.19 10.1266666666667 0.666666666666667 10.3717154331612 1.91136811815741
+12.2 10.1333333333333 0.666666666666667 10.3908045977011 1.90646056282204
+12.21 10.14 0.666666666666667 10.4098445595855 1.90152755778679
+12.22 10.1466666666667 0.666666666666667 10.4288350634371 1.8965689267769
+12.23 10.1533333333333 0.666666666666667 10.4477758521086 1.89158449198878
+12.24 10.16 0.666666666666667 10.4666666666667 1.88657407407407
+12.25 10.1666666666667 0.666666666666667 10.4855072463768 1.8815374921235
+12.26 10.1733333333333 0.666666666666667 10.5042973286876 1.87647456365056
+12.27 10.18 0.666666666666667 10.5230366492147 1.87138510457498
+12.28 10.1866666666667 0.666666666666667 10.5417249417249 1.86626892920599
+12.29 10.1933333333333 0.666666666666667 10.5603619381203 1.86112585022538
+12.3 10.2 0.666666666666667 10.5789473684211 1.85595567867036
+12.31 10.2066666666667 0.666666666666667 10.5974809607499 1.8507582239162
+12.32 10.2133333333333 0.666666666666667 10.6159624413146 1.84553329365867
+12.33 10.22 0.666666666666667 10.6343915343915 1.84028069389621
+12.34 10.2266666666667 0.666666666666667 10.6527679623086 1.835000228912
+12.35 10.2333333333333 0.666666666666667 10.6710914454277 1.82969170125564
+12.36 10.24 0.666666666666667 10.6893617021277 1.82435491172476
+12.37 10.2466666666667 0.666666666666667 10.7075784487863 1.81898965934629
+12.38 10.2533333333333 0.666666666666667 10.7257413997628 1.81359574135755
+12.39 10.26 0.666666666666667 10.7438502673797 1.80817295318711
+12.4 10.2666666666667 0.666666666666667 10.7619047619048 1.80272108843537
+12.41 10.2733333333333 0.666666666666667 10.7799045915325 1.79723993885495
+12.42 10.28 0.666666666666667 10.7978494623656 1.79172929433075
+12.43 10.2866666666667 0.666666666666667 10.8157390783962 1.78618894285988
+12.44 10.2933333333333 0.666666666666667 10.8335731414868 1.7806186705312
+12.45 10.3 0.666666666666667 10.8513513513514 1.77501826150475
+12.46 10.3066666666667 0.666666666666667 10.8690734055355 1.76938749799076
+12.47 10.3133333333333 0.666666666666667 10.8867389993972 1.76372616022855
+12.48 10.32 0.666666666666667 10.904347826087 1.75803402646503
+12.49 10.3266666666667 0.666666666666667 10.9218995765275 1.75231087293301
+12.5 10.3333333333333 0.666666666666667 10.9393939393939 1.7465564738292
+12.51 10.34 0.666666666666667 10.9568306010929 1.74077060129197
+12.52 10.3466666666667 0.666666666666667 10.9742092457421 1.73495302537873
+12.53 10.3533333333333 0.666666666666667 10.9915295551493 1.72910351404314
+12.54 10.36 0.666666666666667 11.0087912087912 1.72322183311194
+12.55 10.3666666666667 0.666666666666667 11.0259938837921 1.71730774626154
+12.56 10.3733333333333 0.666666666666667 11.043137254902 1.71136101499423
+12.57 10.38 0.666666666666667 11.0602209944751 1.70538139861421
+12.58 10.3866666666667 0.666666666666667 11.0772447724477 1.69936865420315
+12.59 10.3933333333333 0.666666666666667 11.0942082563155 1.69332253659559
+12.6 10.4 0.666666666666667 11.1111111111111 1.68724279835391
+12.61 10.4066666666667 0.666666666666667 11.1279529993816 1.68112918974303
+12.62 10.4133333333333 0.666666666666667 11.1447335811648 1.67498145870473
+12.63 10.42 0.666666666666667 11.1614525139665 1.66879935083175
+12.64 10.4266666666667 0.666666666666667 11.1781094527363 1.66258260934135
+12.65 10.4333333333333 0.666666666666667 11.1947040498442 1.65633097504877
+12.66 10.44 0.666666666666667 11.2112359550562 1.65004418634011
+12.67 10.4466666666667 0.666666666666667 11.2277048155097 1.64372197914503
+12.68 10.4533333333333 0.666666666666667 11.2441102756892 1.637364086909
+12.69 10.46 0.666666666666667 11.2604519774011 1.63097024056518
+12.7 10.4666666666667 0.666666666666667 11.2767295597484 1.62454016850599
+12.71 10.4733333333333 0.666666666666667 11.2929426591052 1.61807359655423
+12.72 10.48 0.666666666666667 11.3090909090909 1.61157024793388
+12.73 10.4866666666667 0.666666666666667 11.325173940544 1.60502984324047
+12.74 10.4933333333333 0.666666666666667 11.3411913814956 1.59845210041107
+12.75 10.5 0.666666666666667 11.3571428571429 1.59183673469388
+12.76 10.5066666666667 0.666666666666667 11.3730279898219 1.58518345861741
+12.77 10.5133333333333 0.666666666666667 11.3888463989802 1.57849198195926
+12.78 10.52 0.666666666666667 11.4045977011494 1.57176201171445
+12.79 10.5266666666667 0.666666666666667 11.4202815099168 1.56499325206337
+12.8 10.5333333333333 0.666666666666667 11.4358974358974 1.55818540433925
+12.81 10.54 0.666666666666667 11.4514450867052 1.55133816699522
+12.82 10.5466666666667 0.666666666666667 11.4669240669241 1.54445123557093
+12.83 10.5533333333333 0.666666666666667 11.4823339780787 1.53752430265867
+12.84 10.56 0.666666666666667 11.4976744186047 1.53055705786912
+12.85 10.5666666666667 0.666666666666667 11.5129449838188 1.52354918779652
+12.86 10.5733333333333 0.666666666666667 11.5281452658885 1.51650037598349
+12.87 10.58 0.666666666666667 11.5432748538012 1.50941030288522
+12.88 10.5866666666667 0.666666666666667 11.5583333333333 1.50227864583333
+12.89 10.5933333333333 0.666666666666667 11.5733202870189 1.49510507899914
+12.9 10.6 0.666666666666667 11.5882352941176 1.4878892733564
+12.91 10.6066666666667 0.666666666666667 11.6030779305828 1.48063089664365
+12.92 10.6133333333333 0.666666666666667 11.6178477690289 1.47332961332589
+12.93 10.62 0.666666666666667 11.6325443786982 1.46598508455586
+12.94 10.6266666666667 0.666666666666667 11.6471673254282 1.45859696813469
+12.95 10.6333333333333 0.666666666666667 11.6617161716172 1.45116491847205
+12.96 10.64 0.666666666666667 11.6761904761905 1.44368858654573
+12.97 10.6466666666667 0.666666666666667 11.6905897945659 1.43616761986069
+12.98 10.6533333333333 0.666666666666667 11.7049136786189 1.42860166240747
+12.99 10.66 0.666666666666667 11.7191616766467 1.4209903546201
+13 10.6666666666667 0.666666666666667 11.7333333333333 1.41333333333333
+13.01 10.6733333333333 0.666666666666667 11.7474281897128 1.40563023173936
+13.02 10.68 0.666666666666667 11.7614457831325 1.39788067934388
+13.03 10.6866666666667 0.666666666666667 11.7753856472166 1.39008430192152
+13.04 10.6933333333333 0.666666666666667 11.789247311828 1.38224072147069
+13.05 10.7 0.666666666666667 11.8030303030303 1.37434955616774
+13.06 10.7066666666667 0.666666666666667 11.8167341430499 1.3664104203205
+13.07 10.7133333333333 0.666666666666667 11.8303583502366 1.35842292432116
+13.08 10.72 0.666666666666667 11.8439024390244 1.35038667459845
+13.09 10.7266666666667 0.666666666666667 11.8573659198914 1.34230127356919
+13.1 10.7333333333333 0.666666666666667 11.8707482993197 1.33416631958906
+13.11 10.74 0.666666666666667 11.8840490797546 1.32598140690278
+13.12 10.7466666666667 0.666666666666667 11.8972677595628 1.31774612559348
+13.13 10.7533333333333 0.666666666666667 11.9104038329911 1.30946006153137
+13.14 10.76 0.666666666666667 11.9234567901235 1.3011227963217
+13.15 10.7666666666667 0.666666666666667 11.9364261168385 1.29273390725192
+13.16 10.7733333333333 0.666666666666667 11.9493112947658 1.28429296723812
+13.17 10.78 0.666666666666667 11.9621118012422 1.27579954477065
+13.18 10.7866666666667 0.666666666666667 11.9748271092669 1.26725320385898
+13.19 10.7933333333333 0.666666666666667 11.9874566874567 1.25865350397575
+13.2 10.8 0.666666666666667 12 1.25
+13.21 10.8066666666667 0.666666666666667 12.012456506611 1.24129224215957
+13.22 10.8133333333333 0.666666666666667 12.0248256624826 1.23252977597264
+13.23 10.82 0.666666666666667 12.037106918239 1.22371214218847
+13.24 10.8266666666667 0.666666666666667 12.049299719888 1.21483887672716
+13.25 10.8333333333333 0.666666666666667 12.0614035087719 1.20590951061865
+13.26 10.84 0.666666666666667 12.073417721519 1.19692356994072
+13.27 10.8466666666667 0.666666666666667 12.085341789993 1.18788057575609
+13.28 10.8533333333333 0.666666666666667 12.0971751412429 1.17878004404865
+13.29 10.86 0.666666666666667 12.1089171974522 1.16962148565865
+13.3 10.8666666666667 0.666666666666667 12.1205673758865 1.16040440621699
+13.31 10.8733333333333 0.666666666666667 12.1321250888415 1.1511283060785
+13.32 10.88 0.666666666666667 12.1435897435897 1.14179268025422
+13.33 10.8866666666667 0.666666666666667 12.1549607423269 1.13239701834266
+13.34 10.8933333333333 0.666666666666667 12.1662374821173 1.12294080446008
+13.35 10.9 0.666666666666667 12.1774193548387 1.11342351716962
+13.36 10.9066666666667 0.666666666666667 12.1885057471264 1.10384462940943
+13.37 10.9133333333333 0.666666666666667 12.1994960403168 1.09420360841975
+13.38 10.92 0.666666666666667 12.2103896103896 1.08449991566875
+13.39 10.9266666666667 0.666666666666667 12.2211858279103 1.07473300677737
+13.4 10.9333333333333 0.666666666666667 12.231884057971 1.06490233144297
+13.41 10.94 0.666666666666667 12.2424836601307 1.05500733336181
+13.42 10.9466666666667 0.666666666666667 12.2529839883552 1.04504745015033
+13.43 10.9533333333333 0.666666666666667 12.2633843909555 1.03502211326525
+13.44 10.96 0.666666666666667 12.2736842105263 1.02493074792244
+13.45 10.9666666666667 0.666666666666667 12.2838827838828 1.01477277301453
+13.46 10.9733333333333 0.666666666666667 12.2939794419971 1.00454760102725
+13.47 10.98 0.666666666666667 12.3039735099338 0.994254637954475
+13.48 10.9866666666667 0.666666666666667 12.3138643067847 0.983893283211945
+13.49 10.9933333333333 0.666666666666667 12.3236511456024 0.973462929549674
+13.5 11 0.666666666666667 12.3333333333333 0.962962962962963
+13.51 11.0066666666667 0.666666666666667 12.3429101707498 0.952392762602037
+13.52 11.0133333333333 0.666666666666667 12.352380952381 0.941751700680273
+13.53 11.02 0.666666666666667 12.361744966443 0.931039142380974
+13.54 11.0266666666667 0.666666666666667 12.3710014947683 0.920254445762699
+13.55 11.0333333333333 0.666666666666667 12.3801498127341 0.909396961663089
+13.56 11.04 0.666666666666667 12.3891891891892 0.898466033601168
+13.57 11.0466666666667 0.666666666666667 12.3981188863807 0.88746099767812
+13.58 11.0533333333333 0.666666666666667 12.4069381598793 0.876381182476471
+13.59 11.06 0.666666666666667 12.4156462585034 0.865225908957688
+13.6 11.0666666666667 0.666666666666667 12.4242424242424 0.853994490358127
+13.61 11.0733333333333 0.666666666666667 12.4327258921792 0.84268623208334
+13.62 11.08 0.666666666666667 12.441095890411 0.831300431600674
+13.63 11.0866666666667 0.666666666666667 12.4493516399695 0.819836378330165
+13.64 11.0933333333333 0.666666666666667 12.4574923547401 0.808293353533653
+13.65 11.1 0.666666666666667 12.4655172413793 0.79667063020214
+13.66 11.1066666666667 0.666666666666667 12.473425499232 0.78496747294131
+13.67 11.1133333333333 0.666666666666667 12.4812163202463 0.773183137855199
+13.68 11.12 0.666666666666667 12.4888888888889 0.761316872427984
+13.69 11.1266666666667 0.666666666666667 12.4964423820572 0.749367915403844
+13.7 11.1333333333333 0.666666666666667 12.5038759689922 0.737335496664863
+13.71 11.14 0.666666666666667 12.5111888111888 0.725218837106948
+13.72 11.1466666666667 0.666666666666667 12.5183800623053 0.713017148513698
+13.73 11.1533333333333 0.666666666666667 12.5254488680718 0.700729633428216
+13.74 11.16 0.666666666666667 12.5323943661972 0.688355485022813
+13.75 11.1666666666667 0.666666666666667 12.5392156862745 0.675893886966551
+13.76 11.1733333333333 0.666666666666667 12.5459119496855 0.663344013290614
+13.77 11.18 0.666666666666667 12.5524822695035 0.65070502825143
+13.78 11.1866666666667 0.666666666666667 12.5589257503949 0.637976086191536
+13.79 11.1933333333333 0.666666666666667 12.5652414885194 0.625156331398114
+13.8 11.2 0.666666666666667 12.5714285714286 0.612244897959183
+13.81 11.2066666666667 0.666666666666667 12.5774860779634 0.599240909617359
+13.82 11.2133333333333 0.666666666666667 12.5834130781499 0.586143479621193
+13.83 11.22 0.666666666666667 12.5892086330935 0.572951710573987
+13.84 11.2266666666667 0.666666666666667 12.5948717948718 0.559664694280079
+13.85 11.2333333333333 0.666666666666667 12.6004016064257 0.546281511588523
+13.86 11.24 0.666666666666667 12.6057971014493 0.532801232234125
+13.87 11.2466666666667 0.666666666666667 12.6110573042776 0.51922291467578
+13.88 11.2533333333333 0.666666666666667 12.6161812297735 0.505545605932069
+13.89 11.26 0.666666666666667 12.6211678832117 0.491768341414033
+13.9 11.2666666666667 0.666666666666667 12.6260162601626 0.477890144755106
+13.91 11.2733333333333 0.666666666666667 12.6307253463733 0.463910027638126
+13.92 11.28 0.666666666666667 12.6352941176471 0.449826989619377
+13.93 11.2866666666667 0.666666666666667 12.6397215397215 0.435640017949601
+13.94 11.2933333333333 0.666666666666667 12.6440065681445 0.421348087391913
+13.95 11.3 0.666666666666667 12.6481481481481 0.406950160036578
+13.96 11.3066666666667 0.666666666666667 12.6521452145215 0.392445185112569
+13.97 11.3133333333333 0.666666666666667 12.6559966914806 0.377832098795838
+13.98 11.32 0.666666666666667 12.6597014925373 0.363109824014256
+13.99 11.3266666666667 0.666666666666667 12.6632585203658 0.348277270249148
+14 11.3333333333333 0.666666666666667 12.6666666666667 0.333333333333333
+14.01 11.34 0.666666666666667 12.6699248120301 0.318276895245633
+14.02 11.3466666666667 0.666666666666667 12.6730318257956 0.303106823901754
+14.03 11.3533333333333 0.666666666666667 12.675986565911 0.287821972941478
+14.04 11.36 0.666666666666667 12.6787878787879 0.272421181512089
+14.05 11.3666666666667 0.666666666666667 12.6814345991561 0.256903274047961
+14.06 11.3733333333333 0.666666666666667 12.6839255499154 0.241267060046209
+14.07 11.38 0.666666666666667 12.6862595419847 0.225511333838354
+14.08 11.3866666666667 0.666666666666667 12.6884353741497 0.209634874357906
+14.09 11.3933333333333 0.666666666666667 12.6904518329071 0.193636444903771
+14.1 11.4 0.666666666666667 12.6923076923077 0.177514792899409
+14.11 11.4066666666667 0.666666666666667 12.6940017137961 0.161268649647659
+14.12 11.4133333333333 0.666666666666667 12.6955326460481 0.144896730081126
+14.13 11.42 0.666666666666667 12.6968992248062 0.128397732508061
+14.14 11.4266666666667 0.666666666666667 12.6981001727116 0.111770338353601
+14.15 11.4333333333333 0.666666666666667 12.6991341991342 0.0950132118963282
+14.16 11.44 0.666666666666667 12.7 0.0781249999999999
+14.17 11.4466666666667 0.666666666666667 12.7006962576153 0.0611043318403789
+14.18 11.4533333333333 0.666666666666667 12.7012216404887 0.0439498186270484
+14.19 11.46 0.666666666666667 12.7015748031496 0.0266600533201076
+14.2 11.4666666666667 0.666666666666667 12.7017543859649 0.00923361034164194
+14.21 11.4733333333333 0.666666666666667 12.7017590149516 -0.00833095471812972
+14.22 11.48 0.666666666666667 12.7015873015873 -0.0260351054001859
+14.23 11.4866666666667 0.666666666666667 12.7012378426172 -0.0438803246815692
+14.24 11.4933333333333 0.666666666666667 12.7007092198582 -0.0618681152859518
+14.25 11.5 0.666666666666667 12.7 -0.08
+14.26 11.5066666666667 0.666666666666667 12.6991087344029 -0.0982775219956717
+14.27 11.5133333333333 0.666666666666667 12.6980339588919 -0.116702245158569
+14.28 11.52 0.666666666666667 12.6967741935484 -0.135275754422475
+14.29 11.5266666666667 0.666666666666667 12.6953279424978 -0.153999656110221
+14.3 11.5333333333333 0.666666666666667 12.6936936936937 -0.172875578280985
+14.31 11.54 0.666666666666667 12.6918699186992 -0.191905171084232
+14.32 11.5466666666667 0.666666666666667 12.6898550724638 -0.211090107120353
+14.33 11.5533333333333 0.666666666666667 12.6876475930972 -0.230432081808215
+14.34 11.56 0.666666666666667 12.6852459016393 -0.249932813759742
+14.35 11.5666666666667 0.666666666666667 12.6826484018265 -0.269594045161693
+14.36 11.5733333333333 0.666666666666667 12.6798534798535 -0.289417542164794
+14.37 11.58 0.666666666666667 12.6768595041322 -0.309405095280379
+14.38 11.5866666666667 0.666666666666667 12.673664825046 -0.329558519784705
+14.39 11.5933333333333 0.666666666666667 12.6702677746999 -0.349879656131144
+14.4 11.6 0.666666666666667 12.6666666666667 -0.370370370370371
+14.41 11.6066666666667 0.666666666666667 12.6628597957289 -0.391032554578772
+14.42 11.6133333333333 0.666666666666667 12.6588454376164 -0.411868127295236
+14.43 11.62 0.666666666666667 12.6546218487395 -0.432879033966527
+14.44 11.6266666666667 0.666666666666667 12.6501872659176 -0.454067247401421
+14.45 11.6333333333333 0.666666666666667 12.6455399061033 -0.475434768233818
+14.46 11.64 0.666666666666667 12.6406779661017 -0.496983625395003
+14.47 11.6466666666667 0.666666666666667 12.6355996222852 -0.518715876595325
+14.48 11.6533333333333 0.666666666666667 12.630303030303 -0.540633608815428
+14.49 11.66 0.666666666666667 12.6247863247863 -0.562738938807315
+14.5 11.6666666666667 0.666666666666667 12.6190476190476 -0.585034013605442
+14.51 11.6733333333333 0.666666666666667 12.6130850047755 -0.607521011048075
+14.52 11.68 0.666666666666667 12.6068965517241 -0.630202140309154
+14.53 11.6866666666667 0.666666666666667 12.6004803073967 -0.653079642440901
+14.54 11.6933333333333 0.666666666666667 12.5938342967245 -0.676155790927419
+14.55 11.7 0.666666666666667 12.5869565217391 -0.699432892249529
+14.56 11.7066666666667 0.666666666666667 12.5798449612403 -0.722913286461151
+14.57 11.7133333333333 0.666666666666667 12.5724975704568 -0.746599347777429
+14.58 11.72 0.666666666666667 12.5649122807018 -0.770493485174926
+14.59 11.7266666666667 0.666666666666667 12.5570869990225 -0.794598143004159
+14.6 11.7333333333333 0.666666666666667 12.5490196078431 -0.818915801614762
+14.61 11.74 0.666666666666667 12.5407079646018 -0.843448977993577
+14.62 11.7466666666667 0.666666666666667 12.5321499013807 -0.868200226415978
+14.63 11.7533333333333 0.666666666666667 12.5233432245302 -0.893172139110733
+14.64 11.76 0.666666666666667 12.5142857142857 -0.918367346938776
+14.65 11.7666666666667 0.666666666666667 12.5049751243781 -0.943788520086138
+14.66 11.7733333333333 0.666666666666667 12.4954091816367 -0.96943836877144
+14.67 11.78 0.666666666666667 12.4855855855856 -0.995319643968292
+14.68 11.7866666666667 0.666666666666667 12.4755020080321 -1.02143513814293
+14.69 11.7933333333333 0.666666666666667 12.4651560926485 -1.04778768600749
+14.7 11.8 0.666666666666667 12.4545454545455 -1.07438016528926
+14.71 11.8066666666667 0.666666666666667 12.4436676798379 -1.10121549751635
+14.72 11.8133333333333 0.666666666666667 12.4325203252033 -1.12829664882015
+14.73 11.82 0.666666666666667 12.4211009174312 -1.15562663075499
+14.74 11.8266666666667 0.666666666666667 12.4094069529652 -1.18320850113541
+14.75 11.8333333333333 0.666666666666667 12.3974358974359 -1.21104536489152
+14.76 11.84 0.666666666666667 12.3851851851852 -1.23914037494284
+14.77 11.8466666666667 0.666666666666667 12.3726522187822 -1.26749673309115
+14.78 11.8533333333333 0.666666666666667 12.35983436853 -1.29611769093271
+14.79 11.86 0.666666666666667 12.3467289719626 -1.32500655079047
+14.8 11.8666666666667 0.666666666666667 12.3333333333333 -1.35416666666667
+14.81 11.8733333333333 0.666666666666667 12.319644723093 -1.38360144521641
+14.82 11.88 0.666666666666667 12.3056603773585 -1.41331434674261
+14.83 11.8866666666667 0.666666666666667 12.2913774973712 -1.44330888621308
+14.84 11.8933333333333 0.666666666666667 12.2767932489451 -1.47358863430006
+14.85 11.9 0.666666666666667 12.2619047619048 -1.50415721844293
+14.86 11.9066666666667 0.666666666666667 12.2467091295117 -1.53501832393471
+14.87 11.9133333333333 0.666666666666667 12.2312034078807 -1.56617569503279
+14.88 11.92 0.666666666666667 12.2153846153846 -1.59763313609468
+14.89 11.9266666666667 0.666666666666667 12.1992497320472 -1.62939451273939
+14.9 11.9333333333333 0.666666666666667 12.1827956989247 -1.66146375303503
+14.91 11.94 0.666666666666667 12.1660194174757 -1.69384484871336
+14.92 11.9466666666667 0.666666666666667 12.1489177489178 -1.72654185641199
+14.93 11.9533333333333 0.666666666666667 12.1314875135722 -1.75955889894499
+14.94 11.96 0.666666666666667 12.1137254901961 -1.79290016660259
+14.95 11.9666666666667 0.666666666666667 12.0956284153005 -1.8265699184807
+14.96 11.9733333333333 0.666666666666667 12.0771929824561 -1.86057248384119
+14.97 11.98 0.666666666666667 12.0584158415842 -1.89491226350358
+14.98 11.9866666666667 0.666666666666667 12.039293598234 -1.9295937312691
+14.99 11.9933333333333 0.666666666666667 12.0198228128461 -1.96462143537783
+15 12 0.666666666666667 12 0.666666666666667
Added: trunk/orca/packages/Math-Interpolate-1.02/t/01interval.t
==============================================================================
--- trunk/orca/packages/Math-Interpolate-1.02/t/01interval.t (original)
+++ trunk/orca/packages/Math-Interpolate-1.02/t/01interval.t Sat Jul 13 18:46:23 2002
@@ -0,0 +1,87 @@
+# Before `make' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+use strict;
+use vars qw($loaded $NumberTests $ArraySize);
+
+BEGIN {
+ $| = 1;
+ $NumberTests = 500;
+ $ArraySize = 500;
+ print "1..", 2*$NumberTests+5, "\n";
+}
+END {print "not ok 1\n" unless $loaded; }
+
+my $ok_count = 1;
+sub ok {
+ my $ok = shift;
+ $ok or print "not ";
+ print "ok $ok_count\n";
+ ++$ok_count;
+ $ok;
+}
+
+use Math::IntervalSearch qw(interval_search);
+
+# If we got here, then the package being tested was loaded.
+$loaded = 1;
+ok(1); # 1
+
+sub FakeLessThan {
+ $_[0] > $_[1];
+}
+
+sub FakeLessThanEqualTo {
+ $_[0] >= $_[1];
+}
+
+my @array = (0 .. $ArraySize-1);
+
+srand();
+
+# Check for illegal parameters.
+ok( !interval_search() ); # 2
+ok( !interval_search(2) ); # 3
+ok( !interval_search(2, 3) ); # 4
+
+# Check that -1 is returned for an empty array.
+ok( interval_search(10, []) == -1 ); # 5
+
+# Check a random test.
+for (1 .. $NumberTests) {
+ my $ok = 1;
+ my $number = 1.5 * $ArraySize * rand() - $ArraySize/3;
+ my $answer = interval_search($number, \@array);
+ if ( $number < 0 ) {
+ $ok = 0 unless $answer == -1;
+ }
+ elsif ( $number >= $ArraySize-1 ) {
+ $ok = 0 unless $answer == $ArraySize-1;
+ }
+ elsif ( int($number) != $answer ) {
+ $ok = 0;
+ }
+ ok( $ok ); # 6
+}
+
+# Reverse the array and use some different comparision routines.
+ at array = reverse @array;
+
+# Check a random test.
+for (1 .. $NumberTests) {
+ my $ok = 1;
+ my $number = 1.5 * $ArraySize * rand() - $ArraySize/3;
+ my $answer = interval_search($number, \@array,
+ \&FakeLessThan, \&FakeLessThanEqualTo);
+ if ( $number < 0 ) {
+ $ok = 0 unless $answer == @array-1;
+ }
+ elsif ( $number >= $ArraySize-1 ) {
+ $ok = 0 unless $answer == -1;
+ }
+ elsif ( (int(@array - $number)-1) != $answer ) {
+ $ok = 0;
+ }
+
+ ok( $ok ); # 7
+}
Added: trunk/orca/packages/Math-Interpolate-1.02/MANIFEST
==============================================================================
--- trunk/orca/packages/Math-Interpolate-1.02/MANIFEST (original)
+++ trunk/orca/packages/Math-Interpolate-1.02/MANIFEST Sat Jul 13 18:46:24 2002
@@ -0,0 +1,8 @@
+CHANGES
+MANIFEST
+Makefile.PL
+README
+lib/Math/IntervalSearch.pm
+lib/Math/Interpolate.pm
+t/01interval.t
+t/02interp.t
Added: trunk/orca/packages/Math-Interpolate-1.02/lib/Math/Interpolate.pm
==============================================================================
--- trunk/orca/packages/Math-Interpolate-1.02/lib/Math/Interpolate.pm (original)
+++ trunk/orca/packages/Math-Interpolate-1.02/lib/Math/Interpolate.pm Sat Jul 13 18:46:24 2002
@@ -0,0 +1,363 @@
+package Math::Interpolate;
+
+require 5.004_04;
+
+use strict;
+use vars qw(@ISA $VERSION @EXPORT_OK);
+use Exporter;
+use Carp qw(cluck);
+use Math::IntervalSearch qw(interval_search);
+
+$VERSION = do {my @r=(q$Revision: 1.02 $=~/\d+/g);sprintf "%d."."%02d"x$#r, at r};
+ at ISA = qw(Exporter);
+ at EXPORT_OK = qw(derivatives constant_interpolate
+ linear_interpolate robust_interpolate);
+
+sub derivatives {
+ my $X = shift;
+ return unless defined($X);
+ return unless ref($X);
+
+ my $Y = shift;
+ return unless defined($Y);
+ return unless ref($Y);
+
+ my $num_x = @$X;
+ my $num_y = @$Y;
+
+ return unless $num_x == $num_y;
+
+ if ( $num_x < 2 ) {
+ return ();
+ }
+
+ # Set up the derivative array.
+ my @deriv;
+
+ # If there for two input points, use a straight line as the derivative.
+ if ( $num_x == 2 ) {
+ $deriv[0] = ($Y->[1] - $Y->[0]) / ($X->[1] - $X->[0]);
+ $deriv[1] = $deriv[0];
+ return @deriv;
+ }
+
+ # Calculate the derivatives for the interior points. This loop uses
+ # a total of 6 points to calculate the derivative at any one
+ # point. And when the loop moves along in increasing array
+ # position, the same data point is used three times. So instead of
+ # reading the correct value from the array three times, just shift
+ # the values down by copying them from one variable to the next.
+ my $xi;
+ my $xj = $X->[0];
+ my $xk = $X->[1];
+ my $yi;
+ my $yj = $Y->[0];
+ my $yk = $Y->[1];
+
+ for (my $i=1; $i<$num_x-1; ++$i) {
+ $xi = $xj;
+ $xj = $xk;
+ $xk = $X->[$i+1];
+ $yi = $yj;
+ $yj = $yk;
+ $yk = $Y->[$i+1];
+
+ my $r1 = ($xk - $xj)*($xk - $xj) + ($yk - $yj)*($yk - $yj);
+ my $r2 = ($xj - $xi)*($xj - $xi) + ($yj - $yi)*($yj - $yi);
+
+ $deriv[$i] =
+ ( ($yj - $yi)*$r1 + ($yk - $yj)*$r2 ) /
+ ( ($xj - $xi)*$r1 + ($xk - $xj)*$r2 );
+ }
+
+ # Calculate the derivative at the first point, (x(0),y(0)).
+ my $i = 0;
+ my $j = 1;
+ my $slope = ($Y->[$j] - $Y->[$i])/($X->[$j] - $X->[$i]);
+ if ( (($slope >= 0) && ($slope >= $deriv[$j])) ||
+ (($slope <= 0) && ($slope <= $deriv[$j])) ) {
+ $deriv[0] = 2*$slope - $deriv[1];
+ }
+ else {
+ $deriv[0] = $slope + (abs($slope) * ($slope - $deriv[1])) /
+ (abs($slope) + abs($slope - $deriv[1]) );
+ }
+
+ # Calculate the derivative at the last point.
+ $i = $num_x - 2;
+ $j = $num_x - 1;
+ $slope = ($Y->[$j] - $Y->[$i])/($X->[$j] - $X->[$i]);
+ if ( (($slope >= 0) && ($slope >= $deriv[$i])) ||
+ (($slope <= 0) && ($slope <= $deriv[$i])) ) {
+ $deriv[$j] = 2*$slope - $deriv[$i];
+ }
+ else {
+ $deriv[$j] = $slope + (abs($slope) * ($slope - $deriv[$i])) /
+ (abs($slope) + abs($slope - $deriv[$i]) );
+ }
+
+ @deriv;
+}
+
+sub constant_interpolate {
+ my $x = shift;
+ return unless defined($x);
+
+ my $X = shift;
+ return unless defined($X);
+ return unless ref($X);
+
+ my $Y = shift;
+ return unless defined($Y);
+ return unless ref($Y);
+
+ my $num_x = @$X;
+ my $num_y = @$Y;
+ return unless $num_x == $num_y;
+
+ # Find where the point to be interpolated lies in the input sequence.
+ # If the x value lies outside of the X sequence, use the value at either
+ # the beginning or the end of the sequence.
+ my $j = interval_search($x, $X);
+ if ( $j < 0 ) {
+ $j = 0;
+ }
+ elsif ( $j > $num_x - 1 ) {
+ $j = $num_x - 1;
+ }
+
+ # Return the Y value at the point.
+ $Y->[$j];
+}
+
+sub linear_interpolate {
+ my $x = shift;
+ return unless defined($x);
+
+ my $X = shift;
+ return unless defined($X);
+ return unless ref($X);
+
+ my $Y = shift;
+ return unless defined($Y);
+ return unless ref($Y);
+
+ my $num_x = @$X;
+ my $num_y = @$Y;
+ return unless $num_x == $num_y;
+
+ # Find where the point to be interpolated lies in the input sequence.
+ # If the point lies outside, then coerce the index value to be legal for
+ # the routine to work. Remember, this is only an interpreter, not an
+ # extrapolator.
+ my $j = interval_search($x, $X);
+ if ( $j < 0 ) {
+ $j = 0;
+ }
+ elsif ( $j >= $num_x - 1 ) {
+ $j = $num_x - 2;
+ }
+ my $k = $j + 1;
+
+ # Calculate the linear slope between the two points.
+ my $dy = ($Y->[$k] - $Y->[$j]) / ($X->[$k] - $X->[$j]);
+
+ # Use the straight line between the two points to interpolate.
+ my $y = $dy*($x - $X->[$j]) + $Y->[$j];
+
+ return wantarray ? ($y, $dy) : $y;
+}
+
+sub robust_interpolate {
+ my $x = shift;
+ return unless defined($x);
+
+ my $X = shift;
+ return unless defined($X);
+ return unless ref($X);
+
+ my $Y = shift;
+ return unless defined($Y);
+ return unless ref($Y);
+
+ my $num_x = @$X;
+ my $num_y = @$Y;
+ return unless $num_x == $num_y;
+
+ # Calculate the derivative if it wasn't passed in.
+ my $dY = shift;
+ unless (defined($dY) and ref($dY)) {
+ $dY = [ derivatives($X, $Y) ];
+ }
+
+ # Find where the point to be interpolated lies in the input
+ # sequence. If the point lies outside, then coerce the index value
+ # to be legal for the routine to work. Remember, this is only an
+ # interpreter, not an extrapolator.
+ my $j = interval_search($x, $X);
+ if ( $j < 0 ) {
+ $j = 0;
+ }
+ elsif ( $j >= $num_x - 1 ) {
+ $j = $num_x - 2;
+ }
+ my $k = $j + 1;
+
+ # Calculate a few variables that will be used frequently.
+ my $xj = $X->[$j];
+ my $xk = $X->[$k];
+ my $yj = $Y->[$j];
+ my $yk = $Y->[$k];
+ my $slope = ($yk - $yj) / ($xk - $xj);
+ my $y0 = $yj + $slope * ($x - $xj);
+ my $dely0 = $yj + $dY->[$j] * ($x - $xj) - $y0;
+ my $dely1 = $yk + $dY->[$k] * ($x - $xk) - $y0;
+
+ # Calculate the derivatives of the three variables above with respest
+ # to x.
+ my $d_y0 = $slope;
+ my $d_dely0 = $dY->[$j] - $d_y0;
+ my $d_dely1 = $dY->[$k] - $d_y0;
+
+ # Calculate the interpolated y and dy values.
+ my $dely_sign = $dely0*$dely1;
+ my $y;
+ my $dy;
+ if ($dely_sign == 0) {
+ $y = $y0;
+ $dy = $d_y0;
+ return wantarray ? ($y0, $d_y0) : $y0;
+ }
+
+ my $dely_sum = $dely0 + $dely1;
+ if ($dely_sign > 0) {
+ $y = $y0 + $dely_sign/$dely_sum;
+ $dy = $d_y0 + ($dely_sum*($dely0*$d_dely1 + $d_dely0*$dely1) -
+ $dely_sign*($d_dely0 + $d_dely1)) / ($dely_sum*$dely_sum);
+ }
+ else {
+ my $x_tmp = 2*$x - $xj - $xk;
+ $y = $y0 + $dely_sign*$x_tmp/(($dely0 - $dely1)*($xk - $xj));
+ $dy = $d_y0 + (($dely0 - $dely1)*($xk - $xj)*
+ ($d_dely0*$dely1*$x_tmp +
+ $dely0*$d_dely1*$x_tmp +
+ $dely_sign*2) -
+ $dely_sign*$x_tmp*
+ (($xk - $xj)*($d_dely0 - $d_dely1))) /
+ (($dely0 - $dely1)*($dely0 - $dely1)*($xk - $xj)*($xk - $xj));
+ }
+
+ return wantarray ? ($y, $dy) : $y;
+}
+
+sub degenerate {
+ my ($x1, $y1, $dy1, $x2, $y2, $dy2) = @_;
+ my $slope = ($y2 - $y1)/($x2 - $x1);
+ (sleep == $dy1) && ($dy1 != $dy2);
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+Math::Interpolate - Interpolate the value Y from X using a list of (X, Y) pairs
+
+=head1 SYNOPSIS
+
+ use Math::Interpolate qw(derivatives constant_interpolate
+ linear_interpolate robust_interpolate);
+ my @x = (1..5);
+ my @y = (5, 10, 13, -4.5, 3);
+ my @dy = derivatives(\@x, \@y);
+ my ($l_y, $l_dy) = linear_interpolate(3.4, \@x, \@y);
+ my ($r_y, $r_dy) = robust_interpolate(3.4, \@x, \@y);
+ ($r_y, $r_dy) = robust_interpolate(3.4, \@x, \@y, [-2, 3, 4, -1, 4]);
+
+=head1 DESCRIPTION
+
+=head1 SUBROUTINES
+
+=over 4
+
+=item B<derivatives> I<x_sequence> I<y_sequence>
+
+Given a reference to an array of x values in I<x_sequence> and a reference
+to an array of y values in I<y_sequence>, return an array of reasonable
+derivatives. The I<x_sequence> values are presumed to be sorted in
+increasing numerical order.
+
+If there is an error in the input, such as I<x_sequence> and I<y_sequence>
+containing a different number of elements, then the subroutine returns an
+empty list in list context, an undefined value in scalar context, or nothing
+in a void context.
+
+=item B<constant_interpolate> I<x> I<x_sequence> I<y_sequence>
+
+Given a reference to an array of x values in I<x_sequence> and a reference
+to an array of y values in I<y_sequence>, return the y value associated with
+the first x value less than or equal to I<x>. In other words, if
+ I<x_sequence>->[i] <= I<x> < I<x_sequence>->[i+1]
+
+then return
+ I<y_sequence>->[i]
+
+If I<x> is less than I<x_sequence>->[0], then return I<y_sequence>->[0]. If
+I<x> is greater than I<x_sequence->[-1], then return I<y_sequence>->[-1].
+
+If there is an error in the input, such as I<x_sequence> and I<y_sequence>
+containing a different number of elements, then the subroutine returns an
+empty list in list context, an undefined value in scalar context, or nothing
+in a void context.
+
+=item B<linear_interpolate> I<x> I<x_sequence> I<y_sequence>
+
+Given a reference to an array of x values in I<x_sequence> and a reference
+to an array of y values in I<y_sequence>, calculate the interpolated
+value y that corresponds to the value I<x>. The returned value y lies on
+the straight line between the two points surrounding I<x>. If <x> lies
+outside of the range of values spanned by I<x_sequence> then a linear
+extrapolation will be done.
+
+In an array context, I<linear_interpolate> will return an array containing
+the y value and and slope between the two nearest surrounding points.
+
+If there is an error in the input, such as I<x_sequence> and I<y_sequence>
+containing a different number of elements, then the subroutine returns an
+empty list in list context, an undefined value in scalar context, or nothing
+in a void context.
+
+=item B<robust_interpolate> I<value> I<x_sequence> I<y_sequence> [I<dy_sequence>]
+
+Given a reference to an array of x values in I<x_sequence> and a reference
+to an array of y values in I<y_sequence>, calculate the interpolated
+value y that corresponds to the value I<x>. The interpolated curve
+generated by I<robust_interpolate> is smooth and even the derivatives of the
+curve are smooth with only a few exceptions.
+
+The returned value y lies on the curve between the two points surrounding
+I<x>. If <x> lies outside of the range of values spanned by I<x_sequence>
+then a linear extrapolation will be done.
+
+In an array context, I<linear_interpolate> will return an array containing
+the y value and and slope between the two nearest surrounding points.
+
+If there is an error in the input, such as I<x_sequence> and I<y_sequence>
+containing a different number of elements, then the subroutine returns an
+empty list in list context, an undefined value in scalar context, or nothing
+in a void context.
+
+=back 4
+
+=head1 AUTHOR
+
+Blair Zajac <bzajac at geostaff.com>.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1998 by Blair Zajac.
+
+=cut
Added: trunk/orca/packages/Math-Interpolate-1.02/lib/Math/IntervalSearch.pm
==============================================================================
--- trunk/orca/packages/Math-Interpolate-1.02/lib/Math/IntervalSearch.pm (original)
+++ trunk/orca/packages/Math-Interpolate-1.02/lib/Math/IntervalSearch.pm Sat Jul 13 18:46:24 2002
@@ -0,0 +1,250 @@
+package Math::IntervalSearch;
+
+require 5.004_04;
+
+use strict;
+use vars qw(@ISA $VERSION @EXPORT_OK);
+use Exporter;
+use Carp qw(cluck);
+
+$VERSION = do {my @r=(q$Revision: 1.02 $=~/\d+/g);sprintf "%d."."%02d"x$#r, at r};
+ at ISA = qw(Exporter);
+ at EXPORT_OK = qw(interval_search);
+
+sub LessThan {
+ $_[0] < $_[1];
+}
+
+sub LessThanEqualTo {
+ $_[0] <= $_[1];
+}
+
+# This holds the result from the last interval search.
+my $last_interval_result = undef;
+
+sub interval_search {
+ if ( @_ > 4 ) {
+ cluck "interval called with too many parameters";
+ return;
+ }
+
+ # Get the input arguments.
+ my $x = shift;
+ my $sequenceRef = shift;
+
+ return unless defined($x);
+ return unless defined($sequenceRef);
+ return unless ref($sequenceRef);
+
+ # Check the input arguments for any code references and use them.
+ my $LessThan = \&LessThan;
+ my $LessThanEqualTo = \&LessThanEqualTo;
+ @_ and defined(ref($_[0])) and ref($_[0]) eq 'CODE' and
+ $LessThan = shift;
+ @_ and defined(ref($_[0])) and ref($_[0]) eq 'CODE' and
+ $LessThanEqualTo = shift;
+
+ # Get the number of points in the data.
+ my $num = @$sequenceRef;
+
+ # Return -1 if there's no data.
+ if ( $num <= 0 ) {
+ $last_interval_result = 0;
+ return -1;
+ }
+
+ # Use the result from the last time through the subroutine, if it
+ # exists. Force the result into the range required by the array
+ # size.
+ $last_interval_result = 0 unless defined($last_interval_result);
+
+ # Which side of the data point is x on if there's only one point?
+ if ( $num == 1 ) {
+ $last_interval_result = 0;
+ if ( &$LessThan($x, $sequenceRef->[0]) ) {
+ return -1;
+ }
+ else {
+ return 0;
+ }
+ }
+
+ # Is the point less than the smallest point in the sequence?
+ if ( &$LessThan($x, $sequenceRef->[0]) ) {
+ $last_interval_result = 0;
+ return -1;
+ }
+
+ # Is the point greater than the largest point in the sequence?
+ if ( &$LessThanEqualTo($sequenceRef->[$num-1], $x) ) {
+ $last_interval_result = $num - 1;
+ return $last_interval_result;
+ }
+
+ # Use the result from the last run as a start for this run.
+ if ( $last_interval_result > $num-1 ) {
+ $last_interval_result = $num - 2;
+ }
+ my $ilo = $last_interval_result;
+ my $ihi = $ilo + 1;
+
+ # Is the new upper ihi beyond the extent of the sequence?
+ if ( $ihi >= $num ) {
+ $ihi = $num - 1;
+ $ilo = $ihi - 1;
+ }
+
+ # If x < sequence(ilo), then decrease ilo to capture x.
+ if ( &$LessThan($x, $sequenceRef->[$ilo]) ) {
+ my $istep = 1;
+ for (;;) {
+ $ihi = $ilo;
+ $ilo = $ihi - $istep;
+ if ( $ilo <= 0 ) {
+ $ilo = 0;
+ last;
+ }
+ if ( &$LessThanEqualTo($sequenceRef->[$ilo], $x) ) {
+ last;
+ }
+ $istep *= 2;
+ }
+ }
+
+ # If x >= sequence(ihi), then increase ihi to capture x.
+ if ( &$LessThanEqualTo($sequenceRef->[$ihi], $x) ) {
+ my $istep = 1;
+ for (;;) {
+ $ilo = $ihi;
+ $ihi = $ilo + $istep;
+ if ( $ihi >= $num-1 ) {
+ $ihi = $num - 1;
+ last;
+ }
+ if ( &$LessThan($x, $sequenceRef->[$ihi]) ) {
+ last;
+ }
+ $istep *= 2;
+ }
+ }
+
+ # Now sequence(ilo) <= x < sequence(ihi). Narrow the interval.
+ for (;;) {
+ # Find the middle point of the sequence.
+ my $middle = int(($ilo + $ihi)/2);
+
+ # The division above was integer, so if ihi = ilo+1, then
+ # middle=ilo, which tests if x has been trapped.
+ if ( $middle == $ilo ) {
+ $last_interval_result = $ilo;
+ return $ilo;
+ }
+ if ( &$LessThan($x, $sequenceRef->[$middle]) ) {
+ $ihi = $middle;
+ }
+ else {
+ $ilo = $middle;
+ }
+ }
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+Math::IntervalSearch - Search where an element lies in a list of sorted elements
+
+=head1 SYNOPSIS
+
+ use Math::IntervalSearch qw(interval);
+ my @array = (1..5);
+ my $location = interval(2.4, \@array);
+
+ # Use your own comparison operators.
+ sub ReverseLessThan {
+ $_[0] < $_[1];
+ }
+
+ sub ReverseLessThanEqualTo {
+ $_[0] <= $_[1];
+ }
+
+ $location = interval(2.4,
+ \@array,
+ \&ReverseLessThan,
+ \&ReverseLessThanEqualTo);
+
+=head1 DESCRIPTION
+
+This subroutine is used to locate a position in an array of values where a
+given value would fit. It has been designed to be efficient in the common
+situation that it is called repeatedly. The user can supply a different
+set of comparison operators to replace the standard < and <=.
+
+=head1 SUBROUTINES
+
+=over 4
+
+=item B<interval> I<value> I<sequence> [I<less_than> [I<less_than_equal_to>]]
+
+Given a I<value> I<interval> returns the location in the reference to an array
+I<sequence> where the value would fit. The default < operator to compare the
+elements in I<sequence> can be replaced by the subroutine I<less_than> which
+should return 1 if the first element passed to I<less_than> is less than the
+second. The default <= operator to compare the elements in I<sequence> can
+be replaced by the subroutine I<less_than> which should return 1 if the first
+element passed to I<less_than> is less than the second.
+
+The values in I<sequence> should already be sorted in numerically increasing
+order or in the order that would be produced by using the I<less_than>
+subroutine.
+
+Let N be the number of elements in referenced array I<sequence>, then
+I<interval> returns these values:
+ -1 if I<value> < I<sequence>->[0]
+ i if I<sequence>->[i] <= I<value> < I<sequence>->[i+1]
+ N-1 if I<sequence>->[N-1] <= I<value>
+
+If a reference is made to an empty array, then -1 is always returned.
+
+If there is illegal input to I<interval>, such as an improper number of
+arguments, then an empty list in list context, an undefined value in
+scalar context, or nothing in a void context is returned.
+
+This subroutine is designed to be efficient in the common situation that it is
+called repeatedly, with I<value> taken from an increasing or decreasing
+list of values. This will happen, e.g., when an irregular waveform is
+interpolated to create a sequence with constant separation. The first guess
+for the output is therefore taken to be the value returned at the previous
+call and stored in the variable ilo. A first check ascertains that ilo is
+less than the number of data points in I<sequence>. This is necessary since
+the present call may have nothing to do with the previous call. Then, if
+ I<sequence>->[ilo] <= I<value> < I<sequence>->[ilo+1],
+
+we set left = ilo and are done after just three comparisons.
+Otherwise, we repeatedly double the difference
+ istep = ihi - ilo
+
+while also moving ilo and ihi in the direction of x, until
+ I<sequence>->[ilo] <= x < I<sequence>->[ihi],
+
+after which bisection is used to get, in addition,
+ ilo+1 = ihi.
+
+Then left = ilo is returned.
+
+=back 4
+
+=head1 AUTHOR
+
+Blair Zajac <bzajac at geostaff.com>.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1998 by Blair Zajac.
+
+=cut
Added: trunk/orca/packages/Math-Interpolate-1.02/Makefile.PL
==============================================================================
--- trunk/orca/packages/Math-Interpolate-1.02/Makefile.PL (original)
+++ trunk/orca/packages/Math-Interpolate-1.02/Makefile.PL Sat Jul 13 18:46:24 2002
@@ -0,0 +1,11 @@
+# This -*- perl -*- script writes the Makefile for this package.
+
+use strict;
+use ExtUtils::MakeMaker;
+
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+ 'NAME' => 'Math::Interpolate',
+ 'VERSION_FROM' => 'lib/Math/Interpolate.pm', # finds $VERSION
+);
Added: trunk/orca/packages/Math-Interpolate-1.02/CHANGES
==============================================================================
--- trunk/orca/packages/Math-Interpolate-1.02/CHANGES (original)
+++ trunk/orca/packages/Math-Interpolate-1.02/CHANGES Sat Jul 13 18:46:24 2002
@@ -0,0 +1,31 @@
+Thu Apr 8 10:20:30 PDT 1999 <blair at geostaff.com> (Blair Zajac)
+
+ Have ok() in t/*.t return the success or failure of the
+ test instead of the number of tests performed.
+
+ Release 1.02.
+
+Mon Dec 28 12:35:33 PST 1998 <bzajac at geostaff.com> Blair Zajac
+
+ Add some more documentation for Math::IntervalSearch.
+
+ Update all email addresses from bzajac at geocities.com to
+ bzajac at geostaff.com.
+
+ Version 1.01.
+
+Wed Nov 18 09:01:13 PST 1998 <bzajac at geostaff.com> Blair Zajac
+
+ Change name of interval to interval_search.
+
+ Change "return;" of interval_search to "return -1;" when an
+ empty array is passed in.
+
+ Spell check the documentation.
+
+ Version 1.00.
+
+Wed Aug 5 13:58:40 PDT 1998 <blair at geostaff.com> Blair Zajac
+
+ Version 0.01.
+ First version copied from the Borp source tree.
Added: trunk/orca/packages/Math-Interpolate-1.02/README
==============================================================================
--- trunk/orca/packages/Math-Interpolate-1.02/README (original)
+++ trunk/orca/packages/Math-Interpolate-1.02/README Sat Jul 13 18:46:25 2002
@@ -0,0 +1,72 @@
+Package Math::Interpolate version 1.02
+
+This is the Math::Interpolate package. This module contains several
+useful routines for interpolating data sets and finding where a given
+value lies in a sorted list.
+
+The first is a subroutine used to locate a position in an array of values
+where a given value would fit using bisection. It has been designed
+to be efficient in the common situation that it is called repeatedly.
+The user can supply a different set of comparison operators to replace
+the standard < and <=. For example, given a list (1, 2, 5, 8, 15)
+and the number 9.5 it would return 3.
+
+The remaining routines all are related to interpolating sets of (x, y)
+data pairs. They all take a list of (x, y) data pairs given another
+x value, return a sensible y value using the list of (x, y) data pairs.
+Three different interpolating functions are provided. The first, called a
+constant interpolator, assumes that the function being interpolated moves
+in non-linear jumps from one value to another. The interpolated value
+for some value x is the y value of the neighboring (x, y) to the left of
+the given x. The second interpolator performs a linear interpolation
+between the neighboring points. The third interpolator is called the
+robust interpolator and interpolates a smooth curve between all of
+the (x, y) pairs. To do the interpolation, it first calculates some
+reasonable derivatives at the (x, y) pairs. If you have measured your
+own derivative information, you can supply it to the robust interpolator
+and it will use it.
+
+REQUIREMENTS
+
+ * Perl 5.004_04 or greater.
+
+AVAILABILITY
+
+The latest version of this package is available for download from a CPAN
+(Comprehensive Perl Archive Network) site near your at
+
+ http://www.perl.com/CPAN/authors/id/B/BZ/BZAJAC/
+
+or from my FTP site:
+
+ ftp://ftp.gps.caltech.edu/pub/blair/Perl/
+
+INSTALLATION
+
+In order to use this package you will need Perl version 5.004_04 or
+better. Once that is completed, you install Math::Interpolate as you
+would install any perl module library, by running these commands:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+If you want to install a private copy of this package in some other
+directory, then you should try to produce the initial Makefile with
+something like this command:
+
+ perl Makefile.PL LIB=~/perl
+
+DOCUMENTATION
+
+See the CHANGES file for a list of recent changes. POD style
+documentation is included in all modules and scripts. These are
+normally converted to manual pages end installed as part of the "make
+install" process. You should also be able to use the 'perldoc'
+utility to extract documentation from the module files directly.
+
+AUTHOR, COMMENTS, AND BUGS
+
+I welcome all comments and bug reports. Please email them to
+Blair Zajac <blair at geostaff.com>.
More information about the Orca-checkins
mailing list