Index: extensions/gsdl-video/trunk/CASCADE-MAKE.sh
===================================================================
--- extensions/gsdl-video/trunk/CASCADE-MAKE.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/CASCADE-MAKE.sh	(revision 18425)
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+source bin/script/test-setup.bash
+source lib/cascade-lib.bash
+
+
+# Ensure that the necessary directories exist within the 'installed' area
+dirlist="cmdline server"
+if [ -e packages/devel ] ; then
+  dirlist="$dirlist devel"
+fi
+
+for d in $dirlist ; do
+  if [ ! -e $GEXTVIDEO_INSTALLED/$d ] ; then
+    echo "Creating $GEXTVIDEO_INSTALLED/$d"
+    mkdir $GEXTVIDEO_INSTALLED/$d
+  fi
+done
+
+for d in packages ; do
+  echo "Running $d/CASCADE-MAKE.sh $*"
+
+  (cd $d ; ./CASCADE-MAKE.sh $*)
+
+  if [ $? != 0 ] ; then
+    echo "Error encountered running $d/CASCADE-MAKE.sh"
+    exit 1
+  fi
+done
+
+
+if [ ! -e $GEXTVIDEO_INSTALLED/server/htdocs/gsdl ] ; then
+  ( cd $GEXTVIDEO_INSTALLED/server/htdocs/ ; \
+    ln -s $GSDLHOME gsdl )
+
+  if [ $? != 0 ] ; then
+    echo "Error encountered configuring lighttpd server 'htdocs' to have symbolic link to gsdl home"
+    echo "Is GSDLHOME set?"
+    exit 1
+  fi
+
+
+fi
Index: extensions/gsdl-video/trunk/START-VIDEO-SERVER.sh
===================================================================
--- extensions/gsdl-video/trunk/START-VIDEO-SERVER.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/START-VIDEO-SERVER.sh	(revision 18425)
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+if [ "x$GEXTVIDEO" = "x" ] ; then
+  echo "Video extension environment variable GEXTVIDEO not set."
+  echo "Have you sourced the extension's setup file, e.g. setup.bash?"
+  exit
+fi
+
+echo "Starting Lighttpd: $GEXT_VIDEO_SERVER$GEXT_VIDEO_PREFIX"
+
+$GEXTVIDEO_INSTALLED/server/sbin/lighttpd -f $GEXTVIDEO_INSTALLED/server/conf/lighttpd.conf
Index: extensions/gsdl-video/trunk/bin/script/test-setup.bash
===================================================================
--- extensions/gsdl-video/trunk/bin/script/test-setup.bash	(revision 18425)
+++ extensions/gsdl-video/trunk/bin/script/test-setup.bash	(revision 18425)
@@ -0,0 +1,8 @@
+
+
+if [ "x$GEXTVIDEO" = "x" ] ; then
+  echo "Video extension environment variable GEXTVIDEO not set."
+  echo "Have you sourced the extension's setup file, e.g. setup.bash?"
+  exit -1
+fi
+
Index: extensions/gsdl-video/trunk/installed/cmdline/bin/erb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/bin/erb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/bin/erb	(revision 18425)
@@ -0,0 +1,141 @@
+#!/research/code/gsdl-video-import/trunk/installed/cmdline/bin/ruby
+# Tiny eRuby --- ERB2
+# Copyright (c) 1999-2000,2002 Masatoshi SEKI 
+# You can redistribute it and/or modify it under the same terms as Ruby.
+
+require 'erb'
+
+class ERB
+  module Main
+    def ARGV.switch
+      return nil if self.empty?
+      arg = self.shift
+      return nil if arg == '--'
+      if arg =~ /^-(.)(.*)/
+        return arg if $1 == '-'
+        raise 'unknown switch "-"' if $2.index('-')
+        self.unshift "-#{$2}" if $2.size > 0
+        "-#{$1}"
+      else
+        self.unshift arg
+        nil
+      end
+    end
+    
+    def ARGV.req_arg
+      self.shift || raise('missing argument')
+    end
+
+    def trim_mode_opt(trim_mode, disable_percent)
+      return trim_mode if disable_percent
+      case trim_mode
+      when 0
+        return '%'
+      when 1
+        return '%>'
+      when 2
+        return '%<>'
+      when '-'
+        return '%-'
+      end
+    end
+    module_function :trim_mode_opt
+
+    def run(factory=ERB)
+      trim_mode = 0
+      disable_percent = false
+      begin
+        while switch = ARGV.switch
+          case switch
+          when '-x'                        # ruby source
+            output = true
+          when '-n'                        # line number
+            number = true
+          when '-v'                        # verbose
+            $VERBOSE = true
+          when '--version'                 # version
+            STDERR.puts factory.version
+            exit
+          when '-d', '--debug'             # debug
+            $DEBUG = true
+          when '-r'                        # require
+            require ARGV.req_arg
+          when '-S'                        # security level
+            arg = ARGV.req_arg
+            raise "invalid safe_level #{arg.dump}" unless arg =~ /^[0-4]$/
+            safe_level = arg.to_i
+          when '-T'                        # trim mode
+            arg = ARGV.req_arg
+            if arg == '-'
+              trim_mode = arg 
+              next
+            end
+            raise "invalid trim mode #{arg.dump}" unless arg =~ /^[0-2]$/
+            trim_mode = arg.to_i
+          when '-K'                        # KCODE
+            arg = ARGV.req_arg
+            case arg.downcase
+            when 'e', '-e', 'euc'
+              $KCODE = 'EUC'
+            when 's', '-s', 'sjis'
+              $KCODE = 'SJIS'
+            when 'u', '-u', 'utf8'
+              $KCODE = 'UTF8'
+            when 'n', '-n', 'none'
+              $KCODE = 'NONE'
+            else
+              raise "invalid KCODE #{arg.dump}"
+            end
+          when '-P'
+            disable_percent = true
+          when '--help'
+            raise "print this help"
+          else
+            raise "unknown switch #{switch.dump}"
+          end
+        end
+      rescue                               # usage
+        STDERR.puts $!.to_s
+        STDERR.puts File.basename($0) + 
+          " [switches] [inputfile]"
+        STDERR.puts <<EOU
+  -x               print ruby script
+  -n               print ruby script with line number
+  -v               enable verbose mode
+  -d               set $DEBUG to true
+  -r [library]     load a library
+  -K [kcode]       specify KANJI code-set
+  -S [safe_level]  set $SAFE (0..4)
+  -T [trim_mode]   specify trim_mode (0..2, -)
+  -P               ignore lines which start with "%"
+EOU
+        exit 1
+      end
+
+      src = $<.read
+      filename = $FILENAME
+      exit 2 unless src
+      trim = trim_mode_opt(trim_mode, disable_percent)
+      erb = factory.new(src.untaint, safe_level, trim)
+      erb.filename = filename
+      if output
+        if number
+          l = 1
+          for line in erb.src
+            puts "%3d %s"%[l, line]
+            l += 1
+          end
+        else
+          puts erb.src
+        end
+      else
+        erb.run(TOPLEVEL_BINDING.taint)
+      end
+    end
+    module_function :run
+  end
+end
+
+if __FILE__ == $0
+  ERB::Main.run
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/bin/flvtool2
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/bin/flvtool2	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/bin/flvtool2	(revision 18425)
@@ -0,0 +1,3 @@
+#! /research/code/gsdl-video-import/trunk/installed/cmdline/bin/ruby
+require 'flvtool2'
+
Index: extensions/gsdl-video/trunk/installed/cmdline/bin/irb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/bin/irb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/bin/irb	(revision 18425)
@@ -0,0 +1,21 @@
+#!/research/code/gsdl-video-import/trunk/installed/cmdline/bin/ruby
+#
+#   irb.rb - intaractive ruby
+#   	$Release Version: 0.9.5 $
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+
+require "irb"
+
+if __FILE__ == $0
+  IRB.start(__FILE__)
+else
+  # check -e option
+  if /^-e$/ =~ $0
+    IRB.start(__FILE__)
+  else
+    IRB.setup(__FILE__)
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/bin/rdoc
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/bin/rdoc	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/bin/rdoc	(revision 18425)
@@ -0,0 +1,67 @@
+#!/research/code/gsdl-video-import/trunk/installed/cmdline/bin/ruby
+#
+#  RDoc: Documentation tool for source code
+#        (see lib/rdoc/rdoc.rb for more information)
+#
+#  Copyright (c) 2003 Dave Thomas
+#  Released under the same terms as Ruby
+#
+#  $Revision: 11708 $
+
+## Transitional Hack ####
+#
+#  RDoc was initially distributed independently, and installed
+#  itself into <prefix>/lib/ruby/site_ruby/<ver>/rdoc...
+#
+#  Now that RDoc is part of the distribution, it's installed into
+#  <prefix>/lib/ruby/<ver>, which unfortunately appears later in the
+#  search path. This means that if you have previously installed RDoc,
+#  and then install from ruby-lang, you'll pick up the old one by
+#  default. This hack checks for the condition, and readjusts the
+#  search path if necessary.
+
+def adjust_for_existing_rdoc(path)
+  
+  $stderr.puts %{
+  It seems as if you have a previously-installed RDoc in
+  the directory #{path}.
+
+  Because this is now out-of-date, you might want to consider
+  removing the directories:
+
+    #{File.join(path, "rdoc")}
+
+  and
+
+    #{File.join(path, "markup")}
+
+  }
+
+  # Move all the site_ruby directories to the end
+  p $:
+  $:.replace($:.partition {|path| /site_ruby/ !~ path}.flatten)
+  p $:
+end
+
+$:.each do |path|
+  if /site_ruby/ =~ path 
+    rdoc_path = File.join(path, 'rdoc', 'rdoc.rb')
+    if File.exists?(rdoc_path)
+      adjust_for_existing_rdoc(path)
+      break
+    end
+  end
+end
+
+## End of Transitional Hack ##
+
+
+require 'rdoc/rdoc'
+
+begin
+  r = RDoc::RDoc.new
+  r.document(ARGV)
+rescue RDoc::RDocError => e
+  $stderr.puts e.message
+  exit(1)
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/bin/ri
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/bin/ri	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/bin/ri	(revision 18425)
@@ -0,0 +1,49 @@
+#!/research/code/gsdl-video-import/trunk/installed/cmdline/bin/ruby
+# usage:
+#
+#   ri  name...
+#
+# where name can be 
+#
+#   Class | Class::method | Class#method | Class.method | method
+#
+# All names may be abbreviated to their minimum unbiguous form. If a name
+# _is_ ambiguous, all valid options will be listed.
+#
+# The form '.' method matches either class or instance methods, while 
+# #method matches only instance and ::method matches only class methods.
+#
+#
+# == Installing Documentation
+#
+# 'ri' uses a database of documentation built by the RDoc utility.
+# 
+# So, how do you install this documentation on your system?
+# It depends on how you installed Ruby.
+#
+# <em>If you installed Ruby from source files</em> (that is, if it some point
+# you typed 'make' during the process :), you can install the RDoc
+# documentation yourself. Just go back to the place where you have 
+# your Ruby source and type
+#
+#    make install-doc
+#
+# You'll probably need to do this as a superuser, as the documentation
+# is installed in the Ruby target tree (normally somewhere under 
+# <tt>/usr/local</tt>.
+#
+# <em>If you installed Ruby from a binary distribution</em> (perhaps
+# using a one-click installer, or using some other packaging system),
+# then the team that produced the package probably forgot to package
+# the documentation as well. Contact them, and see if they can add
+# it to the next release.
+#
+
+
+require 'rdoc/ri/ri_driver'
+
+######################################################################
+
+ri = RiDriver.new
+ri.process_args
+
Index: extensions/gsdl-video/trunk/installed/cmdline/bin/testrb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/bin/testrb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/bin/testrb	(revision 18425)
@@ -0,0 +1,5 @@
+#!/research/code/gsdl-video-import/trunk/installed/cmdline/bin/ruby
+require 'test/unit'
+(r = Test::Unit::AutoRunner.new(true)).process_args(ARGV) or
+  abort r.options.banner + " tests..."
+exit r.run
Index: extensions/gsdl-video/trunk/installed/cmdline/include/a52dec/a52.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/a52dec/a52.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/a52dec/a52.h	(revision 18425)
@@ -0,0 +1,62 @@
+/*
+ * a52.h
+ * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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.
+ *
+ * a52dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef A52_H
+#define A52_H
+
+#ifndef LIBA52_DOUBLE
+typedef float sample_t;
+#else
+typedef double sample_t;
+#endif
+
+typedef struct a52_state_s a52_state_t;
+
+#define A52_CHANNEL 0
+#define A52_MONO 1
+#define A52_STEREO 2
+#define A52_3F 3
+#define A52_2F1R 4
+#define A52_3F1R 5
+#define A52_2F2R 6
+#define A52_3F2R 7
+#define A52_CHANNEL1 8
+#define A52_CHANNEL2 9
+#define A52_DOLBY 10
+#define A52_CHANNEL_MASK 15
+
+#define A52_LFE 16
+#define A52_ADJUST_LEVEL 32
+
+a52_state_t * a52_init (uint32_t mm_accel);
+sample_t * a52_samples (a52_state_t * state);
+int a52_syncinfo (uint8_t * buf, int * flags,
+		  int * sample_rate, int * bit_rate);
+int a52_frame (a52_state_t * state, uint8_t * buf, int * flags,
+	       sample_t * level, sample_t bias);
+void a52_dynrng (a52_state_t * state,
+		 sample_t (* call) (sample_t, void *), void * data);
+int a52_block (a52_state_t * state);
+void a52_free (a52_state_t * state);
+
+#endif /* A52_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/a52dec/attributes.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/a52dec/attributes.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/a52dec/attributes.h	(revision 18425)
@@ -0,0 +1,29 @@
+/*
+ * attributes.h
+ * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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.
+ *
+ * a52dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* use gcc attribs to align critical data structures */
+#ifdef ATTRIBUTE_ALIGNED_MAX
+#define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align)))
+#else
+#define ATTR_ALIGN(align)
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/include/a52dec/audio_out.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/a52dec/audio_out.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/a52dec/audio_out.h	(revision 18425)
@@ -0,0 +1,64 @@
+/*
+ * audio_out.h
+ * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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.
+ *
+ * a52dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+typedef struct ao_instance_s ao_instance_t;
+
+struct ao_instance_s {
+    int (* setup) (ao_instance_t * instance, int sample_rate, int * flags,
+		   sample_t * level, sample_t * bias);
+    int (* play) (ao_instance_t * instance, int flags, sample_t * samples);
+    void (* close) (ao_instance_t * instance);
+};
+
+typedef ao_instance_t * ao_open_t (void);
+
+typedef struct ao_driver_s {
+    char * name;
+    ao_open_t * open;
+} ao_driver_t;
+
+/* return NULL terminated array of all drivers */
+ao_driver_t * ao_drivers (void);
+
+static inline ao_instance_t * ao_open (ao_open_t * open)
+{
+    return open ();
+}
+
+static inline int ao_setup (ao_instance_t * instance, int sample_rate,
+			    int * flags, sample_t * level, sample_t * bias)
+{
+    return instance->setup (instance, sample_rate, flags, level, bias);
+}
+
+static inline int ao_play (ao_instance_t * instance, int flags,
+			   sample_t * samples)
+{
+    return instance->play (instance, flags, samples);
+}
+
+static inline void ao_close (ao_instance_t * instance)
+{
+    if (instance->close)
+	instance->close (instance);
+}
Index: extensions/gsdl-video/trunk/installed/cmdline/include/a52dec/mm_accel.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/a52dec/mm_accel.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/a52dec/mm_accel.h	(revision 18425)
@@ -0,0 +1,37 @@
+/*
+ * mm_accel.h
+ * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of a52dec, a free ATSC A-52 stream decoder.
+ * See http://liba52.sourceforge.net/ for updates.
+ *
+ * a52dec 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.
+ *
+ * a52dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef MM_ACCEL_H
+#define MM_ACCEL_H
+
+/* generic accelerations */
+#define MM_ACCEL_DJBFFT		0x00000001
+
+/* x86 accelerations */
+#define MM_ACCEL_X86_MMX	0x80000000
+#define MM_ACCEL_X86_3DNOW	0x40000000
+#define MM_ACCEL_X86_MMXEXT	0x20000000
+
+uint32_t mm_accel (void);
+
+#endif /* MM_ACCEL_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/faac.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/faac.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/faac.h	(revision 18425)
@@ -0,0 +1,99 @@
+/*
+ * FAAC - Freeware Advanced Audio Coder
+ * Copyright (C) 2001 Menno Bakker
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * $Id: faac.h,v 1.33 2004/07/04 12:12:05 corrados Exp $
+ */
+
+#ifndef _FAAC_H_
+#define _FAAC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifdef WIN32
+# ifndef FAACAPI
+#  define FAACAPI __stdcall
+# endif
+#else
+# ifndef FAACAPI
+#  define FAACAPI
+# endif
+#endif
+
+#pragma pack(push, 1)
+
+typedef struct {
+  void *ptr;
+  char *name;
+}
+psymodellist_t;
+
+#include "faaccfg.h"
+
+
+typedef void *faacEncHandle;
+
+#ifndef HAVE_INT32_T
+typedef int int32_t;
+#endif
+
+/*
+	Allows an application to get FAAC version info. This is intended
+	purely for informative purposes.
+
+	Returns FAAC_CFG_VERSION.
+*/
+int FAACAPI faacEncGetVersion(char **faac_id_string,
+			      char **faac_copyright_string);
+
+
+faacEncConfigurationPtr FAACAPI
+  faacEncGetCurrentConfiguration(faacEncHandle hEncoder);
+
+
+int FAACAPI faacEncSetConfiguration(faacEncHandle hEncoder,
+				    faacEncConfigurationPtr config);
+
+
+faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate,
+				  unsigned int numChannels,
+				  unsigned long *inputSamples,
+				  unsigned long *maxOutputBytes);
+
+
+int FAACAPI faacEncGetDecoderSpecificInfo(faacEncHandle hEncoder, unsigned char **ppBuffer,
+					  unsigned long *pSizeOfDecoderSpecificInfo);
+
+
+int FAACAPI faacEncEncode(faacEncHandle hEncoder, int32_t * inputBuffer, unsigned int samplesInput,
+			 unsigned char *outputBuffer,
+			 unsigned int bufferSize);
+
+
+int FAACAPI faacEncClose(faacEncHandle hEncoder);
+
+
+
+#pragma pack(pop)
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _FAAC_H_ */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/faaccfg.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/faaccfg.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/faaccfg.h	(revision 18425)
@@ -0,0 +1,122 @@
+/*
+ * FAAC - Freeware Advanced Audio Coder
+ * Copyright (C) 2001 Menno Bakker
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * $Id: faaccfg.h,v 1.3 2004/07/04 12:12:05 corrados Exp $
+ */
+
+#ifndef _FAACCFG_H_
+#define _FAACCFG_H_
+
+#define FAAC_CFG_VERSION 104
+
+/* MPEG ID's */
+#define MPEG2 1
+#define MPEG4 0
+
+/* AAC object types */
+#define MAIN 1
+#define LOW  2
+#define SSR  3
+#define LTP  4
+
+/* Input Formats */
+#define FAAC_INPUT_NULL    0
+#define FAAC_INPUT_16BIT   1
+#define FAAC_INPUT_24BIT   2
+#define FAAC_INPUT_32BIT   3
+#define FAAC_INPUT_FLOAT   4
+
+#define SHORTCTL_NORMAL    0
+#define SHORTCTL_NOSHORT   1
+#define SHORTCTL_NOLONG    2
+
+#pragma pack(push, 1)
+typedef struct faacEncConfiguration
+{
+    /* config version */
+    int version;
+
+    /* library version */
+    char *name;
+
+    /* copyright string */
+    char *copyright;
+
+    /* MPEG version, 2 or 4 */
+    unsigned int mpegVersion;
+
+    /* AAC object type */
+    unsigned int aacObjectType;
+
+    /* Allow mid/side coding */
+    unsigned int allowMidside;
+
+    /* Use one of the channels as LFE channel */
+    unsigned int useLfe;
+
+    /* Use Temporal Noise Shaping */
+    unsigned int useTns;
+
+    /* bitrate / channel of AAC file */
+    unsigned long bitRate;
+
+    /* AAC file frequency bandwidth */
+    unsigned int bandWidth;
+
+    /* Quantizer quality */
+    unsigned long quantqual;
+
+    /* Bitstream output format (0 = Raw; 1 = ADTS) */
+    unsigned int outputFormat;
+
+    /* psychoacoustic model list */
+    psymodellist_t *psymodellist;
+
+    /* selected index in psymodellist */
+    unsigned int psymodelidx;
+
+    /*
+		PCM Sample Input Format
+		0	FAAC_INPUT_NULL			invalid, signifies a misconfigured config
+		1	FAAC_INPUT_16BIT		native endian 16bit
+		2	FAAC_INPUT_24BIT		native endian 24bit in 24 bits		(not implemented)
+		3	FAAC_INPUT_32BIT		native endian 24bit in 32 bits		(DEFAULT)
+		4	FAAC_INPUT_FLOAT		32bit floating point
+    */
+    unsigned int inputFormat;
+
+    /* block type enforcing (SHORTCTL_NORMAL/SHORTCTL_NOSHORT/SHORTCTL_NOLONG) */
+    int shortctl;
+	
+	/*
+		Channel Remapping
+
+		Default			0, 1, 2, 3 ... 63  (64 is MAX_CHANNELS in coder.h)
+
+		WAVE 4.0		2, 0, 1, 3
+		WAVE 5.0		2, 0, 1, 3, 4
+		WAVE 5.1		2, 0, 1, 4, 5, 3
+		AIFF 5.1		2, 0, 3, 1, 4, 5 
+	*/
+	int channel_map[64];	
+
+} faacEncConfiguration, *faacEncConfigurationPtr;
+
+#pragma pack(pop)
+
+#endif /* _FAACCFG_H_ */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/faad.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/faad.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/faad.h	(revision 18425)
@@ -0,0 +1,35 @@
+/*
+** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
+** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+** 
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+** 
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software 
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** Any non-GPL usage of this software or parts of this software is strictly
+** forbidden.
+**
+** The "appropriate copyright message" mentioned in section 2c of the GPLv2
+** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
+**
+** Commercial non-GPL licensing of this software is possible.
+** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
+**
+** $Id: faad.h,v 1.51 2007/11/01 12:33:29 menno Exp $
+**/
+
+/* warn people for update */
+#pragma message("please update faad2 include filename and function names!")
+
+/* Backwards compatible link */
+#include "neaacdec.h"
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/adler32.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/adler32.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/adler32.h	(revision 18425)
@@ -0,0 +1,29 @@
+/*
+ * copyright (c) 2006 Mans Rullgard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef ADLER32_H
+#define ADLER32_H
+
+#include <stdint.h>
+
+unsigned long av_adler32_update(unsigned long adler, const uint8_t *buf,
+                                unsigned int len);
+
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avcodec.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avcodec.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avcodec.h	(revision 18425)
@@ -0,0 +1,2936 @@
+/*
+ * copyright (c) 2001 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_H
+#define AVCODEC_H
+
+/**
+ * @file avcodec.h
+ * external API header
+ */
+
+
+#include "avutil.h"
+#include <sys/types.h> /* size_t */
+
+#define AV_STRINGIFY(s)         AV_TOSTRING(s)
+#define AV_TOSTRING(s) #s
+
+#define LIBAVCODEC_VERSION_INT  ((51<<16)+(40<<8)+4)
+#define LIBAVCODEC_VERSION      51.40.4
+#define LIBAVCODEC_BUILD        LIBAVCODEC_VERSION_INT
+
+#define LIBAVCODEC_IDENT        "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION)
+
+#define AV_NOPTS_VALUE          INT64_C(0x8000000000000000)
+#define AV_TIME_BASE            1000000
+#define AV_TIME_BASE_Q          (AVRational){1, AV_TIME_BASE}
+
+/**
+ * Identifies the syntax and semantics of the bitstream.
+ * The principle is roughly:
+ * Two decoders with the same ID can decode the same streams.
+ * Two encoders with the same ID can encode compatible streams.
+ * There may be slight deviations from the principle due to implementation
+ * details.
+ *
+ * If you add a codec ID to this list, add it so that
+ * 1. no value of a existing codec ID changes (that would break ABI),
+ * 2. it is as close as possible to similar codecs.
+ */
+enum CodecID {
+    CODEC_ID_NONE,
+    CODEC_ID_MPEG1VIDEO,
+    CODEC_ID_MPEG2VIDEO, /* preferred ID for MPEG-1/2 video decoding */
+    CODEC_ID_MPEG2VIDEO_XVMC,
+    CODEC_ID_H261,
+    CODEC_ID_H263,
+    CODEC_ID_RV10,
+    CODEC_ID_RV20,
+    CODEC_ID_MJPEG,
+    CODEC_ID_MJPEGB,
+    CODEC_ID_LJPEG,
+    CODEC_ID_SP5X,
+    CODEC_ID_JPEGLS,
+    CODEC_ID_MPEG4,
+    CODEC_ID_RAWVIDEO,
+    CODEC_ID_MSMPEG4V1,
+    CODEC_ID_MSMPEG4V2,
+    CODEC_ID_MSMPEG4V3,
+    CODEC_ID_WMV1,
+    CODEC_ID_WMV2,
+    CODEC_ID_H263P,
+    CODEC_ID_H263I,
+    CODEC_ID_FLV1,
+    CODEC_ID_SVQ1,
+    CODEC_ID_SVQ3,
+    CODEC_ID_DVVIDEO,
+    CODEC_ID_HUFFYUV,
+    CODEC_ID_CYUV,
+    CODEC_ID_H264,
+    CODEC_ID_INDEO3,
+    CODEC_ID_VP3,
+    CODEC_ID_THEORA,
+    CODEC_ID_ASV1,
+    CODEC_ID_ASV2,
+    CODEC_ID_FFV1,
+    CODEC_ID_4XM,
+    CODEC_ID_VCR1,
+    CODEC_ID_CLJR,
+    CODEC_ID_MDEC,
+    CODEC_ID_ROQ,
+    CODEC_ID_INTERPLAY_VIDEO,
+    CODEC_ID_XAN_WC3,
+    CODEC_ID_XAN_WC4,
+    CODEC_ID_RPZA,
+    CODEC_ID_CINEPAK,
+    CODEC_ID_WS_VQA,
+    CODEC_ID_MSRLE,
+    CODEC_ID_MSVIDEO1,
+    CODEC_ID_IDCIN,
+    CODEC_ID_8BPS,
+    CODEC_ID_SMC,
+    CODEC_ID_FLIC,
+    CODEC_ID_TRUEMOTION1,
+    CODEC_ID_VMDVIDEO,
+    CODEC_ID_MSZH,
+    CODEC_ID_ZLIB,
+    CODEC_ID_QTRLE,
+    CODEC_ID_SNOW,
+    CODEC_ID_TSCC,
+    CODEC_ID_ULTI,
+    CODEC_ID_QDRAW,
+    CODEC_ID_VIXL,
+    CODEC_ID_QPEG,
+    CODEC_ID_XVID,
+    CODEC_ID_PNG,
+    CODEC_ID_PPM,
+    CODEC_ID_PBM,
+    CODEC_ID_PGM,
+    CODEC_ID_PGMYUV,
+    CODEC_ID_PAM,
+    CODEC_ID_FFVHUFF,
+    CODEC_ID_RV30,
+    CODEC_ID_RV40,
+    CODEC_ID_VC1,
+    CODEC_ID_WMV3,
+    CODEC_ID_LOCO,
+    CODEC_ID_WNV1,
+    CODEC_ID_AASC,
+    CODEC_ID_INDEO2,
+    CODEC_ID_FRAPS,
+    CODEC_ID_TRUEMOTION2,
+    CODEC_ID_BMP,
+    CODEC_ID_CSCD,
+    CODEC_ID_MMVIDEO,
+    CODEC_ID_ZMBV,
+    CODEC_ID_AVS,
+    CODEC_ID_SMACKVIDEO,
+    CODEC_ID_NUV,
+    CODEC_ID_KMVC,
+    CODEC_ID_FLASHSV,
+    CODEC_ID_CAVS,
+    CODEC_ID_JPEG2000,
+    CODEC_ID_VMNC,
+    CODEC_ID_VP5,
+    CODEC_ID_VP6,
+    CODEC_ID_VP6F,
+    CODEC_ID_TARGA,
+    CODEC_ID_DSICINVIDEO,
+    CODEC_ID_TIERTEXSEQVIDEO,
+    CODEC_ID_TIFF,
+    CODEC_ID_GIF,
+    CODEC_ID_FFH264,
+    CODEC_ID_DXA,
+    CODEC_ID_DNXHD,
+    CODEC_ID_THP,
+    CODEC_ID_SGI,
+    CODEC_ID_C93,
+    CODEC_ID_BETHSOFTVID,
+    CODEC_ID_PTX,
+    CODEC_ID_TXD,
+
+    /* various PCM "codecs" */
+    CODEC_ID_PCM_S16LE= 0x10000,
+    CODEC_ID_PCM_S16BE,
+    CODEC_ID_PCM_U16LE,
+    CODEC_ID_PCM_U16BE,
+    CODEC_ID_PCM_S8,
+    CODEC_ID_PCM_U8,
+    CODEC_ID_PCM_MULAW,
+    CODEC_ID_PCM_ALAW,
+    CODEC_ID_PCM_S32LE,
+    CODEC_ID_PCM_S32BE,
+    CODEC_ID_PCM_U32LE,
+    CODEC_ID_PCM_U32BE,
+    CODEC_ID_PCM_S24LE,
+    CODEC_ID_PCM_S24BE,
+    CODEC_ID_PCM_U24LE,
+    CODEC_ID_PCM_U24BE,
+    CODEC_ID_PCM_S24DAUD,
+
+    /* various ADPCM codecs */
+    CODEC_ID_ADPCM_IMA_QT= 0x11000,
+    CODEC_ID_ADPCM_IMA_WAV,
+    CODEC_ID_ADPCM_IMA_DK3,
+    CODEC_ID_ADPCM_IMA_DK4,
+    CODEC_ID_ADPCM_IMA_WS,
+    CODEC_ID_ADPCM_IMA_SMJPEG,
+    CODEC_ID_ADPCM_MS,
+    CODEC_ID_ADPCM_4XM,
+    CODEC_ID_ADPCM_XA,
+    CODEC_ID_ADPCM_ADX,
+    CODEC_ID_ADPCM_EA,
+    CODEC_ID_ADPCM_G726,
+    CODEC_ID_ADPCM_CT,
+    CODEC_ID_ADPCM_SWF,
+    CODEC_ID_ADPCM_YAMAHA,
+    CODEC_ID_ADPCM_SBPRO_4,
+    CODEC_ID_ADPCM_SBPRO_3,
+    CODEC_ID_ADPCM_SBPRO_2,
+    CODEC_ID_ADPCM_THP,
+
+    /* AMR */
+    CODEC_ID_AMR_NB= 0x12000,
+    CODEC_ID_AMR_WB,
+
+    /* RealAudio codecs*/
+    CODEC_ID_RA_144= 0x13000,
+    CODEC_ID_RA_288,
+
+    /* various DPCM codecs */
+    CODEC_ID_ROQ_DPCM= 0x14000,
+    CODEC_ID_INTERPLAY_DPCM,
+    CODEC_ID_XAN_DPCM,
+    CODEC_ID_SOL_DPCM,
+
+    CODEC_ID_MP2= 0x15000,
+    CODEC_ID_MP3, /* preferred ID for decoding MPEG audio layer 1, 2 or 3 */
+    CODEC_ID_AAC,
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+    CODEC_ID_MPEG4AAC,
+#endif
+    CODEC_ID_AC3,
+    CODEC_ID_DTS,
+    CODEC_ID_VORBIS,
+    CODEC_ID_DVAUDIO,
+    CODEC_ID_WMAV1,
+    CODEC_ID_WMAV2,
+    CODEC_ID_MACE3,
+    CODEC_ID_MACE6,
+    CODEC_ID_VMDAUDIO,
+    CODEC_ID_SONIC,
+    CODEC_ID_SONIC_LS,
+    CODEC_ID_FLAC,
+    CODEC_ID_MP3ADU,
+    CODEC_ID_MP3ON4,
+    CODEC_ID_SHORTEN,
+    CODEC_ID_ALAC,
+    CODEC_ID_WESTWOOD_SND1,
+    CODEC_ID_GSM, /* as in Berlin toast format */
+    CODEC_ID_QDM2,
+    CODEC_ID_COOK,
+    CODEC_ID_TRUESPEECH,
+    CODEC_ID_TTA,
+    CODEC_ID_SMACKAUDIO,
+    CODEC_ID_QCELP,
+    CODEC_ID_WAVPACK,
+    CODEC_ID_DSICINAUDIO,
+    CODEC_ID_IMC,
+    CODEC_ID_MUSEPACK7,
+    CODEC_ID_MLP,
+    CODEC_ID_GSM_MS, /* as found in WAV */
+    CODEC_ID_ATRAC3,
+
+    /* subtitle codecs */
+    CODEC_ID_DVD_SUBTITLE= 0x17000,
+    CODEC_ID_DVB_SUBTITLE,
+    CODEC_ID_TEXT,  /* raw UTF-8 text */
+
+    CODEC_ID_MPEG2TS= 0x20000, /* _FAKE_ codec to indicate a raw MPEG-2 TS
+                                * stream (only used by libavformat) */
+};
+
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+/* CODEC_ID_MP3LAME is obsolete */
+#define CODEC_ID_MP3LAME CODEC_ID_MP3
+#define CODEC_ID_MPEG4AAC CODEC_ID_AAC
+#endif
+
+enum CodecType {
+    CODEC_TYPE_UNKNOWN = -1,
+    CODEC_TYPE_VIDEO,
+    CODEC_TYPE_AUDIO,
+    CODEC_TYPE_DATA,
+    CODEC_TYPE_SUBTITLE,
+    CODEC_TYPE_NB
+};
+
+/* Currently unused, may be used if 24/32 bits samples are ever supported. */
+/* all in native-endian format */
+enum SampleFormat {
+    SAMPLE_FMT_NONE = -1,
+    SAMPLE_FMT_U8,              ///< unsigned 8 bits
+    SAMPLE_FMT_S16,             ///< signed 16 bits
+    SAMPLE_FMT_S24,             ///< signed 24 bits
+    SAMPLE_FMT_S32,             ///< signed 32 bits
+    SAMPLE_FMT_FLT,             ///< float
+};
+
+/* in bytes */
+#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
+
+/**
+ * Required number of additionally allocated bytes at the end of the input bitstream for decoding.
+ * This is mainly needed because some optimized bitstream readers read
+ * 32 or 64 bit at once and could read over the end.<br>
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged
+ * MPEG bitstreams could cause overread and segfault.
+ */
+#define FF_INPUT_BUFFER_PADDING_SIZE 8
+
+/**
+ * minimum encoding buffer size
+ * Used to avoid some checks during header writing.
+ */
+#define FF_MIN_BUFFER_SIZE 16384
+
+/* motion estimation type, EPZS by default */
+enum Motion_Est_ID {
+    ME_ZERO = 1,
+    ME_FULL,
+    ME_LOG,
+    ME_PHODS,
+    ME_EPZS,
+    ME_X1,
+    ME_HEX,
+    ME_UMH,
+    ME_ITER,
+};
+
+enum AVDiscard{
+    /* We leave some space between them for extensions (drop some
+     * keyframes for intra-only or drop just some bidir frames). */
+    AVDISCARD_NONE   =-16, ///< discard nothing
+    AVDISCARD_DEFAULT=  0, ///< discard useless packets like 0 size packets in avi
+    AVDISCARD_NONREF =  8, ///< discard all non reference
+    AVDISCARD_BIDIR  = 16, ///< discard all bidirectional frames
+    AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes
+    AVDISCARD_ALL    = 48, ///< discard all
+};
+
+typedef struct RcOverride{
+    int start_frame;
+    int end_frame;
+    int qscale; // If this is 0 then quality_factor will be used instead.
+    float quality_factor;
+} RcOverride;
+
+#define FF_MAX_B_FRAMES 16
+
+/* encoding support
+   These flags can be passed in AVCodecContext.flags before initialization.
+   Note: Not everything is supported yet.
+*/
+
+#define CODEC_FLAG_QSCALE 0x0002  ///< Use fixed qscale.
+#define CODEC_FLAG_4MV    0x0004  ///< 4 MV per MB allowed / advanced prediction for H.263.
+#define CODEC_FLAG_QPEL   0x0010  ///< Use qpel MC.
+#define CODEC_FLAG_GMC    0x0020  ///< Use GMC.
+#define CODEC_FLAG_MV0    0x0040  ///< Always try a MB with MV=<0,0>.
+#define CODEC_FLAG_PART   0x0080  ///< Use data partitioning.
+/* The parent program guarantees that the input for B-frames containing
+ * streams is not written to for at least s->max_b_frames+1 frames, if
+ * this is not set the input will be copied. */
+#define CODEC_FLAG_INPUT_PRESERVED 0x0100
+#define CODEC_FLAG_PASS1 0x0200   ///< Use internal 2pass ratecontrol in first pass mode.
+#define CODEC_FLAG_PASS2 0x0400   ///< Use internal 2pass ratecontrol in second pass mode.
+#define CODEC_FLAG_EXTERN_HUFF 0x1000 ///< Use external Huffman table (for MJPEG).
+#define CODEC_FLAG_GRAY  0x2000   ///< Only decode/encode grayscale.
+#define CODEC_FLAG_EMU_EDGE 0x4000///< Don't draw edges.
+#define CODEC_FLAG_PSNR           0x8000 ///< error[?] variables will be set during encoding.
+#define CODEC_FLAG_TRUNCATED  0x00010000 /** Input bitstream might be truncated at a random location instead
+                                            of only at frame boundaries. */
+#define CODEC_FLAG_NORMALIZE_AQP  0x00020000 ///< Normalize adaptive quantization.
+#define CODEC_FLAG_INTERLACED_DCT 0x00040000 ///< Use interlaced DCT.
+#define CODEC_FLAG_LOW_DELAY      0x00080000 ///< Force low delay.
+#define CODEC_FLAG_ALT_SCAN       0x00100000 ///< Use alternate scan.
+#define CODEC_FLAG_TRELLIS_QUANT  0x00200000 ///< Use trellis quantization.
+#define CODEC_FLAG_GLOBAL_HEADER  0x00400000 ///< Place global headers in extradata instead of every keyframe.
+#define CODEC_FLAG_BITEXACT       0x00800000 ///< Use only bitexact stuff (except (I)DCT).
+/* Fx : Flag for h263+ extra options */
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+#define CODEC_FLAG_H263P_AIC      0x01000000 ///< H.263 advanced intra coding / MPEG-4 AC prediction (remove this)
+#endif
+#define CODEC_FLAG_AC_PRED        0x01000000 ///< H.263 advanced intra coding / MPEG-4 AC prediction
+#define CODEC_FLAG_H263P_UMV      0x02000000 ///< unlimited motion vector
+#define CODEC_FLAG_CBP_RD         0x04000000 ///< Use rate distortion optimization for cbp.
+#define CODEC_FLAG_QP_RD          0x08000000 ///< Use rate distortion optimization for qp selectioon.
+#define CODEC_FLAG_H263P_AIV      0x00000008 ///< H.263 alternative inter VLC
+#define CODEC_FLAG_OBMC           0x00000001 ///< OBMC
+#define CODEC_FLAG_LOOP_FILTER    0x00000800 ///< loop filter
+#define CODEC_FLAG_H263P_SLICE_STRUCT 0x10000000
+#define CODEC_FLAG_INTERLACED_ME  0x20000000 ///< interlaced motion estimation
+#define CODEC_FLAG_SVCD_SCAN_OFFSET 0x40000000 ///< Will reserve space for SVCD scan offset user data.
+#define CODEC_FLAG_CLOSED_GOP     ((int)0x80000000)
+#define CODEC_FLAG2_FAST          0x00000001 ///< Allow non spec compliant speedup tricks.
+#define CODEC_FLAG2_STRICT_GOP    0x00000002 ///< Strictly enforce GOP size.
+#define CODEC_FLAG2_NO_OUTPUT     0x00000004 ///< Skip bitstream encoding.
+#define CODEC_FLAG2_LOCAL_HEADER  0x00000008 ///< Place global headers at every keyframe instead of in extradata.
+#define CODEC_FLAG2_BPYRAMID      0x00000010 ///< H.264 allow B-frames to be used as references.
+#define CODEC_FLAG2_WPRED         0x00000020 ///< H.264 weighted biprediction for B-frames
+#define CODEC_FLAG2_MIXED_REFS    0x00000040 ///< H.264 one reference per partition, as opposed to one reference per macroblock
+#define CODEC_FLAG2_8X8DCT        0x00000080 ///< H.264 high profile 8x8 transform
+#define CODEC_FLAG2_FASTPSKIP     0x00000100 ///< H.264 fast pskip
+#define CODEC_FLAG2_AUD           0x00000200 ///< H.264 access unit delimiters
+#define CODEC_FLAG2_BRDO          0x00000400 ///< B-frame rate-distortion optimization
+#define CODEC_FLAG2_INTRA_VLC     0x00000800 ///< Use MPEG-2 intra VLC table.
+#define CODEC_FLAG2_MEMC_ONLY     0x00001000 ///< Only do ME/MC (I frames -> ref, P frame -> ME+MC).
+#define CODEC_FLAG2_DROP_FRAME_TIMECODE 0x00002000 ///< timecode is in drop frame format.
+#define CODEC_FLAG2_SKIP_RD       0x00004000 ///< RD optimal MB level residual skipping
+#define CODEC_FLAG2_CHUNKS        0x00008000 ///< Input bitstream might be truncated at a packet boundaries instead of only at frame boundaries.
+#define CODEC_FLAG2_NON_LINEAR_QUANT 0x00010000 ///< Use MPEG-2 nonlinear quantizer.
+
+/* Unsupported options :
+ *              Syntax Arithmetic coding (SAC)
+ *              Reference Picture Selection
+ *              Independent Segment Decoding */
+/* /Fx */
+/* codec capabilities */
+
+#define CODEC_CAP_DRAW_HORIZ_BAND 0x0001 ///< Decoder can use draw_horiz_band callback.
+/**
+ * Codec uses get_buffer() for allocating buffers.
+ * direct rendering method 1
+ */
+#define CODEC_CAP_DR1             0x0002
+/* If 'parse_only' field is true, then avcodec_parse_frame() can be used. */
+#define CODEC_CAP_PARSE_ONLY      0x0004
+#define CODEC_CAP_TRUNCATED       0x0008
+/* Codec can export data for HW decoding (XvMC). */
+#define CODEC_CAP_HWACCEL         0x0010
+/**
+ * Codec has a nonzero delay and needs to be fed with NULL at the end to get the delayed data.
+ * If this is not set, the codec is guaranteed to never be fed with NULL data.
+ */
+#define CODEC_CAP_DELAY           0x0020
+/**
+ * Codec can be fed a final frame with a smaller size.
+ * This can be used to prevent truncation of the last audio samples.
+ */
+#define CODEC_CAP_SMALL_LAST_FRAME 0x0040
+
+//The following defines may change, don't expect compatibility if you use them.
+#define MB_TYPE_INTRA4x4   0x0001
+#define MB_TYPE_INTRA16x16 0x0002 //FIXME H.264-specific
+#define MB_TYPE_INTRA_PCM  0x0004 //FIXME H.264-specific
+#define MB_TYPE_16x16      0x0008
+#define MB_TYPE_16x8       0x0010
+#define MB_TYPE_8x16       0x0020
+#define MB_TYPE_8x8        0x0040
+#define MB_TYPE_INTERLACED 0x0080
+#define MB_TYPE_DIRECT2     0x0100 //FIXME
+#define MB_TYPE_ACPRED     0x0200
+#define MB_TYPE_GMC        0x0400
+#define MB_TYPE_SKIP       0x0800
+#define MB_TYPE_P0L0       0x1000
+#define MB_TYPE_P1L0       0x2000
+#define MB_TYPE_P0L1       0x4000
+#define MB_TYPE_P1L1       0x8000
+#define MB_TYPE_L0         (MB_TYPE_P0L0 | MB_TYPE_P1L0)
+#define MB_TYPE_L1         (MB_TYPE_P0L1 | MB_TYPE_P1L1)
+#define MB_TYPE_L0L1       (MB_TYPE_L0   | MB_TYPE_L1)
+#define MB_TYPE_QUANT      0x00010000
+#define MB_TYPE_CBP        0x00020000
+//Note bits 24-31 are reserved for codec specific use (h264 ref0, mpeg1 0mv, ...)
+
+/**
+ * Pan Scan area.
+ * This specifies the area which should be displayed.
+ * Note there may be multiple such areas for one frame.
+ */
+typedef struct AVPanScan{
+    /**
+     * id
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     */
+    int id;
+
+    /**
+     * width and height in 1/16 pel
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     */
+    int width;
+    int height;
+
+    /**
+     * position of the top left corner in 1/16 pel for up to 3 fields/frames
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     */
+    int16_t position[3][2];
+}AVPanScan;
+
+#define FF_COMMON_FRAME \
+    /**\
+     * pointer to the picture planes.\
+     * This might be different from the first allocated byte\
+     * - encoding: \
+     * - decoding: \
+     */\
+    uint8_t *data[4];\
+    int linesize[4];\
+    /**\
+     * pointer to the first allocated byte of the picture. Can be used in get_buffer/release_buffer.\
+     * This isn't used by libavcodec unless the default get/release_buffer() is used.\
+     * - encoding: \
+     * - decoding: \
+     */\
+    uint8_t *base[4];\
+    /**\
+     * 1 -> keyframe, 0-> not\
+     * - encoding: Set by libavcodec.\
+     * - decoding: Set by libavcodec.\
+     */\
+    int key_frame;\
+\
+    /**\
+     * Picture type of the frame, see ?_TYPE below.\
+     * - encoding: Set by libavcodec. for coded_picture (and set by user for input).\
+     * - decoding: Set by libavcodec.\
+     */\
+    int pict_type;\
+\
+    /**\
+     * presentation timestamp in time_base units (time when frame should be shown to user)\
+     * If AV_NOPTS_VALUE then frame_rate = 1/time_base will be assumed.\
+     * - encoding: MUST be set by user.\
+     * - decoding: Set by libavcodec.\
+     */\
+    int64_t pts;\
+\
+    /**\
+     * picture number in bitstream order\
+     * - encoding: set by\
+     * - decoding: Set by libavcodec.\
+     */\
+    int coded_picture_number;\
+    /**\
+     * picture number in display order\
+     * - encoding: set by\
+     * - decoding: Set by libavcodec.\
+     */\
+    int display_picture_number;\
+\
+    /**\
+     * quality (between 1 (good) and FF_LAMBDA_MAX (bad)) \
+     * - encoding: Set by libavcodec. for coded_picture (and set by user for input).\
+     * - decoding: Set by libavcodec.\
+     */\
+    int quality; \
+\
+    /**\
+     * buffer age (1->was last buffer and dint change, 2->..., ...).\
+     * Set to INT_MAX if the buffer has not been used yet.\
+     * - encoding: unused\
+     * - decoding: MUST be set by get_buffer().\
+     */\
+    int age;\
+\
+    /**\
+     * is this picture used as reference\
+     * - encoding: unused\
+     * - decoding: Set by libavcodec. (before get_buffer() call)).\
+     */\
+    int reference;\
+\
+    /**\
+     * QP table\
+     * - encoding: unused\
+     * - decoding: Set by libavcodec.\
+     */\
+    int8_t *qscale_table;\
+    /**\
+     * QP store stride\
+     * - encoding: unused\
+     * - decoding: Set by libavcodec.\
+     */\
+    int qstride;\
+\
+    /**\
+     * mbskip_table[mb]>=1 if MB didn't change\
+     * stride= mb_width = (width+15)>>4\
+     * - encoding: unused\
+     * - decoding: Set by libavcodec.\
+     */\
+    uint8_t *mbskip_table;\
+\
+    /**\
+     * motion vector table\
+     * @code\
+     * example:\
+     * int mv_sample_log2= 4 - motion_subsample_log2;\
+     * int mb_width= (width+15)>>4;\
+     * int mv_stride= (mb_width << mv_sample_log2) + 1;\
+     * motion_val[direction][x + y*mv_stride][0->mv_x, 1->mv_y];\
+     * @endcode\
+     * - encoding: Set by user.\
+     * - decoding: Set by libavcodec.\
+     */\
+    int16_t (*motion_val[2])[2];\
+\
+    /**\
+     * macroblock type table\
+     * mb_type_base + mb_width + 2\
+     * - encoding: Set by user.\
+     * - decoding: Set by libavcodec.\
+     */\
+    uint32_t *mb_type;\
+\
+    /**\
+     * log2 of the size of the block which a single vector in motion_val represents: \
+     * (4->16x16, 3->8x8, 2-> 4x4, 1-> 2x2)\
+     * - encoding: unused\
+     * - decoding: Set by libavcodec.\
+     */\
+    uint8_t motion_subsample_log2;\
+\
+    /**\
+     * for some private data of the user\
+     * - encoding: unused\
+     * - decoding: Set by user.\
+     */\
+    void *opaque;\
+\
+    /**\
+     * error\
+     * - encoding: Set by libavcodec. if flags&CODEC_FLAG_PSNR.\
+     * - decoding: unused\
+     */\
+    uint64_t error[4];\
+\
+    /**\
+     * type of the buffer (to keep track of who has to deallocate data[*])\
+     * - encoding: Set by the one who allocates it.\
+     * - decoding: Set by the one who allocates it.\
+     * Note: User allocated (direct rendering) & internal buffers cannot coexist currently.\
+     */\
+    int type;\
+    \
+    /**\
+     * When decoding, this signals how much the picture must be delayed.\
+     * extra_delay = repeat_pict / (2*fps)\
+     * - encoding: unused\
+     * - decoding: Set by libavcodec.\
+     */\
+    int repeat_pict;\
+    \
+    /**\
+     * \
+     */\
+    int qscale_type;\
+    \
+    /**\
+     * The content of the picture is interlaced.\
+     * - encoding: Set by user.\
+     * - decoding: Set by libavcodec. (default 0)\
+     */\
+    int interlaced_frame;\
+    \
+    /**\
+     * If the content is interlaced, is top field displayed first.\
+     * - encoding: Set by user.\
+     * - decoding: Set by libavcodec.\
+     */\
+    int top_field_first;\
+    \
+    /**\
+     * Pan scan.\
+     * - encoding: Set by user.\
+     * - decoding: Set by libavcodec.\
+     */\
+    AVPanScan *pan_scan;\
+    \
+    /**\
+     * Tell user application that palette has changed from previous frame.\
+     * - encoding: ??? (no palette-enabled encoder yet)\
+     * - decoding: Set by libavcodec. (default 0).\
+     */\
+    int palette_has_changed;\
+    \
+    /**\
+     * codec suggestion on buffer type if != 0\
+     * - encoding: unused\
+     * - decoding: Set by libavcodec. (before get_buffer() call)).\
+     */\
+    int buffer_hints;\
+\
+    /**\
+     * DCT coefficients\
+     * - encoding: unused\
+     * - decoding: Set by libavcodec.\
+     */\
+    short *dct_coeff;\
+\
+    /**\
+     * motion referece frame index\
+     * - encoding: Set by user.\
+     * - decoding: Set by libavcodec.\
+     */\
+    int8_t *ref_index[2];
+
+#define FF_QSCALE_TYPE_MPEG1 0
+#define FF_QSCALE_TYPE_MPEG2 1
+#define FF_QSCALE_TYPE_H264  2
+
+#define FF_BUFFER_TYPE_INTERNAL 1
+#define FF_BUFFER_TYPE_USER     2 ///< direct rendering buffers (image is (de)allocated by user)
+#define FF_BUFFER_TYPE_SHARED   4 ///< Buffer from somewhere else; don't deallocate image (data/base), all other tables are not shared.
+#define FF_BUFFER_TYPE_COPY     8 ///< Just a (modified) copy of some other buffer, don't deallocate anything.
+
+
+#define FF_I_TYPE 1 // Intra
+#define FF_P_TYPE 2 // Predicted
+#define FF_B_TYPE 3 // Bi-dir predicted
+#define FF_S_TYPE 4 // S(GMC)-VOP MPEG4
+#define FF_SI_TYPE 5
+#define FF_SP_TYPE 6
+
+#define FF_BUFFER_HINTS_VALID    0x01 // Buffer hints value is meaningful (if 0 ignore).
+#define FF_BUFFER_HINTS_READABLE 0x02 // Codec will read from buffer.
+#define FF_BUFFER_HINTS_PRESERVE 0x04 // User must not alter buffer content.
+#define FF_BUFFER_HINTS_REUSABLE 0x08 // Codec will reuse the buffer (update).
+
+/**
+ * Audio Video Frame.
+ */
+typedef struct AVFrame {
+    FF_COMMON_FRAME
+} AVFrame;
+
+#define DEFAULT_FRAME_RATE_BASE 1001000
+
+/**
+ * main external API structure
+ */
+typedef struct AVCodecContext {
+    /**
+     * information on struct for av_log
+     * - set by avcodec_alloc_context
+     */
+    AVClass *av_class;
+    /**
+     * the average bitrate
+     * - encoding: Set by user; unused for constant quantizer encoding.
+     * - decoding: Set by libavcodec. 0 or some bitrate if this info is available in the stream.
+     */
+    int bit_rate;
+
+    /**
+     * number of bits the bitstream is allowed to diverge from the reference.
+     *           the reference can be CBR (for CBR pass1) or VBR (for pass2)
+     * - encoding: Set by user; unused for constant quantizer encoding.
+     * - decoding: unused
+     */
+    int bit_rate_tolerance;
+
+    /**
+     * CODEC_FLAG_*.
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     */
+    int flags;
+
+    /**
+     * Some codecs need additional format info. It is stored here.
+     * If any muxer uses this then ALL demuxers/parsers AND encoders for the
+     * specific codec MUST set it correctly otherwise stream copy breaks.
+     * In general use of this field by muxers is not recommanded.
+     * - encoding: Set by libavcodec.
+     * - decoding: Set by libavcodec. (FIXME: Is this OK?)
+     */
+    int sub_id;
+
+    /**
+     * Motion estimation algorithm used for video coding.
+     * 1 (zero), 2 (full), 3 (log), 4 (phods), 5 (epzs), 6 (x1), 7 (hex),
+     * 8 (umh), 9 (iter) [7, 8 are x264 specific, 9 is snow specific]
+     * - encoding: MUST be set by user.
+     * - decoding: unused
+     */
+    int me_method;
+
+    /**
+     * some codecs need / can use extradata like Huffman tables.
+     * mjpeg: Huffman tables
+     * rv10: additional flags
+     * mpeg4: global headers (they can be in the bitstream or here)
+     * The allocated memory should be FF_INPUT_BUFFER_PADDING_SIZE bytes larger
+     * than extradata_size to avoid prolems if it is read with the bitstream reader.
+     * The bytewise contents of extradata must not depend on the architecture or CPU endianness.
+     * - encoding: Set/allocated/freed by libavcodec.
+     * - decoding: Set/allocated/freed by user.
+     */
+    uint8_t *extradata;
+    int extradata_size;
+
+    /**
+     * This is the fundamental unit of time (in seconds) in terms
+     * of which frame timestamps are represented. For fixed-fps content,
+     * timebase should be 1/framerate and timestamp increments should be
+     * identically 1.
+     * - encoding: MUST be set by user.
+     * - decoding: Set by libavcodec.
+     */
+    AVRational time_base;
+
+    /* video only */
+    /**
+     * picture width / height.
+     * - encoding: MUST be set by user.
+     * - decoding: Set by libavcodec.
+     * Note: For compatibility it is possible to set this instead of
+     * coded_width/height before decoding.
+     */
+    int width, height;
+
+#define FF_ASPECT_EXTENDED 15
+
+    /**
+     * the number of pictures in a group of pictures, or 0 for intra_only
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int gop_size;
+
+    /**
+     * Pixel format, see PIX_FMT_xxx.
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     */
+    enum PixelFormat pix_fmt;
+
+    /**
+     * Frame rate emulation. If not zero, the lower layer (i.e. format handler)
+     * has to read frames at native frame rate.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int rate_emu;
+
+    /**
+     * If non NULL, 'draw_horiz_band' is called by the libavcodec
+     * decoder to draw a horizontal band. It improves cache usage. Not
+     * all codecs can do that. You must check the codec capabilities
+     * beforehand.
+     * - encoding: unused
+     * - decoding: Set by user.
+     * @param height the height of the slice
+     * @param y the y position of the slice
+     * @param type 1->top field, 2->bottom field, 3->frame
+     * @param offset offset into the AVFrame.data from which the slice should be read
+     */
+    void (*draw_horiz_band)(struct AVCodecContext *s,
+                            const AVFrame *src, int offset[4],
+                            int y, int type, int height);
+
+    /* audio only */
+    int sample_rate; ///< samples per second
+    int channels;
+
+    /**
+     * audio sample format
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     */
+    enum SampleFormat sample_fmt;  ///< sample format, currently unused
+
+    /* The following data should not be initialized. */
+    /**
+     * Samples per packet, initialized when calling 'init'.
+     */
+    int frame_size;
+    int frame_number;   ///< audio or video frame number
+    int real_pict_num;  ///< Returns the real picture number of previous encoded frame.
+
+    /**
+     * Number of frames the decoded output will be delayed relative to
+     * the encoded input.
+     * - encoding: Set by libavcodec.
+     * - decoding: unused
+     */
+    int delay;
+
+    /* - encoding parameters */
+    float qcompress;  ///< amount of qscale change between easy & hard scenes (0.0-1.0)
+    float qblur;      ///< amount of qscale smoothing over time (0.0-1.0)
+
+    /**
+     * minimum quantizer
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int qmin;
+
+    /**
+     * maximum quantizer
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int qmax;
+
+    /**
+     * maximum quantizer difference between frames
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int max_qdiff;
+
+    /**
+     * maximum number of B-frames between non-B-frames
+     * Note: The output will be delayed by max_b_frames+1 relative to the input.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int max_b_frames;
+
+    /**
+     * qscale factor between IP and B-frames
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float b_quant_factor;
+
+    /** obsolete FIXME remove */
+    int rc_strategy;
+#define FF_RC_STRATEGY_XVID 1
+
+    int b_frame_strategy;
+
+    /**
+     * hurry up amount
+     * - encoding: unused
+     * - decoding: Set by user. 1-> Skip B-frames, 2-> Skip IDCT/dequant too, 5-> Skip everything except header
+     * @deprecated Deprecated in favor of skip_idct and skip_frame.
+     */
+    int hurry_up;
+
+    struct AVCodec *codec;
+
+    void *priv_data;
+
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+    /* unused, FIXME remove*/
+    int rtp_mode;
+#endif
+
+    int rtp_payload_size;   /* The size of the RTP payload: the coder will  */
+                            /* do its best to deliver a chunk with size     */
+                            /* below rtp_payload_size, the chunk will start */
+                            /* with a start code on some codecs like H.263. */
+                            /* This doesn't take account of any particular  */
+                            /* headers inside the transmitted RTP payload.  */
+
+
+    /* The RTP callback: This function is called    */
+    /* every time the encoder has a packet to send. */
+    /* It depends on the encoder if the data starts */
+    /* with a Start Code (it should). H.263 does.   */
+    /* mb_nb contains the number of macroblocks     */
+    /* encoded in the RTP payload.                  */
+    void (*rtp_callback)(struct AVCodecContext *avctx, void *data, int size, int mb_nb);
+
+    /* statistics, used for 2-pass encoding */
+    int mv_bits;
+    int header_bits;
+    int i_tex_bits;
+    int p_tex_bits;
+    int i_count;
+    int p_count;
+    int skip_count;
+    int misc_bits;
+
+    /**
+     * number of bits used for the previously encoded frame
+     * - encoding: Set by libavcodec.
+     * - decoding: unused
+     */
+    int frame_bits;
+
+    /**
+     * Private data of the user, can be used to carry app specific stuff.
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     */
+    void *opaque;
+
+    char codec_name[32];
+    enum CodecType codec_type; /* see CODEC_TYPE_xxx */
+    enum CodecID codec_id; /* see CODEC_ID_xxx */
+
+    /**
+     * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
+     * This is used to work around some encoder bugs.
+     * A demuxer should set this to what is stored in the field used to identify the codec.
+     * If there are multiple such fields in a container then the demuxer should choose the one
+     * which maximizes the information about the used codec.
+     * If the codec tag field in a container is larger then 32 bits then the demuxer should
+     * remap the longer ID to 32 bits with a table or other structure. Alternatively a new
+     * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated
+     * first.
+     * - encoding: Set by user, if not then the default based on codec_id will be used.
+     * - decoding: Set by user, will be converted to uppercase by libavcodec during init.
+     */
+    unsigned int codec_tag;
+
+    /**
+     * Work around bugs in encoders which sometimes cannot be detected automatically.
+     * - encoding: Set by user
+     * - decoding: Set by user
+     */
+    int workaround_bugs;
+#define FF_BUG_AUTODETECT       1  ///< autodetection
+#define FF_BUG_OLD_MSMPEG4      2
+#define FF_BUG_XVID_ILACE       4
+#define FF_BUG_UMP4             8
+#define FF_BUG_NO_PADDING       16
+#define FF_BUG_AMV              32
+#define FF_BUG_AC_VLC           0  ///< Will be removed, libavcodec can now handle these non-compliant files by default.
+#define FF_BUG_QPEL_CHROMA      64
+#define FF_BUG_STD_QPEL         128
+#define FF_BUG_QPEL_CHROMA2     256
+#define FF_BUG_DIRECT_BLOCKSIZE 512
+#define FF_BUG_EDGE             1024
+#define FF_BUG_HPEL_CHROMA      2048
+#define FF_BUG_DC_CLIP          4096
+#define FF_BUG_MS               8192 ///< Work around various bugs in Microsoft's broken decoders.
+//#define FF_BUG_FAKE_SCALABILITY 16 //Autodetection should work 100%.
+
+    /**
+     * luma single coefficient elimination threshold
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int luma_elim_threshold;
+
+    /**
+     * chroma single coeff elimination threshold
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int chroma_elim_threshold;
+
+    /**
+     * strictly follow the standard (MPEG4, ...).
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int strict_std_compliance;
+#define FF_COMPLIANCE_VERY_STRICT   2 ///< Strictly conform to a older more strict version of the spec or reference software.
+#define FF_COMPLIANCE_STRICT        1 ///< Strictly conform to all the things in the spec no matter what consequences.
+#define FF_COMPLIANCE_NORMAL        0
+#define FF_COMPLIANCE_INOFFICIAL   -1 ///< Allow inofficial extensions.
+#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things.
+
+    /**
+     * qscale offset between IP and B-frames
+     * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset).
+     * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset).
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float b_quant_offset;
+
+    /**
+     * Error resilience; higher values will detect more errors but may
+     * misdetect some more or less valid parts as errors.
+     * - encoding: unused
+     * - decoding: Set by user.
+     */
+    int error_resilience;
+#define FF_ER_CAREFUL         1
+#define FF_ER_COMPLIANT       2
+#define FF_ER_AGGRESSIVE      3
+#define FF_ER_VERY_AGGRESSIVE 4
+
+    /**
+     * Called at the beginning of each frame to get a buffer for it.
+     * If pic.reference is set then the frame will be read later by libavcodec.
+     * avcodec_align_dimensions() should be used to find the required width and
+     * height, as they normally need to be rounded up to the next multiple of 16.
+     * - encoding: unused
+     * - decoding: Set by libavcodec., user can override.
+     */
+    int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic);
+
+    /**
+     * Called to release buffers which where allocated with get_buffer.
+     * A released buffer can be reused in get_buffer().
+     * pic.data[*] must be set to NULL.
+     * - encoding: unused
+     * - decoding: Set by libavcodec., user can override.
+     */
+    void (*release_buffer)(struct AVCodecContext *c, AVFrame *pic);
+
+    /**
+     * If 1 the stream has a 1 frame delay during decoding.
+     * - encoding: Set by libavcodec.
+     * - decoding: Set by libavcodec.
+     */
+    int has_b_frames;
+
+    /**
+     * number of bytes per packet if constant and known or 0
+     * Used by some WAV based audio codecs.
+     */
+    int block_align;
+
+    int parse_only; /* - decoding only: If true, only parsing is done
+                       (function avcodec_parse_frame()). The frame
+                       data is returned. Only MPEG codecs support this now. */
+
+    /**
+     * 0-> h263 quant 1-> mpeg quant
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int mpeg_quant;
+
+    /**
+     * pass1 encoding statistics output buffer
+     * - encoding: Set by libavcodec.
+     * - decoding: unused
+     */
+    char *stats_out;
+
+    /**
+     * pass2 encoding statistics input buffer
+     * Concatenated stuff from stats_out of pass1 should be placed here.
+     * - encoding: Allocated/set/freed by user.
+     * - decoding: unused
+     */
+    char *stats_in;
+
+    /**
+     * ratecontrol qmin qmax limiting method
+     * 0-> clipping, 1-> use a nice continous function to limit qscale wthin qmin/qmax.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float rc_qsquish;
+
+    float rc_qmod_amp;
+    int rc_qmod_freq;
+
+    /**
+     * ratecontrol override, see RcOverride
+     * - encoding: Allocated/set/freed by user.
+     * - decoding: unused
+     */
+    RcOverride *rc_override;
+    int rc_override_count;
+
+    /**
+     * rate control equation
+     * - encoding: Set by user
+     * - decoding: unused
+     */
+    char *rc_eq;
+
+    /**
+     * maximum bitrate
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int rc_max_rate;
+
+    /**
+     * minimum bitrate
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int rc_min_rate;
+
+    /**
+     * decoder bitstream buffer size
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int rc_buffer_size;
+    float rc_buffer_aggressivity;
+
+    /**
+     * qscale factor between P and I-frames
+     * If > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset).
+     * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset).
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float i_quant_factor;
+
+    /**
+     * qscale offset between P and I-frames
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float i_quant_offset;
+
+    /**
+     * initial complexity for pass1 ratecontrol
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float rc_initial_cplx;
+
+    /**
+     * DCT algorithm, see FF_DCT_* below
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int dct_algo;
+#define FF_DCT_AUTO    0
+#define FF_DCT_FASTINT 1
+#define FF_DCT_INT     2
+#define FF_DCT_MMX     3
+#define FF_DCT_MLIB    4
+#define FF_DCT_ALTIVEC 5
+#define FF_DCT_FAAN    6
+
+    /**
+     * luminance masking (0-> disabled)
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float lumi_masking;
+
+    /**
+     * temporary complexity masking (0-> disabled)
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float temporal_cplx_masking;
+
+    /**
+     * spatial complexity masking (0-> disabled)
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float spatial_cplx_masking;
+
+    /**
+     * p block masking (0-> disabled)
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float p_masking;
+
+    /**
+     * darkness masking (0-> disabled)
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float dark_masking;
+
+
+    /* for binary compatibility */
+    int unused;
+
+    /**
+     * IDCT algorithm, see FF_IDCT_* below.
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     */
+    int idct_algo;
+#define FF_IDCT_AUTO         0
+#define FF_IDCT_INT          1
+#define FF_IDCT_SIMPLE       2
+#define FF_IDCT_SIMPLEMMX    3
+#define FF_IDCT_LIBMPEG2MMX  4
+#define FF_IDCT_PS2          5
+#define FF_IDCT_MLIB         6
+#define FF_IDCT_ARM          7
+#define FF_IDCT_ALTIVEC      8
+#define FF_IDCT_SH4          9
+#define FF_IDCT_SIMPLEARM    10
+#define FF_IDCT_H264         11
+#define FF_IDCT_VP3          12
+#define FF_IDCT_IPP          13
+#define FF_IDCT_XVIDMMX      14
+#define FF_IDCT_CAVS         15
+#define FF_IDCT_SIMPLEARMV5TE 16
+#define FF_IDCT_SIMPLEARMV6  17
+
+    /**
+     * slice count
+     * - encoding: Set by libavcodec.
+     * - decoding: Set by user (or 0).
+     */
+    int slice_count;
+    /**
+     * slice offsets in the frame in bytes
+     * - encoding: Set/allocated by libavcodec.
+     * - decoding: Set/allocated by user (or NULL).
+     */
+    int *slice_offset;
+
+    /**
+     * error concealment flags
+     * - encoding: unused
+     * - decoding: Set by user.
+     */
+    int error_concealment;
+#define FF_EC_GUESS_MVS   1
+#define FF_EC_DEBLOCK     2
+
+    /**
+     * dsp_mask could be add used to disable unwanted CPU features
+     * CPU features (i.e. MMX, SSE. ...)
+     *
+     * With the FORCE flag you may instead enable given CPU features.
+     * (Dangerous: Usable in case of misdetection, improper usage however will
+     * result into program crash.)
+     */
+    unsigned dsp_mask;
+#define FF_MM_FORCE    0x80000000 /* Force usage of selected flags (OR) */
+    /* lower 16 bits - CPU features */
+#define FF_MM_MMX      0x0001 /* standard MMX */
+#define FF_MM_3DNOW    0x0004 /* AMD 3DNOW */
+#define FF_MM_MMXEXT   0x0002 /* SSE integer functions or AMD MMX ext */
+#define FF_MM_SSE      0x0008 /* SSE functions */
+#define FF_MM_SSE2     0x0010 /* PIV SSE2 functions */
+#define FF_MM_3DNOWEXT 0x0020 /* AMD 3DNowExt */
+#define FF_MM_SSE3     0x0040 /* Prescott SSE3 functions */
+#define FF_MM_SSSE3    0x0080 /* Conroe SSSE3 functions */
+#define FF_MM_IWMMXT   0x0100 /* XScale IWMMXT */
+
+    /**
+     * bits per sample/pixel from the demuxer (needed for huffyuv).
+     * - encoding: Set by libavcodec.
+     * - decoding: Set by user.
+     */
+     int bits_per_sample;
+
+    /**
+     * prediction method (needed for huffyuv)
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+     int prediction_method;
+#define FF_PRED_LEFT   0
+#define FF_PRED_PLANE  1
+#define FF_PRED_MEDIAN 2
+
+    /**
+     * sample aspect ratio (0 if unknown)
+     * Numerator and denominator must be relatively prime and smaller than 256 for some video standards.
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     */
+    AVRational sample_aspect_ratio;
+
+    /**
+     * the picture in the bitstream
+     * - encoding: Set by libavcodec.
+     * - decoding: Set by libavcodec.
+     */
+    AVFrame *coded_frame;
+
+    /**
+     * debug
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     */
+    int debug;
+#define FF_DEBUG_PICT_INFO 1
+#define FF_DEBUG_RC        2
+#define FF_DEBUG_BITSTREAM 4
+#define FF_DEBUG_MB_TYPE   8
+#define FF_DEBUG_QP        16
+#define FF_DEBUG_MV        32
+#define FF_DEBUG_DCT_COEFF 0x00000040
+#define FF_DEBUG_SKIP      0x00000080
+#define FF_DEBUG_STARTCODE 0x00000100
+#define FF_DEBUG_PTS       0x00000200
+#define FF_DEBUG_ER        0x00000400
+#define FF_DEBUG_MMCO      0x00000800
+#define FF_DEBUG_BUGS      0x00001000
+#define FF_DEBUG_VIS_QP    0x00002000
+#define FF_DEBUG_VIS_MB_TYPE 0x00004000
+
+    /**
+     * debug
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     */
+    int debug_mv;
+#define FF_DEBUG_VIS_MV_P_FOR  0x00000001 //visualize forward predicted MVs of P frames
+#define FF_DEBUG_VIS_MV_B_FOR  0x00000002 //visualize forward predicted MVs of B frames
+#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames
+
+    /**
+     * error
+     * - encoding: Set by libavcodec if flags&CODEC_FLAG_PSNR.
+     * - decoding: unused
+     */
+    uint64_t error[4];
+
+    /**
+     * minimum MB quantizer
+     * - encoding: unused
+     * - decoding: unused
+     */
+    int mb_qmin;
+
+    /**
+     * maximum MB quantizer
+     * - encoding: unused
+     * - decoding: unused
+     */
+    int mb_qmax;
+
+    /**
+     * motion estimation comparison function
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int me_cmp;
+    /**
+     * subpixel motion estimation comparison function
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int me_sub_cmp;
+    /**
+     * macroblock comparison function (not supported yet)
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int mb_cmp;
+    /**
+     * interlaced DCT comparison function
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int ildct_cmp;
+#define FF_CMP_SAD  0
+#define FF_CMP_SSE  1
+#define FF_CMP_SATD 2
+#define FF_CMP_DCT  3
+#define FF_CMP_PSNR 4
+#define FF_CMP_BIT  5
+#define FF_CMP_RD   6
+#define FF_CMP_ZERO 7
+#define FF_CMP_VSAD 8
+#define FF_CMP_VSSE 9
+#define FF_CMP_NSSE 10
+#define FF_CMP_W53  11
+#define FF_CMP_W97  12
+#define FF_CMP_DCTMAX 13
+#define FF_CMP_DCT264 14
+#define FF_CMP_CHROMA 256
+
+    /**
+     * ME diamond size & shape
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int dia_size;
+
+    /**
+     * amount of previous MV predictors (2a+1 x 2a+1 square)
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int last_predictor_count;
+
+    /**
+     * prepass for motion estimation
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int pre_me;
+
+    /**
+     * motion estimation prepass comparison function
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int me_pre_cmp;
+
+    /**
+     * ME prepass diamond size & shape
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int pre_dia_size;
+
+    /**
+     * subpel ME quality
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int me_subpel_quality;
+
+    /**
+     * callback to negotiate the pixelFormat
+     * @param fmt is the list of formats which are supported by the codec,
+     * it is terminated by -1 as 0 is a valid format, the formats are ordered by quality.
+     * The first is always the native one.
+     * @return the chosen format
+     * - encoding: unused
+     * - decoding: Set by user, if not set the native format will be chosen.
+     */
+    enum PixelFormat (*get_format)(struct AVCodecContext *s, const enum PixelFormat * fmt);
+
+    /**
+     * DTG active format information (additional aspect ratio
+     * information only used in DVB MPEG-2 transport streams)
+     * 0 if not set.
+     *
+     * - encoding: unused
+     * - decoding: Set by decoder.
+     */
+    int dtg_active_format;
+#define FF_DTG_AFD_SAME         8
+#define FF_DTG_AFD_4_3          9
+#define FF_DTG_AFD_16_9         10
+#define FF_DTG_AFD_14_9         11
+#define FF_DTG_AFD_4_3_SP_14_9  13
+#define FF_DTG_AFD_16_9_SP_14_9 14
+#define FF_DTG_AFD_SP_4_3       15
+
+    /**
+     * maximum motion estimation search range in subpel units
+     * If 0 then no limit.
+     *
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int me_range;
+
+    /**
+     * intra quantizer bias
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int intra_quant_bias;
+#define FF_DEFAULT_QUANT_BIAS 999999
+
+    /**
+     * inter quantizer bias
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int inter_quant_bias;
+
+    /**
+     * color table ID
+     * - encoding: unused
+     * - decoding: Which clrtable should be used for 8bit RGB images.
+     *             Tables have to be stored somewhere. FIXME
+     */
+    int color_table_id;
+
+    /**
+     * internal_buffer count
+     * Don't touch, used by libavcodec default_get_buffer().
+     */
+    int internal_buffer_count;
+
+    /**
+     * internal_buffers
+     * Don't touch, used by libavcodec default_get_buffer().
+     */
+    void *internal_buffer;
+
+#define FF_LAMBDA_SHIFT 7
+#define FF_LAMBDA_SCALE (1<<FF_LAMBDA_SHIFT)
+#define FF_QP2LAMBDA 118 ///< factor to convert from H.263 QP to lambda
+#define FF_LAMBDA_MAX (256*128-1)
+
+#define FF_QUALITY_SCALE FF_LAMBDA_SCALE //FIXME maybe remove
+    /**
+     * Global quality for codecs which cannot change it per frame.
+     * This should be proportional to MPEG-1/2/4 qscale.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int global_quality;
+
+#define FF_CODER_TYPE_VLC       0
+#define FF_CODER_TYPE_AC        1
+#define FF_CODER_TYPE_RAW       2
+#define FF_CODER_TYPE_RLE       3
+#define FF_CODER_TYPE_DEFLATE   4
+    /**
+     * coder type
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int coder_type;
+
+    /**
+     * context model
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int context_model;
+#if 0
+    /**
+     *
+     * - encoding: unused
+     * - decoding: Set by user.
+     */
+    uint8_t * (*realloc)(struct AVCodecContext *s, uint8_t *buf, int buf_size);
+#endif
+
+    /**
+     * slice flags
+     * - encoding: unused
+     * - decoding: Set by user.
+     */
+    int slice_flags;
+#define SLICE_FLAG_CODED_ORDER    0x0001 ///< draw_horiz_band() is called in coded order instead of display
+#define SLICE_FLAG_ALLOW_FIELD    0x0002 ///< allow draw_horiz_band() with field slices (MPEG2 field pics)
+#define SLICE_FLAG_ALLOW_PLANE    0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1)
+
+    /**
+     * XVideo Motion Acceleration
+     * - encoding: forbidden
+     * - decoding: set by decoder
+     */
+    int xvmc_acceleration;
+
+    /**
+     * macroblock decision mode
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int mb_decision;
+#define FF_MB_DECISION_SIMPLE 0        ///< uses mb_cmp
+#define FF_MB_DECISION_BITS   1        ///< chooses the one which needs the fewest bits
+#define FF_MB_DECISION_RD     2        ///< rate distoration
+
+    /**
+     * custom intra quantization matrix
+     * - encoding: Set by user, can be NULL.
+     * - decoding: Set by libavcodec.
+     */
+    uint16_t *intra_matrix;
+
+    /**
+     * custom inter quantization matrix
+     * - encoding: Set by user, can be NULL.
+     * - decoding: Set by libavcodec.
+     */
+    uint16_t *inter_matrix;
+
+    /**
+     * fourcc from the AVI stream header (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
+     * This is used to work around some encoder bugs.
+     * - encoding: unused
+     * - decoding: Set by user, will be converted to uppercase by libavcodec during init.
+     */
+    unsigned int stream_codec_tag;
+
+    /**
+     * scene change detection threshold
+     * 0 is default, larger means fewer detected scene changes.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int scenechange_threshold;
+
+    /**
+     * minimum Lagrange multipler
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int lmin;
+
+    /**
+     * maximum Lagrange multipler
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int lmax;
+
+    /**
+     * palette control structure
+     * - encoding: ??? (no palette-enabled encoder yet)
+     * - decoding: Set by user.
+     */
+    struct AVPaletteControl *palctrl;
+
+    /**
+     * noise reduction strength
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int noise_reduction;
+
+    /**
+     * Called at the beginning of a frame to get cr buffer for it.
+     * Buffer type (size, hints) must be the same. libavcodec won't check it.
+     * libavcodec will pass previous buffer in pic, function should return
+     * same buffer or new buffer with old frame "painted" into it.
+     * If pic.data[0] == NULL must behave like get_buffer().
+     * - encoding: unused
+     * - decoding: Set by libavcodec., user can override
+     */
+    int (*reget_buffer)(struct AVCodecContext *c, AVFrame *pic);
+
+    /**
+     * Number of bits which should be loaded into the rc buffer before decoding starts.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int rc_initial_buffer_occupancy;
+
+    /**
+     *
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int inter_threshold;
+
+    /**
+     * CODEC_FLAG2_*
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     */
+    int flags2;
+
+    /**
+     * Simulates errors in the bitstream to test error concealment.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int error_rate;
+
+    /**
+     * MP3 antialias algorithm, see FF_AA_* below.
+     * - encoding: unused
+     * - decoding: Set by user.
+     */
+    int antialias_algo;
+#define FF_AA_AUTO    0
+#define FF_AA_FASTINT 1 //not implemented yet
+#define FF_AA_INT     2
+#define FF_AA_FLOAT   3
+    /**
+     * quantizer noise shaping
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int quantizer_noise_shaping;
+
+    /**
+     * thread count
+     * is used to decide how many independent tasks should be passed to execute()
+     * - encoding: Set by user.
+     * - decoding: Set by user.
+     */
+    int thread_count;
+
+    /**
+     * The codec may call this to execute several independent things.
+     * It will return only after finishing all tasks.
+     * The user may replace this with some multithreaded implementation,
+     * the default implementation will execute the parts serially.
+     * @param count the number of things to execute
+     * - encoding: Set by libavcodec, user can override.
+     * - decoding: Set by libavcodec, user can override.
+     */
+    int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void **arg2, int *ret, int count);
+
+    /**
+     * thread opaque
+     * Can be used by execute() to store some per AVCodecContext stuff.
+     * - encoding: set by execute()
+     * - decoding: set by execute()
+     */
+    void *thread_opaque;
+
+    /**
+     * Motion estimation threshold below which no motion estimation is
+     * performed, but instead the user specified motion vectors are used.
+     *
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+     int me_threshold;
+
+    /**
+     * Macroblock threshold below which the user specified macroblock types will be used.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+     int mb_threshold;
+
+    /**
+     * precision of the intra DC coefficient - 8
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+     int intra_dc_precision;
+
+    /**
+     * noise vs. sse weight for the nsse comparsion function
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+     int nsse_weight;
+
+    /**
+     * Number of macroblock rows at the top which are skipped.
+     * - encoding: unused
+     * - decoding: Set by user.
+     */
+     int skip_top;
+
+    /**
+     * Number of macroblock rows at the bottom which are skipped.
+     * - encoding: unused
+     * - decoding: Set by user.
+     */
+     int skip_bottom;
+
+    /**
+     * profile
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     */
+     int profile;
+#define FF_PROFILE_UNKNOWN -99
+#define FF_PROFILE_AAC_MAIN 0
+#define FF_PROFILE_AAC_LOW 1
+#define FF_PROFILE_AAC_SSR 2
+#define FF_PROFILE_AAC_LTP 3
+
+    /**
+     * level
+     * - encoding: Set by user.
+     * - decoding: Set by libavcodec.
+     */
+     int level;
+#define FF_LEVEL_UNKNOWN -99
+
+    /**
+     * low resolution decoding, 1-> 1/2 size, 2->1/4 size
+     * - encoding: unused
+     * - decoding: Set by user.
+     */
+     int lowres;
+
+    /**
+     * Bitstream width / height, may be different from width/height if lowres
+     * or other things are used.
+     * - encoding: unused
+     * - decoding: Set by user before init if known. Codec should override / dynamically change if needed.
+     */
+    int coded_width, coded_height;
+
+    /**
+     * frame skip threshold
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int frame_skip_threshold;
+
+    /**
+     * frame skip factor
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int frame_skip_factor;
+
+    /**
+     * frame skip exponent
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int frame_skip_exp;
+
+    /**
+     * frame skip comparison function
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int frame_skip_cmp;
+
+    /**
+     * Border processing masking, raises the quantizer for mbs on the borders
+     * of the picture.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float border_masking;
+
+    /**
+     * minimum MB lagrange multipler
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int mb_lmin;
+
+    /**
+     * maximum MB lagrange multipler
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int mb_lmax;
+
+    /**
+     *
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int me_penalty_compensation;
+
+    /**
+     *
+     * - encoding: unused
+     * - decoding: Set by user.
+     */
+    enum AVDiscard skip_loop_filter;
+
+    /**
+     *
+     * - encoding: unused
+     * - decoding: Set by user.
+     */
+    enum AVDiscard skip_idct;
+
+    /**
+     *
+     * - encoding: unused
+     * - decoding: Set by user.
+     */
+    enum AVDiscard skip_frame;
+
+    /**
+     *
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int bidir_refine;
+
+    /**
+     *
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int brd_scale;
+
+    /**
+     * constant rate factor - quality-based VBR - values ~correspond to qps
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float crf;
+
+    /**
+     * constant quantization parameter rate control method
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int cqp;
+
+    /**
+     * minimum GOP size
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int keyint_min;
+
+    /**
+     * number of reference frames
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int refs;
+
+    /**
+     * chroma qp offset from luma
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int chromaoffset;
+
+    /**
+     * Influences how often B-frames are used.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int bframebias;
+
+    /**
+     * trellis RD quantization
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int trellis;
+
+    /**
+     * Reduce fluctuations in qp (before curve compression).
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    float complexityblur;
+
+    /**
+     * in-loop deblocking filter alphac0 parameter
+     * alpha is in the range -6...6
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int deblockalpha;
+
+    /**
+     * in-loop deblocking filter beta parameter
+     * beta is in the range -6...6
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int deblockbeta;
+
+    /**
+     * macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int partitions;
+#define X264_PART_I4X4 0x001  /* Analyse i4x4 */
+#define X264_PART_I8X8 0x002  /* Analyse i8x8 (requires 8x8 transform) */
+#define X264_PART_P8X8 0x010  /* Analyse p16x8, p8x16 and p8x8 */
+#define X264_PART_P4X4 0x020  /* Analyse p8x4, p4x8, p4x4 */
+#define X264_PART_B8X8 0x100  /* Analyse b16x8, b8x16 and b8x8 */
+
+    /**
+     * direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal)
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int directpred;
+
+    /**
+     * Audio cutoff bandwidth (0 means "automatic"), currently used only by FAAC.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int cutoff;
+
+    /**
+     * Multiplied by qscale for each frame and added to scene_change_score.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int scenechange_factor;
+
+    /**
+     *
+     * Note: Value depends upon the compare function used for fullpel ME.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int mv0_threshold;
+
+    /**
+     * Adjusts sensitivity of b_frame_strategy 1.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int b_sensitivity;
+
+    /**
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int compression_level;
+#define FF_COMPRESSION_DEFAULT -1
+
+    /**
+     * Sets whether to use LPC mode - used by FLAC encoder.
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int use_lpc;
+
+    /**
+     * LPC coefficient precision - used by FLAC encoder
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int lpc_coeff_precision;
+
+    /**
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int min_prediction_order;
+
+    /**
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int max_prediction_order;
+
+    /**
+     * search method for selecting prediction order
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int prediction_order_method;
+
+    /**
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int min_partition_order;
+
+    /**
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int max_partition_order;
+
+    /**
+     * GOP timecode frame start number, in non drop frame format
+     * - encoding: Set by user.
+     * - decoding: unused
+     */
+    int64_t timecode_frame_start;
+} AVCodecContext;
+
+/**
+ * AVCodec.
+ */
+typedef struct AVCodec {
+    /**
+     * Name of the codec implementation.
+     * The name is globally unique among encoders and among decoders (but an
+     * encoder and a decoder can share the same name).
+     * This is the primary way to find a codec from the user perspective.
+     */
+    const char *name;
+    enum CodecType type;
+    enum CodecID id;
+    int priv_data_size;
+    int (*init)(AVCodecContext *);
+    int (*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data);
+    int (*close)(AVCodecContext *);
+    int (*decode)(AVCodecContext *, void *outdata, int *outdata_size,
+                  uint8_t *buf, int buf_size);
+    int capabilities;
+    struct AVCodec *next;
+    void (*flush)(AVCodecContext *);
+    const AVRational *supported_framerates; ///array of supported framerates, or NULL if any, array is terminated by {0,0}
+    const enum PixelFormat *pix_fmts;       ///array of supported pixel formats, or NULL if unknown, array is terminanted by -1
+} AVCodec;
+
+/**
+ * four components are given, that's all.
+ * the last component is alpha
+ */
+typedef struct AVPicture {
+    uint8_t *data[4];
+    int linesize[4];       ///< number of bytes per line
+} AVPicture;
+
+/**
+ * AVPaletteControl
+ * This structure defines a method for communicating palette changes
+ * between and demuxer and a decoder.
+ *
+ * @deprecated Use AVPacket to send palette changes instead.
+ * This is totally broken.
+ */
+#define AVPALETTE_SIZE 1024
+#define AVPALETTE_COUNT 256
+typedef struct AVPaletteControl {
+
+    /* Demuxer sets this to 1 to indicate the palette has changed;
+     * decoder resets to 0. */
+    int palette_changed;
+
+    /* 4-byte ARGB palette entries, stored in native byte order; note that
+     * the individual palette components should be on a 8-bit scale; if
+     * the palette data comes from an IBM VGA native format, the component
+     * data is probably 6 bits in size and needs to be scaled. */
+    unsigned int palette[AVPALETTE_COUNT];
+
+} AVPaletteControl attribute_deprecated;
+
+typedef struct AVSubtitleRect {
+    uint16_t x;
+    uint16_t y;
+    uint16_t w;
+    uint16_t h;
+    uint16_t nb_colors;
+    int linesize;
+    uint32_t *rgba_palette;
+    uint8_t *bitmap;
+} AVSubtitleRect;
+
+typedef struct AVSubtitle {
+    uint16_t format; /* 0 = graphics */
+    uint32_t start_display_time; /* relative to packet pts, in ms */
+    uint32_t end_display_time; /* relative to packet pts, in ms */
+    uint32_t num_rects;
+    AVSubtitleRect *rects;
+} AVSubtitle;
+
+
+/* resample.c */
+
+struct ReSampleContext;
+struct AVResampleContext;
+
+typedef struct ReSampleContext ReSampleContext;
+
+ReSampleContext *audio_resample_init(int output_channels, int input_channels,
+                                     int output_rate, int input_rate);
+int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples);
+void audio_resample_close(ReSampleContext *s);
+
+struct AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_length, int log2_phase_count, int linear, double cutoff);
+int av_resample(struct AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx);
+void av_resample_compensate(struct AVResampleContext *c, int sample_delta, int compensation_distance);
+void av_resample_close(struct AVResampleContext *c);
+
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+/* YUV420 format is assumed ! */
+
+/**
+ * @deprecated Use the software scaler (swscale) instead.
+ */
+typedef struct ImgReSampleContext ImgReSampleContext attribute_deprecated;
+
+/**
+ * @deprecated Use the software scaler (swscale) instead.
+ */
+attribute_deprecated ImgReSampleContext *img_resample_init(int output_width, int output_height,
+                                      int input_width, int input_height);
+
+/**
+ * @deprecated Use the software scaler (swscale) instead.
+ */
+attribute_deprecated ImgReSampleContext *img_resample_full_init(int owidth, int oheight,
+                                      int iwidth, int iheight,
+                                      int topBand, int bottomBand,
+                                      int leftBand, int rightBand,
+                                      int padtop, int padbottom,
+                                      int padleft, int padright);
+
+/**
+ * @deprecated Use the software scaler (swscale) instead.
+ */
+attribute_deprecated void img_resample(struct ImgReSampleContext *s,
+                  AVPicture *output, const AVPicture *input);
+
+/**
+ * @deprecated Use the software scaler (swscale) instead.
+ */
+attribute_deprecated void img_resample_close(struct ImgReSampleContext *s);
+
+#endif
+
+/**
+ * Allocate memory for a picture.  Call avpicture_free to free it.
+ *
+ * @param picture the picture to be filled in
+ * @param pix_fmt the format of the picture
+ * @param width the width of the picture
+ * @param height the height of the picture
+ * @return zero if successful, a negative value if not
+ */
+int avpicture_alloc(AVPicture *picture, int pix_fmt, int width, int height);
+
+/**
+ * Free a picture previously allocated by avpicture_alloc().
+ *
+ * @param picture the AVPicture to be freed
+ */
+void avpicture_free(AVPicture *picture);
+
+/**
+ * Fill in the AVPicture fields.
+ * The fields of the given AVPicture are filled in by using the 'ptr' address
+ * which points to the image data buffer. Depending on the specified picture
+ * format, one or multiple image data pointers and line sizes will be set.
+ * If a planar format is specified, several pointers will be set pointing to
+ * the different picture planes and the line sizes of the different planes
+ * will be stored in the lines_sizes array.
+ *
+ * @param picture AVPicture whose fields are to be filled in
+ * @param ptr Buffer which will contain or contains the actual image data
+ * @param pix_fmt The format in which the picture data is stored.
+ * @param width the width of the image in pixels
+ * @param height the height of the image in pixels
+ * @return size of the image data in bytes
+ */
+int avpicture_fill(AVPicture *picture, uint8_t *ptr,
+                   int pix_fmt, int width, int height);
+int avpicture_layout(const AVPicture* src, int pix_fmt, int width, int height,
+                     unsigned char *dest, int dest_size);
+
+/**
+ * Calculate the size in bytes that a picture of the given width and height
+ * would occupy if stored in the given picture format.
+ *
+ * @param pix_fmt the given picture format
+ * @param width the width of the image
+ * @param height the height of the image
+ * @return Image data size in bytes
+ */
+int avpicture_get_size(int pix_fmt, int width, int height);
+void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift);
+const char *avcodec_get_pix_fmt_name(int pix_fmt);
+void avcodec_set_dimensions(AVCodecContext *s, int width, int height);
+enum PixelFormat avcodec_get_pix_fmt(const char* name);
+unsigned int avcodec_pix_fmt_to_codec_tag(enum PixelFormat p);
+
+#define FF_LOSS_RESOLUTION  0x0001 /**< loss due to resolution change */
+#define FF_LOSS_DEPTH       0x0002 /**< loss due to color depth change */
+#define FF_LOSS_COLORSPACE  0x0004 /**< loss due to color space conversion */
+#define FF_LOSS_ALPHA       0x0008 /**< loss of alpha bits */
+#define FF_LOSS_COLORQUANT  0x0010 /**< loss due to color quantization */
+#define FF_LOSS_CHROMA      0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */
+
+/**
+ * Computes what kind of losses will occur when converting from one specific
+ * pixel format to another.
+ * When converting from one pixel format to another, information loss may occur.
+ * For example, when converting from RGB24 to GRAY, the color information will
+ * be lost. Similarly, other losses occur when converting from some formats to
+ * other formats. These losses can involve loss of chroma, but also loss of
+ * resolution, loss of color depth, loss due to the color space conversion, loss
+ * of the alpha bits or loss due to color quantization.
+ * avcodec_get_fix_fmt_loss() informs you about the various types of losses
+ * which will occur when converting from one pixel format to another.
+ *
+ * @param[in] dst_pix_fmt destination pixel format
+ * @param[in] src_pix_fmt source pixel format
+ * @param[in] has_alpha Whether the source pixel format alpha channel is used.
+ * @return Combination of flags informing you what kind of losses will occur.
+ */
+int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt,
+                             int has_alpha);
+
+/**
+ * Finds the best pixel format to convert to given a certain source pixel
+ * format.  When converting from one pixel format to another, information loss
+ * may occur.  For example, when converting from RGB24 to GRAY, the color
+ * information will be lost. Similarly, other losses occur when converting from
+ * some formats to other formats. avcodec_find_best_pix_fmt() searches which of
+ * the given pixel formats should be used to suffer the least amount of loss.
+ * The pixel formats from which it chooses one, are determined by the
+ * \p pix_fmt_mask parameter.
+ *
+ * @code
+ * src_pix_fmt = PIX_FMT_YUV420P;
+ * pix_fmt_mask = (1 << PIX_FMT_YUV422P) || (1 << PIX_FMT_RGB24);
+ * dst_pix_fmt = avcodec_find_best_pix_fmt(pix_fmt_mask, src_pix_fmt, alpha, &loss);
+ * @endcode
+ *
+ * @param[in] pix_fmt_mask bitmask determining which pixel format to choose from
+ * @param[in] src_pix_fmt source pixel format
+ * @param[in] has_alpha Whether the source pixel format alpha channel is used.
+ * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur.
+ * @return The best pixel format to convert to or -1 if none was found.
+ */
+int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt,
+                              int has_alpha, int *loss_ptr);
+
+
+/**
+ * Print in buf the string corresponding to the pixel format with
+ * number pix_fmt, or an header if pix_fmt is negative.
+ *
+ * @param buf[in] the buffer where to write the string
+ * @param buf_size[in] the size of buf
+ * @param pix_fmt[in] the number of the pixel format to print the corresponding info string, or
+ * a negative value to print the corresponding header.
+ * Meaningful values for obtaining a pixel format info vary from 0 to PIX_FMT_NB -1.
+ */
+void avcodec_pix_fmt_string (char *buf, int buf_size, int pix_fmt);
+
+#define FF_ALPHA_TRANSP       0x0001 /* image has some totally transparent pixels */
+#define FF_ALPHA_SEMI_TRANSP  0x0002 /* image has some transparent pixels */
+
+/**
+ * Tell if an image really has transparent alpha values.
+ * @return ored mask of FF_ALPHA_xxx constants
+ */
+int img_get_alpha_info(const AVPicture *src,
+                       int pix_fmt, int width, int height);
+
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+/**
+ * convert among pixel formats
+ * @deprecated Use the software scaler (swscale) instead.
+ */
+attribute_deprecated int img_convert(AVPicture *dst, int dst_pix_fmt,
+                const AVPicture *src, int pix_fmt,
+                int width, int height);
+#endif
+
+/* deinterlace a picture */
+/* deinterlace - if not supported return -1 */
+int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
+                          int pix_fmt, int width, int height);
+
+/* external high level API */
+
+extern AVCodec *first_avcodec;
+
+/* returns LIBAVCODEC_VERSION_INT constant */
+unsigned avcodec_version(void);
+/* returns LIBAVCODEC_BUILD constant */
+unsigned avcodec_build(void);
+
+/**
+ * Initializes libavcodec.
+ *
+ * @warning This function \e must be called before any other libavcodec
+ * function.
+ */
+void avcodec_init(void);
+
+void register_avcodec(AVCodec *format);
+
+/**
+ * Finds an encoder with a matching codec ID.
+ *
+ * @param id CodecID of the requested encoder
+ * @return An encoder if one was found, NULL otherwise.
+ */
+AVCodec *avcodec_find_encoder(enum CodecID id);
+
+/**
+ * Finds an encoder with the specified name.
+ *
+ * @param name name of the requested encoder
+ * @return An encoder if one was found, NULL otherwise.
+ */
+AVCodec *avcodec_find_encoder_by_name(const char *name);
+
+/**
+ * Finds a decoder with a matching codec ID.
+ *
+ * @param id CodecID of the requested decoder
+ * @return A decoder if one was found, NULL otherwise.
+ */
+AVCodec *avcodec_find_decoder(enum CodecID id);
+
+/**
+ * Finds an decoder with the specified name.
+ *
+ * @param name name of the requested decoder
+ * @return A decoder if one was found, NULL otherwise.
+ */
+AVCodec *avcodec_find_decoder_by_name(const char *name);
+void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode);
+
+/**
+ * Sets the fields of the given AVCodecContext to default values.
+ *
+ * @param s The AVCodecContext of which the fields should be set to default values.
+ */
+void avcodec_get_context_defaults(AVCodecContext *s);
+
+/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API!
+ *  we WILL change its arguments and name a few times! */
+void avcodec_get_context_defaults2(AVCodecContext *s, enum CodecType);
+
+/**
+ * Allocates an AVCodecContext and sets its fields to default values.  The
+ * resulting struct can be deallocated by simply calling av_free().
+ *
+ * @return An AVCodecContext filled with default values or NULL on failure.
+ * @see avcodec_get_context_defaults
+ */
+AVCodecContext *avcodec_alloc_context(void);
+
+/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API!
+ *  we WILL change its arguments and name a few times! */
+AVCodecContext *avcodec_alloc_context2(enum CodecType);
+
+/**
+ * Sets the fields of the given AVFrame to default values.
+ *
+ * @param pic The AVFrame of which the fields should be set to default values.
+ */
+void avcodec_get_frame_defaults(AVFrame *pic);
+
+/**
+ * Allocates an AVFrame and sets its fields to default values.  The resulting
+ * struct can be deallocated by simply calling av_free().
+ *
+ * @return An AVFrame filled with default values or NULL on failure.
+ * @see avcodec_get_frame_defaults
+ */
+AVFrame *avcodec_alloc_frame(void);
+
+int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic);
+void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic);
+int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic);
+void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height);
+
+/**
+ * Checks if the given dimension of a picture is valid, meaning that all
+ * bytes of the picture can be addressed with a signed int.
+ *
+ * @param[in] w Width of the picture.
+ * @param[in] h Height of the picture.
+ * @return Zero if valid, a negative value if invalid.
+ */
+int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h);
+enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat * fmt);
+
+int avcodec_thread_init(AVCodecContext *s, int thread_count);
+void avcodec_thread_free(AVCodecContext *s);
+int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void **arg, int *ret, int count);
+int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void **arg, int *ret, int count);
+//FIXME func typedef
+
+/**
+ * Initializes the AVCodecContext to use the given AVCodec. Prior to using this
+ * function the context has to be allocated.
+ *
+ * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),
+ * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for
+ * retrieving a codec.
+ *
+ * @warning This function is not thread safe!
+ *
+ * @code
+ * avcodec_register_all();
+ * codec = avcodec_find_decoder(CODEC_ID_H264);
+ * if (!codec)
+ *     exit(1);
+ *
+ * context = avcodec_alloc_context();
+ *
+ * if (avcodec_open(context, codec) < 0)
+ *     exit(1);
+ * @endcode
+ *
+ * @param avctx The context which will be set up to use the given codec.
+ * @param codec The codec to use within the context.
+ * @return zero on success, a negative value on error
+ * @see avcodec_alloc_context, avcodec_find_decoder, avcodec_find_encoder
+ */
+int avcodec_open(AVCodecContext *avctx, AVCodec *codec);
+
+/**
+ * @deprecated Use avcodec_decode_audio2() instead.
+ */
+attribute_deprecated int avcodec_decode_audio(AVCodecContext *avctx, int16_t *samples,
+                         int *frame_size_ptr,
+                         uint8_t *buf, int buf_size);
+
+/**
+ * Decodes an audio frame from \p buf into \p samples.
+ * The avcodec_decode_audio2() function decodes an audio frame from the input
+ * buffer \p buf of size \p buf_size. To decode it, it makes use of the
+ * audio codec which was coupled with \p avctx using avcodec_open(). The
+ * resulting decoded frame is stored in output buffer \p samples.  If no frame
+ * could be decompressed, \p frame_size_ptr is zero. Otherwise, it is the
+ * decompressed frame size in \e bytes.
+ *
+ * @warning You \e must set \p frame_size_ptr to the allocated size of the
+ * output buffer before calling avcodec_decode_audio2().
+ *
+ * @warning The input buffer must be \c FF_INPUT_BUFFER_PADDING_SIZE larger than
+ * the actual read bytes because some optimized bitstream readers read 32 or 64
+ * bits at once and could read over the end.
+ *
+ * @warning The end of the input buffer \p buf should be set to 0 to ensure that
+ * no overreading happens for damaged MPEG streams.
+ *
+ * @note You might have to align the input buffer \p buf and output buffer \p
+ * samples. The alignment requirements depend on the CPU: On some CPUs it isn't
+ * necessary at all, on others it won't work at all if not aligned and on others
+ * it will work but it will have an impact on performance. In practice, the
+ * bitstream should have 4 byte alignment at minimum and all sample data should
+ * be 16 byte aligned unless the CPU doesn't need it (AltiVec and SSE do). If
+ * the linesize is not a multiple of 16 then there's no sense in aligning the
+ * start of the buffer to 16.
+ *
+ * @param avctx the codec context
+ * @param[out] samples the output buffer
+ * @param[in,out] frame_size_ptr the output buffer size in bytes
+ * @param[in] buf the input buffer
+ * @param[in] buf_size the input buffer size in bytes
+ * @return On error a negative value is returned, otherwise the number of bytes
+ * used or zero if no frame could be decompressed.
+ */
+int avcodec_decode_audio2(AVCodecContext *avctx, int16_t *samples,
+                         int *frame_size_ptr,
+                         uint8_t *buf, int buf_size);
+
+/**
+ * Decodes a video frame from \p buf into \p picture.
+ * The avcodec_decode_video() function decodes a video frame from the input
+ * buffer \p buf of size \p buf_size. To decode it, it makes use of the
+ * video codec which was coupled with \p avctx using avcodec_open(). The
+ * resulting decoded frame is stored in \p picture.
+ *
+ * @warning The input buffer must be \c FF_INPUT_BUFFER_PADDING_SIZE larger than
+ * the actual read bytes because some optimized bitstream readers read 32 or 64
+ * bits at once and could read over the end.
+ *
+ * @warning The end of the input buffer \p buf should be set to 0 to ensure that
+ * no overreading happens for damaged MPEG streams.
+ *
+ * @note You might have to align the input buffer \p buf and output buffer \p
+ * samples. The alignment requirements depend on the CPU: on some CPUs it isn't
+ * necessary at all, on others it won't work at all if not aligned and on others
+ * it will work but it will have an impact on performance. In practice, the
+ * bitstream should have 4 byte alignment at minimum and all sample data should
+ * be 16 byte aligned unless the CPU doesn't need it (AltiVec and SSE do). If
+ * the linesize is not a multiple of 16 then there's no sense in aligning the
+ * start of the buffer to 16.
+ *
+ * @param avctx the codec context
+ * @param[out] picture The AVFrame in which the decoded video frame will be stored.
+ * @param[in] buf the input buffer
+ * @param[in] buf_size the size of the input buffer in bytes
+ * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero.
+ * @return On error a negative value is returned, otherwise the number of bytes
+ * used or zero if no frame could be decompressed.
+ */
+int avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture,
+                         int *got_picture_ptr,
+                         uint8_t *buf, int buf_size);
+
+/* Decode a subtitle message. Return -1 if error, otherwise return the
+ * number of bytes used. If no subtitle could be decompressed,
+ * got_sub_ptr is zero. Otherwise, the subtitle is stored in *sub. */
+int avcodec_decode_subtitle(AVCodecContext *avctx, AVSubtitle *sub,
+                            int *got_sub_ptr,
+                            const uint8_t *buf, int buf_size);
+int avcodec_parse_frame(AVCodecContext *avctx, uint8_t **pdata,
+                        int *data_size_ptr,
+                        uint8_t *buf, int buf_size);
+
+/**
+ * Encodes an audio frame from \p samples into \p buf.
+ * The avcodec_encode_audio() function encodes an audio frame from the input
+ * buffer \p samples. To encode it, it makes use of the audio codec which was
+ * coupled with \p avctx using avcodec_open(). The resulting encoded frame is
+ * stored in output buffer \p buf.
+ *
+ * @note The output buffer should be at least \c FF_MIN_BUFFER_SIZE bytes large.
+ *
+ * @param avctx the codec context
+ * @param[out] buf the output buffer
+ * @param[in] buf_size the output buffer size
+ * @param[in] samples the input buffer containing the samples
+ * @return On error a negative value is returned, on succes zero or the number
+ * of bytes used from the input buffer.
+ */
+int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size,
+                         const short *samples);
+
+/**
+ * Encodes a video frame from \p pict into \p buf.
+ * The avcodec_encode_video() function encodes a video frame from the input
+ * \p pict. To encode it, it makes use of the video codec which was coupled with
+ * \p avctx using avcodec_open(). The resulting encoded bytes representing the
+ * frame are stored in the output buffer \p buf. The input picture should be
+ * stored using a specific format, namely \c avctx.pix_fmt.
+ *
+ * @param avctx the codec context
+ * @param[out] buf the output buffer for the bitstream of encoded frame
+ * @param[in] buf_size the size of the output buffer in bytes
+ * @param[in] pict the input picture to encode
+ * @return On error a negative value is returned, on success zero or the number
+ * of bytes used from the input buffer.
+ */
+int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size,
+                         const AVFrame *pict);
+int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size,
+                            const AVSubtitle *sub);
+
+int avcodec_close(AVCodecContext *avctx);
+
+void avcodec_register_all(void);
+
+/**
+ * Flush buffers, should be called when seeking or when switching to a different stream.
+ */
+void avcodec_flush_buffers(AVCodecContext *avctx);
+
+void avcodec_default_free_buffers(AVCodecContext *s);
+
+/* misc useful functions */
+
+/**
+ * Returns a single letter to describe the given picture type \p pict_type.
+ *
+ * @param[in] pict_type the picture type
+ * @return A single character representing the picture type.
+ */
+char av_get_pict_type_char(int pict_type);
+
+/**
+ * Returns codec bits per sample.
+ *
+ * @param[in] codec_id the codec
+ * @return Number of bits per sample or zero if unknown for the given codec.
+ */
+int av_get_bits_per_sample(enum CodecID codec_id);
+
+/* frame parsing */
+typedef struct AVCodecParserContext {
+    void *priv_data;
+    struct AVCodecParser *parser;
+    int64_t frame_offset; /* offset of the current frame */
+    int64_t cur_offset; /* current offset
+                           (incremented by each av_parser_parse()) */
+    int64_t last_frame_offset; /* offset of the last frame */
+    /* video info */
+    int pict_type; /* XXX: Put it back in AVCodecContext. */
+    int repeat_pict; /* XXX: Put it back in AVCodecContext. */
+    int64_t pts;     /* pts of the current frame */
+    int64_t dts;     /* dts of the current frame */
+
+    /* private data */
+    int64_t last_pts;
+    int64_t last_dts;
+    int fetch_timestamp;
+
+#define AV_PARSER_PTS_NB 4
+    int cur_frame_start_index;
+    int64_t cur_frame_offset[AV_PARSER_PTS_NB];
+    int64_t cur_frame_pts[AV_PARSER_PTS_NB];
+    int64_t cur_frame_dts[AV_PARSER_PTS_NB];
+
+    int flags;
+#define PARSER_FLAG_COMPLETE_FRAMES           0x0001
+
+    int64_t offset;      ///< byte offset from starting packet start
+    int64_t last_offset;
+} AVCodecParserContext;
+
+typedef struct AVCodecParser {
+    int codec_ids[5]; /* several codec IDs are permitted */
+    int priv_data_size;
+    int (*parser_init)(AVCodecParserContext *s);
+    int (*parser_parse)(AVCodecParserContext *s,
+                        AVCodecContext *avctx,
+                        const uint8_t **poutbuf, int *poutbuf_size,
+                        const uint8_t *buf, int buf_size);
+    void (*parser_close)(AVCodecParserContext *s);
+    int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size);
+    struct AVCodecParser *next;
+} AVCodecParser;
+
+extern AVCodecParser *av_first_parser;
+
+void av_register_codec_parser(AVCodecParser *parser);
+AVCodecParserContext *av_parser_init(int codec_id);
+int av_parser_parse(AVCodecParserContext *s,
+                    AVCodecContext *avctx,
+                    uint8_t **poutbuf, int *poutbuf_size,
+                    const uint8_t *buf, int buf_size,
+                    int64_t pts, int64_t dts);
+int av_parser_change(AVCodecParserContext *s,
+                     AVCodecContext *avctx,
+                     uint8_t **poutbuf, int *poutbuf_size,
+                     const uint8_t *buf, int buf_size, int keyframe);
+void av_parser_close(AVCodecParserContext *s);
+
+extern AVCodecParser aac_parser;
+extern AVCodecParser ac3_parser;
+extern AVCodecParser cavsvideo_parser;
+extern AVCodecParser dca_parser;
+extern AVCodecParser dvbsub_parser;
+extern AVCodecParser dvdsub_parser;
+extern AVCodecParser h261_parser;
+extern AVCodecParser h263_parser;
+extern AVCodecParser h264_parser;
+extern AVCodecParser mjpeg_parser;
+extern AVCodecParser mpeg4video_parser;
+extern AVCodecParser mpegaudio_parser;
+extern AVCodecParser mpegvideo_parser;
+extern AVCodecParser pnm_parser;
+extern AVCodecParser vc1_parser;
+
+
+typedef struct AVBitStreamFilterContext {
+    void *priv_data;
+    struct AVBitStreamFilter *filter;
+    AVCodecParserContext *parser;
+    struct AVBitStreamFilterContext *next;
+} AVBitStreamFilterContext;
+
+
+typedef struct AVBitStreamFilter {
+    const char *name;
+    int priv_data_size;
+    int (*filter)(AVBitStreamFilterContext *bsfc,
+                  AVCodecContext *avctx, const char *args,
+                  uint8_t **poutbuf, int *poutbuf_size,
+                  const uint8_t *buf, int buf_size, int keyframe);
+    struct AVBitStreamFilter *next;
+} AVBitStreamFilter;
+
+extern AVBitStreamFilter *av_first_bitstream_filter;
+
+void av_register_bitstream_filter(AVBitStreamFilter *bsf);
+AVBitStreamFilterContext *av_bitstream_filter_init(const char *name);
+int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
+                               AVCodecContext *avctx, const char *args,
+                               uint8_t **poutbuf, int *poutbuf_size,
+                               const uint8_t *buf, int buf_size, int keyframe);
+void av_bitstream_filter_close(AVBitStreamFilterContext *bsf);
+
+extern AVBitStreamFilter dump_extradata_bsf;
+extern AVBitStreamFilter remove_extradata_bsf;
+extern AVBitStreamFilter noise_bsf;
+extern AVBitStreamFilter mp3_header_compress_bsf;
+extern AVBitStreamFilter mp3_header_decompress_bsf;
+extern AVBitStreamFilter mjpega_dump_header_bsf;
+extern AVBitStreamFilter imx_dump_header_bsf;
+
+
+/* memory */
+
+/**
+ * Reallocates the given block if it is not large enough, otherwise it
+ * does nothing.
+ *
+ * @see av_realloc
+ */
+void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size);
+
+/* for static data only */
+
+/**
+ * Frees all static arrays and resets their pointers to 0.
+ * Call this function to release all statically allocated tables.
+ *
+ * @deprecated. Code which uses av_free_static is broken/missdesigned
+ * and should correctly use static arrays
+ *
+ */
+attribute_deprecated void av_free_static(void);
+
+/**
+ * Allocation of static arrays.
+ *
+ * @warning Do not use for normal allocation.
+ *
+ * @param[in] size The amount of memory you need in bytes.
+ * @return block of memory of the requested size
+ * @deprecated. Code which uses av_mallocz_static is broken/missdesigned
+ * and should correctly use static arrays
+ */
+attribute_deprecated void *av_mallocz_static(unsigned int size);
+
+/**
+ * Copy image 'src' to 'dst'.
+ */
+void av_picture_copy(AVPicture *dst, const AVPicture *src,
+              int pix_fmt, int width, int height);
+
+/**
+ * Crop image top and left side.
+ */
+int av_picture_crop(AVPicture *dst, const AVPicture *src,
+             int pix_fmt, int top_band, int left_band);
+
+/**
+ * Pad image.
+ */
+int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, int pix_fmt,
+            int padtop, int padbottom, int padleft, int padright, int *color);
+
+#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
+/**
+ * @deprecated Use the software scaler (swscale) instead.
+ */
+attribute_deprecated void img_copy(AVPicture *dst, const AVPicture *src,
+              int pix_fmt, int width, int height);
+
+/**
+ * @deprecated Use the software scaler (swscale) instead.
+ */
+attribute_deprecated int img_crop(AVPicture *dst, const AVPicture *src,
+             int pix_fmt, int top_band, int left_band);
+
+/**
+ * @deprecated Use the software scaler (swscale) instead.
+ */
+attribute_deprecated int img_pad(AVPicture *dst, const AVPicture *src, int height, int width, int pix_fmt,
+            int padtop, int padbottom, int padleft, int padright, int *color);
+#endif
+
+extern unsigned int av_xiphlacing(unsigned char *s, unsigned int v);
+
+/**
+ * Parses \p str and put in \p width_ptr and \p height_ptr the detected values.
+ *
+ * @return 0 in case of a successful parsing, a negative value otherwise
+ * @param[in] str the string to parse: it has to be a string in the format
+ * <width>x<height> or a valid video frame size abbreviation.
+ * @param[in,out] width_ptr pointer to the variable which will contain the detected
+ * frame width value
+ * @param[in,out] height_ptr pointer to the variable which will contain the detected
+ * frame height value
+ */
+int av_parse_video_frame_size(int *width_ptr, int *height_ptr, const char *str);
+
+/**
+ * Parses \p str and put in \p frame_rate the detected values.
+ *
+ * @return 0 in case of a successful parsing, a negative value otherwise
+ * @param[in] str the string to parse: it has to be a string in the format
+ * <frame_rate_nom>/<frame_rate_den>, a float number or a valid video rate abbreviation
+ * @param[in,out] frame_rate pointer to the AVRational which will contain the detected
+ * frame rate
+ */
+int av_parse_video_frame_rate(AVRational *frame_rate, const char *str);
+
+/* error handling */
+#if EINVAL > 0
+#define AVERROR(e) (-(e)) /**< Returns a negative error code from a POSIX error code, to return from library functions. */
+#define AVUNERROR(e) (-(e)) /**< Returns a POSIX error code from a library function error return value. */
+#else
+/* Some platforms have E* and errno already negated. */
+#define AVERROR(e) (e)
+#define AVUNERROR(e) (e)
+#endif
+#define AVERROR_UNKNOWN     AVERROR(EINVAL)  /**< unknown error */
+#define AVERROR_IO          AVERROR(EIO)     /**< I/O error */
+#define AVERROR_NUMEXPECTED AVERROR(EDOM)    /**< Number syntax expected in filename. */
+#define AVERROR_INVALIDDATA AVERROR(EINVAL)  /**< invalid data found */
+#define AVERROR_NOMEM       AVERROR(ENOMEM)  /**< not enough memory */
+#define AVERROR_NOFMT       AVERROR(EILSEQ)  /**< unknown format */
+#define AVERROR_NOTSUPP     AVERROR(ENOSYS)  /**< Operation not supported. */
+#define AVERROR_NOENT       AVERROR(ENOENT)  /**< No such file or directory. */
+
+#endif /* AVCODEC_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avformat.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avformat.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avformat.h	(revision 18425)
@@ -0,0 +1,875 @@
+/*
+ * copyright (c) 2001 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFORMAT_H
+#define AVFORMAT_H
+
+#define LIBAVFORMAT_VERSION_INT ((51<<16)+(12<<8)+1)
+#define LIBAVFORMAT_VERSION     51.12.1
+#define LIBAVFORMAT_BUILD       LIBAVFORMAT_VERSION_INT
+
+#define LIBAVFORMAT_IDENT       "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
+
+#include <time.h>
+#include <stdio.h>  /* FILE */
+#include "avcodec.h"
+
+#include "avio.h"
+
+/* packet functions */
+
+typedef struct AVPacket {
+    int64_t pts;                            ///< presentation time stamp in time_base units
+    int64_t dts;                            ///< decompression time stamp in time_base units
+    uint8_t *data;
+    int   size;
+    int   stream_index;
+    int   flags;
+    int   duration;                         ///< presentation duration in time_base units (0 if not available)
+    void  (*destruct)(struct AVPacket *);
+    void  *priv;
+    int64_t pos;                            ///< byte position in stream, -1 if unknown
+} AVPacket;
+#define PKT_FLAG_KEY   0x0001
+
+void av_destruct_packet_nofree(AVPacket *pkt);
+
+/**
+ * Default packet destructor.
+ */
+void av_destruct_packet(AVPacket *pkt);
+
+/**
+ * Initialize optional fields of a packet to default values.
+ *
+ * @param pkt packet
+ */
+void av_init_packet(AVPacket *pkt);
+
+/**
+ * Allocate the payload of a packet and initialize its fields to default values.
+ *
+ * @param pkt packet
+ * @param size wanted payload size
+ * @return 0 if OK. AVERROR_xxx otherwise.
+ */
+int av_new_packet(AVPacket *pkt, int size);
+
+/**
+ * Allocate and read the payload of a packet and initialize its fields to default values.
+ *
+ * @param pkt packet
+ * @param size wanted payload size
+ * @return >0 (read size) if OK. AVERROR_xxx otherwise.
+ */
+int av_get_packet(ByteIOContext *s, AVPacket *pkt, int size);
+
+/**
+ * @warning This is a hack - the packet memory allocation stuff is broken. The
+ * packet is allocated if it was not really allocated
+ */
+int av_dup_packet(AVPacket *pkt);
+
+/**
+ * Free a packet
+ *
+ * @param pkt packet to free
+ */
+static inline void av_free_packet(AVPacket *pkt)
+{
+    if (pkt && pkt->destruct) {
+        pkt->destruct(pkt);
+    }
+}
+
+/*************************************************/
+/* fractional numbers for exact pts handling */
+
+/**
+ * the exact value of the fractional number is: 'val + num / den'.
+ * num is assumed to be such as 0 <= num < den
+ * @deprecated Use AVRational instead
+*/
+typedef struct AVFrac {
+    int64_t val, num, den;
+} AVFrac attribute_deprecated;
+
+/*************************************************/
+/* input/output formats */
+
+struct AVCodecTag;
+
+struct AVFormatContext;
+
+/** this structure contains the data a format has to probe a file */
+typedef struct AVProbeData {
+    const char *filename;
+    unsigned char *buf;
+    int buf_size;
+} AVProbeData;
+
+#define AVPROBE_SCORE_MAX 100               ///< max score, half of that is used for file extension based detection
+#define AVPROBE_PADDING_SIZE 32             ///< extra allocated bytes at the end of the probe buffer
+
+typedef struct AVFormatParameters {
+    AVRational time_base;
+    int sample_rate;
+    int channels;
+    int width;
+    int height;
+    enum PixelFormat pix_fmt;
+    int channel; /**< used to select dv channel */
+#if LIBAVFORMAT_VERSION_INT < (52<<16)
+    const char *device; /**< video, audio or DV device */
+#endif
+    const char *standard; /**< tv standard, NTSC, PAL, SECAM */
+    int mpeg2ts_raw:1;  /**< force raw MPEG2 transport stream output, if possible */
+    int mpeg2ts_compute_pcr:1; /**< compute exact PCR for each transport
+                                  stream packet (only meaningful if
+                                  mpeg2ts_raw is TRUE) */
+    int initial_pause:1;       /**< do not begin to play the stream
+                                  immediately (RTSP only) */
+    int prealloced_context:1;
+    enum CodecID video_codec_id;
+    enum CodecID audio_codec_id;
+} AVFormatParameters;
+
+//! demuxer will use url_fopen, no opened file should be provided by the caller
+#define AVFMT_NOFILE        0x0001
+#define AVFMT_NEEDNUMBER    0x0002 /**< needs '%d' in filename */
+#define AVFMT_SHOW_IDS      0x0008 /**< show format stream IDs numbers */
+#define AVFMT_RAWPICTURE    0x0020 /**< format wants AVPicture structure for
+                                      raw picture data */
+#define AVFMT_GLOBALHEADER  0x0040 /**< format wants global header */
+#define AVFMT_NOTIMESTAMPS  0x0080 /**< format does not need / have any timestamps */
+#define AVFMT_GENERIC_INDEX 0x0100 /**< use generic index building code */
+
+typedef struct AVOutputFormat {
+    const char *name;
+    const char *long_name;
+    const char *mime_type;
+    const char *extensions; /**< comma separated filename extensions */
+    /** size of private data so that it can be allocated in the wrapper */
+    int priv_data_size;
+    /* output support */
+    enum CodecID audio_codec; /**< default audio codec */
+    enum CodecID video_codec; /**< default video codec */
+    int (*write_header)(struct AVFormatContext *);
+    int (*write_packet)(struct AVFormatContext *, AVPacket *pkt);
+    int (*write_trailer)(struct AVFormatContext *);
+    /** can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER */
+    int flags;
+    /** currently only used to set pixel format if not YUV420P */
+    int (*set_parameters)(struct AVFormatContext *, AVFormatParameters *);
+    int (*interleave_packet)(struct AVFormatContext *, AVPacket *out, AVPacket *in, int flush);
+
+    /**
+     * list of supported codec_id-codec_tag pairs, ordered by "better choice first"
+     * the arrays are all CODEC_ID_NONE terminated
+     */
+    const struct AVCodecTag **codec_tag;
+
+    /* private fields */
+    struct AVOutputFormat *next;
+} AVOutputFormat;
+
+typedef struct AVInputFormat {
+    const char *name;
+    const char *long_name;
+    /** size of private data so that it can be allocated in the wrapper */
+    int priv_data_size;
+    /** tell if a given file has a chance of being parsed by this format */
+    int (*read_probe)(AVProbeData *);
+    /** read the format header and initialize the AVFormatContext
+       structure. Return 0 if OK. 'ap' if non NULL contains
+       additional paramters. Only used in raw format right
+       now. 'av_new_stream' should be called to create new streams.  */
+    int (*read_header)(struct AVFormatContext *,
+                       AVFormatParameters *ap);
+    /** read one packet and put it in 'pkt'. pts and flags are also
+       set. 'av_new_stream' can be called only if the flag
+       AVFMTCTX_NOHEADER is used. */
+    int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
+    /** close the stream. The AVFormatContext and AVStreams are not
+       freed by this function */
+    int (*read_close)(struct AVFormatContext *);
+    /**
+     * seek to a given timestamp relative to the frames in
+     * stream component stream_index
+     * @param stream_index must not be -1
+     * @param flags selects which direction should be preferred if no exact
+     *              match is available
+     * @return >= 0 on success (but not necessarily the new offset)
+     */
+    int (*read_seek)(struct AVFormatContext *,
+                     int stream_index, int64_t timestamp, int flags);
+    /**
+     * gets the next timestamp in AV_TIME_BASE units.
+     */
+    int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,
+                              int64_t *pos, int64_t pos_limit);
+    /** can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER */
+    int flags;
+    /** if extensions are defined, then no probe is done. You should
+       usually not use extension format guessing because it is not
+       reliable enough */
+    const char *extensions;
+    /** general purpose read only value that the format can use */
+    int value;
+
+    /** start/resume playing - only meaningful if using a network based format
+       (RTSP) */
+    int (*read_play)(struct AVFormatContext *);
+
+    /** pause playing - only meaningful if using a network based format
+       (RTSP) */
+    int (*read_pause)(struct AVFormatContext *);
+
+    const struct AVCodecTag **codec_tag;
+
+    /* private fields */
+    struct AVInputFormat *next;
+} AVInputFormat;
+
+enum AVStreamParseType {
+    AVSTREAM_PARSE_NONE,
+    AVSTREAM_PARSE_FULL,       /**< full parsing and repack */
+    AVSTREAM_PARSE_HEADERS,    /**< only parse headers, don't repack */
+    AVSTREAM_PARSE_TIMESTAMPS, /**< full parsing and interpolation of timestamps for frames not starting on packet boundary */
+};
+
+typedef struct AVIndexEntry {
+    int64_t pos;
+    int64_t timestamp;
+#define AVINDEX_KEYFRAME 0x0001
+    int flags:2;
+    int size:30; //Yeah, trying to keep the size of this small to reduce memory requirements (it is 24 vs 32 byte due to possible 8byte align).
+    int min_distance;         /**< min distance between this and the previous keyframe, used to avoid unneeded searching */
+} AVIndexEntry;
+
+typedef struct AVStream {
+    int index;    /**< stream index in AVFormatContext */
+    int id;       /**< format specific stream id */
+    AVCodecContext *codec; /**< codec context */
+    /**
+     * real base frame rate of the stream.
+     * this is the lowest framerate with which all timestamps can be
+     * represented accurately (it is the least common multiple of all
+     * framerates in the stream), Note, this value is just a guess!
+     * for example if the timebase is 1/90000 and all frames have either
+     * approximately 3600 or 1800 timer ticks then r_frame_rate will be 50/1
+     */
+    AVRational r_frame_rate;
+    void *priv_data;
+#if LIBAVFORMAT_VERSION_INT < (52<<16)
+    /* internal data used in av_find_stream_info() */
+    int64_t codec_info_duration;
+    int codec_info_nb_frames;
+#endif
+    /** encoding: PTS generation when outputing stream */
+    struct AVFrac pts;
+
+    /**
+     * this is the fundamental unit of time (in seconds) in terms
+     * of which frame timestamps are represented. for fixed-fps content,
+     * timebase should be 1/framerate and timestamp increments should be
+     * identically 1.
+     */
+    AVRational time_base;
+    int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */
+    /* ffmpeg.c private use */
+    int stream_copy; /**< if set, just copy stream */
+    enum AVDiscard discard; ///< selects which packets can be discarded at will and do not need to be demuxed
+    //FIXME move stuff to a flags field?
+    /** quality, as it has been removed from AVCodecContext and put in AVVideoFrame
+     * MN: dunno if that is the right place for it */
+    float quality;
+    /** decoding: pts of the first frame of the stream, in stream time base. */
+    int64_t start_time;
+    /** decoding: duration of the stream, in stream time base. */
+    int64_t duration;
+
+    char language[4]; /** ISO 639 3-letter language code (empty string if undefined) */
+
+    /* av_read_frame() support */
+    enum AVStreamParseType need_parsing;
+    struct AVCodecParserContext *parser;
+
+    int64_t cur_dts;
+    int last_IP_duration;
+    int64_t last_IP_pts;
+    /* av_seek_frame() support */
+    AVIndexEntry *index_entries; /**< only used if the format does not
+                                    support seeking natively */
+    int nb_index_entries;
+    unsigned int index_entries_allocated_size;
+
+    int64_t nb_frames;                 ///< number of frames in this stream if known or 0
+
+#define MAX_REORDER_DELAY 4
+    int64_t pts_buffer[MAX_REORDER_DELAY+1];
+} AVStream;
+
+#define AVFMTCTX_NOHEADER      0x0001 /**< signal that no header is present
+                                         (streams are added dynamically) */
+
+#define MAX_STREAMS 20
+
+/* format I/O context */
+typedef struct AVFormatContext {
+    const AVClass *av_class; /**< set by av_alloc_format_context */
+    /* can only be iformat or oformat, not both at the same time */
+    struct AVInputFormat *iformat;
+    struct AVOutputFormat *oformat;
+    void *priv_data;
+    ByteIOContext pb;
+    unsigned int nb_streams;
+    AVStream *streams[MAX_STREAMS];
+    char filename[1024]; /**< input or output filename */
+    /* stream info */
+    int64_t timestamp;
+    char title[512];
+    char author[512];
+    char copyright[512];
+    char comment[512];
+    char album[512];
+    int year;  /**< ID3 year, 0 if none */
+    int track; /**< track number, 0 if none */
+    char genre[32]; /**< ID3 genre */
+
+    int ctx_flags; /**< format specific flags, see AVFMTCTX_xx */
+    /* private data for pts handling (do not modify directly) */
+    /** This buffer is only needed when packets were already buffered but
+       not decoded, for example to get the codec parameters in mpeg
+       streams */
+    struct AVPacketList *packet_buffer;
+
+    /** decoding: position of the first frame of the component, in
+       AV_TIME_BASE fractional seconds. NEVER set this value directly:
+       it is deduced from the AVStream values.  */
+    int64_t start_time;
+    /** decoding: duration of the stream, in AV_TIME_BASE fractional
+       seconds. NEVER set this value directly: it is deduced from the
+       AVStream values.  */
+    int64_t duration;
+    /** decoding: total file size. 0 if unknown */
+    int64_t file_size;
+    /** decoding: total stream bitrate in bit/s, 0 if not
+       available. Never set it directly if the file_size and the
+       duration are known as ffmpeg can compute it automatically. */
+    int bit_rate;
+
+    /* av_read_frame() support */
+    AVStream *cur_st;
+    const uint8_t *cur_ptr;
+    int cur_len;
+    AVPacket cur_pkt;
+
+    /* av_seek_frame() support */
+    int64_t data_offset; /** offset of the first packet */
+    int index_built;
+
+    int mux_rate;
+    int packet_size;
+    int preload;
+    int max_delay;
+
+#define AVFMT_NOOUTPUTLOOP -1
+#define AVFMT_INFINITEOUTPUTLOOP 0
+    /** number of times to loop output in formats that support it */
+    int loop_output;
+
+    int flags;
+#define AVFMT_FLAG_GENPTS       0x0001 ///< generate pts if missing even if it requires parsing future frames
+#define AVFMT_FLAG_IGNIDX       0x0002 ///< ignore index
+#define AVFMT_FLAG_NONBLOCK     0x0004 ///< do not block when reading packets from input
+
+    int loop_input;
+    /** decoding: size of data to probe; encoding unused */
+    unsigned int probesize;
+
+    /**
+     * maximum duration in AV_TIME_BASE units over which the input should be analyzed in av_find_stream_info()
+     */
+    int max_analyze_duration;
+
+    const uint8_t *key;
+    int keylen;
+} AVFormatContext;
+
+typedef struct AVPacketList {
+    AVPacket pkt;
+    struct AVPacketList *next;
+} AVPacketList;
+
+extern AVInputFormat *first_iformat;
+extern AVOutputFormat *first_oformat;
+
+enum CodecID av_guess_image2_codec(const char *filename);
+
+/* XXX: use automatic init with either ELF sections or C file parser */
+/* modules */
+
+#include "rtp.h"
+
+#include "rtsp.h"
+
+/* utils.c */
+void av_register_input_format(AVInputFormat *format);
+void av_register_output_format(AVOutputFormat *format);
+AVOutputFormat *guess_stream_format(const char *short_name,
+                                    const char *filename, const char *mime_type);
+AVOutputFormat *guess_format(const char *short_name,
+                             const char *filename, const char *mime_type);
+
+/**
+ * Guesses the codec id based upon muxer and filename.
+ */
+enum CodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name,
+                            const char *filename, const char *mime_type, enum CodecType type);
+
+/**
+ * Send a nice hexadecimal dump of a buffer to the specified file stream.
+ *
+ * @param f The file stream pointer where the dump should be sent to.
+ * @param buf buffer
+ * @param size buffer size
+ *
+ * @see av_hex_dump_log, av_pkt_dump, av_pkt_dump_log
+ */
+void av_hex_dump(FILE *f, uint8_t *buf, int size);
+
+/**
+ * Send a nice hexadecimal dump of a buffer to the log.
+ *
+ * @param avcl A pointer to an arbitrary struct of which the first field is a
+ * pointer to an AVClass struct.
+ * @param level The importance level of the message, lower values signifying
+ * higher importance.
+ * @param buf buffer
+ * @param size buffer size
+ *
+ * @see av_hex_dump, av_pkt_dump, av_pkt_dump_log
+ */
+void av_hex_dump_log(void *avcl, int level, uint8_t *buf, int size);
+
+/**
+ * Send a nice dump of a packet to the specified file stream.
+ *
+ * @param f The file stream pointer where the dump should be sent to.
+ * @param pkt packet to dump
+ * @param dump_payload true if the payload must be displayed too
+ */
+void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload);
+
+/**
+ * Send a nice dump of a packet to the log.
+ *
+ * @param avcl A pointer to an arbitrary struct of which the first field is a
+ * pointer to an AVClass struct.
+ * @param level The importance level of the message, lower values signifying
+ * higher importance.
+ * @param pkt packet to dump
+ * @param dump_payload true if the payload must be displayed too
+ */
+void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, int dump_payload);
+
+void av_register_all(void);
+
+/** codec tag <-> codec id */
+enum CodecID av_codec_get_id(const struct AVCodecTag **tags, unsigned int tag);
+unsigned int av_codec_get_tag(const struct AVCodecTag **tags, enum CodecID id);
+
+/* media file input */
+
+/**
+ * finds AVInputFormat based on input format's short name.
+ */
+AVInputFormat *av_find_input_format(const char *short_name);
+
+/**
+ * Guess file format.
+ *
+ * @param is_opened whether the file is already opened, determines whether
+ *                  demuxers with or without AVFMT_NOFILE are probed
+ */
+AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened);
+
+/**
+ * Allocates all the structures needed to read an input stream.
+ *        This does not open the needed codecs for decoding the stream[s].
+ */
+int av_open_input_stream(AVFormatContext **ic_ptr,
+                         ByteIOContext *pb, const char *filename,
+                         AVInputFormat *fmt, AVFormatParameters *ap);
+
+/**
+ * Open a media file as input. The codecs are not opened. Only the file
+ * header (if present) is read.
+ *
+ * @param ic_ptr the opened media file handle is put here
+ * @param filename filename to open.
+ * @param fmt if non NULL, force the file format to use
+ * @param buf_size optional buffer size (zero if default is OK)
+ * @param ap additional parameters needed when opening the file (NULL if default)
+ * @return 0 if OK. AVERROR_xxx otherwise.
+ */
+int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
+                       AVInputFormat *fmt,
+                       int buf_size,
+                       AVFormatParameters *ap);
+/** no av_open for output, so applications will need this: */
+AVFormatContext *av_alloc_format_context(void);
+
+/**
+ * Read packets of a media file to get stream information. This
+ * is useful for file formats with no headers such as MPEG. This
+ * function also computes the real frame rate in case of mpeg2 repeat
+ * frame mode.
+ * The logical file position is not changed by this function;
+ * examined packets may be buffered for later processing.
+ *
+ * @param ic media file handle
+ * @return >=0 if OK. AVERROR_xxx if error.
+ * @todo Let user decide somehow what information is needed so we do not waste time geting stuff the user does not need.
+ */
+int av_find_stream_info(AVFormatContext *ic);
+
+/**
+ * Read a transport packet from a media file.
+ *
+ * This function is obsolete and should never be used.
+ * Use av_read_frame() instead.
+ *
+ * @param s media file handle
+ * @param pkt is filled
+ * @return 0 if OK. AVERROR_xxx if error.
+ */
+int av_read_packet(AVFormatContext *s, AVPacket *pkt);
+
+/**
+ * Return the next frame of a stream.
+ *
+ * The returned packet is valid
+ * until the next av_read_frame() or until av_close_input_file() and
+ * must be freed with av_free_packet. For video, the packet contains
+ * exactly one frame. For audio, it contains an integer number of
+ * frames if each frame has a known fixed size (e.g. PCM or ADPCM
+ * data). If the audio frames have a variable size (e.g. MPEG audio),
+ * then it contains one frame.
+ *
+ * pkt->pts, pkt->dts and pkt->duration are always set to correct
+ * values in AVStream.timebase units (and guessed if the format cannot
+ * provided them). pkt->pts can be AV_NOPTS_VALUE if the video format
+ * has B frames, so it is better to rely on pkt->dts if you do not
+ * decompress the payload.
+ *
+ * @return 0 if OK, < 0 if error or end of file.
+ */
+int av_read_frame(AVFormatContext *s, AVPacket *pkt);
+
+/**
+ * Seek to the key frame at timestamp.
+ * 'timestamp' in 'stream_index'.
+ * @param stream_index If stream_index is (-1), a default
+ * stream is selected, and timestamp is automatically converted
+ * from AV_TIME_BASE units to the stream specific time_base.
+ * @param timestamp timestamp in AVStream.time_base units
+ *        or if there is no stream specified then in AV_TIME_BASE units
+ * @param flags flags which select direction and seeking mode
+ * @return >= 0 on success
+ */
+int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);
+
+/**
+ * start playing a network based stream (e.g. RTSP stream) at the
+ * current position
+ */
+int av_read_play(AVFormatContext *s);
+
+/**
+ * Pause a network based stream (e.g. RTSP stream).
+ *
+ * Use av_read_play() to resume it.
+ */
+int av_read_pause(AVFormatContext *s);
+
+/**
+ * Close a media file (but not its codecs).
+ *
+ * @param s media file handle
+ */
+void av_close_input_file(AVFormatContext *s);
+
+/**
+ * Add a new stream to a media file.
+ *
+ * Can only be called in the read_header() function. If the flag
+ * AVFMTCTX_NOHEADER is in the format context, then new streams
+ * can be added in read_packet too.
+ *
+ * @param s media file handle
+ * @param id file format dependent stream id
+ */
+AVStream *av_new_stream(AVFormatContext *s, int id);
+
+/**
+ * Set the pts for a given stream.
+ *
+ * @param s stream
+ * @param pts_wrap_bits number of bits effectively used by the pts
+ *        (used for wrap control, 33 is the value for MPEG)
+ * @param pts_num numerator to convert to seconds (MPEG: 1)
+ * @param pts_den denominator to convert to seconds (MPEG: 90000)
+ */
+void av_set_pts_info(AVStream *s, int pts_wrap_bits,
+                     int pts_num, int pts_den);
+
+#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward
+#define AVSEEK_FLAG_BYTE     2 ///< seeking based on position in bytes
+#define AVSEEK_FLAG_ANY      4 ///< seek to any frame, even non keyframes
+
+int av_find_default_stream_index(AVFormatContext *s);
+
+/**
+ * Gets the index for a specific timestamp.
+ * @param flags if AVSEEK_FLAG_BACKWARD then the returned index will correspond to
+ *                 the timestamp which is <= the requested one, if backward is 0
+ *                 then it will be >=
+ *              if AVSEEK_FLAG_ANY seek to any frame, only keyframes otherwise
+ * @return < 0 if no such timestamp could be found
+ */
+int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags);
+
+/**
+ * Add a index entry into a sorted list updateing if it is already there.
+ *
+ * @param timestamp timestamp in the timebase of the given stream
+ */
+int av_add_index_entry(AVStream *st,
+                       int64_t pos, int64_t timestamp, int size, int distance, int flags);
+
+/**
+ * Does a binary search using av_index_search_timestamp() and AVCodec.read_timestamp().
+ * This is not supposed to be called directly by a user application, but by demuxers.
+ * @param target_ts target timestamp in the time base of the given stream
+ * @param stream_index stream number
+ */
+int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags);
+
+/**
+ * Updates cur_dts of all streams based on given timestamp and AVStream.
+ *
+ * Stream ref_st unchanged, others set cur_dts in their native timebase
+ * only needed for timestamp wrapping or if (dts not set and pts!=dts).
+ * @param timestamp new dts expressed in time_base of param ref_st
+ * @param ref_st reference stream giving time_base of param timestamp
+ */
+void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp);
+
+/**
+ * Does a binary search using read_timestamp().
+ * This is not supposed to be called directly by a user application, but by demuxers.
+ * @param target_ts target timestamp in the time base of the given stream
+ * @param stream_index stream number
+ */
+int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, int64_t pos_min, int64_t pos_max, int64_t pos_limit, int64_t ts_min, int64_t ts_max, int flags, int64_t *ts_ret, int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t ));
+
+/** media file output */
+int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap);
+
+/**
+ * Allocate the stream private data and write the stream header to an
+ * output media file.
+ *
+ * @param s media file handle
+ * @return 0 if OK. AVERROR_xxx if error.
+ */
+int av_write_header(AVFormatContext *s);
+
+/**
+ * Write a packet to an output media file.
+ *
+ * The packet shall contain one audio or video frame.
+ * The packet must be correctly interleaved according to the container specification,
+ * if not then av_interleaved_write_frame must be used
+ *
+ * @param s media file handle
+ * @param pkt the packet, which contains the stream_index, buf/buf_size, dts/pts, ...
+ * @return < 0 if error, = 0 if OK, 1 if end of stream wanted.
+ */
+int av_write_frame(AVFormatContext *s, AVPacket *pkt);
+
+/**
+ * Writes a packet to an output media file ensuring correct interleaving.
+ *
+ * The packet must contain one audio or video frame.
+ * If the packets are already correctly interleaved the application should
+ * call av_write_frame() instead as it is slightly faster. It is also important
+ * to keep in mind that completely non-interleaved input will need huge amounts
+ * of memory to interleave with this, so it is preferable to interleave at the
+ * demuxer level.
+ *
+ * @param s media file handle
+ * @param pkt the packet, which contains the stream_index, buf/buf_size, dts/pts, ...
+ * @return < 0 if error, = 0 if OK, 1 if end of stream wanted.
+ */
+int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);
+
+/**
+ * Interleave a packet per DTS in an output media file.
+ *
+ * Packets with pkt->destruct == av_destruct_packet will be freed inside this function,
+ * so they cannot be used after it, note calling av_free_packet() on them is still safe.
+ *
+ * @param s media file handle
+ * @param out the interleaved packet will be output here
+ * @param in the input packet
+ * @param flush 1 if no further packets are available as input and all
+ *              remaining packets should be output
+ * @return 1 if a packet was output, 0 if no packet could be output,
+ *         < 0 if an error occured
+ */
+int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush);
+
+/**
+ * @brief Write the stream trailer to an output media file and
+ *        free the file private data.
+ *
+ * @param s media file handle
+ * @return 0 if OK. AVERROR_xxx if error.
+ */
+int av_write_trailer(AVFormatContext *s);
+
+void dump_format(AVFormatContext *ic,
+                 int index,
+                 const char *url,
+                 int is_output);
+
+/**
+ * parses width and height out of string str.
+ * @deprecated Use av_parse_video_frame_size instead.
+ */
+attribute_deprecated int parse_image_size(int *width_ptr, int *height_ptr, const char *str);
+
+/**
+ * Converts frame rate from string to a fraction.
+ * @deprecated Use av_parse_video_frame_rate instead.
+ */
+attribute_deprecated int parse_frame_rate(int *frame_rate, int *frame_rate_base, const char *arg);
+
+/**
+ * Converts date string to number of seconds since Jan 1st, 1970.
+ *
+ * @code
+ * Syntax:
+ * - If not a duration:
+ *  [{YYYY-MM-DD|YYYYMMDD}]{T| }{HH[:MM[:SS[.m...]]][Z]|HH[MM[SS[.m...]]][Z]}
+ * Time is localtime unless Z is suffixed to the end. In this case GMT
+ * Return the date in micro seconds since 1970
+ *
+ * - If a duration:
+ *  HH[:MM[:SS[.m...]]]
+ *  S+[.m...]
+ * @endcode
+ */
+int64_t parse_date(const char *datestr, int duration);
+
+int64_t av_gettime(void);
+
+/* ffm specific for ffserver */
+#define FFM_PACKET_SIZE 4096
+offset_t ffm_read_write_index(int fd);
+void ffm_write_write_index(int fd, offset_t pos);
+void ffm_set_write_index(AVFormatContext *s, offset_t pos, offset_t file_size);
+
+/**
+ * Attempts to find a specific tag in a URL.
+ *
+ * syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done.
+ * Return 1 if found.
+ */
+int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info);
+
+/**
+ * Returns in 'buf' the path with '%d' replaced by number.
+
+ * Also handles the '%0nd' format where 'n' is the total number
+ * of digits and '%%'.
+ *
+ * @param buf destination buffer
+ * @param buf_size destination buffer size
+ * @param path numbered sequence string
+ * @number frame number
+ * @return 0 if OK, -1 if format error.
+ */
+int av_get_frame_filename(char *buf, int buf_size,
+                          const char *path, int number);
+
+/**
+ * Check whether filename actually is a numbered sequence generator.
+ *
+ * @param filename possible numbered sequence string
+ * @return 1 if a valid numbered sequence string, 0 otherwise.
+ */
+int av_filename_number_test(const char *filename);
+
+#ifdef HAVE_AV_CONFIG_H
+
+#include "os_support.h"
+
+void __dynarray_add(unsigned long **tab_ptr, int *nb_ptr, unsigned long elem);
+
+#ifdef __GNUC__
+#define dynarray_add(tab, nb_ptr, elem)\
+do {\
+    typeof(tab) _tab = (tab);\
+    typeof(elem) _elem = (elem);\
+    (void)sizeof(**_tab == _elem); /* check that types are compatible */\
+    __dynarray_add((unsigned long **)_tab, nb_ptr, (unsigned long)_elem);\
+} while(0)
+#else
+#define dynarray_add(tab, nb_ptr, elem)\
+do {\
+    __dynarray_add((unsigned long **)(tab), nb_ptr, (unsigned long)(elem));\
+} while(0)
+#endif
+
+time_t mktimegm(struct tm *tm);
+struct tm *brktimegm(time_t secs, struct tm *tm);
+const char *small_strptime(const char *p, const char *fmt,
+                           struct tm *dt);
+
+struct in_addr;
+int resolve_host(struct in_addr *sin_addr, const char *hostname);
+
+void url_split(char *proto, int proto_size,
+               char *authorization, int authorization_size,
+               char *hostname, int hostname_size,
+               int *port_ptr,
+               char *path, int path_size,
+               const char *url);
+
+int match_ext(const char *filename, const char *extensions);
+
+#endif /* HAVE_AV_CONFIG_H */
+
+#endif /* AVFORMAT_H */
+
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avio.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avio.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avio.h	(revision 18425)
@@ -0,0 +1,274 @@
+/*
+ * unbuffered io for ffmpeg system
+ * copyright (c) 2001 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef AVIO_H
+#define AVIO_H
+
+#include <stdint.h>
+
+/* output byte stream handling */
+
+typedef int64_t offset_t;
+
+/* unbuffered I/O */
+
+struct URLContext {
+    struct URLProtocol *prot;
+    int flags;
+    int is_streamed;  /**< true if streamed (no seek possible), default = false */
+    int max_packet_size;  /**< if non zero, the stream is packetized with this max packet size */
+    void *priv_data;
+#if LIBAVFORMAT_VERSION_INT >= (52<<16)
+    char *filename; /**< specified filename */
+#else
+    char filename[1]; /**< specified filename */
+#endif
+};
+
+typedef struct URLContext URLContext;
+
+typedef struct URLPollEntry {
+    URLContext *handle;
+    int events;
+    int revents;
+} URLPollEntry;
+
+#define URL_RDONLY 0
+#define URL_WRONLY 1
+#define URL_RDWR   2
+
+typedef int URLInterruptCB(void);
+
+int url_open(URLContext **h, const char *filename, int flags);
+int url_read(URLContext *h, unsigned char *buf, int size);
+int url_write(URLContext *h, unsigned char *buf, int size);
+offset_t url_seek(URLContext *h, offset_t pos, int whence);
+int url_close(URLContext *h);
+int url_exist(const char *filename);
+offset_t url_filesize(URLContext *h);
+
+/**
+ * Return the maximum packet size associated to packetized file
+ * handle. If the file is not packetized (stream like http or file on
+ * disk), then 0 is returned.
+ *
+ * @param h file handle
+ * @return maximum packet size in bytes
+ */
+int url_get_max_packet_size(URLContext *h);
+void url_get_filename(URLContext *h, char *buf, int buf_size);
+
+/**
+ * the callback is called in blocking functions to test regulary if
+ * asynchronous interruption is needed. AVERROR(EINTR) is returned
+ * in this case by the interrupted function. 'NULL' means no interrupt
+ * callback is given. i
+ */
+void url_set_interrupt_cb(URLInterruptCB *interrupt_cb);
+
+/* not implemented */
+int url_poll(URLPollEntry *poll_table, int n, int timeout);
+
+/**
+ * Passing this as the "whence" parameter to a seek function causes it to
+ * return the filesize without seeking anywhere. Supporting this is optional.
+ * If it is not supported then the seek function will return <0.
+ */
+#define AVSEEK_SIZE 0x10000
+
+typedef struct URLProtocol {
+    const char *name;
+    int (*url_open)(URLContext *h, const char *filename, int flags);
+    int (*url_read)(URLContext *h, unsigned char *buf, int size);
+    int (*url_write)(URLContext *h, unsigned char *buf, int size);
+    offset_t (*url_seek)(URLContext *h, offset_t pos, int whence);
+    int (*url_close)(URLContext *h);
+    struct URLProtocol *next;
+} URLProtocol;
+
+extern URLProtocol *first_protocol;
+extern URLInterruptCB *url_interrupt_cb;
+
+int register_protocol(URLProtocol *protocol);
+
+typedef struct {
+    unsigned char *buffer;
+    int buffer_size;
+    unsigned char *buf_ptr, *buf_end;
+    void *opaque;
+    int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);
+    int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);
+    offset_t (*seek)(void *opaque, offset_t offset, int whence);
+    offset_t pos; /**< position in the file of the current buffer */
+    int must_flush; /**< true if the next seek should flush */
+    int eof_reached; /**< true if eof reached */
+    int write_flag;  /**< true if open for writing */
+    int is_streamed;
+    int max_packet_size;
+    unsigned long checksum;
+    unsigned char *checksum_ptr;
+    unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);
+    int error;         ///< contains the error code or 0 if no error happened
+} ByteIOContext;
+
+int init_put_byte(ByteIOContext *s,
+                  unsigned char *buffer,
+                  int buffer_size,
+                  int write_flag,
+                  void *opaque,
+                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
+                  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
+                  offset_t (*seek)(void *opaque, offset_t offset, int whence));
+
+void put_byte(ByteIOContext *s, int b);
+void put_buffer(ByteIOContext *s, const unsigned char *buf, int size);
+void put_le64(ByteIOContext *s, uint64_t val);
+void put_be64(ByteIOContext *s, uint64_t val);
+void put_le32(ByteIOContext *s, unsigned int val);
+void put_be32(ByteIOContext *s, unsigned int val);
+void put_le24(ByteIOContext *s, unsigned int val);
+void put_be24(ByteIOContext *s, unsigned int val);
+void put_le16(ByteIOContext *s, unsigned int val);
+void put_be16(ByteIOContext *s, unsigned int val);
+void put_tag(ByteIOContext *s, const char *tag);
+
+void put_strz(ByteIOContext *s, const char *buf);
+
+offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence);
+void url_fskip(ByteIOContext *s, offset_t offset);
+offset_t url_ftell(ByteIOContext *s);
+offset_t url_fsize(ByteIOContext *s);
+int url_feof(ByteIOContext *s);
+int url_ferror(ByteIOContext *s);
+
+#define URL_EOF (-1)
+/** @note return URL_EOF (-1) if EOF */
+int url_fgetc(ByteIOContext *s);
+
+/** @warning currently size is limited */
+#ifdef __GNUC__
+int url_fprintf(ByteIOContext *s, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
+#else
+int url_fprintf(ByteIOContext *s, const char *fmt, ...);
+#endif
+
+/** @note unlike fgets, the EOL character is not returned and a whole
+   line is parsed. return NULL if first char read was EOF */
+char *url_fgets(ByteIOContext *s, char *buf, int buf_size);
+
+void put_flush_packet(ByteIOContext *s);
+
+int get_buffer(ByteIOContext *s, unsigned char *buf, int size);
+int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size);
+
+/** @note return 0 if EOF, so you cannot use it if EOF handling is
+   necessary */
+int get_byte(ByteIOContext *s);
+unsigned int get_le24(ByteIOContext *s);
+unsigned int get_le32(ByteIOContext *s);
+uint64_t get_le64(ByteIOContext *s);
+unsigned int get_le16(ByteIOContext *s);
+
+char *get_strz(ByteIOContext *s, char *buf, int maxlen);
+unsigned int get_be16(ByteIOContext *s);
+unsigned int get_be24(ByteIOContext *s);
+unsigned int get_be32(ByteIOContext *s);
+uint64_t get_be64(ByteIOContext *s);
+
+static inline int url_is_streamed(ByteIOContext *s)
+{
+    return s->is_streamed;
+}
+
+int url_fdopen(ByteIOContext *s, URLContext *h);
+
+/** @warning must be called before any I/O */
+int url_setbufsize(ByteIOContext *s, int buf_size);
+
+/** @note when opened as read/write, the buffers are only used for
+   reading */
+int url_fopen(ByteIOContext *s, const char *filename, int flags);
+int url_fclose(ByteIOContext *s);
+URLContext *url_fileno(ByteIOContext *s);
+
+/**
+ * Return the maximum packet size associated to packetized buffered file
+ * handle. If the file is not packetized (stream like http or file on
+ * disk), then 0 is returned.
+ *
+ * @param h buffered file handle
+ * @return maximum packet size in bytes
+ */
+int url_fget_max_packet_size(ByteIOContext *s);
+
+int url_open_buf(ByteIOContext *s, uint8_t *buf, int buf_size, int flags);
+
+/** return the written or read size */
+int url_close_buf(ByteIOContext *s);
+
+/**
+ * Open a write only memory stream.
+ *
+ * @param s new IO context
+ * @return zero if no error.
+ */
+int url_open_dyn_buf(ByteIOContext *s);
+
+/**
+ * Open a write only packetized memory stream with a maximum packet
+ * size of 'max_packet_size'.  The stream is stored in a memory buffer
+ * with a big endian 4 byte header giving the packet size in bytes.
+ *
+ * @param s new IO context
+ * @param max_packet_size maximum packet size (must be > 0)
+ * @return zero if no error.
+ */
+int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size);
+
+/**
+ * Return the written size and a pointer to the buffer. The buffer
+ *  must be freed with av_free().
+ * @param s IO context
+ * @param pointer to a byte buffer
+ * @return the length of the byte buffer
+ */
+int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer);
+
+unsigned long get_checksum(ByteIOContext *s);
+void init_checksum(ByteIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum);
+
+/* file.c */
+extern URLProtocol file_protocol;
+extern URLProtocol pipe_protocol;
+
+/* udp.c */
+extern URLProtocol udp_protocol;
+int udp_set_remote_url(URLContext *h, const char *uri);
+int udp_get_local_port(URLContext *h);
+int udp_get_file_handle(URLContext *h);
+
+/* tcp.c  */
+extern URLProtocol tcp_protocol;
+
+/* http.c */
+extern URLProtocol http_protocol;
+
+#endif
+
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avstring.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avstring.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avstring.h	(revision 18425)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007 Mans Rullgard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_STRING_H
+#define AVUTIL_STRING_H
+
+#include <stddef.h>
+
+/**
+ * Return non-zero if pfx is a prefix of str. If it is, *ptr is set to
+ * the address of the first character in str after the prefix.
+ *
+ * @param str input string
+ * @param pfx prefix to test
+ * @param ptr updated after the prefix in str in there is a match
+ * @return non-zero if the prefix matches, zero otherwise
+ */
+int av_strstart(const char *str, const char *pfx, const char **ptr);
+
+/**
+ * Return non-zero if pfx is a prefix of str independent of case. If
+ * it is, *ptr is set to the address of the first character in str
+ * after the prefix.
+ *
+ * @param str input string
+ * @param pfx prefix to test
+ * @param ptr updated after the prefix in str in there is a match
+ * @return non-zero if the prefix matches, zero otherwise
+ */
+int av_stristart(const char *str, const char *pfx, const char **ptr);
+
+/**
+ * Copy the string src to dst, but no more than size - 1 bytes, and
+ * null terminate dst.
+ *
+ * This function is the same as BSD strlcpy().
+ *
+ * @param dst destination buffer
+ * @param src source string
+ * @param size size of destination buffer
+ * @return the length of src
+ */
+size_t av_strlcpy(char *dst, const char *src, size_t size);
+
+/**
+ * Append the string src to the string dst, but to a total length of
+ * no more than size - 1 bytes, and null terminate dst.
+ *
+ * This function is similar to BSD strlcat(), but differs when
+ * size <= strlen(dst).
+ *
+ * @param dst destination buffer
+ * @param src source string
+ * @param size size of destination buffer
+ * @return the total length of src and dst
+ */
+size_t av_strlcat(char *dst, const char *src, size_t size);
+
+/**
+ * Append output to a string, according to a format. Never write out of
+ * the destination buffer, and and always put a terminating 0 within
+ * the buffer.
+ * @param dst destination buffer (string to which the output is
+ *  appended)
+ * @param size total size of the destination buffer
+ * @param fmt printf-compatible format string, specifying how the
+ *  following parameters are used
+ * @return the length of the string that would have been generated
+ *  if enough space had been available
+ */
+size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...);
+
+#endif /* AVUTIL_STRING_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avutil.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avutil.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/avutil.h	(revision 18425)
@@ -0,0 +1,131 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_H
+#define AVUTIL_H
+
+/**
+ * @file avutil.h
+ * external api header.
+ */
+
+
+#define AV_STRINGIFY(s)         AV_TOSTRING(s)
+#define AV_TOSTRING(s) #s
+
+#define LIBAVUTIL_VERSION_INT   ((49<<16)+(4<<8)+1)
+#define LIBAVUTIL_VERSION       49.4.1
+#define LIBAVUTIL_BUILD         LIBAVUTIL_VERSION_INT
+
+#define LIBAVUTIL_IDENT         "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION)
+
+
+#include "common.h"
+#include "mathematics.h"
+#include "rational.h"
+#include "integer.h"
+#include "intfloat_readwrite.h"
+#include "log.h"
+
+/**
+ * Pixel format. Notes:
+ *
+ * PIX_FMT_RGB32 is handled in an endian-specific manner. A RGBA
+ * color is put together as:
+ *  (A << 24) | (R << 16) | (G << 8) | B
+ * This is stored as BGRA on little endian CPU architectures and ARGB on
+ * big endian CPUs.
+ *
+ * When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized
+ * image data is stored in AVFrame.data[0]. The palette is transported in
+ * AVFrame.data[1] and, is 1024 bytes long (256 4-byte entries) and is
+ * formatted the same as in PIX_FMT_RGB32 described above (i.e., it is
+ * also endian-specific). Note also that the individual RGB palette
+ * components stored in AVFrame.data[1] should be in the range 0..255.
+ * This is important as many custom PAL8 video codecs that were designed
+ * to run on the IBM VGA graphics adapter use 6-bit palette components.
+ */
+enum PixelFormat {
+    PIX_FMT_NONE= -1,
+    PIX_FMT_YUV420P,   ///< Planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
+    PIX_FMT_YUYV422,   ///< Packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
+    PIX_FMT_RGB24,     ///< Packed RGB 8:8:8, 24bpp, RGBRGB...
+    PIX_FMT_BGR24,     ///< Packed RGB 8:8:8, 24bpp, BGRBGR...
+    PIX_FMT_YUV422P,   ///< Planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
+    PIX_FMT_YUV444P,   ///< Planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
+    PIX_FMT_RGB32,     ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8R 8G 8B(lsb), in cpu endianness
+    PIX_FMT_YUV410P,   ///< Planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples)
+    PIX_FMT_YUV411P,   ///< Planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
+    PIX_FMT_RGB565,    ///< Packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), in cpu endianness
+    PIX_FMT_RGB555,    ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), in cpu endianness most significant bit to 0
+    PIX_FMT_GRAY8,     ///<        Y        ,  8bpp
+    PIX_FMT_MONOWHITE, ///<        Y        ,  1bpp, 0 is white, 1 is black
+    PIX_FMT_MONOBLACK, ///<        Y        ,  1bpp, 0 is black, 1 is white
+    PIX_FMT_PAL8,      ///< 8 bit with PIX_FMT_RGB32 palette
+    PIX_FMT_YUVJ420P,  ///< Planar YUV 4:2:0, 12bpp, full scale (jpeg)
+    PIX_FMT_YUVJ422P,  ///< Planar YUV 4:2:2, 16bpp, full scale (jpeg)
+    PIX_FMT_YUVJ444P,  ///< Planar YUV 4:4:4, 24bpp, full scale (jpeg)
+    PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h)
+    PIX_FMT_XVMC_MPEG2_IDCT,
+    PIX_FMT_UYVY422,   ///< Packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
+    PIX_FMT_UYYVYY411, ///< Packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
+    PIX_FMT_BGR32,     ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8B 8G 8R(lsb), in cpu endianness
+    PIX_FMT_BGR565,    ///< Packed RGB 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), in cpu endianness
+    PIX_FMT_BGR555,    ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), in cpu endianness most significant bit to 1
+    PIX_FMT_BGR8,      ///< Packed RGB 3:3:2,  8bpp, (msb)2B 3G 3R(lsb)
+    PIX_FMT_BGR4,      ///< Packed RGB 1:2:1,  4bpp, (msb)1B 2G 1R(lsb)
+    PIX_FMT_BGR4_BYTE, ///< Packed RGB 1:2:1,  8bpp, (msb)1B 2G 1R(lsb)
+    PIX_FMT_RGB8,      ///< Packed RGB 3:3:2,  8bpp, (msb)2R 3G 3B(lsb)
+    PIX_FMT_RGB4,      ///< Packed RGB 1:2:1,  4bpp, (msb)2R 3G 3B(lsb)
+    PIX_FMT_RGB4_BYTE, ///< Packed RGB 1:2:1,  8bpp, (msb)2R 3G 3B(lsb)
+    PIX_FMT_NV12,      ///< Planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 for UV
+    PIX_FMT_NV21,      ///< as above, but U and V bytes are swapped
+
+    PIX_FMT_RGB32_1,   ///< Packed RGB 8:8:8, 32bpp, (msb)8R 8G 8B 8A(lsb), in cpu endianness
+    PIX_FMT_BGR32_1,   ///< Packed RGB 8:8:8, 32bpp, (msb)8B 8G 8R 8A(lsb), in cpu endianness
+
+    PIX_FMT_GRAY16BE,  ///<        Y        , 16bpp, big-endian
+    PIX_FMT_GRAY16LE,  ///<        Y        , 16bpp, little-endian
+    PIX_FMT_YUV440P,   ///< Planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
+    PIX_FMT_YUVJ440P,  ///< Planar YUV 4:4:0 full scale (jpeg)
+    PIX_FMT_NB,        ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
+};
+
+#ifdef WORDS_BIGENDIAN
+#define PIX_FMT_RGBA PIX_FMT_RGB32_1
+#define PIX_FMT_BGRA PIX_FMT_BGR32_1
+#define PIX_FMT_ARGB PIX_FMT_RGB32
+#define PIX_FMT_ABGR PIX_FMT_BGR32
+#define PIX_FMT_GRAY16 PIX_FMT_GRAY16BE
+#else
+#define PIX_FMT_RGBA PIX_FMT_BGR32
+#define PIX_FMT_BGRA PIX_FMT_RGB32
+#define PIX_FMT_ARGB PIX_FMT_BGR32_1
+#define PIX_FMT_ABGR PIX_FMT_RGB32_1
+#define PIX_FMT_GRAY16 PIX_FMT_GRAY16LE
+#endif
+
+#if LIBAVUTIL_VERSION_INT < (50<<16)
+#define PIX_FMT_UYVY411 PIX_FMT_UYYVYY411
+#define PIX_FMT_RGBA32  PIX_FMT_RGB32
+#define PIX_FMT_YUV422  PIX_FMT_YUYV422
+#endif
+
+#endif /* AVUTIL_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/base64.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/base64.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/base64.h	(revision 18425)
@@ -0,0 +1,40 @@
+/*
+ * Base64.c
+ * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_BASE64_H
+#define AVUTIL_BASE64_H
+
+#include <stdint.h>
+
+/**
+ * decodes base64
+ * param order as strncpy()
+ */
+int av_base64_decode(uint8_t * out, const char *in, int out_length);
+
+/**
+ * encodes base64
+ * @param src data, not a string
+ * @param buf output string
+ */
+char *av_base64_encode(char * buf, int buf_len, uint8_t * src, int len);
+
+#endif // AVUTIL_BASE64_H
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/common.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/common.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/common.h	(revision 18425)
@@ -0,0 +1,347 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file common.h
+ * common internal and external api header.
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <inttypes.h>
+
+#ifdef HAVE_AV_CONFIG_H
+/* only include the following when compiling package */
+#    include "config.h"
+
+#    include <stdlib.h>
+#    include <stdio.h>
+#    include <string.h>
+#    include <ctype.h>
+#    include <limits.h>
+#    include <errno.h>
+#    include <math.h>
+#endif /* HAVE_AV_CONFIG_H */
+
+#ifndef av_always_inline
+#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
+#    define av_always_inline __attribute__((always_inline)) inline
+#    define av_noinline __attribute__((noinline))
+#else
+#    define av_always_inline inline
+#    define av_noinline
+#endif
+#endif
+
+#ifdef HAVE_AV_CONFIG_H
+#    include "internal.h"
+#endif /* HAVE_AV_CONFIG_H */
+
+#ifndef attribute_deprecated
+#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
+#    define attribute_deprecated __attribute__((deprecated))
+#else
+#    define attribute_deprecated
+#endif
+#endif
+
+#ifndef av_unused
+#if defined(__GNUC__)
+#    define av_unused __attribute__((unused))
+#else
+#    define av_unused
+#endif
+#endif
+
+#include "mem.h"
+
+//rounded divison & shift
+#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b))
+/* assume b>0 */
+#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))
+#define FFABS(a) ((a) >= 0 ? (a) : (-(a)))
+#define FFSIGN(a) ((a) > 0 ? 1 : -1)
+
+#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
+#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
+
+#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
+
+/* misc math functions */
+extern const uint8_t ff_log2_tab[256];
+
+static inline int av_log2(unsigned int v)
+{
+    int n;
+
+    n = 0;
+    if (v & 0xffff0000) {
+        v >>= 16;
+        n += 16;
+    }
+    if (v & 0xff00) {
+        v >>= 8;
+        n += 8;
+    }
+    n += ff_log2_tab[v];
+
+    return n;
+}
+
+static inline int av_log2_16bit(unsigned int v)
+{
+    int n;
+
+    n = 0;
+    if (v & 0xff00) {
+        v >>= 8;
+        n += 8;
+    }
+    n += ff_log2_tab[v];
+
+    return n;
+}
+
+/* median of 3 */
+static inline int mid_pred(int a, int b, int c)
+{
+#ifdef HAVE_CMOV
+    int i=b;
+    asm volatile(
+        "cmp    %2, %1 \n\t"
+        "cmovg  %1, %0 \n\t"
+        "cmovg  %2, %1 \n\t"
+        "cmp    %3, %1 \n\t"
+        "cmovl  %3, %1 \n\t"
+        "cmp    %1, %0 \n\t"
+        "cmovg  %1, %0 \n\t"
+        :"+&r"(i), "+&r"(a)
+        :"r"(b), "r"(c)
+    );
+    return i;
+#elif 0
+    int t= (a-b)&((a-b)>>31);
+    a-=t;
+    b+=t;
+    b-= (b-c)&((b-c)>>31);
+    b+= (a-b)&((a-b)>>31);
+
+    return b;
+#else
+    if(a>b){
+        if(c>b){
+            if(c>a) b=a;
+            else    b=c;
+        }
+    }else{
+        if(b>c){
+            if(c>a) b=c;
+            else    b=a;
+        }
+    }
+    return b;
+#endif
+}
+
+/**
+ * clip a signed integer value into the amin-amax range
+ * @param a value to clip
+ * @param amin minimum value of the clip range
+ * @param amax maximum value of the clip range
+ * @return clipped value
+ */
+static inline int av_clip(int a, int amin, int amax)
+{
+    if (a < amin)      return amin;
+    else if (a > amax) return amax;
+    else               return a;
+}
+
+/**
+ * clip a signed integer value into the 0-255 range
+ * @param a value to clip
+ * @return clipped value
+ */
+static inline uint8_t av_clip_uint8(int a)
+{
+    if (a&(~255)) return (-a)>>31;
+    else          return a;
+}
+
+/* math */
+int64_t ff_gcd(int64_t a, int64_t b);
+
+/**
+ * converts fourcc string to int
+ */
+static inline int ff_get_fourcc(const char *s){
+#ifdef HAVE_AV_CONFIG_H
+    assert( strlen(s)==4 );
+#endif
+
+    return (s[0]) + (s[1]<<8) + (s[2]<<16) + (s[3]<<24);
+}
+
+#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
+#define MKBETAG(a,b,c,d) (d | (c << 8) | (b << 16) | (a << 24))
+
+/*!
+ * \def GET_UTF8(val, GET_BYTE, ERROR)
+ * converts a UTF-8 character (up to 4 bytes long) to its 32-bit UCS-4 encoded form
+ * \param val is the output and should be of type uint32_t. It holds the converted
+ * UCS-4 character and should be a left value.
+ * \param GET_BYTE gets UTF-8 encoded bytes from any proper source. It can be
+ * a function or a statement whose return value or evaluated value is of type
+ * uint8_t. It will be executed up to 4 times for values in the valid UTF-8 range,
+ * and up to 7 times in the general case.
+ * \param ERROR action that should be taken when an invalid UTF-8 byte is returned
+ * from GET_BYTE. It should be a statement that jumps out of the macro,
+ * like exit(), goto, return, break, or continue.
+ */
+#define GET_UTF8(val, GET_BYTE, ERROR)\
+    val= GET_BYTE;\
+    {\
+        int ones= 7 - av_log2(val ^ 255);\
+        if(ones==1)\
+            ERROR\
+        val&= 127>>ones;\
+        while(--ones > 0){\
+            int tmp= GET_BYTE - 128;\
+            if(tmp>>6)\
+                ERROR\
+            val= (val<<6) + tmp;\
+        }\
+    }
+
+/*!
+ * \def PUT_UTF8(val, tmp, PUT_BYTE)
+ * converts a 32-bit unicode character to its UTF-8 encoded form (up to 4 bytes long).
+ * \param val is an input only argument and should be of type uint32_t. It holds
+ * a ucs4 encoded unicode character that is to be converted to UTF-8. If
+ * val is given as a function it's executed only once.
+ * \param tmp is a temporary variable and should be of type uint8_t. It
+ * represents an intermediate value during conversion that is to be
+ * outputted by PUT_BYTE.
+ * \param PUT_BYTE writes the converted UTF-8 bytes to any proper destination.
+ * It could be a function or a statement, and uses tmp as the input byte.
+ * For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be
+ * executed up to 4 times for values in the valid UTF-8 range and up to
+ * 7 times in the general case, depending on the length of the converted
+ * unicode character.
+ */
+#define PUT_UTF8(val, tmp, PUT_BYTE)\
+    {\
+        int bytes, shift;\
+        uint32_t in = val;\
+        if (in < 0x80) {\
+            tmp = in;\
+            PUT_BYTE\
+        } else {\
+            bytes = (av_log2(in) + 4) / 5;\
+            shift = (bytes - 1) * 6;\
+            tmp = (256 - (256 >> bytes)) | (in >> shift);\
+            PUT_BYTE\
+            while (shift >= 6) {\
+                shift -= 6;\
+                tmp = 0x80 | ((in >> shift) & 0x3f);\
+                PUT_BYTE\
+            }\
+        }\
+    }
+
+#if defined(ARCH_X86) || defined(ARCH_POWERPC) || defined(ARCH_BFIN)
+#if defined(ARCH_X86_64)
+static inline uint64_t read_time(void)
+{
+        uint64_t a, d;
+        asm volatile(   "rdtsc\n\t"
+                : "=a" (a), "=d" (d)
+        );
+        return (d << 32) | (a & 0xffffffff);
+}
+#elif defined(ARCH_X86_32)
+static inline long long read_time(void)
+{
+        long long l;
+        asm volatile(   "rdtsc\n\t"
+                : "=A" (l)
+        );
+        return l;
+}
+#elif ARCH_BFIN
+static inline uint64_t read_time(void)
+{
+    union {
+        struct {
+            unsigned lo;
+            unsigned hi;
+        } p;
+        unsigned long long c;
+    } t;
+    asm volatile ("%0=cycles; %1=cycles2;" : "=d" (t.p.lo), "=d" (t.p.hi));
+    return t.c;
+}
+#else //FIXME check ppc64
+static inline uint64_t read_time(void)
+{
+    uint32_t tbu, tbl, temp;
+
+     /* from section 2.2.1 of the 32-bit PowerPC PEM */
+     __asm__ __volatile__(
+         "1:\n"
+         "mftbu  %2\n"
+         "mftb   %0\n"
+         "mftbu  %1\n"
+         "cmpw   %2,%1\n"
+         "bne    1b\n"
+     : "=r"(tbl), "=r"(tbu), "=r"(temp)
+     :
+     : "cc");
+
+     return (((uint64_t)tbu)<<32) | (uint64_t)tbl;
+}
+#endif
+
+#define START_TIMER \
+uint64_t tend;\
+uint64_t tstart= read_time();\
+
+#define STOP_TIMER(id) \
+tend= read_time();\
+{\
+  static uint64_t tsum=0;\
+  static int tcount=0;\
+  static int tskip_count=0;\
+  if(tcount<2 || tend - tstart < FFMAX(8*tsum/tcount, 2000)){\
+      tsum+= tend - tstart;\
+      tcount++;\
+  }else\
+      tskip_count++;\
+  if(((tcount+tskip_count)&(tcount+tskip_count-1))==0){\
+      av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" dezicycles in %s, %d runs, %d skips\n", tsum*10/tcount, id, tcount, tskip_count);\
+  }\
+}
+#else
+#define START_TIMER
+#define STOP_TIMER(id) {}
+#endif
+
+#endif /* COMMON_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/fifo.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/fifo.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/fifo.h	(revision 18425)
@@ -0,0 +1,102 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file fifo.h
+ * A very simple circular buffer FIFO implementation.
+ */
+
+#ifndef FIFO_H
+#define FIFO_H
+
+#include <stdint.h>
+
+typedef struct AVFifoBuffer {
+    uint8_t *buffer;
+    uint8_t *rptr, *wptr, *end;
+} AVFifoBuffer;
+
+/**
+ * Initializes an AVFifoBuffer.
+ * @param *f AVFifoBuffer to initialize
+ * @param size of FIFO
+ * @return <0 for failure >=0 otherwise
+ */
+int av_fifo_init(AVFifoBuffer *f, int size);
+
+/**
+ * Frees an AVFifoBuffer.
+ * @param *f AVFifoBuffer to free
+ */
+void av_fifo_free(AVFifoBuffer *f);
+
+/**
+ * Returns the amount of data in bytes in the AVFifoBuffer, that is the
+ * amount of data you can read from it.
+ * @param *f AVFifoBuffer to read from
+ * @return size
+ */
+int av_fifo_size(AVFifoBuffer *f);
+
+/**
+ * Reads data from an AVFifoBuffer.
+ * @param *f AVFifoBuffer to read from
+ * @param *buf data destination
+ * @param buf_size number of bytes to read
+ */
+int av_fifo_read(AVFifoBuffer *f, uint8_t *buf, int buf_size);
+
+/**
+ * Feeds data from an AVFifoBuffer to a user supplied callback.
+ * @param *f AVFifoBuffer to read from
+ * @param buf_size number of bytes to read
+ * @param *func generic read function
+ * @param *dest data destination
+ */
+int av_fifo_generic_read(AVFifoBuffer *f, int buf_size, void (*func)(void*, void*, int), void* dest);
+
+/**
+ * Writes data into an AVFifoBuffer.
+ * @param *f AVFifoBuffer to write to
+ * @param *buf data source
+ * @param size data size
+ */
+void av_fifo_write(AVFifoBuffer *f, const uint8_t *buf, int size);
+
+/**
+ * Resizes an AVFifoBuffer.
+ * @param *f AVFifoBuffer to resize
+ * @param size new AVFifoBuffer size in bytes
+ */
+void av_fifo_realloc(AVFifoBuffer *f, unsigned int size);
+
+/**
+ * Reads and discards the specified amount of data from an AVFifoBuffer.
+ * @param *f AVFifoBuffer to read from
+ * @param size amount of data to read in bytes
+ */
+void av_fifo_drain(AVFifoBuffer *f, int size);
+
+static inline uint8_t av_fifo_peek(AVFifoBuffer *f, int offs)
+{
+    uint8_t *ptr = f->rptr + offs;
+    if (ptr >= f->end)
+        ptr -= f->end - f->buffer;
+    return *ptr;
+}
+#endif /* FIFO_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/integer.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/integer.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/integer.h	(revision 18425)
@@ -0,0 +1,83 @@
+/*
+ * arbitrary precision integers
+ * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file integer.h
+ * arbitrary precision integers
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#ifndef INTEGER_H
+#define INTEGER_H
+
+#include <stdint.h>
+
+#define AV_INTEGER_SIZE 8
+
+typedef struct AVInteger{
+    uint16_t v[AV_INTEGER_SIZE];
+} AVInteger;
+
+AVInteger av_add_i(AVInteger a, AVInteger b);
+AVInteger av_sub_i(AVInteger a, AVInteger b);
+
+/**
+ * returns the rounded down value of the logarithm of base 2 of the given AVInteger.
+ * this is simply the index of the most significant bit which is 1. Or 0 of all bits are 0
+ */
+int av_log2_i(AVInteger a);
+AVInteger av_mul_i(AVInteger a, AVInteger b);
+
+/**
+ * returns 0 if a==b, 1 if a>b and -1 if a<b.
+ */
+int av_cmp_i(AVInteger a, AVInteger b);
+
+/**
+ * bitwise shift.
+ * @param s the number of bits by which the value should be shifted right, may be negative for shifting left
+ */
+AVInteger av_shr_i(AVInteger a, int s);
+
+/**
+ * returns a % b.
+ * @param quot a/b will be stored here
+ */
+AVInteger av_mod_i(AVInteger *quot, AVInteger a, AVInteger b);
+
+/**
+ * returns a/b.
+ */
+AVInteger av_div_i(AVInteger a, AVInteger b);
+
+/**
+ * converts the given int64_t to an AVInteger.
+ */
+AVInteger av_int2i(int64_t a);
+
+/**
+ * converts the given AVInteger to an int64_t.
+ * if the AVInteger is too large to fit into an int64_t,
+ * then only the least significant 64bit will be used
+ */
+int64_t av_i2int(AVInteger a);
+
+#endif // INTEGER_H
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/intfloat_readwrite.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/intfloat_readwrite.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/intfloat_readwrite.h	(revision 18425)
@@ -0,0 +1,39 @@
+/*
+ * copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef INTFLOAT_READWRITE_H
+#define INTFLOAT_READWRITE_H
+
+#include "common.h"
+
+/* IEEE 80 bits extended float */
+typedef struct AVExtFloat  {
+    uint8_t exponent[2];
+    uint8_t mantissa[8];
+} AVExtFloat;
+
+double av_int2dbl(int64_t v);
+float av_int2flt(int32_t v);
+double av_ext2dbl(const AVExtFloat ext);
+int64_t av_dbl2int(double d);
+int32_t av_flt2int(float d);
+AVExtFloat av_dbl2ext(double d);
+
+#endif /* INTFLOAT_READWRITE_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/log.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/log.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/log.h	(revision 18425)
@@ -0,0 +1,116 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LOG_H
+#define LOG_H
+
+#include <stdarg.h>
+
+/**
+ * Used by av_log
+ */
+typedef struct AVCLASS AVClass;
+struct AVCLASS {
+    const char* class_name;
+    const char* (*item_name)(void*); /* actually passing a pointer to an AVCodecContext
+                                        or AVFormatContext, which begin with an AVClass.
+                                        Needed because av_log is in libavcodec and has no visibility
+                                        of AVIn/OutputFormat */
+    const struct AVOption *option;
+};
+
+/* av_log API */
+
+#if LIBAVUTIL_VERSION_INT < (50<<16)
+#define AV_LOG_QUIET -1
+#define AV_LOG_FATAL 0
+#define AV_LOG_ERROR 0
+#define AV_LOG_WARNING 1
+#define AV_LOG_INFO 1
+#define AV_LOG_VERBOSE 1
+#define AV_LOG_DEBUG 2
+#else
+#define AV_LOG_QUIET    -8
+
+/**
+ * something went really wrong and we will crash now
+ */
+#define AV_LOG_PANIC     0
+
+/**
+ * something went wrong and recovery is not possible
+ * like no header in a format which depends on it or a combination
+ * of parameters which are not allowed
+ */
+#define AV_LOG_FATAL     8
+
+/**
+ * something went wrong and cannot losslessly be recovered
+ * but not all future data is affected
+ */
+#define AV_LOG_ERROR    16
+
+/**
+ * something somehow does not look correct / something which may or may not
+ * lead to some problems like use of -vstrict -2
+ */
+#define AV_LOG_WARNING  24
+
+#define AV_LOG_INFO     32
+#define AV_LOG_VERBOSE  40
+
+/**
+ * stuff which is only useful for libav* developers
+ */
+#define AV_LOG_DEBUG    48
+#endif
+extern int av_log_level;
+
+/**
+ * Send the specified message to the log if the level is less than or equal to
+ * the current av_log_level. By default, all logging messages are sent to
+ * stderr. This behavior can be altered by setting a different av_vlog callback
+ * function.
+ *
+ * @param avcl A pointer to an arbitrary struct of which the first field is a
+ * pointer to an AVClass struct.
+ * @param level The importance level of the message, lower values signifying
+ * higher importance.
+ * @param fmt The format string (printf-compatible) that specifies how
+ * subsequent arguments are converted to output.
+ * @see av_vlog
+ */
+#ifdef __GNUC__
+extern void av_log(void*, int level, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 3, 4)));
+#else
+extern void av_log(void*, int level, const char *fmt, ...);
+#endif
+
+#if LIBAVUTIL_VERSION_INT < (50<<16)
+extern void av_vlog(void*, int level, const char *fmt, va_list);
+extern int av_log_get_level(void);
+extern void av_log_set_level(int);
+extern void av_log_set_callback(void (*)(void*, int, const char*, va_list));
+extern void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl);
+#else
+extern void (*av_vlog)(void*, int, const char*, va_list);
+#endif
+
+#endif /* LOG_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/lzo.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/lzo.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/lzo.h	(revision 18425)
@@ -0,0 +1,35 @@
+/*
+ * LZO 1x decompression
+ * copyright (c) 2006 Reimar Doeffinger
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LZO_H
+#define LZO_H
+
+#define LZO_INPUT_DEPLETED 1
+#define LZO_OUTPUT_FULL 2
+#define LZO_INVALID_BACKPTR 4
+#define LZO_ERROR 8
+
+#define LZO_INPUT_PADDING 8
+#define LZO_OUTPUT_PADDING 12
+
+int lzo1x_decode(void *out, int *outlen, void *in, int *inlen);
+
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/mathematics.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/mathematics.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/mathematics.h	(revision 18425)
@@ -0,0 +1,51 @@
+/*
+ * copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef MATHEMATICS_H
+#define MATHEMATICS_H
+
+#include "rational.h"
+
+enum AVRounding {
+    AV_ROUND_ZERO     = 0, ///< round toward zero
+    AV_ROUND_INF      = 1, ///< round away from zero
+    AV_ROUND_DOWN     = 2, ///< round toward -infinity
+    AV_ROUND_UP       = 3, ///< round toward +infinity
+    AV_ROUND_NEAR_INF = 5, ///< round to nearest and halfway cases away from zero
+};
+
+/**
+ * rescale a 64bit integer with rounding to nearest.
+ * a simple a*b/c isn't possible as it can overflow
+ */
+int64_t av_rescale(int64_t a, int64_t b, int64_t c);
+
+/**
+ * rescale a 64bit integer with specified rounding.
+ * a simple a*b/c isn't possible as it can overflow
+ */
+int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding);
+
+/**
+ * rescale a 64bit integer by 2 rational numbers.
+ */
+int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq);
+
+#endif /* MATHEMATICS_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/md5.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/md5.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/md5.h	(revision 18425)
@@ -0,0 +1,36 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef MD5_H
+#define MD5_H
+
+#include <stdint.h>
+
+extern const int av_md5_size;
+
+struct AVMD5;
+
+void av_md5_init(struct AVMD5 *ctx);
+void av_md5_update(struct AVMD5 *ctx, const uint8_t *src, const int len);
+void av_md5_final(struct AVMD5 *ctx, uint8_t *dst);
+void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len);
+
+#endif /* MD5_H */
+
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/mem.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/mem.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/mem.h	(revision 18425)
@@ -0,0 +1,65 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file mem.h
+ * Memory handling functions.
+ */
+
+#ifndef AV_MEM_H
+#define AV_MEM_H
+
+#ifdef __GNUC__
+  #define DECLARE_ALIGNED(n,t,v)       t v __attribute__ ((aligned (n)))
+#else
+  #define DECLARE_ALIGNED(n,t,v)      __declspec(align(n)) t v
+#endif
+
+/**
+ * Memory allocation of size byte with alignment suitable for all
+ * memory accesses (including vectors if available on the
+ * CPU). av_malloc(0) must return a non NULL pointer.
+ */
+void *av_malloc(unsigned int size);
+
+/**
+ * av_realloc semantics (same as glibc): if ptr is NULL and size > 0,
+ * identical to malloc(size). If size is zero, it is identical to
+ * free(ptr) and NULL is returned.
+ */
+void *av_realloc(void *ptr, unsigned int size);
+
+/**
+ * Free memory which has been allocated with av_malloc(z)() or av_realloc().
+ * NOTE: ptr = NULL is explicetly allowed
+ * Note2: it is recommended that you use av_freep() instead
+ */
+void av_free(void *ptr);
+
+void *av_mallocz(unsigned int size);
+char *av_strdup(const char *s);
+
+/**
+ * Frees memory and sets the pointer to NULL.
+ * @param ptr pointer to the pointer which should be freed
+ */
+void av_freep(void *ptr);
+
+#endif /* AV_MEM_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/opt.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/opt.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/opt.h	(revision 18425)
@@ -0,0 +1,87 @@
+/*
+ * AVOptions
+ * copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVOPT_H
+#define AVOPT_H
+
+/**
+ * @file opt.h
+ * AVOptions
+ */
+
+#include "rational.h"
+
+enum AVOptionType{
+    FF_OPT_TYPE_FLAGS,
+    FF_OPT_TYPE_INT,
+    FF_OPT_TYPE_INT64,
+    FF_OPT_TYPE_DOUBLE,
+    FF_OPT_TYPE_FLOAT,
+    FF_OPT_TYPE_STRING,
+    FF_OPT_TYPE_RATIONAL,
+    FF_OPT_TYPE_CONST=128,
+};
+
+/**
+ * AVOption.
+ */
+typedef struct AVOption {
+    const char *name;
+
+    /**
+     * short English text help.
+     * @todo what about other languages
+     */
+    const char *help;
+    int offset;             ///< offset to context structure where the parsed value should be stored
+    enum AVOptionType type;
+
+    double default_val;
+    double min;
+    double max;
+
+    int flags;
+#define AV_OPT_FLAG_ENCODING_PARAM  1   ///< a generic parameter which can be set by the user for muxing or encoding
+#define AV_OPT_FLAG_DECODING_PARAM  2   ///< a generic parameter which can be set by the user for demuxing or decoding
+#define AV_OPT_FLAG_METADATA        4   ///< some data extracted or inserted into the file like title, comment, ...
+#define AV_OPT_FLAG_AUDIO_PARAM     8
+#define AV_OPT_FLAG_VIDEO_PARAM     16
+#define AV_OPT_FLAG_SUBTITLE_PARAM  32
+//FIXME think about enc-audio, ... style flags
+    const char *unit;
+} AVOption;
+
+
+const AVOption *av_find_opt(void *obj, const char *name, const char *unit, int mask, int flags);
+const AVOption *av_set_string(void *obj, const char *name, const char *val);
+const AVOption *av_set_double(void *obj, const char *name, double n);
+const AVOption *av_set_q(void *obj, const char *name, AVRational n);
+const AVOption *av_set_int(void *obj, const char *name, int64_t n);
+double av_get_double(void *obj, const char *name, const AVOption **o_out);
+AVRational av_get_q(void *obj, const char *name, const AVOption **o_out);
+int64_t av_get_int(void *obj, const char *name, const AVOption **o_out);
+const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len);
+const AVOption *av_next_option(void *obj, const AVOption *last);
+int av_opt_show(void *obj, void *av_log_obj);
+void av_opt_set_defaults(void *s);
+void av_opt_set_defaults2(void *s, int mask, int flags);
+
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/random.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/random.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/random.h	(revision 18425)
@@ -0,0 +1,69 @@
+/*
+ * Mersenne Twister Random Algorithm
+ * Copyright (c) 2006 Ryan Martell.
+ * Based on A C-program for MT19937, with initialization improved 2002/1/26. Coded by
+ * Takuji Nishimura and Makoto Matsumoto.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AV_RANDOM_H
+#define AV_RANDOM_H
+
+#define AV_RANDOM_N 624
+
+typedef struct {
+    unsigned int mt[AV_RANDOM_N]; ///< the array for the state vector
+    int index; ///< current untempered value we use as the base.
+} AVRandomState;
+
+
+void av_init_random(unsigned int seed, AVRandomState *state); ///< to be inlined, the struct must be visible, so it doesn't make sense to try and keep it opaque with malloc/free like calls
+void av_random_generate_untempered_numbers(AVRandomState *state); ///< Regenerate the untempered numbers (must be done every 624 iterations, or it will loop)
+
+/** generates a random number on [0,0xffffffff]-interval */
+static inline unsigned int av_random(AVRandomState *state)
+{
+    unsigned int y;
+
+    // regenerate the untempered numbers if we should...
+    if (state->index >= AV_RANDOM_N)
+        av_random_generate_untempered_numbers(state);
+
+    // grab one...
+    y = state->mt[state->index++];
+
+    /* Now temper (Mersenne Twister coefficients) The coefficients for MT19937 are.. */
+    y ^= (y >> 11);
+    y ^= (y << 7) & 0x9d2c5680;
+    y ^= (y << 15) & 0xefc60000;
+    y ^= (y >> 18);
+
+    return y;
+}
+
+/** return random in range [0-1] as double */
+static inline double av_random_real1(AVRandomState *state)
+{
+    /* divided by 2^32-1 */
+    return av_random(state) * (1.0 / 4294967296.0);
+}
+
+// only available if DEBUG is defined in the .c file
+void av_benchmark_random(void);
+#endif // AV_RANDOM_H
+
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rational.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rational.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rational.h	(revision 18425)
@@ -0,0 +1,115 @@
+/*
+ * Rational numbers
+ * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file rational.h
+ * Rational numbers.
+ * @author Michael Niedermayer <michaelni@gmx.at>
+ */
+
+#ifndef RATIONAL_H
+#define RATIONAL_H
+
+#include <stdint.h>
+
+/**
+ * Rational number num/den.
+ */
+typedef struct AVRational{
+    int num; ///< numerator
+    int den; ///< denominator
+} AVRational;
+
+/**
+ * Compare two rationals.
+ * @param a first rational
+ * @param b second rational
+ * @return 0 if a==b, 1 if a>b and -1 if a<b.
+ */
+static inline int av_cmp_q(AVRational a, AVRational b){
+    const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den;
+
+    if(tmp) return (tmp>>63)|1;
+    else    return 0;
+}
+
+/**
+ * Rational to double conversion.
+ * @param a rational to convert
+ * @return (double) a
+ */
+static inline double av_q2d(AVRational a){
+    return a.num / (double) a.den;
+}
+
+/**
+ * Reduce a fraction.
+ * This is useful for framerate calculations.
+ * @param dst_nom destination numerator
+ * @param dst_den destination denominator
+ * @param nom source numerator
+ * @param den source denominator
+ * @param max the maximum allowed for dst_nom & dst_den
+ * @return 1 if exact, 0 otherwise
+ */
+int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max);
+
+/**
+ * Multiplies two rationals.
+ * @param b first rational.
+ * @param c second rational.
+ * @return b*c.
+ */
+AVRational av_mul_q(AVRational b, AVRational c);
+
+/**
+ * Divides one rational by another.
+ * @param b first rational.
+ * @param c second rational.
+ * @return b/c.
+ */
+AVRational av_div_q(AVRational b, AVRational c);
+
+/**
+ * Adds two rationals.
+ * @param b first rational.
+ * @param c second rational.
+ * @return b+c.
+ */
+AVRational av_add_q(AVRational b, AVRational c);
+
+/**
+ * Subtracts one rational from another.
+ * @param b first rational.
+ * @param c second rational.
+ * @return b-c.
+ */
+AVRational av_sub_q(AVRational b, AVRational c);
+
+/**
+ * Converts a double precision floating point number to a rational.
+ * @param d double to convert
+ * @param max the maximum allowed numerator and denominator
+ * @return (AVRational) d.
+ */
+AVRational av_d2q(double d, int max);
+
+#endif // RATIONAL_H
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rgb2rgb.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rgb2rgb.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rgb2rgb.h	(revision 18425)
@@ -0,0 +1,146 @@
+/*
+ *  rgb2rgb.h, Software RGB to RGB convertor
+ *  pluralize by Software PAL8 to RGB convertor
+ *               Software YUV to YUV convertor
+ *               Software YUV to RGB convertor
+ *  Written by Nick Kurshev.
+ *  palette & YUV & runtime CPU stuff by Michael (michaelni@gmx.at)
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RGB2RGB_INCLUDED
+#define RGB2RGB_INCLUDED
+
+#include <inttypes.h>
+
+/* A full collection of rgb to rgb(bgr) convertors */
+extern void (*rgb24to32)   (const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb24to16)   (const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb24to15)   (const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb32to24)   (const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb32to16)   (const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb32to15)   (const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb15to16)   (const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb15to24)   (const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb15to32)   (const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb16to15)   (const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb16to24)   (const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb16to32)   (const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb24tobgr24)(const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb24tobgr16)(const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb24tobgr15)(const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb32tobgr32)(const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb32tobgr16)(const uint8_t *src, uint8_t *dst, long src_size);
+extern void (*rgb32tobgr15)(const uint8_t *src, uint8_t *dst, long src_size);
+
+extern void rgb24tobgr32(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb32tobgr24(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb16tobgr32(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb16tobgr24(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb16tobgr16(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb16tobgr15(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb15tobgr32(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb15tobgr24(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb15tobgr16(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb15tobgr15(const uint8_t *src, uint8_t *dst, long src_size);
+extern void rgb8tobgr8  (const uint8_t *src, uint8_t *dst, long src_size);
+
+
+extern void palette8torgb32(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8tobgr32(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8torgb24(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8tobgr24(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8torgb16(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8tobgr16(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8torgb15(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+extern void palette8tobgr15(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette);
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ * chrominance data is only taken from every secound line others are ignored FIXME write HQ version
+ */
+//void uyvytoyv12(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ */
+extern void (*yv12toyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+                          long width, long height,
+                          long lumStride, long chromStride, long dstStride);
+
+/**
+ *
+ * width should be a multiple of 16
+ */
+extern void (*yuv422ptoyuy2)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+                             long width, long height,
+                             long lumStride, long chromStride, long dstStride);
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ */
+extern void (*yuy2toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
+                          long width, long height,
+                          long lumStride, long chromStride, long srcStride);
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ */
+extern void (*yv12touyvy)(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+                          long width, long height,
+                          long lumStride, long chromStride, long dstStride);
+
+/**
+ *
+ * height should be a multiple of 2 and width should be a multiple of 2 (if this is a
+ * problem for anyone then tell me, and ill fix it)
+ * chrominance data is only taken from every secound line others are ignored FIXME write HQ version
+ */
+extern void (*rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
+                           long width, long height,
+                           long lumStride, long chromStride, long srcStride);
+extern void (*planar2x)(const uint8_t *src, uint8_t *dst, long width, long height,
+                        long srcStride, long dstStride);
+
+extern void (*interleaveBytes)(uint8_t *src1, uint8_t *src2, uint8_t *dst,
+                               long width, long height, long src1Stride,
+                               long src2Stride, long dstStride);
+
+extern void (*vu9_to_vu12)(const uint8_t *src1, const uint8_t *src2,
+                           uint8_t *dst1, uint8_t *dst2,
+                           long width, long height,
+                           long srcStride1, long srcStride2,
+                           long dstStride1, long dstStride2);
+
+extern void (*yvu9_to_yuy2)(const uint8_t *src1, const uint8_t *src2, const uint8_t *src3,
+                            uint8_t *dst,
+                            long width, long height,
+                            long srcStride1, long srcStride2,
+                            long srcStride3, long dstStride);
+
+void sws_rgb2rgb_init(int flags);
+
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rtp.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rtp.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rtp.h	(revision 18425)
@@ -0,0 +1,130 @@
+/*
+ * RTP definitions
+ * Copyright (c) 2002 Fabrice Bellard.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef RTP_H
+#define RTP_H
+
+#include "avcodec.h"
+#include "avformat.h"
+
+#define RTP_MIN_PACKET_LENGTH 12
+#define RTP_MAX_PACKET_LENGTH 1500 /* XXX: suppress this define */
+
+int rtp_init(void);
+int rtp_get_codec_info(AVCodecContext *codec, int payload_type);
+
+/** return < 0 if unknown payload type */
+int rtp_get_payload_type(AVCodecContext *codec);
+
+typedef struct RTPDemuxContext RTPDemuxContext;
+typedef struct rtp_payload_data_s rtp_payload_data_s;
+RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, rtp_payload_data_s *rtp_payload_data);
+int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
+                     const uint8_t *buf, int len);
+void rtp_parse_close(RTPDemuxContext *s);
+
+extern AVOutputFormat rtp_muxer;
+extern AVInputFormat rtp_demuxer;
+
+int rtp_get_local_port(URLContext *h);
+int rtp_set_remote_url(URLContext *h, const char *uri);
+void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd);
+
+/**
+ * some rtp servers assume client is dead if they don't hear from them...
+ * so we send a Receiver Report to the provided ByteIO context
+ * (we don't have access to the rtcp handle from here)
+ */
+int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count);
+
+extern URLProtocol rtp_protocol;
+
+#define RTP_PT_PRIVATE 96
+#define RTP_VERSION 2
+#define RTP_MAX_SDES 256   /**< maximum text length for SDES */
+
+/* RTCP paquets use 0.5 % of the bandwidth */
+#define RTCP_TX_RATIO_NUM 5
+#define RTCP_TX_RATIO_DEN 1000
+
+/** Structure listing useful vars to parse RTP packet payload*/
+typedef struct rtp_payload_data_s
+{
+    int sizelength;
+    int indexlength;
+    int indexdeltalength;
+    int profile_level_id;
+    int streamtype;
+    int objecttype;
+    char *mode;
+
+    /** mpeg 4 AU headers */
+    struct AUHeaders {
+        int size;
+        int index;
+        int cts_flag;
+        int cts;
+        int dts_flag;
+        int dts;
+        int rap_flag;
+        int streamstate;
+    } *au_headers;
+    int nb_au_headers;
+    int au_headers_length_bytes;
+    int cur_au_index;
+} rtp_payload_data_t;
+
+typedef struct AVRtpPayloadType_s
+{
+    int pt;
+    const char enc_name[50]; /* XXX: why 50 ? */
+    enum CodecType codec_type;
+    enum CodecID codec_id;
+    int clock_rate;
+    int audio_channels;
+} AVRtpPayloadType_t;
+
+#if 0
+typedef enum {
+  RTCP_SR   = 200,
+  RTCP_RR   = 201,
+  RTCP_SDES = 202,
+  RTCP_BYE  = 203,
+  RTCP_APP  = 204
+} rtcp_type_t;
+
+typedef enum {
+  RTCP_SDES_END    =  0,
+  RTCP_SDES_CNAME  =  1,
+  RTCP_SDES_NAME   =  2,
+  RTCP_SDES_EMAIL  =  3,
+  RTCP_SDES_PHONE  =  4,
+  RTCP_SDES_LOC    =  5,
+  RTCP_SDES_TOOL   =  6,
+  RTCP_SDES_NOTE   =  7,
+  RTCP_SDES_PRIV   =  8,
+  RTCP_SDES_IMG    =  9,
+  RTCP_SDES_DOOR   = 10,
+  RTCP_SDES_SOURCE = 11
+} rtcp_sdes_type_t;
+#endif
+
+extern AVRtpPayloadType_t AVRtpPayloadTypes[];
+#endif /* RTP_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rtsp.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rtsp.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rtsp.h	(revision 18425)
@@ -0,0 +1,92 @@
+/*
+ * RTSP definitions
+ * Copyright (c) 2002 Fabrice Bellard.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef RTSP_H
+#define RTSP_H
+
+#include <stdint.h>
+#include "avformat.h"
+#include "rtspcodes.h"
+
+enum RTSPProtocol {
+    RTSP_PROTOCOL_RTP_UDP = 0,
+    RTSP_PROTOCOL_RTP_TCP = 1,
+    RTSP_PROTOCOL_RTP_UDP_MULTICAST = 2,
+};
+
+#define RTSP_DEFAULT_PORT   554
+#define RTSP_MAX_TRANSPORTS 8
+#define RTSP_TCP_MAX_PACKET_SIZE 1472
+#define RTSP_DEFAULT_NB_AUDIO_CHANNELS 2
+#define RTSP_DEFAULT_AUDIO_SAMPLERATE 44100
+#define RTSP_RTP_PORT_MIN 5000
+#define RTSP_RTP_PORT_MAX 10000
+
+typedef struct RTSPTransportField {
+    int interleaved_min, interleaved_max;  /**< interleave ids, if TCP transport */
+    int port_min, port_max; /**< RTP ports */
+    int client_port_min, client_port_max; /**< RTP ports */
+    int server_port_min, server_port_max; /**< RTP ports */
+    int ttl; /**< ttl value */
+    uint32_t destination; /**< destination IP address */
+    enum RTSPProtocol protocol;
+} RTSPTransportField;
+
+typedef struct RTSPHeader {
+    int content_length;
+    enum RTSPStatusCode status_code; /**< response code from server */
+    int nb_transports;
+    /** in AV_TIME_BASE unit, AV_NOPTS_VALUE if not used */
+    int64_t range_start, range_end;
+    RTSPTransportField transports[RTSP_MAX_TRANSPORTS];
+    int seq; /**< sequence number */
+    char session_id[512];
+} RTSPHeader;
+
+/** the callback can be used to extend the connection setup/teardown step */
+enum RTSPCallbackAction {
+    RTSP_ACTION_SERVER_SETUP,
+    RTSP_ACTION_SERVER_TEARDOWN,
+    RTSP_ACTION_CLIENT_SETUP,
+    RTSP_ACTION_CLIENT_TEARDOWN,
+};
+
+typedef struct RTSPActionServerSetup {
+    uint32_t ipaddr;
+    char transport_option[512];
+} RTSPActionServerSetup;
+
+typedef int FFRTSPCallback(enum RTSPCallbackAction action,
+                           const char *session_id,
+                           char *buf, int buf_size,
+                           void *arg);
+
+int rtsp_init(void);
+void rtsp_parse_line(RTSPHeader *reply, const char *buf);
+
+extern int rtsp_default_protocols;
+extern int rtsp_rtp_port_min;
+extern int rtsp_rtp_port_max;
+extern AVInputFormat rtsp_demuxer;
+
+int rtsp_pause(AVFormatContext *s);
+int rtsp_resume(AVFormatContext *s);
+
+#endif /* RTSP_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rtspcodes.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rtspcodes.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/rtspcodes.h	(revision 18425)
@@ -0,0 +1,40 @@
+/*
+ * RTSP definitions
+ * copyright (c) 2002 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFORMAT_RTSPCODES_H
+#define AVFORMAT_RTSPCODES_H
+
+/** RTSP handling */
+enum RTSPStatusCode {
+RTSP_STATUS_OK              =200, /**< OK */
+RTSP_STATUS_METHOD          =405, /**< Method Not Allowed */
+RTSP_STATUS_BANDWIDTH       =453, /**< Not Enough Bandwidth */
+RTSP_STATUS_SESSION         =454, /**< Session Not Found */
+RTSP_STATUS_STATE           =455, /**< Method Not Valid in This State */
+RTSP_STATUS_AGGREGATE       =459, /**< Aggregate operation not allowed */
+RTSP_STATUS_ONLY_AGGREGATE  =460, /**< Only aggregate operation allowed */
+RTSP_STATUS_TRANSPORT       =461, /**< Unsupported transport */
+RTSP_STATUS_INTERNAL        =500, /**< Internal Server Error */
+RTSP_STATUS_SERVICE         =503, /**< Service Unavailable */
+RTSP_STATUS_VERSION         =505, /**< RTSP Version not supported */
+};
+
+#endif // AVFORMAT_RTSPCODES_H
Index: extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/swscale.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/swscale.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/ffmpeg/swscale.h	(revision 18425)
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SWSCALE_H
+#define SWSCALE_H
+
+/**
+ * @file swscale.h
+ * @brief
+ *     external api for the swscale stuff
+ */
+
+#include "avutil.h"
+
+#define AV_STRINGIFY(s)         AV_TOSTRING(s)
+#define AV_TOSTRING(s) #s
+
+#define LIBSWSCALE_VERSION_INT  ((0<<16)+(5<<8)+0)
+#define LIBSWSCALE_VERSION      0.5.0
+#define LIBSWSCALE_BUILD        LIBSWSCALE_VERSION_INT
+
+#define LIBSWSCALE_IDENT        "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION)
+
+/* values for the flags, the stuff on the command line is different */
+#define SWS_FAST_BILINEAR     1
+#define SWS_BILINEAR          2
+#define SWS_BICUBIC           4
+#define SWS_X                 8
+#define SWS_POINT          0x10
+#define SWS_AREA           0x20
+#define SWS_BICUBLIN       0x40
+#define SWS_GAUSS          0x80
+#define SWS_SINC          0x100
+#define SWS_LANCZOS       0x200
+#define SWS_SPLINE        0x400
+
+#define SWS_SRC_V_CHR_DROP_MASK     0x30000
+#define SWS_SRC_V_CHR_DROP_SHIFT    16
+
+#define SWS_PARAM_DEFAULT           123456
+
+#define SWS_PRINT_INFO              0x1000
+
+//the following 3 flags are not completely implemented
+//internal chrominace subsampling info
+#define SWS_FULL_CHR_H_INT    0x2000
+//input subsampling info
+#define SWS_FULL_CHR_H_INP    0x4000
+#define SWS_DIRECT_BGR        0x8000
+#define SWS_ACCURATE_RND      0x40000
+
+#define SWS_CPU_CAPS_MMX      0x80000000
+#define SWS_CPU_CAPS_MMX2     0x20000000
+#define SWS_CPU_CAPS_3DNOW    0x40000000
+#define SWS_CPU_CAPS_ALTIVEC  0x10000000
+#define SWS_CPU_CAPS_BFIN     0x01000000
+
+#define SWS_MAX_REDUCE_CUTOFF 0.002
+
+#define SWS_CS_ITU709         1
+#define SWS_CS_FCC            4
+#define SWS_CS_ITU601         5
+#define SWS_CS_ITU624         5
+#define SWS_CS_SMPTE170M      5
+#define SWS_CS_SMPTE240M      7
+#define SWS_CS_DEFAULT        5
+
+
+
+// when used for filters they must have an odd number of elements
+// coeffs cannot be shared between vectors
+typedef struct {
+    double *coeff;
+    int length;
+} SwsVector;
+
+// vectors can be shared
+typedef struct {
+    SwsVector *lumH;
+    SwsVector *lumV;
+    SwsVector *chrH;
+    SwsVector *chrV;
+} SwsFilter;
+
+struct SwsContext;
+
+void sws_freeContext(struct SwsContext *swsContext);
+
+struct SwsContext *sws_getContext(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat, int flags,
+                                  SwsFilter *srcFilter, SwsFilter *dstFilter, double *param);
+int sws_scale(struct SwsContext *context, uint8_t* src[], int srcStride[], int srcSliceY,
+              int srcSliceH, uint8_t* dst[], int dstStride[]);
+int sws_scale_ordered(struct SwsContext *context, uint8_t* src[], int srcStride[], int srcSliceY,
+                      int srcSliceH, uint8_t* dst[], int dstStride[]) attribute_deprecated;
+
+
+int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], int srcRange, const int table[4], int dstRange, int brightness, int contrast, int saturation);
+int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table, int *srcRange, int **table, int *dstRange, int *brightness, int *contrast, int *saturation);
+SwsVector *sws_getGaussianVec(double variance, double quality);
+SwsVector *sws_getConstVec(double c, int length);
+SwsVector *sws_getIdentityVec(void);
+void sws_scaleVec(SwsVector *a, double scalar);
+void sws_normalizeVec(SwsVector *a, double height);
+void sws_convVec(SwsVector *a, SwsVector *b);
+void sws_addVec(SwsVector *a, SwsVector *b);
+void sws_subVec(SwsVector *a, SwsVector *b);
+void sws_shiftVec(SwsVector *a, int shift);
+SwsVector *sws_cloneVec(SwsVector *a);
+
+void sws_printVec(SwsVector *a);
+void sws_freeVec(SwsVector *a);
+
+SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
+                                float lumaSarpen, float chromaSharpen,
+                                float chromaHShift, float chromaVShift,
+                                int verbose);
+void sws_freeFilter(SwsFilter *filter);
+
+struct SwsContext *sws_getCachedContext(struct SwsContext *context,
+                                        int srcW, int srcH, int srcFormat,
+                                        int dstW, int dstH, int dstFormat, int flags,
+                                        SwsFilter *srcFilter, SwsFilter *dstFilter, double *param);
+
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/include/jconfig.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/jconfig.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/jconfig.h	(revision 18425)
@@ -0,0 +1,45 @@
+/* jconfig.h.  Generated automatically by configure.  */
+/* jconfig.cfg --- source file edited by configure script */
+/* see jconfig.doc for explanations */
+
+#define HAVE_PROTOTYPES 
+#define HAVE_UNSIGNED_CHAR 
+#define HAVE_UNSIGNED_SHORT 
+#undef void
+#undef const
+#undef CHAR_IS_UNSIGNED
+#define HAVE_STDDEF_H 
+#define HAVE_STDLIB_H 
+#undef NEED_BSD_STRINGS
+#undef NEED_SYS_TYPES_H
+#undef NEED_FAR_POINTERS
+#undef NEED_SHORT_EXTERNAL_NAMES
+/* Define this if you get warnings about undefined structures. */
+#undef INCOMPLETE_TYPES_BROKEN
+
+#ifdef JPEG_INTERNALS
+
+#undef RIGHT_SHIFT_IS_UNSIGNED
+#define INLINE __inline__
+/* These are for configuring the JPEG memory manager. */
+#undef DEFAULT_MAX_MEM
+#undef NO_MKTEMP
+
+#endif /* JPEG_INTERNALS */
+
+#ifdef JPEG_CJPEG_DJPEG
+
+#define BMP_SUPPORTED		/* BMP image file format */
+#define GIF_SUPPORTED		/* GIF image file format */
+#define PPM_SUPPORTED		/* PBMPLUS PPM/PGM image file format */
+#undef RLE_SUPPORTED		/* Utah RLE image file format */
+#define TARGA_SUPPORTED		/* Targa image file format */
+
+#undef TWO_FILE_COMMANDLINE
+#undef NEED_SIGNAL_CATCHER
+#undef DONT_USE_B_MODE
+
+/* Define this if you want percent-done progress reports from cjpeg/djpeg. */
+#undef PROGRESS_REPORT
+
+#endif /* JPEG_CJPEG_DJPEG */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/jerror.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/jerror.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/jerror.h	(revision 18425)
@@ -0,0 +1,291 @@
+/*
+ * jerror.h
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the error and message codes for the JPEG library.
+ * Edit this file to add new codes, or to translate the message strings to
+ * some other language.
+ * A set of error-reporting macros are defined too.  Some applications using
+ * the JPEG library may wish to include this file to get the error codes
+ * and/or the macros.
+ */
+
+/*
+ * To define the enum list of message codes, include this file without
+ * defining macro JMESSAGE.  To create a message string table, include it
+ * again with a suitable JMESSAGE definition (see jerror.c for an example).
+ */
+#ifndef JMESSAGE
+#ifndef JERROR_H
+/* First time through, define the enum list */
+#define JMAKE_ENUM_LIST
+#else
+/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
+#define JMESSAGE(code,string)
+#endif /* JERROR_H */
+#endif /* JMESSAGE */
+
+#ifdef JMAKE_ENUM_LIST
+
+typedef enum {
+
+#define JMESSAGE(code,string)	code ,
+
+#endif /* JMAKE_ENUM_LIST */
+
+JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
+
+/* For maintenance convenience, list is alphabetical by message code name */
+JMESSAGE(JERR_ARITH_NOTIMPL,
+	 "Sorry, there are legal restrictions on arithmetic coding")
+JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
+JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
+JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
+JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
+JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
+JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
+JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
+JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
+JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
+JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
+JMESSAGE(JERR_BAD_LIB_VERSION,
+	 "Wrong JPEG library version: library is %d, caller expects %d")
+JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
+JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
+JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
+JMESSAGE(JERR_BAD_PROGRESSION,
+	 "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
+JMESSAGE(JERR_BAD_PROG_SCRIPT,
+	 "Invalid progressive parameters at scan script entry %d")
+JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
+JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
+JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
+JMESSAGE(JERR_BAD_STRUCT_SIZE,
+	 "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u")
+JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
+JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
+JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
+JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
+JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
+JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
+JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
+JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
+JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
+JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
+JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
+JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
+JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
+JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
+JMESSAGE(JERR_FILE_READ, "Input file read error")
+JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
+JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
+JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
+JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
+JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
+JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
+JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
+JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
+	 "Cannot transcode due to multiple use of quantization table %d")
+JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
+JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
+JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
+JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
+JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
+JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
+JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
+JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
+JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
+JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
+JMESSAGE(JERR_QUANT_COMPONENTS,
+	 "Cannot quantize more than %d color components")
+JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
+JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
+JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
+JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
+JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
+JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
+JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
+JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
+JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
+JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
+JMESSAGE(JERR_TFILE_WRITE,
+	 "Write failed on temporary file --- out of disk space?")
+JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
+JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
+JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
+JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
+JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
+JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
+JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
+JMESSAGE(JMSG_VERSION, JVERSION)
+JMESSAGE(JTRC_16BIT_TABLES,
+	 "Caution: quantization tables are too coarse for baseline JPEG")
+JMESSAGE(JTRC_ADOBE,
+	 "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
+JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
+JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
+JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
+JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
+JMESSAGE(JTRC_DQT, "Define Quantization Table %d  precision %d")
+JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
+JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
+JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
+JMESSAGE(JTRC_EOI, "End Of Image")
+JMESSAGE(JTRC_HUFFBITS, "        %3d %3d %3d %3d %3d %3d %3d %3d")
+JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d  %d")
+JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
+	 "Warning: thumbnail image size does not match data length %u")
+JMESSAGE(JTRC_JFIF_EXTENSION,
+	 "JFIF extension marker: type 0x%02x, length %u")
+JMESSAGE(JTRC_JFIF_THUMBNAIL, "    with %d x %d thumbnail image")
+JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
+JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
+JMESSAGE(JTRC_QUANTVALS, "        %4u %4u %4u %4u %4u %4u %4u %4u")
+JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
+JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
+JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
+JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
+JMESSAGE(JTRC_RST, "RST%d")
+JMESSAGE(JTRC_SMOOTH_NOTIMPL,
+	 "Smoothing not supported with nonstandard sampling ratios")
+JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
+JMESSAGE(JTRC_SOF_COMPONENT, "    Component %d: %dhx%dv q=%d")
+JMESSAGE(JTRC_SOI, "Start of Image")
+JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
+JMESSAGE(JTRC_SOS_COMPONENT, "    Component %d: dc=%d ac=%d")
+JMESSAGE(JTRC_SOS_PARAMS, "  Ss=%d, Se=%d, Ah=%d, Al=%d")
+JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
+JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
+JMESSAGE(JTRC_THUMB_JPEG,
+	 "JFIF extension marker: JPEG-compressed thumbnail image, length %u")
+JMESSAGE(JTRC_THUMB_PALETTE,
+	 "JFIF extension marker: palette thumbnail image, length %u")
+JMESSAGE(JTRC_THUMB_RGB,
+	 "JFIF extension marker: RGB thumbnail image, length %u")
+JMESSAGE(JTRC_UNKNOWN_IDS,
+	 "Unrecognized component IDs %d %d %d, assuming YCbCr")
+JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
+JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
+JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
+JMESSAGE(JWRN_BOGUS_PROGRESSION,
+	 "Inconsistent progression sequence for component %d coefficient %d")
+JMESSAGE(JWRN_EXTRANEOUS_DATA,
+	 "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
+JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
+JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
+JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
+JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
+JMESSAGE(JWRN_MUST_RESYNC,
+	 "Corrupt JPEG data: found marker 0x%02x instead of RST%d")
+JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
+JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
+
+#ifdef JMAKE_ENUM_LIST
+
+  JMSG_LASTMSGCODE
+} J_MESSAGE_CODE;
+
+#undef JMAKE_ENUM_LIST
+#endif /* JMAKE_ENUM_LIST */
+
+/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
+#undef JMESSAGE
+
+
+#ifndef JERROR_H
+#define JERROR_H
+
+/* Macros to simplify using the error and trace message stuff */
+/* The first parameter is either type of cinfo pointer */
+
+/* Fatal errors (print message and exit) */
+#define ERREXIT(cinfo,code)  \
+  ((cinfo)->err->msg_code = (code), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT1(cinfo,code,p1)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT2(cinfo,code,p1,p2)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (cinfo)->err->msg_parm.i[1] = (p2), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT3(cinfo,code,p1,p2,p3)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (cinfo)->err->msg_parm.i[1] = (p2), \
+   (cinfo)->err->msg_parm.i[2] = (p3), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT4(cinfo,code,p1,p2,p3,p4)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (cinfo)->err->msg_parm.i[1] = (p2), \
+   (cinfo)->err->msg_parm.i[2] = (p3), \
+   (cinfo)->err->msg_parm.i[3] = (p4), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXITS(cinfo,code,str)  \
+  ((cinfo)->err->msg_code = (code), \
+   strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+
+#define MAKESTMT(stuff)		do { stuff } while (0)
+
+/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
+#define WARNMS(cinfo,code)  \
+  ((cinfo)->err->msg_code = (code), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+#define WARNMS1(cinfo,code,p1)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+#define WARNMS2(cinfo,code,p1,p2)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (cinfo)->err->msg_parm.i[1] = (p2), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+
+/* Informational/debugging messages */
+#define TRACEMS(cinfo,lvl,code)  \
+  ((cinfo)->err->msg_code = (code), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS1(cinfo,lvl,code,p1)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS2(cinfo,lvl,code,p1,p2)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (cinfo)->err->msg_parm.i[1] = (p2), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS3(cinfo,lvl,code,p1,p2,p3)  \
+  MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+	   _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
+	   (cinfo)->err->msg_code = (code); \
+	   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4)  \
+  MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+	   _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+	   (cinfo)->err->msg_code = (code); \
+	   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5)  \
+  MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+	   _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+	   _mp[4] = (p5); \
+	   (cinfo)->err->msg_code = (code); \
+	   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8)  \
+  MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+	   _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+	   _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
+	   (cinfo)->err->msg_code = (code); \
+	   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMSS(cinfo,lvl,code,str)  \
+  ((cinfo)->err->msg_code = (code), \
+   strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+
+#endif /* JERROR_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/jmorecfg.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/jmorecfg.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/jmorecfg.h	(revision 18425)
@@ -0,0 +1,363 @@
+/*
+ * jmorecfg.h
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains additional configuration options that customize the
+ * JPEG software for special applications or support machine-dependent
+ * optimizations.  Most users will not need to touch this file.
+ */
+
+
+/*
+ * Define BITS_IN_JSAMPLE as either
+ *   8   for 8-bit sample values (the usual setting)
+ *   12  for 12-bit sample values
+ * Only 8 and 12 are legal data precisions for lossy JPEG according to the
+ * JPEG standard, and the IJG code does not support anything else!
+ * We do not support run-time selection of data precision, sorry.
+ */
+
+#define BITS_IN_JSAMPLE  8	/* use 8 or 12 */
+
+
+/*
+ * Maximum number of components (color channels) allowed in JPEG image.
+ * To meet the letter of the JPEG spec, set this to 255.  However, darn
+ * few applications need more than 4 channels (maybe 5 for CMYK + alpha
+ * mask).  We recommend 10 as a reasonable compromise; use 4 if you are
+ * really short on memory.  (Each allowed component costs a hundred or so
+ * bytes of storage, whether actually used in an image or not.)
+ */
+
+#define MAX_COMPONENTS  10	/* maximum number of image components */
+
+
+/*
+ * Basic data types.
+ * You may need to change these if you have a machine with unusual data
+ * type sizes; for example, "char" not 8 bits, "short" not 16 bits,
+ * or "long" not 32 bits.  We don't care whether "int" is 16 or 32 bits,
+ * but it had better be at least 16.
+ */
+
+/* Representation of a single sample (pixel element value).
+ * We frequently allocate large arrays of these, so it's important to keep
+ * them small.  But if you have memory to burn and access to char or short
+ * arrays is very slow on your hardware, you might want to change these.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+/* JSAMPLE should be the smallest type that will hold the values 0..255.
+ * You can use a signed char by having GETJSAMPLE mask it with 0xFF.
+ */
+
+#ifdef HAVE_UNSIGNED_CHAR
+
+typedef unsigned char JSAMPLE;
+#define GETJSAMPLE(value)  ((int) (value))
+
+#else /* not HAVE_UNSIGNED_CHAR */
+
+typedef char JSAMPLE;
+#ifdef CHAR_IS_UNSIGNED
+#define GETJSAMPLE(value)  ((int) (value))
+#else
+#define GETJSAMPLE(value)  ((int) (value) & 0xFF)
+#endif /* CHAR_IS_UNSIGNED */
+
+#endif /* HAVE_UNSIGNED_CHAR */
+
+#define MAXJSAMPLE	255
+#define CENTERJSAMPLE	128
+
+#endif /* BITS_IN_JSAMPLE == 8 */
+
+
+#if BITS_IN_JSAMPLE == 12
+/* JSAMPLE should be the smallest type that will hold the values 0..4095.
+ * On nearly all machines "short" will do nicely.
+ */
+
+typedef short JSAMPLE;
+#define GETJSAMPLE(value)  ((int) (value))
+
+#define MAXJSAMPLE	4095
+#define CENTERJSAMPLE	2048
+
+#endif /* BITS_IN_JSAMPLE == 12 */
+
+
+/* Representation of a DCT frequency coefficient.
+ * This should be a signed value of at least 16 bits; "short" is usually OK.
+ * Again, we allocate large arrays of these, but you can change to int
+ * if you have memory to burn and "short" is really slow.
+ */
+
+typedef short JCOEF;
+
+
+/* Compressed datastreams are represented as arrays of JOCTET.
+ * These must be EXACTLY 8 bits wide, at least once they are written to
+ * external storage.  Note that when using the stdio data source/destination
+ * managers, this is also the data type passed to fread/fwrite.
+ */
+
+#ifdef HAVE_UNSIGNED_CHAR
+
+typedef unsigned char JOCTET;
+#define GETJOCTET(value)  (value)
+
+#else /* not HAVE_UNSIGNED_CHAR */
+
+typedef char JOCTET;
+#ifdef CHAR_IS_UNSIGNED
+#define GETJOCTET(value)  (value)
+#else
+#define GETJOCTET(value)  ((value) & 0xFF)
+#endif /* CHAR_IS_UNSIGNED */
+
+#endif /* HAVE_UNSIGNED_CHAR */
+
+
+/* These typedefs are used for various table entries and so forth.
+ * They must be at least as wide as specified; but making them too big
+ * won't cost a huge amount of memory, so we don't provide special
+ * extraction code like we did for JSAMPLE.  (In other words, these
+ * typedefs live at a different point on the speed/space tradeoff curve.)
+ */
+
+/* UINT8 must hold at least the values 0..255. */
+
+#ifdef HAVE_UNSIGNED_CHAR
+typedef unsigned char UINT8;
+#else /* not HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+typedef char UINT8;
+#else /* not CHAR_IS_UNSIGNED */
+typedef short UINT8;
+#endif /* CHAR_IS_UNSIGNED */
+#endif /* HAVE_UNSIGNED_CHAR */
+
+/* UINT16 must hold at least the values 0..65535. */
+
+#ifdef HAVE_UNSIGNED_SHORT
+typedef unsigned short UINT16;
+#else /* not HAVE_UNSIGNED_SHORT */
+typedef unsigned int UINT16;
+#endif /* HAVE_UNSIGNED_SHORT */
+
+/* INT16 must hold at least the values -32768..32767. */
+
+#ifndef XMD_H			/* X11/xmd.h correctly defines INT16 */
+typedef short INT16;
+#endif
+
+/* INT32 must hold at least signed 32-bit values. */
+
+#ifndef XMD_H			/* X11/xmd.h correctly defines INT32 */
+typedef long INT32;
+#endif
+
+/* Datatype used for image dimensions.  The JPEG standard only supports
+ * images up to 64K*64K due to 16-bit fields in SOF markers.  Therefore
+ * "unsigned int" is sufficient on all machines.  However, if you need to
+ * handle larger images and you don't mind deviating from the spec, you
+ * can change this datatype.
+ */
+
+typedef unsigned int JDIMENSION;
+
+#define JPEG_MAX_DIMENSION  65500L  /* a tad under 64K to prevent overflows */
+
+
+/* These macros are used in all function definitions and extern declarations.
+ * You could modify them if you need to change function linkage conventions;
+ * in particular, you'll need to do that to make the library a Windows DLL.
+ * Another application is to make all functions global for use with debuggers
+ * or code profilers that require it.
+ */
+
+/* a function called through method pointers: */
+#define METHODDEF(type)		static type
+/* a function used only in its module: */
+#define LOCAL(type)		static type
+/* a function referenced thru EXTERNs: */
+#define GLOBAL(type)		type
+/* a reference to a GLOBAL function: */
+#define EXTERN(type)		extern type
+
+
+/* This macro is used to declare a "method", that is, a function pointer.
+ * We want to supply prototype parameters if the compiler can cope.
+ * Note that the arglist parameter must be parenthesized!
+ * Again, you can customize this if you need special linkage keywords.
+ */
+
+#ifdef HAVE_PROTOTYPES
+#define JMETHOD(type,methodname,arglist)  type (*methodname) arglist
+#else
+#define JMETHOD(type,methodname,arglist)  type (*methodname) ()
+#endif
+
+
+/* Here is the pseudo-keyword for declaring pointers that must be "far"
+ * on 80x86 machines.  Most of the specialized coding for 80x86 is handled
+ * by just saying "FAR *" where such a pointer is needed.  In a few places
+ * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
+ */
+
+#ifdef NEED_FAR_POINTERS
+#define FAR  far
+#else
+#define FAR
+#endif
+
+
+/*
+ * On a few systems, type boolean and/or its values FALSE, TRUE may appear
+ * in standard header files.  Or you may have conflicts with application-
+ * specific header files that you want to include together with these files.
+ * Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
+ */
+
+#ifndef HAVE_BOOLEAN
+typedef int boolean;
+#endif
+#ifndef FALSE			/* in case these macros already exist */
+#define FALSE	0		/* values of boolean */
+#endif
+#ifndef TRUE
+#define TRUE	1
+#endif
+
+
+/*
+ * The remaining options affect code selection within the JPEG library,
+ * but they don't need to be visible to most applications using the library.
+ * To minimize application namespace pollution, the symbols won't be
+ * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
+ */
+
+#ifdef JPEG_INTERNALS
+#define JPEG_INTERNAL_OPTIONS
+#endif
+
+#ifdef JPEG_INTERNAL_OPTIONS
+
+
+/*
+ * These defines indicate whether to include various optional functions.
+ * Undefining some of these symbols will produce a smaller but less capable
+ * library.  Note that you can leave certain source files out of the
+ * compilation/linking process if you've #undef'd the corresponding symbols.
+ * (You may HAVE to do that if your compiler doesn't like null source files.)
+ */
+
+/* Arithmetic coding is unsupported for legal reasons.  Complaints to IBM. */
+
+/* Capability options common to encoder and decoder: */
+
+#define DCT_ISLOW_SUPPORTED	/* slow but accurate integer algorithm */
+#define DCT_IFAST_SUPPORTED	/* faster, less accurate integer method */
+#define DCT_FLOAT_SUPPORTED	/* floating-point: accurate, fast on fast HW */
+
+/* Encoder capability options: */
+
+#undef  C_ARITH_CODING_SUPPORTED    /* Arithmetic coding back end? */
+#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
+#define C_PROGRESSIVE_SUPPORTED	    /* Progressive JPEG? (Requires MULTISCAN)*/
+#define ENTROPY_OPT_SUPPORTED	    /* Optimization of entropy coding parms? */
+/* Note: if you selected 12-bit data precision, it is dangerous to turn off
+ * ENTROPY_OPT_SUPPORTED.  The standard Huffman tables are only good for 8-bit
+ * precision, so jchuff.c normally uses entropy optimization to compute
+ * usable tables for higher precision.  If you don't want to do optimization,
+ * you'll have to supply different default Huffman tables.
+ * The exact same statements apply for progressive JPEG: the default tables
+ * don't work for progressive mode.  (This may get fixed, however.)
+ */
+#define INPUT_SMOOTHING_SUPPORTED   /* Input image smoothing option? */
+
+/* Decoder capability options: */
+
+#undef  D_ARITH_CODING_SUPPORTED    /* Arithmetic coding back end? */
+#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
+#define D_PROGRESSIVE_SUPPORTED	    /* Progressive JPEG? (Requires MULTISCAN)*/
+#define SAVE_MARKERS_SUPPORTED	    /* jpeg_save_markers() needed? */
+#define BLOCK_SMOOTHING_SUPPORTED   /* Block smoothing? (Progressive only) */
+#define IDCT_SCALING_SUPPORTED	    /* Output rescaling via IDCT? */
+#undef  UPSAMPLE_SCALING_SUPPORTED  /* Output rescaling at upsample stage? */
+#define UPSAMPLE_MERGING_SUPPORTED  /* Fast path for sloppy upsampling? */
+#define QUANT_1PASS_SUPPORTED	    /* 1-pass color quantization? */
+#define QUANT_2PASS_SUPPORTED	    /* 2-pass color quantization? */
+
+/* more capability options later, no doubt */
+
+
+/*
+ * Ordering of RGB data in scanlines passed to or from the application.
+ * If your application wants to deal with data in the order B,G,R, just
+ * change these macros.  You can also deal with formats such as R,G,B,X
+ * (one extra byte per pixel) by changing RGB_PIXELSIZE.  Note that changing
+ * the offsets will also change the order in which colormap data is organized.
+ * RESTRICTIONS:
+ * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
+ * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not
+ *    useful if you are using JPEG color spaces other than YCbCr or grayscale.
+ * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
+ *    is not 3 (they don't understand about dummy color components!).  So you
+ *    can't use color quantization if you change that value.
+ */
+
+#define RGB_RED		0	/* Offset of Red in an RGB scanline element */
+#define RGB_GREEN	1	/* Offset of Green */
+#define RGB_BLUE	2	/* Offset of Blue */
+#define RGB_PIXELSIZE	3	/* JSAMPLEs per RGB scanline element */
+
+
+/* Definitions for speed-related optimizations. */
+
+
+/* If your compiler supports inline functions, define INLINE
+ * as the inline keyword; otherwise define it as empty.
+ */
+
+#ifndef INLINE
+#ifdef __GNUC__			/* for instance, GNU C knows about inline */
+#define INLINE __inline__
+#endif
+#ifndef INLINE
+#define INLINE			/* default is to define it as empty */
+#endif
+#endif
+
+
+/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
+ * two 16-bit shorts is faster than multiplying two ints.  Define MULTIPLIER
+ * as short on such a machine.  MULTIPLIER must be at least 16 bits wide.
+ */
+
+#ifndef MULTIPLIER
+#define MULTIPLIER  int		/* type for fastest integer multiply */
+#endif
+
+
+/* FAST_FLOAT should be either float or double, whichever is done faster
+ * by your compiler.  (Note that this type is only used in the floating point
+ * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
+ * Typically, float is faster in ANSI C compilers, while double is faster in
+ * pre-ANSI compilers (because they insist on converting to double anyway).
+ * The code below therefore chooses float if we have ANSI-style prototypes.
+ */
+
+#ifndef FAST_FLOAT
+#ifdef HAVE_PROTOTYPES
+#define FAST_FLOAT  float
+#else
+#define FAST_FLOAT  double
+#endif
+#endif
+
+#endif /* JPEG_INTERNAL_OPTIONS */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/jpeglib.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/jpeglib.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/jpeglib.h	(revision 18425)
@@ -0,0 +1,1096 @@
+/*
+ * jpeglib.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the application interface for the JPEG library.
+ * Most applications using the library need only include this file,
+ * and perhaps jerror.h if they want to know the exact error codes.
+ */
+
+#ifndef JPEGLIB_H
+#define JPEGLIB_H
+
+/*
+ * First we include the configuration files that record how this
+ * installation of the JPEG library is set up.  jconfig.h can be
+ * generated automatically for many systems.  jmorecfg.h contains
+ * manual configuration options that most people need not worry about.
+ */
+
+#ifndef JCONFIG_INCLUDED	/* in case jinclude.h already did */
+#include "jconfig.h"		/* widely used configuration options */
+#endif
+#include "jmorecfg.h"		/* seldom changed options */
+
+
+/* Version ID for the JPEG library.
+ * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
+ */
+
+#define JPEG_LIB_VERSION  62	/* Version 6b */
+
+
+/* Various constants determining the sizes of things.
+ * All of these are specified by the JPEG standard, so don't change them
+ * if you want to be compatible.
+ */
+
+#define DCTSIZE		    8	/* The basic DCT block is 8x8 samples */
+#define DCTSIZE2	    64	/* DCTSIZE squared; # of elements in a block */
+#define NUM_QUANT_TBLS      4	/* Quantization tables are numbered 0..3 */
+#define NUM_HUFF_TBLS       4	/* Huffman tables are numbered 0..3 */
+#define NUM_ARITH_TBLS      16	/* Arith-coding tables are numbered 0..15 */
+#define MAX_COMPS_IN_SCAN   4	/* JPEG limit on # of components in one scan */
+#define MAX_SAMP_FACTOR     4	/* JPEG limit on sampling factors */
+/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard;
+ * the PostScript DCT filter can emit files with many more than 10 blocks/MCU.
+ * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU
+ * to handle it.  We even let you do this from the jconfig.h file.  However,
+ * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe
+ * sometimes emits noncompliant files doesn't mean you should too.
+ */
+#define C_MAX_BLOCKS_IN_MCU   10 /* compressor's limit on blocks per MCU */
+#ifndef D_MAX_BLOCKS_IN_MCU
+#define D_MAX_BLOCKS_IN_MCU   10 /* decompressor's limit on blocks per MCU */
+#endif
+
+
+/* Data structures for images (arrays of samples and of DCT coefficients).
+ * On 80x86 machines, the image arrays are too big for near pointers,
+ * but the pointer arrays can fit in near memory.
+ */
+
+typedef JSAMPLE FAR *JSAMPROW;	/* ptr to one image row of pixel samples. */
+typedef JSAMPROW *JSAMPARRAY;	/* ptr to some rows (a 2-D sample array) */
+typedef JSAMPARRAY *JSAMPIMAGE;	/* a 3-D sample array: top index is color */
+
+typedef JCOEF JBLOCK[DCTSIZE2];	/* one block of coefficients */
+typedef JBLOCK FAR *JBLOCKROW;	/* pointer to one row of coefficient blocks */
+typedef JBLOCKROW *JBLOCKARRAY;		/* a 2-D array of coefficient blocks */
+typedef JBLOCKARRAY *JBLOCKIMAGE;	/* a 3-D array of coefficient blocks */
+
+typedef JCOEF FAR *JCOEFPTR;	/* useful in a couple of places */
+
+
+/* Types for JPEG compression parameters and working tables. */
+
+
+/* DCT coefficient quantization tables. */
+
+typedef struct {
+  /* This array gives the coefficient quantizers in natural array order
+   * (not the zigzag order in which they are stored in a JPEG DQT marker).
+   * CAUTION: IJG versions prior to v6a kept this array in zigzag order.
+   */
+  UINT16 quantval[DCTSIZE2];	/* quantization step for each coefficient */
+  /* This field is used only during compression.  It's initialized FALSE when
+   * the table is created, and set TRUE when it's been output to the file.
+   * You could suppress output of a table by setting this to TRUE.
+   * (See jpeg_suppress_tables for an example.)
+   */
+  boolean sent_table;		/* TRUE when table has been output */
+} JQUANT_TBL;
+
+
+/* Huffman coding tables. */
+
+typedef struct {
+  /* These two fields directly represent the contents of a JPEG DHT marker */
+  UINT8 bits[17];		/* bits[k] = # of symbols with codes of */
+				/* length k bits; bits[0] is unused */
+  UINT8 huffval[256];		/* The symbols, in order of incr code length */
+  /* This field is used only during compression.  It's initialized FALSE when
+   * the table is created, and set TRUE when it's been output to the file.
+   * You could suppress output of a table by setting this to TRUE.
+   * (See jpeg_suppress_tables for an example.)
+   */
+  boolean sent_table;		/* TRUE when table has been output */
+} JHUFF_TBL;
+
+
+/* Basic info about one component (color channel). */
+
+typedef struct {
+  /* These values are fixed over the whole image. */
+  /* For compression, they must be supplied by parameter setup; */
+  /* for decompression, they are read from the SOF marker. */
+  int component_id;		/* identifier for this component (0..255) */
+  int component_index;		/* its index in SOF or cinfo->comp_info[] */
+  int h_samp_factor;		/* horizontal sampling factor (1..4) */
+  int v_samp_factor;		/* vertical sampling factor (1..4) */
+  int quant_tbl_no;		/* quantization table selector (0..3) */
+  /* These values may vary between scans. */
+  /* For compression, they must be supplied by parameter setup; */
+  /* for decompression, they are read from the SOS marker. */
+  /* The decompressor output side may not use these variables. */
+  int dc_tbl_no;		/* DC entropy table selector (0..3) */
+  int ac_tbl_no;		/* AC entropy table selector (0..3) */
+  
+  /* Remaining fields should be treated as private by applications. */
+  
+  /* These values are computed during compression or decompression startup: */
+  /* Component's size in DCT blocks.
+   * Any dummy blocks added to complete an MCU are not counted; therefore
+   * these values do not depend on whether a scan is interleaved or not.
+   */
+  JDIMENSION width_in_blocks;
+  JDIMENSION height_in_blocks;
+  /* Size of a DCT block in samples.  Always DCTSIZE for compression.
+   * For decompression this is the size of the output from one DCT block,
+   * reflecting any scaling we choose to apply during the IDCT step.
+   * Values of 1,2,4,8 are likely to be supported.  Note that different
+   * components may receive different IDCT scalings.
+   */
+  int DCT_scaled_size;
+  /* The downsampled dimensions are the component's actual, unpadded number
+   * of samples at the main buffer (preprocessing/compression interface), thus
+   * downsampled_width = ceil(image_width * Hi/Hmax)
+   * and similarly for height.  For decompression, IDCT scaling is included, so
+   * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE)
+   */
+  JDIMENSION downsampled_width;	 /* actual width in samples */
+  JDIMENSION downsampled_height; /* actual height in samples */
+  /* This flag is used only for decompression.  In cases where some of the
+   * components will be ignored (eg grayscale output from YCbCr image),
+   * we can skip most computations for the unused components.
+   */
+  boolean component_needed;	/* do we need the value of this component? */
+
+  /* These values are computed before starting a scan of the component. */
+  /* The decompressor output side may not use these variables. */
+  int MCU_width;		/* number of blocks per MCU, horizontally */
+  int MCU_height;		/* number of blocks per MCU, vertically */
+  int MCU_blocks;		/* MCU_width * MCU_height */
+  int MCU_sample_width;		/* MCU width in samples, MCU_width*DCT_scaled_size */
+  int last_col_width;		/* # of non-dummy blocks across in last MCU */
+  int last_row_height;		/* # of non-dummy blocks down in last MCU */
+
+  /* Saved quantization table for component; NULL if none yet saved.
+   * See jdinput.c comments about the need for this information.
+   * This field is currently used only for decompression.
+   */
+  JQUANT_TBL * quant_table;
+
+  /* Private per-component storage for DCT or IDCT subsystem. */
+  void * dct_table;
+} jpeg_component_info;
+
+
+/* The script for encoding a multiple-scan file is an array of these: */
+
+typedef struct {
+  int comps_in_scan;		/* number of components encoded in this scan */
+  int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
+  int Ss, Se;			/* progressive JPEG spectral selection parms */
+  int Ah, Al;			/* progressive JPEG successive approx. parms */
+} jpeg_scan_info;
+
+/* The decompressor can save APPn and COM markers in a list of these: */
+
+typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr;
+
+struct jpeg_marker_struct {
+  jpeg_saved_marker_ptr next;	/* next in list, or NULL */
+  UINT8 marker;			/* marker code: JPEG_COM, or JPEG_APP0+n */
+  unsigned int original_length;	/* # bytes of data in the file */
+  unsigned int data_length;	/* # bytes of data saved at data[] */
+  JOCTET FAR * data;		/* the data contained in the marker */
+  /* the marker length word is not counted in data_length or original_length */
+};
+
+/* Known color spaces. */
+
+typedef enum {
+	JCS_UNKNOWN,		/* error/unspecified */
+	JCS_GRAYSCALE,		/* monochrome */
+	JCS_RGB,		/* red/green/blue */
+	JCS_YCbCr,		/* Y/Cb/Cr (also known as YUV) */
+	JCS_CMYK,		/* C/M/Y/K */
+	JCS_YCCK		/* Y/Cb/Cr/K */
+} J_COLOR_SPACE;
+
+/* DCT/IDCT algorithm options. */
+
+typedef enum {
+	JDCT_ISLOW,		/* slow but accurate integer algorithm */
+	JDCT_IFAST,		/* faster, less accurate integer method */
+	JDCT_FLOAT		/* floating-point: accurate, fast on fast HW */
+} J_DCT_METHOD;
+
+#ifndef JDCT_DEFAULT		/* may be overridden in jconfig.h */
+#define JDCT_DEFAULT  JDCT_ISLOW
+#endif
+#ifndef JDCT_FASTEST		/* may be overridden in jconfig.h */
+#define JDCT_FASTEST  JDCT_IFAST
+#endif
+
+/* Dithering options for decompression. */
+
+typedef enum {
+	JDITHER_NONE,		/* no dithering */
+	JDITHER_ORDERED,	/* simple ordered dither */
+	JDITHER_FS		/* Floyd-Steinberg error diffusion dither */
+} J_DITHER_MODE;
+
+
+/* Common fields between JPEG compression and decompression master structs. */
+
+#define jpeg_common_fields \
+  struct jpeg_error_mgr * err;	/* Error handler module */\
+  struct jpeg_memory_mgr * mem;	/* Memory manager module */\
+  struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\
+  void * client_data;		/* Available for use by application */\
+  boolean is_decompressor;	/* So common code can tell which is which */\
+  int global_state		/* For checking call sequence validity */
+
+/* Routines that are to be used by both halves of the library are declared
+ * to receive a pointer to this structure.  There are no actual instances of
+ * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct.
+ */
+struct jpeg_common_struct {
+  jpeg_common_fields;		/* Fields common to both master struct types */
+  /* Additional fields follow in an actual jpeg_compress_struct or
+   * jpeg_decompress_struct.  All three structs must agree on these
+   * initial fields!  (This would be a lot cleaner in C++.)
+   */
+};
+
+typedef struct jpeg_common_struct * j_common_ptr;
+typedef struct jpeg_compress_struct * j_compress_ptr;
+typedef struct jpeg_decompress_struct * j_decompress_ptr;
+
+
+/* Master record for a compression instance */
+
+struct jpeg_compress_struct {
+  jpeg_common_fields;		/* Fields shared with jpeg_decompress_struct */
+
+  /* Destination for compressed data */
+  struct jpeg_destination_mgr * dest;
+
+  /* Description of source image --- these fields must be filled in by
+   * outer application before starting compression.  in_color_space must
+   * be correct before you can even call jpeg_set_defaults().
+   */
+
+  JDIMENSION image_width;	/* input image width */
+  JDIMENSION image_height;	/* input image height */
+  int input_components;		/* # of color components in input image */
+  J_COLOR_SPACE in_color_space;	/* colorspace of input image */
+
+  double input_gamma;		/* image gamma of input image */
+
+  /* Compression parameters --- these fields must be set before calling
+   * jpeg_start_compress().  We recommend calling jpeg_set_defaults() to
+   * initialize everything to reasonable defaults, then changing anything
+   * the application specifically wants to change.  That way you won't get
+   * burnt when new parameters are added.  Also note that there are several
+   * helper routines to simplify changing parameters.
+   */
+
+  int data_precision;		/* bits of precision in image data */
+
+  int num_components;		/* # of color components in JPEG image */
+  J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
+
+  jpeg_component_info * comp_info;
+  /* comp_info[i] describes component that appears i'th in SOF */
+  
+  JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
+  /* ptrs to coefficient quantization tables, or NULL if not defined */
+  
+  JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
+  JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
+  /* ptrs to Huffman coding tables, or NULL if not defined */
+  
+  UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+  UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+  UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
+
+  int num_scans;		/* # of entries in scan_info array */
+  const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */
+  /* The default value of scan_info is NULL, which causes a single-scan
+   * sequential JPEG file to be emitted.  To create a multi-scan file,
+   * set num_scans and scan_info to point to an array of scan definitions.
+   */
+
+  boolean raw_data_in;		/* TRUE=caller supplies downsampled data */
+  boolean arith_code;		/* TRUE=arithmetic coding, FALSE=Huffman */
+  boolean optimize_coding;	/* TRUE=optimize entropy encoding parms */
+  boolean CCIR601_sampling;	/* TRUE=first samples are cosited */
+  int smoothing_factor;		/* 1..100, or 0 for no input smoothing */
+  J_DCT_METHOD dct_method;	/* DCT algorithm selector */
+
+  /* The restart interval can be specified in absolute MCUs by setting
+   * restart_interval, or in MCU rows by setting restart_in_rows
+   * (in which case the correct restart_interval will be figured
+   * for each scan).
+   */
+  unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */
+  int restart_in_rows;		/* if > 0, MCU rows per restart interval */
+
+  /* Parameters controlling emission of special markers. */
+
+  boolean write_JFIF_header;	/* should a JFIF marker be written? */
+  UINT8 JFIF_major_version;	/* What to write for the JFIF version number */
+  UINT8 JFIF_minor_version;
+  /* These three values are not used by the JPEG code, merely copied */
+  /* into the JFIF APP0 marker.  density_unit can be 0 for unknown, */
+  /* 1 for dots/inch, or 2 for dots/cm.  Note that the pixel aspect */
+  /* ratio is defined by X_density/Y_density even when density_unit=0. */
+  UINT8 density_unit;		/* JFIF code for pixel size units */
+  UINT16 X_density;		/* Horizontal pixel density */
+  UINT16 Y_density;		/* Vertical pixel density */
+  boolean write_Adobe_marker;	/* should an Adobe marker be written? */
+  
+  /* State variable: index of next scanline to be written to
+   * jpeg_write_scanlines().  Application may use this to control its
+   * processing loop, e.g., "while (next_scanline < image_height)".
+   */
+
+  JDIMENSION next_scanline;	/* 0 .. image_height-1  */
+
+  /* Remaining fields are known throughout compressor, but generally
+   * should not be touched by a surrounding application.
+   */
+
+  /*
+   * These fields are computed during compression startup
+   */
+  boolean progressive_mode;	/* TRUE if scan script uses progressive mode */
+  int max_h_samp_factor;	/* largest h_samp_factor */
+  int max_v_samp_factor;	/* largest v_samp_factor */
+
+  JDIMENSION total_iMCU_rows;	/* # of iMCU rows to be input to coef ctlr */
+  /* The coefficient controller receives data in units of MCU rows as defined
+   * for fully interleaved scans (whether the JPEG file is interleaved or not).
+   * There are v_samp_factor * DCTSIZE sample rows of each component in an
+   * "iMCU" (interleaved MCU) row.
+   */
+  
+  /*
+   * These fields are valid during any one scan.
+   * They describe the components and MCUs actually appearing in the scan.
+   */
+  int comps_in_scan;		/* # of JPEG components in this scan */
+  jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
+  /* *cur_comp_info[i] describes component that appears i'th in SOS */
+  
+  JDIMENSION MCUs_per_row;	/* # of MCUs across the image */
+  JDIMENSION MCU_rows_in_scan;	/* # of MCU rows in the image */
+  
+  int blocks_in_MCU;		/* # of DCT blocks per MCU */
+  int MCU_membership[C_MAX_BLOCKS_IN_MCU];
+  /* MCU_membership[i] is index in cur_comp_info of component owning */
+  /* i'th block in an MCU */
+
+  int Ss, Se, Ah, Al;		/* progressive JPEG parameters for scan */
+
+  /*
+   * Links to compression subobjects (methods and private variables of modules)
+   */
+  struct jpeg_comp_master * master;
+  struct jpeg_c_main_controller * main;
+  struct jpeg_c_prep_controller * prep;
+  struct jpeg_c_coef_controller * coef;
+  struct jpeg_marker_writer * marker;
+  struct jpeg_color_converter * cconvert;
+  struct jpeg_downsampler * downsample;
+  struct jpeg_forward_dct * fdct;
+  struct jpeg_entropy_encoder * entropy;
+  jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */
+  int script_space_size;
+};
+
+
+/* Master record for a decompression instance */
+
+struct jpeg_decompress_struct {
+  jpeg_common_fields;		/* Fields shared with jpeg_compress_struct */
+
+  /* Source of compressed data */
+  struct jpeg_source_mgr * src;
+
+  /* Basic description of image --- filled in by jpeg_read_header(). */
+  /* Application may inspect these values to decide how to process image. */
+
+  JDIMENSION image_width;	/* nominal image width (from SOF marker) */
+  JDIMENSION image_height;	/* nominal image height */
+  int num_components;		/* # of color components in JPEG image */
+  J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
+
+  /* Decompression processing parameters --- these fields must be set before
+   * calling jpeg_start_decompress().  Note that jpeg_read_header() initializes
+   * them to default values.
+   */
+
+  J_COLOR_SPACE out_color_space; /* colorspace for output */
+
+  unsigned int scale_num, scale_denom; /* fraction by which to scale image */
+
+  double output_gamma;		/* image gamma wanted in output */
+
+  boolean buffered_image;	/* TRUE=multiple output passes */
+  boolean raw_data_out;		/* TRUE=downsampled data wanted */
+
+  J_DCT_METHOD dct_method;	/* IDCT algorithm selector */
+  boolean do_fancy_upsampling;	/* TRUE=apply fancy upsampling */
+  boolean do_block_smoothing;	/* TRUE=apply interblock smoothing */
+
+  boolean quantize_colors;	/* TRUE=colormapped output wanted */
+  /* the following are ignored if not quantize_colors: */
+  J_DITHER_MODE dither_mode;	/* type of color dithering to use */
+  boolean two_pass_quantize;	/* TRUE=use two-pass color quantization */
+  int desired_number_of_colors;	/* max # colors to use in created colormap */
+  /* these are significant only in buffered-image mode: */
+  boolean enable_1pass_quant;	/* enable future use of 1-pass quantizer */
+  boolean enable_external_quant;/* enable future use of external colormap */
+  boolean enable_2pass_quant;	/* enable future use of 2-pass quantizer */
+
+  /* Description of actual output image that will be returned to application.
+   * These fields are computed by jpeg_start_decompress().
+   * You can also use jpeg_calc_output_dimensions() to determine these values
+   * in advance of calling jpeg_start_decompress().
+   */
+
+  JDIMENSION output_width;	/* scaled image width */
+  JDIMENSION output_height;	/* scaled image height */
+  int out_color_components;	/* # of color components in out_color_space */
+  int output_components;	/* # of color components returned */
+  /* output_components is 1 (a colormap index) when quantizing colors;
+   * otherwise it equals out_color_components.
+   */
+  int rec_outbuf_height;	/* min recommended height of scanline buffer */
+  /* If the buffer passed to jpeg_read_scanlines() is less than this many rows
+   * high, space and time will be wasted due to unnecessary data copying.
+   * Usually rec_outbuf_height will be 1 or 2, at most 4.
+   */
+
+  /* When quantizing colors, the output colormap is described by these fields.
+   * The application can supply a colormap by setting colormap non-NULL before
+   * calling jpeg_start_decompress; otherwise a colormap is created during
+   * jpeg_start_decompress or jpeg_start_output.
+   * The map has out_color_components rows and actual_number_of_colors columns.
+   */
+  int actual_number_of_colors;	/* number of entries in use */
+  JSAMPARRAY colormap;		/* The color map as a 2-D pixel array */
+
+  /* State variables: these variables indicate the progress of decompression.
+   * The application may examine these but must not modify them.
+   */
+
+  /* Row index of next scanline to be read from jpeg_read_scanlines().
+   * Application may use this to control its processing loop, e.g.,
+   * "while (output_scanline < output_height)".
+   */
+  JDIMENSION output_scanline;	/* 0 .. output_height-1  */
+
+  /* Current input scan number and number of iMCU rows completed in scan.
+   * These indicate the progress of the decompressor input side.
+   */
+  int input_scan_number;	/* Number of SOS markers seen so far */
+  JDIMENSION input_iMCU_row;	/* Number of iMCU rows completed */
+
+  /* The "output scan number" is the notional scan being displayed by the
+   * output side.  The decompressor will not allow output scan/row number
+   * to get ahead of input scan/row, but it can fall arbitrarily far behind.
+   */
+  int output_scan_number;	/* Nominal scan number being displayed */
+  JDIMENSION output_iMCU_row;	/* Number of iMCU rows read */
+
+  /* Current progression status.  coef_bits[c][i] indicates the precision
+   * with which component c's DCT coefficient i (in zigzag order) is known.
+   * It is -1 when no data has yet been received, otherwise it is the point
+   * transform (shift) value for the most recent scan of the coefficient
+   * (thus, 0 at completion of the progression).
+   * This pointer is NULL when reading a non-progressive file.
+   */
+  int (*coef_bits)[DCTSIZE2];	/* -1 or current Al value for each coef */
+
+  /* Internal JPEG parameters --- the application usually need not look at
+   * these fields.  Note that the decompressor output side may not use
+   * any parameters that can change between scans.
+   */
+
+  /* Quantization and Huffman tables are carried forward across input
+   * datastreams when processing abbreviated JPEG datastreams.
+   */
+
+  JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
+  /* ptrs to coefficient quantization tables, or NULL if not defined */
+
+  JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
+  JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
+  /* ptrs to Huffman coding tables, or NULL if not defined */
+
+  /* These parameters are never carried across datastreams, since they
+   * are given in SOF/SOS markers or defined to be reset by SOI.
+   */
+
+  int data_precision;		/* bits of precision in image data */
+
+  jpeg_component_info * comp_info;
+  /* comp_info[i] describes component that appears i'th in SOF */
+
+  boolean progressive_mode;	/* TRUE if SOFn specifies progressive mode */
+  boolean arith_code;		/* TRUE=arithmetic coding, FALSE=Huffman */
+
+  UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+  UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+  UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
+
+  unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */
+
+  /* These fields record data obtained from optional markers recognized by
+   * the JPEG library.
+   */
+  boolean saw_JFIF_marker;	/* TRUE iff a JFIF APP0 marker was found */
+  /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */
+  UINT8 JFIF_major_version;	/* JFIF version number */
+  UINT8 JFIF_minor_version;
+  UINT8 density_unit;		/* JFIF code for pixel size units */
+  UINT16 X_density;		/* Horizontal pixel density */
+  UINT16 Y_density;		/* Vertical pixel density */
+  boolean saw_Adobe_marker;	/* TRUE iff an Adobe APP14 marker was found */
+  UINT8 Adobe_transform;	/* Color transform code from Adobe marker */
+
+  boolean CCIR601_sampling;	/* TRUE=first samples are cosited */
+
+  /* Aside from the specific data retained from APPn markers known to the
+   * library, the uninterpreted contents of any or all APPn and COM markers
+   * can be saved in a list for examination by the application.
+   */
+  jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */
+
+  /* Remaining fields are known throughout decompressor, but generally
+   * should not be touched by a surrounding application.
+   */
+
+  /*
+   * These fields are computed during decompression startup
+   */
+  int max_h_samp_factor;	/* largest h_samp_factor */
+  int max_v_samp_factor;	/* largest v_samp_factor */
+
+  int min_DCT_scaled_size;	/* smallest DCT_scaled_size of any component */
+
+  JDIMENSION total_iMCU_rows;	/* # of iMCU rows in image */
+  /* The coefficient controller's input and output progress is measured in
+   * units of "iMCU" (interleaved MCU) rows.  These are the same as MCU rows
+   * in fully interleaved JPEG scans, but are used whether the scan is
+   * interleaved or not.  We define an iMCU row as v_samp_factor DCT block
+   * rows of each component.  Therefore, the IDCT output contains
+   * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row.
+   */
+
+  JSAMPLE * sample_range_limit; /* table for fast range-limiting */
+
+  /*
+   * These fields are valid during any one scan.
+   * They describe the components and MCUs actually appearing in the scan.
+   * Note that the decompressor output side must not use these fields.
+   */
+  int comps_in_scan;		/* # of JPEG components in this scan */
+  jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
+  /* *cur_comp_info[i] describes component that appears i'th in SOS */
+
+  JDIMENSION MCUs_per_row;	/* # of MCUs across the image */
+  JDIMENSION MCU_rows_in_scan;	/* # of MCU rows in the image */
+
+  int blocks_in_MCU;		/* # of DCT blocks per MCU */
+  int MCU_membership[D_MAX_BLOCKS_IN_MCU];
+  /* MCU_membership[i] is index in cur_comp_info of component owning */
+  /* i'th block in an MCU */
+
+  int Ss, Se, Ah, Al;		/* progressive JPEG parameters for scan */
+
+  /* This field is shared between entropy decoder and marker parser.
+   * It is either zero or the code of a JPEG marker that has been
+   * read from the data source, but has not yet been processed.
+   */
+  int unread_marker;
+
+  /*
+   * Links to decompression subobjects (methods, private variables of modules)
+   */
+  struct jpeg_decomp_master * master;
+  struct jpeg_d_main_controller * main;
+  struct jpeg_d_coef_controller * coef;
+  struct jpeg_d_post_controller * post;
+  struct jpeg_input_controller * inputctl;
+  struct jpeg_marker_reader * marker;
+  struct jpeg_entropy_decoder * entropy;
+  struct jpeg_inverse_dct * idct;
+  struct jpeg_upsampler * upsample;
+  struct jpeg_color_deconverter * cconvert;
+  struct jpeg_color_quantizer * cquantize;
+};
+
+
+/* "Object" declarations for JPEG modules that may be supplied or called
+ * directly by the surrounding application.
+ * As with all objects in the JPEG library, these structs only define the
+ * publicly visible methods and state variables of a module.  Additional
+ * private fields may exist after the public ones.
+ */
+
+
+/* Error handler object */
+
+struct jpeg_error_mgr {
+  /* Error exit handler: does not return to caller */
+  JMETHOD(void, error_exit, (j_common_ptr cinfo));
+  /* Conditionally emit a trace or warning message */
+  JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level));
+  /* Routine that actually outputs a trace or error message */
+  JMETHOD(void, output_message, (j_common_ptr cinfo));
+  /* Format a message string for the most recent JPEG error or message */
+  JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer));
+#define JMSG_LENGTH_MAX  200	/* recommended size of format_message buffer */
+  /* Reset error state variables at start of a new image */
+  JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo));
+  
+  /* The message ID code and any parameters are saved here.
+   * A message can have one string parameter or up to 8 int parameters.
+   */
+  int msg_code;
+#define JMSG_STR_PARM_MAX  80
+  union {
+    int i[8];
+    char s[JMSG_STR_PARM_MAX];
+  } msg_parm;
+  
+  /* Standard state variables for error facility */
+  
+  int trace_level;		/* max msg_level that will be displayed */
+  
+  /* For recoverable corrupt-data errors, we emit a warning message,
+   * but keep going unless emit_message chooses to abort.  emit_message
+   * should count warnings in num_warnings.  The surrounding application
+   * can check for bad data by seeing if num_warnings is nonzero at the
+   * end of processing.
+   */
+  long num_warnings;		/* number of corrupt-data warnings */
+
+  /* These fields point to the table(s) of error message strings.
+   * An application can change the table pointer to switch to a different
+   * message list (typically, to change the language in which errors are
+   * reported).  Some applications may wish to add additional error codes
+   * that will be handled by the JPEG library error mechanism; the second
+   * table pointer is used for this purpose.
+   *
+   * First table includes all errors generated by JPEG library itself.
+   * Error code 0 is reserved for a "no such error string" message.
+   */
+  const char * const * jpeg_message_table; /* Library errors */
+  int last_jpeg_message;    /* Table contains strings 0..last_jpeg_message */
+  /* Second table can be added by application (see cjpeg/djpeg for example).
+   * It contains strings numbered first_addon_message..last_addon_message.
+   */
+  const char * const * addon_message_table; /* Non-library errors */
+  int first_addon_message;	/* code for first string in addon table */
+  int last_addon_message;	/* code for last string in addon table */
+};
+
+
+/* Progress monitor object */
+
+struct jpeg_progress_mgr {
+  JMETHOD(void, progress_monitor, (j_common_ptr cinfo));
+
+  long pass_counter;		/* work units completed in this pass */
+  long pass_limit;		/* total number of work units in this pass */
+  int completed_passes;		/* passes completed so far */
+  int total_passes;		/* total number of passes expected */
+};
+
+
+/* Data destination object for compression */
+
+struct jpeg_destination_mgr {
+  JOCTET * next_output_byte;	/* => next byte to write in buffer */
+  size_t free_in_buffer;	/* # of byte spaces remaining in buffer */
+
+  JMETHOD(void, init_destination, (j_compress_ptr cinfo));
+  JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo));
+  JMETHOD(void, term_destination, (j_compress_ptr cinfo));
+};
+
+
+/* Data source object for decompression */
+
+struct jpeg_source_mgr {
+  const JOCTET * next_input_byte; /* => next byte to read from buffer */
+  size_t bytes_in_buffer;	/* # of bytes remaining in buffer */
+
+  JMETHOD(void, init_source, (j_decompress_ptr cinfo));
+  JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo));
+  JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes));
+  JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired));
+  JMETHOD(void, term_source, (j_decompress_ptr cinfo));
+};
+
+
+/* Memory manager object.
+ * Allocates "small" objects (a few K total), "large" objects (tens of K),
+ * and "really big" objects (virtual arrays with backing store if needed).
+ * The memory manager does not allow individual objects to be freed; rather,
+ * each created object is assigned to a pool, and whole pools can be freed
+ * at once.  This is faster and more convenient than remembering exactly what
+ * to free, especially where malloc()/free() are not too speedy.
+ * NB: alloc routines never return NULL.  They exit to error_exit if not
+ * successful.
+ */
+
+#define JPOOL_PERMANENT	0	/* lasts until master record is destroyed */
+#define JPOOL_IMAGE	1	/* lasts until done with image/datastream */
+#define JPOOL_NUMPOOLS	2
+
+typedef struct jvirt_sarray_control * jvirt_sarray_ptr;
+typedef struct jvirt_barray_control * jvirt_barray_ptr;
+
+
+struct jpeg_memory_mgr {
+  /* Method pointers */
+  JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id,
+				size_t sizeofobject));
+  JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id,
+				     size_t sizeofobject));
+  JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id,
+				     JDIMENSION samplesperrow,
+				     JDIMENSION numrows));
+  JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id,
+				      JDIMENSION blocksperrow,
+				      JDIMENSION numrows));
+  JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo,
+						  int pool_id,
+						  boolean pre_zero,
+						  JDIMENSION samplesperrow,
+						  JDIMENSION numrows,
+						  JDIMENSION maxaccess));
+  JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo,
+						  int pool_id,
+						  boolean pre_zero,
+						  JDIMENSION blocksperrow,
+						  JDIMENSION numrows,
+						  JDIMENSION maxaccess));
+  JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo));
+  JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo,
+					   jvirt_sarray_ptr ptr,
+					   JDIMENSION start_row,
+					   JDIMENSION num_rows,
+					   boolean writable));
+  JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo,
+					    jvirt_barray_ptr ptr,
+					    JDIMENSION start_row,
+					    JDIMENSION num_rows,
+					    boolean writable));
+  JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id));
+  JMETHOD(void, self_destruct, (j_common_ptr cinfo));
+
+  /* Limit on memory allocation for this JPEG object.  (Note that this is
+   * merely advisory, not a guaranteed maximum; it only affects the space
+   * used for virtual-array buffers.)  May be changed by outer application
+   * after creating the JPEG object.
+   */
+  long max_memory_to_use;
+
+  /* Maximum allocation request accepted by alloc_large. */
+  long max_alloc_chunk;
+};
+
+
+/* Routine signature for application-supplied marker processing methods.
+ * Need not pass marker code since it is stored in cinfo->unread_marker.
+ */
+typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo));
+
+
+/* Declarations for routines called by application.
+ * The JPP macro hides prototype parameters from compilers that can't cope.
+ * Note JPP requires double parentheses.
+ */
+
+#ifdef HAVE_PROTOTYPES
+#define JPP(arglist)	arglist
+#else
+#define JPP(arglist)	()
+#endif
+
+
+/* Short forms of external names for systems with brain-damaged linkers.
+ * We shorten external names to be unique in the first six letters, which
+ * is good enough for all known systems.
+ * (If your compiler itself needs names to be unique in less than 15 
+ * characters, you are out of luck.  Get a better compiler.)
+ */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_std_error		jStdError
+#define jpeg_CreateCompress	jCreaCompress
+#define jpeg_CreateDecompress	jCreaDecompress
+#define jpeg_destroy_compress	jDestCompress
+#define jpeg_destroy_decompress	jDestDecompress
+#define jpeg_stdio_dest		jStdDest
+#define jpeg_stdio_src		jStdSrc
+#define jpeg_set_defaults	jSetDefaults
+#define jpeg_set_colorspace	jSetColorspace
+#define jpeg_default_colorspace	jDefColorspace
+#define jpeg_set_quality	jSetQuality
+#define jpeg_set_linear_quality	jSetLQuality
+#define jpeg_add_quant_table	jAddQuantTable
+#define jpeg_quality_scaling	jQualityScaling
+#define jpeg_simple_progression	jSimProgress
+#define jpeg_suppress_tables	jSuppressTables
+#define jpeg_alloc_quant_table	jAlcQTable
+#define jpeg_alloc_huff_table	jAlcHTable
+#define jpeg_start_compress	jStrtCompress
+#define jpeg_write_scanlines	jWrtScanlines
+#define jpeg_finish_compress	jFinCompress
+#define jpeg_write_raw_data	jWrtRawData
+#define jpeg_write_marker	jWrtMarker
+#define jpeg_write_m_header	jWrtMHeader
+#define jpeg_write_m_byte	jWrtMByte
+#define jpeg_write_tables	jWrtTables
+#define jpeg_read_header	jReadHeader
+#define jpeg_start_decompress	jStrtDecompress
+#define jpeg_read_scanlines	jReadScanlines
+#define jpeg_finish_decompress	jFinDecompress
+#define jpeg_read_raw_data	jReadRawData
+#define jpeg_has_multiple_scans	jHasMultScn
+#define jpeg_start_output	jStrtOutput
+#define jpeg_finish_output	jFinOutput
+#define jpeg_input_complete	jInComplete
+#define jpeg_new_colormap	jNewCMap
+#define jpeg_consume_input	jConsumeInput
+#define jpeg_calc_output_dimensions	jCalcDimensions
+#define jpeg_save_markers	jSaveMarkers
+#define jpeg_set_marker_processor	jSetMarker
+#define jpeg_read_coefficients	jReadCoefs
+#define jpeg_write_coefficients	jWrtCoefs
+#define jpeg_copy_critical_parameters	jCopyCrit
+#define jpeg_abort_compress	jAbrtCompress
+#define jpeg_abort_decompress	jAbrtDecompress
+#define jpeg_abort		jAbort
+#define jpeg_destroy		jDestroy
+#define jpeg_resync_to_restart	jResyncRestart
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Default error-management setup */
+EXTERN(struct jpeg_error_mgr *) jpeg_std_error
+	JPP((struct jpeg_error_mgr * err));
+
+/* Initialization of JPEG compression objects.
+ * jpeg_create_compress() and jpeg_create_decompress() are the exported
+ * names that applications should call.  These expand to calls on
+ * jpeg_CreateCompress and jpeg_CreateDecompress with additional information
+ * passed for version mismatch checking.
+ * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx.
+ */
+#define jpeg_create_compress(cinfo) \
+    jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
+			(size_t) sizeof(struct jpeg_compress_struct))
+#define jpeg_create_decompress(cinfo) \
+    jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
+			  (size_t) sizeof(struct jpeg_decompress_struct))
+EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo,
+				      int version, size_t structsize));
+EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo,
+					int version, size_t structsize));
+/* Destruction of JPEG compression objects */
+EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo));
+
+/* Standard data source and destination managers: stdio streams. */
+/* Caller is responsible for opening the file before and closing after. */
+EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile));
+EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile));
+
+/* Default parameter setup for compression */
+EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo));
+/* Compression parameter setup aids */
+EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo,
+				      J_COLOR_SPACE colorspace));
+EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality,
+				   boolean force_baseline));
+EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo,
+					  int scale_factor,
+					  boolean force_baseline));
+EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl,
+				       const unsigned int *basic_table,
+				       int scale_factor,
+				       boolean force_baseline));
+EXTERN(int) jpeg_quality_scaling JPP((int quality));
+EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo,
+				       boolean suppress));
+EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo));
+EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo));
+
+/* Main entry points for compression */
+EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo,
+				      boolean write_all_tables));
+EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo,
+					     JSAMPARRAY scanlines,
+					     JDIMENSION num_lines));
+EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo));
+
+/* Replaces jpeg_write_scanlines when writing raw downsampled data. */
+EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo,
+					    JSAMPIMAGE data,
+					    JDIMENSION num_lines));
+
+/* Write a special marker.  See libjpeg.doc concerning safe usage. */
+EXTERN(void) jpeg_write_marker
+	JPP((j_compress_ptr cinfo, int marker,
+	     const JOCTET * dataptr, unsigned int datalen));
+/* Same, but piecemeal. */
+EXTERN(void) jpeg_write_m_header
+	JPP((j_compress_ptr cinfo, int marker, unsigned int datalen));
+EXTERN(void) jpeg_write_m_byte
+	JPP((j_compress_ptr cinfo, int val));
+
+/* Alternate compression function: just write an abbreviated table file */
+EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo));
+
+/* Decompression startup: read start of JPEG datastream to see what's there */
+EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo,
+				  boolean require_image));
+/* Return value is one of: */
+#define JPEG_SUSPENDED		0 /* Suspended due to lack of input data */
+#define JPEG_HEADER_OK		1 /* Found valid image datastream */
+#define JPEG_HEADER_TABLES_ONLY	2 /* Found valid table-specs-only datastream */
+/* If you pass require_image = TRUE (normal case), you need not check for
+ * a TABLES_ONLY return code; an abbreviated file will cause an error exit.
+ * JPEG_SUSPENDED is only possible if you use a data source module that can
+ * give a suspension return (the stdio source module doesn't).
+ */
+
+/* Main entry points for decompression */
+EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo));
+EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo,
+					    JSAMPARRAY scanlines,
+					    JDIMENSION max_lines));
+EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo));
+
+/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
+EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo,
+					   JSAMPIMAGE data,
+					   JDIMENSION max_lines));
+
+/* Additional entry points for buffered-image mode. */
+EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo));
+EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo,
+				       int scan_number));
+EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo));
+EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo));
+EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo));
+EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo));
+/* Return value is one of: */
+/* #define JPEG_SUSPENDED	0    Suspended due to lack of input data */
+#define JPEG_REACHED_SOS	1 /* Reached start of new scan */
+#define JPEG_REACHED_EOI	2 /* Reached end of image */
+#define JPEG_ROW_COMPLETED	3 /* Completed one iMCU row */
+#define JPEG_SCAN_COMPLETED	4 /* Completed last iMCU row of a scan */
+
+/* Precalculate output dimensions for current decompression parameters. */
+EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo));
+
+/* Control saving of COM and APPn markers into marker_list. */
+EXTERN(void) jpeg_save_markers
+	JPP((j_decompress_ptr cinfo, int marker_code,
+	     unsigned int length_limit));
+
+/* Install a special processing method for COM or APPn markers. */
+EXTERN(void) jpeg_set_marker_processor
+	JPP((j_decompress_ptr cinfo, int marker_code,
+	     jpeg_marker_parser_method routine));
+
+/* Read or write raw DCT coefficients --- useful for lossless transcoding. */
+EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo));
+EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo,
+					  jvirt_barray_ptr * coef_arrays));
+EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo,
+						j_compress_ptr dstinfo));
+
+/* If you choose to abort compression or decompression before completing
+ * jpeg_finish_(de)compress, then you need to clean up to release memory,
+ * temporary files, etc.  You can just call jpeg_destroy_(de)compress
+ * if you're done with the JPEG object, but if you want to clean it up and
+ * reuse it, call this:
+ */
+EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo));
+
+/* Generic versions of jpeg_abort and jpeg_destroy that work on either
+ * flavor of JPEG object.  These may be more convenient in some places.
+ */
+EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo));
+EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo));
+
+/* Default restart-marker-resync procedure for use by data source modules */
+EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo,
+					    int desired));
+
+
+/* These marker codes are exported since applications and data source modules
+ * are likely to want to use them.
+ */
+
+#define JPEG_RST0	0xD0	/* RST0 marker code */
+#define JPEG_EOI	0xD9	/* EOI marker code */
+#define JPEG_APP0	0xE0	/* APP0 marker code */
+#define JPEG_COM	0xFE	/* COM marker code */
+
+
+/* If we have a brain-damaged compiler that emits warnings (or worse, errors)
+ * for structure definitions that are never filled in, keep it quiet by
+ * supplying dummy definitions for the various substructures.
+ */
+
+#ifdef INCOMPLETE_TYPES_BROKEN
+#ifndef JPEG_INTERNALS		/* will be defined in jpegint.h */
+struct jvirt_sarray_control { long dummy; };
+struct jvirt_barray_control { long dummy; };
+struct jpeg_comp_master { long dummy; };
+struct jpeg_c_main_controller { long dummy; };
+struct jpeg_c_prep_controller { long dummy; };
+struct jpeg_c_coef_controller { long dummy; };
+struct jpeg_marker_writer { long dummy; };
+struct jpeg_color_converter { long dummy; };
+struct jpeg_downsampler { long dummy; };
+struct jpeg_forward_dct { long dummy; };
+struct jpeg_entropy_encoder { long dummy; };
+struct jpeg_decomp_master { long dummy; };
+struct jpeg_d_main_controller { long dummy; };
+struct jpeg_d_coef_controller { long dummy; };
+struct jpeg_d_post_controller { long dummy; };
+struct jpeg_input_controller { long dummy; };
+struct jpeg_marker_reader { long dummy; };
+struct jpeg_entropy_decoder { long dummy; };
+struct jpeg_inverse_dct { long dummy; };
+struct jpeg_upsampler { long dummy; };
+struct jpeg_color_deconverter { long dummy; };
+struct jpeg_color_quantizer { long dummy; };
+#endif /* JPEG_INTERNALS */
+#endif /* INCOMPLETE_TYPES_BROKEN */
+
+
+/*
+ * The JPEG library modules define JPEG_INTERNALS before including this file.
+ * The internal structure declarations are read only when that is true.
+ * Applications using the library should not include jpegint.h, but may wish
+ * to include jerror.h.
+ */
+
+#ifdef JPEG_INTERNALS
+#include "jpegint.h"		/* fetch private declarations */
+#include "jerror.h"		/* fetch error codes too */
+#endif
+
+#endif /* JPEGLIB_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/lame/lame.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/lame/lame.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/lame/lame.h	(revision 18425)
@@ -0,0 +1,1110 @@
+/*
+ *	Interface to MP3 LAME encoding engine
+ *
+ *	Copyright (c) 1999 Mark Taylor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* $Id: lame.h,v 1.154 2004/04/11 15:39:53 glessard Exp $ */
+
+#ifndef LAME_LAME_H
+#define LAME_LAME_H
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(WIN32)
+#undef CDECL
+#define CDECL _cdecl
+#else
+#define CDECL
+#endif
+
+
+typedef enum vbr_mode_e {
+  vbr_off=0,
+  vbr_mt,               /* obsolete, same as vbr_mtrh */
+  vbr_rh,
+  vbr_abr,
+  vbr_mtrh,
+  vbr_max_indicator,    /* Don't use this! It's used for sanity checks.       */
+  vbr_default=vbr_rh    /* change this to change the default VBR mode of LAME */
+} vbr_mode;
+
+
+/* MPEG modes */
+typedef enum MPEG_mode_e {
+  STEREO = 0,
+  JOINT_STEREO,
+  DUAL_CHANNEL,   /* LAME doesn't supports this! */
+  MONO,
+  NOT_SET,
+  MAX_INDICATOR   /* Don't use this! It's used for sanity checks. */ 
+} MPEG_mode;
+
+/* Padding types */
+typedef enum Padding_type_e {
+  PAD_NO = 0,
+  PAD_ALL,
+  PAD_ADJUST,
+  PAD_MAX_INDICATOR   /* Don't use this! It's used for sanity checks. */
+} Padding_type;
+
+
+
+/*presets*/
+typedef enum preset_mode_e {
+    /*values from 8 to 320 should be reserved for abr bitrates*/
+    /*for abr I'd suggest to directly use the targeted bitrate as a value*/
+    ABR_8 = 8,
+    ABR_320 = 320,
+
+    V9 = 410, /*Vx to match Lame and VBR_xx to match FhG*/
+    VBR_10 = 410,
+    V8 = 420,
+    VBR_20 = 420,
+    V7 = 430,
+    VBR_30 = 430,
+    V6 = 440,
+    VBR_40 = 440,
+    V5 = 450,
+    VBR_50 = 450,
+    V4 = 460,
+    VBR_60 = 460,
+    V3 = 470,
+    VBR_70 = 470,
+    V2 = 480,
+    VBR_80 = 480,
+    V1 = 490,
+    VBR_90 = 490,
+    V0 = 500,
+    VBR_100 = 500,
+
+
+
+    /*still there for compatibility*/
+    R3MIX = 1000,
+    STANDARD = 1001,
+    EXTREME = 1002,
+    INSANE = 1003,
+    STANDARD_FAST = 1004,
+    EXTREME_FAST = 1005,
+    MEDIUM = 1006,
+    MEDIUM_FAST = 1007
+} preset_mode;
+
+
+/*asm optimizations*/
+typedef enum asm_optimizations_e {
+    MMX = 1,
+    AMD_3DNOW = 2,
+    SSE = 3
+} asm_optimizations;
+
+
+/* psychoacoustic model */
+typedef enum Psy_model_e {
+    PSY_GPSYCHO = 1,
+    PSY_NSPSYTUNE = 2
+} Psy_model;
+
+
+struct lame_global_struct;
+typedef struct lame_global_struct lame_global_flags;
+typedef lame_global_flags *lame_t;
+
+
+
+
+/***********************************************************************
+ *
+ *  The LAME API
+ *  These functions should be called, in this order, for each
+ *  MP3 file to be encoded.  See the file "API" for more documentation 
+ *
+ ***********************************************************************/
+
+
+/*
+ * REQUIRED:
+ * initialize the encoder.  sets default for all encoder parameters,
+ * returns NULL if some malloc()'s failed
+ * otherwise returns pointer to structure needed for all future
+ * API calls.
+ */
+lame_global_flags * CDECL lame_init(void);
+/* obsolete version */
+int CDECL lame_init_old(lame_global_flags *);
+
+
+/*
+ * OPTIONAL:
+ * set as needed to override defaults
+ */
+
+/********************************************************************
+ *  input stream description
+ ***********************************************************************/
+/* number of samples.  default = 2^32-1   */
+int CDECL lame_set_num_samples(lame_global_flags *, unsigned long);
+unsigned long CDECL lame_get_num_samples(const lame_global_flags *);
+
+/* input sample rate in Hz.  default = 44100hz */
+int CDECL lame_set_in_samplerate(lame_global_flags *, int);
+int CDECL lame_get_in_samplerate(const lame_global_flags *);
+
+/* number of channels in input stream. default=2  */
+int CDECL lame_set_num_channels(lame_global_flags *, int);
+int CDECL lame_get_num_channels(const lame_global_flags *);
+
+/*
+  scale the input by this amount before encoding.  default=0 (disabled)
+  (not used by decoding routines)
+*/
+int CDECL lame_set_scale(lame_global_flags *, float);
+float CDECL lame_get_scale(const lame_global_flags *);
+    
+/*
+  scale the channel 0 (left) input by this amount before encoding.
+    default=0 (disabled)
+  (not used by decoding routines)
+*/
+int CDECL lame_set_scale_left(lame_global_flags *, float);
+float CDECL lame_get_scale_left(const lame_global_flags *);
+
+/*
+  scale the channel 1 (right) input by this amount before encoding.
+    default=0 (disabled)
+  (not used by decoding routines)
+*/
+int CDECL lame_set_scale_right(lame_global_flags *, float);
+float CDECL lame_get_scale_right(const lame_global_flags *);
+
+/*
+  output sample rate in Hz.  default = 0, which means LAME picks best value
+  based on the amount of compression.  MPEG only allows:
+  MPEG1    32, 44.1,   48khz
+  MPEG2    16, 22.05,  24
+  MPEG2.5   8, 11.025, 12
+  (not used by decoding routines)
+*/
+int CDECL lame_set_out_samplerate(lame_global_flags *, int);
+int CDECL lame_get_out_samplerate(const lame_global_flags *);
+
+
+/********************************************************************
+ *  general control parameters
+ ***********************************************************************/
+/* 1=cause LAME to collect data for an MP3 frame analyzer. default=0 */
+int CDECL lame_set_analysis(lame_global_flags *, int);
+int CDECL lame_get_analysis(const lame_global_flags *);
+
+/*
+  1 = write a Xing VBR header frame.
+  default = 1
+  this variable must have been added by a Hungarian notation Windows programmer :-)
+*/
+int CDECL lame_set_bWriteVbrTag(lame_global_flags *, int);
+int CDECL lame_get_bWriteVbrTag(const lame_global_flags *);
+
+/* 1=decode only.  use lame/mpglib to convert mp3/ogg to wav.  default=0 */
+int CDECL lame_set_decode_only(lame_global_flags *, int);
+int CDECL lame_get_decode_only(const lame_global_flags *);
+
+/* 1=encode a Vorbis .ogg file.  default=0 */
+/* DEPRECATED */
+int CDECL lame_set_ogg(lame_global_flags *, int);
+int CDECL lame_get_ogg(const lame_global_flags *);
+
+/*
+  internal algorithm selection.  True quality is determined by the bitrate
+  but this variable will effect quality by selecting expensive or cheap algorithms.
+  quality=0..9.  0=best (very slow).  9=worst.
+  recommended:  2     near-best quality, not too slow
+                5     good quality, fast
+                7     ok quality, really fast
+*/
+int CDECL lame_set_quality(lame_global_flags *, int);
+int CDECL lame_get_quality(const lame_global_flags *);
+
+/*
+  mode = 0,1,2,3 = stereo, jstereo, dual channel (not supported), mono
+  default: lame picks based on compression ration and input channels
+*/
+int CDECL lame_set_mode(lame_global_flags *, MPEG_mode);
+MPEG_mode CDECL lame_get_mode(const lame_global_flags *);
+
+/*
+  mode_automs.  Use a M/S mode with a switching threshold based on
+  compression ratio
+  DEPRECATED
+*/
+int CDECL lame_set_mode_automs(lame_global_flags *, int);
+int CDECL lame_get_mode_automs(const lame_global_flags *);
+
+/*
+  force_ms.  Force M/S for all frames.  For testing only.
+  default = 0 (disabled)
+*/
+int CDECL lame_set_force_ms(lame_global_flags *, int);
+int CDECL lame_get_force_ms(const lame_global_flags *);
+
+/* use free_format?  default = 0 (disabled) */
+int CDECL lame_set_free_format(lame_global_flags *, int);
+int CDECL lame_get_free_format(const lame_global_flags *);
+
+/* perform ReplayGain analysis?  default = 0 (disabled) */
+int CDECL lame_set_findReplayGain(lame_global_flags *, int);
+int CDECL lame_get_findReplayGain(const lame_global_flags *);
+
+/* decode on the fly. Search for the peak sample. If the ReplayGain
+ * analysis is enabled then perform the analysis on the decoded data
+ * stream. default = 0 (disabled) 
+ * NOTE: if this option is set the build-in decoder should not be used */
+int CDECL lame_set_decode_on_the_fly(lame_global_flags *, int);
+int CDECL lame_get_decode_on_the_fly(const lame_global_flags *);
+
+/* DEPRECATED: now does the same as lame_set_findReplayGain() 
+   default = 0 (disabled) */
+int CDECL lame_set_ReplayGain_input(lame_global_flags *, int);
+int CDECL lame_get_ReplayGain_input(const lame_global_flags *);
+
+/* DEPRECATED: now does the same as 
+   lame_set_decode_on_the_fly() && lame_set_findReplayGain()
+   default = 0 (disabled) */
+int CDECL lame_set_ReplayGain_decode(lame_global_flags *, int);
+int CDECL lame_get_ReplayGain_decode(const lame_global_flags *);
+
+/* DEPRECATED: now does the same as lame_set_decode_on_the_fly() 
+   default = 0 (disabled) */
+int CDECL lame_set_findPeakSample(lame_global_flags *, int);
+int CDECL lame_get_findPeakSample(const lame_global_flags *);
+
+/* counters for gapless encoding */
+int CDECL lame_set_nogap_total(lame_global_flags*, int);
+int CDECL lame_get_nogap_total(const lame_global_flags*);
+
+int CDECL lame_set_nogap_currentindex(lame_global_flags* , int);
+int CDECL lame_get_nogap_currentindex(const lame_global_flags*);
+
+
+/*
+ * OPTIONAL:
+ * Set printf like error/debug/message reporting functions.
+ * The second argument has to be a pointer to a function which looks like
+ *   void my_debugf(const char *format, va_list ap)
+ *   {
+ *       (void) vfprintf(stdout, format, ap);
+ *   }
+ * If you use NULL as the value of the pointer in the set function, the
+ * lame buildin function will be used (prints to stderr).
+ * To quiet any output you have to replace the body of the example function
+ * with just "return;" and use it in the set function.
+ */
+int CDECL lame_set_errorf(lame_global_flags *,
+                          void (*func)(const char *, va_list));
+int CDECL lame_set_debugf(lame_global_flags *,
+                          void (*func)(const char *, va_list));
+int CDECL lame_set_msgf  (lame_global_flags *,
+                          void (*func)(const char *, va_list));
+
+
+
+/* set one of brate compression ratio.  default is compression ratio of 11.  */
+int CDECL lame_set_brate(lame_global_flags *, int);
+int CDECL lame_get_brate(const lame_global_flags *);
+int CDECL lame_set_compression_ratio(lame_global_flags *, float);
+float CDECL lame_get_compression_ratio(const lame_global_flags *);
+
+
+int CDECL lame_set_preset( lame_global_flags*  gfp, int );
+int CDECL lame_set_asm_optimizations( lame_global_flags*  gfp, int, int );
+
+
+
+/********************************************************************
+ *  frame params
+ ***********************************************************************/
+/* mark as copyright.  default=0 */
+int CDECL lame_set_copyright(lame_global_flags *, int);
+int CDECL lame_get_copyright(const lame_global_flags *);
+
+/* mark as original.  default=1 */
+int CDECL lame_set_original(lame_global_flags *, int);
+int CDECL lame_get_original(const lame_global_flags *);
+
+/* error_protection.  Use 2 bytes from each frame for CRC checksum. default=0 */
+int CDECL lame_set_error_protection(lame_global_flags *, int);
+int CDECL lame_get_error_protection(const lame_global_flags *);
+
+/* padding_type. 0=pad no frames  1=pad all frames 2=adjust padding(default) */
+int CDECL lame_set_padding_type(lame_global_flags *, Padding_type);
+Padding_type CDECL lame_get_padding_type(const lame_global_flags *);
+
+/* MP3 'private extension' bit  Meaningless.  default=0 */
+int CDECL lame_set_extension(lame_global_flags *, int);
+int CDECL lame_get_extension(const lame_global_flags *);
+
+/* enforce strict ISO compliance.  default=0 */
+int CDECL lame_set_strict_ISO(lame_global_flags *, int);
+int CDECL lame_get_strict_ISO(const lame_global_flags *);
+ 
+
+/********************************************************************
+ * quantization/noise shaping 
+ ***********************************************************************/
+
+/* disable the bit reservoir. For testing only. default=0 */
+int CDECL lame_set_disable_reservoir(lame_global_flags *, int);
+int CDECL lame_get_disable_reservoir(const lame_global_flags *);
+
+/* select a different "best quantization" function. default=0  */
+int CDECL lame_set_quant_comp(lame_global_flags *, int);
+int CDECL lame_get_quant_comp(const lame_global_flags *);
+int CDECL lame_set_quant_comp_short(lame_global_flags *, int);
+int CDECL lame_get_quant_comp_short(const lame_global_flags *);
+
+int CDECL lame_set_experimentalX(lame_global_flags *, int); /* compatibility*/
+int CDECL lame_get_experimentalX(const lame_global_flags *);
+
+/* another experimental option.  for testing only */
+int CDECL lame_set_experimentalY(lame_global_flags *, int);
+int CDECL lame_get_experimentalY(const lame_global_flags *);
+
+/* another experimental option.  for testing only */
+int CDECL lame_set_experimentalZ(lame_global_flags *, int);
+int CDECL lame_get_experimentalZ(const lame_global_flags *);
+
+/* Naoki's psycho acoustic model.  default=0 */
+int CDECL lame_set_exp_nspsytune(lame_global_flags *, int);
+int CDECL lame_get_exp_nspsytune(const lame_global_flags *);
+
+void CDECL lame_set_msfix(lame_global_flags *, double);
+float CDECL lame_get_msfix(const lame_global_flags *);
+
+int lame_set_exp_nspsytune2_int( lame_global_flags*, int, int);
+float lame_set_exp_nspsytune2_real( lame_global_flags*, int, float);
+void * lame_set_exp_nspsytune2_pointer( lame_global_flags*, int, void *);
+
+/********************************************************************
+ * VBR control
+ ***********************************************************************/
+/* Types of VBR.  default = vbr_off = CBR */
+int CDECL lame_set_VBR(lame_global_flags *, vbr_mode);
+vbr_mode CDECL lame_get_VBR(const lame_global_flags *);
+
+/* VBR quality level.  0=highest  9=lowest  */
+int CDECL lame_set_VBR_q(lame_global_flags *, int);
+int CDECL lame_get_VBR_q(const lame_global_flags *);
+
+/* Ignored except for VBR=vbr_abr (ABR mode) */
+int CDECL lame_set_VBR_mean_bitrate_kbps(lame_global_flags *, int);
+int CDECL lame_get_VBR_mean_bitrate_kbps(const lame_global_flags *);
+
+int CDECL lame_set_VBR_min_bitrate_kbps(lame_global_flags *, int);
+int CDECL lame_get_VBR_min_bitrate_kbps(const lame_global_flags *);
+
+int CDECL lame_set_VBR_max_bitrate_kbps(lame_global_flags *, int);
+int CDECL lame_get_VBR_max_bitrate_kbps(const lame_global_flags *);
+
+/*
+  1=strictly enforce VBR_min_bitrate.  Normally it will be violated for
+  analog silence
+*/
+int CDECL lame_set_VBR_hard_min(lame_global_flags *, int);
+int CDECL lame_get_VBR_hard_min(const lame_global_flags *);
+
+/* for preset */
+int CDECL lame_set_preset_expopts(lame_global_flags *, int);
+
+
+/********************************************************************
+ * Filtering control
+ ***********************************************************************/
+/* freq in Hz to apply lowpass. Default = 0 = lame chooses.  -1 = disabled */
+int CDECL lame_set_lowpassfreq(lame_global_flags *, int);
+int CDECL lame_get_lowpassfreq(const lame_global_flags *);
+/* width of transition band, in Hz.  Default = one polyphase filter band */
+int CDECL lame_set_lowpasswidth(lame_global_flags *, int);
+int CDECL lame_get_lowpasswidth(const lame_global_flags *);
+
+/* freq in Hz to apply highpass. Default = 0 = lame chooses.  -1 = disabled */
+int CDECL lame_set_highpassfreq(lame_global_flags *, int);
+int CDECL lame_get_highpassfreq(const lame_global_flags *);
+/* width of transition band, in Hz.  Default = one polyphase filter band */
+int CDECL lame_set_highpasswidth(lame_global_flags *, int);
+int CDECL lame_get_highpasswidth(const lame_global_flags *);
+
+
+/********************************************************************
+ * psycho acoustics and other arguments which you should not change 
+ * unless you know what you are doing
+ ***********************************************************************/
+
+/* only use ATH for masking */
+int CDECL lame_set_ATHonly(lame_global_flags *, int);
+int CDECL lame_get_ATHonly(const lame_global_flags *);
+
+/* only use ATH for short blocks */
+int CDECL lame_set_ATHshort(lame_global_flags *, int);
+int CDECL lame_get_ATHshort(const lame_global_flags *);
+
+/* disable ATH */
+int CDECL lame_set_noATH(lame_global_flags *, int);
+int CDECL lame_get_noATH(const lame_global_flags *);
+
+/* select ATH formula */
+int CDECL lame_set_ATHtype(lame_global_flags *, int);
+int CDECL lame_get_ATHtype(const lame_global_flags *);
+
+/* lower ATH by this many db */
+int CDECL lame_set_ATHlower(lame_global_flags *, float);
+float CDECL lame_get_ATHlower(const lame_global_flags *);
+
+/* select ATH adaptive adjustment type */
+int CDECL lame_set_athaa_type( lame_global_flags *, int);
+int CDECL lame_get_athaa_type( const lame_global_flags *);
+
+/* select the loudness approximation used by the ATH adaptive auto-leveling  */
+int CDECL lame_set_athaa_loudapprox( lame_global_flags *, int);
+int CDECL lame_get_athaa_loudapprox( const lame_global_flags *);
+
+/* adjust (in dB) the point below which adaptive ATH level adjustment occurs */
+int CDECL lame_set_athaa_sensitivity( lame_global_flags *, float);
+float CDECL lame_get_athaa_sensitivity( const lame_global_flags* );
+
+/* predictability limit (ISO tonality formula) */
+int CDECL lame_set_cwlimit(lame_global_flags *, int);
+int CDECL lame_get_cwlimit(const lame_global_flags *);
+
+/*
+  allow blocktypes to differ between channels?
+  default: 0 for jstereo, 1 for stereo
+*/
+int CDECL lame_set_allow_diff_short(lame_global_flags *, int);
+int CDECL lame_get_allow_diff_short(const lame_global_flags *);
+
+/* use temporal masking effect (default = 1) */
+int CDECL lame_set_useTemporal(lame_global_flags *, int);
+int CDECL lame_get_useTemporal(const lame_global_flags *);
+
+/* use temporal masking effect (default = 1) */
+int CDECL lame_set_interChRatio(lame_global_flags *, float);
+float CDECL lame_get_interChRatio(const lame_global_flags *);
+
+/* disable short blocks */
+int CDECL lame_set_no_short_blocks(lame_global_flags *, int);
+int CDECL lame_get_no_short_blocks(const lame_global_flags *);
+
+/* force short blocks */
+int CDECL lame_set_force_short_blocks(lame_global_flags *, int);
+int CDECL lame_get_force_short_blocks(const lame_global_flags *);
+
+/* Input PCM is emphased PCM (for instance from one of the rarely
+   emphased CDs), it is STRONGLY not recommended to use this, because
+   psycho does not take it into account, and last but not least many decoders
+   ignore these bits */
+int CDECL lame_set_emphasis(lame_global_flags *, int);
+int CDECL lame_get_emphasis(const lame_global_flags *);
+
+
+
+/************************************************************************/
+/* internal variables, cannot be set...                                 */
+/* provided because they may be of use to calling application           */
+/************************************************************************/
+/* version  0=MPEG-2  1=MPEG-1  (2=MPEG-2.5)     */
+int CDECL lame_get_version(const lame_global_flags *);
+
+/* encoder delay   */
+int CDECL lame_get_encoder_delay(const lame_global_flags *);
+
+/*
+  padding appended to the input to make sure decoder can fully decode
+  all input.  Note that this value can only be calculated during the
+  call to lame_encoder_flush().  Before lame_encoder_flush() has
+  been called, the value of encoder_padding = 0.
+*/
+int CDECL lame_get_encoder_padding(const lame_global_flags *);
+
+/* size of MPEG frame */
+int CDECL lame_get_framesize(const lame_global_flags *);
+
+/* number of PCM samples buffered, but not yet encoded to mp3 data. */
+int CDECL lame_get_mf_samples_to_encode( const lame_global_flags*  gfp );
+
+/*
+  size (bytes) of mp3 data buffered, but not yet encoded.
+  this is the number of bytes which would be output by a call to 
+  lame_encode_flush_nogap.  NOTE: lame_encode_flush() will return
+  more bytes than this because it will encode the reamining buffered
+  PCM samples before flushing the mp3 buffers.
+*/
+int CDECL lame_get_size_mp3buffer( const lame_global_flags*  gfp );
+
+/* number of frames encoded so far */
+int CDECL lame_get_frameNum(const lame_global_flags *);
+
+/*
+  lame's estimate of the total number of frames to be encoded
+   only valid if calling program set num_samples
+*/
+int CDECL lame_get_totalframes(const lame_global_flags *);
+
+/* RadioGain value. Multiplied by 10 and rounded to the nearest. */
+int CDECL lame_get_RadioGain(const lame_global_flags *);
+
+/* AudiophileGain value. Multipled by 10 and rounded to the nearest. */
+int CDECL lame_get_AudiophileGain(const lame_global_flags *);
+
+/* the peak sample */
+float CDECL lame_get_PeakSample(const lame_global_flags *);
+
+/* is decoding on the fly performed */
+int CDECL lame_get_decode_on_the_fly(const lame_global_flags *);
+
+/* is ReplayGain analysis performed */
+int CDECL lame_get_findReplayGain(const lame_global_flags *);
+
+/* Gain change required for preventing clipping. The value is correct only if 
+   peak sample searching was enabled. If negative then the waveform 
+   already does not clip. The value is multiplied by 10 and rounded up. */
+int CDECL lame_get_noclipGainChange(const lame_global_flags *);
+
+/* user-specified scale factor required for preventing clipping. Value is 
+   correct only if peak sample searching was enabled and no user-specified
+   scaling was performed. If negative then either the waveform already does
+   not clip or the value cannot be determined */
+float CDECL lame_get_noclipScale(const lame_global_flags *);
+
+
+
+
+
+
+
+/*
+ * REQUIRED:
+ * sets more internal configuration based on data provided above.
+ * returns -1 if something failed.
+ */
+int CDECL lame_init_params(lame_global_flags * const );
+
+
+/*
+ * OPTIONAL:
+ * get the version number, in a string. of the form:  
+ * "3.63 (beta)" or just "3.63". 
+ */
+const char*  CDECL get_lame_version       ( void );
+const char*  CDECL get_lame_short_version ( void );
+const char*  CDECL get_lame_very_short_version ( void );
+const char*  CDECL get_psy_version        ( void );
+const char*  CDECL get_lame_url           ( void );
+
+/*
+ * OPTIONAL:
+ * get the version numbers in numerical form.
+ */
+typedef struct {
+    /* generic LAME version */
+    int major;
+    int minor;
+    int alpha;               /* 0 if not an alpha version                  */
+    int beta;                /* 0 if not a beta version                    */
+
+    /* version of the psy model */
+    int psy_major;
+    int psy_minor;
+    int psy_alpha;           /* 0 if not an alpha version                  */
+    int psy_beta;            /* 0 if not a beta version                    */
+
+    /* compile time features */
+    const char *features;    /* Don't make assumptions about the contents! */
+} lame_version_t;
+void CDECL get_lame_version_numerical ( lame_version_t *const );
+
+
+/*
+ * OPTIONAL:
+ * print internal lame configuration to message handler
+ */
+void CDECL lame_print_config(const lame_global_flags*  gfp);
+
+void CDECL lame_print_internals( const lame_global_flags *gfp);
+
+
+/*
+ * input pcm data, output (maybe) mp3 frames.
+ * This routine handles all buffering, resampling and filtering for you.
+ * 
+ * return code     number of bytes output in mp3buf. Can be 0 
+ *                 -1:  mp3buf was too small
+ *                 -2:  malloc() problem
+ *                 -3:  lame_init_params() not called
+ *                 -4:  psycho acoustic problems 
+ *
+ * The required mp3buf_size can be computed from num_samples, 
+ * samplerate and encoding rate, but here is a worst case estimate:
+ *
+ * mp3buf_size in bytes = 1.25*num_samples + 7200
+ *
+ * I think a tighter bound could be:  (mt, March 2000)
+ * MPEG1:
+ *    num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512
+ * MPEG2:
+ *    num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256
+ *
+ * but test first if you use that!
+ *
+ * set mp3buf_size = 0 and LAME will not check if mp3buf_size is
+ * large enough.
+ *
+ * NOTE:
+ * if gfp->num_channels=2, but gfp->mode = 3 (mono), the L & R channels
+ * will be averaged into the L channel before encoding only the L channel
+ * This will overwrite the data in buffer_l[] and buffer_r[].
+ * 
+*/
+int CDECL lame_encode_buffer (
+        lame_global_flags*  gfp,           /* global context handle         */
+        const short int     buffer_l [],   /* PCM data for left channel     */
+        const short int     buffer_r [],   /* PCM data for right channel    */
+        const int           nsamples,      /* number of samples per channel */
+        unsigned char*      mp3buf,        /* pointer to encoded MP3 stream */
+        const int           mp3buf_size ); /* number of valid octets in this
+                                              stream                        */
+
+/*
+ * as above, but input has L & R channel data interleaved.
+ * NOTE: 
+ * num_samples = number of samples in the L (or R)
+ * channel, not the total number of samples in pcm[]  
+ */
+int CDECL lame_encode_buffer_interleaved(
+        lame_global_flags*  gfp,           /* global context handlei        */
+        short int           pcm[],         /* PCM data for left and right
+                                              channel, interleaved          */
+        int                 num_samples,   /* number of samples per channel,
+                                              _not_ number of samples in
+                                              pcm[]                         */
+        unsigned char*      mp3buf,        /* pointer to encoded MP3 stream */
+        int                 mp3buf_size ); /* number of valid octets in this
+                                              stream                        */
+
+
+/* as lame_encode_buffer, but for 'float's.
+ * !! NOTE: !! data must still be scaled to be in the same range as 
+ * short int, +/- 32768  
+ */
+int CDECL lame_encode_buffer_float(
+        lame_global_flags*  gfp,           /* global context handle         */
+        const float     buffer_l [],       /* PCM data for left channel     */
+        const float     buffer_r [],       /* PCM data for right channel    */
+        const int           nsamples,      /* number of samples per channel */
+        unsigned char*      mp3buf,        /* pointer to encoded MP3 stream */
+        const int           mp3buf_size ); /* number of valid octets in this
+                                              stream                        */
+
+
+/* as lame_encode_buffer, but for long's 
+ * !! NOTE: !! data must still be scaled to be in the same range as 
+ * short int, +/- 32768  
+ *
+ * This scaling was a mistake (doesn't allow one to exploit full
+ * precision of type 'long'.  Use lame_encode_buffer_long2() instead.
+ *
+ */
+int CDECL lame_encode_buffer_long(
+        lame_global_flags*  gfp,           /* global context handle         */
+        const long     buffer_l [],       /* PCM data for left channel     */
+        const long     buffer_r [],       /* PCM data for right channel    */
+        const int           nsamples,      /* number of samples per channel */
+        unsigned char*      mp3buf,        /* pointer to encoded MP3 stream */
+        const int           mp3buf_size ); /* number of valid octets in this
+                                              stream                        */
+
+/* Same as lame_encode_buffer_long(), but with correct scaling. 
+ * !! NOTE: !! data must still be scaled to be in the same range as  
+ * type 'long'.   Data should be in the range:  +/- 2^(8*size(long)-1)
+ *
+ */
+int CDECL lame_encode_buffer_long2(
+        lame_global_flags*  gfp,           /* global context handle         */
+        const long     buffer_l [],       /* PCM data for left channel     */
+        const long     buffer_r [],       /* PCM data for right channel    */
+        const int           nsamples,      /* number of samples per channel */
+        unsigned char*      mp3buf,        /* pointer to encoded MP3 stream */
+        const int           mp3buf_size ); /* number of valid octets in this
+                                              stream                        */
+
+/* as lame_encode_buffer, but for int's 
+ * !! NOTE: !! input should be scaled to the maximum range of 'int'
+ * If int is 4 bytes, then the values should range from
+ * +/- 2147483648.  
+ *
+ * This routine does not (and cannot, without loosing precision) use
+ * the same scaling as the rest of the lame_encode_buffer() routines.
+ * 
+ */   
+int CDECL lame_encode_buffer_int(
+        lame_global_flags*  gfp,           /* global context handle         */
+        const int      buffer_l [],       /* PCM data for left channel     */
+        const int      buffer_r [],       /* PCM data for right channel    */
+        const int           nsamples,      /* number of samples per channel */
+        unsigned char*      mp3buf,        /* pointer to encoded MP3 stream */
+        const int           mp3buf_size ); /* number of valid octets in this
+                                              stream                        */
+
+
+
+
+
+/*
+ * REQUIRED:
+ * lame_encode_flush will flush the intenal PCM buffers, padding with 
+ * 0's to make sure the final frame is complete, and then flush
+ * the internal MP3 buffers, and thus may return a 
+ * final few mp3 frames.  'mp3buf' should be at least 7200 bytes long
+ * to hold all possible emitted data.
+ *
+ * will also write id3v1 tags (if any) into the bitstream       
+ *
+ * return code = number of bytes output to mp3buf. Can be 0
+ */
+int CDECL lame_encode_flush(
+        lame_global_flags *  gfp,    /* global context handle                 */
+        unsigned char*       mp3buf, /* pointer to encoded MP3 stream         */
+        int                  size);  /* number of valid octets in this stream */
+
+/*
+ * OPTIONAL:
+ * lame_encode_flush_nogap will flush the internal mp3 buffers and pad
+ * the last frame with ancillary data so it is a complete mp3 frame.
+ * 
+ * 'mp3buf' should be at least 7200 bytes long
+ * to hold all possible emitted data.
+ *
+ * After a call to this routine, the outputed mp3 data is complete, but
+ * you may continue to encode new PCM samples and write future mp3 data
+ * to a different file.  The two mp3 files will play back with no gaps
+ * if they are concatenated together.
+ *
+ * This routine will NOT write id3v1 tags into the bitstream.
+ *
+ * return code = number of bytes output to mp3buf. Can be 0
+ */
+int CDECL lame_encode_flush_nogap(
+        lame_global_flags *  gfp,    /* global context handle                 */
+        unsigned char*       mp3buf, /* pointer to encoded MP3 stream         */
+        int                  size);  /* number of valid octets in this stream */
+
+/*
+ * OPTIONAL:
+ * Normally, this is called by lame_init_params().  It writes id3v2 and
+ * Xing headers into the front of the bitstream, and sets frame counters
+ * and bitrate histogram data to 0.  You can also call this after 
+ * lame_encode_flush_nogap().  
+ */
+int CDECL lame_init_bitstream(
+        lame_global_flags *  gfp);    /* global context handle                 */
+
+
+
+/*
+ * OPTIONAL:    some simple statistics
+ * a bitrate histogram to visualize the distribution of used frame sizes
+ * a stereo mode histogram to visualize the distribution of used stereo
+ *   modes, useful in joint-stereo mode only
+ *   0: LR    left-right encoded
+ *   1: LR-I  left-right and intensity encoded (currently not supported)
+ *   2: MS    mid-side encoded
+ *   3: MS-I  mid-side and intensity encoded (currently not supported)
+ *
+ * attention: don't call them after lame_encode_finish
+ * suggested: lame_encode_flush -> lame_*_hist -> lame_close
+ */
+
+void CDECL lame_bitrate_hist( 
+        const lame_global_flags *const gfp, 
+              int                      bitrate_count[14] );
+void CDECL lame_bitrate_kbps( 
+        const lame_global_flags *const gfp, 
+              int                      bitrate_kbps [14] );
+void CDECL lame_stereo_mode_hist( 
+        const lame_global_flags *const gfp, 
+              int                      stereo_mode_count[4] );
+
+void CDECL lame_bitrate_stereo_mode_hist ( 
+        const lame_global_flags * const gfp, 
+        int  bitrate_stmode_count [14] [4] );
+
+void CDECL lame_block_type_hist (
+        const lame_global_flags * const gfp, 
+        int btype_count[6] );
+
+void CDECL lame_bitrate_block_type_hist ( 
+        const lame_global_flags * const gfp, 
+        int bitrate_btype_count[14][6] );
+
+
+/*
+ * OPTIONAL:
+ * lame_mp3_tags_fid will append a Xing VBR tag to the mp3 file with file
+ * pointer fid.  These calls perform forward and backwards seeks, so make
+ * sure fid is a real file.  Make sure lame_encode_flush has been called,
+ * and all mp3 data has been written to the file before calling this
+ * function.
+ * NOTE:
+ * if VBR  tags are turned off by the user, or turned off by LAME because
+ * the output is not a regular file, this call does nothing
+*/
+void CDECL lame_mp3_tags_fid(lame_global_flags *,FILE* fid);
+
+
+/*
+ * REQUIRED:
+ * final call to free all remaining buffers
+ */
+int  CDECL lame_close (lame_global_flags *);
+
+/*
+ * OBSOLETE:
+ * lame_encode_finish combines lame_encode_flush() and lame_close() in
+ * one call.  However, once this call is made, the statistics routines
+ * will no longer work because the data will have been cleared, and
+ * lame_mp3_tags_fid() cannot be called to add data to the VBR header  
+ */
+int CDECL lame_encode_finish(
+        lame_global_flags*  gfp,
+        unsigned char*      mp3buf,
+        int                 size );
+
+
+
+
+
+
+
+/*********************************************************************
+ *
+ * decoding 
+ *
+ * a simple interface to mpglib, part of mpg123, is also included if
+ * libmp3lame is compiled with HAVE_MPGLIB
+ *
+ *********************************************************************/
+typedef struct {
+  int header_parsed;   /* 1 if header was parsed and following data was
+                          computed                                       */
+  int stereo;          /* number of channels                             */
+  int samplerate;      /* sample rate                                    */
+  int bitrate;         /* bitrate                                        */
+  int mode;            /* mp3 frame type                                 */
+  int mode_ext;        /* mp3 frame type                                 */
+  int framesize;       /* number of samples per mp3 frame                */
+
+  /* this data is only computed if mpglib detects a Xing VBR header */
+  unsigned long nsamp; /* number of samples in mp3 file.                 */
+  int totalframes;     /* total number of frames in mp3 file             */
+
+  /* this data is not currently computed by the mpglib routines */
+  int framenum;        /* frames decoded counter                         */
+} mp3data_struct;
+
+
+/* required call to initialize decoder 
+ * NOTE: the decoder should not be used when encoding is performed
+ * with decoding on the fly */
+int CDECL lame_decode_init(void);
+
+/*********************************************************************
+ * input 1 mp3 frame, output (maybe) pcm data.  
+ *
+ *  nout = lame_decode(mp3buf,len,pcm_l,pcm_r);
+ *
+ * input:  
+ *    len          :  number of bytes of mp3 data in mp3buf
+ *    mp3buf[len]  :  mp3 data to be decoded
+ *
+ * output:
+ *    nout:  -1    : decoding error
+ *            0    : need more data before we can complete the decode 
+ *           >0    : returned 'nout' samples worth of data in pcm_l,pcm_r
+ *    pcm_l[nout]  : left channel data
+ *    pcm_r[nout]  : right channel data 
+ *    
+ *********************************************************************/
+int CDECL lame_decode(
+        unsigned char *  mp3buf,
+        int              len,
+        short            pcm_l[],
+        short            pcm_r[] );
+
+/* same as lame_decode, and also returns mp3 header data */
+int CDECL lame_decode_headers(
+        unsigned char*   mp3buf,
+        int              len,
+        short            pcm_l[],
+        short            pcm_r[],
+        mp3data_struct*  mp3data );
+
+/* same as lame_decode, but returns at most one frame */
+int CDECL lame_decode1(
+        unsigned char*  mp3buf,
+        int             len,
+        short           pcm_l[],
+        short           pcm_r[] );
+
+/* same as lame_decode1, but returns at most one frame and mp3 header data */
+int CDECL lame_decode1_headers(
+        unsigned char*   mp3buf,
+        int              len,
+        short            pcm_l[],
+        short            pcm_r[],
+        mp3data_struct*  mp3data );
+
+/* same as lame_decode1_headers, but also returns enc_delay and enc_padding
+   from VBR Info tag, (-1 if no info tag was found) */
+int CDECL lame_decode1_headersB(
+        unsigned char*   mp3buf,
+        int              len,
+        short            pcm_l[],
+        short            pcm_r[],
+        mp3data_struct*  mp3data,
+        int              *enc_delay,
+        int              *enc_padding );
+
+
+/* cleanup call to exit decoder  */
+int CDECL lame_decode_exit(void);
+
+
+
+/*********************************************************************
+ *
+ * id3tag stuff
+ *
+ *********************************************************************/
+
+/*
+ * id3tag.h -- Interface to write ID3 version 1 and 2 tags.
+ *
+ * Copyright (C) 2000 Don Melton.
+ *
+ * This 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.
+ *
+ * This 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* utility to obtain alphabetically sorted list of genre names with numbers */
+extern void id3tag_genre_list(
+        void (*handler)(int, const char *, void *),
+        void*  cookie);
+
+extern void id3tag_init   (lame_global_flags *gfp);
+
+/* force addition of version 2 tag */
+extern void id3tag_add_v2   (lame_global_flags *gfp);
+
+/* add only a version 1 tag */
+extern void id3tag_v1_only  (lame_global_flags *gfp);
+
+/* add only a version 2 tag */
+extern void id3tag_v2_only  (lame_global_flags *gfp);
+
+/* pad version 1 tag with spaces instead of nulls */
+extern void id3tag_space_v1 (lame_global_flags *gfp);
+
+/* pad version 2 tag with extra 128 bytes */
+extern void id3tag_pad_v2   (lame_global_flags *gfp);
+
+extern void id3tag_set_title(
+        lame_global_flags*  gfp,
+        const char*         title );
+extern void id3tag_set_artist(
+        lame_global_flags*  gfp,
+        const char*         artist );
+extern void id3tag_set_album(
+        lame_global_flags*  gfp,
+        const char*         album );
+extern void id3tag_set_year(
+        lame_global_flags*  gfp,
+        const char*         year );
+extern void id3tag_set_comment(
+        lame_global_flags*  gfp,
+        const char*         comment );
+extern void id3tag_set_track(
+        lame_global_flags*  gfp,
+        const char*         track );
+
+/* return non-zero result if genre name or number is invalid */
+extern int id3tag_set_genre(
+        lame_global_flags*  gfp,
+        const char*         genre );
+
+/***********************************************************************
+*
+*  list of valid bitrates [kbps] & sample frequencies [Hz].
+*  first index: 0: MPEG-2   values  (sample frequencies 16...24 kHz) 
+*               1: MPEG-1   values  (sample frequencies 32...48 kHz)
+*               2: MPEG-2.5 values  (sample frequencies  8...12 kHz)
+***********************************************************************/
+extern const int      bitrate_table    [3] [16];
+extern const int      samplerate_table [3] [ 4];
+
+
+
+/* maximum size of mp3buffer needed if you encode at most 1152 samples for
+   each call to lame_encode_buffer.  see lame_encode_buffer() below  
+   (LAME_MAXMP3BUFFER is now obsolete)  */
+#define LAME_MAXMP3BUFFER   16384
+
+
+typedef enum {
+    LAME_OKAY             =   0,
+    LAME_NOERROR          =   0,
+    LAME_GENERICERROR     =  -1,
+    LAME_NOMEM            = -10,
+    LAME_BADBITRATE       = -11,
+    LAME_BADSAMPFREQ      = -12,
+    LAME_INTERNALERROR    = -13,
+    
+    FRONTEND_READERROR    = -80,
+    FRONTEND_WRITEERROR   = -81,
+    FRONTEND_FILETOOLARGE = -82
+    
+} lame_errorcodes_t;
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* LAME_LAME_H */
+
Index: extensions/gsdl-video/trunk/installed/cmdline/include/mp4.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/mp4.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/mp4.h	(revision 18425)
@@ -0,0 +1,1146 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2001 - 2004.  All Rights Reserved.
+ * 
+ * 3GPP features implementation is based on 3GPP's TS26.234-v5.60,
+ * and was contributed by Ximpo Group Ltd.
+ *
+ * Portions created by Ximpo Group Ltd. are
+ * Copyright (C) Ximpo Group Ltd. 2003, 2004.  All Rights Reserved.
+ *
+ * Contributor(s): 
+ *		Dave Mackie			dmackie@cisco.com
+ *		Alix Marchandise-Franquet	alix@cisco.com
+ *              Ximpo Group Ltd.                mp4v2@ximpo.com
+ */
+
+#ifndef __MP4_INCLUDED__
+#define __MP4_INCLUDED__
+
+/* include system and project specific headers */
+#include "mpeg4ip.h"
+
+#include <math.h>	/* to define float HUGE_VAL and/or NAN */
+#ifndef NAN
+#define NAN HUGE_VAL
+#endif
+
+#ifdef __cplusplus
+/* exploit C++ ability of default values for function parameters */
+#define DEFAULT(x)	=x
+#else
+#define DEFAULT(x)
+#endif
+
+/* MP4 API types */
+typedef void*		MP4FileHandle;
+typedef u_int32_t	MP4TrackId;
+typedef u_int32_t	MP4SampleId;
+typedef u_int64_t	MP4Timestamp;
+typedef u_int64_t	MP4Duration;
+typedef u_int32_t	MP4EditId;
+
+/* Invalid values for API types */
+#define MP4_INVALID_FILE_HANDLE	((MP4FileHandle)NULL)
+#define MP4_INVALID_TRACK_ID	((MP4TrackId)0)
+#define MP4_INVALID_SAMPLE_ID	((MP4SampleId)0)
+#define MP4_INVALID_TIMESTAMP	((MP4Timestamp)-1)
+#define MP4_INVALID_DURATION	((MP4Duration)-1)
+#define MP4_INVALID_EDIT_ID		((MP4EditId)0)
+
+/* Macros to test for API type validity */
+#define MP4_IS_VALID_FILE_HANDLE(x)	((x) != MP4_INVALID_FILE_HANDLE) 
+#define MP4_IS_VALID_TRACK_ID(x)	((x) != MP4_INVALID_TRACK_ID) 
+#define MP4_IS_VALID_SAMPLE_ID(x)	((x) != MP4_INVALID_SAMPLE_ID) 
+#define MP4_IS_VALID_TIMESTAMP(x)	((x) != MP4_INVALID_TIMESTAMP) 
+#define MP4_IS_VALID_DURATION(x)	((x) != MP4_INVALID_DURATION) 
+#define MP4_IS_VALID_EDIT_ID(x)		((x) != MP4_INVALID_EDIT_ID) 
+
+/* MP4 verbosity levels - e.g. MP4SetVerbosity() */
+#define MP4_DETAILS_ALL				0xFFFFFFFF
+#define MP4_DETAILS_ERROR			0x00000001
+#define MP4_DETAILS_WARNING			0x00000002
+#define MP4_DETAILS_READ			0x00000004
+#define MP4_DETAILS_WRITE			0x00000008
+#define MP4_DETAILS_FIND			0x00000010
+#define MP4_DETAILS_TABLE			0x00000020
+#define MP4_DETAILS_SAMPLE			0x00000040
+#define MP4_DETAILS_HINT			0x00000080
+#define MP4_DETAILS_ISMA			0x00000100
+#define MP4_DETAILS_EDIT			0x00000200
+
+#define MP4_DETAILS_READ_ALL		\
+	(MP4_DETAILS_READ | MP4_DETAILS_TABLE | MP4_DETAILS_SAMPLE)
+#define MP4_DETAILS_WRITE_ALL		\
+	(MP4_DETAILS_WRITE | MP4_DETAILS_TABLE | MP4_DETAILS_SAMPLE)
+
+/*
+ * MP4 Known track type names - e.g. MP4GetNumberOfTracks(type) 
+ *
+ * Note this first group of track types should be created 
+ * via the MP4Add<Type>Track() functions, and not MP4AddTrack(type)
+ */
+#define MP4_OD_TRACK_TYPE		"odsm"
+#define MP4_SCENE_TRACK_TYPE	"sdsm"
+#define MP4_AUDIO_TRACK_TYPE	"soun"
+#define MP4_VIDEO_TRACK_TYPE	"vide"
+#define MP4_HINT_TRACK_TYPE		"hint"
+/*
+ * This second set of track types should be created 
+ * via MP4AddSystemsTrack(type)
+ */
+#define MP4_CLOCK_TRACK_TYPE	"crsm"
+#define MP4_MPEG7_TRACK_TYPE	"m7sm"
+#define MP4_OCI_TRACK_TYPE		"ocsm"
+#define MP4_IPMP_TRACK_TYPE		"ipsm"
+#define MP4_MPEGJ_TRACK_TYPE	"mjsm"
+
+#define MP4_IS_VIDEO_TRACK_TYPE(type) \
+	(!strcasecmp(type, MP4_VIDEO_TRACK_TYPE))
+
+#define MP4_IS_AUDIO_TRACK_TYPE(type) \
+	(!strcasecmp(type, MP4_AUDIO_TRACK_TYPE))
+
+#define MP4_IS_OD_TRACK_TYPE(type) \
+	(!strcasecmp(type, MP4_OD_TRACK_TYPE))
+
+#define MP4_IS_SCENE_TRACK_TYPE(type) \
+	(!strcasecmp(type, MP4_SCENE_TRACK_TYPE))
+
+#define MP4_IS_HINT_TRACK_TYPE(type) \
+	(!strcasecmp(type, MP4_HINT_TRACK_TYPE))
+
+#define MP4_IS_SYSTEMS_TRACK_TYPE(type) \
+	(!strcasecmp(type, MP4_CLOCK_TRACK_TYPE) \
+	|| !strcasecmp(type, MP4_MPEG7_TRACK_TYPE) \
+	|| !strcasecmp(type, MP4_OCI_TRACK_TYPE) \
+	|| !strcasecmp(type, MP4_IPMP_TRACK_TYPE) \
+	|| !strcasecmp(type, MP4_MPEGJ_TRACK_TYPE))
+
+/* MP4 Audio track types - see MP4AddAudioTrack()*/
+#define MP4_INVALID_AUDIO_TYPE			0x00
+#define MP4_MPEG1_AUDIO_TYPE			0x6B
+#define MP4_MPEG2_AUDIO_TYPE			0x69
+#define MP4_MP3_AUDIO_TYPE				MP4_MPEG2_AUDIO_TYPE
+#define MP4_MPEG2_AAC_MAIN_AUDIO_TYPE	0x66
+#define MP4_MPEG2_AAC_LC_AUDIO_TYPE		0x67
+#define MP4_MPEG2_AAC_SSR_AUDIO_TYPE	0x68
+#define MP4_MPEG2_AAC_AUDIO_TYPE		MP4_MPEG2_AAC_MAIN_AUDIO_TYPE
+#define MP4_MPEG4_AUDIO_TYPE			0x40
+#define MP4_PRIVATE_AUDIO_TYPE			0xC0
+#define MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE	0xE0	/* a private definition */
+#define MP4_VORBIS_AUDIO_TYPE			0xE1	/* a private definition */
+#define MP4_AC3_AUDIO_TYPE				0xE2	/* a private definition */
+#define MP4_ALAW_AUDIO_TYPE				0xE3	/* a private definition */
+#define MP4_ULAW_AUDIO_TYPE				0xE4	/* a private definition */
+#define MP4_G723_AUDIO_TYPE                             0xE5    /* a private definition */
+#define MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE         0xE6 /* a private definition */
+
+/* MP4 MPEG-4 Audio types from 14496-3 Table 1.5.1 */
+#define MP4_MPEG4_INVALID_AUDIO_TYPE		0
+#define MP4_MPEG4_AAC_MAIN_AUDIO_TYPE		1
+#define MP4_MPEG4_AAC_LC_AUDIO_TYPE			2
+#define MP4_MPEG4_AAC_SSR_AUDIO_TYPE		3
+#define MP4_MPEG4_AAC_LTP_AUDIO_TYPE		4
+#define MP4_MPEG4_AAC_SCALABLE_AUDIO_TYPE	6
+#define MP4_MPEG4_CELP_AUDIO_TYPE			8
+#define MP4_MPEG4_HVXC_AUDIO_TYPE			9
+#define MP4_MPEG4_TTSI_AUDIO_TYPE			12
+#define MP4_MPEG4_MAIN_SYNTHETIC_AUDIO_TYPE	13
+#define MP4_MPEG4_WAVETABLE_AUDIO_TYPE		14
+#define MP4_MPEG4_MIDI_AUDIO_TYPE			15
+#define MP4_MPEG4_ALGORITHMIC_FX_AUDIO_TYPE	16
+
+/* MP4 Audio type utilities following common usage */
+#define MP4_IS_MP3_AUDIO_TYPE(type) \
+	((type) == MP4_MPEG1_AUDIO_TYPE || (type) == MP4_MPEG2_AUDIO_TYPE) 
+
+#define MP4_IS_MPEG2_AAC_AUDIO_TYPE(type) \
+	(((type) >= MP4_MPEG2_AAC_MAIN_AUDIO_TYPE \
+		&& (type) <= MP4_MPEG2_AAC_SSR_AUDIO_TYPE))
+
+#define MP4_IS_MPEG4_AAC_AUDIO_TYPE(mpeg4Type) \
+	(((mpeg4Type) >= MP4_MPEG4_AAC_MAIN_AUDIO_TYPE \
+		&& (mpeg4Type) <= MP4_MPEG4_AAC_LTP_AUDIO_TYPE) \
+	  || (mpeg4Type) == MP4_MPEG4_AAC_SCALABLE_AUDIO_TYPE \
+          || (mpeg4Type) == 17)
+
+#define MP4_IS_AAC_AUDIO_TYPE(type) \
+	(MP4_IS_MPEG2_AAC_AUDIO_TYPE(type) \
+	|| (type) == MP4_MPEG4_AUDIO_TYPE)
+
+/* MP4 Video track types - see MP4AddVideoTrack() */
+#define MP4_INVALID_VIDEO_TYPE			0x00
+#define MP4_MPEG1_VIDEO_TYPE			0x6A
+#define MP4_MPEG2_SIMPLE_VIDEO_TYPE		0x60
+#define MP4_MPEG2_MAIN_VIDEO_TYPE		0x61
+#define MP4_MPEG2_SNR_VIDEO_TYPE		0x62
+#define MP4_MPEG2_SPATIAL_VIDEO_TYPE	0x63
+#define MP4_MPEG2_HIGH_VIDEO_TYPE		0x64
+#define MP4_MPEG2_442_VIDEO_TYPE		0x65
+#define MP4_MPEG2_VIDEO_TYPE			MP4_MPEG2_MAIN_VIDEO_TYPE
+#define MP4_MPEG4_VIDEO_TYPE			0x20
+#define MP4_JPEG_VIDEO_TYPE				0x6C
+#define MP4_PRIVATE_VIDEO_TYPE			0xD0
+#define MP4_YUV12_VIDEO_TYPE			0xF0	/* a private definition */
+#define MP4_H264_VIDEO_TYPE				0xF1	/* a private definition */
+#define MP4_H263_VIDEO_TYPE				0xF2	/* a private definition */
+#define MP4_H261_VIDEO_TYPE				0xF3	/* a private definition */
+
+/* MP4 Video type utilities */
+#define MP4_IS_MPEG1_VIDEO_TYPE(type) \
+	((type) == MP4_MPEG1_VIDEO_TYPE)
+
+#define MP4_IS_MPEG2_VIDEO_TYPE(type) \
+	(((type) >= MP4_MPEG2_SIMPLE_VIDEO_TYPE \
+		&& (type) <= MP4_MPEG2_442_VIDEO_TYPE) \
+	  || MP4_IS_MPEG1_VIDEO_TYPE(type))
+
+#define MP4_IS_MPEG4_VIDEO_TYPE(type) \
+	((type) == MP4_MPEG4_VIDEO_TYPE)
+
+/* Mpeg4 Visual Profile Defines - ISO/IEC 14496-2:2001/Amd.2:2002(E) */
+#define MPEG4_SP_L1 (0x1)
+#define MPEG4_SP_L2 (0x2)
+#define MPEG4_SP_L3 (0x3)
+#define MPEG4_SP_L0 (0x8)
+#define MPEG4_SSP_L1 (0x11)
+#define MPEG4_SSP_L2 (0x12)
+#define MPEG4_CP_L1 (0x21)
+#define MPEG4_CP_L2 (0x22)
+#define MPEG4_MP_L2 (0x32)
+#define MPEG4_MP_L3 (0x33)
+#define MPEG4_MP_L4 (0x34)
+#define MPEG4_NBP_L2 (0x42)
+#define MPEG4_STP_L1 (0x51)
+#define MPEG4_SFAP_L1 (0x61)
+#define MPEG4_SFAP_L2 (0x62)
+#define MPEG4_SFBAP_L1 (0x63)
+#define MPEG4_SFBAP_L2 (0x64)
+#define MPEG4_BATP_L1 (0x71)
+#define MPEG4_BATP_L2 (0x72)
+#define MPEG4_HP_L1 (0x81)
+#define MPEG4_HP_L2 (0x82)
+#define MPEG4_ARTSP_L1 (0x91)
+#define MPEG4_ARTSP_L2 (0x92)
+#define MPEG4_ARTSP_L3 (0x93)
+#define MPEG4_ARTSP_L4 (0x94)
+#define MPEG4_CSP_L1 (0xa1)
+#define MPEG4_CSP_L2 (0xa2)
+#define MPEG4_CSP_L3 (0xa3)
+#define MPEG4_ACEP_L1 (0xb1)
+#define MPEG4_ACEP_L2 (0xb2)
+#define MPEG4_ACEP_L3 (0xb3)
+#define MPEG4_ACEP_L4 (0xb4)
+#define MPEG4_ACP_L1 (0xc1)
+#define MPEG4_ACP_L2 (0xc2)
+#define MPEG4_AST_L1 (0xd1)
+#define MPEG4_AST_L2 (0xd2)
+#define MPEG4_AST_L3 (0xd3)
+#define MPEG4_S_STUDIO_P_L1 (0xe1)
+#define MPEG4_S_STUDIO_P_L2 (0xe2)
+#define MPEG4_S_STUDIO_P_L3 (0xe3)
+#define MPEG4_S_STUDIO_P_L4 (0xe4)
+#define MPEG4_C_STUDIO_P_L1 (0xe5)
+#define MPEG4_C_STUDIO_P_L2 (0xe6)
+#define MPEG4_C_STUDIO_P_L3 (0xe7)
+#define MPEG4_C_STUDIO_P_L4 (0xe8)
+#define MPEG4_ASP_L0 (0xF0)
+#define MPEG4_ASP_L1 (0xF1)
+#define MPEG4_ASP_L2 (0xF2)
+#define MPEG4_ASP_L3 (0xF3)
+#define MPEG4_ASP_L4 (0xF4)
+#define MPEG4_ASP_L5 (0xF5)
+#define MPEG4_ASP_L3B (0xF7)
+#define MPEG4_FGSP_L0 (0xf8)
+#define MPEG4_FGSP_L1 (0xf9)
+#define MPEG4_FGSP_L2 (0xfa)
+#define MPEG4_FGSP_L3 (0xfb)
+#define MPEG4_FGSP_L4 (0xfc)
+#define MPEG4_FGSP_L5 (0xfd)
+
+/* MP4 API declarations */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* file operations */
+#define MP4_CREATE_64BIT_DATA (0x01)
+#define MP4_CREATE_64BIT_TIME (0x02) // Quicktime is not compatible with this
+#define MP4_CREATE_64BIT (MP4_CREATE_64BIT_DATA | MP4_CREATE_64BIT_TIME)
+#define MP4_CREATE_EXTENSIBLE_FORMAT (0x04)
+
+MP4FileHandle MP4Create(
+	const char* fileName, 
+	u_int32_t verbosity DEFAULT(0),
+	u_int32_t flags DEFAULT(0));
+
+MP4FileHandle MP4CreateEx(
+		const char* fileName,
+		u_int32_t verbosity DEFAULT(0),
+		u_int32_t flags  DEFAULT(0),
+		char* majorBrand DEFAULT(0),
+		u_int32_t minorVersion DEFAULT(0),
+		char** supportedBrands DEFAULT(0),
+		u_int32_t supportedBrandsCount DEFAULT(0));
+
+MP4FileHandle MP4Modify(
+	const char* fileName, 
+	u_int32_t verbosity DEFAULT(0),
+	u_int32_t flags DEFAULT(0));
+
+MP4FileHandle MP4Read(
+	const char* fileName, 
+	u_int32_t verbosity DEFAULT(0));
+
+bool MP4Close(
+	MP4FileHandle hFile);
+
+bool MP4Optimize(
+	const char* existingFileName, 
+	const char* newFileName DEFAULT(NULL), 
+	u_int32_t verbosity DEFAULT(0));
+
+bool MP4Dump(
+	MP4FileHandle hFile, 
+	FILE* pDumpFile DEFAULT(NULL), 
+	bool dumpImplicits DEFAULT(0));
+
+char* MP4Info(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID));
+
+char* MP4FileInfo(
+	const char* fileName,
+	MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID));
+
+/* file properties */
+
+/* specific file properties */
+
+u_int32_t MP4GetVerbosity(MP4FileHandle hFile);
+
+bool MP4SetVerbosity(MP4FileHandle hFile, u_int32_t verbosity);
+
+MP4Duration MP4GetDuration(MP4FileHandle hFile);
+
+u_int32_t MP4GetTimeScale(MP4FileHandle hFile);
+
+bool MP4SetTimeScale(MP4FileHandle hFile, u_int32_t value);
+
+u_int8_t MP4GetODProfileLevel(MP4FileHandle hFile);
+
+bool MP4SetODProfileLevel(MP4FileHandle hFile, u_int8_t value);
+
+u_int8_t MP4GetSceneProfileLevel(MP4FileHandle hFile);
+
+bool MP4SetSceneProfileLevel(MP4FileHandle hFile, u_int8_t value);
+
+u_int8_t MP4GetVideoProfileLevel(MP4FileHandle hFile);
+
+bool MP4SetVideoProfileLevel(MP4FileHandle hFile, u_int8_t value);
+
+u_int8_t MP4GetAudioProfileLevel(MP4FileHandle hFile);
+
+bool MP4SetAudioProfileLevel(MP4FileHandle hFile, u_int8_t value);
+
+u_int8_t MP4GetGraphicsProfileLevel(MP4FileHandle hFile);
+
+bool MP4SetGraphicsProfileLevel(MP4FileHandle hFile, u_int8_t value);
+
+/* generic file properties */
+
+u_int64_t MP4GetIntegerProperty(
+	MP4FileHandle hFile, 
+	const char* propName);
+
+bool MP4HaveTrackIntegerProperty(
+	MP4FileHandle hFile, MP4TrackId trackId, 
+	const char* propName);
+
+float MP4GetFloatProperty(
+	MP4FileHandle hFile, 
+	const char* propName);
+
+const char* MP4GetStringProperty(
+	MP4FileHandle hFile, 
+	const char* propName);
+
+void MP4GetBytesProperty(
+	MP4FileHandle hFile, 
+	const char* propName,
+	u_int8_t** ppValue, 
+	u_int32_t* pValueSize);
+
+bool MP4SetIntegerProperty(
+	MP4FileHandle hFile, 
+	const char* propName, 
+	int64_t value);
+
+bool MP4SetFloatProperty(
+	MP4FileHandle hFile, 
+	const char* propName, 
+	float value);
+
+bool MP4SetStringProperty(
+	MP4FileHandle hFile, const char* propName, const char* value);
+
+bool MP4SetBytesProperty(
+	MP4FileHandle hFile, const char* propName, 
+	const u_int8_t* pValue, u_int32_t valueSize);
+
+/* track operations */
+
+MP4TrackId MP4AddTrack(
+	MP4FileHandle hFile, 
+	const char* type);
+
+MP4TrackId MP4AddSystemsTrack(
+	MP4FileHandle hFile, 
+	const char* type);
+
+MP4TrackId MP4AddODTrack(
+	MP4FileHandle hFile);
+
+MP4TrackId MP4AddSceneTrack(
+	MP4FileHandle hFile);
+
+MP4TrackId MP4AddAudioTrack(
+	MP4FileHandle hFile, 
+	u_int32_t timeScale, 
+	MP4Duration sampleDuration,
+	u_int8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE));
+
+typedef struct mp4v2_ismacryp_session_params {
+  u_int32_t  scheme_type;
+  u_int16_t  scheme_version;
+  u_int8_t  key_ind_len;
+  u_int8_t  iv_len;
+  u_int8_t  selective_enc;
+  char      *kms_uri;
+} mp4v2_ismacrypParams;
+
+
+MP4TrackId MP4AddEncAudioTrack(
+	MP4FileHandle hFile, 
+	u_int32_t timeScale, 
+	MP4Duration sampleDuration,
+        mp4v2_ismacrypParams *icPp,
+	u_int8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE));
+MP4TrackId MP4AddAmrAudioTrack(
+		MP4FileHandle hFile,
+		u_int32_t timeScale,
+		u_int16_t modeSet,
+		u_int8_t modeChangePeriod,
+		u_int8_t framesPerSample,
+		bool isAmrWB);
+
+void MP4SetAmrVendor(
+		MP4FileHandle hFile,
+		MP4TrackId trackId,
+		u_int32_t vendor);
+
+void MP4SetAmrDecoderVersion(
+		MP4FileHandle hFile,
+		MP4TrackId trackId,
+		u_int8_t decoderVersion);
+
+void MP4SetAmrModeSet(
+		MP4FileHandle hFile,
+		MP4TrackId trackId,
+		u_int16_t modeSet);
+
+MP4TrackId MP4AddVideoTrack(
+	MP4FileHandle hFile, 
+	u_int32_t timeScale, 
+	MP4Duration sampleDuration,
+	u_int16_t width, 
+	u_int16_t height,
+	u_int8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE));
+
+MP4TrackId MP4AddEncVideoTrack(
+	MP4FileHandle hFile, 
+	u_int32_t timeScale, 
+	MP4Duration sampleDuration,
+	u_int16_t width, 
+	u_int16_t height,
+        mp4v2_ismacrypParams *icPp,
+	u_int8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE));
+
+void MP4SetH263Vendor(
+		MP4FileHandle hFile,
+		MP4TrackId trackId,
+		u_int32_t vendor);
+
+void  MP4SetH263DecoderVersion(
+		MP4FileHandle hFile,
+		MP4TrackId trackId,
+		u_int8_t decoderVersion);
+
+void MP4SetH263Bitrates(
+		MP4FileHandle hFile,
+		MP4TrackId trackId,
+		u_int32_t avgBitrate,
+		u_int32_t maxBitrate);
+
+MP4TrackId MP4AddH263VideoTrack(
+		MP4FileHandle hFile,
+		u_int32_t timeScale,
+		MP4Duration sampleDuration,
+		u_int16_t width,
+		u_int16_t height,
+		u_int8_t h263Level,
+		u_int8_t h263Profile,
+		u_int32_t avgBitrate,
+		u_int32_t maxBitrate);
+
+MP4TrackId MP4AddHintTrack(
+	MP4FileHandle hFile, 
+	MP4TrackId refTrackId);
+
+MP4TrackId MP4CloneTrack(
+	MP4FileHandle srcFile, 
+	MP4TrackId srcTrackId,
+	MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE),
+	MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID));
+
+MP4TrackId MP4EncAndCloneTrack(
+        MP4FileHandle srcFile,
+        MP4TrackId srcTrackId,
+        mp4v2_ismacrypParams *icPp,
+        MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE),
+        MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID));
+
+MP4TrackId MP4CopyTrack(
+	MP4FileHandle srcFile, 
+	MP4TrackId srcTrackId,
+	MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), 
+	bool applyEdits DEFAULT(false),
+	MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID));
+
+typedef u_int32_t (*encryptFunc_t)(u_int32_t, u_int32_t, u_int8_t*, u_int32_t*, u_int8_t **);
+
+MP4TrackId MP4EncAndCopyTrack(
+	MP4FileHandle srcFile, 
+	MP4TrackId srcTrackId,
+        mp4v2_ismacrypParams *icPp,
+        encryptFunc_t encfcnp,
+        u_int32_t encfcnparam1,
+	MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE),
+	bool applyEdits DEFAULT(false),
+	MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID));
+
+bool MP4DeleteTrack(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+u_int32_t MP4GetNumberOfTracks(
+	MP4FileHandle hFile, 
+	const char* type DEFAULT(NULL),
+	u_int8_t subType DEFAULT(0));
+
+MP4TrackId MP4FindTrackId(
+	MP4FileHandle hFile, 
+	u_int16_t index, 
+	const char* type DEFAULT(NULL),
+	u_int8_t subType DEFAULT(0));
+
+u_int16_t MP4FindTrackIndex(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+/* track properties */
+
+/* specific track properties */
+
+const char* MP4GetTrackType(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+MP4Duration MP4GetTrackDuration(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+u_int32_t MP4GetTrackTimeScale(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+bool MP4SetTrackTimeScale(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId, 
+	u_int32_t value);
+
+// Should not be used, replace with MP4GetTrackEsdsObjectTypeId
+u_int8_t MP4GetTrackAudioType(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+u_int8_t MP4GetTrackAudioMpeg4Type(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+// Should not be used, replace with MP4GetTrackEsdsObjectTypeId
+u_int8_t MP4GetTrackVideoType(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+u_int8_t MP4GetTrackEsdsObjectTypeId(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+/* returns MP4_INVALID_DURATION if track samples do not have a fixed duration */
+MP4Duration MP4GetTrackFixedSampleDuration(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+u_int32_t MP4GetTrackBitRate(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+bool MP4GetTrackESConfiguration(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId, 
+	u_int8_t** ppConfig, 
+	u_int32_t* pConfigSize);
+
+bool MP4SetTrackESConfiguration(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId, 
+	const u_int8_t* pConfig, 
+	u_int32_t configSize);
+
+MP4SampleId MP4GetTrackNumberOfSamples(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+u_int16_t MP4GetTrackVideoWidth(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+u_int16_t MP4GetTrackVideoHeight(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+float MP4GetTrackVideoFrameRate(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId);
+
+bool MP4IsIsmaCrypMediaTrack(
+        MP4FileHandle hFile,
+        MP4TrackId trackId);
+
+/* generic track properties */
+
+u_int64_t MP4GetTrackIntegerProperty(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId, 
+	const char* propName);
+
+float MP4GetTrackFloatProperty(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId, 
+	const char* propName);
+
+const char* MP4GetTrackStringProperty(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId, 
+	const char* propName);
+
+void MP4GetTrackBytesProperty(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId, 
+	const char* propName,
+	u_int8_t** ppValue, 
+	u_int32_t* pValueSize);
+
+bool MP4SetTrackIntegerProperty(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId, 
+	const char* propName, 
+	int64_t value);
+
+bool MP4SetTrackFloatProperty(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId, 
+	const char* propName, 
+	float value);
+
+bool MP4SetTrackStringProperty(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId, 
+	const char* propName, 
+	const char* value);
+
+bool MP4SetTrackBytesProperty(
+	MP4FileHandle hFile, 
+	MP4TrackId trackId, 
+	const char* propName, 
+	const u_int8_t* pValue, 
+	u_int32_t valueSize);
+
+/* sample operations */
+
+bool MP4ReadSample(
+	/* input parameters */
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4SampleId sampleId,
+	/* input/output parameters */
+	u_int8_t** ppBytes, 
+	u_int32_t* pNumBytes, 
+	/* output parameters */
+	MP4Timestamp* pStartTime DEFAULT(NULL), 
+	MP4Duration* pDuration DEFAULT(NULL),
+	MP4Duration* pRenderingOffset DEFAULT(NULL), 
+	bool* pIsSyncSample DEFAULT(NULL));
+
+/* uses (unedited) time to specify sample instead of sample id */
+bool MP4ReadSampleFromTime(
+	/* input parameters */
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4Timestamp when,
+	/* input/output parameters */
+	u_int8_t** ppBytes, 
+	u_int32_t* pNumBytes, 
+	/* output parameters */
+	MP4Timestamp* pStartTime DEFAULT(NULL), 
+	MP4Duration* pDuration DEFAULT(NULL),
+	MP4Duration* pRenderingOffset DEFAULT(NULL), 
+	bool* pIsSyncSample DEFAULT(NULL));
+
+bool MP4WriteSample(
+	MP4FileHandle hFile,
+	MP4TrackId trackId,
+	const u_int8_t* pBytes, 
+	u_int32_t numBytes,
+	MP4Duration duration DEFAULT(MP4_INVALID_DURATION),
+	MP4Duration renderingOffset DEFAULT(0), 
+	bool isSyncSample DEFAULT(true));
+
+bool MP4CopySample(
+	MP4FileHandle srcFile,
+	MP4TrackId srcTrackId, 
+	MP4SampleId srcSampleId,
+	MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE),
+	MP4TrackId dstTrackId DEFAULT(MP4_INVALID_TRACK_ID),
+	MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION));
+
+bool MP4EncAndCopySample(
+	MP4FileHandle srcFile,
+	MP4TrackId srcTrackId, 
+	MP4SampleId srcSampleId,
+        encryptFunc_t encfcnp,
+        u_int32_t encfcnparam1,
+	MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE),
+	MP4TrackId dstTrackId DEFAULT(MP4_INVALID_TRACK_ID),
+	MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION));
+
+/* Note this function is not yet implemented */
+bool MP4ReferenceSample(
+	MP4FileHandle srcFile,
+	MP4TrackId srcTrackId, 
+	MP4SampleId srcSampleId,
+	MP4FileHandle dstFile,
+	MP4TrackId dstTrackId,
+	MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION));
+
+u_int32_t MP4GetSampleSize(
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4SampleId sampleId);
+
+u_int32_t MP4GetTrackMaxSampleSize(
+	MP4FileHandle hFile,
+	MP4TrackId trackId); 
+
+MP4SampleId MP4GetSampleIdFromTime(
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4Timestamp when, 
+	bool wantSyncSample DEFAULT(false));
+
+MP4Timestamp MP4GetSampleTime(
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4SampleId sampleId);
+
+MP4Duration MP4GetSampleDuration(
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4SampleId sampleId);
+
+MP4Duration MP4GetSampleRenderingOffset(
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4SampleId sampleId);
+
+bool MP4SetSampleRenderingOffset(
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4SampleId sampleId,
+	MP4Duration renderingOffset);
+
+int8_t MP4GetSampleSync(
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4SampleId sampleId);
+
+/* rtp hint track operations */
+
+bool MP4GetHintTrackRtpPayload(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	char** ppPayloadName DEFAULT(NULL),
+	u_int8_t* pPayloadNumber DEFAULT(NULL),
+	u_int16_t* pMaxPayloadSize DEFAULT(NULL),
+	char **ppEncodingParams DEFAULT(NULL));
+
+#define MP4_SET_DYNAMIC_PAYLOAD 0xff
+
+bool MP4SetHintTrackRtpPayload(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	const char* pPayloadName,
+	u_int8_t* pPayloadNumber,
+	u_int16_t maxPayloadSize DEFAULT(0),
+	const char *encode_params DEFAULT(NULL),
+	bool include_rtp_map DEFAULT(true),
+	bool include_mpeg4_esid DEFAULT(true));
+
+const char* MP4GetSessionSdp(
+	MP4FileHandle hFile);
+
+bool MP4SetSessionSdp(
+	MP4FileHandle hFile,
+	const char* sdpString);
+
+bool MP4AppendSessionSdp(
+	MP4FileHandle hFile,
+	const char* sdpString);
+
+const char* MP4GetHintTrackSdp(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId);
+
+bool MP4SetHintTrackSdp(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	const char* sdpString);
+
+bool MP4AppendHintTrackSdp(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	const char* sdpString);
+
+MP4TrackId MP4GetHintTrackReferenceTrackId(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId);
+
+bool MP4ReadRtpHint(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	MP4SampleId hintSampleId,
+	u_int16_t* pNumPackets DEFAULT(NULL));
+
+u_int16_t MP4GetRtpHintNumberOfPackets(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId);
+
+int8_t MP4GetRtpPacketBFrame(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	u_int16_t packetIndex);
+
+int32_t MP4GetRtpPacketTransmitOffset(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	u_int16_t packetIndex);
+
+bool MP4ReadRtpPacket(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	u_int16_t packetIndex,
+	u_int8_t** ppBytes, 
+	u_int32_t* pNumBytes,
+	u_int32_t ssrc DEFAULT(0),
+	bool includeHeader DEFAULT(true),
+	bool includePayload DEFAULT(true));
+
+MP4Timestamp MP4GetRtpTimestampStart(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId);
+
+bool MP4SetRtpTimestampStart(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	MP4Timestamp rtpStart);
+
+bool MP4AddRtpHint(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId);
+
+bool MP4AddRtpVideoHint(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	bool isBframe DEFAULT(false), 
+	u_int32_t timestampOffset DEFAULT(0));
+
+bool MP4AddRtpPacket(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	bool setMbit DEFAULT(false),
+	int32_t transmitOffset DEFAULT(0));
+
+bool MP4AddRtpImmediateData(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	const u_int8_t* pBytes,
+	u_int32_t numBytes);
+
+bool MP4AddRtpSampleData(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	MP4SampleId sampleId,
+	u_int32_t dataOffset,
+	u_int32_t dataLength);
+
+bool MP4AddRtpESConfigurationPacket(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId);
+
+bool MP4WriteRtpHint(
+	MP4FileHandle hFile,
+	MP4TrackId hintTrackId,
+	MP4Duration duration,
+	bool isSyncSample DEFAULT(true));
+
+/* 3GP specific utilities */
+
+bool MP4Make3GPCompliant(
+	const char* fileName,
+	u_int32_t verbosity DEFAULT(0),
+	char* majorBrand DEFAULT(0),
+	u_int32_t minorVersion DEFAULT(0),
+	char** supportedBrands DEFAULT(NULL),
+	u_int32_t supportedBrandsCount DEFAULT(0),
+	bool deleteIodsAtom DEFAULT(true));
+
+/* ISMA specific utilities */
+
+bool MP4MakeIsmaCompliant(const char* fileName, 
+	u_int32_t verbosity DEFAULT(0),
+	bool addIsmaComplianceSdp DEFAULT(true));
+
+char* MP4MakeIsmaSdpIod(
+	u_int8_t videoProfile,
+	u_int32_t videoBitrate,
+	u_int8_t* videoConfig,
+	u_int32_t videoConfigLength,
+	u_int8_t audioProfile,
+	u_int32_t audioBitrate,
+	u_int8_t* audioConfig,
+	u_int32_t audioConfigLength,
+	u_int32_t verbosity DEFAULT(0));
+
+/* edit list */
+
+/* NOTE this section of functionality 
+ * has not yet been fully tested 
+ */
+
+MP4EditId MP4AddTrackEdit(
+	MP4FileHandle hFile,
+	MP4TrackId trackId,
+	MP4EditId editId DEFAULT(MP4_INVALID_EDIT_ID),
+	MP4Timestamp startTime DEFAULT(0),
+	MP4Duration duration DEFAULT(0),
+	bool dwell DEFAULT(false));
+
+bool MP4DeleteTrackEdit(
+	MP4FileHandle hFile,
+	MP4TrackId trackId,
+	MP4EditId editId);
+
+u_int32_t MP4GetTrackNumberOfEdits(
+	MP4FileHandle hFile,
+	MP4TrackId trackId);
+
+MP4Timestamp MP4GetTrackEditStart(
+	MP4FileHandle hFile,
+	MP4TrackId trackId,
+	MP4EditId editId);
+
+MP4Duration MP4GetTrackEditTotalDuration(
+	MP4FileHandle hFile,
+	MP4TrackId trackId,
+	MP4EditId editId DEFAULT(MP4_INVALID_EDIT_ID));
+
+MP4Timestamp MP4GetTrackEditMediaStart(
+	MP4FileHandle hFile,
+	MP4TrackId trackId,
+	MP4EditId editId);
+
+bool MP4SetTrackEditMediaStart(
+	MP4FileHandle hFile,
+	MP4TrackId trackId,
+	MP4EditId editId,
+	MP4Timestamp startTime);
+
+MP4Duration MP4GetTrackEditDuration(
+	MP4FileHandle hFile,
+	MP4TrackId trackId,
+	MP4EditId editId);
+
+bool MP4SetTrackEditDuration(
+	MP4FileHandle hFile,
+	MP4TrackId trackId,
+	MP4EditId editId,
+	MP4Duration duration);
+
+int8_t MP4GetTrackEditDwell(
+	MP4FileHandle hFile,
+	MP4TrackId trackId,
+	MP4EditId editId);
+
+bool MP4SetTrackEditDwell(
+	MP4FileHandle hFile,
+	MP4TrackId trackId,
+	MP4EditId editId,
+	bool dwell);
+
+bool MP4ReadSampleFromEditTime(
+	/* input parameters */
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4Timestamp when, 
+	/* input/output parameters */
+	u_int8_t** ppBytes, 
+	u_int32_t* pNumBytes, 
+	/* output parameters */
+	MP4Timestamp* pStartTime DEFAULT(NULL), 
+	MP4Duration* pDuration DEFAULT(NULL),
+	MP4Duration* pRenderingOffset DEFAULT(NULL), 
+	bool* pIsSyncSample DEFAULT(NULL));
+
+MP4SampleId MP4GetSampleIdFromEditTime(
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4Timestamp when, 
+	MP4Timestamp* pStartTime DEFAULT(NULL), 
+	MP4Duration* pDuration DEFAULT(NULL));
+/* iTunes metadata handling */
+bool MP4MetadataDelete(MP4FileHandle hFile);
+bool MP4GetMetadataByIndex(MP4FileHandle hFile, u_int32_t index,
+			   const char** ppName,
+			   u_int8_t** ppValue, u_int32_t* pValueSize);
+bool MP4SetMetadataName(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataName(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataArtist(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataArtist(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataWriter(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataWriter(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataComment(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataComment(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataTool(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataTool(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataYear(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataYear(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataAlbum(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataAlbum(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataTrack(MP4FileHandle hFile,
+			 u_int16_t track, u_int16_t totalTracks);
+bool MP4GetMetadataTrack(MP4FileHandle hFile,
+			 u_int16_t* track, u_int16_t* totalTracks);
+bool MP4SetMetadataDisk(MP4FileHandle hFile,
+			u_int16_t disk, u_int16_t totalDisks);
+bool MP4GetMetadataDisk(MP4FileHandle hFile,
+			u_int16_t* disk, u_int16_t* totalDisks);
+bool MP4SetMetadataGenre(MP4FileHandle hFile, const char *genre);
+bool MP4GetMetadataGenre(MP4FileHandle hFile, char **genre);
+bool MP4SetMetadataTempo(MP4FileHandle hFile, u_int16_t tempo);
+bool MP4GetMetadataTempo(MP4FileHandle hFile, u_int16_t* tempo);
+bool MP4SetMetadataCompilation(MP4FileHandle hFile, u_int8_t cpl);
+bool MP4GetMetadataCompilation(MP4FileHandle hFile, u_int8_t* cpl);
+bool MP4SetMetadataCoverArt(MP4FileHandle hFile,
+			    u_int8_t *coverArt, u_int32_t size);
+bool MP4GetMetadataCoverArt(MP4FileHandle hFile,
+			    u_int8_t **coverArt, u_int32_t* size);
+bool MP4SetMetadataFreeForm(MP4FileHandle hFile, char *name,
+			    u_int8_t* pValue, u_int32_t valueSize);
+bool MP4GetMetadataFreeForm(MP4FileHandle hFile, char *name,
+			    u_int8_t** pValue, u_int32_t* valueSize);
+ 
+
+/* time conversion utilties */
+
+/* predefined values for timeScale parameter below */
+#define MP4_SECONDS_TIME_SCALE		1
+#define MP4_MILLISECONDS_TIME_SCALE 1000
+#define MP4_MICROSECONDS_TIME_SCALE 1000000
+#define MP4_NANOSECONDS_TIME_SCALE 	1000000000
+
+#define MP4_SECS_TIME_SCALE 	MP4_SECONDS_TIME_SCALE
+#define MP4_MSECS_TIME_SCALE	MP4_MILLISECONDS_TIME_SCALE
+#define MP4_USECS_TIME_SCALE	MP4_MICROSECONDS_TIME_SCALE
+#define MP4_NSECS_TIME_SCALE	MP4_NANOSECONDS_TIME_SCALE
+
+u_int64_t MP4ConvertFromMovieDuration(
+	MP4FileHandle hFile,
+	MP4Duration duration,
+	u_int32_t timeScale);
+
+u_int64_t MP4ConvertFromTrackTimestamp(
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4Timestamp timeStamp,
+	u_int32_t timeScale);
+
+MP4Timestamp MP4ConvertToTrackTimestamp(
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	u_int64_t timeStamp,
+	u_int32_t timeScale);
+
+u_int64_t MP4ConvertFromTrackDuration(
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	MP4Duration duration,
+	u_int32_t timeScale);
+
+MP4Duration MP4ConvertToTrackDuration(
+	MP4FileHandle hFile,
+	MP4TrackId trackId, 
+	u_int64_t duration,
+	u_int32_t timeScale);
+
+char* MP4BinaryToBase16(
+	const u_int8_t* pData, 
+	u_int32_t dataSize);
+
+char* MP4BinaryToBase64(
+	const u_int8_t* pData, 
+	u_int32_t dataSize);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* undefined our utlity macro to avoid conflicts */
+#undef DEFAULT
+
+#endif /* __MP4_INCLUDED__ */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/mpeg4ip.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/mpeg4ip.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/mpeg4ip.h	(revision 18425)
@@ -0,0 +1,368 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved.
+ * 
+ * Contributor(s): 
+ *		Dave Mackie		dmackie@cisco.com
+ */
+
+#ifndef __MPEG4IP_INCLUDED__
+#define __MPEG4IP_INCLUDED__
+
+/* project wide applicable stuff here */
+
+
+#ifdef WIN32
+#define HAVE_IN_PORT_T
+#define HAVE_SOCKLEN_T
+#define NEED_SDL_VIDEO_IN_MAIN_THREAD
+#else
+#undef PACKAGE
+#undef VERSION
+#include <mpeg4ip_config.h>
+#undef PACKAGE
+#undef VERSION
+// so these don't propogate
+#endif
+
+// the mpeg4ip_package and mpeg4ip_version are always in this
+// file 
+#include "mpeg4ip_version.h"
+
+
+
+
+#ifdef WIN32
+
+#define _WIN32_WINNT 0x0400
+#define _WINSOCKAPI_
+#include <windows.h>
+#include <winsock2.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <limits.h>
+
+typedef unsigned __int64 uint64_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int64 u_int64_t;
+typedef unsigned __int32 u_int32_t;
+typedef unsigned __int16 u_int16_t;
+typedef unsigned __int8 u_int8_t;
+typedef __int64 int64_t;
+typedef __int32 int32_t;
+typedef __int16 int16_t;
+typedef __int8  int8_t;
+typedef unsigned short in_port_t;
+typedef int socklen_t;
+typedef int ssize_t;
+#define snprintf _snprintf
+#define strncasecmp _strnicmp
+#define strcasecmp _stricmp
+
+#include <io.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#define write _write
+#define lseek _lseek
+#define close _close
+#define open _open
+#define access _access
+#define vsnprintf _vsnprintf
+#define F_OK 0
+#define OPEN_RDWR (_O_RDWR | _O_BINARY)
+#define OPEN_CREAT (_O_CREAT | _O_BINARY)
+#define OPEN_RDONLY (_O_RDONLY | _O_BINARY)
+#define srandom srand
+#define random rand
+
+#define IOSBINARY ios::binary
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int gettimeofday(struct timeval *t, void *);
+#ifdef __cplusplus
+}
+#endif
+
+#define PATH_MAX MAX_PATH
+#define MAX_UINT64 -1
+#define D64F "I64d"
+#define U64F  "I64u"
+#define X64F "I64x"
+
+#define TO_D64(a) (a##I64)
+#define TO_U64(a) (a##UI64)
+
+#define LOG_EMERG 0
+#define LOG_ALERT 1
+#define LOG_CRIT 2
+#define LOG_ERR 3
+#define LOG_WARNING 4
+#define LOG_NOTICE 5
+#define LOG_INFO 6
+#define LOG_DEBUG 7
+
+#if     !__STDC__ && _INTEGRAL_MAX_BITS >= 64
+#define VAR_TO_FPOS(fpos, var) (fpos) = (var)
+#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)(_FPOSOFF(fpos))
+#else
+#define VAR_TO_FPOS(fpos, var) (fpos).lopart = ((var) & UINT_MAX); (fpos).hipart = ((var) >> 32)
+#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)((uint64_t)((fpos).hipart ) << 32 | (fpos).lopart)
+#endif
+
+#define __STRING(expr) #expr
+
+#define FOPEN_READ_BINARY "rb"
+#define FOPEN_WRITE_BINARY "wb"
+
+#define UINT64_TO_DOUBLE(a) ((double)((int64_t)(a)))
+#else /* UNIX */
+/*****************************************************************************
+ *   UNIX LIKE DEFINES BELOW THIS POINT
+ *****************************************************************************/
+#ifdef sun
+#include <sys/feature_tests.h>
+#endif
+
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#else
+#ifndef sun
+#if _FILE_OFFSET_BITS < 64
+ #error File offset bits is already set to non-64 value
+#endif
+#endif
+#endif
+
+#ifndef _LARGEFILE_SOURCE
+#define _LARGEFILE_SOURCE
+#endif
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#if !defined(HAVE_INTTYPES_H) || !defined(HAVE_STDINT_H)
+#error "Don't have stdint.h or inttypes.h - no way to get uint8_t"
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <syslog.h>
+#include <string.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <sys/stat.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+#include <sys/param.h>
+
+#define OPEN_RDWR O_RDWR
+#define OPEN_CREAT O_CREAT 
+#define OPEN_RDONLY O_RDONLY
+
+#define closesocket close
+#define IOSBINARY ios::bin
+
+#if SIZEOF_LONG == 8
+#define MAX_UINT64 -1LU
+#define D64F "ld"
+#define U64F  "lu"
+#define X64F "lx"
+
+#define TO_D64(a) (a##LD)
+#define TO_U64(a) (a##LU)
+#else
+#define MAX_UINT64 -1LLU
+#define D64F "lld"
+#define U64F  "llu"
+#define X64F "llx"
+
+#define TO_D64(a) (a##LLD)
+#define TO_U64(a) (a##LLU)
+#endif
+
+#ifdef HAVE_FPOS_T___POS
+#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)((fpos).__pos)
+#define VAR_TO_FPOS(fpos, var) (fpos).__pos = (var)
+#else
+#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)(fpos)
+#define VAR_TO_FPOS(fpos, var) (fpos) = (var)
+#endif
+
+#define FOPEN_READ_BINARY "r"
+#define FOPEN_WRITE_BINARY "w"
+#define UINT64_TO_DOUBLE(a) ((double)(a))
+#endif /* define unix */
+
+/*****************************************************************************
+ *             Generic type includes used in the whole package               *
+ *****************************************************************************/
+#define D64  "%"D64F
+#define U64  "%"U64F
+#define X64 "%"X64F
+
+#define M_LLU TO_U64(1000)
+#define M_64 TO_U64(1000)
+#define LLU  U64
+
+#include <stdarg.h>
+typedef void (*error_msg_func_t)(int loglevel,
+				 const char *lib,
+				 const char *fmt,
+				 va_list ap);
+typedef void (*lib_message_func_t)(int loglevel,
+				   const char *lib,
+				   const char *fmt,
+				   ...);
+#ifndef HAVE_IN_PORT_T
+typedef uint16_t in_port_t;
+#endif
+
+#ifndef HAVE_SOCKLEN_T
+typedef unsigned int socklen_t;
+#endif
+
+#ifdef sun
+#include <limits.h>
+#define u_int8_t uint8_t
+#define u_int16_t uint16_t
+#define u_int32_t uint32_t
+#define u_int64_t uint64_t
+#define __STRING(expr) #expr
+#endif
+
+#ifndef HAVE_STRSEP
+#ifdef __cplusplus
+extern "C" {
+#endif
+char *strsep(char **strp, const char *delim); 
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef INADDR_NONE
+#define INADDR_NONE (-1)
+#endif
+
+#define MALLOC_STRUCTURE(a) ((a *)malloc(sizeof(a)))
+
+#define CHECK_AND_FREE(a) if ((a) != NULL) { free((void *)(a)); (a) = NULL;}
+
+#define NUM_ELEMENTS_IN_ARRAY(name) ((sizeof((name))) / (sizeof(*(name))))
+
+#define ADV_SPACE(a) {while (isspace(*(a)) && (*(a) != '\0'))(a)++;}
+
+#ifndef HAVE_GTK
+typedef char gchar;
+typedef unsigned char guchar;
+
+typedef int gint;
+typedef unsigned int guint;
+
+typedef long glong;
+typedef unsigned long gulong;
+
+typedef double gdouble;
+
+typedef int gboolean;
+
+typedef int16_t gint16;
+typedef uint16_t guint16;
+
+typedef int32_t gint32;
+typedef uint32_t guint32;
+
+typedef int64_t gint64;
+typedef uint64_t guint64;
+
+typedef uint8_t  guint8;
+typedef int8_t gint8;
+
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef __cplusplus
+#ifndef bool
+typedef unsigned char bool;
+#endif
+#endif
+
+#ifndef ROUND
+# ifdef HAVE_RINT
+# define ROUND(f) rint(f)
+# else
+# define ROUND(f) (int)(floor((f) + 0.5))
+# endif
+#endif
+
+#ifndef INT16_MAX
+# define INT16_MAX (32767)
+#endif
+#ifndef INT16_MIN 
+# define INT16_MIN (-32767-1)
+#endif 
+
+#ifndef UINT32_MAX
+# define UINT32_MAX             (4294967295U)
+#endif
+
+#ifndef UINT64_MAX
+# define UINT64_MAX TO_U64(0xffffffffffffffff)
+#endif
+
+#endif /* __MPEG4IP_INCLUDED__ */
+
Index: extensions/gsdl-video/trunk/installed/cmdline/include/mpeg4ip_config.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/mpeg4ip_config.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/mpeg4ip_config.h	(revision 18425)
@@ -0,0 +1,134 @@
+/* config.h.  Generated by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define if you want to encode for DRM */
+/* #undef DRM */
+
+/* Define to 1 if you have the declaration of `MP4Create', and to 0 if you
+   don't. */
+#define HAVE_DECL_MP4CREATE 0
+
+/* Define to 1 if you have the declaration of `MP4MetadataDelete', and to 0 if
+   you don't. */
+#define HAVE_DECL_MP4METADATADELETE 0
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <float.h> header file. */
+#define HAVE_FLOAT_H 1
+
+/* Define to 1 if `__pos' is member of `fpos_t'. */
+#define HAVE_FPOS_T___POS 1
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if the system has the type `int16_t'. */
+#define HAVE_INT16_T 1
+
+/* Define to 1 if the system has the type `int32_t'. */
+#define HAVE_INT32_T 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if the system has the type `in_port_t'. */
+#define HAVE_IN_PORT_T 1
+
+/* Define to 1 if you have the `gnugetopt' library (-lgnugetopt). */
+/* #undef HAVE_LIBGNUGETOPT */
+
+/* define if needed */
+#define HAVE_LIBMP4V2 1
+
+/* Define to 1 if you have the <mathf.h> header file. */
+/* #undef HAVE_MATHF_H */
+
+/* define if needed */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if the system has the type `socklen_t'. */
+#define HAVE_SOCKLEN_T 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* define if needed */
+#define HAVE_STRCASECMP 1
+
+/* define if needed */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* define if needed */
+#define HAVE_STRSEP 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if the system has the type `u_int16_t'. */
+#define HAVE_U_INT16_T 1
+
+/* Define to 1 if the system has the type `u_int32_t'. */
+#define HAVE_U_INT32_T 1
+
+/* Name of package */
+#define PACKAGE "faac"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "faac-dev@lists.sourceforge.net"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "FAAC"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "FAAC 1.25"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "faac"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.25"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Version number of package */
+#define VERSION "1.25"
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#define _FILE_OFFSET_BITS 64
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
Index: extensions/gsdl-video/trunk/installed/cmdline/include/mpeg4ip_version.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/mpeg4ip_version.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/mpeg4ip_version.h	(revision 18425)
@@ -0,0 +1,2 @@
+#define MPEG4IP_PACKAGE "mpeg4ip"
+#define MPEG4IP_VERSION "1.1.3"
Index: extensions/gsdl-video/trunk/installed/cmdline/include/neaacdec.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/include/neaacdec.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/include/neaacdec.h	(revision 18425)
@@ -0,0 +1,255 @@
+/*
+** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
+** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+** 
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+** 
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software 
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** Any non-GPL usage of this software or parts of this software is strictly
+** forbidden.
+**
+** The "appropriate copyright message" mentioned in section 2c of the GPLv2
+** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
+**
+** Commercial non-GPL licensing of this software is possible.
+** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
+**
+** $Id: neaacdec.h,v 1.11 2007/11/01 12:33:29 menno Exp $
+**/
+
+#ifndef __NEAACDEC_H__
+#define __NEAACDEC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#if 1
+/* MACROS FOR BACKWARDS COMPATIBILITY */
+/* structs */
+#define faacDecHandle                  NeAACDecHandle
+#define faacDecConfiguration           NeAACDecConfiguration
+#define faacDecConfigurationPtr        NeAACDecConfigurationPtr
+#define faacDecFrameInfo               NeAACDecFrameInfo
+/* functions */
+#define faacDecGetErrorMessage         NeAACDecGetErrorMessage
+#define faacDecSetConfiguration        NeAACDecSetConfiguration
+#define faacDecGetCurrentConfiguration NeAACDecGetCurrentConfiguration
+#define faacDecInit                    NeAACDecInit
+#define faacDecInit2                   NeAACDecInit2
+#define faacDecInitDRM                 NeAACDecInitDRM
+#define faacDecPostSeekReset           NeAACDecPostSeekReset
+#define faacDecOpen                    NeAACDecOpen
+#define faacDecClose                   NeAACDecClose
+#define faacDecDecode                  NeAACDecDecode
+#define AudioSpecificConfig            NeAACDecAudioSpecificConfig
+#endif
+
+
+#ifdef _WIN32
+  #pragma pack(push, 8)
+  #ifndef NEAACDECAPI
+    #define NEAACDECAPI __cdecl
+  #endif
+#else
+  #ifndef NEAACDECAPI
+    #define NEAACDECAPI
+  #endif
+#endif
+
+#define FAAD2_VERSION "2.6"
+
+/* object types for AAC */
+#define MAIN       1
+#define LC         2
+#define SSR        3
+#define LTP        4
+#define HE_AAC     5
+#define ER_LC     17
+#define ER_LTP    19
+#define LD        23
+#define DRM_ER_LC 27 /* special object type for DRM */
+
+/* header types */
+#define RAW        0
+#define ADIF       1
+#define ADTS       2
+
+/* SBR signalling */
+#define NO_SBR           0
+#define SBR_UPSAMPLED    1
+#define SBR_DOWNSAMPLED  2
+#define NO_SBR_UPSAMPLED 3
+
+/* library output formats */
+#define FAAD_FMT_16BIT  1
+#define FAAD_FMT_24BIT  2
+#define FAAD_FMT_32BIT  3
+#define FAAD_FMT_FLOAT  4
+#define FAAD_FMT_FIXED  FAAD_FMT_FLOAT
+#define FAAD_FMT_DOUBLE 5
+
+/* Capabilities */
+#define LC_DEC_CAP           (1<<0) /* Can decode LC */
+#define MAIN_DEC_CAP         (1<<1) /* Can decode MAIN */
+#define LTP_DEC_CAP          (1<<2) /* Can decode LTP */
+#define LD_DEC_CAP           (1<<3) /* Can decode LD */
+#define ERROR_RESILIENCE_CAP (1<<4) /* Can decode ER */
+#define FIXED_POINT_CAP      (1<<5) /* Fixed point */
+
+/* Channel definitions */
+#define FRONT_CHANNEL_CENTER (1)
+#define FRONT_CHANNEL_LEFT   (2)
+#define FRONT_CHANNEL_RIGHT  (3)
+#define SIDE_CHANNEL_LEFT    (4)
+#define SIDE_CHANNEL_RIGHT   (5)
+#define BACK_CHANNEL_LEFT    (6)
+#define BACK_CHANNEL_RIGHT   (7)
+#define BACK_CHANNEL_CENTER  (8)
+#define LFE_CHANNEL          (9)
+#define UNKNOWN_CHANNEL      (0)
+
+/* DRM channel definitions */
+#define DRMCH_MONO          1
+#define DRMCH_STEREO        2
+#define DRMCH_SBR_MONO      3
+#define DRMCH_SBR_STEREO    4
+#define DRMCH_SBR_PS_STEREO 5
+
+
+/* A decode call can eat up to FAAD_MIN_STREAMSIZE bytes per decoded channel,
+   so at least so much bytes per channel should be available in this stream */
+#define FAAD_MIN_STREAMSIZE 768 /* 6144 bits/channel */
+
+
+typedef void *NeAACDecHandle;
+
+typedef struct mp4AudioSpecificConfig
+{
+    /* Audio Specific Info */
+    unsigned char objectTypeIndex;
+    unsigned char samplingFrequencyIndex;
+    unsigned long samplingFrequency;
+    unsigned char channelsConfiguration;
+
+    /* GA Specific Info */
+    unsigned char frameLengthFlag;
+    unsigned char dependsOnCoreCoder;
+    unsigned short coreCoderDelay;
+    unsigned char extensionFlag;
+    unsigned char aacSectionDataResilienceFlag;
+    unsigned char aacScalefactorDataResilienceFlag;
+    unsigned char aacSpectralDataResilienceFlag;
+    unsigned char epConfig;
+
+    char sbr_present_flag;
+    char forceUpSampling;
+    char downSampledSBR;
+} mp4AudioSpecificConfig;
+
+typedef struct NeAACDecConfiguration
+{
+    unsigned char defObjectType;
+    unsigned long defSampleRate;
+    unsigned char outputFormat;
+    unsigned char downMatrix;
+    unsigned char useOldADTSFormat;
+    unsigned char dontUpSampleImplicitSBR;
+} NeAACDecConfiguration, *NeAACDecConfigurationPtr;
+
+typedef struct NeAACDecFrameInfo
+{
+    unsigned long bytesconsumed;
+    unsigned long samples;
+    unsigned char channels;
+    unsigned char error;
+    unsigned long samplerate;
+
+    /* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */
+    unsigned char sbr;
+
+    /* MPEG-4 ObjectType */
+    unsigned char object_type;
+
+    /* AAC header type; MP4 will be signalled as RAW also */
+    unsigned char header_type;
+
+    /* multichannel configuration */
+    unsigned char num_front_channels;
+    unsigned char num_side_channels;
+    unsigned char num_back_channels;
+    unsigned char num_lfe_channels;
+    unsigned char channel_position[64];
+
+    /* PS: 0: off, 1: on */
+    unsigned char ps;
+} NeAACDecFrameInfo;
+
+char* NEAACDECAPI NeAACDecGetErrorMessage(unsigned char errcode);
+
+unsigned long NEAACDECAPI NeAACDecGetCapabilities(void);
+
+NeAACDecHandle NEAACDECAPI NeAACDecOpen(void);
+
+NeAACDecConfigurationPtr NEAACDECAPI NeAACDecGetCurrentConfiguration(NeAACDecHandle hDecoder);
+
+unsigned char NEAACDECAPI NeAACDecSetConfiguration(NeAACDecHandle hDecoder,
+                                                   NeAACDecConfigurationPtr config);
+
+/* Init the library based on info from the AAC file (ADTS/ADIF) */
+long NEAACDECAPI NeAACDecInit(NeAACDecHandle hDecoder,
+                              unsigned char *buffer,
+                              unsigned long buffer_size,
+                              unsigned long *samplerate,
+                              unsigned char *channels);
+
+/* Init the library using a DecoderSpecificInfo */
+char NEAACDECAPI NeAACDecInit2(NeAACDecHandle hDecoder, unsigned char *pBuffer,
+                               unsigned long SizeOfDecoderSpecificInfo,
+                               unsigned long *samplerate, unsigned char *channels);
+
+/* Init the library for DRM */
+char NEAACDECAPI NeAACDecInitDRM(NeAACDecHandle *hDecoder, unsigned long samplerate,
+                                 unsigned char channels);
+
+void NEAACDECAPI NeAACDecPostSeekReset(NeAACDecHandle hDecoder, long frame);
+
+void NEAACDECAPI NeAACDecClose(NeAACDecHandle hDecoder);
+
+void* NEAACDECAPI NeAACDecDecode(NeAACDecHandle hDecoder,
+                                 NeAACDecFrameInfo *hInfo,
+                                 unsigned char *buffer,
+                                 unsigned long buffer_size);
+
+void* NEAACDECAPI NeAACDecDecode2(NeAACDecHandle hDecoder,
+                                  NeAACDecFrameInfo *hInfo,
+                                  unsigned char *buffer,
+                                  unsigned long buffer_size,
+                                  void **sample_buffer,
+                                  unsigned long sample_buffer_size);
+
+char NEAACDECAPI NeAACDecAudioSpecificConfig(unsigned char *pBuffer,
+                                             unsigned long buffer_size,
+                                             mp4AudioSpecificConfig *mp4ASC);
+
+#ifdef _WIN32
+  #pragma pack(pop)
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/libavcodec.so.51
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/libavcodec.so.51	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/libavcodec.so.51	(revision 18425)
@@ -0,0 +1,1 @@
+link libavcodec.so.51.40.4
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/libavformat.so.51
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/libavformat.so.51	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/libavformat.so.51	(revision 18425)
@@ -0,0 +1,1 @@
+link libavformat.so.51.12.1
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/libavutil.so.49
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/libavutil.so.49	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/libavutil.so.49	(revision 18425)
@@ -0,0 +1,1 @@
+link libavutil.so.49.4.1
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/libfaac.so.0
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/libfaac.so.0	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/libfaac.so.0	(revision 18425)
@@ -0,0 +1,1 @@
+link libfaac.so.0.0.0
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/libfaad.so.0
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/libfaad.so.0	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/libfaad.so.0	(revision 18425)
@@ -0,0 +1,1 @@
+link libfaad.so.0.0.0
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/libmp3lame.so.0
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/libmp3lame.so.0	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/libmp3lame.so.0	(revision 18425)
@@ -0,0 +1,1 @@
+link libmp3lame.so.0.0.0
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/libmp4v2.so.0
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/libmp4v2.so.0	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/libmp4v2.so.0	(revision 18425)
@@ -0,0 +1,1 @@
+link libmp4v2.so.0.0.0
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/libswscale.so.0
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/libswscale.so.0	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/libswscale.so.0	(revision 18425)
@@ -0,0 +1,1 @@
+link libswscale.so.0.5.0
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/pkgconfig/libavcodec.pc
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/pkgconfig/libavcodec.pc	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/pkgconfig/libavcodec.pc	(revision 18425)
@@ -0,0 +1,12 @@
+prefix=/research/code/gsdl-video-import/trunk/installed/cmdline
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: libavcodec
+Description: FFmpeg codec library
+Version: 51.40.4
+Requires:  ogg >= 1.1 vorbis vorbisenc libavutil = 49.4.1
+Conflicts:
+Libs: -L${libdir} -lavcodec  -lm -lz -la52 -lmp3lame -lm -lvorbis -lvorbisenc -logg -logg -lfaac -lfaad -ldl 
+Cflags: -I${includedir} -I${includedir}/ffmpeg
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/pkgconfig/libavformat.pc
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/pkgconfig/libavformat.pc	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/pkgconfig/libavformat.pc	(revision 18425)
@@ -0,0 +1,12 @@
+prefix=/research/code/gsdl-video-import/trunk/installed/cmdline
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: libavformat
+Description: FFmpeg container format library
+Version: 51.12.1
+Requires:  ogg >= 1.1 vorbis vorbisenc libavcodec = 51.40.4
+Conflicts:
+Libs: -L${libdir} -lavformat  -lm -lz -la52 -lmp3lame -lm -lvorbis -lvorbisenc -logg -logg -lfaac -lfaad -ldl 
+Cflags: -I${includedir} -I${includedir}/ffmpeg
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/pkgconfig/libavutil.pc
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/pkgconfig/libavutil.pc	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/pkgconfig/libavutil.pc	(revision 18425)
@@ -0,0 +1,12 @@
+prefix=/research/code/gsdl-video-import/trunk/installed/cmdline
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: libavutil
+Description: FFmpeg utility library
+Version: 49.4.1
+Requires: 
+Conflicts:
+Libs: -L${libdir} -lavutil
+Cflags: -I${includedir} -I${includedir}/ffmpeg
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/pkgconfig/libswscale.pc
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/pkgconfig/libswscale.pc	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/pkgconfig/libswscale.pc	(revision 18425)
@@ -0,0 +1,12 @@
+prefix=/research/code/gsdl-video-import/trunk/installed/cmdline
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: libswscale
+Description: FFmpeg image rescaling library
+Version: 0.5.0
+Requires: libavutil = 49.4.1
+Conflicts:
+Libs: -L${libdir} -lswscale
+Cflags: -I${includedir} -I${includedir}/ffmpeg
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/English.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/English.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/English.rb	(revision 18425)
@@ -0,0 +1,155 @@
+#  Include the English library file in a Ruby script, and you can
+#  reference the global variables such as \VAR{\$\_} using less
+#  cryptic names, listed in the following table.% \vref{tab:english}.
+#
+#  Without 'English':
+#
+#      $\ = ' -- '
+#      "waterbuffalo" =~ /buff/
+#      print $", $', $$, "\n"
+#
+#  With English:
+#
+#      require "English"
+#      
+#      $OUTPUT_FIELD_SEPARATOR = ' -- '
+#      "waterbuffalo" =~ /buff/
+#      print $LOADED_FEATURES, $POSTMATCH, $PID, "\n"
+
+
+# The exception object passed to +raise+.
+alias $ERROR_INFO              $!
+
+# The stack backtrace generated by the last
+# exception. <tt>See Kernel.caller</tt> for details. Thread local.
+alias $ERROR_POSITION          $@
+
+# The default separator pattern used by <tt>String.split</tt>.  May be
+# set from the command line using the <tt>-F</tt> flag.
+alias $FS                      $;
+
+# The default separator pattern used by <tt>String.split</tt>.  May be
+# set from the command line using the <tt>-F</tt> flag.
+alias $FIELD_SEPARATOR         $;
+
+# The separator string output between the parameters to methods such
+# as <tt>Kernel.print</tt> and <tt>Array.join</tt>. Defaults to +nil+,
+# which adds no text.
+alias $OFS                     $,
+
+# The separator string output between the parameters to methods such
+# as <tt>Kernel.print</tt> and <tt>Array.join</tt>. Defaults to +nil+,
+# which adds no text.
+alias $OUTPUT_FIELD_SEPARATOR  $,
+
+# The input record separator (newline by default). This is the value
+# that routines such as <tt>Kernel.gets</tt> use to determine record
+# boundaries. If set to +nil+, +gets+ will read the entire file.
+alias $RS                      $/
+
+# The input record separator (newline by default). This is the value
+# that routines such as <tt>Kernel.gets</tt> use to determine record
+# boundaries. If set to +nil+, +gets+ will read the entire file.
+alias $INPUT_RECORD_SEPARATOR  $/
+
+# The string appended to the output of every call to methods such as
+# <tt>Kernel.print</tt> and <tt>IO.write</tt>. The default value is
+# +nil+.
+alias $ORS                     $\
+
+# The string appended to the output of every call to methods such as
+# <tt>Kernel.print</tt> and <tt>IO.write</tt>. The default value is
+# +nil+.
+alias $OUTPUT_RECORD_SEPARATOR $\
+
+# The number of the last line read from the current input file.
+alias $INPUT_LINE_NUMBER       $.
+
+# The number of the last line read from the current input file.
+alias $NR                      $.
+
+# The last line read by <tt>Kernel.gets</tt> or
+# <tt>Kernel.readline</tt>. Many string-related functions in the
+# +Kernel+ module operate on <tt>$_</tt> by default. The variable is
+# local to the current scope. Thread local.
+alias $LAST_READ_LINE          $_
+
+# The destination of output for <tt>Kernel.print</tt>
+# and <tt>Kernel.printf</tt>. The default value is
+# <tt>$stdout</tt>.
+alias $DEFAULT_OUTPUT          $>
+
+# An object that provides access to the concatenation
+# of the contents of all the files
+# given as command-line arguments, or <tt>$stdin</tt>
+# (in the case where there are no
+# arguments). <tt>$<</tt> supports methods similar to a 
+# +File+ object:
+# +inmode+, +close+,
+# <tt>closed?</tt>, +each+,
+# <tt>each_byte</tt>, <tt>each_line</tt>,
+# +eof+, <tt>eof?</tt>, +file+,
+# +filename+, +fileno+,
+# +getc+, +gets+, +lineno+,
+# <tt>lineno=</tt>, +path+, 
+# +pos+, <tt>pos=</tt>,
+# +read+, +readchar+,
+# +readline+, +readlines+,
+# +rewind+, +seek+, +skip+,
+# +tell+, <tt>to_a</tt>, <tt>to_i</tt>,
+# <tt>to_io</tt>, <tt>to_s</tt>, along with the
+# methods in +Enumerable+. The method +file+
+# returns a +File+ object for the file currently
+# being read. This may change as <tt>$<</tt> reads
+# through the files on the command line. Read only.
+alias $DEFAULT_INPUT           $<
+
+# The process number of the program being executed. Read only.
+alias $PID                     $$
+
+# The process number of the program being executed. Read only.
+alias $PROCESS_ID              $$
+
+# The exit status of the last child process to terminate. Read
+# only. Thread local.
+alias $CHILD_STATUS            $?
+
+# A +MatchData+ object that encapsulates the results of a successful
+# pattern match. The variables <tt>$&</tt>, <tt>$`</tt>, <tt>$'</tt>,
+# and <tt>$1</tt> to <tt>$9</tt> are all derived from
+# <tt>$~</tt>. Assigning to <tt>$~</tt> changes the values of these
+# derived variables.  This variable is local to the current
+# scope. Thread local.
+alias $LAST_MATCH_INFO         $~
+
+# If set to any value apart from +nil+ or +false+, all pattern matches
+# will be case insensitive, string comparisons will ignore case, and
+# string hash values will be case insensitive. Deprecated
+alias $IGNORECASE              $=
+
+# An array of strings containing the command-line
+# options from the invocation of the program. Options
+# used by the Ruby interpreter will have been
+# removed. Read only. Also known simply as +ARGV+.
+alias $ARGV                    $*
+
+# The string matched by the last successful pattern
+# match. This variable is local to the current
+# scope. Read only. Thread local.
+alias $MATCH                   $&
+
+# The string preceding the match in the last
+# successful pattern match. This variable is local to 
+# the current scope. Read only. Thread local.
+alias $PREMATCH                $`
+
+# The string following the match in the last
+# successful pattern match. This variable is local to 
+# the current scope. Read only. Thread local.
+alias $POSTMATCH               $'
+
+# The contents of the highest-numbered group matched in the last
+# successful pattern match. Thus, in <tt>"cat" =~ /(c|a)(t|z)/</tt>,
+# <tt>$+</tt> will be set to "t".  This variable is local to the
+# current scope. Read only. Thread local.
+alias $LAST_PAREN_MATCH        $+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/Env.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/Env.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/Env.rb	(revision 18425)
@@ -0,0 +1,18 @@
+# Env.rb -- imports environment variables as global variables, Perlish ;(
+# Usage:
+#
+#  require 'Env'
+#  p $USER
+#  $USER = "matz"
+#  p ENV["USER"]
+
+require 'importenv'
+
+if __FILE__ == $0
+  p $TERM
+  $TERM = nil
+  p $TERM
+  p ENV["TERM"]
+  $TERM = "foo"
+  p ENV["TERM"]
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/abbrev.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/abbrev.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/abbrev.rb	(revision 18425)
@@ -0,0 +1,103 @@
+#!/usr/bin/env ruby
+=begin
+#
+# Copyright (c) 2001,2003 Akinori MUSHA <knu@iDaemons.org>
+#
+# All rights reserved.  You can redistribute and/or modify it under
+# the same terms as Ruby.
+#
+# $Idaemons: /home/cvs/rb/abbrev.rb,v 1.2 2001/05/30 09:37:45 knu Exp $
+# $RoughId: abbrev.rb,v 1.4 2003/10/14 19:45:42 knu Exp $
+# $Id: abbrev.rb 11708 2007-02-12 23:01:19Z shyouhei $
+=end
+
+# Calculate the set of unique abbreviations for a given set of strings.
+#
+#   require 'abbrev'
+#   require 'pp'
+#
+#   pp Abbrev::abbrev(['ruby', 'rules']).sort
+#
+# <i>Generates:</i>
+#
+#   [["rub", "ruby"],
+#    ["ruby", "ruby"],
+#    ["rul", "rules"],
+#    ["rule", "rules"],
+#    ["rules", "rules"]]
+#
+# Also adds an +abbrev+ method to class +Array+.
+
+module Abbrev
+
+  # Given a set of strings, calculate the set of unambiguous
+  # abbreviations for those strings, and return a hash where the keys
+  # are all the possible abbreviations and the values are the full
+  # strings. Thus, given input of "car" and "cone", the keys pointing
+  # to "car" would be "ca" and "car", while those pointing to "cone"
+  # would be "co", "con", and "cone".
+  #
+  # The optional +pattern+ parameter is a pattern or a string. Only
+  # those input strings matching the pattern, or begging the string,
+  # are considered for inclusion in the output hash
+
+  def abbrev(words, pattern = nil)
+    table = {}
+    seen = Hash.new(0)
+
+    if pattern.is_a?(String)
+      pattern = /^#{Regexp.quote(pattern)}/	# regard as a prefix
+    end
+
+    words.each do |word|
+      next if (abbrev = word).empty?
+      while (len = abbrev.rindex(/[\w\W]\z/)) > 0
+	abbrev = word[0,len]
+
+	next if pattern && pattern !~ abbrev
+
+	case seen[abbrev] += 1
+	when 1
+	  table[abbrev] = word
+	when 2
+	  table.delete(abbrev)
+	else
+	  break
+	end
+      end
+    end
+
+    words.each do |word|
+      next if pattern && pattern !~ word
+
+      table[word] = word
+    end
+
+    table
+  end
+
+  module_function :abbrev
+end
+
+class Array
+  # Calculates the set of unambiguous abbreviations for the strings in
+  # +self+. If passed a pattern or a string, only the strings matching
+  # the pattern or starting with the string are considered.
+  #
+  #   %w{ car cone }.abbrev   #=> { "ca" => "car", "car" => "car",
+  #                                 "co" => "cone", "con" => cone",
+  #                                 "cone" => "cone" }
+  def abbrev(pattern = nil)
+    Abbrev::abbrev(self, pattern)
+  end
+end
+
+if $0 == __FILE__
+  while line = gets
+    hash = line.split.abbrev
+
+    hash.sort.each do |k, v|
+      puts "#{k} => #{v}"
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/base64.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/base64.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/base64.rb	(revision 18425)
@@ -0,0 +1,133 @@
+#
+# = base64.rb: methods for base64-encoding and -decoding stings
+#
+# Author:: Yukihiro Matsumoto 
+# Documentation:: Dave Thomas and Gavin Sinclair
+#
+# Until Ruby 1.8.1, these methods were defined at the top-level.  Now
+# they are in the Base64 module but included in the top-level, where
+# their usage is deprecated.
+#
+# See Base64 for documentation.
+#
+
+require "kconv"
+
+
+# The Base64 module provides for the encoding (#encode64) and decoding
+# (#decode64) of binary data using a Base64 representation.
+# 
+# The following particular features are also provided:
+# - encode into lines of a given length (#b64encode)
+# - decode the special format specified in RFC2047 for the
+#   representation of email headers (decode_b)
+#
+# == Example
+#
+# A simple encoding and decoding. 
+# 
+#     require "base64"
+#
+#     enc   = Base64.encode64('Send reinforcements')
+#                         # -> "U2VuZCByZWluZm9yY2VtZW50cw==\n" 
+#     plain = Base64.decode64(enc)
+#                         # -> "Send reinforcements"
+#
+# The purpose of using base64 to encode data is that it translates any
+# binary data into purely printable characters.  It is specified in
+# RFC 2045 (http://www.faqs.org/rfcs/rfc2045.html).
+
+module Base64
+  module_function
+
+  # Returns the Base64-decoded version of +str+.
+  #
+  #   require 'base64'
+  #   str = 'VGhpcyBpcyBsaW5lIG9uZQpUaGlzIG' +
+  #         'lzIGxpbmUgdHdvClRoaXMgaXMgbGlu' +
+  #         'ZSB0aHJlZQpBbmQgc28gb24uLi4K'
+  #   puts Base64.decode64(str)
+  #
+  # <i>Generates:</i>
+  #
+  #    This is line one
+  #    This is line two
+  #    This is line three
+  #    And so on...
+
+  def decode64(str)
+    str.unpack("m")[0]
+  end
+
+
+  # Decodes text formatted using a subset of RFC2047 (the one used for
+  # mime-encoding mail headers).
+  #
+  # Only supports an encoding type of 'b' (base 64), and only supports
+  # the character sets ISO-2022-JP and SHIFT_JIS (so the only two
+  # encoded word sequences recognized are <tt>=?ISO-2022-JP?B?...=</tt> and
+  # <tt>=?SHIFT_JIS?B?...=</tt>).  Recognition of these sequences is case
+  # insensitive.
+
+  def decode_b(str)
+    str.gsub!(/=\?ISO-2022-JP\?B\?([!->@-~]+)\?=/i) {
+      decode64($1)
+    }
+    str = Kconv::toeuc(str)
+    str.gsub!(/=\?SHIFT_JIS\?B\?([!->@-~]+)\?=/i) {
+      decode64($1)
+    }
+    str = Kconv::toeuc(str)
+    str.gsub!(/\n/, ' ') 
+    str.gsub!(/\0/, '')
+    str
+  end
+
+  # Returns the Base64-encoded version of +str+.
+  #
+  #    require 'base64'
+  #    Base64.b64encode("Now is the time for all good coders\nto learn Ruby")
+  #
+  # <i>Generates:</i>
+  #
+  #    Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g
+  #    UnVieQ==
+
+  def encode64(bin)
+    [bin].pack("m")
+  end
+
+  # _Prints_ the Base64 encoded version of +bin+ (a +String+) in lines of
+  # +len+ (default 60) characters.
+  #
+  #    require 'base64'
+  #    data = "Now is the time for all good coders\nto learn Ruby" 
+  #    Base64.b64encode(data)
+  #
+  # <i>Generates:</i>
+  #
+  #    Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g
+  #    UnVieQ==
+
+  def b64encode(bin, len = 60)
+    encode64(bin).scan(/.{1,#{len}}/o) do
+      print $&, "\n"
+    end
+  end 
+
+
+  module Deprecated # :nodoc:
+    include Base64
+
+    for m in Base64.private_instance_methods(false)
+      module_eval %{
+        def #{m}(*args)
+          warn("\#{caller(1)[0]}: #{m} is deprecated; use Base64.#{m} instead")
+          super
+        end
+      }
+    end
+  end
+end
+
+include Base64::Deprecated
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/benchmark.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/benchmark.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/benchmark.rb	(revision 18425)
@@ -0,0 +1,569 @@
+=begin
+#
+# benchmark.rb - a performance benchmarking library 
+# 
+# $Id: benchmark.rb 11708 2007-02-12 23:01:19Z shyouhei $
+# 
+# Created by Gotoken (gotoken@notwork.org). 
+#
+# Documentation by Gotoken (original RD), Lyle Johnson (RDoc conversion), and
+# Gavin Sinclair (editing). 
+#
+=end
+
+# == Overview
+#
+# The Benchmark module provides methods for benchmarking Ruby code, giving
+# detailed reports on the time taken for each task.
+#
+
+# The Benchmark module provides methods to measure and report the time
+# used to execute Ruby code.
+#
+# * Measure the time to construct the string given by the expression
+#   <tt>"a"*1_000_000</tt>:
+#
+#       require 'benchmark'
+#
+#       puts Benchmark.measure { "a"*1_000_000 }
+# 
+#   On my machine (FreeBSD 3.2 on P5, 100MHz) this generates:
+# 
+#       1.166667   0.050000   1.216667 (  0.571355)
+# 
+#   This report shows the user CPU time, system CPU time, the sum of
+#   the user and system CPU times, and the elapsed real time. The unit
+#   of time is seconds.
+# 
+# * Do some experiments sequentially using the #bm method:
+#
+#       require 'benchmark'
+#
+#       n = 50000
+#       Benchmark.bm do |x|
+#         x.report { for i in 1..n; a = "1"; end }
+#         x.report { n.times do   ; a = "1"; end }
+#         x.report { 1.upto(n) do ; a = "1"; end }
+#       end
+# 
+#   The result:
+#
+#              user     system      total        real
+#          1.033333   0.016667   1.016667 (  0.492106)
+#          1.483333   0.000000   1.483333 (  0.694605)
+#          1.516667   0.000000   1.516667 (  0.711077)
+#
+# * Continuing the previous example, put a label in each report:
+#
+#       require 'benchmark'
+#
+#       n = 50000
+#       Benchmark.bm(7) do |x|
+#         x.report("for:")   { for i in 1..n; a = "1"; end }
+#         x.report("times:") { n.times do   ; a = "1"; end }
+#         x.report("upto:")  { 1.upto(n) do ; a = "1"; end }
+#       end
+# 
+# The result:
+# 
+#                     user     system      total        real
+#        for:     1.050000   0.000000   1.050000 (  0.503462)
+#        times:   1.533333   0.016667   1.550000 (  0.735473)
+#        upto:    1.500000   0.016667   1.516667 (  0.711239)
+# 
+#
+# * The times for some benchmarks depend on the order in which items
+#   are run.  These differences are due to the cost of memory
+#   allocation and garbage collection. To avoid these discrepancies,
+#   the #bmbm method is provided.  For example, to compare ways to
+#   sort an array of floats:
+#
+#       require 'benchmark'
+#       
+#       array = (1..1000000).map { rand }
+#       
+#       Benchmark.bmbm do |x|
+#         x.report("sort!") { array.dup.sort! }
+#         x.report("sort")  { array.dup.sort  }
+#       end
+# 
+#   The result:
+# 
+#        Rehearsal -----------------------------------------
+#        sort!  11.928000   0.010000  11.938000 ( 12.756000)
+#        sort   13.048000   0.020000  13.068000 ( 13.857000)
+#        ------------------------------- total: 25.006000sec
+#        
+#                    user     system      total        real
+#        sort!  12.959000   0.010000  12.969000 ( 13.793000)
+#        sort   12.007000   0.000000  12.007000 ( 12.791000)
+#
+#
+# * Report statistics of sequential experiments with unique labels,
+#   using the #benchmark method:
+#
+#       require 'benchmark'
+#
+#       n = 50000
+#       Benchmark.benchmark(" "*7 + CAPTION, 7, FMTSTR, ">total:", ">avg:") do |x|
+#         tf = x.report("for:")   { for i in 1..n; a = "1"; end }
+#         tt = x.report("times:") { n.times do   ; a = "1"; end }
+#         tu = x.report("upto:")  { 1.upto(n) do ; a = "1"; end }
+#         [tf+tt+tu, (tf+tt+tu)/3]
+#       end
+# 
+#   The result:
+# 
+#                     user     system      total        real
+#        for:     1.016667   0.016667   1.033333 (  0.485749)
+#        times:   1.450000   0.016667   1.466667 (  0.681367)
+#        upto:    1.533333   0.000000   1.533333 (  0.722166)
+#        >total:  4.000000   0.033333   4.033333 (  1.889282)
+#        >avg:    1.333333   0.011111   1.344444 (  0.629761)
+
+module Benchmark
+
+  BENCHMARK_VERSION = "2002-04-25" #:nodoc"
+
+  def Benchmark::times() # :nodoc:
+      Process::times()
+  end
+
+
+  # Invokes the block with a <tt>Benchmark::Report</tt> object, which
+  # may be used to collect and report on the results of individual
+  # benchmark tests. Reserves <i>label_width</i> leading spaces for
+  # labels on each line. Prints _caption_ at the top of the
+  # report, and uses _fmt_ to format each line.
+  # If the block returns an array of
+  # <tt>Benchmark::Tms</tt> objects, these will be used to format
+  # additional lines of output. If _label_ parameters are
+  # given, these are used to label these extra lines.
+  #
+  # _Note_: Other methods provide a simpler interface to this one, and are
+  # suitable for nearly all benchmarking requirements.  See the examples in
+  # Benchmark, and the #bm and #bmbm methods.
+  #
+  # Example: 
+  #
+  #     require 'benchmark'
+  #     include Benchmark          # we need the CAPTION and FMTSTR constants 
+  #
+  #     n = 50000
+  #     Benchmark.benchmark(" "*7 + CAPTION, 7, FMTSTR, ">total:", ">avg:") do |x|
+  #       tf = x.report("for:")   { for i in 1..n; a = "1"; end }
+  #       tt = x.report("times:") { n.times do   ; a = "1"; end }
+  #       tu = x.report("upto:")  { 1.upto(n) do ; a = "1"; end }
+  #       [tf+tt+tu, (tf+tt+tu)/3]
+  #     end
+  # 
+  # <i>Generates:</i>
+  # 
+  #                     user     system      total        real
+  #        for:     1.016667   0.016667   1.033333 (  0.485749)
+  #        times:   1.450000   0.016667   1.466667 (  0.681367)
+  #        upto:    1.533333   0.000000   1.533333 (  0.722166)
+  #        >total:  4.000000   0.033333   4.033333 (  1.889282)
+  #        >avg:    1.333333   0.011111   1.344444 (  0.629761)
+  # 
+
+  def benchmark(caption = "", label_width = nil, fmtstr = nil, *labels) # :yield: report
+    sync = STDOUT.sync
+    STDOUT.sync = true
+    label_width ||= 0
+    fmtstr ||= FMTSTR
+    raise ArgumentError, "no block" unless iterator?
+    print caption
+    results = yield(Report.new(label_width, fmtstr))
+    Array === results and results.grep(Tms).each {|t|
+      print((labels.shift || t.label || "").ljust(label_width), 
+            t.format(fmtstr))
+    }
+    STDOUT.sync = sync
+  end
+
+
+  # A simple interface to the #benchmark method, #bm is generates sequential reports
+  # with labels.  The parameters have the same meaning as for #benchmark.
+  # 
+  #     require 'benchmark'
+  #
+  #     n = 50000
+  #     Benchmark.bm(7) do |x|
+  #       x.report("for:")   { for i in 1..n; a = "1"; end }
+  #       x.report("times:") { n.times do   ; a = "1"; end }
+  #       x.report("upto:")  { 1.upto(n) do ; a = "1"; end }
+  #     end
+  # 
+  # <i>Generates:</i>
+  # 
+  #                     user     system      total        real
+  #        for:     1.050000   0.000000   1.050000 (  0.503462)
+  #        times:   1.533333   0.016667   1.550000 (  0.735473)
+  #        upto:    1.500000   0.016667   1.516667 (  0.711239)
+  #
+
+  def bm(label_width = 0, *labels, &blk) # :yield: report
+    benchmark(" "*label_width + CAPTION, label_width, FMTSTR, *labels, &blk)
+  end
+
+
+  # Sometimes benchmark results are skewed because code executed
+  # earlier encounters different garbage collection overheads than
+  # that run later. #bmbm attempts to minimize this effect by running
+  # the tests twice, the first time as a rehearsal in order to get the
+  # runtime environment stable, the second time for
+  # real. <tt>GC.start</tt> is executed before the start of each of
+  # the real timings; the cost of this is not included in the
+  # timings. In reality, though, there's only so much that #bmbm can
+  # do, and the results are not guaranteed to be isolated from garbage
+  # collection and other effects.
+  #
+  # Because #bmbm takes two passes through the tests, it can
+  # calculate the required label width.
+  #
+  #       require 'benchmark'
+  #       
+  #       array = (1..1000000).map { rand }
+  #       
+  #       Benchmark.bmbm do |x|
+  #         x.report("sort!") { array.dup.sort! }
+  #         x.report("sort")  { array.dup.sort  }
+  #       end
+  # 
+  # <i>Generates:</i>
+  # 
+  #        Rehearsal -----------------------------------------
+  #        sort!  11.928000   0.010000  11.938000 ( 12.756000)
+  #        sort   13.048000   0.020000  13.068000 ( 13.857000)
+  #        ------------------------------- total: 25.006000sec
+  #        
+  #                    user     system      total        real
+  #        sort!  12.959000   0.010000  12.969000 ( 13.793000)
+  #        sort   12.007000   0.000000  12.007000 ( 12.791000)
+  #
+  # #bmbm yields a Benchmark::Job object and returns an array of
+  # Benchmark::Tms objects.
+  #
+  def bmbm(width = 0, &blk) # :yield: job
+    job = Job.new(width)
+    yield(job)
+    width = job.width
+    sync = STDOUT.sync
+    STDOUT.sync = true
+
+    # rehearsal
+    print "Rehearsal "
+    puts '-'*(width+CAPTION.length - "Rehearsal ".length)
+    list = []
+    job.list.each{|label,item|
+      print(label.ljust(width))
+      res = Benchmark::measure(&item)
+      print res.format()
+      list.push res
+    }
+    sum = Tms.new; list.each{|i| sum += i}
+    ets = sum.format("total: %tsec")
+    printf("%s %s\n\n",
+           "-"*(width+CAPTION.length-ets.length-1), ets)
+    
+    # take
+    print ' '*width, CAPTION
+    list = []
+    ary = []
+    job.list.each{|label,item|
+      GC::start
+      print label.ljust(width)
+      res = Benchmark::measure(&item)
+      print res.format()
+      ary.push res
+      list.push [label, res]
+    }
+
+    STDOUT.sync = sync
+    ary
+  end
+
+  # 
+  # Returns the time used to execute the given block as a
+  # Benchmark::Tms object.
+  #
+  def measure(label = "") # :yield:
+    t0, r0 = Benchmark.times, Time.now
+    yield
+    t1, r1 = Benchmark.times, Time.now
+    Benchmark::Tms.new(t1.utime  - t0.utime, 
+                       t1.stime  - t0.stime, 
+                       t1.cutime - t0.cutime, 
+                       t1.cstime - t0.cstime, 
+                       r1.to_f - r0.to_f,
+                       label)
+  end
+
+  #
+  # Returns the elapsed real time used to execute the given block.
+  #
+  def realtime(&blk) # :yield:
+    Benchmark::measure(&blk).real
+  end
+
+
+
+  #
+  # A Job is a sequence of labelled blocks to be processed by the
+  # Benchmark.bmbm method.  It is of little direct interest to the user.
+  #
+  class Job # :nodoc:
+    #
+    # Returns an initialized Job instance.
+    # Usually, one doesn't call this method directly, as new
+    # Job objects are created by the #bmbm method.
+    # _width_ is a initial value for the label offset used in formatting;
+    # the #bmbm method passes its _width_ argument to this constructor. 
+    # 
+    def initialize(width)
+      @width = width
+      @list = []
+    end
+
+    #
+    # Registers the given label and block pair in the job list.
+    #
+    def item(label = "", &blk) # :yield:
+      raise ArgmentError, "no block" unless block_given?
+      label.concat ' '
+      w = label.length
+      @width = w if @width < w
+      @list.push [label, blk]
+      self
+    end
+
+    alias report item
+    
+    # An array of 2-element arrays, consisting of label and block pairs.
+    attr_reader :list
+    
+    # Length of the widest label in the #list, plus one.  
+    attr_reader :width
+  end
+
+  module_function :benchmark, :measure, :realtime, :bm, :bmbm
+
+
+
+  #
+  # This class is used by the Benchmark.benchmark and Benchmark.bm methods.
+  # It is of little direct interest to the user.
+  #
+  class Report # :nodoc:
+    #
+    # Returns an initialized Report instance.
+    # Usually, one doesn't call this method directly, as new
+    # Report objects are created by the #benchmark and #bm methods. 
+    # _width_ and _fmtstr_ are the label offset and 
+    # format string used by Tms#format. 
+    # 
+    def initialize(width = 0, fmtstr = nil)
+      @width, @fmtstr = width, fmtstr
+    end
+
+    #
+    # Prints the _label_ and measured time for the block,
+    # formatted by _fmt_. See Tms#format for the
+    # formatting rules.
+    #
+    def item(label = "", *fmt, &blk) # :yield:
+      print label.ljust(@width)
+      res = Benchmark::measure(&blk)
+      print res.format(@fmtstr, *fmt)
+      res
+    end
+
+    alias report item
+  end
+
+
+
+  #
+  # A data object, representing the times associated with a benchmark
+  # measurement.
+  #
+  class Tms
+    CAPTION = "      user     system      total        real\n"
+    FMTSTR = "%10.6u %10.6y %10.6t %10.6r\n"
+
+    # User CPU time
+    attr_reader :utime
+    
+    # System CPU time
+    attr_reader :stime
+   
+    # User CPU time of children
+    attr_reader :cutime
+    
+    # System CPU time of children
+    attr_reader :cstime
+    
+    # Elapsed real time
+    attr_reader :real
+    
+    # Total time, that is _utime_ + _stime_ + _cutime_ + _cstime_ 
+    attr_reader :total
+    
+    # Label
+    attr_reader :label
+
+    #
+    # Returns an initialized Tms object which has
+    # _u_ as the user CPU time, _s_ as the system CPU time, 
+    # _cu_ as the children's user CPU time, _cs_ as the children's
+    # system CPU time, _real_ as the elapsed real time and _l_
+    # as the label. 
+    # 
+    def initialize(u = 0.0, s = 0.0, cu = 0.0, cs = 0.0, real = 0.0, l = nil)
+      @utime, @stime, @cutime, @cstime, @real, @label = u, s, cu, cs, real, l
+      @total = @utime + @stime + @cutime + @cstime
+    end
+
+    # 
+    # Returns a new Tms object whose times are the sum of the times for this
+    # Tms object, plus the time required to execute the code block (_blk_).
+    # 
+    def add(&blk) # :yield:
+      self + Benchmark::measure(&blk) 
+    end
+
+    # 
+    # An in-place version of #add.
+    # 
+    def add!
+      t = Benchmark::measure(&blk) 
+      @utime  = utime + t.utime
+      @stime  = stime + t.stime
+      @cutime = cutime + t.cutime
+      @cstime = cstime + t.cstime
+      @real   = real + t.real
+      self
+    end
+
+    # 
+    # Returns a new Tms object obtained by memberwise summation
+    # of the individual times for this Tms object with those of the other
+    # Tms object.
+    # This method and #/() are useful for taking statistics. 
+    # 
+    def +(other); memberwise(:+, other) end
+    
+    #
+    # Returns a new Tms object obtained by memberwise subtraction
+    # of the individual times for the other Tms object from those of this
+    # Tms object.
+    #
+    def -(other); memberwise(:-, other) end
+    
+    #
+    # Returns a new Tms object obtained by memberwise multiplication
+    # of the individual times for this Tms object by _x_.
+    #
+    def *(x); memberwise(:*, x) end
+
+    # 
+    # Returns a new Tms object obtained by memberwise division
+    # of the individual times for this Tms object by _x_.
+    # This method and #+() are useful for taking statistics. 
+    # 
+    def /(x); memberwise(:/, x) end
+
+    #
+    # Returns the contents of this Tms object as
+    # a formatted string, according to a format string
+    # like that passed to Kernel.format. In addition, #format
+    # accepts the following extensions:
+    #
+    # <tt>%u</tt>::     Replaced by the user CPU time, as reported by Tms#utime.
+    # <tt>%y</tt>::     Replaced by the system CPU time, as reported by #stime (Mnemonic: y of "s*y*stem")
+    # <tt>%U</tt>::     Replaced by the children's user CPU time, as reported by Tms#cutime 
+    # <tt>%Y</tt>::     Replaced by the children's system CPU time, as reported by Tms#cstime
+    # <tt>%t</tt>::     Replaced by the total CPU time, as reported by Tms#total
+    # <tt>%r</tt>::     Replaced by the elapsed real time, as reported by Tms#real
+    # <tt>%n</tt>::     Replaced by the label string, as reported by Tms#label (Mnemonic: n of "*n*ame")
+    # 
+    # If _fmtstr_ is not given, FMTSTR is used as default value, detailing the
+    # user, system and real elapsed time.
+    # 
+    def format(arg0 = nil, *args)
+      fmtstr = (arg0 || FMTSTR).dup
+      fmtstr.gsub!(/(%[-+\.\d]*)n/){"#{$1}s" % label}
+      fmtstr.gsub!(/(%[-+\.\d]*)u/){"#{$1}f" % utime}
+      fmtstr.gsub!(/(%[-+\.\d]*)y/){"#{$1}f" % stime}
+      fmtstr.gsub!(/(%[-+\.\d]*)U/){"#{$1}f" % cutime}
+      fmtstr.gsub!(/(%[-+\.\d]*)Y/){"#{$1}f" % cstime}
+      fmtstr.gsub!(/(%[-+\.\d]*)t/){"#{$1}f" % total}
+      fmtstr.gsub!(/(%[-+\.\d]*)r/){"(#{$1}f)" % real}
+      arg0 ? Kernel::format(fmtstr, *args) : fmtstr
+    end
+
+    # 
+    # Same as #format.
+    # 
+    def to_s
+      format
+    end
+
+    # 
+    # Returns a new 6-element array, consisting of the
+    # label, user CPU time, system CPU time, children's
+    # user CPU time, children's system CPU time and elapsed
+    # real time.
+    # 
+    def to_a
+      [@label, @utime, @stime, @cutime, @cstime, @real]
+    end
+
+    protected
+    def memberwise(op, x)
+      case x
+      when Benchmark::Tms
+        Benchmark::Tms.new(utime.__send__(op, x.utime),
+                           stime.__send__(op, x.stime),
+                           cutime.__send__(op, x.cutime),
+                           cstime.__send__(op, x.cstime),
+                           real.__send__(op, x.real)
+                           )
+      else
+        Benchmark::Tms.new(utime.__send__(op, x),
+                           stime.__send__(op, x),
+                           cutime.__send__(op, x),
+                           cstime.__send__(op, x),
+                           real.__send__(op, x)
+                           )
+      end
+    end
+  end
+
+  # The default caption string (heading above the output times).
+  CAPTION = Benchmark::Tms::CAPTION
+
+  # The default format string used to display times.  See also Benchmark::Tms#format. 
+  FMTSTR = Benchmark::Tms::FMTSTR
+end
+
+if __FILE__ == $0
+  include Benchmark
+
+  n = ARGV[0].to_i.nonzero? || 50000
+  puts %Q([#{n} times iterations of `a = "1"'])
+  benchmark("       " + CAPTION, 7, FMTSTR) do |x|
+    x.report("for:")   {for i in 1..n; a = "1"; end} # Benchmark::measure
+    x.report("times:") {n.times do   ; a = "1"; end}
+    x.report("upto:")  {1.upto(n) do ; a = "1"; end}
+  end
+
+  benchmark do
+    [
+      measure{for i in 1..n; a = "1"; end},  # Benchmark::measure
+      measure{n.times do   ; a = "1"; end},
+      measure{1.upto(n) do ; a = "1"; end}
+    ]
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/jacobian.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/jacobian.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/jacobian.rb	(revision 18425)
@@ -0,0 +1,85 @@
+#
+# require 'bigdecimal/jacobian'
+#
+# Provides methods to compute the Jacobian matrix of a set of equations at a
+# point x. In the methods below:
+#
+# f is an Object which is used to compute the Jacobian matrix of the equations.
+# It must provide the following methods:
+#
+# f.values(x):: returns the values of all functions at x
+#
+# f.zero:: returns 0.0
+# f.one:: returns 1.0
+# f.two:: returns 1.0
+# f.ten:: returns 10.0
+#
+# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
+#
+# x is the point at which to compute the Jacobian.
+#
+# fx is f.values(x).
+#
+module Jacobian
+  #--
+  def isEqual(a,b,zero=0.0,e=1.0e-8)
+    aa = a.abs
+    bb = b.abs
+    if aa == zero &&  bb == zero then
+          true
+    else
+          if ((a-b)/(aa+bb)).abs < e then
+             true
+          else
+             false
+          end
+    end
+  end
+  #++
+
+  # Computes the derivative of f[i] at x[i].
+  # fx is the value of f at x.
+  def dfdxi(f,fx,x,i)
+    nRetry = 0
+    n = x.size
+    xSave = x[i]
+    ok = 0
+    ratio = f.ten*f.ten*f.ten
+    dx = x[i].abs/ratio
+    dx = fx[i].abs/ratio if isEqual(dx,f.zero,f.zero,f.eps)
+    dx = f.one/f.ten     if isEqual(dx,f.zero,f.zero,f.eps)
+    until ok>0 do
+      s = f.zero
+      deriv = []
+      if(nRetry>100) then
+         raize "Singular Jacobian matrix. No change at x[" + i.to_s + "]"
+      end
+      dx = dx*f.two
+      x[i] += dx
+      fxNew = f.values(x)
+      for j in 0...n do
+        if !isEqual(fxNew[j],fx[j],f.zero,f.eps) then
+           ok += 1
+           deriv <<= (fxNew[j]-fx[j])/dx
+        else
+           deriv <<= f.zero
+        end
+      end
+      x[i] = xSave
+    end
+    deriv
+  end
+
+  # Computes the Jacobian of f at x. fx is the value of f at x.
+  def jacobian(f,fx,x)
+    n = x.size
+    dfdx = Array::new(n*n)
+    for i in 0...n do
+      df = dfdxi(f,fx,x,i)
+      for j in 0...n do
+         dfdx[j*n+i] = df[j]
+      end
+    end
+    dfdx
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/ludcmp.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/ludcmp.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/ludcmp.rb	(revision 18425)
@@ -0,0 +1,84 @@
+#
+# Solves a*x = b for x, using LU decomposition.
+#
+module LUSolve
+  # Performs LU decomposition of the n by n matrix a.
+  def ludecomp(a,n,zero=0,one=1)
+    prec = BigDecimal.limit(nil)
+    ps     = []
+    scales = []
+    for i in 0...n do  # pick up largest(abs. val.) element in each row.
+      ps <<= i
+      nrmrow  = zero
+      ixn = i*n
+      for j in 0...n do
+         biggst = a[ixn+j].abs
+         nrmrow = biggst if biggst>nrmrow
+      end
+      if nrmrow>zero then
+         scales <<= one.div(nrmrow,prec)
+      else 
+         raise "Singular matrix"
+      end
+    end
+    n1          = n - 1
+    for k in 0...n1 do # Gaussian elimination with partial pivoting.
+      biggst  = zero;
+      for i in k...n do
+         size = a[ps[i]*n+k].abs*scales[ps[i]]
+         if size>biggst then
+            biggst = size
+            pividx  = i
+         end
+      end
+      raise "Singular matrix" if biggst<=zero
+      if pividx!=k then
+        j = ps[k]
+        ps[k] = ps[pividx]
+        ps[pividx] = j
+      end
+      pivot   = a[ps[k]*n+k]
+      for i in (k+1)...n do
+        psin = ps[i]*n
+        a[psin+k] = mult = a[psin+k].div(pivot,prec)
+        if mult!=zero then
+           pskn = ps[k]*n
+           for j in (k+1)...n do
+             a[psin+j] -= mult.mult(a[pskn+j],prec)
+           end
+        end
+      end
+    end
+    raise "Singular matrix" if a[ps[n1]*n+n1] == zero
+    ps
+  end
+
+  # Solves a*x = b for x, using LU decomposition.
+  #
+  # a is a matrix, b is a constant vector, x is the solution vector.
+  #
+  # ps is the pivot, a vector which indicates the permutation of rows performed
+  # during LU decomposition.
+  def lusolve(a,b,ps,zero=0.0)
+    prec = BigDecimal.limit(nil)
+    n = ps.size
+    x = []
+    for i in 0...n do
+      dot = zero
+      psin = ps[i]*n
+      for j in 0...i do
+        dot = a[psin+j].mult(x[j],prec) + dot
+      end
+      x <<= b[ps[i]] - dot
+    end
+    (n-1).downto(0) do |i|
+       dot = zero
+       psin = ps[i]*n
+       for j in (i+1)...n do
+         dot = a[psin+j].mult(x[j],prec) + dot
+       end
+       x[i]  = (x[i]-dot).div(a[psin+i],prec)
+    end
+    x
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/math.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/math.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/math.rb	(revision 18425)
@@ -0,0 +1,235 @@
+#
+#--
+# Contents:
+#   sqrt(x, prec)
+#   sin (x, prec)
+#   cos (x, prec)
+#   atan(x, prec)  Note: |x|<1, x=0.9999 may not converge.
+#   exp (x, prec)
+#   log (x, prec)
+#   PI  (prec)
+#   E   (prec) == exp(1.0,prec)
+#
+# where:
+#   x    ... BigDecimal number to be computed.
+#            |x| must be small enough to get convergence.
+#   prec ... Number of digits to be obtained.
+#++
+#
+# Provides mathematical functions.
+#
+# Example:
+#
+#   require "bigdecimal"
+#   require "bigdecimal/math"
+#
+#   include BigMath
+#
+#   a = BigDecimal((PI(100)/2).to_s)
+#   puts sin(a,100) # -> 0.10000000000000000000......E1
+#
+module BigMath
+
+  # Computes the square root of x to the specified number of digits of 
+  # precision.
+  #
+  # BigDecimal.new('2').sqrt(16).to_s 
+  #  -> "0.14142135623730950488016887242096975E1"
+  #
+  def sqrt(x,prec)
+    x.sqrt(prec)
+  end
+
+  # Computes the sine of x to the specified number of digits of precision.
+  #
+  # If x is infinite or NaN, returns NaN.
+  def sin(x, prec)
+    raise ArgumentError, "Zero or negative precision for sin" if prec <= 0
+    return BigDecimal("NaN") if x.infinite? || x.nan?
+    n    = prec + BigDecimal.double_fig
+    one  = BigDecimal("1")
+    two  = BigDecimal("2")
+    x1   = x
+    x2   = x.mult(x,n)
+    sign = 1
+    y    = x
+    d    = y
+    i    = one
+    z    = one
+    while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
+      m = BigDecimal.double_fig if m < BigDecimal.double_fig
+      sign = -sign
+      x1  = x2.mult(x1,n)
+      i  += two
+      z  *= (i-one) * i
+      d   = sign * x1.div(z,m)
+      y  += d
+    end
+    y
+  end
+
+  # Computes the cosine of x to the specified number of digits of precision.
+  #
+  # If x is infinite or NaN, returns NaN.
+  def cos(x, prec)
+    raise ArgumentError, "Zero or negative precision for cos" if prec <= 0
+    return BigDecimal("NaN") if x.infinite? || x.nan?
+    n    = prec + BigDecimal.double_fig
+    one  = BigDecimal("1")
+    two  = BigDecimal("2")
+    x1 = one
+    x2 = x.mult(x,n)
+    sign = 1
+    y = one
+    d = y
+    i = BigDecimal("0")
+    z = one
+    while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
+      m = BigDecimal.double_fig if m < BigDecimal.double_fig
+      sign = -sign
+      x1  = x2.mult(x1,n)
+      i  += two
+      z  *= (i-one) * i
+      d   = sign * x1.div(z,m)
+      y  += d
+    end
+    y
+  end
+
+  # Computes the arctangent of x to the specified number of digits of precision.
+  #
+  # If x is infinite or NaN, returns NaN.
+  # Raises an argument error if x > 1.
+  def atan(x, prec)
+    raise ArgumentError, "Zero or negative precision for atan" if prec <= 0
+    return BigDecimal("NaN") if x.infinite? || x.nan?
+    raise ArgumentError, "x.abs must be less than 1.0" if x.abs>=1
+    n    = prec + BigDecimal.double_fig
+    y = x
+    d = y
+    t = x
+    r = BigDecimal("3")
+    x2 = x.mult(x,n)
+    while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
+      m = BigDecimal.double_fig if m < BigDecimal.double_fig
+      t = -t.mult(x2,n)
+      d = t.div(r,m)
+      y += d
+      r += 2
+    end
+    y
+  end
+
+  # Computes the value of e (the base of natural logarithms) raised to the 
+  # power of x, to the specified number of digits of precision.
+  #
+  # If x is infinite or NaN, returns NaN.
+  #
+  # BigMath::exp(BigDecimal.new('1'), 10).to_s
+  # -> "0.271828182845904523536028752390026306410273E1"
+  def exp(x, prec)
+    raise ArgumentError, "Zero or negative precision for exp" if prec <= 0
+    return BigDecimal("NaN") if x.infinite? || x.nan?
+    n    = prec + BigDecimal.double_fig
+    one  = BigDecimal("1")
+    x1 = one
+    y  = one
+    d  = y
+    z  = one
+    i  = 0
+    while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
+      m = BigDecimal.double_fig if m < BigDecimal.double_fig
+      x1  = x1.mult(x,n)
+      i += 1
+      z *= i
+      d  = x1.div(z,m)
+      y += d
+    end
+    y
+  end
+
+  # Computes the natural logarithm of x to the specified number of digits 
+  # of precision.
+  #
+  # Returns x if x is infinite or NaN.
+  #
+  def log(x, prec)
+    raise ArgumentError, "Zero or negative argument for log" if x <= 0 || prec <= 0
+    return x if x.infinite? || x.nan?
+    one = BigDecimal("1")
+    two = BigDecimal("2")
+    n  = prec + BigDecimal.double_fig
+    x  = (x - one).div(x + one,n)
+    x2 = x.mult(x,n)
+    y  = x
+    d  = y
+    i = one
+    while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
+      m = BigDecimal.double_fig if m < BigDecimal.double_fig
+      x  = x2.mult(x,n)
+      i += two
+      d  = x.div(i,m)
+      y += d
+    end
+    y*two
+  end
+
+  # Computes the value of pi to the specified number of digits of precision.
+  def PI(prec)
+    raise ArgumentError, "Zero or negative argument for PI" if prec <= 0
+    n      = prec + BigDecimal.double_fig
+    zero   = BigDecimal("0")
+    one    = BigDecimal("1")
+    two    = BigDecimal("2")
+
+    m25    = BigDecimal("-0.04")
+    m57121 = BigDecimal("-57121")
+
+    pi     = zero
+
+    d = one
+    k = one
+    w = one
+    t = BigDecimal("-80")
+    while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0)
+      m = BigDecimal.double_fig if m < BigDecimal.double_fig
+      t   = t*m25
+      d   = t.div(k,m)
+      k   = k+two
+      pi  = pi + d
+    end
+
+    d = one
+    k = one
+    w = one
+    t = BigDecimal("956")
+    while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0)
+      m = BigDecimal.double_fig if m < BigDecimal.double_fig
+      t   = t.div(m57121,n)
+      d   = t.div(k,m)
+      pi  = pi + d
+      k   = k+two
+    end
+    pi
+  end
+
+  # Computes e (the base of natural logarithms) to the specified number of
+  # digits of precision.
+  def E(prec)
+    raise ArgumentError, "Zero or negative precision for E" if prec <= 0
+    n    = prec + BigDecimal.double_fig
+    one  = BigDecimal("1")
+    y  = one
+    d  = y
+    z  = one
+    i  = 0
+    while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
+      m = BigDecimal.double_fig if m < BigDecimal.double_fig
+      i += 1
+      z *= i
+      d  = one.div(z,m)
+      y += d
+    end
+    y
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/newton.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/newton.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/newton.rb	(revision 18425)
@@ -0,0 +1,77 @@
+#
+# newton.rb 
+#
+# Solves the nonlinear algebraic equation system f = 0 by Newton's method.
+# This program is not dependent on BigDecimal.
+#
+# To call:
+#    n = nlsolve(f,x)
+#  where n is the number of iterations required,
+#        x is the initial value vector
+#        f is an Object which is used to compute the values of the equations to be solved.
+# It must provide the following methods:
+#
+# f.values(x):: returns the values of all functions at x
+#
+# f.zero:: returns 0.0
+# f.one:: returns 1.0
+# f.two:: returns 1.0
+# f.ten:: returns 10.0
+#
+# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
+#
+# On exit, x is the solution vector.
+#
+require "bigdecimal/ludcmp"
+require "bigdecimal/jacobian"
+
+module Newton
+  include LUSolve
+  include Jacobian
+  
+  def norm(fv,zero=0.0)
+    s = zero
+    n = fv.size
+    for i in 0...n do
+      s += fv[i]*fv[i]
+    end
+    s
+  end
+
+  def nlsolve(f,x)
+    nRetry = 0
+    n = x.size
+
+    f0 = f.values(x)
+    zero = f.zero
+    one  = f.one
+    two  = f.two
+    p5 = one/two
+    d  = norm(f0,zero)
+    minfact = f.ten*f.ten*f.ten
+    minfact = one/minfact
+    e = f.eps
+    while d >= e do
+      nRetry += 1
+      # Not yet converged. => Compute Jacobian matrix
+      dfdx = jacobian(f,f0,x)
+      # Solve dfdx*dx = -f0 to estimate dx
+      dx = lusolve(dfdx,f0,ludecomp(dfdx,n,zero,one),zero)
+      fact = two
+      xs = x.dup
+      begin
+        fact *= p5
+        if fact < minfact then
+          raise "Failed to reduce function values."
+        end
+        for i in 0...n do
+          x[i] = xs[i] - dx[i]*fact
+        end
+        f0 = f.values(x)
+        dn = norm(f0,zero)
+      end while(dn>=d)
+      d = dn
+    end
+    nRetry
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/util.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/util.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/bigdecimal/util.rb	(revision 18425)
@@ -0,0 +1,65 @@
+#
+# BigDecimal utility library.
+#
+# To use these functions, require 'bigdecimal/util'
+#
+# The following methods are provided to convert other types to BigDecimals:
+#
+#   String#to_d -> BigDecimal
+#   Float#to_d -> BigDecimal
+#   Rational#to_d -> BigDecimal
+#
+# The following method is provided to convert BigDecimals to other types:
+#
+#   BigDecimal#to_r -> Rational
+#
+# ----------------------------------------------------------------------
+#
+class Float < Numeric
+  def to_d
+    BigDecimal(self.to_s)
+  end
+end
+
+class String
+  def to_d
+    BigDecimal(self)
+  end
+end
+
+class BigDecimal < Numeric
+  # Converts a BigDecimal to a String of the form "nnnnnn.mmm".
+  # This method is deprecated; use BigDecimal#to_s("F") instead.
+  def to_digits
+     if self.nan? || self.infinite? || self.zero?
+        self.to_s
+     else
+       i       = self.to_i.to_s
+       s,f,y,z = self.frac.split
+       i + "." + ("0"*(-z)) + f
+     end
+  end
+
+  # Converts a BigDecimal to a Rational.
+  def to_r 
+     sign,digits,base,power = self.split
+     numerator = sign*digits.to_i
+     denomi_power = power - digits.size # base is always 10
+     if denomi_power < 0
+        Rational(numerator,base ** (-denomi_power))
+     else
+        Rational(numerator * (base ** denomi_power),1)
+     end
+  end
+end
+
+class Rational < Numeric
+  # Converts a Rational to a BigDecimal
+  def to_d(nFig=0)
+     num = self.numerator.to_s
+     if nFig<=0
+        nFig = BigDecimal.double_fig*2+1
+     end
+     BigDecimal.new(num).div(self.denominator,nFig)
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/cgi-lib.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/cgi-lib.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/cgi-lib.rb	(revision 18425)
@@ -0,0 +1,272 @@
+warn "Warning:#{caller[0].sub(/:in `.*'\z/, '')}: cgi-lib is deprecated after Ruby 1.8.1; use cgi instead"
+
+=begin
+
+= simple CGI support library
+
+= example
+
+== get form values
+
+	require "cgi-lib.rb"
+	query = CGI.new
+	query['field']   # <== value of 'field'
+	query.keys       # <== array of fields
+
+and query has Hash class methods
+
+
+== get cookie values
+
+	require "cgi-lib.rb"
+	query = CGI.new
+	query.cookie['name']  # <== cookie value of 'name'
+	query.cookie.keys     # <== all cookie names
+
+and query.cookie has Hash class methods
+
+
+== print HTTP header and HTML string to $>
+
+	require "cgi-lib.rb"
+	CGI::print{
+	  CGI::tag("HTML"){
+	    CGI::tag("HEAD"){ CGI::tag("TITLE"){"TITLE"} } +
+	    CGI::tag("BODY"){
+	      CGI::tag("FORM", {"ACTION"=>"test.rb", "METHOD"=>"POST"}){
+	        CGI::tag("INPUT", {"TYPE"=>"submit", "VALUE"=>"submit"})
+	      } +
+	      CGI::tag("HR")
+	    }
+	  }
+	}
+
+
+== make raw cookie string
+
+	require "cgi-lib.rb"
+	cookie1 = CGI::cookie({'name'    => 'name',
+	                       'value'   => 'value',
+	                       'path'    => 'path',   # optional
+	                       'domain'  => 'domain', # optional
+	                       'expires' => Time.now, # optional
+	                       'secure'  => true      # optional
+	                      })
+
+	CGI::print("Content-Type: text/html", cookie1, cookie2){ "string" }
+
+
+== print HTTP header and string to $>
+
+	require "cgi-lib.rb"
+	CGI::print{ "string" }
+	  # == CGI::print("Content-Type: text/html"){ "string" }
+	CGI::print("Content-Type: text/html", cookie1, cookie2){ "string" }
+
+
+=== NPH (no-parse-header) mode
+
+	require "cgi-lib.rb"
+	CGI::print("nph"){ "string" }
+	  # == CGI::print("nph", "Content-Type: text/html"){ "string" }
+	CGI::print("nph", "Content-Type: text/html", cookie1, cookie2){ "string" }
+
+
+== make HTML tag string
+
+	require "cgi-lib.rb"
+	CGI::tag("element", {"attribute_name"=>"attribute_value"}){"content"}
+
+
+== make HTTP header string
+
+	require "cgi-lib.rb"
+	CGI::header # == CGI::header("Content-Type: text/html")
+	CGI::header("Content-Type: text/html", cookie1, cookie2)
+
+
+=== NPH (no-parse-header) mode
+
+	CGI::header("nph") # == CGI::header("nph", "Content-Type: text/html")
+	CGI::header("nph", "Content-Type: text/html", cookie1, cookie2)
+
+
+== escape url encode
+
+	require "cgi-lib.rb"
+	url_encoded_string = CGI::escape("string")
+
+
+== unescape url encoded
+
+	require "cgi-lib.rb"
+	string = CGI::unescape("url encoded string")
+
+
+== escape HTML &"<>
+
+	require "cgi-lib.rb"
+	CGI::escapeHTML("string")
+
+
+=end
+
+require "delegate"
+
+class CGI < SimpleDelegator
+
+  CR  = "\015"
+  LF  = "\012"
+  EOL = CR + LF
+
+  RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
+  RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
+
+  # make rfc1123 date string
+  def CGI::rfc1123_date(time)
+    t = time.clone.gmtime
+    return format("%s, %.2d %s %d %.2d:%.2d:%.2d GMT",
+                RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
+                t.hour, t.min, t.sec)
+  end
+
+  # escape url encode
+  def CGI::escape(str)
+    str.gsub(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) }
+  end
+
+  # unescape url encoded
+  def CGI::unescape(str)
+    str.gsub(/\+/, ' ').gsub(/%([0-9a-fA-F]{2})/){ [$1.hex].pack("c") }
+  end
+
+  # escape HTML
+  def CGI::escapeHTML(str)
+    str.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
+  end
+
+  # offline mode. read name=value pairs on standard input.
+  def read_from_cmdline
+    require "shellwords.rb"
+    words = Shellwords.shellwords(
+              if not ARGV.empty?
+                ARGV.join(' ')
+              else
+                STDERR.print "(offline mode: enter name=value pairs on standard input)\n" if STDIN.tty?
+                readlines.join(' ').gsub(/\n/, '')
+              end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26'))
+
+    if words.find{|x| x =~ /=/} then words.join('&') else words.join('+') end
+  end
+
+  def initialize(input = $stdin)
+
+    @inputs = {}
+    @cookie = {}
+
+    case ENV['REQUEST_METHOD']
+    when "GET"
+      ENV['QUERY_STRING'] or ""
+    when "POST"
+      input.read(Integer(ENV['CONTENT_LENGTH'])) or ""
+    else
+      read_from_cmdline
+    end.split(/[&;]/).each do |x|
+      key, val = x.split(/=/,2).collect{|x|CGI::unescape(x)}
+      if @inputs.include?(key)
+        @inputs[key] += "\0" + (val or "")
+      else
+        @inputs[key] = (val or "")
+      end
+    end
+
+    super(@inputs)
+
+    if ENV.has_key?('HTTP_COOKIE') or ENV.has_key?('COOKIE')
+      (ENV['HTTP_COOKIE'] or ENV['COOKIE']).split(/; /).each do |x|
+        key, val = x.split(/=/,2)
+        key = CGI::unescape(key)
+        val = val.split(/&/).collect{|x|CGI::unescape(x)}.join("\0")
+        if @cookie.include?(key)
+          @cookie[key] += "\0" + val
+        else
+          @cookie[key] = val
+        end
+      end
+    end
+  end
+
+  attr("inputs")
+  attr("cookie")
+
+  # make HTML tag string
+  def CGI::tag(element, attributes = {})
+    "<" + escapeHTML(element) + attributes.collect{|name, value|
+      " " + escapeHTML(name) + '="' + escapeHTML(value) + '"'
+    }.to_s + ">" +
+    (iterator? ? yield.to_s + "</" + escapeHTML(element) + ">" : "")
+  end
+
+  # make raw cookie string
+  def CGI::cookie(options)
+    "Set-Cookie: " + options['name'] + '=' + escape(options['value']) +
+    (options['domain']  ? '; domain='  + options['domain'] : '') +
+    (options['path']    ? '; path='    + options['path']   : '') +
+    (options['expires'] ? '; expires=' + rfc1123_date(options['expires']) : '') +
+    (options['secure']  ? '; secure' : '')
+  end
+
+  # make HTTP header string
+  def CGI::header(*options)
+    if defined?(MOD_RUBY)
+      options.each{|option|
+        option.sub(/(.*?): (.*)/){
+          Apache::request.headers_out[$1] = $2
+        }
+      }
+      Apache::request.send_http_header
+      ''
+    else
+      if options.delete("nph") or (ENV['SERVER_SOFTWARE'] =~ /IIS/)
+        [(ENV['SERVER_PROTOCOL'] or "HTTP/1.0") + " 200 OK",
+         "Date: " + rfc1123_date(Time.now),
+         "Server: " + (ENV['SERVER_SOFTWARE'] or ""),
+         "Connection: close"] +
+        (options.empty? ? ["Content-Type: text/html"] : options)
+      else
+        options.empty? ? ["Content-Type: text/html"] : options
+      end.join(EOL) + EOL + EOL
+    end
+  end
+
+  # print HTTP header and string to $>
+  def CGI::print(*options)
+    $>.print CGI::header(*options) + yield.to_s
+  end
+
+  # print message to $>
+  def CGI::message(message, title = "", header = ["Content-Type: text/html"])
+    if message.kind_of?(Hash)
+      title   = message['title']
+      header  = message['header']
+      message = message['body']
+    end
+    CGI::print(*header){
+      CGI::tag("HTML"){
+        CGI::tag("HEAD"){ CGI.tag("TITLE"){ title } } +
+        CGI::tag("BODY"){ message }
+      }
+    }
+    true
+  end
+
+  # print error message to $> and exit
+  def CGI::error
+    CGI::message({'title'=>'ERROR', 'body'=>
+      CGI::tag("PRE"){
+        "ERROR: " + CGI::tag("STRONG"){ escapeHTML($!.to_s) } + "\n" + escapeHTML($@.join("\n"))
+      }
+    })
+    exit
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/cgi.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/cgi.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/cgi.rb	(revision 18425)
@@ -0,0 +1,2302 @@
+# 
+# cgi.rb - cgi support library
+# 
+# Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
+# 
+# Copyright (C) 2000  Information-technology Promotion Agency, Japan
+#
+# Author: Wakou Aoyama <wakou@ruby-lang.org>
+#
+# Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber) 
+# 
+# == Overview
+#
+# The Common Gateway Interface (CGI) is a simple protocol
+# for passing an HTTP request from a web server to a
+# standalone program, and returning the output to the web
+# browser.  Basically, a CGI program is called with the
+# parameters of the request passed in either in the
+# environment (GET) or via $stdin (POST), and everything
+# it prints to $stdout is returned to the client.
+# 
+# This file holds the +CGI+ class.  This class provides
+# functionality for retrieving HTTP request parameters,
+# managing cookies, and generating HTML output.  See the
+# class documentation for more details and examples of use.
+#
+# The file cgi/session.rb provides session management
+# functionality; see that file for more details.
+#
+# See http://www.w3.org/CGI/ for more information on the CGI
+# protocol.
+
+raise "Please, use ruby 1.5.4 or later." if RUBY_VERSION < "1.5.4"
+
+require 'English'
+
+# CGI class.  See documentation for the file cgi.rb for an overview
+# of the CGI protocol.
+#
+# == Introduction
+#
+# CGI is a large class, providing several categories of methods, many of which
+# are mixed in from other modules.  Some of the documentation is in this class,
+# some in the modules CGI::QueryExtension and CGI::HtmlExtension.  See
+# CGI::Cookie for specific information on handling cookies, and cgi/session.rb
+# (CGI::Session) for information on sessions.
+#
+# For queries, CGI provides methods to get at environmental variables,
+# parameters, cookies, and multipart request data.  For responses, CGI provides
+# methods for writing output and generating HTML.
+#
+# Read on for more details.  Examples are provided at the bottom.
+#
+# == Queries
+#
+# The CGI class dynamically mixes in parameter and cookie-parsing
+# functionality,  environmental variable access, and support for
+# parsing multipart requests (including uploaded files) from the
+# CGI::QueryExtension module.
+#
+# === Environmental Variables
+#
+# The standard CGI environmental variables are available as read-only
+# attributes of a CGI object.  The following is a list of these variables:
+#
+#
+#   AUTH_TYPE               HTTP_HOST          REMOTE_IDENT
+#   CONTENT_LENGTH          HTTP_NEGOTIATE     REMOTE_USER
+#   CONTENT_TYPE            HTTP_PRAGMA        REQUEST_METHOD
+#   GATEWAY_INTERFACE       HTTP_REFERER       SCRIPT_NAME
+#   HTTP_ACCEPT             HTTP_USER_AGENT    SERVER_NAME
+#   HTTP_ACCEPT_CHARSET     PATH_INFO          SERVER_PORT
+#   HTTP_ACCEPT_ENCODING    PATH_TRANSLATED    SERVER_PROTOCOL
+#   HTTP_ACCEPT_LANGUAGE    QUERY_STRING       SERVER_SOFTWARE
+#   HTTP_CACHE_CONTROL      REMOTE_ADDR
+#   HTTP_FROM               REMOTE_HOST
+#
+#
+# For each of these variables, there is a corresponding attribute with the
+# same name, except all lower case and without a preceding HTTP_.  
+# +content_length+ and +server_port+ are integers; the rest are strings.
+#
+# === Parameters
+#
+# The method #params() returns a hash of all parameters in the request as
+# name/value-list pairs, where the value-list is an Array of one or more
+# values.  The CGI object itself also behaves as a hash of parameter names 
+# to values, but only returns a single value (as a String) for each 
+# parameter name.
+#
+# For instance, suppose the request contains the parameter 
+# "favourite_colours" with the multiple values "blue" and "green".  The
+# following behaviour would occur:
+#
+#   cgi.params["favourite_colours"]  # => ["blue", "green"]
+#   cgi["favourite_colours"]         # => "blue"
+#
+# If a parameter does not exist, the former method will return an empty
+# array, the latter an empty string.  The simplest way to test for existence
+# of a parameter is by the #has_key? method.
+#
+# === Cookies
+#
+# HTTP Cookies are automatically parsed from the request.  They are available
+# from the #cookies() accessor, which returns a hash from cookie name to
+# CGI::Cookie object.
+#
+# === Multipart requests
+#
+# If a request's method is POST and its content type is multipart/form-data, 
+# then it may contain uploaded files.  These are stored by the QueryExtension
+# module in the parameters of the request.  The parameter name is the name
+# attribute of the file input field, as usual.  However, the value is not
+# a string, but an IO object, either an IOString for small files, or a
+# Tempfile for larger ones.  This object also has the additional singleton
+# methods:
+#
+# #local_path():: the path of the uploaded file on the local filesystem
+# #original_filename():: the name of the file on the client computer
+# #content_type():: the content type of the file
+#
+# == Responses
+#
+# The CGI class provides methods for sending header and content output to
+# the HTTP client, and mixes in methods for programmatic HTML generation
+# from CGI::HtmlExtension and CGI::TagMaker modules.  The precise version of HTML
+# to use for HTML generation is specified at object creation time.
+#
+# === Writing output
+#
+# The simplest way to send output to the HTTP client is using the #out() method.
+# This takes the HTTP headers as a hash parameter, and the body content
+# via a block.  The headers can be generated as a string using the #header()
+# method.  The output stream can be written directly to using the #print()
+# method.
+#
+# === Generating HTML
+#
+# Each HTML element has a corresponding method for generating that
+# element as a String.  The name of this method is the same as that
+# of the element, all lowercase.  The attributes of the element are 
+# passed in as a hash, and the body as a no-argument block that evaluates
+# to a String.  The HTML generation module knows which elements are
+# always empty, and silently drops any passed-in body.  It also knows
+# which elements require matching closing tags and which don't.  However,
+# it does not know what attributes are legal for which elements.
+#
+# There are also some additional HTML generation methods mixed in from
+# the CGI::HtmlExtension module.  These include individual methods for the
+# different types of form inputs, and methods for elements that commonly
+# take particular attributes where the attributes can be directly specified
+# as arguments, rather than via a hash.
+#
+# == Examples of use
+# 
+# === Get form values
+# 
+#   require "cgi"
+#   cgi = CGI.new
+#   value = cgi['field_name']   # <== value string for 'field_name'
+#     # if not 'field_name' included, then return "".
+#   fields = cgi.keys            # <== array of field names
+# 
+#   # returns true if form has 'field_name'
+#   cgi.has_key?('field_name')
+#   cgi.has_key?('field_name')
+#   cgi.include?('field_name')
+# 
+# CAUTION! cgi['field_name'] returned an Array with the old 
+# cgi.rb(included in ruby 1.6)
+# 
+# === Get form values as hash
+# 
+#   require "cgi"
+#   cgi = CGI.new
+#   params = cgi.params
+# 
+# cgi.params is a hash.
+# 
+#   cgi.params['new_field_name'] = ["value"]  # add new param
+#   cgi.params['field_name'] = ["new_value"]  # change value
+#   cgi.params.delete('field_name')           # delete param
+#   cgi.params.clear                          # delete all params
+# 
+# 
+# === Save form values to file
+# 
+#   require "pstore"
+#   db = PStore.new("query.db")
+#   db.transaction do
+#     db["params"] = cgi.params
+#   end
+# 
+# 
+# === Restore form values from file
+# 
+#   require "pstore"
+#   db = PStore.new("query.db")
+#   db.transaction do
+#     cgi.params = db["params"]
+#   end
+# 
+# 
+# === Get multipart form values
+# 
+#   require "cgi"
+#   cgi = CGI.new
+#   value = cgi['field_name']   # <== value string for 'field_name'
+#   value.read                  # <== body of value
+#   value.local_path            # <== path to local file of value
+#   value.original_filename     # <== original filename of value
+#   value.content_type          # <== content_type of value
+# 
+# and value has StringIO or Tempfile class methods.
+# 
+# === Get cookie values
+# 
+#   require "cgi"
+#   cgi = CGI.new
+#   values = cgi.cookies['name']  # <== array of 'name'
+#     # if not 'name' included, then return [].
+#   names = cgi.cookies.keys      # <== array of cookie names
+# 
+# and cgi.cookies is a hash.
+# 
+# === Get cookie objects
+# 
+#   require "cgi"
+#   cgi = CGI.new
+#   for name, cookie in cgi.cookies
+#     cookie.expires = Time.now + 30
+#   end
+#   cgi.out("cookie" => cgi.cookies) {"string"}
+# 
+#   cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... }
+# 
+#   require "cgi"
+#   cgi = CGI.new
+#   cgi.cookies['name'].expires = Time.now + 30
+#   cgi.out("cookie" => cgi.cookies['name']) {"string"}
+# 
+# === Print http header and html string to $DEFAULT_OUTPUT ($>)
+# 
+#   require "cgi"
+#   cgi = CGI.new("html3")  # add HTML generation methods
+#   cgi.out() do
+#     cgi.html() do
+#       cgi.head{ cgi.title{"TITLE"} } +
+#       cgi.body() do
+#         cgi.form() do
+#           cgi.textarea("get_text") +
+#           cgi.br +
+#           cgi.submit
+#         end +
+#         cgi.pre() do
+#           CGI::escapeHTML(
+#             "params: " + cgi.params.inspect + "\n" +
+#             "cookies: " + cgi.cookies.inspect + "\n" +
+#             ENV.collect() do |key, value|
+#               key + " --> " + value + "\n"
+#             end.join("")
+#           )
+#         end
+#       end
+#     end
+#   end
+# 
+#   # add HTML generation methods
+#   CGI.new("html3")    # html3.2
+#   CGI.new("html4")    # html4.01 (Strict)
+#   CGI.new("html4Tr")  # html4.01 Transitional
+#   CGI.new("html4Fr")  # html4.01 Frameset
+#
+class CGI
+
+  # :stopdoc:
+
+  # String for carriage return
+  CR  = "\015"
+
+  # String for linefeed
+  LF  = "\012"
+
+  # Standard internet newline sequence
+  EOL = CR + LF
+
+  REVISION = '$Id: cgi.rb 12050 2007-03-12 17:55:03Z knu $' #:nodoc:
+
+  NEEDS_BINMODE = true if /WIN/ni.match(RUBY_PLATFORM) 
+
+  # Path separators in different environments.
+  PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'}
+
+  # HTTP status codes.
+  HTTP_STATUS = {
+    "OK"                  => "200 OK",
+    "PARTIAL_CONTENT"     => "206 Partial Content",
+    "MULTIPLE_CHOICES"    => "300 Multiple Choices",
+    "MOVED"               => "301 Moved Permanently",
+    "REDIRECT"            => "302 Found",
+    "NOT_MODIFIED"        => "304 Not Modified",
+    "BAD_REQUEST"         => "400 Bad Request",
+    "AUTH_REQUIRED"       => "401 Authorization Required",
+    "FORBIDDEN"           => "403 Forbidden",
+    "NOT_FOUND"           => "404 Not Found",
+    "METHOD_NOT_ALLOWED"  => "405 Method Not Allowed",
+    "NOT_ACCEPTABLE"      => "406 Not Acceptable",
+    "LENGTH_REQUIRED"     => "411 Length Required",
+    "PRECONDITION_FAILED" => "412 Rrecondition Failed",
+    "SERVER_ERROR"        => "500 Internal Server Error",
+    "NOT_IMPLEMENTED"     => "501 Method Not Implemented",
+    "BAD_GATEWAY"         => "502 Bad Gateway",
+    "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates"
+  }
+
+  # Abbreviated day-of-week names specified by RFC 822
+  RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
+
+  # Abbreviated month names specified by RFC 822
+  RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
+
+  # :startdoc:
+
+  def env_table 
+    ENV
+  end
+
+  def stdinput
+    $stdin
+  end
+
+  def stdoutput
+    $DEFAULT_OUTPUT
+  end
+
+  private :env_table, :stdinput, :stdoutput
+
+  # URL-encode a string.
+  #   url_encoded_string = CGI::escape("'Stop!' said Fred")
+  #      # => "%27Stop%21%27+said+Fred"
+  def CGI::escape(string)
+    string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
+      '%' + $1.unpack('H2' * $1.size).join('%').upcase
+    end.tr(' ', '+')
+  end
+
+
+  # URL-decode a string.
+  #   string = CGI::unescape("%27Stop%21%27+said+Fred")
+  #      # => "'Stop!' said Fred"
+  def CGI::unescape(string)
+    string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do
+      [$1.delete('%')].pack('H*')
+    end
+  end
+
+
+  # Escape special characters in HTML, namely &\"<>
+  #   CGI::escapeHTML('Usage: foo "bar" <baz>')
+  #      # => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
+  def CGI::escapeHTML(string)
+    string.gsub(/&/n, '&amp;').gsub(/\"/n, '&quot;').gsub(/>/n, '&gt;').gsub(/</n, '&lt;')
+  end
+
+
+  # Unescape a string that has been HTML-escaped
+  #   CGI::unescapeHTML("Usage: foo &quot;bar&quot; &lt;baz&gt;")
+  #      # => "Usage: foo \"bar\" <baz>"
+  def CGI::unescapeHTML(string)
+    string.gsub(/&(amp|quot|gt|lt|\#[0-9]+|\#x[0-9A-Fa-f]+);/n) do
+      match = $1.dup
+      case match
+      when 'amp'                 then '&'
+      when 'quot'                then '"'
+      when 'gt'                  then '>'
+      when 'lt'                  then '<'
+      when /\A#0*(\d+)\z/n       then
+        if Integer($1) < 256
+          Integer($1).chr
+        else
+          if Integer($1) < 65536 and ($KCODE[0] == ?u or $KCODE[0] == ?U)
+            [Integer($1)].pack("U")
+          else
+            "&##{$1};"
+          end
+        end
+      when /\A#x([0-9a-f]+)\z/ni then
+        if $1.hex < 256
+          $1.hex.chr
+        else
+          if $1.hex < 65536 and ($KCODE[0] == ?u or $KCODE[0] == ?U)
+            [$1.hex].pack("U")
+          else
+            "&#x#{$1};"
+          end
+        end
+      else
+        "&#{match};"
+      end
+    end
+  end
+
+
+  # Escape only the tags of certain HTML elements in +string+.
+  #
+  # Takes an element or elements or array of elements.  Each element
+  # is specified by the name of the element, without angle brackets.
+  # This matches both the start and the end tag of that element.
+  # The attribute list of the open tag will also be escaped (for
+  # instance, the double-quotes surrounding attribute values).
+  #
+  #   print CGI::escapeElement('<BR><A HREF="url"></A>', "A", "IMG")
+  #     # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
+  #
+  #   print CGI::escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
+  #     # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
+  def CGI::escapeElement(string, *elements)
+    elements = elements[0] if elements[0].kind_of?(Array)
+    unless elements.empty?
+      string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/ni) do
+        CGI::escapeHTML($&)
+      end
+    else
+      string
+    end
+  end
+
+
+  # Undo escaping such as that done by CGI::escapeElement()
+  #
+  #   print CGI::unescapeElement(
+  #           CGI::escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
+  #     # "&lt;BR&gt;<A HREF="url"></A>"
+  # 
+  #   print CGI::unescapeElement(
+  #           CGI::escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
+  #     # "&lt;BR&gt;<A HREF="url"></A>"
+  def CGI::unescapeElement(string, *elements)
+    elements = elements[0] if elements[0].kind_of?(Array)
+    unless elements.empty?
+      string.gsub(/&lt;\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?&gt;/ni) do
+        CGI::unescapeHTML($&)
+      end
+    else
+      string
+    end
+  end
+
+
+  # Format a +Time+ object as a String using the format specified by RFC 1123.
+  #
+  #   CGI::rfc1123_date(Time.now)
+  #     # Sat, 01 Jan 2000 00:00:00 GMT
+  def CGI::rfc1123_date(time)
+    t = time.clone.gmtime
+    return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
+                RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
+                t.hour, t.min, t.sec)
+  end
+
+
+  # Create an HTTP header block as a string.
+  #
+  # Includes the empty line that ends the header block.
+  #
+  # +options+ can be a string specifying the Content-Type (defaults
+  # to text/html), or a hash of header key/value pairs.  The following
+  # header keys are recognized:
+  #
+  # type:: the Content-Type header.  Defaults to "text/html"
+  # charset:: the charset of the body, appended to the Content-Type header.
+  # nph:: a boolean value.  If true, prepend protocol string and status code, and
+  #       date; and sets default values for "server" and "connection" if not
+  #       explicitly set.
+  # status:: the HTTP status code, returned as the Status header.  See the
+  #          list of available status codes below.
+  # server:: the server software, returned as the Server header.
+  # connection:: the connection type, returned as the Connection header (for 
+  #              instance, "close".
+  # length:: the length of the content that will be sent, returned as the
+  #          Content-Length header.
+  # language:: the language of the content, returned as the Content-Language
+  #            header.
+  # expires:: the time on which the current content expires, as a +Time+
+  #           object, returned as the Expires header.
+  # cookie:: a cookie or cookies, returned as one or more Set-Cookie headers.
+  #          The value can be the literal string of the cookie; a CGI::Cookie
+  #          object; an Array of literal cookie strings or Cookie objects; or a 
+  #          hash all of whose values are literal cookie strings or Cookie objects.
+  #          These cookies are in addition to the cookies held in the
+  #          @output_cookies field.
+  #
+  # Other header lines can also be set; they are appended as key: value.
+  # 
+  #   header
+  #     # Content-Type: text/html
+  # 
+  #   header("text/plain")
+  #     # Content-Type: text/plain
+  # 
+  #   header("nph"        => true,
+  #          "status"     => "OK",  # == "200 OK"
+  #            # "status"     => "200 GOOD",
+  #          "server"     => ENV['SERVER_SOFTWARE'],
+  #          "connection" => "close",
+  #          "type"       => "text/html",
+  #          "charset"    => "iso-2022-jp",
+  #            # Content-Type: text/html; charset=iso-2022-jp
+  #          "length"     => 103,
+  #          "language"   => "ja",
+  #          "expires"    => Time.now + 30,
+  #          "cookie"     => [cookie1, cookie2],
+  #          "my_header1" => "my_value"
+  #          "my_header2" => "my_value")
+  # 
+  # The status codes are:
+  # 
+  #   "OK"                  --> "200 OK"
+  #   "PARTIAL_CONTENT"     --> "206 Partial Content"
+  #   "MULTIPLE_CHOICES"    --> "300 Multiple Choices"
+  #   "MOVED"               --> "301 Moved Permanently"
+  #   "REDIRECT"            --> "302 Found"
+  #   "NOT_MODIFIED"        --> "304 Not Modified"
+  #   "BAD_REQUEST"         --> "400 Bad Request"
+  #   "AUTH_REQUIRED"       --> "401 Authorization Required"
+  #   "FORBIDDEN"           --> "403 Forbidden"
+  #   "NOT_FOUND"           --> "404 Not Found"
+  #   "METHOD_NOT_ALLOWED"  --> "405 Method Not Allowed"
+  #   "NOT_ACCEPTABLE"      --> "406 Not Acceptable"
+  #   "LENGTH_REQUIRED"     --> "411 Length Required"
+  #   "PRECONDITION_FAILED" --> "412 Precondition Failed"
+  #   "SERVER_ERROR"        --> "500 Internal Server Error"
+  #   "NOT_IMPLEMENTED"     --> "501 Method Not Implemented"
+  #   "BAD_GATEWAY"         --> "502 Bad Gateway"
+  #   "VARIANT_ALSO_VARIES" --> "506 Variant Also Negotiates"
+  # 
+  # This method does not perform charset conversion. 
+  #
+  def header(options = "text/html")
+
+    buf = ""
+
+    case options
+    when String
+      options = { "type" => options }
+    when Hash
+      options = options.dup
+    end
+
+    unless options.has_key?("type")
+      options["type"] = "text/html"
+    end
+
+    if options.has_key?("charset")
+      options["type"] += "; charset=" + options.delete("charset")
+    end
+
+    options.delete("nph") if defined?(MOD_RUBY)
+    if options.delete("nph") or
+        (/IIS\/(\d+)/n.match(env_table['SERVER_SOFTWARE']) and $1.to_i < 5)
+      buf += (env_table["SERVER_PROTOCOL"] or "HTTP/1.0")  + " " +
+             (HTTP_STATUS[options["status"]] or options["status"] or "200 OK") +
+             EOL +
+             "Date: " + CGI::rfc1123_date(Time.now) + EOL
+
+      unless options.has_key?("server")
+        options["server"] = (env_table['SERVER_SOFTWARE'] or "")
+      end
+
+      unless options.has_key?("connection")
+        options["connection"] = "close"
+      end
+
+      options.delete("status")
+    end
+
+    if options.has_key?("status")
+      buf += "Status: " +
+             (HTTP_STATUS[options["status"]] or options["status"]) + EOL
+      options.delete("status")
+    end
+
+    if options.has_key?("server")
+      buf += "Server: " + options.delete("server") + EOL
+    end
+
+    if options.has_key?("connection")
+      buf += "Connection: " + options.delete("connection") + EOL
+    end
+
+    buf += "Content-Type: " + options.delete("type") + EOL
+
+    if options.has_key?("length")
+      buf += "Content-Length: " + options.delete("length").to_s + EOL
+    end
+
+    if options.has_key?("language")
+      buf += "Content-Language: " + options.delete("language") + EOL
+    end
+
+    if options.has_key?("expires")
+      buf += "Expires: " + CGI::rfc1123_date( options.delete("expires") ) + EOL
+    end
+
+    if options.has_key?("cookie")
+      if options["cookie"].kind_of?(String) or
+           options["cookie"].kind_of?(Cookie)
+        buf += "Set-Cookie: " + options.delete("cookie").to_s + EOL
+      elsif options["cookie"].kind_of?(Array)
+        options.delete("cookie").each{|cookie|
+          buf += "Set-Cookie: " + cookie.to_s + EOL
+        }
+      elsif options["cookie"].kind_of?(Hash)
+        options.delete("cookie").each_value{|cookie|
+          buf += "Set-Cookie: " + cookie.to_s + EOL
+        }
+      end
+    end
+    if @output_cookies
+      for cookie in @output_cookies
+        buf += "Set-Cookie: " + cookie.to_s + EOL
+      end
+    end
+
+    options.each{|key, value|
+      buf += key + ": " + value.to_s + EOL
+    }
+
+    if defined?(MOD_RUBY)
+      table = Apache::request.headers_out
+      buf.scan(/([^:]+): (.+)#{EOL}/n){ |name, value|
+        warn sprintf("name:%s value:%s\n", name, value) if $DEBUG
+        case name
+        when 'Set-Cookie'
+          table.add(name, value)
+        when /^status$/ni
+          Apache::request.status_line = value
+          Apache::request.status = value.to_i
+        when /^content-type$/ni
+          Apache::request.content_type = value
+        when /^content-encoding$/ni
+          Apache::request.content_encoding = value
+        when /^location$/ni
+	  if Apache::request.status == 200
+	    Apache::request.status = 302
+	  end
+          Apache::request.headers_out[name] = value
+        else
+          Apache::request.headers_out[name] = value
+        end
+      }
+      Apache::request.send_http_header
+      ''
+    else
+      buf + EOL
+    end
+
+  end # header()
+
+
+  # Print an HTTP header and body to $DEFAULT_OUTPUT ($>)
+  #
+  # The header is provided by +options+, as for #header().
+  # The body of the document is that returned by the passed-
+  # in block.  This block takes no arguments.  It is required.
+  #
+  #   cgi = CGI.new
+  #   cgi.out{ "string" }
+  #     # Content-Type: text/html
+  #     # Content-Length: 6
+  #     #
+  #     # string
+  # 
+  #   cgi.out("text/plain") { "string" }
+  #     # Content-Type: text/plain
+  #     # Content-Length: 6
+  #     #
+  #     # string
+  # 
+  #   cgi.out("nph"        => true,
+  #           "status"     => "OK",  # == "200 OK"
+  #           "server"     => ENV['SERVER_SOFTWARE'],
+  #           "connection" => "close",
+  #           "type"       => "text/html",
+  #           "charset"    => "iso-2022-jp",
+  #             # Content-Type: text/html; charset=iso-2022-jp
+  #           "language"   => "ja",
+  #           "expires"    => Time.now + (3600 * 24 * 30),
+  #           "cookie"     => [cookie1, cookie2],
+  #           "my_header1" => "my_value",
+  #           "my_header2" => "my_value") { "string" }
+  # 
+  # Content-Length is automatically calculated from the size of
+  # the String returned by the content block.
+  #
+  # If ENV['REQUEST_METHOD'] == "HEAD", then only the header
+  # is outputted (the content block is still required, but it
+  # is ignored).
+  # 
+  # If the charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then
+  # the content is converted to this charset, and the language is set 
+  # to "ja".
+  def out(options = "text/html") # :yield:
+
+    options = { "type" => options } if options.kind_of?(String)
+    content = yield
+
+    if options.has_key?("charset")
+      require "nkf"
+      case options["charset"]
+      when /iso-2022-jp/ni
+        content = NKF::nkf('-m0 -x -j', content)
+        options["language"] = "ja" unless options.has_key?("language")
+      when /euc-jp/ni
+        content = NKF::nkf('-m0 -x -e', content)
+        options["language"] = "ja" unless options.has_key?("language")
+      when /shift_jis/ni
+        content = NKF::nkf('-m0 -x -s', content)
+        options["language"] = "ja" unless options.has_key?("language")
+      end
+    end
+
+    options["length"] = content.length.to_s
+    output = stdoutput
+    output.binmode if defined? output.binmode
+    output.print header(options)
+    output.print content unless "HEAD" == env_table['REQUEST_METHOD']
+  end
+
+
+  # Print an argument or list of arguments to the default output stream
+  #
+  #   cgi = CGI.new
+  #   cgi.print    # default:  cgi.print == $DEFAULT_OUTPUT.print
+  def print(*options)
+    stdoutput.print(*options)
+  end
+
+  require "delegate"
+
+  # Class representing an HTTP cookie.
+  #
+  # In addition to its specific fields and methods, a Cookie instance
+  # is a delegator to the array of its values.
+  #
+  # See RFC 2965.
+  #
+  # == Examples of use
+  #   cookie1 = CGI::Cookie::new("name", "value1", "value2", ...)
+  #   cookie1 = CGI::Cookie::new("name" => "name", "value" => "value")
+  #   cookie1 = CGI::Cookie::new('name'    => 'name',
+  #                              'value'   => ['value1', 'value2', ...],
+  #                              'path'    => 'path',   # optional
+  #                              'domain'  => 'domain', # optional
+  #                              'expires' => Time.now, # optional
+  #                              'secure'  => true      # optional
+  #                             )
+  # 
+  #   cgi.out("cookie" => [cookie1, cookie2]) { "string" }
+  # 
+  #   name    = cookie1.name
+  #   values  = cookie1.value
+  #   path    = cookie1.path
+  #   domain  = cookie1.domain
+  #   expires = cookie1.expires
+  #   secure  = cookie1.secure
+  # 
+  #   cookie1.name    = 'name'
+  #   cookie1.value   = ['value1', 'value2', ...]
+  #   cookie1.path    = 'path'
+  #   cookie1.domain  = 'domain'
+  #   cookie1.expires = Time.now + 30
+  #   cookie1.secure  = true
+  class Cookie < DelegateClass(Array)
+
+    # Create a new CGI::Cookie object.
+    #
+    # The contents of the cookie can be specified as a +name+ and one
+    # or more +value+ arguments.  Alternatively, the contents can
+    # be specified as a single hash argument.  The possible keywords of
+    # this hash are as follows:
+    #
+    # name:: the name of the cookie.  Required.
+    # value:: the cookie's value or list of values.
+    # path:: the path for which this cookie applies.  Defaults to the
+    #        base directory of the CGI script.
+    # domain:: the domain for which this cookie applies.
+    # expires:: the time at which this cookie expires, as a +Time+ object.
+    # secure:: whether this cookie is a secure cookie or not (default to
+    #          false).  Secure cookies are only transmitted to HTTPS 
+    #          servers.
+    #
+    # These keywords correspond to attributes of the cookie object.
+    def initialize(name = "", *value)
+      options = if name.kind_of?(String)
+                  { "name" => name, "value" => value }
+                else
+                  name
+                end
+      unless options.has_key?("name")
+        raise ArgumentError, "`name' required"
+      end
+
+      @name = options["name"]
+      @value = Array(options["value"])
+      # simple support for IE
+      if options["path"]
+        @path = options["path"]
+      else
+        %r|^(.*/)|.match(ENV["SCRIPT_NAME"])
+        @path = ($1 or "")
+      end
+      @domain = options["domain"]
+      @expires = options["expires"]
+      @secure = options["secure"] == true ? true : false
+
+      super(@value)
+    end
+
+    attr_accessor("name", "value", "path", "domain", "expires")
+    attr_reader("secure")
+
+    # Set whether the Cookie is a secure cookie or not.
+    #
+    # +val+ must be a boolean.
+    def secure=(val)
+      @secure = val if val == true or val == false
+      @secure
+    end
+
+    # Convert the Cookie to its string representation.
+    def to_s
+      buf = ""
+      buf += @name + '='
+
+      if @value.kind_of?(String)
+        buf += CGI::escape(@value)
+      else
+        buf += @value.collect{|v| CGI::escape(v) }.join("&")
+      end
+
+      if @domain
+        buf += '; domain=' + @domain
+      end
+
+      if @path
+        buf += '; path=' + @path
+      end
+
+      if @expires
+        buf += '; expires=' + CGI::rfc1123_date(@expires)
+      end
+
+      if @secure == true
+        buf += '; secure'
+      end
+
+      buf
+    end
+
+  end # class Cookie
+
+
+  # Parse a raw cookie string into a hash of cookie-name=>Cookie
+  # pairs.
+  #
+  #   cookies = CGI::Cookie::parse("raw_cookie_string")
+  #     # { "name1" => cookie1, "name2" => cookie2, ... }
+  #
+  def Cookie::parse(raw_cookie)
+    cookies = Hash.new([])
+    return cookies unless raw_cookie
+
+    raw_cookie.split(/[;,]\s?/).each do |pairs|
+      name, values = pairs.split('=',2)
+      next unless name and values
+      name = CGI::unescape(name)
+      values ||= ""
+      values = values.split('&').collect{|v| CGI::unescape(v) }
+      if cookies.has_key?(name)
+        values = cookies[name].value + values
+      end
+      cookies[name] = Cookie::new({ "name" => name, "value" => values })
+    end
+
+    cookies
+  end
+
+  # Parse an HTTP query string into a hash of key=>value pairs.
+  #
+  #   params = CGI::parse("query_string")
+  #     # {"name1" => ["value1", "value2", ...],
+  #     #  "name2" => ["value1", "value2", ...], ... }
+  #
+  def CGI::parse(query)
+    params = Hash.new([].freeze)
+
+    query.split(/[&;]/n).each do |pairs|
+      key, value = pairs.split('=',2).collect{|v| CGI::unescape(v) }
+      if params.has_key?(key)
+        params[key].push(value)
+      else
+        params[key] = [value]
+      end
+    end
+
+    params
+  end
+
+  # Mixin module. It provides the follow functionality groups:
+  #
+  # 1. Access to CGI environment variables as methods.  See 
+  #    documentation to the CGI class for a list of these variables.
+  #
+  # 2. Access to cookies, including the cookies attribute.
+  #
+  # 3. Access to parameters, including the params attribute, and overloading
+  #    [] to perform parameter value lookup by key.
+  #
+  # 4. The initialize_query method, for initialising the above
+  #    mechanisms, handling multipart forms, and allowing the
+  #    class to be used in "offline" mode.
+  #
+  module QueryExtension
+
+    %w[ CONTENT_LENGTH SERVER_PORT ].each do |env|
+      define_method(env.sub(/^HTTP_/n, '').downcase) do
+        (val = env_table[env]) && Integer(val)
+      end
+    end
+
+    %w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO
+        PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST
+        REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME
+        SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE
+
+        HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
+        HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST
+        HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env|
+      define_method(env.sub(/^HTTP_/n, '').downcase) do
+        env_table[env]
+      end
+    end
+
+    # Get the raw cookies as a string.
+    def raw_cookie
+      env_table["HTTP_COOKIE"]
+    end
+
+    # Get the raw RFC2965 cookies as a string.
+    def raw_cookie2
+      env_table["HTTP_COOKIE2"]
+    end
+
+    # Get the cookies as a hash of cookie-name=>Cookie pairs.
+    attr_accessor("cookies")
+
+    # Get the parameters as a hash of name=>values pairs, where
+    # values is an Array.
+    attr("params")
+
+    # Set all the parameters.
+    def params=(hash)
+      @params.clear
+      @params.update(hash)
+    end
+
+    def read_multipart(boundary, content_length)
+      params = Hash.new([])
+      boundary = "--" + boundary
+      quoted_boundary = Regexp.quote(boundary, "n")
+      buf = ""
+      bufsize = 10 * 1024
+      boundary_end=""
+
+      # start multipart/form-data
+      stdinput.binmode if defined? stdinput.binmode
+      boundary_size = boundary.size + EOL.size
+      content_length -= boundary_size
+      status = stdinput.read(boundary_size)
+      if nil == status
+        raise EOFError, "no content body"
+      elsif boundary + EOL != status
+        raise EOFError, "bad content body"
+      end
+
+      loop do
+        head = nil
+        if 10240 < content_length
+          require "tempfile"
+          body = Tempfile.new("CGI")
+        else
+          begin
+            require "stringio"
+            body = StringIO.new
+          rescue LoadError
+            require "tempfile"
+            body = Tempfile.new("CGI")
+          end
+        end
+        body.binmode if defined? body.binmode
+
+        until head and /#{quoted_boundary}(?:#{EOL}|--)/n.match(buf)
+
+          if (not head) and /#{EOL}#{EOL}/n.match(buf)
+            buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
+              head = $1.dup
+              ""
+            end
+            next
+          end
+
+          if head and ( (EOL + boundary + EOL).size < buf.size )
+            body.print buf[0 ... (buf.size - (EOL + boundary + EOL).size)]
+            buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
+          end
+
+          c = if bufsize < content_length
+                stdinput.read(bufsize)
+              else
+                stdinput.read(content_length)
+              end
+          if c.nil? || c.empty?
+            raise EOFError, "bad content body"
+          end
+          buf.concat(c)
+          content_length -= c.size
+        end
+
+        buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do
+          body.print $1
+          if "--" == $2
+            content_length = -1
+          end
+         boundary_end = $2.dup
+          ""
+        end
+
+        body.rewind
+
+        /Content-Disposition:.* filename=(?:"((?:\\.|[^\"])*)"|([^;]*))/ni.match(head)
+	filename = ($1 or $2 or "")
+	if /Mac/ni.match(env_table['HTTP_USER_AGENT']) and
+	    /Mozilla/ni.match(env_table['HTTP_USER_AGENT']) and
+	    (not /MSIE/ni.match(env_table['HTTP_USER_AGENT']))
+	  filename = CGI::unescape(filename)
+	end
+        
+        /Content-Type: (.*)/ni.match(head)
+        content_type = ($1 or "")
+
+        (class << body; self; end).class_eval do
+          alias local_path path
+          define_method(:original_filename) {filename.dup.taint}
+          define_method(:content_type) {content_type.dup.taint}
+        end
+
+        /Content-Disposition:.* name="?([^\";]*)"?/ni.match(head)
+        name = $1.dup
+
+        if params.has_key?(name)
+          params[name].push(body)
+        else
+          params[name] = [body]
+        end
+        break if buf.size == 0
+        break if content_length == -1
+      end
+      raise EOFError, "bad boundary end of body part" unless boundary_end=~/--/
+
+      params
+    end # read_multipart
+    private :read_multipart
+
+    # offline mode. read name=value pairs on standard input.
+    def read_from_cmdline
+      require "shellwords"
+
+      string = unless ARGV.empty?
+        ARGV.join(' ')
+      else
+        if STDIN.tty?
+          STDERR.print(
+            %|(offline mode: enter name=value pairs on standard input)\n|
+          )
+        end
+        readlines.join(' ').gsub(/\n/n, '')
+      end.gsub(/\\=/n, '%3D').gsub(/\\&/n, '%26')
+
+      words = Shellwords.shellwords(string)
+
+      if words.find{|x| /=/n.match(x) }
+        words.join('&')
+      else
+        words.join('+')
+      end
+    end
+    private :read_from_cmdline
+
+    # Initialize the data from the query.
+    #
+    # Handles multipart forms (in particular, forms that involve file uploads).
+    # Reads query parameters in the @params field, and cookies into @cookies.
+    def initialize_query()
+      if ("POST" == env_table['REQUEST_METHOD']) and
+         %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n.match(env_table['CONTENT_TYPE'])
+        boundary = $1.dup
+        @multipart = true
+        @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
+      else
+        @multipart = false
+        @params = CGI::parse(
+                    case env_table['REQUEST_METHOD']
+                    when "GET", "HEAD"
+                      if defined?(MOD_RUBY)
+                        Apache::request.args or ""
+                      else
+                        env_table['QUERY_STRING'] or ""
+                      end
+                    when "POST"
+                      stdinput.binmode if defined? stdinput.binmode
+                      stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or ''
+                    else
+                      read_from_cmdline
+                    end
+                  )
+      end
+
+      @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or env_table['COOKIE']))
+    end
+    private :initialize_query
+
+    def multipart?
+      @multipart
+    end
+
+    module Value    # :nodoc:
+      def set_params(params)
+        @params = params
+      end
+      def [](idx, *args)
+        if args.size == 0
+          warn "#{caller(1)[0]}:CAUTION! cgi['key'] == cgi.params['key'][0]; if want Array, use cgi.params['key']"
+          @params[idx]
+        else
+          super[idx,*args]
+        end
+      end
+      def first
+        warn "#{caller(1)[0]}:CAUTION! cgi['key'] == cgi.params['key'][0]; if want Array, use cgi.params['key']"
+        self
+      end
+      alias last first
+      def to_a
+        @params || [self]
+      end
+      alias to_ary to_a   	# to be rhs of multiple assignment
+    end
+
+    # Get the value for the parameter with a given key.
+    #
+    # If the parameter has multiple values, only the first will be 
+    # retrieved; use #params() to get the array of values.
+    def [](key)
+      params = @params[key]
+      value = params[0]
+      if @multipart
+        if value
+          return value
+        elsif defined? StringIO
+          StringIO.new("")
+        else
+          Tempfile.new("CGI")
+        end
+      else
+        str = if value then value.dup else "" end
+        str.extend(Value)
+        str.set_params(params)
+        str
+      end
+    end
+
+    # Return all parameter keys as an array.
+    def keys(*args)
+      @params.keys(*args)
+    end
+
+    # Returns true if a given parameter key exists in the query.
+    def has_key?(*args)
+      @params.has_key?(*args)
+    end
+    alias key? has_key?
+    alias include? has_key?
+
+  end # QueryExtension
+
+
+  # Prettify (indent) an HTML string.
+  #
+  # +string+ is the HTML string to indent.  +shift+ is the indentation
+  # unit to use; it defaults to two spaces.
+  #
+  #   print CGI::pretty("<HTML><BODY></BODY></HTML>")
+  #     # <HTML>
+  #     #   <BODY>
+  #     #   </BODY>
+  #     # </HTML>
+  # 
+  #   print CGI::pretty("<HTML><BODY></BODY></HTML>", "\t")
+  #     # <HTML>
+  #     #         <BODY>
+  #     #         </BODY>
+  #     # </HTML>
+  #
+  def CGI::pretty(string, shift = "  ")
+    lines = string.gsub(/(?!\A)<(?:.|\n)*?>/n, "\n\\0").gsub(/<(?:.|\n)*?>(?!\n)/n, "\\0\n")
+    end_pos = 0
+    while end_pos = lines.index(/^<\/(\w+)/n, end_pos)
+      element = $1.dup
+      start_pos = lines.rindex(/^\s*<#{element}/ni, end_pos)
+      lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/n, "\n" + shift) + "__"
+    end
+    lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/n, '\1')
+  end
+
+
+  # Base module for HTML-generation mixins.
+  #
+  # Provides methods for code generation for tags following
+  # the various DTD element types.
+  module TagMaker # :nodoc:
+
+    # Generate code for an element with required start and end tags.
+    #
+    #   - -
+    def nn_element_def(element)
+      nOE_element_def(element, <<-END)
+          if block_given?
+            yield.to_s
+          else
+            ""
+          end +
+          "</#{element.upcase}>"
+      END
+    end
+
+    # Generate code for an empty element.
+    #
+    #   - O EMPTY
+    def nOE_element_def(element, append = nil)
+      s = <<-END
+          "<#{element.upcase}" + attributes.collect{|name, value|
+            next unless value
+            " " + CGI::escapeHTML(name) +
+            if true == value
+              ""
+            else
+              '="' + CGI::escapeHTML(value) + '"'
+            end
+          }.to_s + ">"
+      END
+      s.sub!(/\Z/, " +") << append if append
+      s
+    end
+
+    # Generate code for an element for which the end (and possibly the
+    # start) tag is optional.
+    #
+    #   O O or - O
+    def nO_element_def(element)
+      nOE_element_def(element, <<-END)
+          if block_given?
+            yield.to_s + "</#{element.upcase}>"
+          else
+            ""
+          end
+      END
+    end
+
+  end # TagMaker
+
+
+  #
+  # Mixin module providing HTML generation methods.
+  #
+  # For example,
+  #   cgi.a("http://www.example.com") { "Example" }
+  #     # => "<A HREF=\"http://www.example.com\">Example</A>"
+  #
+  # Modules Http3, Http4, etc., contain more basic HTML-generation methods
+  # (:title, :center, etc.).
+  #
+  # See class CGI for a detailed example. 
+  #
+  module HtmlExtension
+
+
+    # Generate an Anchor element as a string.
+    #
+    # +href+ can either be a string, giving the URL
+    # for the HREF attribute, or it can be a hash of
+    # the element's attributes.
+    #
+    # The body of the element is the string returned by the no-argument
+    # block passed in.
+    #
+    #   a("http://www.example.com") { "Example" }
+    #     # => "<A HREF=\"http://www.example.com\">Example</A>"
+    #
+    #   a("HREF" => "http://www.example.com", "TARGET" => "_top") { "Example" }
+    #     # => "<A HREF=\"http://www.example.com\" TARGET=\"_top\">Example</A>"
+    #
+    def a(href = "") # :yield:
+      attributes = if href.kind_of?(String)
+                     { "HREF" => href }
+                   else
+                     href
+                   end
+      if block_given?
+        super(attributes){ yield }
+      else
+        super(attributes)
+      end
+    end
+
+    # Generate a Document Base URI element as a String. 
+    #
+    # +href+ can either by a string, giving the base URL for the HREF
+    # attribute, or it can be a has of the element's attributes.
+    #
+    # The passed-in no-argument block is ignored.
+    #
+    #   base("http://www.example.com/cgi")
+    #     # => "<BASE HREF=\"http://www.example.com/cgi\">"
+    def base(href = "") # :yield:
+      attributes = if href.kind_of?(String)
+                     { "HREF" => href }
+                   else
+                     href
+                   end
+      if block_given?
+        super(attributes){ yield }
+      else
+        super(attributes)
+      end
+    end
+
+    # Generate a BlockQuote element as a string.
+    #
+    # +cite+ can either be a string, give the URI for the source of
+    # the quoted text, or a hash, giving all attributes of the element,
+    # or it can be omitted, in which case the element has no attributes.
+    #
+    # The body is provided by the passed-in no-argument block
+    #
+    #   blockquote("http://www.example.com/quotes/foo.html") { "Foo!" }
+    #     #=> "<BLOCKQUOTE CITE=\"http://www.example.com/quotes/foo.html\">Foo!</BLOCKQUOTE>
+    def blockquote(cite = nil)  # :yield:
+      attributes = if cite.kind_of?(String)
+                     { "CITE" => cite }
+                   else
+                     cite or ""
+                   end
+      if block_given?
+        super(attributes){ yield }
+      else
+        super(attributes)
+      end
+    end
+
+
+    # Generate a Table Caption element as a string.
+    #
+    # +align+ can be a string, giving the alignment of the caption
+    # (one of top, bottom, left, or right).  It can be a hash of
+    # all the attributes of the element.  Or it can be omitted.
+    #
+    # The body of the element is provided by the passed-in no-argument block.
+    #
+    #   caption("left") { "Capital Cities" }
+    #     # => <CAPTION ALIGN=\"left\">Capital Cities</CAPTION>
+    def caption(align = nil) # :yield:
+      attributes = if align.kind_of?(String)
+                     { "ALIGN" => align }
+                   else
+                     align or ""
+                   end
+      if block_given?
+        super(attributes){ yield }
+      else
+        super(attributes)
+      end
+    end
+
+
+    # Generate a Checkbox Input element as a string.
+    #
+    # The attributes of the element can be specified as three arguments,
+    # +name+, +value+, and +checked+.  +checked+ is a boolean value;
+    # if true, the CHECKED attribute will be included in the element.
+    #
+    # Alternatively, the attributes can be specified as a hash.
+    #
+    #   checkbox("name")
+    #     # = checkbox("NAME" => "name")
+    # 
+    #   checkbox("name", "value")
+    #     # = checkbox("NAME" => "name", "VALUE" => "value")
+    # 
+    #   checkbox("name", "value", true)
+    #     # = checkbox("NAME" => "name", "VALUE" => "value", "CHECKED" => true)
+    def checkbox(name = "", value = nil, checked = nil)
+      attributes = if name.kind_of?(String)
+                     { "TYPE" => "checkbox", "NAME" => name,
+                       "VALUE" => value, "CHECKED" => checked }
+                   else
+                     name["TYPE"] = "checkbox"
+                     name
+                   end
+      input(attributes)
+    end
+
+    # Generate a sequence of checkbox elements, as a String.
+    #
+    # The checkboxes will all have the same +name+ attribute.
+    # Each checkbox is followed by a label.
+    # There will be one checkbox for each value.  Each value
+    # can be specified as a String, which will be used both
+    # as the value of the VALUE attribute and as the label
+    # for that checkbox.  A single-element array has the
+    # same effect.
+    #
+    # Each value can also be specified as a three-element array.
+    # The first element is the VALUE attribute; the second is the
+    # label; and the third is a boolean specifying whether this
+    # checkbox is CHECKED.
+    #
+    # Each value can also be specified as a two-element
+    # array, by omitting either the value element (defaults
+    # to the same as the label), or the boolean checked element
+    # (defaults to false).
+    #
+    #   checkbox_group("name", "foo", "bar", "baz")
+    #     # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
+    #     # <INPUT TYPE="checkbox" NAME="name" VALUE="bar">bar
+    #     # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
+    # 
+    #   checkbox_group("name", ["foo"], ["bar", true], "baz")
+    #     # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
+    #     # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="bar">bar
+    #     # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
+    # 
+    #   checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
+    #     # <INPUT TYPE="checkbox" NAME="name" VALUE="1">Foo
+    #     # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="2">Bar
+    #     # <INPUT TYPE="checkbox" NAME="name" VALUE="Baz">Baz
+    # 
+    #   checkbox_group("NAME" => "name",
+    #                    "VALUES" => ["foo", "bar", "baz"])
+    # 
+    #   checkbox_group("NAME" => "name",
+    #                    "VALUES" => [["foo"], ["bar", true], "baz"])
+    # 
+    #   checkbox_group("NAME" => "name",
+    #                    "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
+    def checkbox_group(name = "", *values)
+      if name.kind_of?(Hash)
+        values = name["VALUES"]
+        name = name["NAME"]
+      end
+      values.collect{|value|
+        if value.kind_of?(String)
+          checkbox(name, value) + value
+        else
+          if value[value.size - 1] == true
+            checkbox(name, value[0], true) +
+            value[value.size - 2]
+          else
+            checkbox(name, value[0]) +
+            value[value.size - 1]
+          end
+        end
+      }.to_s
+    end
+
+
+    # Generate an File Upload Input element as a string.
+    #
+    # The attributes of the element can be specified as three arguments,
+    # +name+, +size+, and +maxlength+.  +maxlength+ is the maximum length
+    # of the file's _name_, not of the file's _contents_.
+    #
+    # Alternatively, the attributes can be specified as a hash.
+    #
+    # See #multipart_form() for forms that include file uploads.
+    #
+    #   file_field("name")
+    #     # <INPUT TYPE="file" NAME="name" SIZE="20">
+    # 
+    #   file_field("name", 40)
+    #     # <INPUT TYPE="file" NAME="name" SIZE="40">
+    # 
+    #   file_field("name", 40, 100)
+    #     # <INPUT TYPE="file" NAME="name" SIZE="40" MAXLENGTH="100">
+    # 
+    #   file_field("NAME" => "name", "SIZE" => 40)
+    #     # <INPUT TYPE="file" NAME="name" SIZE="40">
+    def file_field(name = "", size = 20, maxlength = nil)
+      attributes = if name.kind_of?(String)
+                     { "TYPE" => "file", "NAME" => name,
+                       "SIZE" => size.to_s }
+                   else
+                     name["TYPE"] = "file"
+                     name
+                   end
+      attributes["MAXLENGTH"] = maxlength.to_s if maxlength
+      input(attributes)
+    end
+
+
+    # Generate a Form element as a string.
+    #
+    # +method+ should be either "get" or "post", and defaults to the latter.
+    # +action+ defaults to the current CGI script name.  +enctype+
+    # defaults to "application/x-www-form-urlencoded".  
+    #
+    # Alternatively, the attributes can be specified as a hash.
+    #
+    # See also #multipart_form() for forms that include file uploads.
+    #
+    #   form{ "string" }
+    #     # <FORM METHOD="post" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
+    # 
+    #   form("get") { "string" }
+    #     # <FORM METHOD="get" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
+    # 
+    #   form("get", "url") { "string" }
+    #     # <FORM METHOD="get" ACTION="url" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
+    # 
+    #   form("METHOD" => "post", "ENCTYPE" => "enctype") { "string" }
+    #     # <FORM METHOD="post" ENCTYPE="enctype">string</FORM>
+    def form(method = "post", action = script_name, enctype = "application/x-www-form-urlencoded")
+      attributes = if method.kind_of?(String)
+                     { "METHOD" => method, "ACTION" => action,
+                       "ENCTYPE" => enctype } 
+                   else
+                     unless method.has_key?("METHOD")
+                       method["METHOD"] = "post"
+                     end
+                     unless method.has_key?("ENCTYPE")
+                       method["ENCTYPE"] = enctype
+                     end
+                     method
+                   end
+      if block_given?
+        body = yield
+      else
+        body = ""
+      end
+      if @output_hidden
+        body += @output_hidden.collect{|k,v|
+          "<INPUT TYPE=\"HIDDEN\" NAME=\"#{k}\" VALUE=\"#{v}\">"
+        }.to_s
+      end
+      super(attributes){body}
+    end
+
+    # Generate a Hidden Input element as a string.
+    #
+    # The attributes of the element can be specified as two arguments,
+    # +name+ and +value+.
+    #
+    # Alternatively, the attributes can be specified as a hash.
+    #
+    #   hidden("name")
+    #     # <INPUT TYPE="hidden" NAME="name">
+    # 
+    #   hidden("name", "value")
+    #     # <INPUT TYPE="hidden" NAME="name" VALUE="value">
+    # 
+    #   hidden("NAME" => "name", "VALUE" => "reset", "ID" => "foo")
+    #     # <INPUT TYPE="hidden" NAME="name" VALUE="value" ID="foo">
+    def hidden(name = "", value = nil)
+      attributes = if name.kind_of?(String)
+                     { "TYPE" => "hidden", "NAME" => name, "VALUE" => value }
+                   else
+                     name["TYPE"] = "hidden"
+                     name
+                   end
+      input(attributes)
+    end
+
+    # Generate a top-level HTML element as a string.
+    #
+    # The attributes of the element are specified as a hash.  The
+    # pseudo-attribute "PRETTY" can be used to specify that the generated
+    # HTML string should be indented.  "PRETTY" can also be specified as
+    # a string as the sole argument to this method.  The pseudo-attribute
+    # "DOCTYPE", if given, is used as the leading DOCTYPE SGML tag; it
+    # should include the entire text of this tag, including angle brackets.
+    #
+    # The body of the html element is supplied as a block.
+    # 
+    #   html{ "string" }
+    #     # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML>string</HTML>
+    # 
+    #   html("LANG" => "ja") { "string" }
+    #     # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML LANG="ja">string</HTML>
+    # 
+    #   html("DOCTYPE" => false) { "string" }
+    #     # <HTML>string</HTML>
+    # 
+    #   html("DOCTYPE" => '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">') { "string" }
+    #     # <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML>string</HTML>
+    # 
+    #   html("PRETTY" => "  ") { "<BODY></BODY>" }
+    #     # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+    #     # <HTML>
+    #     #   <BODY>
+    #     #   </BODY>
+    #     # </HTML>
+    # 
+    #   html("PRETTY" => "\t") { "<BODY></BODY>" }
+    #     # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+    #     # <HTML>
+    #     #         <BODY>
+    #     #         </BODY>
+    #     # </HTML>
+    # 
+    #   html("PRETTY") { "<BODY></BODY>" }
+    #     # = html("PRETTY" => "  ") { "<BODY></BODY>" }
+    # 
+    #   html(if $VERBOSE then "PRETTY" end) { "HTML string" }
+    #
+    def html(attributes = {}) # :yield:
+      if nil == attributes
+        attributes = {}
+      elsif "PRETTY" == attributes
+        attributes = { "PRETTY" => true }
+      end
+      pretty = attributes.delete("PRETTY")
+      pretty = "  " if true == pretty
+      buf = ""
+
+      if attributes.has_key?("DOCTYPE")
+        if attributes["DOCTYPE"]
+          buf += attributes.delete("DOCTYPE")
+        else
+          attributes.delete("DOCTYPE")
+        end
+      else
+        buf += doctype
+      end
+
+      if block_given?
+        buf += super(attributes){ yield }
+      else
+        buf += super(attributes)
+      end
+
+      if pretty
+        CGI::pretty(buf, pretty)
+      else
+        buf
+      end
+
+    end
+
+    # Generate an Image Button Input element as a string.
+    #
+    # +src+ is the URL of the image to use for the button.  +name+ 
+    # is the input name.  +alt+ is the alternative text for the image.
+    #
+    # Alternatively, the attributes can be specified as a hash.
+    # 
+    #   image_button("url")
+    #     # <INPUT TYPE="image" SRC="url">
+    # 
+    #   image_button("url", "name", "string")
+    #     # <INPUT TYPE="image" SRC="url" NAME="name" ALT="string">
+    # 
+    #   image_button("SRC" => "url", "ATL" => "strng")
+    #     # <INPUT TYPE="image" SRC="url" ALT="string">
+    def image_button(src = "", name = nil, alt = nil)
+      attributes = if src.kind_of?(String)
+                     { "TYPE" => "image", "SRC" => src, "NAME" => name,
+                       "ALT" => alt }
+                   else
+                     src["TYPE"] = "image"
+                     src["SRC"] ||= ""
+                     src
+                   end
+      input(attributes)
+    end
+
+
+    # Generate an Image element as a string.
+    #
+    # +src+ is the URL of the image.  +alt+ is the alternative text for
+    # the image.  +width+ is the width of the image, and +height+ is
+    # its height.
+    #
+    # Alternatively, the attributes can be specified as a hash.
+    #
+    #   img("src", "alt", 100, 50)
+    #     # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
+    # 
+    #   img("SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50)
+    #     # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
+    def img(src = "", alt = "", width = nil, height = nil)
+      attributes = if src.kind_of?(String)
+                     { "SRC" => src, "ALT" => alt }
+                   else
+                     src
+                   end
+      attributes["WIDTH"] = width.to_s if width
+      attributes["HEIGHT"] = height.to_s if height
+      super(attributes)
+    end
+
+
+    # Generate a Form element with multipart encoding as a String.
+    #
+    # Multipart encoding is used for forms that include file uploads.
+    #
+    # +action+ is the action to perform.  +enctype+ is the encoding
+    # type, which defaults to "multipart/form-data".
+    #
+    # Alternatively, the attributes can be specified as a hash.
+    #
+    #   multipart_form{ "string" }
+    #     # <FORM METHOD="post" ENCTYPE="multipart/form-data">string</FORM>
+    # 
+    #   multipart_form("url") { "string" }
+    #     # <FORM METHOD="post" ACTION="url" ENCTYPE="multipart/form-data">string</FORM>
+    def multipart_form(action = nil, enctype = "multipart/form-data")
+      attributes = if action == nil
+                     { "METHOD" => "post", "ENCTYPE" => enctype } 
+                   elsif action.kind_of?(String)
+                     { "METHOD" => "post", "ACTION" => action,
+                       "ENCTYPE" => enctype } 
+                   else
+                     unless action.has_key?("METHOD")
+                       action["METHOD"] = "post"
+                     end
+                     unless action.has_key?("ENCTYPE")
+                       action["ENCTYPE"] = enctype
+                     end
+                     action
+                   end
+      if block_given?
+        form(attributes){ yield }
+      else
+        form(attributes)
+      end
+    end
+
+
+    # Generate a Password Input element as a string.
+    #
+    # +name+ is the name of the input field.  +value+ is its default
+    # value.  +size+ is the size of the input field display.  +maxlength+
+    # is the maximum length of the inputted password.
+    #
+    # Alternatively, attributes can be specified as a hash.
+    #
+    #   password_field("name")
+    #     # <INPUT TYPE="password" NAME="name" SIZE="40">
+    # 
+    #   password_field("name", "value")
+    #     # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="40">
+    # 
+    #   password_field("password", "value", 80, 200)
+    #     # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
+    # 
+    #   password_field("NAME" => "name", "VALUE" => "value")
+    #     # <INPUT TYPE="password" NAME="name" VALUE="value">
+    def password_field(name = "", value = nil, size = 40, maxlength = nil)
+      attributes = if name.kind_of?(String)
+                     { "TYPE" => "password", "NAME" => name,
+                       "VALUE" => value, "SIZE" => size.to_s }
+                   else
+                     name["TYPE"] = "password"
+                     name
+                   end
+      attributes["MAXLENGTH"] = maxlength.to_s if maxlength
+      input(attributes)
+    end
+
+    # Generate a Select element as a string.
+    #
+    # +name+ is the name of the element.  The +values+ are the options that
+    # can be selected from the Select menu.  Each value can be a String or
+    # a one, two, or three-element Array.  If a String or a one-element
+    # Array, this is both the value of that option and the text displayed for
+    # it.  If a three-element Array, the elements are the option value, displayed
+    # text, and a boolean value specifying whether this option starts as selected.
+    # The two-element version omits either the option value (defaults to the same
+    # as the display text) or the boolean selected specifier (defaults to false).
+    #
+    # The attributes and options can also be specified as a hash.  In this
+    # case, options are specified as an array of values as described above,
+    # with the hash key of "VALUES".
+    #
+    #   popup_menu("name", "foo", "bar", "baz")
+    #     # <SELECT NAME="name">
+    #     #   <OPTION VALUE="foo">foo</OPTION>
+    #     #   <OPTION VALUE="bar">bar</OPTION>
+    #     #   <OPTION VALUE="baz">baz</OPTION>
+    #     # </SELECT>
+    # 
+    #   popup_menu("name", ["foo"], ["bar", true], "baz")
+    #     # <SELECT NAME="name">
+    #     #   <OPTION VALUE="foo">foo</OPTION>
+    #     #   <OPTION VALUE="bar" SELECTED>bar</OPTION>
+    #     #   <OPTION VALUE="baz">baz</OPTION>
+    #     # </SELECT>
+    # 
+    #   popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
+    #     # <SELECT NAME="name">
+    #     #   <OPTION VALUE="1">Foo</OPTION>
+    #     #   <OPTION SELECTED VALUE="2">Bar</OPTION>
+    #     #   <OPTION VALUE="Baz">Baz</OPTION>
+    #     # </SELECT>
+    # 
+    #   popup_menu("NAME" => "name", "SIZE" => 2, "MULTIPLE" => true,
+    #               "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
+    #     # <SELECT NAME="name" MULTIPLE SIZE="2">
+    #     #   <OPTION VALUE="1">Foo</OPTION>
+    #     #   <OPTION SELECTED VALUE="2">Bar</OPTION>
+    #     #   <OPTION VALUE="Baz">Baz</OPTION>
+    #     # </SELECT>
+    def popup_menu(name = "", *values)
+
+      if name.kind_of?(Hash)
+        values   = name["VALUES"]
+        size     = name["SIZE"].to_s if name["SIZE"]
+        multiple = name["MULTIPLE"]
+        name     = name["NAME"]
+      else
+        size = nil
+        multiple = nil
+      end
+
+      select({ "NAME" => name, "SIZE" => size,
+               "MULTIPLE" => multiple }){
+        values.collect{|value|
+          if value.kind_of?(String)
+            option({ "VALUE" => value }){ value }
+          else
+            if value[value.size - 1] == true
+              option({ "VALUE" => value[0], "SELECTED" => true }){
+                value[value.size - 2]
+              }
+            else
+              option({ "VALUE" => value[0] }){
+                value[value.size - 1]
+              }
+            end
+          end
+        }.to_s
+      }
+
+    end
+
+    # Generates a radio-button Input element.
+    #
+    # +name+ is the name of the input field.  +value+ is the value of
+    # the field if checked.  +checked+ specifies whether the field
+    # starts off checked.
+    #
+    # Alternatively, the attributes can be specified as a hash.
+    #
+    #   radio_button("name", "value")
+    #     # <INPUT TYPE="radio" NAME="name" VALUE="value">
+    # 
+    #   radio_button("name", "value", true)
+    #     # <INPUT TYPE="radio" NAME="name" VALUE="value" CHECKED>
+    # 
+    #   radio_button("NAME" => "name", "VALUE" => "value", "ID" => "foo")
+    #     # <INPUT TYPE="radio" NAME="name" VALUE="value" ID="foo">
+    def radio_button(name = "", value = nil, checked = nil)
+      attributes = if name.kind_of?(String)
+                     { "TYPE" => "radio", "NAME" => name,
+                       "VALUE" => value, "CHECKED" => checked }
+                   else
+                     name["TYPE"] = "radio"
+                     name
+                   end
+      input(attributes)
+    end
+
+    # Generate a sequence of radio button Input elements, as a String.
+    #
+    # This works the same as #checkbox_group().  However, it is not valid
+    # to have more than one radiobutton in a group checked.
+    # 
+    #   radio_group("name", "foo", "bar", "baz")
+    #     # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
+    #     # <INPUT TYPE="radio" NAME="name" VALUE="bar">bar
+    #     # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
+    # 
+    #   radio_group("name", ["foo"], ["bar", true], "baz")
+    #     # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
+    #     # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="bar">bar
+    #     # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
+    # 
+    #   radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
+    #     # <INPUT TYPE="radio" NAME="name" VALUE="1">Foo
+    #     # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="2">Bar
+    #     # <INPUT TYPE="radio" NAME="name" VALUE="Baz">Baz
+    # 
+    #   radio_group("NAME" => "name",
+    #                 "VALUES" => ["foo", "bar", "baz"])
+    # 
+    #   radio_group("NAME" => "name",
+    #                 "VALUES" => [["foo"], ["bar", true], "baz"])
+    # 
+    #   radio_group("NAME" => "name",
+    #                 "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
+    def radio_group(name = "", *values)
+      if name.kind_of?(Hash)
+        values = name["VALUES"]
+        name = name["NAME"]
+      end
+      values.collect{|value|
+        if value.kind_of?(String)
+          radio_button(name, value) + value
+        else
+          if value[value.size - 1] == true
+            radio_button(name, value[0], true) +
+            value[value.size - 2]
+          else
+            radio_button(name, value[0]) +
+            value[value.size - 1]
+          end
+        end
+      }.to_s
+    end
+
+    # Generate a reset button Input element, as a String.
+    #
+    # This resets the values on a form to their initial values.  +value+
+    # is the text displayed on the button. +name+ is the name of this button.
+    #
+    # Alternatively, the attributes can be specified as a hash.
+    #
+    #   reset
+    #     # <INPUT TYPE="reset">
+    # 
+    #   reset("reset")
+    #     # <INPUT TYPE="reset" VALUE="reset">
+    # 
+    #   reset("VALUE" => "reset", "ID" => "foo")
+    #     # <INPUT TYPE="reset" VALUE="reset" ID="foo">
+    def reset(value = nil, name = nil)
+      attributes = if (not value) or value.kind_of?(String)
+                     { "TYPE" => "reset", "VALUE" => value, "NAME" => name }
+                   else
+                     value["TYPE"] = "reset"
+                     value
+                   end
+      input(attributes)
+    end
+
+    alias scrolling_list popup_menu
+
+    # Generate a submit button Input element, as a String.
+    #
+    # +value+ is the text to display on the button.  +name+ is the name
+    # of the input.
+    #
+    # Alternatively, the attributes can be specified as a hash.
+    #
+    #   submit
+    #     # <INPUT TYPE="submit">
+    # 
+    #   submit("ok")
+    #     # <INPUT TYPE="submit" VALUE="ok">
+    # 
+    #   submit("ok", "button1")
+    #     # <INPUT TYPE="submit" VALUE="ok" NAME="button1">
+    # 
+    #   submit("VALUE" => "ok", "NAME" => "button1", "ID" => "foo")
+    #     # <INPUT TYPE="submit" VALUE="ok" NAME="button1" ID="foo">
+    def submit(value = nil, name = nil)
+      attributes = if (not value) or value.kind_of?(String)
+                     { "TYPE" => "submit", "VALUE" => value, "NAME" => name }
+                   else
+                     value["TYPE"] = "submit"
+                     value
+                   end
+      input(attributes)
+    end
+
+    # Generate a text field Input element, as a String.
+    #
+    # +name+ is the name of the input field.  +value+ is its initial
+    # value.  +size+ is the size of the input area.  +maxlength+
+    # is the maximum length of input accepted.
+    #
+    # Alternatively, the attributes can be specified as a hash.
+    #
+    #   text_field("name")
+    #     # <INPUT TYPE="text" NAME="name" SIZE="40">
+    # 
+    #   text_field("name", "value")
+    #     # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="40">
+    # 
+    #   text_field("name", "value", 80)
+    #     # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80">
+    # 
+    #   text_field("name", "value", 80, 200)
+    #     # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
+    # 
+    #   text_field("NAME" => "name", "VALUE" => "value")
+    #     # <INPUT TYPE="text" NAME="name" VALUE="value">
+    def text_field(name = "", value = nil, size = 40, maxlength = nil)
+      attributes = if name.kind_of?(String)
+                     { "TYPE" => "text", "NAME" => name, "VALUE" => value,
+                       "SIZE" => size.to_s }
+                   else
+                     name["TYPE"] = "text"
+                     name
+                   end
+      attributes["MAXLENGTH"] = maxlength.to_s if maxlength
+      input(attributes)
+    end
+
+    # Generate a TextArea element, as a String.
+    #
+    # +name+ is the name of the textarea.  +cols+ is the number of
+    # columns and +rows+ is the number of rows in the display.
+    #
+    # Alternatively, the attributes can be specified as a hash.
+    #
+    # The body is provided by the passed-in no-argument block
+    #
+    #   textarea("name")
+    #      # = textarea("NAME" => "name", "COLS" => 70, "ROWS" => 10)
+    #
+    #   textarea("name", 40, 5)
+    #      # = textarea("NAME" => "name", "COLS" => 40, "ROWS" => 5)
+    def textarea(name = "", cols = 70, rows = 10)  # :yield:
+      attributes = if name.kind_of?(String)
+                     { "NAME" => name, "COLS" => cols.to_s,
+                       "ROWS" => rows.to_s }
+                   else
+                     name
+                   end
+      if block_given?
+        super(attributes){ yield }
+      else
+        super(attributes)
+      end
+    end
+
+  end # HtmlExtension
+
+
+  # Mixin module for HTML version 3 generation methods.
+  module Html3 # :nodoc:
+
+    # The DOCTYPE declaration for this version of HTML
+    def doctype
+      %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">|
+    end
+
+    # Initialise the HTML generation methods for this version.
+    def element_init
+      extend TagMaker
+      methods = ""
+      # - -
+      for element in %w[ A TT I B U STRIKE BIG SMALL SUB SUP EM STRONG
+          DFN CODE SAMP KBD VAR CITE FONT ADDRESS DIV center MAP
+          APPLET PRE XMP LISTING DL OL UL DIR MENU SELECT table TITLE
+          STYLE SCRIPT H1 H2 H3 H4 H5 H6 TEXTAREA FORM BLOCKQUOTE
+          CAPTION ]
+        methods += <<-BEGIN + nn_element_def(element) + <<-END
+          def #{element.downcase}(attributes = {})
+        BEGIN
+          end
+        END
+      end
+
+      # - O EMPTY
+      for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
+          ISINDEX META ]
+        methods += <<-BEGIN + nOE_element_def(element) + <<-END
+          def #{element.downcase}(attributes = {})
+        BEGIN
+          end
+        END
+      end
+
+      # O O or - O
+      for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION tr
+          th td ]
+        methods += <<-BEGIN + nO_element_def(element) + <<-END
+          def #{element.downcase}(attributes = {})
+        BEGIN
+          end
+        END
+      end
+      eval(methods)
+    end
+
+  end # Html3
+
+
+  # Mixin module for HTML version 4 generation methods.
+  module Html4 # :nodoc:
+
+    # The DOCTYPE declaration for this version of HTML
+    def doctype
+      %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">|
+    end
+
+    # Initialise the HTML generation methods for this version.
+    def element_init
+      extend TagMaker
+      methods = ""
+      # - -
+      for element in %w[ TT I B BIG SMALL EM STRONG DFN CODE SAMP KBD
+        VAR CITE ABBR ACRONYM SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT
+        H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT OPTGROUP
+        FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT
+        TEXTAREA FORM A BLOCKQUOTE CAPTION ]
+        methods += <<-BEGIN + nn_element_def(element) + <<-END
+          def #{element.downcase}(attributes = {})
+        BEGIN
+          end
+        END
+      end
+
+      # - O EMPTY
+      for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META ]
+        methods += <<-BEGIN + nOE_element_def(element) + <<-END
+          def #{element.downcase}(attributes = {})
+        BEGIN
+          end
+        END
+      end
+
+      # O O or - O
+      for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
+          COLGROUP TR TH TD HEAD]
+        methods += <<-BEGIN + nO_element_def(element) + <<-END
+          def #{element.downcase}(attributes = {})
+        BEGIN
+          end
+        END
+      end
+      eval(methods)
+    end
+
+  end # Html4
+
+
+  # Mixin module for HTML version 4 transitional generation methods.
+  module Html4Tr # :nodoc:
+
+    # The DOCTYPE declaration for this version of HTML
+    def doctype
+      %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">|
+    end
+
+    # Initialise the HTML generation methods for this version.
+    def element_init
+      extend TagMaker
+      methods = ""
+      # - -
+      for element in %w[ TT I B U S STRIKE BIG SMALL EM STRONG DFN
+          CODE SAMP KBD VAR CITE ABBR ACRONYM FONT SUB SUP SPAN BDO
+          ADDRESS DIV CENTER MAP OBJECT APPLET H1 H2 H3 H4 H5 H6 PRE Q
+          INS DEL DL OL UL DIR MENU LABEL SELECT OPTGROUP FIELDSET
+          LEGEND BUTTON TABLE IFRAME NOFRAMES TITLE STYLE SCRIPT
+          NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ]
+        methods += <<-BEGIN + nn_element_def(element) + <<-END
+          def #{element.downcase}(attributes = {})
+        BEGIN
+          end
+        END
+      end
+
+      # - O EMPTY
+      for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
+          COL ISINDEX META ]
+        methods += <<-BEGIN + nOE_element_def(element) + <<-END
+          def #{element.downcase}(attributes = {})
+        BEGIN
+          end
+        END
+      end
+
+      # O O or - O
+      for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
+          COLGROUP TR TH TD HEAD ]
+        methods += <<-BEGIN + nO_element_def(element) + <<-END
+          def #{element.downcase}(attributes = {})
+        BEGIN
+          end
+        END
+      end
+      eval(methods)
+    end
+
+  end # Html4Tr
+
+
+  # Mixin module for generating HTML version 4 with framesets.
+  module Html4Fr # :nodoc:
+
+    # The DOCTYPE declaration for this version of HTML
+    def doctype
+      %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">|
+    end
+
+    # Initialise the HTML generation methods for this version.
+    def element_init
+      methods = ""
+      # - -
+      for element in %w[ FRAMESET ]
+        methods += <<-BEGIN + nn_element_def(element) + <<-END
+          def #{element.downcase}(attributes = {})
+        BEGIN
+          end
+        END
+      end
+
+      # - O EMPTY
+      for element in %w[ FRAME ]
+        methods += <<-BEGIN + nOE_element_def(element) + <<-END
+          def #{element.downcase}(attributes = {})
+        BEGIN
+          end
+        END
+      end
+      eval(methods)
+    end
+
+  end # Html4Fr
+
+
+  # Creates a new CGI instance.
+  #
+  # +type+ specifies which version of HTML to load the HTML generation
+  # methods for.  The following versions of HTML are supported:
+  #
+  # html3:: HTML 3.x
+  # html4:: HTML 4.0
+  # html4Tr:: HTML 4.0 Transitional
+  # html4Fr:: HTML 4.0 with Framesets
+  #
+  # If not specified, no HTML generation methods will be loaded.
+  #
+  # If the CGI object is not created in a standard CGI call environment
+  # (that is, it can't locate REQUEST_METHOD in its environment), then
+  # it will run in "offline" mode.  In this mode, it reads its parameters
+  # from the command line or (failing that) from standard input.  Otherwise,
+  # cookies and other parameters are parsed automatically from the standard
+  # CGI locations, which varies according to the REQUEST_METHOD.
+  def initialize(type = "query")
+    if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE")
+      Apache.request.setup_cgi_env
+    end
+
+    extend QueryExtension
+    @multipart = false
+    if defined?(CGI_PARAMS)
+      warn "do not use CGI_PARAMS and CGI_COOKIES"
+      @params = CGI_PARAMS.dup
+      @cookies = CGI_COOKIES.dup
+    else
+      initialize_query()  # set @params, @cookies
+    end
+    @output_cookies = nil
+    @output_hidden = nil
+
+    case type
+    when "html3"
+      extend Html3
+      element_init()
+      extend HtmlExtension
+    when "html4"
+      extend Html4
+      element_init()
+      extend HtmlExtension
+    when "html4Tr"
+      extend Html4Tr
+      element_init()
+      extend HtmlExtension
+    when "html4Fr"
+      extend Html4Tr
+      element_init()
+      extend Html4Fr
+      element_init()
+      extend HtmlExtension
+    end
+  end
+
+end   # class CGI
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/cgi/session.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/cgi/session.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/cgi/session.rb	(revision 18425)
@@ -0,0 +1,484 @@
+#
+# cgi/session.rb - session support for cgi scripts
+#
+# Copyright (C) 2001  Yukihiro "Matz" Matsumoto
+# Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
+# Copyright (C) 2000  Information-technology Promotion Agency, Japan
+#
+# Author: Yukihiro "Matz" Matsumoto
+#
+# Documentation: William Webber (william@williamwebber.com)
+#
+# == Overview
+#
+# This file provides the +CGI::Session+ class, which provides session
+# support for CGI scripts.  A session is a sequence of HTTP requests
+# and responses linked together and associated with a single client.  
+# Information associated with the session is stored
+# on the server between requests.  A session id is passed between client
+# and server with every request and response, transparently
+# to the user.  This adds state information to the otherwise stateless
+# HTTP request/response protocol.
+#
+# See the documentation to the +CGI::Session+ class for more details
+# and examples of usage.  See cgi.rb for the +CGI+ class itself.
+
+require 'cgi'
+require 'tmpdir'
+
+class CGI
+
+  # Class representing an HTTP session.  See documentation for the file 
+  # cgi/session.rb for an introduction to HTTP sessions.
+  #
+  # == Lifecycle
+  #
+  # A CGI::Session instance is created from a CGI object.  By default,
+  # this CGI::Session instance will start a new session if none currently
+  # exists, or continue the current session for this client if one does
+  # exist.  The +new_session+ option can be used to either always or
+  # never create a new session.  See #new() for more details.
+  #
+  # #delete() deletes a session from session storage.  It
+  # does not however remove the session id from the client.  If the client
+  # makes another request with the same id, the effect will be to start
+  # a new session with the old session's id.
+  #
+  # == Setting and retrieving session data.
+  #
+  # The Session class associates data with a session as key-value pairs.
+  # This data can be set and retrieved by indexing the Session instance 
+  # using '[]', much the same as hashes (although other hash methods
+  # are not supported).
+  #
+  # When session processing has been completed for a request, the
+  # session should be closed using the close() method.  This will
+  # store the session's state to persistent storage.  If you want
+  # to store the session's state to persistent storage without
+  # finishing session processing for this request, call the update()
+  # method.
+  #
+  # == Storing session state
+  #
+  # The caller can specify what form of storage to use for the session's 
+  # data with the +database_manager+ option to CGI::Session::new.  The
+  # following storage classes are provided as part of the standard library:
+  #
+  # CGI::Session::FileStore:: stores data as plain text in a flat file.  Only 
+  #                           works with String data.  This is the default 
+  #                           storage type.
+  # CGI::Session::MemoryStore:: stores data in an in-memory hash.  The data 
+  #                             only persists for as long as the current ruby 
+  #                             interpreter instance does.
+  # CGI::Session::PStore:: stores data in Marshalled format.  Provided by
+  #                        cgi/session/pstore.rb.  Supports data of any type, 
+  #                        and provides file-locking and transaction support.
+  #
+  # Custom storage types can also be created by defining a class with 
+  # the following methods:
+  #
+  #    new(session, options)
+  #    restore  # returns hash of session data.
+  #    update
+  #    close
+  #    delete
+  #
+  # Changing storage type mid-session does not work.  Note in particular
+  # that by default the FileStore and PStore session data files have the
+  # same name.  If your application switches from one to the other without
+  # making sure that filenames will be different
+  # and clients still have old sessions lying around in cookies, then
+  # things will break nastily!
+  #
+  # == Maintaining the session id.
+  #
+  # Most session state is maintained on the server.  However, a session
+  # id must be passed backwards and forwards between client and server
+  # to maintain a reference to this session state.
+  #
+  # The simplest way to do this is via cookies.  The CGI::Session class
+  # provides transparent support for session id communication via cookies
+  # if the client has cookies enabled.
+  # 
+  # If the client has cookies disabled, the session id must be included
+  # as a parameter of all requests sent by the client to the server.  The
+  # CGI::Session class in conjunction with the CGI class will transparently
+  # add the session id as a hidden input field to all forms generated
+  # using the CGI#form() HTML generation method.  No built-in support is
+  # provided for other mechanisms, such as URL re-writing.  The caller is
+  # responsible for extracting the session id from the session_id 
+  # attribute and manually encoding it in URLs and adding it as a hidden
+  # input to HTML forms created by other mechanisms.  Also, session expiry
+  # is not automatically handled.
+  #
+  # == Examples of use
+  #
+  # === Setting the user's name
+  #
+  #   require 'cgi'
+  #   require 'cgi/session'
+  #   require 'cgi/session/pstore'     # provides CGI::Session::PStore
+  #
+  #   cgi = CGI.new("html4")
+  #
+  #   session = CGI::Session.new(cgi,
+  #       'database_manager' => CGI::Session::PStore,  # use PStore
+  #       'session_key' => '_rb_sess_id',              # custom session key
+  #       'session_expires' => Time.now + 30 * 60,     # 30 minute timeout 
+  #       'prefix' => 'pstore_sid_')                   # PStore option
+  #   if cgi.has_key?('user_name') and cgi['user_name'] != ''
+  #       # coerce to String: cgi[] returns the 
+  #       # string-like CGI::QueryExtension::Value
+  #       session['user_name'] = cgi['user_name'].to_s
+  #   elsif !session['user_name']
+  #       session['user_name'] = "guest"
+  #   end
+  #   session.close
+  #
+  # === Creating a new session safely
+  #
+  #   require 'cgi'
+  #   require 'cgi/session'
+  #
+  #   cgi = CGI.new("html4")
+  #
+  #   # We make sure to delete an old session if one exists,
+  #   # not just to free resources, but to prevent the session 
+  #   # from being maliciously hijacked later on.
+  #   begin
+  #       session = CGI::Session.new(cgi, 'new_session' => false)      
+  #       session.delete                 
+  #   rescue ArgumentError  # if no old session
+  #   end
+  #   session = CGI::Session.new(cgi, 'new_session' => true)
+  #   session.close
+  #
+  class Session
+
+    class NoSession < RuntimeError #:nodoc:
+    end
+
+    # The id of this session.
+    attr_reader :session_id, :new_session
+
+    def Session::callback(dbman)  #:nodoc:
+      Proc.new{
+	dbman[0].close unless dbman.empty?
+      }
+    end
+
+    # Create a new session id.
+    #
+    # The session id is an MD5 hash based upon the time,
+    # a random number, and a constant string.  This routine
+    # is used internally for automatically generated
+    # session ids. 
+    def create_new_id
+      require 'digest/md5'
+      md5 = Digest::MD5::new
+      now = Time::now
+      md5.update(now.to_s)
+      md5.update(String(now.usec))
+      md5.update(String(rand(0)))
+      md5.update(String($$))
+      md5.update('foobar')
+      @new_session = true
+      md5.hexdigest
+    end
+    private :create_new_id
+
+    # Create a new CGI::Session object for +request+.
+    #
+    # +request+ is an instance of the +CGI+ class (see cgi.rb).
+    # +option+ is a hash of options for initialising this
+    # CGI::Session instance.  The following options are
+    # recognised:
+    #
+    # session_key:: the parameter name used for the session id.
+    #               Defaults to '_session_id'.
+    # session_id:: the session id to use.  If not provided, then
+    #              it is retrieved from the +session_key+ parameter
+    #              of the request, or automatically generated for
+    #              a new session.
+    # new_session:: if true, force creation of a new session.  If not set, 
+    #               a new session is only created if none currently
+    #               exists.  If false, a new session is never created,
+    #               and if none currently exists and the +session_id+
+    #               option is not set, an ArgumentError is raised.
+    # database_manager:: the name of the class providing storage facilities
+    #                    for session state persistence.  Built-in support
+    #                    is provided for +FileStore+ (the default),
+    #                    +MemoryStore+, and +PStore+ (from
+    #                    cgi/session/pstore.rb).  See the documentation for
+    #                    these classes for more details.
+    #
+    # The following options are also recognised, but only apply if the
+    # session id is stored in a cookie.
+    #
+    # session_expires:: the time the current session expires, as a 
+    #                   +Time+ object.  If not set, the session will terminate
+    #                   when the user's browser is closed.
+    # session_domain:: the hostname domain for which this session is valid.
+    #                  If not set, defaults to the hostname of the server.
+    # session_secure:: if +true+, this session will only work over HTTPS.
+    # session_path:: the path for which this session applies.  Defaults
+    #                to the directory of the CGI script.
+    #
+    # +option+ is also passed on to the session storage class initialiser; see
+    # the documentation for each session storage class for the options
+    # they support.
+    #                  
+    # The retrieved or created session is automatically added to +request+
+    # as a cookie, and also to its +output_hidden+ table, which is used
+    # to add hidden input elements to forms.  
+    #
+    # *WARNING* the +output_hidden+
+    # fields are surrounded by a <fieldset> tag in HTML 4 generation, which
+    # is _not_ invisible on many browsers; you may wish to disable the
+    # use of fieldsets with code similar to the following
+    # (see http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/37805)
+    #
+    #   cgi = CGI.new("html4")
+    #   class << cgi
+    #       undef_method :fieldset
+    #   end
+    #
+    def initialize(request, option={})
+      @new_session = false
+      session_key = option['session_key'] || '_session_id'
+      session_id = option['session_id']
+      unless session_id
+	if option['new_session']
+	  session_id = create_new_id
+	end
+      end
+      unless session_id
+	if request.key?(session_key)
+	  session_id = request[session_key]
+	  session_id = session_id.read if session_id.respond_to?(:read)
+	end
+	unless session_id
+	  session_id, = request.cookies[session_key]
+	end
+	unless session_id
+	  unless option.fetch('new_session', true)
+	    raise ArgumentError, "session_key `%s' should be supplied"%session_key
+	  end
+	  session_id = create_new_id
+	end
+      end
+      @session_id = session_id
+      dbman = option['database_manager'] || FileStore
+      begin
+        @dbman = dbman::new(self, option)
+      rescue NoSession
+        unless option.fetch('new_session', true)
+          raise ArgumentError, "invalid session_id `%s'"%session_id
+        end
+        session_id = @session_id = create_new_id
+        retry
+      end
+      request.instance_eval do
+	@output_hidden = {session_key => session_id} unless option['no_hidden']
+	@output_cookies =  [
+          Cookie::new("name" => session_key,
+		      "value" => session_id,
+		      "expires" => option['session_expires'],
+		      "domain" => option['session_domain'],
+		      "secure" => option['session_secure'],
+		      "path" => if option['session_path'] then
+				  option['session_path']
+		                elsif ENV["SCRIPT_NAME"] then
+				  File::dirname(ENV["SCRIPT_NAME"])
+				else
+				  ""
+				end)
+        ] unless option['no_cookies']
+      end
+      @dbprot = [@dbman]
+      ObjectSpace::define_finalizer(self, Session::callback(@dbprot))
+    end
+
+    # Retrieve the session data for key +key+.
+    def [](key)
+      @data ||= @dbman.restore
+      @data[key]
+    end
+
+    # Set the session date for key +key+.
+    def []=(key, val)
+      @write_lock ||= true
+      @data ||= @dbman.restore
+      @data[key] = val
+    end
+
+    # Store session data on the server.  For some session storage types,
+    # this is a no-op.
+    def update  
+      @dbman.update
+    end
+
+    # Store session data on the server and close the session storage.  
+    # For some session storage types, this is a no-op.
+    def close
+      @dbman.close
+      @dbprot.clear
+    end
+
+    # Delete the session from storage.  Also closes the storage.
+    #
+    # Note that the session's data is _not_ automatically deleted
+    # upon the session expiring.
+    def delete
+      @dbman.delete
+      @dbprot.clear
+    end
+
+    # File-based session storage class.
+    #
+    # Implements session storage as a flat file of 'key=value' values.
+    # This storage type only works directly with String values; the
+    # user is responsible for converting other types to Strings when
+    # storing and from Strings when retrieving.
+    class FileStore
+      # Create a new FileStore instance.
+      #
+      # This constructor is used internally by CGI::Session.  The
+      # user does not generally need to call it directly.
+      #
+      # +session+ is the session for which this instance is being
+      # created.  The session id must only contain alphanumeric
+      # characters; automatically generated session ids observe
+      # this requirement.
+      # 
+      # +option+ is a hash of options for the initialiser.  The
+      # following options are recognised:
+      #
+      # tmpdir:: the directory to use for storing the FileStore
+      #          file.  Defaults to Dir::tmpdir (generally "/tmp"
+      #          on Unix systems).
+      # prefix:: the prefix to add to the session id when generating
+      #          the filename for this session's FileStore file.
+      #          Defaults to the empty string.
+      # suffix:: the prefix to add to the session id when generating
+      #          the filename for this session's FileStore file.
+      #          Defaults to the empty string.
+      #
+      # This session's FileStore file will be created if it does
+      # not exist, or opened if it does.
+      def initialize(session, option={})
+	dir = option['tmpdir'] || Dir::tmpdir
+	prefix = option['prefix'] || ''
+	suffix = option['suffix'] || ''
+	id = session.session_id
+        require 'digest/md5'
+        md5 = Digest::MD5.hexdigest(id)[0,16]
+	@path = dir+"/"+prefix+md5+suffix
+	if File::exist? @path
+	  @hash = nil
+	else
+          unless session.new_session
+            raise CGI::Session::NoSession, "uninitialized session"
+          end
+	  @hash = {}
+	end
+      end
+
+      # Restore session state from the session's FileStore file.
+      #
+      # Returns the session state as a hash.
+      def restore
+	unless @hash
+	  @hash = {}
+          begin
+	    f = File.open(@path, 'r')
+	    f.flock File::LOCK_SH
+	    for line in f
+	      line.chomp!
+	      k, v = line.split('=',2)
+	      @hash[CGI::unescape(k)] = CGI::unescape(v)
+	    end
+          ensure
+	    f.close unless f.nil?
+          end
+	end
+	@hash
+      end
+
+      # Save session state to the session's FileStore file.
+      def update
+	return unless @hash
+        begin
+	  f = File.open(@path, File::CREAT|File::TRUNC|File::RDWR, 0600)
+	  f.flock File::LOCK_EX
+   	  for k,v in @hash
+	    f.printf "%s=%s\n", CGI::escape(k), CGI::escape(String(v))
+	  end
+        ensure
+          f.close unless f.nil?
+        end
+      end
+
+      # Update and close the session's FileStore file.
+      def close
+	update
+      end
+
+      # Close and delete the session's FileStore file.
+      def delete
+        File::unlink @path
+      rescue Errno::ENOENT
+      end
+    end
+
+    # In-memory session storage class.
+    #
+    # Implements session storage as a global in-memory hash.  Session
+    # data will only persist for as long as the ruby interpreter 
+    # instance does.
+    class MemoryStore
+      GLOBAL_HASH_TABLE = {} #:nodoc:
+
+      # Create a new MemoryStore instance.
+      #
+      # +session+ is the session this instance is associated with.
+      # +option+ is a list of initialisation options.  None are
+      # currently recognised.
+      def initialize(session, option=nil)
+	@session_id = session.session_id
+        unless GLOBAL_HASH_TABLE.key?(@session_id)
+          unless session.new_session
+            raise CGI::Session::NoSession, "uninitialized session"
+          end
+          GLOBAL_HASH_TABLE[@session_id] = {}
+        end
+      end
+
+      # Restore session state.
+      #
+      # Returns session data as a hash.
+      def restore
+	GLOBAL_HASH_TABLE[@session_id]
+      end
+
+      # Update session state.
+      #
+      # A no-op.
+      def update
+	# don't need to update; hash is shared
+      end
+
+      # Close session storage.
+      #
+      # A no-op.
+      def close
+	# don't need to close
+      end
+
+      # Delete the session state.
+      def delete
+	GLOBAL_HASH_TABLE.delete(@session_id)
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/cgi/session/pstore.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/cgi/session/pstore.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/cgi/session/pstore.rb	(revision 18425)
@@ -0,0 +1,111 @@
+#
+# cgi/session/pstore.rb - persistent storage of marshalled session data
+#
+# Documentation: William Webber (william@williamwebber.com)
+# 
+# == Overview
+#
+# This file provides the CGI::Session::PStore class, which builds
+# persistent of session data on top of the pstore library.  See
+# cgi/session.rb for more details on session storage managers.
+
+require 'cgi/session'
+require 'pstore'
+
+class CGI
+  class Session
+    # PStore-based session storage class.
+    #
+    # This builds upon the top-level PStore class provided by the
+    # library file pstore.rb.  Session data is marshalled and stored
+    # in a file.  File locking and transaction services are provided.
+    class PStore
+      # Create a new CGI::Session::PStore instance
+      #
+      # This constructor is used internally by CGI::Session.  The
+      # user does not generally need to call it directly.
+      #
+      # +session+ is the session for which this instance is being
+      # created.  The session id must only contain alphanumeric
+      # characters; automatically generated session ids observe
+      # this requirement.
+      # 
+      # +option+ is a hash of options for the initialiser.  The
+      # following options are recognised:
+      #
+      # tmpdir:: the directory to use for storing the PStore
+      #          file.  Defaults to Dir::tmpdir (generally "/tmp"
+      #          on Unix systems).
+      # prefix:: the prefix to add to the session id when generating
+      #          the filename for this session's PStore file.
+      #          Defaults to the empty string.
+      #
+      # This session's PStore file will be created if it does
+      # not exist, or opened if it does.
+      def initialize(session, option={})
+	dir = option['tmpdir'] || Dir::tmpdir
+	prefix = option['prefix'] || ''
+	id = session.session_id
+        require 'digest/md5'
+        md5 = Digest::MD5.hexdigest(id)[0,16]
+	path = dir+"/"+prefix+md5
+	path.untaint
+	if File::exist?(path)
+	  @hash = nil
+	else
+          unless session.new_session
+            raise CGI::Session::NoSession, "uninitialized session"
+          end
+	  @hash = {}
+	end
+	@p = ::PStore.new(path)
+	@p.transaction do |p|
+	  File.chmod(0600, p.path)
+	end
+      end
+
+      # Restore session state from the session's PStore file.
+      #
+      # Returns the session state as a hash.
+      def restore
+	unless @hash
+	  @p.transaction do
+           @hash = @p['hash'] || {}
+	  end
+	end
+	@hash
+      end
+
+      # Save session state to the session's PStore file.
+      def update 
+	@p.transaction do
+	    @p['hash'] = @hash
+	end
+      end
+
+      # Update and close the session's PStore file.
+      def close
+	update
+      end
+
+      # Close and delete the session's PStore file.
+      def delete
+	path = @p.path
+	File::unlink path
+      end
+
+    end
+  end
+end
+
+if $0 == __FILE__
+  # :enddoc:
+  STDIN.reopen("/dev/null")
+  cgi = CGI.new
+  session = CGI::Session.new(cgi, 'database_manager' => CGI::Session::PStore)
+  session['key'] = {'k' => 'v'}
+  puts session['key'].class
+  fail unless Hash === session['key']
+  puts session['key'].inspect
+  fail unless session['key'].inspect == '{"k"=>"v"}'
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/complex.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/complex.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/complex.rb	(revision 18425)
@@ -0,0 +1,631 @@
+#
+#   complex.rb - 
+#   	$Release Version: 0.5 $
+#   	$Revision: 1.3 $
+#   	$Date: 1998/07/08 10:05:28 $
+#   	by Keiju ISHITSUKA(SHL Japan Inc.)
+#
+# ----
+#
+# complex.rb implements the Complex class for complex numbers.  Additionally,
+# some methods in other Numeric classes are redefined or added to allow greater
+# interoperability with Complex numbers.
+#
+# Complex numbers can be created in the following manner:
+# - <tt>Complex(a, b)</tt>
+# - <tt>Complex.polar(radius, theta)</tt>
+#   
+# Additionally, note the following:
+# - <tt>Complex::I</tt> (the mathematical constant <i>i</i>)
+# - <tt>Numeric#im</tt> (e.g. <tt>5.im -> 0+5i</tt>)
+#
+# The following +Math+ module methods are redefined to handle Complex arguments.
+# They will work as normal with non-Complex arguments.
+#    sqrt exp cos sin tan log log10
+#    cosh sinh tanh acos asin atan atan2 acosh asinh atanh
+#
+
+
+#
+# Numeric is a built-in class on which Fixnum, Bignum, etc., are based.  Here
+# some methods are added so that all number types can be treated to some extent
+# as Complex numbers.
+#
+class Numeric
+  #
+  # Returns a Complex number <tt>(0,<i>self</i>)</tt>.
+  #
+  def im
+    Complex(0, self)
+  end
+  
+  #
+  # The real part of a complex number, i.e. <i>self</i>.
+  #
+  def real
+    self
+  end
+  
+  #
+  # The imaginary part of a complex number, i.e. 0.
+  #
+  def image
+    0
+  end
+  alias imag image
+  
+  #
+  # See Complex#arg.
+  #
+  def arg
+    if self >= 0
+      return 0
+    else
+      return Math::PI
+    end
+  end
+  alias angle arg
+  
+  #
+  # See Complex#polar.
+  #
+  def polar
+    return abs, arg
+  end
+  
+  #
+  # See Complex#conjugate (short answer: returns <i>self</i>).
+  #
+  def conjugate
+    self
+  end
+  alias conj conjugate
+end
+
+
+#
+# Creates a Complex number.  +a+ and +b+ should be Numeric.  The result will be
+# <tt>a+bi</tt>.
+#
+def Complex(a, b = 0)
+  if b == 0 and (a.kind_of?(Complex) or defined? Complex::Unify)
+    a
+  else
+    Complex.new( a.real-b.imag, a.imag+b.real )
+  end
+end
+
+#
+# The complex number class.  See complex.rb for an overview.
+#
+class Complex < Numeric
+  @RCS_ID='-$Id: complex.rb,v 1.3 1998/07/08 10:05:28 keiju Exp keiju $-'
+
+  undef step
+
+  def Complex.generic?(other) # :nodoc:
+    other.kind_of?(Integer) or
+    other.kind_of?(Float) or
+    (defined?(Rational) and other.kind_of?(Rational))
+  end
+
+  #
+  # Creates a +Complex+ number in terms of +r+ (radius) and +theta+ (angle).
+  #
+  def Complex.polar(r, theta)
+    Complex(r*Math.cos(theta), r*Math.sin(theta))
+  end
+
+  #
+  # Creates a +Complex+ number <tt>a</tt>+<tt>b</tt><i>i</i>.
+  #
+  def Complex.new!(a, b=0)
+    new(a,b)
+  end
+
+  def initialize(a, b)
+    raise TypeError, "non numeric 1st arg `#{a.inspect}'" if !a.kind_of? Numeric
+    raise TypeError, "`#{a.inspect}' for 1st arg" if a.kind_of? Complex
+    raise TypeError, "non numeric 2nd arg `#{b.inspect}'" if !b.kind_of? Numeric
+    raise TypeError, "`#{b.inspect}' for 2nd arg" if b.kind_of? Complex
+    @real = a
+    @image = b
+  end
+
+  #
+  # Addition with real or complex number.
+  #
+  def + (other)
+    if other.kind_of?(Complex)
+      re = @real + other.real
+      im = @image + other.image
+      Complex(re, im)
+    elsif Complex.generic?(other)
+      Complex(@real + other, @image)
+    else
+      x , y = other.coerce(self)
+      x + y
+    end
+  end
+  
+  #
+  # Subtraction with real or complex number.
+  #
+  def - (other)
+    if other.kind_of?(Complex)
+      re = @real - other.real
+      im = @image - other.image
+      Complex(re, im)
+    elsif Complex.generic?(other)
+      Complex(@real - other, @image)
+    else
+      x , y = other.coerce(self)
+      x - y
+    end
+  end
+  
+  #
+  # Multiplication with real or complex number.
+  #
+  def * (other)
+    if other.kind_of?(Complex)
+      re = @real*other.real - @image*other.image
+      im = @real*other.image + @image*other.real
+      Complex(re, im)
+    elsif Complex.generic?(other)
+      Complex(@real * other, @image * other)
+    else
+      x , y = other.coerce(self)
+      x * y
+    end
+  end
+  
+  #
+  # Division by real or complex number.
+  #
+  def / (other)
+    if other.kind_of?(Complex)
+      self*other.conjugate/other.abs2
+    elsif Complex.generic?(other)
+      Complex(@real/other, @image/other)
+    else
+      x, y = other.coerce(self)
+      x/y
+    end
+  end
+  
+  #
+  # Raise this complex number to the given (real or complex) power.
+  #
+  def ** (other)
+    if other == 0
+      return Complex(1)
+    end
+    if other.kind_of?(Complex)
+      r, theta = polar
+      ore = other.real
+      oim = other.image
+      nr = Math.exp!(ore*Math.log!(r) - oim * theta)
+      ntheta = theta*ore + oim*Math.log!(r)
+      Complex.polar(nr, ntheta)
+    elsif other.kind_of?(Integer)
+      if other > 0
+	x = self
+	z = x
+	n = other - 1
+	while n != 0
+	  while (div, mod = n.divmod(2)
+		 mod == 0)
+	    x = Complex(x.real*x.real - x.image*x.image, 2*x.real*x.image)
+	    n = div
+	  end
+	  z *= x
+	  n -= 1
+	end
+	z
+      else
+	if defined? Rational
+	  (Rational(1) / self) ** -other
+	else
+	  self ** Float(other)
+	end
+      end
+    elsif Complex.generic?(other)
+      r, theta = polar
+      Complex.polar(r**other, theta*other)
+    else
+      x, y = other.coerce(self)
+      x**y
+    end
+  end
+  
+  #
+  # Remainder after division by a real or complex number.
+  #
+  def % (other)
+    if other.kind_of?(Complex)
+      Complex(@real % other.real, @image % other.image)
+    elsif Complex.generic?(other)
+      Complex(@real % other, @image % other)
+    else
+      x , y = other.coerce(self)
+      x % y
+    end
+  end
+  
+#--
+#    def divmod(other)
+#      if other.kind_of?(Complex)
+#        rdiv, rmod = @real.divmod(other.real)
+#        idiv, imod = @image.divmod(other.image)
+#        return Complex(rdiv, idiv), Complex(rmod, rmod)
+#      elsif Complex.generic?(other)
+#        Complex(@real.divmod(other), @image.divmod(other))
+#      else
+#        x , y = other.coerce(self)
+#        x.divmod(y)
+#      end
+#    end
+#++
+  
+  #
+  # Absolute value (aka modulus): distance from the zero point on the complex
+  # plane.
+  #
+  def abs
+    Math.hypot(@real, @image)
+  end
+  
+  #
+  # Square of the absolute value.
+  #
+  def abs2
+    @real*@real + @image*@image
+  end
+  
+  #
+  # Argument (angle from (1,0) on the complex plane).
+  #
+  def arg
+    Math.atan2!(@image, @real)
+  end
+  alias angle arg
+  
+  #
+  # Returns the absolute value _and_ the argument.
+  #
+  def polar
+    return abs, arg
+  end
+  
+  #
+  # Complex conjugate (<tt>z + z.conjugate = 2 * z.real</tt>).
+  #
+  def conjugate
+    Complex(@real, -@image)
+  end
+  alias conj conjugate
+  
+  #
+  # Compares the absolute values of the two numbers.
+  #
+  def <=> (other)
+    self.abs <=> other.abs
+  end
+  
+  #
+  # Test for numerical equality (<tt>a == a + 0<i>i</i></tt>).
+  #
+  def == (other)
+    if other.kind_of?(Complex)
+      @real == other.real and @image == other.image
+    elsif Complex.generic?(other)
+      @real == other and @image == 0
+    else
+      other == self
+    end
+  end
+
+  #
+  # Attempts to coerce +other+ to a Complex number.
+  #
+  def coerce(other)
+    if Complex.generic?(other)
+      return Complex.new!(other), self
+    else
+      super
+    end
+  end
+
+  #
+  # FIXME
+  #
+  def denominator
+    @real.denominator.lcm(@image.denominator)
+  end
+  
+  #
+  # FIXME
+  #
+  def numerator
+    cd = denominator
+    Complex(@real.numerator*(cd/@real.denominator),
+	    @image.numerator*(cd/@image.denominator))
+  end
+  
+  #
+  # Standard string representation of the complex number.
+  #
+  def to_s
+    if @real != 0
+      if defined?(Rational) and @image.kind_of?(Rational) and @image.denominator != 1
+	if @image >= 0
+	  @real.to_s+"+("+@image.to_s+")i"
+	else
+	  @real.to_s+"-("+(-@image).to_s+")i"
+	end
+      else
+	if @image >= 0
+	  @real.to_s+"+"+@image.to_s+"i"
+	else
+	  @real.to_s+"-"+(-@image).to_s+"i"
+	end
+      end
+    else
+      if defined?(Rational) and @image.kind_of?(Rational) and @image.denominator != 1
+	"("+@image.to_s+")i"
+      else
+	@image.to_s+"i"
+      end
+    end
+  end
+  
+  #
+  # Returns a hash code for the complex number.
+  #
+  def hash
+    @real.hash ^ @image.hash
+  end
+  
+  #
+  # Returns "<tt>Complex(<i>real</i>, <i>image</i>)</tt>".
+  #
+  def inspect
+    sprintf("Complex(%s, %s)", @real.inspect, @image.inspect)
+  end
+
+  
+  #
+  # +I+ is the imaginary number.  It exists at point (0,1) on the complex plane.
+  #
+  I = Complex(0,1)
+  
+  # The real part of a complex number.
+  attr :real
+
+  # The imaginary part of a complex number.
+  attr :image
+  alias imag image
+  
+end
+
+
+
+
+module Math
+  alias sqrt! sqrt
+  alias exp! exp
+  alias log! log
+  alias log10! log10
+  alias cos! cos
+  alias sin! sin
+  alias tan! tan
+  alias cosh! cosh
+  alias sinh! sinh
+  alias tanh! tanh
+  alias acos! acos
+  alias asin! asin
+  alias atan! atan
+  alias atan2! atan2
+  alias acosh! acosh
+  alias asinh! asinh
+  alias atanh! atanh  
+
+  # Redefined to handle a Complex argument.
+  def sqrt(z)
+    if Complex.generic?(z)
+      if z >= 0
+	sqrt!(z)
+      else
+	Complex(0,sqrt!(-z))
+      end
+    else
+      if z.image < 0
+	sqrt(z.conjugate).conjugate
+      else
+	r = z.abs
+	x = z.real
+	Complex( sqrt!((r+x)/2), sqrt!((r-x)/2) )
+      end
+    end
+  end
+  
+  # Redefined to handle a Complex argument.
+  def exp(z)
+    if Complex.generic?(z)
+      exp!(z)
+    else
+      Complex(exp!(z.real) * cos!(z.image), exp!(z.real) * sin!(z.image))
+    end
+  end
+  
+  # Redefined to handle a Complex argument.
+  def cos(z)
+    if Complex.generic?(z)
+      cos!(z)
+    else
+      Complex(cos!(z.real)*cosh!(z.image),
+	      -sin!(z.real)*sinh!(z.image))
+    end
+  end
+    
+  # Redefined to handle a Complex argument.
+  def sin(z)
+    if Complex.generic?(z)
+      sin!(z)
+    else
+      Complex(sin!(z.real)*cosh!(z.image),
+	      cos!(z.real)*sinh!(z.image))
+    end
+  end
+  
+  # Redefined to handle a Complex argument.
+  def tan(z)
+    if Complex.generic?(z)
+      tan!(z)
+    else
+      sin(z)/cos(z)
+    end
+  end
+
+  def sinh(z)
+    if Complex.generic?(z)
+      sinh!(z)
+    else
+      Complex( sinh!(z.real)*cos!(z.image), cosh!(z.real)*sin!(z.image) )
+    end
+  end
+
+  def cosh(z)
+    if Complex.generic?(z)
+      cosh!(z)
+    else
+      Complex( cosh!(z.real)*cos!(z.image), sinh!(z.real)*sin!(z.image) )
+    end
+  end
+
+  def tanh(z)
+    if Complex.generic?(z)
+      tanh!(z)
+    else
+      sinh(z)/cosh(z)
+    end
+  end
+  
+  # Redefined to handle a Complex argument.
+  def log(z)
+    if Complex.generic?(z) and z >= 0
+      log!(z)
+    else
+      r, theta = z.polar
+      Complex(log!(r.abs), theta)
+    end
+  end
+  
+  # Redefined to handle a Complex argument.
+  def log10(z)
+    if Complex.generic?(z)
+      log10!(z)
+    else
+      log(z)/log!(10)
+    end
+  end
+
+  def acos(z)
+    if Complex.generic?(z) and z >= -1 and z <= 1
+      acos!(z)
+    else
+      -1.0.im * log( z + 1.0.im * sqrt(1.0-z*z) )
+    end
+  end
+
+  def asin(z)
+    if Complex.generic?(z) and z >= -1 and z <= 1
+      asin!(z)
+    else
+      -1.0.im * log( 1.0.im * z + sqrt(1.0-z*z) )
+    end
+  end
+
+  def atan(z)
+    if Complex.generic?(z)
+      atan!(z)
+    else
+      1.0.im * log( (1.0.im+z) / (1.0.im-z) ) / 2.0
+    end
+  end
+
+  def atan2(y,x)
+    if Complex.generic?(y) and Complex.generic?(x)
+      atan2!(y,x)
+    else
+      -1.0.im * log( (x+1.0.im*y) / sqrt(x*x+y*y) )
+    end
+  end
+
+  def acosh(z)
+    if Complex.generic?(z) and z >= 1
+      acosh!(z)
+    else
+      log( z + sqrt(z*z-1.0) )
+    end
+  end
+
+  def asinh(z)
+    if Complex.generic?(z)
+      asinh!(z)
+    else
+      log( z + sqrt(1.0+z*z) )
+    end
+  end
+
+  def atanh(z)
+    if Complex.generic?(z) and z >= -1 and z <= 1
+      atanh!(z)
+    else
+      log( (1.0+z) / (1.0-z) ) / 2.0
+    end
+  end
+
+  module_function :sqrt!
+  module_function :sqrt
+  module_function :exp!
+  module_function :exp
+  module_function :log!
+  module_function :log
+  module_function :log10!
+  module_function :log10
+  module_function :cosh!
+  module_function :cosh
+  module_function :cos!
+  module_function :cos
+  module_function :sinh!
+  module_function :sinh
+  module_function :sin!
+  module_function :sin
+  module_function :tan!
+  module_function :tan
+  module_function :tanh!
+  module_function :tanh
+  module_function :acos!
+  module_function :acos
+  module_function :asin!
+  module_function :asin
+  module_function :atan!
+  module_function :atan
+  module_function :atan2!
+  module_function :atan2
+  module_function :acosh!
+  module_function :acosh
+  module_function :asinh!
+  module_function :asinh
+  module_function :atanh!
+  module_function :atanh
+  
+end
+
+# Documentation comments:
+#  - source: original (researched from pickaxe)
+#  - a couple of fixme's
+#  - RDoc output for Bignum etc. is a bit short, with nothing but an
+#    (undocumented) alias.  No big deal.
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/csv.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/csv.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/csv.rb	(revision 18425)
@@ -0,0 +1,992 @@
+# CSV -- module for generating/parsing CSV data.
+# Copyright (C) 2000-2004  NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>.
+  
+# $Id: csv.rb 11708 2007-02-12 23:01:19Z shyouhei $
+  
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+  
+  
+class CSV
+  class IllegalFormatError < RuntimeError; end
+
+  # deprecated
+  class Cell < String
+    def initialize(data = "", is_null = false)
+      super(is_null ? "" : data)
+    end
+
+    def data
+      to_s
+    end
+  end
+
+  # deprecated
+  class Row < Array
+  end
+
+  # Open a CSV formatted file for reading or writing.
+  #
+  # For reading.
+  #
+  # EXAMPLE 1
+  #   CSV.open('csvfile.csv', 'r') do |row|
+  #     p row
+  #   end
+  #
+  # EXAMPLE 2
+  #   reader = CSV.open('csvfile.csv', 'r')
+  #   row1 = reader.shift
+  #   row2 = reader.shift
+  #   if row2.empty?
+  #     p 'row2 not find.'
+  #   end
+  #   reader.close
+  #
+  # ARGS
+  #   filename: filename to parse.
+  #   col_sep: Column separator.  ?, by default.  If you want to separate
+  #     fields with semicolon, give ?; here.
+  #   row_sep: Row separator.  nil by default.  nil means "\r\n or \n".  If you
+  #     want to separate records with \r, give ?\r here.
+  #
+  # RETURNS
+  #   reader instance.  To get parse result, see CSV::Reader#each.
+  #
+  #
+  # For writing.
+  #
+  # EXAMPLE 1
+  #   CSV.open('csvfile.csv', 'w') do |writer|
+  #     writer << ['r1c1', 'r1c2']
+  #     writer << ['r2c1', 'r2c2']
+  #     writer << [nil, nil]
+  #   end
+  #
+  # EXAMPLE 2
+  #   writer = CSV.open('csvfile.csv', 'w')
+  #   writer << ['r1c1', 'r1c2'] << ['r2c1', 'r2c2'] << [nil, nil]
+  #   writer.close
+  #
+  # ARGS
+  #   filename: filename to generate.
+  #   col_sep: Column separator.  ?, by default.  If you want to separate
+  #     fields with semicolon, give ?; here.
+  #   row_sep: Row separator.  nil by default.  nil means "\r\n or \n".  If you
+  #     want to separate records with \r, give ?\r here.
+  #
+  # RETURNS
+  #   writer instance.  See CSV::Writer#<< and CSV::Writer#add_row to know how
+  #   to generate CSV string.
+  #
+  def CSV.open(path, mode, fs = nil, rs = nil, &block)
+    if mode == 'r' or mode == 'rb'
+      open_reader(path, mode, fs, rs, &block)
+    elsif mode == 'w' or mode == 'wb'
+      open_writer(path, mode, fs, rs, &block)
+    else
+      raise ArgumentError.new("'mode' must be 'r', 'rb', 'w', or 'wb'")
+    end
+  end
+
+  def CSV.foreach(path, rs = nil, &block)
+    open_reader(path, 'r', ',', rs, &block)
+  end
+
+  def CSV.read(path, length = nil, offset = nil)
+    CSV.parse(IO.read(path, length, offset))
+  end
+  
+  def CSV.readlines(path, rs = nil)
+    reader = open_reader(path, 'r', ',', rs)
+    begin
+      reader.collect { |row| row }
+    ensure
+      reader.close
+    end
+  end
+
+  def CSV.generate(path, fs = nil, rs = nil, &block)
+    open_writer(path, 'w', fs, rs, &block)
+  end
+
+  # Parse lines from given string or stream.  Return rows as an Array of Arrays.
+  def CSV.parse(str_or_readable, fs = nil, rs = nil, &block)
+    if File.exist?(str_or_readable)
+      STDERR.puts("CSV.parse(filename) is deprecated." +
+        "  Use CSV.open(filename, 'r') instead.")
+      return open_reader(str_or_readable, 'r', fs, rs, &block)
+    end
+    if block
+      CSV::Reader.parse(str_or_readable, fs, rs) do |row|
+        yield(row)
+      end
+      nil
+    else
+      CSV::Reader.create(str_or_readable, fs, rs).collect { |row| row }
+    end
+  end
+
+  # Parse a line from given string.  Bear in mind it parses ONE LINE.  Rest of
+  # the string is ignored for example "a,b\r\nc,d" => ['a', 'b'] and the
+  # second line 'c,d' is ignored.
+  #
+  # If you don't know whether a target string to parse is exactly 1 line or
+  # not, use CSV.parse_row instead of this method.
+  def CSV.parse_line(src, fs = nil, rs = nil)
+    fs ||= ','
+    if fs.is_a?(Fixnum)
+      fs = fs.chr
+    end
+    if !rs.nil? and rs.is_a?(Fixnum)
+      rs = rs.chr
+    end
+    idx = 0
+    res_type = :DT_COLSEP
+    row = []
+    begin
+      while res_type == :DT_COLSEP
+        res_type, idx, cell = parse_body(src, idx, fs, rs)
+        row << cell
+      end
+    rescue IllegalFormatError
+      return []
+    end
+    row
+  end
+
+  # Create a line from cells.  each cell is stringified by to_s.
+  def CSV.generate_line(row, fs = nil, rs = nil)
+    if row.size == 0
+      return ''
+    end
+    fs ||= ','
+    if fs.is_a?(Fixnum)
+      fs = fs.chr
+    end
+    if !rs.nil? and rs.is_a?(Fixnum)
+      rs = rs.chr
+    end
+    res_type = :DT_COLSEP
+    result_str = ''
+    idx = 0
+    while true
+      generate_body(row[idx], result_str, fs, rs)
+      idx += 1
+      if (idx == row.size)
+        break
+      end
+      generate_separator(:DT_COLSEP, result_str, fs, rs)
+    end
+    result_str
+  end
+  
+  # Parse a line from string.  Consider using CSV.parse_line instead.
+  # To parse lines in CSV string, see EXAMPLE below.
+  #
+  # EXAMPLE
+  #   src = "a,b\r\nc,d\r\ne,f"
+  #   idx = 0
+  #   begin
+  #     parsed = []
+  #     parsed_cells, idx = CSV.parse_row(src, idx, parsed)
+  #     puts "Parsed #{ parsed_cells } cells."
+  #     p parsed
+  #   end while parsed_cells > 0
+  #
+  # ARGS
+  #   src: a CSV data to be parsed.  Must respond '[](idx)'.
+  #     src[](idx) must return a char. (Not a string such as 'a', but 97).
+  #     src[](idx_out_of_bounds) must return nil.  A String satisfies this
+  #     requirement.
+  #   idx: index of parsing location of 'src'.  0 origin.
+  #   out_dev: buffer for parsed cells.  Must respond '<<(aString)'.
+  #   col_sep: Column separator.  ?, by default.  If you want to separate
+  #     fields with semicolon, give ?; here.
+  #   row_sep: Row separator.  nil by default.  nil means "\r\n or \n".  If you
+  #     want to separate records with \r, give ?\r here.
+  #
+  # RETURNS
+  #   parsed_cells: num of parsed cells.
+  #   idx: index of next parsing location of 'src'.
+  #
+  def CSV.parse_row(src, idx, out_dev, fs = nil, rs = nil)
+    fs ||= ','
+    if fs.is_a?(Fixnum)
+      fs = fs.chr
+    end
+    if !rs.nil? and rs.is_a?(Fixnum)
+      rs = rs.chr
+    end
+    idx_backup = idx
+    parsed_cells = 0
+    res_type = :DT_COLSEP
+    begin
+      while res_type != :DT_ROWSEP
+        res_type, idx, cell = parse_body(src, idx, fs, rs)
+        if res_type == :DT_EOS
+          if idx == idx_backup #((parsed_cells == 0) and cell.nil?)
+            return 0, 0
+          end
+          res_type = :DT_ROWSEP
+        end
+        parsed_cells += 1
+        out_dev << cell
+      end
+    rescue IllegalFormatError
+      return 0, 0
+    end
+    return parsed_cells, idx
+  end
+  
+  # Convert a line from cells data to string.  Consider using CSV.generate_line
+  # instead.  To generate multi-row CSV string, see EXAMPLE below.
+  #
+  # EXAMPLE
+  #   row1 = ['a', 'b']
+  #   row2 = ['c', 'd']
+  #   row3 = ['e', 'f']
+  #   src = [row1, row2, row3]
+  #   buf = ''
+  #   src.each do |row|
+  #     parsed_cells = CSV.generate_row(row, 2, buf)
+  #     puts "Created #{ parsed_cells } cells."
+  #   end
+  #   p buf
+  #
+  # ARGS
+  #   src: an Array of String to be converted to CSV string.  Must respond to
+  #     'size' and '[](idx)'.  src[idx] must return String.
+  #   cells: num of cells in a line.
+  #   out_dev: buffer for generated CSV string.  Must respond to '<<(string)'.
+  #   col_sep: Column separator.  ?, by default.  If you want to separate
+  #     fields with semicolon, give ?; here.
+  #   row_sep: Row separator.  nil by default.  nil means "\r\n or \n".  If you
+  #     want to separate records with \r, give ?\r here.
+  #
+  # RETURNS
+  #   parsed_cells: num of converted cells.
+  #
+  def CSV.generate_row(src, cells, out_dev, fs = nil, rs = nil)
+    fs ||= ','
+    if fs.is_a?(Fixnum)
+      fs = fs.chr
+    end
+    if !rs.nil? and rs.is_a?(Fixnum)
+      rs = rs.chr
+    end
+    src_size = src.size
+    if (src_size == 0)
+      if cells == 0
+        generate_separator(:DT_ROWSEP, out_dev, fs, rs)
+      end
+      return 0
+    end
+    res_type = :DT_COLSEP
+    parsed_cells = 0
+    generate_body(src[parsed_cells], out_dev, fs, rs)
+    parsed_cells += 1
+    while ((parsed_cells < cells) and (parsed_cells != src_size))
+      generate_separator(:DT_COLSEP, out_dev, fs, rs)
+      generate_body(src[parsed_cells], out_dev, fs, rs)
+      parsed_cells += 1
+    end
+    if (parsed_cells == cells)
+      generate_separator(:DT_ROWSEP, out_dev, fs, rs)
+    else
+      generate_separator(:DT_COLSEP, out_dev, fs, rs)
+    end
+    parsed_cells
+  end
+  
+  # Private class methods.
+  class << self
+  private
+
+    def open_reader(path, mode, fs, rs, &block)
+      file = File.open(path, mode)
+      if block
+        begin
+          CSV::Reader.parse(file, fs, rs) do |row|
+            yield(row)
+          end
+        ensure
+          file.close
+        end
+        nil
+      else
+        reader = CSV::Reader.create(file, fs, rs)
+        reader.close_on_terminate
+        reader
+      end
+    end
+
+    def open_writer(path, mode, fs, rs, &block)
+      file = File.open(path, mode)
+      if block
+        begin
+          CSV::Writer.generate(file, fs, rs) do |writer|
+            yield(writer)
+          end
+        ensure
+          file.close
+        end
+        nil
+      else
+        writer = CSV::Writer.create(file, fs, rs) 
+        writer.close_on_terminate
+        writer
+      end
+    end
+
+    def parse_body(src, idx, fs, rs)
+      fs_str = fs
+      fs_size = fs_str.size
+      rs_str = rs || "\n"
+      rs_size = rs_str.size
+      fs_idx = rs_idx = 0
+      cell = Cell.new
+      state = :ST_START
+      quoted = cr = false
+      c = nil
+      last_idx = idx
+      while c = src[idx]
+        unless quoted
+          fschar = (c == fs_str[fs_idx])
+          rschar = (c == rs_str[rs_idx])
+          # simple 1 char backtrack
+          if !fschar and c == fs_str[0]
+            fs_idx = 0
+            fschar = true
+            if state == :ST_START
+              state = :ST_DATA
+            elsif state == :ST_QUOTE
+              raise IllegalFormatError
+            end
+          end
+          if !rschar and c == rs_str[0]
+            rs_idx = 0
+            rschar = true
+            if state == :ST_START
+              state = :ST_DATA
+            elsif state == :ST_QUOTE
+              raise IllegalFormatError
+            end
+          end
+        end
+        if c == ?"
+          fs_idx = rs_idx = 0
+          if cr
+            raise IllegalFormatError
+          end
+          cell << src[last_idx, (idx - last_idx)]
+          last_idx = idx
+          if state == :ST_DATA
+            if quoted
+              last_idx += 1
+              quoted = false
+              state = :ST_QUOTE
+            else
+              raise IllegalFormatError
+            end
+          elsif state == :ST_QUOTE
+            cell << c.chr
+            last_idx += 1
+            quoted = true
+            state = :ST_DATA
+          else  # :ST_START
+            quoted = true
+            last_idx += 1
+            state = :ST_DATA
+          end
+        elsif fschar or rschar
+          if fschar
+            fs_idx += 1
+          end
+          if rschar
+            rs_idx += 1
+          end
+          sep = nil
+          if fs_idx == fs_size
+            if state == :ST_START and rs_idx > 0 and fs_idx < rs_idx
+              state = :ST_DATA
+            end
+            cell << src[last_idx, (idx - last_idx - (fs_size - 1))]
+            last_idx = idx
+            fs_idx = rs_idx = 0
+            if cr
+              raise IllegalFormatError
+            end
+            sep = :DT_COLSEP
+          elsif rs_idx == rs_size
+            if state == :ST_START and fs_idx > 0 and rs_idx < fs_idx
+              state = :ST_DATA
+            end
+            if !(rs.nil? and cr)
+              cell << src[last_idx, (idx - last_idx - (rs_size - 1))]
+              last_idx = idx
+            end
+            fs_idx = rs_idx = 0
+            sep = :DT_ROWSEP
+          end
+          if sep
+            if state == :ST_DATA
+              return sep, idx + 1, cell;
+            elsif state == :ST_QUOTE
+              return sep, idx + 1, cell;
+            else  # :ST_START
+              return sep, idx + 1, nil
+            end
+          end
+        elsif rs.nil? and c == ?\r
+          # special \r treatment for backward compatibility
+          fs_idx = rs_idx = 0
+          if cr
+            raise IllegalFormatError
+          end
+          cell << src[last_idx, (idx - last_idx)]
+          last_idx = idx
+          if quoted
+            state = :ST_DATA
+          else
+            cr = true
+          end
+        else
+          fs_idx = rs_idx = 0
+          if state == :ST_DATA or state == :ST_START
+            if cr
+              raise IllegalFormatError
+            end
+            state = :ST_DATA
+          else  # :ST_QUOTE
+            raise IllegalFormatError
+          end
+        end
+        idx += 1
+      end
+      if state == :ST_START
+        if fs_idx > 0 or rs_idx > 0
+          state = :ST_DATA
+        else
+          return :DT_EOS, idx, nil
+        end
+      elsif quoted
+        raise IllegalFormatError
+      elsif cr
+        raise IllegalFormatError
+      end
+      cell << src[last_idx, (idx - last_idx)]
+      last_idx = idx
+      return :DT_EOS, idx, cell
+    end
+  
+    def generate_body(cell, out_dev, fs, rs)
+      if cell.nil?
+        # empty
+      else
+        cell = cell.to_s
+        row_data = cell.dup
+        if (row_data.gsub!('"', '""') or
+            row_data.index(fs) or
+            (rs and row_data.index(rs)) or
+            (/[\r\n]/ =~ row_data) or
+            (cell.empty?))
+          out_dev << '"' << row_data << '"'
+        else
+          out_dev << row_data
+        end
+      end
+    end
+    
+    def generate_separator(type, out_dev, fs, rs)
+      case type
+      when :DT_COLSEP
+        out_dev << fs
+      when :DT_ROWSEP
+        out_dev << (rs || "\n")
+      end
+    end
+  end
+
+
+  # CSV formatted string/stream reader.
+  #
+  # EXAMPLE
+  #   read CSV lines untill the first column is 'stop'.
+  #
+  #   CSV::Reader.parse(File.open('bigdata', 'rb')) do |row|
+  #     p row
+  #     break if !row[0].is_null && row[0].data == 'stop'
+  #   end
+  #
+  class Reader
+    include Enumerable
+
+    # Parse CSV data and get lines.  Given block is called for each parsed row.
+    # Block value is always nil.  Rows are not cached for performance reason.
+    def Reader.parse(str_or_readable, fs = ',', rs = nil, &block)
+      reader = Reader.create(str_or_readable, fs, rs)
+      if block
+        reader.each do |row|
+          yield(row)
+        end
+        reader.close
+        nil
+      else
+        reader
+      end
+    end
+
+    # Returns reader instance.
+    def Reader.create(str_or_readable, fs = ',', rs = nil)
+      case str_or_readable
+      when IO
+        IOReader.new(str_or_readable, fs, rs)
+      when String
+        StringReader.new(str_or_readable, fs, rs)
+      else
+        IOReader.new(str_or_readable, fs, rs)
+      end
+    end
+
+    def each
+      while true
+        row = []
+        parsed_cells = get_row(row)
+        if parsed_cells == 0
+          break
+        end
+        yield(row)
+      end
+      nil
+    end
+
+    def shift
+      row = []
+      parsed_cells = get_row(row)
+      row
+    end
+
+    def close
+      terminate
+    end
+
+  private
+
+    def initialize(dev)
+      raise RuntimeError.new('Do not instanciate this class directly.')
+    end
+
+    def get_row(row)
+      raise NotImplementedError.new('Method get_row must be defined in a derived class.')
+    end
+
+    def terminate
+      # Define if needed.
+    end
+  end
+  
+
+  class StringReader < Reader
+    def initialize(string, fs = ',', rs = nil)
+      @fs = fs
+      @rs = rs
+      @dev = string
+      @idx = 0
+      if @dev[0, 3] == "\xef\xbb\xbf"
+        @idx += 3
+      end
+    end
+
+  private
+
+    def get_row(row)
+      parsed_cells, next_idx = CSV.parse_row(@dev, @idx, row, @fs, @rs)
+      if parsed_cells == 0 and next_idx == 0 and @idx != @dev.size
+        raise IllegalFormatError.new
+      end
+      @idx = next_idx
+      parsed_cells
+    end
+  end
+
+
+  class IOReader < Reader
+    def initialize(io, fs = ',', rs = nil)
+      @io = io
+      @fs = fs
+      @rs = rs
+      @dev = CSV::IOBuf.new(@io)
+      @idx = 0
+      if @dev[0] == 0xef and @dev[1] == 0xbb and @dev[2] == 0xbf
+        @idx += 3
+      end
+      @close_on_terminate = false
+    end
+
+    # Tell this reader to close the IO when terminated (Triggered by invoking
+    # CSV::IOReader#close).
+    def close_on_terminate
+      @close_on_terminate = true
+    end
+
+  private
+
+    def get_row(row)
+      parsed_cells, next_idx = CSV.parse_row(@dev, @idx, row, @fs, @rs)
+      if parsed_cells == 0 and next_idx == 0 and !@dev.is_eos?
+        raise IllegalFormatError.new
+      end
+      dropped = @dev.drop(next_idx)
+      @idx = next_idx - dropped
+      parsed_cells
+    end
+
+    def terminate
+      if @close_on_terminate
+        @io.close
+      end
+
+      if @dev
+        @dev.close
+      end
+    end
+  end
+
+
+  # CSV formatted string/stream writer.
+  #
+  # EXAMPLE
+  #   Write rows to 'csvout' file.
+  #
+  #   outfile = File.open('csvout', 'wb')
+  #   CSV::Writer.generate(outfile) do |csv|
+  #     csv << ['c1', nil, '', '"', "\r\n", 'c2']
+  #     ...
+  #   end
+  #
+  #   outfile.close
+  #
+  class Writer
+    # Given block is called with the writer instance.  str_or_writable must
+    # handle '<<(string)'.
+    def Writer.generate(str_or_writable, fs = ',', rs = nil, &block)
+      writer = Writer.create(str_or_writable, fs, rs)
+      if block
+        yield(writer)
+        writer.close
+        nil
+      else
+        writer
+      end
+    end
+
+    # str_or_writable must handle '<<(string)'.
+    def Writer.create(str_or_writable, fs = ',', rs = nil)
+      BasicWriter.new(str_or_writable, fs, rs)
+    end
+
+    # dump CSV stream to the device.  argument must be an Array of String.
+    def <<(row)
+      CSV.generate_row(row, row.size, @dev, @fs, @rs)
+      self
+    end
+    alias add_row <<
+
+    def close
+      terminate
+    end
+
+  private
+
+    def initialize(dev)
+      raise RuntimeError.new('Do not instanciate this class directly.')
+    end
+
+    def terminate
+      # Define if needed.
+    end
+  end
+
+
+  class BasicWriter < Writer
+    def initialize(str_or_writable, fs = ',', rs = nil)
+      @fs = fs
+      @rs = rs
+      @dev = str_or_writable
+      @close_on_terminate = false
+    end
+
+    # Tell this writer to close the IO when terminated (Triggered by invoking
+    # CSV::BasicWriter#close).
+    def close_on_terminate
+      @close_on_terminate = true
+    end
+
+  private
+
+    def terminate
+      if @close_on_terminate
+        @dev.close
+      end
+    end
+  end
+
+private
+
+  # Buffered stream.
+  #
+  # EXAMPLE 1 -- an IO.
+  #   class MyBuf < StreamBuf
+  #     # Do initialize myself before a super class.  Super class might call my
+  #     # method 'read'. (Could be awful for C++ user. :-)
+  #     def initialize(s)
+  #       @s = s
+  #       super()
+  #     end
+  #
+  #     # define my own 'read' method.
+  #     # CAUTION: Returning nil means EnfOfStream.
+  #     def read(size)
+  #       @s.read(size)
+  #     end
+  #
+  #     # release buffers. in Ruby which has GC, you do not have to call this...
+  #     def terminate
+  #       @s = nil
+  #       super()
+  #     end
+  #   end
+  #
+  #   buf = MyBuf.new(STDIN)
+  #   my_str = ''
+  #   p buf[0, 0]               # => '' (null string)
+  #   p buf[0]                  # => 97 (char code of 'a')
+  #   p buf[0, 1]               # => 'a'
+  #   my_str = buf[0, 5]
+  #   p my_str                  # => 'abcde' (5 chars)
+  #   p buf[0, 6]               # => "abcde\n" (6 chars)
+  #   p buf[0, 7]               # => "abcde\n" (6 chars)
+  #   p buf.drop(3)             # => 3 (dropped chars)
+  #   p buf.get(0, 2)           # => 'de' (2 chars)
+  #   p buf.is_eos?             # => false (is not EOS here)
+  #   p buf.drop(5)             # => 3 (dropped chars)
+  #   p buf.is_eos?             # => true (is EOS here)
+  #   p buf[0]                  # => nil (is EOS here)
+  #
+  # EXAMPLE 2 -- String.
+  #   This is a conceptual example.  No pros with this.
+  #
+  #   class StrBuf < StreamBuf
+  #     def initialize(s)
+  #       @str = s
+  #       @idx = 0
+  #       super()
+  #     end
+  #
+  #     def read(size)
+  #       str = @str[@idx, size]
+  #       @idx += str.size
+  #       str
+  #     end
+  #   end
+  #
+  class StreamBuf
+    # get a char or a partial string from the stream.
+    # idx: index of a string to specify a start point of a string to get.
+    # unlike String instance, idx < 0 returns nil.
+    # n: size of a string to get.
+    # returns char at idx if n == nil.
+    # returns a partial string, from idx to (idx + n) if n != nil.  at EOF,
+    # the string size could not equal to arg n.
+    def [](idx, n = nil) 
+      if idx < 0
+        return nil
+      end
+      if (idx_is_eos?(idx))
+        if n and (@offset + idx == buf_size(@cur_buf))
+          # Like a String, 'abc'[4, 1] returns nil and
+          # 'abc'[3, 1] returns '' not nil.
+          return ''
+        else
+          return nil
+        end
+      end
+      my_buf = @cur_buf
+      my_offset = @offset
+      next_idx = idx
+      while (my_offset + next_idx >= buf_size(my_buf))
+        if (my_buf == @buf_tail_idx)
+          unless add_buf
+            break
+          end
+        end
+        next_idx = my_offset + next_idx - buf_size(my_buf)
+        my_buf += 1
+        my_offset = 0
+      end
+      loc = my_offset + next_idx
+      if !n
+        return @buf_list[my_buf][loc]           # Fixnum of char code.
+      elsif (loc + n - 1 < buf_size(my_buf))
+        return @buf_list[my_buf][loc, n]        # String.
+      else # should do loop insted of (tail) recursive call...
+        res = @buf_list[my_buf][loc, BufSize]
+        size_added = buf_size(my_buf) - loc
+        if size_added > 0
+          idx += size_added
+          n -= size_added
+          ret = self[idx, n]
+          if ret
+            res << ret
+          end
+        end
+        return res
+      end
+    end
+    alias get []
+  
+    # drop a string from the stream.
+    # returns dropped size.  at EOF, dropped size might not equals to arg n.
+    # Once you drop the head of the stream, access to the dropped part via []
+    # or get returns nil.
+    def drop(n)
+      if is_eos?
+        return 0
+      end
+      size_dropped = 0
+      while (n > 0)
+        if !@is_eos or (@cur_buf != @buf_tail_idx)
+          if (@offset + n < buf_size(@cur_buf))
+            size_dropped += n
+            @offset += n
+            n = 0
+          else
+            size = buf_size(@cur_buf) - @offset
+            size_dropped += size
+            n -= size
+            @offset = 0
+            unless rel_buf
+              unless add_buf
+                break
+              end
+              @cur_buf = @buf_tail_idx
+            end
+          end
+        end
+      end
+      size_dropped
+    end
+  
+    def is_eos?
+      return idx_is_eos?(0)
+    end
+  
+    # WARN: Do not instantiate this class directly.  Define your own class
+    # which derives this class and define 'read' instance method.
+    def initialize
+      @buf_list = []
+      @cur_buf = @buf_tail_idx = -1
+      @offset = 0
+      @is_eos = false
+      add_buf
+      @cur_buf = @buf_tail_idx
+    end
+  
+  protected
+
+    def terminate
+      while (rel_buf); end
+    end
+  
+    # protected method 'read' must be defined in derived classes.
+    # CAUTION: Returning a string which size is not equal to 'size' means
+    # EnfOfStream.  When it is not at EOS, you must block the callee, try to
+    # read and return the sized string.
+    def read(size) # raise EOFError
+      raise NotImplementedError.new('Method read must be defined in a derived class.')
+    end
+  
+  private
+  
+    def buf_size(idx)
+      @buf_list[idx].size
+    end
+
+    def add_buf
+      if @is_eos
+        return false
+      end
+      begin
+        str_read = read(BufSize)
+      rescue EOFError
+        str_read = nil
+      rescue
+        terminate
+        raise
+      end
+      if str_read.nil?
+        @is_eos = true
+        @buf_list.push('')
+        @buf_tail_idx += 1
+        false
+      else
+        @buf_list.push(str_read)
+        @buf_tail_idx += 1
+        true
+      end
+    end
+  
+    def rel_buf
+      if (@cur_buf < 0)
+        return false
+      end
+      @buf_list[@cur_buf] = nil
+      if (@cur_buf == @buf_tail_idx)
+        @cur_buf = -1
+        return false
+      else
+        @cur_buf += 1
+        return true
+      end
+    end
+  
+    def idx_is_eos?(idx)
+      (@is_eos and ((@cur_buf < 0) or (@cur_buf == @buf_tail_idx)))
+    end
+  
+    BufSize = 1024 * 8
+  end
+
+  # Buffered IO.
+  #
+  # EXAMPLE
+  #   # File 'bigdata' could be a giga-byte size one!
+  #   buf = CSV::IOBuf.new(File.open('bigdata', 'rb'))
+  #   CSV::Reader.new(buf).each do |row|
+  #     p row
+  #     break if row[0].data == 'admin'
+  #   end
+  #
+  class IOBuf < StreamBuf
+    def initialize(s)
+      @s = s
+      super()
+    end
+  
+    def close
+      terminate
+    end
+
+  private
+
+    def read(size)
+      @s.read(size)
+    end
+ 
+    def terminate
+      super()
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/date.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/date.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/date.rb	(revision 18425)
@@ -0,0 +1,1708 @@
+#
+# date.rb - date and time library
+#
+# Author: Tadayoshi Funaba 1998-2006
+#
+# Documentation: William Webber <william@williamwebber.com>
+#
+#--
+# $Id: date.rb,v 2.30 2006-12-30 21:43:41+09 tadf Exp $
+#++
+#
+# == Overview
+#
+# This file provides two classes for working with
+# dates and times.
+#
+# The first class, Date, represents dates.
+# It works with years, months, weeks, and days.
+# See the Date class documentation for more details.
+#
+# The second, DateTime, extends Date to include hours,
+# minutes, seconds, and fractions of a second.  It
+# provides basic support for time zones.  See the
+# DateTime class documentation for more details.
+#
+# === Ways of calculating the date.
+#
+# In common usage, the date is reckoned in years since or
+# before the Common Era (CE/BCE, also known as AD/BC), then
+# as a month and day-of-the-month within the current year.
+# This is known as the *Civil* *Date*, and abbreviated
+# as +civil+ in the Date class.
+#
+# Instead of year, month-of-the-year,  and day-of-the-month,
+# the date can also be reckoned in terms of year and
+# day-of-the-year.  This is known as the *Ordinal* *Date*,
+# and is abbreviated as +ordinal+ in the Date class.  (Note
+# that referring to this as the Julian date is incorrect.)
+#
+# The date can also be reckoned in terms of year, week-of-the-year,
+# and day-of-the-week.  This is known as the *Commercial*
+# *Date*, and is abbreviated as +commercial+ in the
+# Date class.  The commercial week runs Monday (day-of-the-week
+# 1) to Sunday (day-of-the-week 7), in contrast to the civil
+# week which runs Sunday (day-of-the-week 0) to Saturday
+# (day-of-the-week 6).  The first week of the commercial year
+# starts on the Monday on or before January 1, and the commercial
+# year itself starts on this Monday, not January 1.
+#
+# For scientific purposes, it is convenient to refer to a date
+# simply as a day count, counting from an arbitrary initial
+# day.  The date first chosen for this was January 1, 4713 BCE.
+# A count of days from this date is the *Julian* *Day* *Number*
+# or *Julian* *Date*, which is abbreviated as +jd+ in the
+# Date class.  This is in local time, and counts from midnight
+# on the initial day.  The stricter usage is in UTC, and counts
+# from midday on the initial day.  This is referred to in the
+# Date class as the *Astronomical* *Julian* *Day* *Number*, and
+# abbreviated as +ajd+.  In the Date class, the Astronomical
+# Julian Day Number includes fractional days.
+#
+# Another absolute day count is the *Modified* *Julian* *Day*
+# *Number*, which takes November 17, 1858 as its initial day.
+# This is abbreviated as +mjd+ in the Date class.  There
+# is also an *Astronomical* *Modified* *Julian* *Day* *Number*,
+# which is in UTC and includes fractional days.  This is
+# abbreviated as +amjd+ in the Date class.  Like the Modified
+# Julian Day Number (and unlike the Astronomical Julian
+# Day Number), it counts from midnight.
+#
+# Alternative calendars such as the Chinese Lunar Calendar,
+# the Islamic Calendar, or the French Revolutionary Calendar
+# are not supported by the Date class; nor are calendars that
+# are based on an Era different from the Common Era, such as
+# the Japanese Imperial Calendar or the Republic of China
+# Calendar.
+#
+# === Calendar Reform
+#
+# The standard civil year is 365 days long.  However, the
+# solar year is fractionally longer than this.  To account
+# for this, a *leap* *year* is occasionally inserted.  This
+# is a year with 366 days, the extra day falling on February 29.
+# In the early days of the civil calendar, every fourth
+# year without exception was a leap year.  This way of
+# reckoning leap years is the *Julian* *Calendar*.
+#
+# However, the solar year is marginally shorter than 365 1/4
+# days, and so the *Julian* *Calendar* gradually ran slow
+# over the centuries.  To correct this, every 100th year
+# (but not every 400th year) was excluded as a leap year.
+# This way of reckoning leap years, which we use today, is
+# the *Gregorian* *Calendar*.
+#
+# The Gregorian Calendar was introduced at different times
+# in different regions.  The day on which it was introduced
+# for a particular region is the *Day* *of* *Calendar*
+# *Reform* for that region.  This is abbreviated as +sg+
+# (for Start of Gregorian calendar) in the Date class.
+#
+# Two such days are of particular
+# significance.  The first is October 15, 1582, which was
+# the Day of Calendar Reform for Italy and most Catholic
+# countries.  The second is September 14, 1752, which was
+# the Day of Calendar Reform for England and its colonies
+# (including what is now the United States).  These two
+# dates are available as the constants Date::ITALY and
+# Date::ENGLAND, respectively.  (By comparison, Germany and
+# Holland, less Catholic than Italy but less stubborn than
+# England, changed over in 1698; Sweden in 1753; Russia not
+# till 1918, after the Revolution; and Greece in 1923.  Many
+# Orthodox churches still use the Julian Calendar.  A complete
+# list of Days of Calendar Reform can be found at
+# http://www.polysyllabic.com/GregConv.html.)
+#
+# Switching from the Julian to the Gregorian calendar
+# involved skipping a number of days to make up for the
+# accumulated lag, and the later the switch was (or is)
+# done, the more days need to be skipped.  So in 1582 in Italy,
+# 4th October was followed by 15th October, skipping 10 days; in 1752
+# in England, 2nd September was followed by 14th September, skipping
+# 11 days; and if I decided to switch from Julian to Gregorian
+# Calendar this midnight, I would go from 27th July 2003 (Julian)
+# today to 10th August 2003 (Gregorian) tomorrow, skipping
+# 13 days.  The Date class is aware of this gap, and a supposed
+# date that would fall in the middle of it is regarded as invalid.
+#
+# The Day of Calendar Reform is relevant to all date representations
+# involving years.  It is not relevant to the Julian Day Numbers,
+# except for converting between them and year-based representations.
+#
+# In the Date and DateTime classes, the Day of Calendar Reform or
+# +sg+ can be specified a number of ways.  First, it can be as
+# the Julian Day Number of the Day of Calendar Reform.  Second,
+# it can be using the constants Date::ITALY or Date::ENGLAND; these
+# are in fact the Julian Day Numbers of the Day of Calendar Reform
+# of the respective regions.  Third, it can be as the constant
+# Date::JULIAN, which means to always use the Julian Calendar.
+# Finally, it can be as the constant Date::GREGORIAN, which means
+# to always use the Gregorian Calendar.
+#
+# Note: in the Julian Calendar, New Years Day was March 25.  The
+# Date class does not follow this convention.
+#
+# === Time Zones
+#
+# DateTime objects support a simple representation
+# of time zones.  Time zones are represented as an offset
+# from UTC, as a fraction of a day.  This offset is the
+# how much local time is later (or earlier) than UTC.
+# UTC offset 0 is centred on England (also known as GMT).
+# As you travel east, the offset increases until you
+# reach the dateline in the middle of the Pacific Ocean;
+# as you travel west, the offset decreases.  This offset
+# is abbreviated as +of+ in the Date class.
+#
+# This simple representation of time zones does not take
+# into account the common practice of Daylight Savings
+# Time or Summer Time.
+#
+# Most DateTime methods return the date and the
+# time in local time.  The two exceptions are
+# #ajd() and #amjd(), which return the date and time
+# in UTC time, including fractional days.
+#
+# The Date class does not support time zone offsets, in that
+# there is no way to create a Date object with a time zone.
+# However, methods of the Date class when used by a
+# DateTime instance will use the time zone offset of this
+# instance.
+#
+# == Examples of use
+#
+# === Print out the date of every Sunday between two dates.
+#
+#     def print_sundays(d1, d2)
+#         d1 +=1 while (d1.wday != 0)
+#         d1.step(d2, 7) do |date|
+#             puts "#{Date::MONTHNAMES[date.mon]} #{date.day}"
+#         end
+#     end
+#
+#     print_sundays(Date::civil(2003, 4, 8), Date::civil(2003, 5, 23))
+#
+# === Calculate how many seconds to go till midnight on New Year's Day.
+#
+#     def secs_to_new_year(now = DateTime::now())
+#         new_year = DateTime.new(now.year + 1, 1, 1)
+#         dif = new_year - now
+#         hours, mins, secs, ignore_fractions = Date::day_fraction_to_time(dif)
+#         return hours * 60 * 60 + mins * 60 + secs
+#     end
+#
+#     puts secs_to_new_year()
+
+require 'rational'
+require 'date/format'
+
+# Class representing a date.
+#
+# See the documentation to the file date.rb for an overview.
+#
+# Internally, the date is represented as an Astronomical
+# Julian Day Number, +ajd+.  The Day of Calendar Reform, +sg+, is
+# also stored, for conversions to other date formats.  (There
+# is also an +of+ field for a time zone offset, but this
+# is only for the use of the DateTime subclass.)
+#
+# A new Date object is created using one of the object creation
+# class methods named after the corresponding date format, and the
+# arguments appropriate to that date format; for instance,
+# Date::civil() (aliased to Date::new()) with year, month,
+# and day-of-month, or Date::ordinal() with year and day-of-year.
+# All of these object creation class methods also take the
+# Day of Calendar Reform as an optional argument.
+#
+# Date objects are immutable once created.
+#
+# Once a Date has been created, date values
+# can be retrieved for the different date formats supported
+# using instance methods.  For instance, #mon() gives the
+# Civil month, #cwday() gives the Commercial day of the week,
+# and #yday() gives the Ordinal day of the year.  Date values
+# can be retrieved in any format, regardless of what format
+# was used to create the Date instance.
+#
+# The Date class includes the Comparable module, allowing
+# date objects to be compared and sorted, ranges of dates
+# to be created, and so forth.
+class Date
+
+  include Comparable
+
+  # Full month names, in English.  Months count from 1 to 12; a
+  # month's numerical representation indexed into this array
+  # gives the name of that month (hence the first element is nil).
+  MONTHNAMES = [nil] + %w(January February March April May June July
+			  August September October November December)
+
+  # Full names of days of the week, in English.  Days of the week
+  # count from 0 to 6 (except in the commercial week); a day's numerical
+  # representation indexed into this array gives the name of that day.
+  DAYNAMES = %w(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
+
+  # Abbreviated month names, in English.
+  ABBR_MONTHNAMES = [nil] + %w(Jan Feb Mar Apr May Jun
+			       Jul Aug Sep Oct Nov Dec)
+
+  # Abbreviated day names, in English.
+  ABBR_DAYNAMES = %w(Sun Mon Tue Wed Thu Fri Sat)
+
+  [MONTHNAMES, DAYNAMES, ABBR_MONTHNAMES, ABBR_DAYNAMES].each do |xs|
+    xs.each{|x| x.freeze}.freeze
+  end
+
+  class Infinity < Numeric # :nodoc:
+
+    include Comparable
+
+    def initialize(d=1) @d = d <=> 0 end
+
+    def d() @d end
+
+    protected :d
+
+    def zero? () false end
+    def finite? () false end
+    def infinite? () d.nonzero? end
+    def nan? () d.zero? end
+
+    def abs() self.class.new end
+
+    def -@ () self.class.new(-d) end
+    def +@ () self.class.new(+d) end
+
+    def <=> (other)
+      case other
+      when Infinity; d <=> other.d
+      when Numeric; d
+      else
+	begin
+	  l, r = other.coerce(self)
+	  return l <=> r
+	rescue NoMethodError
+	end
+      end
+      nil
+    end
+
+    def coerce(other)
+      case other
+      when Numeric; return -d, d
+      else
+	super
+      end
+    end
+
+  end
+
+  # The Julian Day Number of the Day of Calendar Reform for Italy
+  # and the Catholic countries.
+  ITALY     = 2299161 # 1582-10-15
+
+  # The Julian Day Number of the Day of Calendar Reform for England
+  # and her Colonies.
+  ENGLAND   = 2361222 # 1752-09-14
+
+  # A constant used to indicate that a Date should always use the
+  # Julian calendar.
+  JULIAN    =  Infinity.new
+
+  # A constant used to indicate that a Date should always use the
+  # Gregorian calendar.
+  GREGORIAN = -Infinity.new
+
+  UNIXEPOCH = 2440588 # 1970-01-01 :nodoc:
+
+  # Does a given Julian Day Number fall inside the old-style (Julian)
+  # calendar?
+  #
+  # +jd+ is the Julian Day Number in question. +sg+ may be Date::GREGORIAN,
+  # in which case the answer is false; it may be Date::JULIAN, in which case
+  # the answer is true; or it may a number representing the Day of
+  # Calendar Reform. Date::ENGLAND and Date::ITALY are two possible such
+  # days.
+
+  def self.julian? (jd, sg)
+    case sg
+    when Numeric
+      jd < sg
+    else
+      if $VERBOSE
+	warn("#{caller.shift.sub(/:in .*/, '')}: " \
+"warning: do not use non-numerical object as julian day number anymore")
+      end
+      not sg
+    end
+  end
+
+  # Does a given Julian Day Number fall inside the new-style (Gregorian)
+  # calendar?
+  #
+  # The reverse of self.os?  See the documentation for that method for
+  # more details.
+  def self.gregorian? (jd, sg) !julian?(jd, sg) end
+
+  def self.fix_style(jd, sg) # :nodoc:
+    if julian?(jd, sg)
+    then JULIAN
+    else GREGORIAN end
+  end
+
+  private_class_method :fix_style
+
+  # Convert an Ordinal Date to a Julian Day Number.
+  #
+  # +y+ and +d+ are the year and day-of-year to convert.
+  # +sg+ specifies the Day of Calendar Reform.
+  #
+  # Returns the corresponding Julian Day Number.
+  def self.ordinal_to_jd(y, d, sg=GREGORIAN)
+    civil_to_jd(y, 1, d, sg)
+  end
+
+  # Convert a Julian Day Number to an Ordinal Date.
+  #
+  # +jd+ is the Julian Day Number to convert.
+  # +sg+ specifies the Day of Calendar Reform.
+  #
+  # Returns the corresponding Ordinal Date as
+  # [year, day_of_year]
+  def self.jd_to_ordinal(jd, sg=GREGORIAN)
+    y = jd_to_civil(jd, sg)[0]
+    doy = jd - civil_to_jd(y - 1, 12, 31, fix_style(jd, sg))
+    return y, doy
+  end
+
+  # Convert a Civil Date to a Julian Day Number.
+  # +y+, +m+, and +d+ are the year, month, and day of the
+  # month.  +sg+ specifies the Day of Calendar Reform.
+  #
+  # Returns the corresponding Julian Day Number.
+  def self.civil_to_jd(y, m, d, sg=GREGORIAN)
+    if m <= 2
+      y -= 1
+      m += 12
+    end
+    a = (y / 100.0).floor
+    b = 2 - a + (a / 4.0).floor
+    jd = (365.25 * (y + 4716)).floor +
+      (30.6001 * (m + 1)).floor +
+      d + b - 1524
+    if julian?(jd, sg)
+      jd -= b
+    end
+    jd
+  end
+
+  # Convert a Julian Day Number to a Civil Date.  +jd+ is
+  # the Julian Day Number. +sg+ specifies the Day of
+  # Calendar Reform.
+  #
+  # Returns the corresponding [year, month, day_of_month]
+  # as a three-element array.
+  def self.jd_to_civil(jd, sg=GREGORIAN)
+    if julian?(jd, sg)
+      a = jd
+    else
+      x = ((jd - 1867216.25) / 36524.25).floor
+      a = jd + 1 + x - (x / 4.0).floor
+    end
+    b = a + 1524
+    c = ((b - 122.1) / 365.25).floor
+    d = (365.25 * c).floor
+    e = ((b - d) / 30.6001).floor
+    dom = b - d - (30.6001 * e).floor
+    if e <= 13
+      m = e - 1
+      y = c - 4716
+    else
+      m = e - 13
+      y = c - 4715
+    end
+    return y, m, dom
+  end
+
+  # Convert a Commercial Date to a Julian Day Number.
+  #
+  # +y+, +w+, and +d+ are the (commercial) year, week of the year,
+  # and day of the week of the Commercial Date to convert.
+  # +sg+ specifies the Day of Calendar Reform.
+  def self.commercial_to_jd(y, w, d, ns=GREGORIAN)
+    jd = civil_to_jd(y, 1, 4, ns)
+    (jd - (((jd - 1) + 1) % 7)) +
+      7 * (w - 1) +
+      (d - 1)
+  end
+
+  # Convert a Julian Day Number to a Commercial Date
+  #
+  # +jd+ is the Julian Day Number to convert.
+  # +sg+ specifies the Day of Calendar Reform.
+  #
+  # Returns the corresponding Commercial Date as
+  # [commercial_year, week_of_year, day_of_week]
+  def self.jd_to_commercial(jd, sg=GREGORIAN)
+    ns = fix_style(jd, sg)
+    a = jd_to_civil(jd - 3, ns)[0]
+    y = if jd >= commercial_to_jd(a + 1, 1, 1, ns) then a + 1 else a end
+    w = 1 + ((jd - commercial_to_jd(y, 1, 1, ns)) / 7).floor
+    d = (jd + 1) % 7
+    d = 7 if d == 0
+    return y, w, d
+  end
+
+  def self.weeknum_to_jd(y, w, d, f=0, ns=GREGORIAN) # :nodoc:
+    a = civil_to_jd(y, 1, 1, ns) + 6
+    (a - ((a - f) + 1) % 7 - 7) + 7 * w + d
+  end
+
+  def self.jd_to_weeknum(jd, f=0, sg=GREGORIAN) # :nodoc:
+    ns = fix_style(jd, sg)
+    y, m, d = jd_to_civil(jd, ns)
+    a = civil_to_jd(y, 1, 1, ns) + 6
+    w, d = (jd - (a - ((a - f) + 1) % 7) + 7).divmod(7)
+    return y, w, d
+  end
+
+  private_class_method :weeknum_to_jd, :jd_to_weeknum
+
+  # Convert an Astronomical Julian Day Number to a (civil) Julian
+  # Day Number.
+  #
+  # +ajd+ is the Astronomical Julian Day Number to convert.
+  # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
+  #
+  # Returns the (civil) Julian Day Number as [day_number,
+  # fraction] where +fraction+ is always 1/2.
+  def self.ajd_to_jd(ajd, of=0) (ajd + of + 1.to_r/2).divmod(1) end
+
+  # Convert a (civil) Julian Day Number to an Astronomical Julian
+  # Day Number.
+  #
+  # +jd+ is the Julian Day Number to convert, and +fr+ is a
+  # fractional day.
+  # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
+  #
+  # Returns the Astronomical Julian Day Number as a single
+  # numeric value.
+  def self.jd_to_ajd(jd, fr, of=0) jd + fr - of - 1.to_r/2 end
+
+  # Convert a fractional day +fr+ to [hours, minutes, seconds,
+  # fraction_of_a_second]
+  def self.day_fraction_to_time(fr)
+    h,   fr = fr.divmod(1.to_r/24)
+    min, fr = fr.divmod(1.to_r/1440)
+    s,   fr = fr.divmod(1.to_r/86400)
+    return h, min, s, fr
+  end
+
+  # Convert an +h+ hour, +min+ minutes, +s+ seconds period
+  # to a fractional day.
+  def self.time_to_day_fraction(h, min, s)
+    h.to_r/24 + min.to_r/1440 + s.to_r/86400
+  end
+
+  # Convert an Astronomical Modified Julian Day Number to an
+  # Astronomical Julian Day Number.
+  def self.amjd_to_ajd(amjd) amjd + 4800001.to_r/2 end
+
+  # Convert an Astronomical Julian Day Number to an
+  # Astronomical Modified Julian Day Number.
+  def self.ajd_to_amjd(ajd) ajd - 4800001.to_r/2 end
+
+  # Convert a Modified Julian Day Number to a Julian
+  # Day Number.
+  def self.mjd_to_jd(mjd) mjd + 2400001 end
+
+  # Convert a Julian Day Number to a Modified Julian Day
+  # Number.
+  def self.jd_to_mjd(jd) jd - 2400001 end
+
+  # Convert a count of the number of days since the adoption
+  # of the Gregorian Calendar (in Italy) to a Julian Day Number.
+  def self.ld_to_jd(ld) ld + 2299160 end
+
+  # Convert a Julian Day Number to the number of days since
+  # the adoption of the Gregorian Calendar (in Italy).
+  def self.jd_to_ld(jd) jd - 2299160 end
+
+  # Convert a Julian Day Number to the day of the week.
+  #
+  # Sunday is day-of-week 0; Saturday is day-of-week 6.
+  def self.jd_to_wday(jd) (jd + 1) % 7 end
+
+  # Is a year a leap year in the Julian calendar?
+  #
+  # All years divisible by 4 are leap years in the Julian calendar.
+  def self.julian_leap? (y) y % 4 == 0 end
+
+  # Is a year a leap year in the Gregorian calendar?
+  #
+  # All years divisible by 4 are leap years in the Gregorian calendar,
+  # except for years divisible by 100 and not by 400.
+  def self.gregorian_leap? (y) y % 4 == 0 && y % 100 != 0 || y % 400 == 0 end
+
+  class << self; alias_method :leap?, :gregorian_leap? end
+  class << self; alias_method :new!, :new end
+
+  # Is +jd+ a valid Julian Day Number?
+  #
+  # If it is, returns it.  In fact, any value is treated as a valid
+  # Julian Day Number.
+  def self.valid_jd? (jd, sg=ITALY) jd end
+
+  # Do the year +y+ and day-of-year +d+ make a valid Ordinal Date?
+  # Returns the corresponding Julian Day Number if they do, or
+  # nil if they don't.
+  #
+  # +d+ can be a negative number, in which case it counts backwards
+  # from the end of the year (-1 being the last day of the year).
+  # No year wraparound is performed, however, so valid values of
+  # +d+ are -365 .. -1, 1 .. 365 on a non-leap-year,
+  # -366 .. -1, 1 .. 366 on a leap year.
+  # A date falling in the period skipped in the Day of Calendar Reform
+  # adjustment is not valid.
+  #
+  # +sg+ specifies the Day of Calendar Reform.
+  def self.valid_ordinal? (y, d, sg=ITALY)
+    if d < 0
+      ny, = (y + 1).divmod(1)
+      jd = ordinal_to_jd(ny, d + 1, sg)
+      ns = fix_style(jd, sg)
+      return unless [y] == jd_to_ordinal(jd, sg)[0..0]
+      return unless [ny, 1] == jd_to_ordinal(jd - d, ns)
+    else
+      jd = ordinal_to_jd(y, d, sg)
+      return unless [y, d] == jd_to_ordinal(jd, sg)
+    end
+    jd
+  end
+
+  # Do year +y+, month +m+, and day-of-month +d+ make a
+  # valid Civil Date?  Returns the corresponding Julian
+  # Day Number if they do, nil if they don't.
+  #
+  # +m+ and +d+ can be negative, in which case they count
+  # backwards from the end of the year and the end of the
+  # month respectively.  No wraparound is performed, however,
+  # and invalid values cause an ArgumentError to be raised.
+  # A date falling in the period skipped in the Day of Calendar
+  # Reform adjustment is not valid.
+  #
+  # +sg+ specifies the Day of Calendar Reform.
+  def self.valid_civil? (y, m, d, sg=ITALY)
+    if m < 0
+      m += 13
+    end
+    if d < 0
+      ny, nm = (y * 12 + m).divmod(12)
+      nm,    = (nm + 1).divmod(1)
+      jd = civil_to_jd(ny, nm, d + 1, sg)
+      ns = fix_style(jd, sg)
+      return unless [y, m] == jd_to_civil(jd, sg)[0..1]
+      return unless [ny, nm, 1] == jd_to_civil(jd - d, ns)
+    else
+      jd = civil_to_jd(y, m, d, sg)
+      return unless [y, m, d] == jd_to_civil(jd, sg)
+    end
+    jd
+  end
+
+  class << self; alias_method :valid_date?, :valid_civil? end
+
+  # Do year +y+, week-of-year +w+, and day-of-week +d+ make a
+  # valid Commercial Date?  Returns the corresponding Julian
+  # Day Number if they do, nil if they don't.
+  #
+  # Monday is day-of-week 1; Sunday is day-of-week 7.
+  #
+  # +w+ and +d+ can be negative, in which case they count
+  # backwards from the end of the year and the end of the
+  # week respectively.  No wraparound is performed, however,
+  # and invalid values cause an ArgumentError to be raised.
+  # A date falling in the period skipped in the Day of Calendar
+  # Reform adjustment is not valid.
+  #
+  # +sg+ specifies the Day of Calendar Reform.
+  def self.valid_commercial? (y, w, d, sg=ITALY)
+    if d < 0
+      d += 8
+    end
+    if w < 0
+      ny, nw, nd =
+	jd_to_commercial(commercial_to_jd(y + 1, 1, 1) + w * 7)
+      return unless ny == y
+      w = nw
+    end
+    jd = commercial_to_jd(y, w, d)
+    return unless gregorian?(jd, sg)
+    return unless [y, w, d] == jd_to_commercial(jd)
+    jd
+  end
+
+  def self.valid_weeknum? (y, w, d, f, sg=ITALY) # :nodoc:
+    if d < 0
+      d += 7
+    end
+    if w < 0
+      ny, nw, nd, nf =
+	jd_to_weeknum(weeknum_to_jd(y + 1, 1, f, f) + w * 7, f)
+      return unless ny == y
+      w = nw
+    end
+    jd = weeknum_to_jd(y, w, d, f)
+    return unless gregorian?(jd, sg)
+    return unless [y, w, d] == jd_to_weeknum(jd, f)
+    jd
+  end
+
+  private_class_method :valid_weeknum?
+
+  # Do hour +h+, minute +min+, and second +s+ constitute a valid time?
+  #
+  # If they do, returns their value as a fraction of a day.  If not,
+  # returns nil.
+  #
+  # The 24-hour clock is used.  Negative values of +h+, +min+, and
+  # +sec+ are treating as counting backwards from the end of the
+  # next larger unit (e.g. a +min+ of -2 is treated as 58).  No
+  # wraparound is performed.
+  def self.valid_time? (h, min, s)
+    h   += 24 if h   < 0
+    min += 60 if min < 0
+    s   += 60 if s   < 0
+    return unless ((0..23) === h &&
+		   (0..59) === min &&
+		   (0..59) === s) ||
+		  (24 == h &&
+		    0 == min &&
+		    0 == s)
+    time_to_day_fraction(h, min, s)
+  end
+
+  # Create a new Date object from a Julian Day Number.
+  #
+  # +jd+ is the Julian Day Number; if not specified, it defaults to
+  # 0.
+  # +sg+ specifies the Day of Calendar Reform.
+  def self.jd(jd=0, sg=ITALY)
+    jd = valid_jd?(jd, sg)
+    new!(jd_to_ajd(jd, 0, 0), 0, sg)
+  end
+
+  # Create a new Date object from an Ordinal Date, specified
+  # by year +y+ and day-of-year +d+. +d+ can be negative,
+  # in which it counts backwards from the end of the year.
+  # No year wraparound is performed, however.  An invalid
+  # value for +d+ results in an ArgumentError being raised.
+  #
+  # +y+ defaults to -4712, and +d+ to 1; this is Julian Day
+  # Number day 0.
+  #
+  # +sg+ specifies the Day of Calendar Reform.
+  def self.ordinal(y=-4712, d=1, sg=ITALY)
+    unless jd = valid_ordinal?(y, d, sg)
+      raise ArgumentError, 'invalid date'
+    end
+    new!(jd_to_ajd(jd, 0, 0), 0, sg)
+  end
+
+  # Create a new Date object for the Civil Date specified by
+  # year +y+, month +m+, and day-of-month +d+.
+  #
+  # +m+ and +d+ can be negative, in which case they count
+  # backwards from the end of the year and the end of the
+  # month respectively.  No wraparound is performed, however,
+  # and invalid values cause an ArgumentError to be raised.
+  # can be negative
+  #
+  # +y+ defaults to -4712, +m+ to 1, and +d+ to 1; this is
+  # Julian Day Number day 0.
+  #
+  # +sg+ specifies the Day of Calendar Reform.
+  def self.civil(y=-4712, m=1, d=1, sg=ITALY)
+    unless jd = valid_civil?(y, m, d, sg)
+      raise ArgumentError, 'invalid date'
+    end
+    new!(jd_to_ajd(jd, 0, 0), 0, sg)
+  end
+
+  class << self; alias_method :new, :civil end
+
+  # Create a new Date object for the Commercial Date specified by
+  # year +y+, week-of-year +w+, and day-of-week +d+.
+  #
+  # Monday is day-of-week 1; Sunday is day-of-week 7.
+  #
+  # +w+ and +d+ can be negative, in which case they count
+  # backwards from the end of the year and the end of the
+  # week respectively.  No wraparound is performed, however,
+  # and invalid values cause an ArgumentError to be raised.
+  #
+  # +y+ defaults to 1582, +w+ to 41, and +d+ to 5, the Day of
+  # Calendar Reform for Italy and the Catholic countries.
+  #
+  # +sg+ specifies the Day of Calendar Reform.
+  def self.commercial(y=1582, w=41, d=5, sg=ITALY)
+    unless jd = valid_commercial?(y, w, d, sg)
+      raise ArgumentError, 'invalid date'
+    end
+    new!(jd_to_ajd(jd, 0, 0), 0, sg)
+  end
+
+  def self.weeknum(y=1582, w=41, d=5, f=0, sg=ITALY) # :nodoc:
+    unless jd = valid_weeknum?(y, w, d, f, sg)
+      raise ArgumentError, 'invalid date'
+    end
+    new!(jd_to_ajd(jd, 0, 0), 0, sg)
+  end
+
+  private_class_method :weeknum
+
+  def self.rewrite_frags(elem) # :nodoc:
+    elem ||= {}
+    if seconds = elem[:seconds]
+      d,   fr = seconds.divmod(86400)
+      h,   fr = fr.divmod(3600)
+      min, fr = fr.divmod(60)
+      s,   fr = fr.divmod(1)
+      elem[:jd] = UNIXEPOCH + d
+      elem[:hour] = h
+      elem[:min] = min
+      elem[:sec] = s
+      elem[:sec_fraction] = fr
+      elem.delete(:seconds)
+      elem.delete(:offset)
+    end
+    elem
+  end
+
+  private_class_method :rewrite_frags
+
+  def self.complete_frags(elem) # :nodoc:
+    i = 0
+    g = [[:time, [:hour, :min, :sec]],
+	 [nil, [:jd]],
+	 [:ordinal, [:year, :yday, :hour, :min, :sec]],
+	 [:civil, [:year, :mon, :mday, :hour, :min, :sec]],
+	 [:commercial, [:cwyear, :cweek, :cwday, :hour, :min, :sec]],
+	 [:wday, [:wday, :hour, :min, :sec]],
+	 [:wnum0, [:year, :wnum0, :wday, :hour, :min, :sec]],
+	 [:wnum1, [:year, :wnum1, :wday, :hour, :min, :sec]],
+	 [nil, [:cwyear, :cweek, :wday, :hour, :min, :sec]],
+	 [nil, [:year, :wnum0, :cwday, :hour, :min, :sec]],
+	 [nil, [:year, :wnum1, :cwday, :hour, :min, :sec]]].
+      collect{|k, a| e = elem.values_at(*a).compact; [k, a, e]}.
+      select{|k, a, e| e.size > 0}.
+      sort_by{|k, a, e| [e.size, i -= 1]}.last
+
+    d = nil
+
+    if g && g[0] && (g[1].size - g[2].size) != 0
+      d ||= Date.today
+
+      case g[0]
+      when :ordinal
+	elem[:year] ||= d.year
+	elem[:yday] ||= 1
+      when :civil
+	g[1].each do |e|
+	  break if elem[e]
+	  elem[e] = d.__send__(e)
+	end
+	elem[:mon]  ||= 1
+	elem[:mday] ||= 1
+      when :commercial
+	g[1].each do |e|
+	  break if elem[e]
+	  elem[e] = d.__send__(e)
+	end
+	elem[:cweek] ||= 1
+	elem[:cwday] ||= 1
+      when :wday
+	elem[:jd] ||= (d - d.wday + elem[:wday]).jd
+      when :wnum0
+	g[1].each do |e|
+	  break if elem[e]
+	  elem[e] = d.__send__(e)
+	end
+	elem[:wnum0] ||= 0
+	elem[:wday]  ||= 0
+      when :wnum1
+	g[1].each do |e|
+	  break if elem[e]
+	  elem[e] = d.__send__(e)
+	end
+	elem[:wnum1] ||= 0
+	elem[:wday]  ||= 0
+      end
+    end
+
+    if g && g[0] == :time
+      if self <= DateTime
+	d ||= Date.today
+	elem[:jd] ||= d.jd
+      end
+    end
+
+    elem[:hour] ||= 0
+    elem[:min]  ||= 0
+    elem[:sec]  ||= 0
+    elem[:sec] = [elem[:sec], 59].min
+
+    elem
+  end
+
+  private_class_method :complete_frags
+
+  def self.valid_date_frags?(elem, sg) # :nodoc:
+    catch :jd do
+      a = elem.values_at(:jd)
+      if a.all?
+	if jd = valid_jd?(*(a << sg))
+	  throw :jd, jd
+	end
+      end
+
+      a = elem.values_at(:year, :yday)
+      if a.all?
+	if jd = valid_ordinal?(*(a << sg))
+	  throw :jd, jd
+	end
+      end
+
+      a = elem.values_at(:year, :mon, :mday)
+      if a.all?
+	if jd = valid_civil?(*(a << sg))
+	  throw :jd, jd
+	end
+      end
+
+      a = elem.values_at(:cwyear, :cweek, :cwday)
+      if a[2].nil? && elem[:wday]
+	a[2] = elem[:wday].nonzero? || 7
+      end
+      if a.all?
+	if jd = valid_commercial?(*(a << sg))
+	  throw :jd, jd
+	end
+      end
+
+      a = elem.values_at(:year, :wnum0, :wday)
+      if a[2].nil? && elem[:cwday]
+	a[2] = elem[:cwday] % 7
+      end
+      if a.all?
+	if jd = valid_weeknum?(*(a << 0 << sg))
+	  throw :jd, jd
+	end
+      end
+
+      a = elem.values_at(:year, :wnum1, :wday)
+      if a[2]
+	a[2] = (a[2] - 1) % 7
+      end
+      if a[2].nil? && elem[:cwday]
+	a[2] = (elem[:cwday] - 1) % 7
+      end
+      if a.all?
+	if jd = valid_weeknum?(*(a << 1 << sg))
+	  throw :jd, jd
+	end
+      end
+    end
+  end
+
+  private_class_method :valid_date_frags?
+
+  def self.valid_time_frags? (elem) # :nodoc:
+    h, min, s = elem.values_at(:hour, :min, :sec)
+    valid_time?(h, min, s)
+  end
+
+  private_class_method :valid_time_frags?
+
+  def self.new_by_frags(elem, sg) # :nodoc:
+    elem = rewrite_frags(elem)
+    elem = complete_frags(elem)
+    unless jd = valid_date_frags?(elem, sg)
+      raise ArgumentError, 'invalid date'
+    end
+    new!(jd_to_ajd(jd, 0, 0), 0, sg)
+  end
+
+  private_class_method :new_by_frags
+
+  # Create a new Date object by parsing from a String
+  # according to a specified format.
+  #
+  # +str+ is a String holding a date representation.
+  # +fmt+ is the format that the date is in.  See
+  # date/format.rb for details on supported formats.
+  #
+  # The default +str+ is '-4712-01-01', and the default
+  # +fmt+ is '%F', which means Year-Month-Day_of_Month.
+  # This gives Julian Day Number day 0.
+  #
+  # +sg+ specifies the Day of Calendar Reform.
+  #
+  # An ArgumentError will be raised if +str+ cannot be
+  # parsed.
+  def self.strptime(str='-4712-01-01', fmt='%F', sg=ITALY)
+    elem = _strptime(str, fmt)
+    new_by_frags(elem, sg)
+  end
+
+  # Create a new Date object by parsing from a String,
+  # without specifying the format.
+  #
+  # +str+ is a String holding a date representation.
+  # +comp+ specifies whether to interpret 2-digit years
+  # as 19XX (>= 69) or 20XX (< 69); the default is not to.
+  # The method will attempt to parse a date from the String
+  # using various heuristics; see #_parse in date/format.rb
+  # for more details.  If parsing fails, an ArgumentError
+  # will be raised.
+  #
+  # The default +str+ is '-4712-01-01'; this is Julian
+  # Day Number day 0.
+  #
+  # +sg+ specifies the Day of Calendar Reform.
+  def self.parse(str='-4712-01-01', comp=false, sg=ITALY)
+    elem = _parse(str, comp)
+    new_by_frags(elem, sg)
+  end
+
+  class << self
+
+    def once(*ids) # :nodoc:
+      for id in ids
+	module_eval <<-"end;"
+	  alias_method :__#{id.to_i}__, :#{id.to_s}
+	  private :__#{id.to_i}__
+	  def #{id.to_s}(*args, &block)
+	    (@__#{id.to_i}__ ||= [__#{id.to_i}__(*args, &block)])[0]
+	  end
+	end;
+      end
+    end
+
+    private :once
+
+  end
+
+  # *NOTE* this is the documentation for the method new!().  If
+  # you are reading this as the documentation for new(), that is
+  # because rdoc doesn't fully support the aliasing of the
+  # initialize() method.
+  # new() is in
+  # fact an alias for #civil(): read the documentation for that
+  # method instead.
+  #
+  # Create a new Date object.
+  #
+  # +ajd+ is the Astronomical Julian Day Number.
+  # +of+ is the offset from UTC as a fraction of a day.
+  # Both default to 0.
+  #
+  # +sg+ specifies the Day of Calendar Reform to use for this
+  # Date object.
+  #
+  # Using one of the factory methods such as Date::civil is
+  # generally easier and safer.
+  def initialize(ajd=0, of=0, sg=ITALY) @ajd, @of, @sg = ajd, of, sg end
+
+  # Get the date as an Astronomical Julian Day Number.
+  def ajd() @ajd end
+
+  # Get the date as an Astronomical Modified Julian Day Number.
+  def amjd() self.class.ajd_to_amjd(@ajd) end
+
+  once :amjd
+
+  # Get the date as a Julian Day Number.
+  def jd() self.class.ajd_to_jd(@ajd, @of)[0] end
+
+  # Get any fractional day part of the date.
+  def day_fraction() self.class.ajd_to_jd(@ajd, @of)[1] end
+
+  # Get the date as a Modified Julian Day Number.
+  def mjd() self.class.jd_to_mjd(jd) end
+
+  # Get the date as the number of days since the Day of Calendar
+  # Reform (in Italy and the Catholic countries).
+  def ld() self.class.jd_to_ld(jd) end
+
+  once :jd, :day_fraction, :mjd, :ld
+
+  # Get the date as a Civil Date, [year, month, day_of_month]
+  def civil() self.class.jd_to_civil(jd, @sg) end # :nodoc:
+
+  # Get the date as an Ordinal Date, [year, day_of_year]
+  def ordinal() self.class.jd_to_ordinal(jd, @sg) end # :nodoc:
+
+  # Get the date as a Commercial Date, [year, week_of_year, day_of_week]
+  def commercial() self.class.jd_to_commercial(jd, @sg) end # :nodoc:
+
+  def weeknum0() self.class.__send__(:jd_to_weeknum, jd, 0, @sg) end # :nodoc:
+  def weeknum1() self.class.__send__(:jd_to_weeknum, jd, 1, @sg) end # :nodoc:
+
+  once :civil, :ordinal, :commercial, :weeknum0, :weeknum1
+  private :civil, :ordinal, :commercial, :weeknum0, :weeknum1
+
+  # Get the year of this date.
+  def year() civil[0] end
+
+  # Get the day-of-the-year of this date.
+  #
+  # January 1 is day-of-the-year 1
+  def yday() ordinal[1] end
+
+  # Get the month of this date.
+  #
+  # January is month 1.
+  def mon() civil[1] end
+
+  # Get the day-of-the-month of this date.
+  def mday() civil[2] end
+
+  alias_method :month, :mon
+  alias_method :day, :mday
+
+  def wnum0() weeknum0[1] end # :nodoc:
+  def wnum1() weeknum1[1] end # :nodoc:
+
+  private :wnum0, :wnum1
+
+  # Get the time of this date as [hours, minutes, seconds,
+  # fraction_of_a_second]
+  def time() self.class.day_fraction_to_time(day_fraction) end # :nodoc:
+
+  once :time
+  private :time
+
+  # Get the hour of this date.
+  def hour() time[0] end
+
+  # Get the minute of this date.
+  def min() time[1] end
+
+  # Get the second of this date.
+  def sec() time[2] end
+
+  # Get the fraction-of-a-second of this date.  The unit is in days.
+  # I do NOT recommend you to use this method.
+  def sec_fraction() time[3] end
+
+  private :hour, :min, :sec, :sec_fraction
+
+  def zone() strftime('%:z') end
+
+  private :zone
+
+  # Get the commercial year of this date.  See *Commercial* *Date*
+  # in the introduction for how this differs from the normal year.
+  def cwyear() commercial[0] end
+
+  # Get the commercial week of the year of this date.
+  def cweek() commercial[1] end
+
+  # Get the commercial day of the week of this date.  Monday is
+  # commercial day-of-week 1; Sunday is commercial day-of-week 7.
+  def cwday() commercial[2] end
+
+  # Get the week day of this date.  Sunday is day-of-week 0;
+  # Saturday is day-of-week 6.
+  def wday() self.class.jd_to_wday(jd) end
+
+  once :wday
+
+=begin
+  MONTHNAMES.each_with_index do |n, i|
+    if n
+      define_method(n.downcase + '?'){mon == i}
+    end
+  end
+
+  DAYNAMES.each_with_index do |n, i|
+    define_method(n.downcase + '?'){wday == i}
+  end
+=end
+
+  # Is the current date old-style (Julian Calendar)?
+  def julian? () self.class.julian?(jd, @sg) end
+
+  # Is the current date new-style (Gregorian Calendar)?
+  def gregorian? () self.class.gregorian?(jd, @sg) end
+
+  once :julian?, :gregorian?
+
+  def fix_style # :nodoc:
+    if julian?
+    then self.class::JULIAN
+    else self.class::GREGORIAN end
+  end
+
+  private :fix_style
+
+  # Is this a leap year?
+  def leap?
+    self.class.jd_to_civil(self.class.civil_to_jd(year, 3, 1, fix_style) - 1,
+		     fix_style)[-1] == 29
+  end
+
+  once :leap?
+
+  # When is the Day of Calendar Reform for this Date object?
+  def start() @sg end
+
+  # Create a copy of this Date object using a new Day of Calendar Reform.
+  def new_start(sg=self.class::ITALY) self.class.new!(@ajd, @of, sg) end
+
+  # Create a copy of this Date object that uses the Italian/Catholic
+  # Day of Calendar Reform.
+  def italy() new_start(self.class::ITALY) end
+
+  # Create a copy of this Date object that uses the English/Colonial
+  # Day of Calendar Reform.
+  def england() new_start(self.class::ENGLAND) end
+
+  # Create a copy of this Date object that always uses the Julian
+  # Calendar.
+  def julian() new_start(self.class::JULIAN) end
+
+  # Create a copy of this Date object that always uses the Gregorian
+  # Calendar.
+  def gregorian() new_start(self.class::GREGORIAN) end
+
+  def offset() @of end
+
+  def new_offset(of=0)
+    if String === of
+      of = (self.class.zone_to_diff(of) || 0).to_r/86400
+    end
+    self.class.new!(@ajd, of, @sg)
+  end
+
+  private :offset, :new_offset
+
+  # Return a new Date object that is +n+ days later than the
+  # current one.
+  #
+  # +n+ may be a negative value, in which case the new Date
+  # is earlier than the current one; however, #-() might be
+  # more intuitive.
+  #
+  # If +n+ is not a Numeric, a TypeError will be thrown.  In
+  # particular, two Dates cannot be added to each other.
+  def + (n)
+    case n
+    when Numeric; return self.class.new!(@ajd + n, @of, @sg)
+    end
+    raise TypeError, 'expected numeric'
+  end
+
+  # If +x+ is a Numeric value, create a new Date object that is
+  # +x+ days earlier than the current one.
+  #
+  # If +x+ is a Date, return the number of days between the
+  # two dates; or, more precisely, how many days later the current
+  # date is than +x+.
+  #
+  # If +x+ is neither Numeric nor a Date, a TypeError is raised.
+  def - (x)
+    case x
+    when Numeric; return self.class.new!(@ajd - x, @of, @sg)
+    when Date;    return @ajd - x.ajd
+    end
+    raise TypeError, 'expected numeric or date'
+  end
+
+  # Compare this date with another date.
+  #
+  # +other+ can also be a Numeric value, in which case it is
+  # interpreted as an Astronomical Julian Day Number.
+  #
+  # Comparison is by Astronomical Julian Day Number, including
+  # fractional days.  This means that both the time and the
+  # timezone offset are taken into account when comparing
+  # two DateTime instances.  When comparing a DateTime instance
+  # with a Date instance, the time of the latter will be
+  # considered as falling on midnight UTC.
+  def <=> (other)
+    case other
+    when Numeric; return @ajd <=> other
+    when Date;    return @ajd <=> other.ajd
+    end
+    nil
+  end
+
+  # The relationship operator for Date.
+  #
+  # Compares dates by Julian Day Number.  When comparing
+  # two DateTime instances, or a DateTime with a Date,
+  # the instances will be regarded as equivalent if they
+  # fall on the same date in local time.
+  def === (other)
+    case other
+    when Numeric; return jd == other
+    when Date;    return jd == other.jd
+    end
+    false
+  end
+
+  def next_day(n=1) self + n end
+# def prev_day(n=1) self - n end
+
+  private :next_day
+
+  # Return a new Date one day after this one.
+  def next() next_day end
+
+  alias_method :succ, :next
+
+  # Return a new Date object that is +n+ months later than
+  # the current one.
+  #
+  # If the day-of-the-month of the current Date is greater
+  # than the last day of the target month, the day-of-the-month
+  # of the returned Date will be the last day of the target month.
+  def >> (n)
+    y, m = (year * 12 + (mon - 1) + n).divmod(12)
+    m,   = (m + 1)                    .divmod(1)
+    d = mday
+    d -= 1 until jd2 = self.class.valid_civil?(y, m, d, fix_style)
+    self + (jd2 - jd)
+  end
+
+  # Return a new Date object that is +n+ months earlier than
+  # the current one.
+  #
+  # If the day-of-the-month of the current Date is greater
+  # than the last day of the target month, the day-of-the-month
+  # of the returned Date will be the last day of the target month.
+  def << (n) self >> -n end
+
+=begin
+  def next_month(n=1) self >> n end
+  def prev_month(n=1) self << n end
+
+  def next_year(n=1) self >> n * 12 end
+  def prev_year(n=1) self << n * 12 end
+=end
+
+#  require 'enumerator'
+
+  # Step the current date forward +step+ days at a
+  # time (or backward, if +step+ is negative) until
+  # we reach +limit+ (inclusive), yielding the resultant
+  # date at each step.
+  def step(limit, step=1) # :yield: date
+=begin
+    unless block_given?
+      return to_enum(:step, limit, step)
+    end
+=end
+    da = self
+    op = %w(- <= >=)[step <=> 0]
+    while da.__send__(op, limit)
+      yield da
+      da += step
+    end
+    self
+  end
+
+  # Step forward one day at a time until we reach +max+
+  # (inclusive), yielding each date as we go.
+  def upto(max, &block) # :yield: date
+    step(max, +1, &block)
+  end
+
+  # Step backward one day at a time until we reach +min+
+  # (inclusive), yielding each date as we go.
+  def downto(min, &block) # :yield: date
+    step(min, -1, &block)
+  end
+
+  # Is this Date equal to +other+?
+  #
+  # +other+ must both be a Date object, and represent the same date.
+  def eql? (other) Date === other && self == other end
+
+  # Calculate a hash value for this date.
+  def hash() @ajd.hash end
+
+  # Return internal object state as a programmer-readable string.
+  def inspect() format('#<%s: %s,%s,%s>', self.class, @ajd, @of, @sg) end
+
+  # Return the date as a human-readable string.
+  #
+  # The format used is YYYY-MM-DD.
+  def to_s() strftime end
+
+  # Dump to Marshal format.
+  def _dump(limit) Marshal.dump([@ajd, @of, @sg], -1) end
+
+# def self._load(str) new!(*Marshal.load(str)) end
+
+  # Load from Marshall format.
+  def self._load(str)
+    a = Marshal.load(str)
+    if a.size == 2
+      ajd,     sg = a
+           of = 0
+      ajd -= 1.to_r/2
+    else
+      ajd, of, sg = a
+    end
+    new!(ajd, of, sg)
+  end
+
+end
+
+# Class representing a date and time.
+#
+# See the documentation to the file date.rb for an overview.
+#
+# DateTime objects are immutable once created.
+#
+# == Other methods.
+#
+# The following methods are defined in Date, but declared private
+# there.  They are made public in DateTime.  They are documented
+# here.
+#
+# === hour()
+#
+# Get the hour-of-the-day of the time.  This is given
+# using the 24-hour clock, counting from midnight.  The first
+# hour after midnight is hour 0; the last hour of the day is
+# hour 23.
+#
+# === min()
+#
+# Get the minute-of-the-hour of the time.
+#
+# === sec()
+#
+# Get the second-of-the-minute of the time.
+#
+# === sec_fraction()
+#
+# Get the fraction of a second of the time.  This is returned as
+# a +Rational+.  The unit is in days.
+# I do NOT recommend you to use this method.
+#
+# === zone()
+#
+# Get the time zone as a String.  This is representation of the
+# time offset such as "+1000", not the true time-zone name.
+#
+# === offset()
+#
+# Get the time zone offset as a fraction of a day.  This is returned
+# as a +Rational+.
+#
+# === new_offset(of=0)
+#
+# Create a new DateTime object, identical to the current one, except
+# with a new time zone offset of +of+.  +of+ is the new offset from
+# UTC as a fraction of a day.
+#
+class DateTime < Date
+
+  # Create a new DateTime object corresponding to the specified
+  # Julian Day Number +jd+ and hour +h+, minute +min+, second +s+.
+  #
+  # The 24-hour clock is used.  Negative values of +h+, +min+, and
+  # +sec+ are treating as counting backwards from the end of the
+  # next larger unit (e.g. a +min+ of -2 is treated as 58).  No
+  # wraparound is performed.  If an invalid time portion is specified,
+  # an ArgumentError is raised.
+  #
+  # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
+  # +sg+ specifies the Day of Calendar Reform.
+  #
+  # All day/time values default to 0.
+  def self.jd(jd=0, h=0, min=0, s=0, of=0, sg=ITALY)
+    unless (jd = valid_jd?(jd, sg)) &&
+	   (fr = valid_time?(h, min, s))
+      raise ArgumentError, 'invalid date'
+    end
+    if String === of
+      of = (zone_to_diff(of) || 0).to_r/86400
+    end
+    new!(jd_to_ajd(jd, fr, of), of, sg)
+  end
+
+  # Create a new DateTime object corresponding to the specified
+  # Ordinal Date and hour +h+, minute +min+, second +s+.
+  #
+  # The 24-hour clock is used.  Negative values of +h+, +min+, and
+  # +sec+ are treating as counting backwards from the end of the
+  # next larger unit (e.g. a +min+ of -2 is treated as 58).  No
+  # wraparound is performed.  If an invalid time portion is specified,
+  # an ArgumentError is raised.
+  #
+  # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
+  # +sg+ specifies the Day of Calendar Reform.
+  #
+  # +y+ defaults to -4712, and +d+ to 1; this is Julian Day Number
+  # day 0.  The time values default to 0.
+  def self.ordinal(y=-4712, d=1, h=0, min=0, s=0, of=0, sg=ITALY)
+    unless (jd = valid_ordinal?(y, d, sg)) &&
+	   (fr = valid_time?(h, min, s))
+      raise ArgumentError, 'invalid date'
+    end
+    if String === of
+      of = (zone_to_diff(of) || 0).to_r/86400
+    end
+    new!(jd_to_ajd(jd, fr, of), of, sg)
+  end
+
+  # Create a new DateTime object corresponding to the specified
+  # Civil Date and hour +h+, minute +min+, second +s+.
+  #
+  # The 24-hour clock is used.  Negative values of +h+, +min+, and
+  # +sec+ are treating as counting backwards from the end of the
+  # next larger unit (e.g. a +min+ of -2 is treated as 58).  No
+  # wraparound is performed.  If an invalid time portion is specified,
+  # an ArgumentError is raised.
+  #
+  # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
+  # +sg+ specifies the Day of Calendar Reform.
+  #
+  # +y+ defaults to -4712, +m+ to 1, and +d+ to 1; this is Julian Day
+  # Number day 0.  The time values default to 0.
+  def self.civil(y=-4712, m=1, d=1, h=0, min=0, s=0, of=0, sg=ITALY)
+    unless (jd = valid_civil?(y, m, d, sg)) &&
+	   (fr = valid_time?(h, min, s))
+      raise ArgumentError, 'invalid date'
+    end
+    if String === of
+      of = (zone_to_diff(of) || 0).to_r/86400
+    end
+    new!(jd_to_ajd(jd, fr, of), of, sg)
+  end
+
+  class << self; alias_method :new, :civil end
+
+  # Create a new DateTime object corresponding to the specified
+  # Commercial Date and hour +h+, minute +min+, second +s+.
+  #
+  # The 24-hour clock is used.  Negative values of +h+, +min+, and
+  # +sec+ are treating as counting backwards from the end of the
+  # next larger unit (e.g. a +min+ of -2 is treated as 58).  No
+  # wraparound is performed.  If an invalid time portion is specified,
+  # an ArgumentError is raised.
+  #
+  # +of+ is the offset from UTC as a fraction of a day (defaults to 0).
+  # +sg+ specifies the Day of Calendar Reform.
+  #
+  # +y+ defaults to 1582, +w+ to 41, and +d+ to 5; this is the Day of
+  # Calendar Reform for Italy and the Catholic countries.
+  # The time values default to 0.
+  def self.commercial(y=1582, w=41, d=5, h=0, min=0, s=0, of=0, sg=ITALY)
+    unless (jd = valid_commercial?(y, w, d, sg)) &&
+	   (fr = valid_time?(h, min, s))
+      raise ArgumentError, 'invalid date'
+    end
+    if String === of
+      of = (zone_to_diff(of) || 0).to_r/86400
+    end
+    new!(jd_to_ajd(jd, fr, of), of, sg)
+  end
+
+  def self.weeknum(y=1582, w=41, d=5, f=0, h=0, min=0, s=0, of=0, sg=ITALY) # :nodoc:
+    unless (jd = valid_weeknum?(y, w, d, f, sg)) &&
+	   (fr = valid_time?(h, min, s))
+      raise ArgumentError, 'invalid date'
+    end
+    if String === of
+      of = (zone_to_diff(of) || 0).to_r/86400
+    end
+    new!(jd_to_ajd(jd, fr, of), of, sg)
+  end
+
+  private_class_method :weeknum
+
+  def self.new_by_frags(elem, sg) # :nodoc:
+    elem = rewrite_frags(elem)
+    elem = complete_frags(elem)
+    unless (jd = valid_date_frags?(elem, sg)) &&
+	   (fr = valid_time_frags?(elem))
+      raise ArgumentError, 'invalid date'
+    end
+    sf = (elem[:sec_fraction] || 0)
+    fr += sf/86400
+    of = (elem[:offset] || 0)
+    of = of.to_r/86400
+    new!(jd_to_ajd(jd, fr, of), of, sg)
+  end
+
+  private_class_method :new_by_frags
+
+  # Create a new DateTime object by parsing from a String
+  # according to a specified format.
+  #
+  # +str+ is a String holding a date-time representation.
+  # +fmt+ is the format that the date-time is in.  See
+  # date/format.rb for details on supported formats.
+  #
+  # The default +str+ is '-4712-01-01T00:00:00+00:00', and the default
+  # +fmt+ is '%FT%T%z'.  This gives midnight on Julian Day Number day 0.
+  #
+  # +sg+ specifies the Day of Calendar Reform.
+  #
+  # An ArgumentError will be raised if +str+ cannot be
+  # parsed.
+  def self.strptime(str='-4712-01-01T00:00:00+00:00', fmt='%FT%T%z', sg=ITALY)
+    elem = _strptime(str, fmt)
+    new_by_frags(elem, sg)
+  end
+
+  # Create a new DateTime object by parsing from a String,
+  # without specifying the format.
+  #
+  # +str+ is a String holding a date-time representation.
+  # +comp+ specifies whether to interpret 2-digit years
+  # as 19XX (>= 69) or 20XX (< 69); the default is not to.
+  # The method will attempt to parse a date-time from the String
+  # using various heuristics; see #_parse in date/format.rb
+  # for more details.  If parsing fails, an ArgumentError
+  # will be raised.
+  #
+  # The default +str+ is '-4712-01-01T00:00:00+00:00'; this is Julian
+  # Day Number day 0.
+  #
+  # +sg+ specifies the Day of Calendar Reform.
+  def self.parse(str='-4712-01-01T00:00:00+00:00', comp=false, sg=ITALY)
+    elem = _parse(str, comp)
+    new_by_frags(elem, sg)
+  end
+
+  public :hour, :min, :sec, :sec_fraction, :zone, :offset, :new_offset
+
+end
+
+class Time
+
+#  def to_time() getlocal end
+
+  def to_date
+    jd = Date.civil_to_jd(year, mon, mday, Date::ITALY)
+    Date.new!(Date.jd_to_ajd(jd, 0, 0), 0, Date::ITALY)
+  end
+
+  def to_datetime
+    jd = DateTime.civil_to_jd(year, mon, mday, DateTime::ITALY)
+    fr = DateTime.time_to_day_fraction(hour, min, [sec, 59].min) +
+	 usec.to_r/86400000000
+    of = utc_offset.to_r/86400
+    DateTime.new!(DateTime.jd_to_ajd(jd, fr, of), of, DateTime::ITALY)
+  end
+
+  private :to_date, :to_datetime
+
+end
+
+class Date
+
+=begin
+  def to_time() Time.local(year, mon, mday) end
+  def to_date() self end
+  def to_datetime() DateTime.new!(self.class.jd_to_ajd(jd, 0, 0), @of, @sg) end
+=end
+
+  # Create a new Date object representing today.
+  #
+  # +sg+ specifies the Day of Calendar Reform.
+  def self.today(sg=ITALY) Time.now.__send__(:to_date)    .new_start(sg) end
+
+  # Create a new DateTime object representing the current time.
+  #
+  # +sg+ specifies the Day of Calendar Reform.
+  def self.now  (sg=ITALY) Time.now.__send__(:to_datetime).new_start(sg) end
+
+  private_class_method :now
+
+end
+
+class DateTime < Date
+
+=begin
+  def to_time
+    d = new_offset(0)
+    d.instance_eval do
+      Time.utc(year, mon, mday, hour, min, sec,
+	       (sec_fraction * 86400000000).to_i)
+    end.
+	getlocal
+  end
+
+  def to_date() Date.new!(self.class.jd_to_ajd(jd, 0, 0), 0, @sg) end
+  def to_datetime() self end
+=end
+
+  private_class_method :today
+  public_class_method  :now
+
+end
+
+class Date
+
+  [ %w(os?	julian?),
+    %w(ns?	gregorian?),
+    %w(exist1?	valid_jd?),
+    %w(exist2?	valid_ordinal?),
+    %w(exist3?	valid_date?),
+    %w(exist?	valid_date?),
+    %w(existw?	valid_commercial?),
+    %w(new0	new!),
+    %w(new1	jd),
+    %w(new2	ordinal),
+    %w(new3	new),
+    %w(neww	commercial)
+  ].each do |old, new|
+    module_eval <<-"end;"
+      def self.#{old}(*args, &block)
+	if $VERBOSE
+	  warn("\#{caller.shift.sub(/:in .*/, '')}: " \
+	       "warning: \#{self}::#{old} is deprecated; " \
+	       "use \#{self}::#{new}")
+	end
+	#{new}(*args, &block)
+      end
+    end;
+  end
+
+  [ %w(os?	julian?),
+    %w(ns?	gregorian?),
+    %w(sg	start),
+    %w(newsg	new_start),
+    %w(of	offset),
+    %w(newof	new_offset)
+  ].each do |old, new|
+    module_eval <<-"end;"
+      def #{old}(*args, &block)
+	if $VERBOSE
+	  warn("\#{caller.shift.sub(/:in .*/, '')}: " \
+	       "warning: \#{self.class}\##{old} is deprecated; " \
+	       "use \#{self.class}\##{new}")
+	end
+	#{new}(*args, &block)
+      end
+    end;
+  end
+
+  private :of, :newof
+
+end
+
+class DateTime < Date
+
+  public :of, :newof
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/date/format.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/date/format.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/date/format.rb	(revision 18425)
@@ -0,0 +1,1088 @@
+# format.rb: Written by Tadayoshi Funaba 1999-2007
+# $Id: format.rb,v 2.30 2007-01-07 09:16:24+09 tadf Exp $
+
+require 'rational'
+
+class Date
+
+  module Format # :nodoc:
+
+    MONTHS = {
+      'january'  => 1, 'february' => 2, 'march'    => 3, 'april'    => 4,
+      'may'      => 5, 'june'     => 6, 'july'     => 7, 'august'   => 8,
+      'september'=> 9, 'october'  =>10, 'november' =>11, 'december' =>12
+    }
+
+    DAYS = {
+      'sunday'   => 0, 'monday'   => 1, 'tuesday'  => 2, 'wednesday'=> 3,
+      'thursday' => 4, 'friday'   => 5, 'saturday' => 6
+    }
+
+    ABBR_MONTHS = {
+      'jan'      => 1, 'feb'      => 2, 'mar'      => 3, 'apr'      => 4,
+      'may'      => 5, 'jun'      => 6, 'jul'      => 7, 'aug'      => 8,
+      'sep'      => 9, 'oct'      =>10, 'nov'      =>11, 'dec'      =>12
+    }
+
+    ABBR_DAYS = {
+      'sun'      => 0, 'mon'      => 1, 'tue'      => 2, 'wed'      => 3,
+      'thu'      => 4, 'fri'      => 5, 'sat'      => 6
+    }
+
+    ZONES = {
+      'ut'  =>  0*3600, 'gmt' =>  0*3600, 'est' => -5*3600, 'edt' => -4*3600,
+      'cst' => -6*3600, 'cdt' => -5*3600, 'mst' => -7*3600, 'mdt' => -6*3600,
+      'pst' => -8*3600, 'pdt' => -7*3600,
+      'a'   =>  1*3600, 'b'   =>  2*3600, 'c'   =>  3*3600, 'd'   =>  4*3600,
+      'e'   =>  5*3600, 'f'   =>  6*3600, 'g'   =>  7*3600, 'h'   =>  8*3600,
+      'i'   =>  9*3600, 'k'   => 10*3600, 'l'   => 11*3600, 'm'   => 12*3600,
+      'n'   => -1*3600, 'o'   => -2*3600, 'p'   => -3*3600, 'q'   => -4*3600,
+      'r'   => -5*3600, 's'   => -6*3600, 't'   => -7*3600, 'u'   => -8*3600,
+      'v'   => -9*3600, 'w'   =>-10*3600, 'x'   =>-11*3600, 'y'   =>-12*3600,
+      'z'   =>  0*3600,
+      'utc' =>  0*3600, 'wet' =>  0*3600, 'bst' =>  1*3600, 'wat' => -1*3600,
+      'at'  => -2*3600, 'ast' => -4*3600, 'adt' => -3*3600, 'yst' => -9*3600,
+      'ydt' => -8*3600, 'hst' =>-10*3600, 'hdt' => -9*3600, 'cat' =>-10*3600,
+      'ahst'=>-10*3600, 'nt'  =>-11*3600, 'idlw'=>-12*3600, 'cet' =>  1*3600,
+      'met' =>  1*3600, 'mewt'=>  1*3600, 'mest'=>  2*3600, 'mesz'=>  2*3600,
+      'swt' =>  1*3600, 'sst' =>  2*3600, 'fwt' =>  1*3600, 'fst' =>  2*3600,
+      'eet' =>  2*3600, 'bt'  =>  3*3600, 'zp4' =>  4*3600, 'zp5' =>  5*3600,
+      'zp6' =>  6*3600, 'wast'=>  7*3600, 'wadt'=>  8*3600, 'cct' =>  8*3600,
+      'jst' =>  9*3600, 'east'=> 10*3600, 'eadt'=> 11*3600, 'gst' => 10*3600,
+      'nzt' => 12*3600, 'nzst'=> 12*3600, 'nzdt'=> 13*3600, 'idle'=> 12*3600,
+
+      'afghanistan'           =>   16200, 'alaskan'               =>  -32400,
+      'arab'                  =>   10800, 'arabian'               =>   14400,
+      'arabic'                =>   10800, 'atlantic'              =>  -14400,
+      'aus central'           =>   34200, 'aus eastern'           =>   36000,
+      'azores'                =>   -3600, 'canada central'        =>  -21600,
+      'cape verde'            =>   -3600, 'caucasus'              =>   14400,
+      'cen. australia'        =>   34200, 'central america'       =>  -21600,
+      'central asia'          =>   21600, 'central europe'        =>    3600,
+      'central european'      =>    3600, 'central pacific'       =>   39600,
+      'central'               =>  -21600, 'china'                 =>   28800,
+      'dateline'              =>  -43200, 'e. africa'             =>   10800,
+      'e. australia'          =>   36000, 'e. europe'             =>    7200,
+      'e. south america'      =>  -10800, 'eastern'               =>  -18000,
+      'egypt'                 =>    7200, 'ekaterinburg'          =>   18000,
+      'fiji'                  =>   43200, 'fle'                   =>    7200,
+      'greenland'             =>  -10800, 'greenwich'             =>       0,
+      'gtb'                   =>    7200, 'hawaiian'              =>  -36000,
+      'india'                 =>   19800, 'iran'                  =>   12600,
+      'jerusalem'             =>    7200, 'korea'                 =>   32400,
+      'mexico'                =>  -21600, 'mid-atlantic'          =>   -7200,
+      'mountain'              =>  -25200, 'myanmar'               =>   23400,
+      'n. central asia'       =>   21600, 'nepal'                 =>   20700,
+      'new zealand'           =>   43200, 'newfoundland'          =>  -12600,
+      'north asia east'       =>   28800, 'north asia'            =>   25200,
+      'pacific sa'            =>  -14400, 'pacific'               =>  -28800,
+      'romance'               =>    3600, 'russian'               =>   10800,
+      'sa eastern'            =>  -10800, 'sa pacific'            =>  -18000,
+      'sa western'            =>  -14400, 'samoa'                 =>  -39600,
+      'se asia'               =>   25200, 'malay peninsula'       =>   28800,
+      'south africa'          =>    7200, 'sri lanka'             =>   21600,
+      'taipei'                =>   28800, 'tasmania'              =>   36000,
+      'tokyo'                 =>   32400, 'tonga'                 =>   46800,
+      'us eastern'            =>  -18000, 'us mountain'           =>  -25200,
+      'vladivostok'           =>   36000, 'w. australia'          =>   28800,
+      'w. central africa'     =>    3600, 'w. europe'             =>    3600,
+      'west asia'             =>   18000, 'west pacific'          =>   36000,
+      'yakutsk'               =>   32400
+    }
+
+    [MONTHS, DAYS, ABBR_MONTHS, ABBR_DAYS, ZONES].each do |x|
+      x.freeze
+    end
+
+    class Bag # :nodoc:
+
+      def initialize
+	@elem = {}
+      end
+
+      def method_missing(t, *args, &block)
+	t = t.to_s
+	set = t.chomp!('=')
+	t = t.intern
+	if set
+	  @elem[t] = args[0]
+	else
+	  @elem[t]
+	end
+      end
+
+      def to_hash
+	@elem.reject{|k, v| /\A_/ =~ k.to_s || v.nil?}
+      end
+
+    end
+
+  end
+
+  def emit(e, f) # :nodoc:
+    case e
+    when Numeric
+      sign = %w(+ + -)[e <=> 0]
+      e = e.abs
+    end
+
+    s = e.to_s
+
+    if f[:s] && f[:p] == '0'
+      f[:w] -= 1
+    end
+
+    if f[:s] && f[:p] == "\s"
+      s[0,0] = sign
+    end
+
+    if f[:p] != '-'
+      s = s.rjust(f[:w], f[:p])
+    end
+
+    if f[:s] && f[:p] != "\s"
+      s[0,0] = sign
+    end
+
+    s = s.upcase if f[:u]
+    s = s.downcase if f[:d]
+    s
+  end
+
+  def emit_w(e, w, f) # :nodoc:
+    f[:w] = [f[:w], w].compact.max
+    emit(e, f)
+  end
+
+  def emit_n(e, w, f) # :nodoc:
+    f[:p] ||= '0'
+    emit_w(e, w, f)
+  end
+
+  def emit_sn(e, w, f) # :nodoc:
+    if e < 0
+      w += 1
+      f[:s] = true
+    end
+    emit_n(e, w, f)
+  end
+
+  def emit_z(e, w, f) # :nodoc:
+    w += 1
+    f[:s] = true
+    emit_n(e, w, f)
+  end
+
+  def emit_a(e, w, f) # :nodoc:
+    f[:p] ||= "\s"
+    emit_w(e, w, f)
+  end
+
+  def emit_ad(e, w, f) # :nodoc:
+    if f[:x]
+      f[:u] = true
+      f[:d] = false
+    end
+    emit_a(e, w, f)
+  end
+
+  def emit_au(e, w, f) # :nodoc:
+    if f[:x]
+      f[:u] = false
+      f[:d] = true
+    end
+    emit_a(e, w, f)
+  end
+
+  private :emit, :emit_w, :emit_n, :emit_sn, :emit_z,
+	  :emit_a, :emit_ad, :emit_au
+
+  def strftime(fmt='%F')
+    fmt.gsub(/%([-_0^#]+)?(\d+)?[EO]?(:{1,3}z|.)/m) do |m|
+      f = {}
+      s, w, c = $1, $2, $3
+      if s
+	s.scan(/./) do |k|
+	  case k
+	  when '-'; f[:p] = '-'
+	  when '_'; f[:p] = "\s"
+	  when '0'; f[:p] = '0'
+	  when '^'; f[:u] = true
+	  when '#'; f[:x] = true
+	  end
+	end
+      end
+      if w
+	f[:w] = w.to_i
+      end
+      case c
+      when 'A'; emit_ad(DAYNAMES[wday], 0, f)
+      when 'a'; emit_ad(ABBR_DAYNAMES[wday], 0, f)
+      when 'B'; emit_ad(MONTHNAMES[mon], 0, f)
+      when 'b'; emit_ad(ABBR_MONTHNAMES[mon], 0, f)
+      when 'C'; emit_sn((year / 100).floor, 2, f)
+      when 'c'; emit_a(strftime('%a %b %e %H:%M:%S %Y'), 0, f)
+      when 'D'; emit_a(strftime('%m/%d/%y'), 0, f)
+      when 'd'; emit_n(mday, 2, f)
+      when 'e'; emit_a(mday, 2, f)
+      when 'F'
+	if m == '%F'
+	  format('%.4d-%02d-%02d', year, mon, mday) # 4p
+	else
+	  emit_a(strftime('%Y-%m-%d'), 0, f)
+	end
+      when 'G'; emit_sn(cwyear, 4, f)
+      when 'g'; emit_n(cwyear % 100, 2, f)
+      when 'H'; emit_n(hour, 2, f)
+      when 'h'; emit_ad(strftime('%b'), 0, f)
+      when 'I'; emit_n((hour % 12).nonzero? || 12, 2, f)
+      when 'j'; emit_n(yday, 3, f)
+      when 'k'; emit_a(hour, 2, f)
+      when 'L'
+	emit_n((sec_fraction / (1.to_r/86400/(10**3))).round, 3, f)
+      when 'l'; emit_a((hour % 12).nonzero? || 12, 2, f)
+      when 'M'; emit_n(min, 2, f)
+      when 'm'; emit_n(mon, 2, f)
+      when 'N'
+	emit_n((sec_fraction / (1.to_r/86400/(10**9))).round, 9, f)
+      when 'n'; "\n"
+      when 'P'; emit_ad(strftime('%p').downcase, 0, f)
+      when 'p'; emit_au(if hour < 12 then 'AM' else 'PM' end, 0, f)
+      when 'Q'
+	d = ajd - self.class.jd_to_ajd(self.class::UNIXEPOCH, 0)
+	s = (d * 86400*10**3).to_i
+	emit_sn(s, 1, f)
+      when 'R'; emit_a(strftime('%H:%M'), 0, f)
+      when 'r'; emit_a(strftime('%I:%M:%S %p'), 0, f)
+      when 'S'; emit_n(sec, 2, f)
+      when 's'
+	d = ajd - self.class.jd_to_ajd(self.class::UNIXEPOCH, 0)
+	s = (d * 86400).to_i
+	emit_sn(s, 1, f)
+      when 'T'
+	if m == '%T'
+	  format('%02d:%02d:%02d', hour, min, sec) # 4p
+	else
+	  emit_a(strftime('%H:%M:%S'), 0, f)
+	end
+      when 't'; "\t"
+      when 'U', 'W'
+	emit_n(if c == 'U' then wnum0 else wnum1 end, 2, f)
+      when 'u'; emit_n(cwday, 1, f)
+      when 'V'; emit_n(cweek, 2, f)
+      when 'v'; emit_a(strftime('%e-%b-%Y'), 0, f)
+      when 'w'; emit_n(wday, 1, f)
+      when 'X'; emit_a(strftime('%H:%M:%S'), 0, f)
+      when 'x'; emit_a(strftime('%m/%d/%y'), 0, f)
+      when 'Y'; emit_sn(year, 4, f)
+      when 'y'; emit_n(year % 100, 2, f)
+      when 'Z'; emit_au(strftime('%:z'), 0, f)
+      when /\A(:{0,3})z/
+	t = $1.size
+	sign = if offset < 0 then -1 else +1 end
+	fr = offset.abs
+	hh, fr = fr.divmod(1.to_r/24)
+	mm, fr = fr.divmod(1.to_r/1440)
+	ss, fr = fr.divmod(1.to_r/86400)
+	if t == 3
+	  if    ss.nonzero? then t =  2
+	  elsif mm.nonzero? then t =  1
+	  else                   t = -1
+	  end
+	end
+	case t
+	when -1
+	  tail = []
+	  sep = ''
+	when 0
+	  f[:w] -= 2 if f[:w]
+	  tail = ['%02d' % mm]
+	  sep = ''
+	when 1
+	  f[:w] -= 3 if f[:w]
+	  tail = ['%02d' % mm]
+	  sep = ':'
+	when 2
+	  f[:w] -= 6 if f[:w]
+	  tail = ['%02d' % mm, '%02d' % ss]
+	  sep = ':'
+	end
+	([emit_z(sign * hh, 2, f)] + tail).join(sep)
+      when '%'; emit_a('%', 0, f)
+      when '+'; emit_a(strftime('%a %b %e %H:%M:%S %Z %Y'), 0, f)
+      when '1'
+	if $VERBOSE
+	  warn("warning: strftime: %1 is deprecated; forget this")
+	end
+	emit_n(jd, 1, f)
+      when '2'
+	if $VERBOSE
+	  warn("warning: strftime: %2 is deprecated; use '%Y-%j'")
+	end
+	emit_a(strftime('%Y-%j'), 0, f)
+      when '3'
+	if $VERBOSE
+	  warn("warning: strftime: %3 is deprecated; use '%F'")
+	end
+	emit_a(strftime('%F'), 0, f)
+      else
+	c
+      end
+    end
+  end
+
+# alias_method :format, :strftime
+
+  def asctime() strftime('%c') end
+
+  alias_method :ctime, :asctime
+
+=begin
+  def iso8601() strftime('%F') end
+
+  def rfc3339() iso8601 end
+
+  def rfc2822() strftime('%a, %-d %b %Y %T %z') end
+
+  alias_method :rfc822, :rfc2822
+
+  def jisx0301
+    if jd < 2405160
+      iso8601
+    else
+      case jd
+      when 2405160...2419614
+	g = 'M%02d' % (year - 1867)
+      when 2419614...2424875
+	g = 'T%02d' % (year - 1911)
+      when 2424875...2447535
+	g = 'S%02d' % (year - 1925)
+      else
+	g = 'H%02d' % (year - 1988)
+      end
+      g + strftime('.%m.%d')
+    end
+  end
+
+  def beat(n=0)
+    i, f = (new_offset(1.to_r/24).day_fraction * 1000).divmod(1)
+    ('@%03d' % i) +
+      if n < 1
+	''
+      else
+	'.%0*d' % [n, (f / (1.to_r/(10**n))).round]
+      end
+  end
+=end
+
+  def self.num_pattern? (s) # :nodoc:
+    /\A%[EO]?[CDdeFGgHIjkLlMmNQRrSsTUuVvWwXxYy\d]/ =~ s || /\A\d/ =~ s
+  end
+
+  private_class_method :num_pattern?
+
+  def self._strptime_i(str, fmt, e) # :nodoc:
+    fmt.scan(/%[EO]?(:{1,3}z|.)|(.)/m) do |s, c|
+      if s
+	case s
+	when 'A', 'a'
+	  return unless str.sub!(/\A(#{Format::DAYS.keys.join('|')})/io, '') ||
+			str.sub!(/\A(#{Format::ABBR_DAYS.keys.join('|')})/io, '')
+	  val = Format::DAYS[$1.downcase] || Format::ABBR_DAYS[$1.downcase]
+	  return unless val
+	  e.wday = val
+	when 'B', 'b', 'h'
+	  return unless str.sub!(/\A(#{Format::MONTHS.keys.join('|')})/io, '') ||
+			str.sub!(/\A(#{Format::ABBR_MONTHS.keys.join('|')})/io, '')
+	  val = Format::MONTHS[$1.downcase] || Format::ABBR_MONTHS[$1.downcase]
+	  return unless val
+	  e.mon = val
+	when 'C'
+	  return unless str.sub!(if num_pattern?($')
+				 then /\A([-+]?\d{1,2})/
+				 else /\A([-+]?\d{1,})/
+				 end, '')
+	  val = $1.to_i
+	  e._cent = val
+	when 'c'
+	  return unless _strptime_i(str, '%a %b %e %H:%M:%S %Y', e)
+	when 'D'
+	  return unless _strptime_i(str, '%m/%d/%y', e)
+	when 'd', 'e'
+	  return unless str.sub!(/\A( \d|\d{1,2})/, '')
+	  val = $1.to_i
+	  return unless (1..31) === val
+	  e.mday = val
+	when 'F'
+	  return unless _strptime_i(str, '%Y-%m-%d', e)
+	when 'G'
+	  return unless str.sub!(if num_pattern?($')
+				 then /\A([-+]?\d{1,4})/
+				 else /\A([-+]?\d{1,})/
+				 end, '')
+	  val = $1.to_i
+	  e.cwyear = val
+	when 'g'
+	  return unless str.sub!(/\A(\d{1,2})/, '')
+	  val = $1.to_i
+	  return unless (0..99) === val
+	  e.cwyear = val
+	  e._cent ||= if val >= 69 then 19 else 20 end
+	when 'H', 'k'
+	  return unless str.sub!(/\A( \d|\d{1,2})/, '')
+	  val = $1.to_i
+	  return unless (0..24) === val
+	  e.hour = val
+	when 'I', 'l'
+	  return unless str.sub!(/\A( \d|\d{1,2})/, '')
+	  val = $1.to_i
+	  return unless (1..12) === val
+	  e.hour = val
+	when 'j'
+	  return unless str.sub!(/\A(\d{1,3})/, '')
+	  val = $1.to_i
+	  return unless (1..366) === val
+	  e.yday = val
+	when 'L'
+	  return unless str.sub!(if num_pattern?($')
+				 then /\A([-+]?\d{1,3})/
+				 else /\A([-+]?\d{1,})/
+				 end, '')
+#	  val = $1.to_i.to_r / (10**3)
+	  val = $1.to_i.to_r / (10**$1.size)
+	  e.sec_fraction = val
+	when 'M'
+	  return unless str.sub!(/\A(\d{1,2})/, '')
+	  val = $1.to_i
+	  return unless (0..59) === val
+	  e.min = val
+	when 'm'
+	  return unless str.sub!(/\A(\d{1,2})/, '')
+	  val = $1.to_i
+	  return unless (1..12) === val
+	  e.mon = val
+	when 'N'
+	  return unless str.sub!(if num_pattern?($')
+				 then /\A([-+]?\d{1,9})/
+				 else /\A([-+]?\d{1,})/
+				 end, '')
+#	  val = $1.to_i.to_r / (10**9)
+	  val = $1.to_i.to_r / (10**$1.size)
+	  e.sec_fraction = val
+	when 'n', 't'
+	  return unless _strptime_i(str, "\s", e)
+	when 'P', 'p'
+	  return unless str.sub!(/\A([ap])(?:m\b|\.m\.)/i, '')
+	  e._merid = if $1.downcase == 'a' then 0 else 12 end
+	when 'Q'
+	  return unless str.sub!(/\A(-?\d{1,})/, '')
+	  val = $1.to_i.to_r / 10**3
+	  e.seconds = val
+	when 'R'
+	  return unless _strptime_i(str, '%H:%M', e)
+	when 'r'
+	  return unless _strptime_i(str, '%I:%M:%S %p', e)
+	when 'S'
+	  return unless str.sub!(/\A(\d{1,2})/, '')
+	  val = $1.to_i
+	  return unless (0..60) === val
+	  e.sec = val
+	when 's'
+	  return unless str.sub!(/\A(-?\d{1,})/, '')
+	  val = $1.to_i
+	  e.seconds = val
+	when 'T'
+	  return unless _strptime_i(str, '%H:%M:%S', e)
+	when 'U', 'W'
+	  return unless str.sub!(/\A(\d{1,2})/, '')
+	  val = $1.to_i
+	  return unless (0..53) === val
+	  e.__send__(if s == 'U' then :wnum0= else :wnum1= end, val)
+	when 'u'
+	  return unless str.sub!(/\A(\d{1})/, '')
+	  val = $1.to_i
+	  return unless (1..7) === val
+	  e.cwday = val
+	when 'V'
+	  return unless str.sub!(/\A(\d{1,2})/, '')
+	  val = $1.to_i
+	  return unless (1..53) === val
+	  e.cweek = val
+	when 'v'
+	  return unless _strptime_i(str, '%e-%b-%Y', e)
+	when 'w'
+	  return unless str.sub!(/\A(\d{1})/, '')
+	  val = $1.to_i
+	  return unless (0..6) === val
+	  e.wday = val
+	when 'X'
+	  return unless _strptime_i(str, '%H:%M:%S', e)
+	when 'x'
+	  return unless _strptime_i(str, '%m/%d/%y', e)
+	when 'Y'
+	  return unless str.sub!(if num_pattern?($')
+				 then /\A([-+]?\d{1,4})/
+				 else /\A([-+]?\d{1,})/
+				 end, '')
+	  val = $1.to_i
+	  e.year = val
+	when 'y'
+	  return unless str.sub!(/\A(\d{1,2})/, '')
+	  val = $1.to_i
+	  return unless (0..99) === val
+	  e.year = val
+	  e._cent ||= if val >= 69 then 19 else 20 end
+	when 'Z', /\A:{0,3}z/
+	  return unless str.sub!(/\A((?:gmt|utc?)?[-+]\d+(?:[,.:]\d+(?::\d+)?)?
+				    |[a-z.\s]+(?:standard|daylight)\s+time\b
+				    |[a-z]+(?:\s+dst)?\b
+				    )/ix, '')
+	  val = $1
+	  e.zone = val
+	  offset = zone_to_diff(val)
+	  e.offset = offset
+	when '%'
+	  return unless str.sub!(/\A%/, '')
+	when '+'
+	  return unless _strptime_i(str, '%a %b %e %H:%M:%S %Z %Y', e)
+	when '1'
+	  if $VERBOSE
+	    warn("warning: strptime: %1 is deprecated; forget this")
+	  end
+	  return unless str.sub!(/\A(\d+)/, '')
+	  val = $1.to_i
+	  e.jd = val
+	when '2'
+	  if $VERBOSE
+	    warn("warning: strptime: %2 is deprecated; use '%Y-%j'")
+	  end
+	  return unless _strptime_i(str, '%Y-%j', e)
+	when '3'
+	  if $VERBOSE
+	    warn("warning: strptime: %3 is deprecated; use '%F'")
+	  end
+	  return unless _strptime_i(str, '%F', e)
+	else
+	  return unless str.sub!(Regexp.new('\\A' + Regexp.quote(s)), '')
+	end
+      else
+	case c
+	when /\A[\s\v]/
+	  str.sub!(/\A[\s\v]+/, '')
+	else
+	  return unless str.sub!(Regexp.new('\\A' + Regexp.quote(c)), '')
+	end
+      end
+    end
+  end
+
+  private_class_method :_strptime_i
+
+  def self._strptime(str, fmt='%F')
+    e = Format::Bag.new
+    return unless _strptime_i(str.dup, fmt, e)
+
+    if e._cent
+      if e.cwyear
+	e.cwyear += e._cent * 100
+      end
+      if e.year
+	e.  year += e._cent * 100
+      end
+    end
+
+    if e._merid
+      if e.hour
+	e.hour %= 12
+	e.hour += e._merid
+      end
+    end
+
+    e.to_hash
+  end
+
+  def self.s3e(e, y, m, d, bc=false)
+    unless String === m
+      m = m.to_s
+    end
+
+    if y == nil
+      if d && d.size > 2
+	y = d
+	d = nil
+      end
+      if d && d[0,1] == "'"
+	y = d
+	d = nil
+      end
+    end
+
+    if y
+      y.scan(/(\d+)(.+)?/)
+      if $2
+	y, d = d, $1
+      end
+    end
+
+    if m
+      if m[0,1] == "'" || m.size > 2
+	y, m, d = m, d, y # us -> be
+      end
+    end
+
+    if d
+      if d[0,1] == "'" || d.size > 2
+	y, d = d, y
+      end
+    end
+
+    if y
+      y =~ /([-+])?(\d+)/
+      if $1 || $2.size > 2
+	c = false
+      end
+      iy = $&.to_i
+      if bc
+	iy = -iy + 1
+      end
+      e.year = iy
+    end
+
+    if m
+      m =~ /\d+/
+      e.mon = $&.to_i
+    end
+
+    if d
+      d =~ /\d+/
+      e.mday = $&.to_i
+    end
+
+    if c != nil
+      e._comp = c
+    end
+
+  end
+
+  private_class_method :s3e
+
+  def self._parse_day(str, e) # :nodoc:
+    if str.sub!(/\b(#{Format::ABBR_DAYS.keys.join('|')})[^-\d\s]*/ino, ' ')
+      e.wday = Format::ABBR_DAYS[$1.downcase]
+      true
+=begin
+    elsif str.sub!(/\b(?!\dth)(su|mo|tu|we|th|fr|sa)\b/in, ' ')
+      e.wday = %w(su mo tu we th fr sa).index($1.downcase)
+      true
+=end
+    end
+  end
+
+  def self._parse_time(str, e) # :nodoc:
+    if str.sub!(
+		/(
+		   (?:
+		     \d+\s*:\s*\d+
+		     (?:
+		       \s*:\s*\d+(?:[,.]\d*)?
+		     )?
+		   |
+		     \d+\s*h(?:\s*\d+m?(?:\s*\d+s?)?)?
+		   )
+		   (?:
+		     \s*
+		     [ap](?:m\b|\.m\.)
+		   )?
+		 |
+		   \d+\s*[ap](?:m\b|\.m\.)
+		 )
+		 (?:
+		   \s*
+		   (
+		     (?:gmt|utc?)?[-+]\d+(?:[,.:]\d+(?::\d+)?)?
+		   |
+		     [a-z.\s]+(?:standard|daylight)\stime\b
+		   |
+		     [a-z]+(?:\sdst)?\b
+		   )
+		 )?
+		/inx,
+		' ')
+
+      t = $1
+      e.zone = $2 if $2
+
+      t =~ /\A(\d+)h?
+	      (?:\s*:?\s*(\d+)m?
+		(?:
+		  \s*:?\s*(\d+)(?:[,.](\d+))?s?
+		)?
+	      )?
+	    (?:\s*([ap])(?:m\b|\.m\.))?/inx
+
+      e.hour = $1.to_i
+      e.min = $2.to_i if $2
+      e.sec = $3.to_i if $3
+      e.sec_fraction = $4.to_i.to_r / (10**$4.size) if $4
+
+      if $5
+	e.hour %= 12
+	if $5.downcase == 'p'
+	  e.hour += 12
+	end
+      end
+      true
+    end
+  end
+
+  def self._parse_beat(str, e) # :nodoc:
+    if str.sub!(/@\s*(\d+)(?:[,.](\d*))?/, ' ')
+      beat = $1.to_i.to_r
+      beat += $2.to_i.to_r / (10**$2.size) if $2
+      secs = beat.to_r / 1000
+      h, min, s, fr = self.day_fraction_to_time(secs)
+      e.hour = h
+      e.min = min
+      e.sec = s
+      e.sec_fraction = fr * 86400
+      e.zone = '+01:00'
+      true
+    end
+  end
+
+  def self._parse_eu(str, e) # :nodoc:
+    if str.sub!(
+		/'?(\d+)[^-\d\s]*
+		 \s*
+		 (#{Format::ABBR_MONTHS.keys.join('|')})[^-\d\s']*
+		 (?:
+		   \s*
+		   (c(?:e|\.e\.)|b(?:ce|\.c\.e\.)|a(?:d|\.d\.)|b(?:c|\.c\.))?
+		   \s*
+		   ('?-?\d+(?:(?:st|nd|rd|th)\b)?)
+		 )?
+		/inox,
+		' ') # '
+      s3e(e, $4, Format::ABBR_MONTHS[$2.downcase], $1,
+	  $3 && $3[0,1].downcase == 'b')
+      true
+    end
+  end
+
+  def self._parse_us(str, e) # :nodoc:
+    if str.sub!(
+		/\b(#{Format::ABBR_MONTHS.keys.join('|')})[^-\d\s']*
+		 \s*
+		 ('?\d+)[^-\d\s']*
+		 (?:
+		   \s*
+		   (c(?:e|\.e\.)|b(?:ce|\.c\.e\.)|a(?:d|\.d\.)|b(?:c|\.c\.))?
+		   \s*
+		   ('?-?\d+)
+		 )?
+		/inox,
+		' ') # '
+      s3e(e, $4, Format::ABBR_MONTHS[$1.downcase], $2,
+	  $3 && $3[0,1].downcase == 'b')
+      true
+    end
+  end
+
+  def self._parse_iso(str, e) # :nodoc:
+    if str.sub!(/('?[-+]?\d+)-(\d+)-('?-?\d+)/n, ' ')
+      s3e(e, $1, $2, $3)
+      true
+    end
+  end
+
+  def self._parse_iso2(str, e) # :nodoc:
+    if str.sub!(/\b(\d{2}|\d{4})?-?w(\d{2})(?:-?(\d+))?/in, ' ')
+      e.cwyear = $1.to_i if $1
+      e.cweek = $2.to_i
+      e.cwday = $3.to_i if $3
+      true
+    elsif str.sub!(/--(\d{2})-(\d{2})\b/n, ' ')
+      e.mon = $1.to_i
+      e.mday = $2.to_i
+      true
+    elsif str.sub!(/\b(\d{2}|\d{4})-(\d{2,3})\b/n, ' ')
+      e.year = $1.to_i
+      if $2.size < 3
+	e.mon = $2.to_i
+      else
+	e.yday = $2.to_i
+      end
+      true
+    end
+  end
+
+  def self._parse_jis(str, e) # :nodoc:
+    if str.sub!(/\b([MTSH])(\d+)\.(\d+)\.(\d+)/in, ' ')
+      era = { 'm'=>1867,
+	      't'=>1911,
+	      's'=>1925,
+	      'h'=>1988
+	  }[$1.downcase]
+      e.year = $2.to_i + era
+      e.mon = $3.to_i
+      e.mday = $4.to_i
+      true
+    end
+  end
+
+  def self._parse_vms(str, e) # :nodoc:
+    if str.sub!(/('?-?\d+)-(#{Format::ABBR_MONTHS.keys.join('|')})[^-]*
+		-('?-?\d+)/inox, ' ')
+      s3e(e, $3, Format::ABBR_MONTHS[$2.downcase], $1)
+      true
+    elsif str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})[^-]*
+		-('?-?\d+)(?:-('?-?\d+))?/inox, ' ')
+      s3e(e, $3, Format::ABBR_MONTHS[$1.downcase], $2)
+      true
+    end
+  end
+
+  def self._parse_sla_ja(str, e) # :nodoc:
+    if str.sub!(%r|('?-?\d+)[/.]\s*('?\d+)(?:[^\d]\s*('?-?\d+))?|n, ' ') # '
+      s3e(e, $1, $2, $3)
+      true
+    end
+  end
+
+  def self._parse_sla_eu(str, e) # :nodoc:
+    if str.sub!(%r|('?-?\d+)[/.]\s*('?\d+)(?:[^\d]\s*('?-?\d+))?|n, ' ') # '
+      s3e(e, $3, $2, $1)
+      true
+    end
+  end
+
+  def self._parse_sla_us(str, e) # :nodoc:
+    if str.sub!(%r|('?-?\d+)[/.]\s*('?\d+)(?:[^\d]\s*('?-?\d+))?|n, ' ') # '
+      s3e(e, $3, $1, $2)
+      true
+    end
+  end
+
+  def self._parse_year(str, e) # :nodoc:
+    if str.sub!(/'(\d+)\b/in, ' ')
+      e.year = $1.to_i
+      true
+    end
+  end
+
+  def self._parse_mon(str, e) # :nodoc:
+    if str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})\S*/ino, ' ')
+      e.mon = Format::ABBR_MONTHS[$1.downcase]
+      true
+    end
+  end
+
+  def self._parse_mday(str, e) # :nodoc:
+    if str.sub!(/(\d+)(st|nd|rd|th)\b/in, ' ')
+      e.mday = $1.to_i
+      true
+    end
+  end
+
+  def self._parse_ddd(str, e) # :nodoc:
+    if str.sub!(
+		/([-+]?)(\d{2,14})
+		  (?:
+		    \s*
+		    T?
+		    \s*
+		    (\d{2,6})(?:[,.](\d*))?
+		  )?
+		  (?:
+		    \s*
+		    (
+		      Z
+		    |
+		      [-+]\d{1,4}
+		    )
+		    \b
+		  )?
+		/inx,
+		' ')
+      case $2.size
+      when 2
+	e.mday = $2[ 0, 2].to_i
+      when 4
+	e.mon  = $2[ 0, 2].to_i
+	e.mday = $2[ 2, 2].to_i
+      when 6
+	e.year = ($1 + $2[ 0, 2]).to_i
+	e.mon  = $2[ 2, 2].to_i
+	e.mday = $2[ 4, 2].to_i
+      when 8, 10, 12, 14
+	e.year = ($1 + $2[ 0, 4]).to_i
+	e.mon  = $2[ 4, 2].to_i
+	e.mday = $2[ 6, 2].to_i
+	e.hour = $2[ 8, 2].to_i if $2.size >= 10
+	e.min  = $2[10, 2].to_i if $2.size >= 12
+	e.sec  = $2[12, 2].to_i if $2.size >= 14
+	e._comp = false
+      when 3
+	e.yday = $2[ 0, 3].to_i
+      when 5
+	e.year = ($1 + $2[ 0, 2]).to_i
+	e.yday = $2[ 2, 3].to_i
+      when 7
+	e.year = ($1 + $2[ 0, 4]).to_i
+	e.yday = $2[ 4, 3].to_i
+      end
+      if $3
+	case $3.size
+	when 2, 4, 6
+	  e.hour = $3[ 0, 2].to_i
+	  e.min  = $3[ 2, 2].to_i if $3.size >= 4
+	  e.sec  = $3[ 4, 2].to_i if $3.size >= 6
+	end
+      end
+      if $4
+	e.sec_fraction = $4.to_i.to_r / (10**$4.size)
+      end
+      if $5
+	e.zone = $5
+      end
+      true
+    end
+  end
+
+  private_class_method :_parse_day, :_parse_time, :_parse_beat,
+	:_parse_eu, :_parse_us, :_parse_iso, :_parse_iso2,
+	:_parse_jis, :_parse_vms,
+	:_parse_sla_ja, :_parse_sla_eu, :_parse_sla_us,
+	:_parse_year, :_parse_mon, :_parse_mday, :_parse_ddd
+
+  def self._parse(str, comp=false)
+    str = str.dup
+
+    e = Format::Bag.new
+
+    e._comp = comp
+
+    str.gsub!(/[^-+',.\/:0-9@a-z\x80-\xff]+/in, ' ')
+
+    _parse_time(str, e) # || _parse_beat(str, e)
+    _parse_day(str, e)
+
+    _parse_eu(str, e)     ||
+    _parse_us(str, e)     ||
+    _parse_iso(str, e)    ||
+    _parse_jis(str, e)    ||
+    _parse_vms(str, e)    ||
+    _parse_sla_us(str, e) ||
+    _parse_iso2(str, e)   ||
+    _parse_year(str, e)   ||
+    _parse_mon(str, e)    ||
+    _parse_mday(str, e)   ||
+    _parse_ddd(str, e)
+
+    if str.sub!(/\b(bc\b|bce\b|b\.c\.|b\.c\.e\.)/in, ' ')
+      if e.year
+	e.year = -e.year + 1
+      end
+    end
+
+    if str.sub!(/\A\s*(\d{1,2})\s*\z/n, ' ')
+      if e.hour && !e.mday
+	v = $1.to_i
+	if (1..31) === v
+	  e.mday = v
+	end
+      end
+      if e.mday && !e.hour
+	v = $1.to_i
+	if (0..24) === v
+	  e.hour = v
+	end
+      end
+    end
+
+    if e._comp and e.year
+      if e.year >= 0 and e.year <= 99
+	if e.year >= 69
+	  e.year += 1900
+	else
+	  e.year += 2000
+	end
+      end
+    end
+
+    e.offset ||= zone_to_diff(e.zone) if e.zone
+
+    e.to_hash
+  end
+
+  def self.zone_to_diff(zone) # :nodoc:
+    zone = zone.downcase
+    if zone.sub!(/\s+(standard|daylight)\s+time\z/, '')
+      dst = $1 == 'daylight'
+    else
+      dst = zone.sub!(/\s+dst\z/, '')
+    end
+    if Format::ZONES.include?(zone)
+      offset = Format::ZONES[zone]
+      offset += 3600 if dst
+    elsif zone.sub!(/\A(?:gmt|utc?)?([-+])/, '')
+      sign = $1
+      if zone.include?(':')
+	hour, min, sec, = zone.split(':')
+      elsif zone.include?(',') || zone.include?('.')
+	hour, fr, = zone.split(/[,.]/)
+	min = fr.to_i.to_r / (10**fr.size) * 60
+      else
+	case zone.size
+	when 3
+	  hour = zone[0,1]
+	  min = zone[1,2]
+	else
+	  hour = zone[0,2]
+	  min = zone[2,2]
+	  sec = zone[4,2]
+	end
+      end
+      offset = hour.to_i * 3600 + min.to_i * 60 + sec.to_i
+      offset *= -1 if sign == '-'
+    end
+    offset
+  end
+
+end
+
+class DateTime < Date
+
+  def strftime(fmt='%FT%T%:z')
+    super(fmt)
+  end
+
+  def self._strptime(str, fmt='%FT%T%z')
+    super(str, fmt)
+  end
+
+=begin
+  def iso8601_timediv(n) # :nodoc:
+    strftime('T%T' +
+	     if n < 1
+	       ''
+	     else
+	       '.%0*d' % [n, (sec_fraction / (1.to_r/86400/(10**n))).round]
+	     end +
+	     '%:z')
+  end
+
+  private :iso8601_timediv
+
+  def iso8601(n=0)
+    super() + iso8601_timediv(n)
+  end
+
+  def rfc3339(n=0) iso8601(n) end
+
+  def jisx0301(n=0)
+    super() + iso8601_timediv(n)
+  end
+=end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/date2.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/date2.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/date2.rb	(revision 18425)
@@ -0,0 +1,5 @@
+# date2 was overridden by date.
+# To be precise, date was overridden by date2,
+# and date2 was renamed to date.
+
+require 'date'
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/debug.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/debug.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/debug.rb	(revision 18425)
@@ -0,0 +1,947 @@
+# Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
+# Copyright (C) 2000  Information-technology Promotion Agency, Japan
+# Copyright (C) 2000-2003  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>
+
+if $SAFE > 0
+  STDERR.print "-r debug.rb is not available in safe mode\n"
+  exit 1
+end
+
+require 'tracer'
+require 'pp'
+
+class Tracer
+  def Tracer.trace_func(*vars)
+    Single.trace_func(*vars)
+  end
+end
+
+SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
+
+class DEBUGGER__
+class Mutex
+  def initialize
+    @locker = nil
+    @waiting = []
+    @locked = false;
+  end
+
+  def locked?
+    @locked
+  end
+
+  def lock
+    return if Thread.critical
+    return if @locker == Thread.current
+    while (Thread.critical = true; @locked)
+      @waiting.push Thread.current
+      Thread.stop
+    end
+    @locked = true
+    @locker = Thread.current
+    Thread.critical = false
+    self
+  end
+
+  def unlock
+    return if Thread.critical
+    return unless @locked
+    unless @locker == Thread.current
+      raise RuntimeError, "unlocked by other"
+    end
+    Thread.critical = true
+    t = @waiting.shift
+    @locked = false
+    @locker = nil
+    Thread.critical = false
+    t.run if t
+    self
+  end
+end
+MUTEX = Mutex.new
+
+class Context
+  DEBUG_LAST_CMD = []
+
+  begin
+    require 'readline'
+    def readline(prompt, hist)
+      Readline::readline(prompt, hist)
+    end
+  rescue LoadError
+    def readline(prompt, hist)
+      STDOUT.print prompt
+      STDOUT.flush
+      line = STDIN.gets
+      exit unless line
+      line.chomp!
+      line
+    end
+    USE_READLINE = false
+  end
+
+  def initialize
+    if Thread.current == Thread.main
+      @stop_next = 1
+    else
+      @stop_next = 0
+    end
+    @last_file = nil
+    @file = nil
+    @line = nil
+    @no_step = nil
+    @frames = []
+    @finish_pos = 0
+    @trace = false
+    @catch = "StandardError"
+    @suspend_next = false
+  end
+
+  def stop_next(n=1)
+    @stop_next = n
+  end
+
+  def set_suspend
+    @suspend_next = true
+  end
+
+  def clear_suspend
+    @suspend_next = false
+  end
+
+  def suspend_all
+    DEBUGGER__.suspend
+  end
+
+  def resume_all
+    DEBUGGER__.resume
+  end
+
+  def check_suspend
+    return if Thread.critical
+    while (Thread.critical = true; @suspend_next)
+      DEBUGGER__.waiting.push Thread.current
+      @suspend_next = false
+      Thread.stop
+    end
+    Thread.critical = false
+  end
+
+  def trace?
+    @trace
+  end
+
+  def set_trace(arg)
+    @trace = arg
+  end
+
+  def stdout
+    DEBUGGER__.stdout
+  end
+
+  def break_points
+    DEBUGGER__.break_points
+  end
+
+  def display
+    DEBUGGER__.display
+  end
+
+  def context(th)
+    DEBUGGER__.context(th)
+  end
+
+  def set_trace_all(arg)
+    DEBUGGER__.set_trace(arg)
+  end
+
+  def set_last_thread(th)
+    DEBUGGER__.set_last_thread(th)
+  end
+
+  def debug_eval(str, binding)
+    begin
+      val = eval(str, binding)
+    rescue StandardError, ScriptError => e
+      at = eval("caller(1)", binding)
+      stdout.printf "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '')
+      for i in at
+	stdout.printf "\tfrom %s\n", i
+      end
+      throw :debug_error
+    end
+  end
+
+  def debug_silent_eval(str, binding)
+    begin
+      eval(str, binding)
+    rescue StandardError, ScriptError
+      nil
+    end
+  end
+
+  def var_list(ary, binding)
+    ary.sort!
+    for v in ary
+      stdout.printf "  %s => %s\n", v, eval(v, binding).inspect
+    end
+  end
+
+  def debug_variable_info(input, binding)
+    case input
+    when /^\s*g(?:lobal)?\s*$/
+      var_list(global_variables, binding)
+
+    when /^\s*l(?:ocal)?\s*$/
+      var_list(eval("local_variables", binding), binding)
+
+    when /^\s*i(?:nstance)?\s+/
+      obj = debug_eval($', binding)
+      var_list(obj.instance_variables, obj.instance_eval{binding()})
+
+    when /^\s*c(?:onst(?:ant)?)?\s+/
+      obj = debug_eval($', binding)
+      unless obj.kind_of? Module
+	stdout.print "Should be Class/Module: ", $', "\n"
+      else
+	var_list(obj.constants, obj.module_eval{binding()})
+      end
+    end
+  end
+
+  def debug_method_info(input, binding)
+    case input
+    when /^i(:?nstance)?\s+/
+      obj = debug_eval($', binding)
+
+      len = 0
+      for v in obj.methods.sort
+	len += v.size + 1
+	if len > 70
+	  len = v.size + 1
+	  stdout.print "\n"
+	end
+	stdout.print v, " "
+      end
+      stdout.print "\n"
+
+    else
+      obj = debug_eval(input, binding)
+      unless obj.kind_of? Module
+	stdout.print "Should be Class/Module: ", input, "\n"
+      else
+	len = 0
+	for v in obj.instance_methods(false).sort
+	  len += v.size + 1
+	  if len > 70
+	    len = v.size + 1
+	    stdout.print "\n"
+	  end
+	  stdout.print v, " "
+	end
+	stdout.print "\n"
+      end
+    end
+  end
+
+  def thnum
+    num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
+    unless num
+      DEBUGGER__.make_thread_list
+      num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
+    end
+    num
+  end
+
+  def debug_command(file, line, id, binding)
+    MUTEX.lock
+    unless defined?($debugger_restart) and $debugger_restart
+      callcc{|c| $debugger_restart = c} 
+    end
+    set_last_thread(Thread.current)
+    frame_pos = 0
+    binding_file = file
+    binding_line = line
+    previous_line = nil
+    if ENV['EMACS']
+      stdout.printf "\032\032%s:%d:\n", binding_file, binding_line
+    else
+      stdout.printf "%s:%d:%s", binding_file, binding_line,
+	line_at(binding_file, binding_line)
+    end
+    @frames[0] = [binding, file, line, id]
+    display_expressions(binding)
+    prompt = true
+    while prompt and input = readline("(rdb:%d) "%thnum(), true)
+      catch(:debug_error) do
+	if input == ""
+          next unless DEBUG_LAST_CMD[0]
+	  input = DEBUG_LAST_CMD[0]
+	  stdout.print input, "\n"
+	else
+	  DEBUG_LAST_CMD[0] = input
+	end
+
+	case input
+	when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/
+          if defined?( $2 )
+            if $1 == 'on'
+              set_trace_all true
+            else
+              set_trace_all false
+            end
+          elsif defined?( $1 )
+            if $1 == 'on'
+              set_trace true
+            else
+              set_trace false
+            end
+          end
+          if trace?
+            stdout.print "Trace on.\n"
+          else
+            stdout.print "Trace off.\n"
+          end
+
+	when /^\s*b(?:reak)?\s+(?:(.+):)?([^.:]+)$/
+	  pos = $2
+          if $1
+            klass = debug_silent_eval($1, binding)
+            file = $1
+          end
+	  if pos =~ /^\d+$/
+	    pname = pos
+	    pos = pos.to_i
+	  else
+	    pname = pos = pos.intern.id2name
+	  end
+	  break_points.push [true, 0, klass || file, pos]
+	  stdout.printf "Set breakpoint %d at %s:%s\n", break_points.size, klass || file, pname
+
+	when /^\s*b(?:reak)?\s+(.+)[#.]([^.:]+)$/
+	  pos = $2.intern.id2name
+	  klass = debug_eval($1, binding)
+	  break_points.push [true, 0, klass, pos]
+	  stdout.printf "Set breakpoint %d at %s.%s\n", break_points.size, klass, pos
+
+	when /^\s*wat(?:ch)?\s+(.+)$/
+	  exp = $1
+	  break_points.push [true, 1, exp]
+	  stdout.printf "Set watchpoint %d:%s\n", break_points.size, exp
+
+	when /^\s*b(?:reak)?$/
+	  if break_points.find{|b| b[1] == 0}
+	    n = 1
+	    stdout.print "Breakpoints:\n"
+	    for b in break_points
+	      if b[0] and b[1] == 0
+		stdout.printf "  %d %s:%s\n", n, b[2], b[3] 
+	      end
+	      n += 1
+	    end
+	  end
+	  if break_points.find{|b| b[1] == 1}
+	    n = 1
+	    stdout.print "\n"
+	    stdout.print "Watchpoints:\n"
+	    for b in break_points
+	      if b[0] and b[1] == 1
+		stdout.printf "  %d %s\n", n, b[2]
+	      end
+	      n += 1
+	    end
+	  end
+	  if break_points.size == 0
+	    stdout.print "No breakpoints\n"
+	  else
+	    stdout.print "\n"
+	  end
+
+	when /^\s*del(?:ete)?(?:\s+(\d+))?$/
+	  pos = $1
+	  unless pos
+	    input = readline("Clear all breakpoints? (y/n) ", false)
+	    if input == "y"
+	      for b in break_points
+		b[0] = false
+	      end
+	    end
+	  else
+	    pos = pos.to_i
+	    if break_points[pos-1]
+	      break_points[pos-1][0] = false
+	    else
+	      stdout.printf "Breakpoint %d is not defined\n", pos
+	    end
+	  end
+
+	when /^\s*disp(?:lay)?\s+(.+)$/
+	  exp = $1
+	  display.push [true, exp]
+	  stdout.printf "%d: ", display.size
+	  display_expression(exp, binding)
+
+	when /^\s*disp(?:lay)?$/
+	  display_expressions(binding)
+
+	when /^\s*undisp(?:lay)?(?:\s+(\d+))?$/
+	  pos = $1
+	  unless pos
+	    input = readline("Clear all expressions? (y/n) ", false)
+	    if input == "y"
+	      for d in display
+		d[0] = false
+	      end
+	    end
+	  else
+	    pos = pos.to_i
+	    if display[pos-1]
+	      display[pos-1][0] = false
+	    else
+	      stdout.printf "Display expression %d is not defined\n", pos
+	    end
+	  end
+
+	when /^\s*c(?:ont)?$/
+	  prompt = false
+
+	when /^\s*s(?:tep)?(?:\s+(\d+))?$/
+	  if $1
+	    lev = $1.to_i
+	  else
+	    lev = 1
+	  end
+	  @stop_next = lev
+	  prompt = false
+
+	when /^\s*n(?:ext)?(?:\s+(\d+))?$/
+	  if $1
+	    lev = $1.to_i
+	  else
+	    lev = 1
+	  end
+	  @stop_next = lev
+	  @no_step = @frames.size - frame_pos
+	  prompt = false
+
+	when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
+	  display_frames(frame_pos)
+
+	when /^\s*l(?:ist)?(?:\s+(.+))?$/
+	  if not $1
+	    b = previous_line ? previous_line + 10 : binding_line - 5
+	    e = b + 9
+	  elsif $1 == '-'
+	    b = previous_line ? previous_line - 10 : binding_line - 5
+	    e = b + 9
+	  else
+	    b, e = $1.split(/[-,]/)
+	    if e
+	      b = b.to_i
+	      e = e.to_i
+	    else
+	      b = b.to_i - 5
+	      e = b + 9
+	    end
+	  end
+	  previous_line = b
+	  display_list(b, e, binding_file, binding_line)
+
+	when /^\s*up(?:\s+(\d+))?$/
+	  previous_line = nil
+	  if $1
+	    lev = $1.to_i
+	  else
+	    lev = 1
+	  end
+	  frame_pos += lev
+	  if frame_pos >= @frames.size
+	    frame_pos = @frames.size - 1
+	    stdout.print "At toplevel\n"
+	  end
+	  binding, binding_file, binding_line = @frames[frame_pos]
+	  stdout.print format_frame(frame_pos)
+
+	when /^\s*down(?:\s+(\d+))?$/
+	  previous_line = nil
+	  if $1
+	    lev = $1.to_i
+	  else
+	    lev = 1
+	  end
+	  frame_pos -= lev
+	  if frame_pos < 0
+	    frame_pos = 0
+	    stdout.print "At stack bottom\n"
+	  end
+	  binding, binding_file, binding_line = @frames[frame_pos]
+	  stdout.print format_frame(frame_pos)
+
+	when /^\s*fin(?:ish)?$/
+	  if frame_pos == @frames.size
+	    stdout.print "\"finish\" not meaningful in the outermost frame.\n"
+	  else
+	    @finish_pos = @frames.size - frame_pos
+	    frame_pos = 0
+	    prompt = false
+	  end
+
+	when /^\s*cat(?:ch)?(?:\s+(.+))?$/
+	  if $1
+	    excn = $1
+	    if excn == 'off'
+	      @catch = nil
+	      stdout.print "Clear catchpoint.\n"
+	    else
+	      @catch = excn
+	      stdout.printf "Set catchpoint %s.\n", @catch
+	    end
+	  else
+	    if @catch
+	      stdout.printf "Catchpoint %s.\n", @catch
+	    else
+	      stdout.print "No catchpoint.\n"
+	    end
+	  end
+
+	when /^\s*q(?:uit)?$/
+	  input = readline("Really quit? (y/n) ", false)
+	  if input == "y"
+	    exit!	# exit -> exit!: No graceful way to stop threads...
+	  end
+
+	when /^\s*v(?:ar)?\s+/
+	  debug_variable_info($', binding)
+
+	when /^\s*m(?:ethod)?\s+/
+	  debug_method_info($', binding)
+
+	when /^\s*th(?:read)?\s+/
+	  if DEBUGGER__.debug_thread_info($', binding) == :cont
+	    prompt = false
+	  end
+
+	when /^\s*pp\s+/
+	  PP.pp(debug_eval($', binding), stdout)
+
+	when /^\s*p\s+/
+	  stdout.printf "%s\n", debug_eval($', binding).inspect
+
+	when /^\s*r(?:estart)?$/
+          $debugger_restart.call
+
+	when /^\s*h(?:elp)?$/
+	  debug_print_help()
+
+	else
+	  v = debug_eval(input, binding)
+	  stdout.printf "%s\n", v.inspect
+	end
+      end
+    end
+    MUTEX.unlock
+    resume_all
+  end
+
+  def debug_print_help
+    stdout.print <<EOHELP
+Debugger help v.-0.002b
+Commands
+  b[reak] [file:|class:]<line|method>
+  b[reak] [class.]<line|method>
+                             set breakpoint to some position
+  wat[ch] <expression>       set watchpoint to some expression
+  cat[ch] (<exception>|off)  set catchpoint to an exception
+  b[reak]                    list breakpoints
+  cat[ch]                    show catchpoint
+  del[ete][ nnn]             delete some or all breakpoints
+  disp[lay] <expression>     add expression into display expression list
+  undisp[lay][ nnn]          delete one particular or all display expressions
+  c[ont]                     run until program ends or hit breakpoint
+  s[tep][ nnn]               step (into methods) one line or till line nnn
+  n[ext][ nnn]               go over one line or till line nnn
+  w[here]                    display frames
+  f[rame]                    alias for where
+  l[ist][ (-|nn-mm)]         list program, - lists backwards
+                             nn-mm lists given lines
+  up[ nn]                    move to higher frame
+  down[ nn]                  move to lower frame
+  fin[ish]                   return to outer frame
+  tr[ace] (on|off)           set trace mode of current thread
+  tr[ace] (on|off) all       set trace mode of all threads
+  q[uit]                     exit from debugger
+  v[ar] g[lobal]             show global variables
+  v[ar] l[ocal]              show local variables
+  v[ar] i[nstance] <object>  show instance variables of object
+  v[ar] c[onst] <object>     show constants of object
+  m[ethod] i[nstance] <obj>  show methods of object
+  m[ethod] <class|module>    show instance methods of class or module
+  th[read] l[ist]            list all threads
+  th[read] c[ur[rent]]       show current thread
+  th[read] [sw[itch]] <nnn>  switch thread context to nnn
+  th[read] stop <nnn>        stop thread nnn
+  th[read] resume <nnn>      resume thread nnn
+  p expression               evaluate expression and print its value
+  h[elp]                     print this help
+  <everything else>          evaluate
+EOHELP
+  end
+
+  def display_expressions(binding)
+    n = 1
+    for d in display
+      if d[0]
+	stdout.printf "%d: ", n
+	display_expression(d[1], binding)
+      end
+      n += 1
+    end
+  end
+
+  def display_expression(exp, binding)
+    stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s
+  end
+
+  def frame_set_pos(file, line)
+    if @frames[0]
+      @frames[0][1] = file
+      @frames[0][2] = line
+    end
+  end
+
+  def display_frames(pos)
+    0.upto(@frames.size - 1) do |n|
+      if n == pos
+	stdout.print "--> "
+      else
+	stdout.print "    "
+      end
+      stdout.print format_frame(n)
+    end
+  end
+
+  def format_frame(pos)
+    bind, file, line, id = @frames[pos]
+    sprintf "#%d %s:%s%s\n", pos + 1, file, line,
+      (id ? ":in `#{id.id2name}'" : "")
+  end
+
+  def display_list(b, e, file, line)
+    stdout.printf "[%d, %d] in %s\n", b, e, file
+    if lines = SCRIPT_LINES__[file] and lines != true
+      n = 0
+      b.upto(e) do |n|
+	if n > 0 && lines[n-1]
+	  if n == line
+	    stdout.printf "=> %d  %s\n", n, lines[n-1].chomp
+	  else
+	    stdout.printf "   %d  %s\n", n, lines[n-1].chomp
+	  end
+	end
+      end
+    else
+      stdout.printf "No sourcefile available for %s\n", file
+    end
+  end
+
+  def line_at(file, line)
+    lines = SCRIPT_LINES__[file]
+    if lines
+      return "\n" if lines == true
+      line = lines[line-1]
+      return "\n" unless line
+      return line
+    end
+    return "\n"
+  end
+
+  def debug_funcname(id)
+    if id.nil?
+      "toplevel"
+    else
+      id.id2name
+    end
+  end
+
+  def check_break_points(file, klass, pos, binding, id)
+    return false if break_points.empty?
+    n = 1
+    for b in break_points
+      if b[0]		# valid
+	if b[1] == 0	# breakpoint
+	  if (b[2] == file and b[3] == pos) or
+	      (klass and b[2] == klass and b[3] == pos)
+	    stdout.printf "Breakpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
+	    return true
+	  end
+	elsif b[1] == 1	# watchpoint
+	  if debug_silent_eval(b[2], binding)
+	    stdout.printf "Watchpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
+	    return true
+	  end
+	end
+      end
+      n += 1
+    end
+    return false
+  end
+
+  def excn_handle(file, line, id, binding)
+    if $!.class <= SystemExit
+      set_trace_func nil
+      exit
+    end
+
+    if @catch and ($!.class.ancestors.find { |e| e.to_s == @catch })
+      stdout.printf "%s:%d: `%s' (%s)\n", file, line, $!, $!.class
+      fs = @frames.size
+      tb = caller(0)[-fs..-1]
+      if tb
+	for i in tb
+	  stdout.printf "\tfrom %s\n", i
+	end
+      end
+      suspend_all
+      debug_command(file, line, id, binding)
+    end
+  end
+
+  def trace_func(event, file, line, id, binding, klass)
+    Tracer.trace_func(event, file, line, id, binding, klass) if trace?
+    context(Thread.current).check_suspend
+    @file = file
+    @line = line
+    case event
+    when 'line'
+      frame_set_pos(file, line)
+      if !@no_step or @frames.size == @no_step
+	@stop_next -= 1
+	@stop_next = -1 if @stop_next < 0
+      elsif @frames.size < @no_step
+	@stop_next = 0		# break here before leaving...
+      else
+	# nothing to do. skipped.
+      end
+      if @stop_next == 0 or check_break_points(file, nil, line, binding, id)
+	@no_step = nil
+	suspend_all
+	debug_command(file, line, id, binding)
+      end
+
+    when 'call'
+      @frames.unshift [binding, file, line, id]
+      if check_break_points(file, klass, id.id2name, binding, id)
+	suspend_all
+	debug_command(file, line, id, binding)
+      end
+
+    when 'c-call'
+      frame_set_pos(file, line)
+
+    when 'class'
+      @frames.unshift [binding, file, line, id]
+
+    when 'return', 'end'
+      if @frames.size == @finish_pos
+	@stop_next = 1
+	@finish_pos = 0
+      end
+      @frames.shift
+
+    when 'end'
+      @frames.shift
+
+    when 'raise' 
+      excn_handle(file, line, id, binding)
+
+    end
+    @last_file = file
+  end
+end
+
+trap("INT") { DEBUGGER__.interrupt }
+@last_thread = Thread::main
+@max_thread = 1
+@thread_list = {Thread::main => 1}
+@break_points = []
+@display = []
+@waiting = []
+@stdout = STDOUT
+
+class << DEBUGGER__
+  def stdout
+    @stdout
+  end
+
+  def stdout=(s)
+    @stdout = s
+  end
+
+  def display
+    @display
+  end
+
+  def break_points
+    @break_points
+  end
+
+  def waiting
+    @waiting
+  end
+
+  def set_trace( arg )
+    saved_crit = Thread.critical
+    Thread.critical = true
+    make_thread_list
+    for th, in @thread_list
+      context(th).set_trace arg
+    end
+    Thread.critical = saved_crit
+    arg
+  end
+
+  def set_last_thread(th)
+    @last_thread = th
+  end
+
+  def suspend
+    saved_crit = Thread.critical
+    Thread.critical = true
+    make_thread_list
+    for th, in @thread_list
+      next if th == Thread.current
+      context(th).set_suspend
+    end
+    Thread.critical = saved_crit
+    # Schedule other threads to suspend as soon as possible.
+    Thread.pass unless Thread.critical
+  end
+
+  def resume
+    saved_crit = Thread.critical
+    Thread.critical = true
+    make_thread_list
+    for th, in @thread_list
+      next if th == Thread.current
+      context(th).clear_suspend
+    end
+    waiting.each do |th|
+      th.run
+    end
+    waiting.clear
+    Thread.critical = saved_crit
+    # Schedule other threads to restart as soon as possible.
+    Thread.pass
+  end
+
+  def context(thread=Thread.current)
+    c = thread[:__debugger_data__]
+    unless c
+      thread[:__debugger_data__] = c = Context.new
+    end
+    c
+  end
+
+  def interrupt
+    context(@last_thread).stop_next
+  end
+
+  def get_thread(num)
+    th = @thread_list.index(num)
+    unless th
+      @stdout.print "No thread ##{num}\n"
+      throw :debug_error
+    end
+    th
+  end
+
+  def thread_list(num)
+    th = get_thread(num)
+    if th == Thread.current
+      @stdout.print "+"
+    else
+      @stdout.print " "
+    end
+    @stdout.printf "%d ", num
+    @stdout.print th.inspect, "\t"
+    file = context(th).instance_eval{@file}
+    if file
+      @stdout.print file,":",context(th).instance_eval{@line}
+    end
+    @stdout.print "\n"
+  end
+
+  def thread_list_all
+    for th in @thread_list.values.sort
+      thread_list(th)
+    end
+  end
+
+  def make_thread_list
+    hash = {}
+    for th in Thread::list
+      if @thread_list.key? th
+	hash[th] = @thread_list[th]
+      else
+	@max_thread += 1
+	hash[th] = @max_thread
+      end
+    end
+    @thread_list = hash
+  end
+
+  def debug_thread_info(input, binding)
+    case input
+    when /^l(?:ist)?/
+      make_thread_list
+      thread_list_all
+
+    when /^c(?:ur(?:rent)?)?$/
+      make_thread_list
+      thread_list(@thread_list[Thread.current])
+
+    when /^(?:sw(?:itch)?\s+)?(\d+)/
+      make_thread_list
+      th = get_thread($1.to_i)
+      if th == Thread.current
+	@stdout.print "It's the current thread.\n"
+      else
+	thread_list(@thread_list[th])
+	context(th).stop_next
+	th.run
+	return :cont
+      end
+
+    when /^stop\s+(\d+)/
+      make_thread_list
+      th = get_thread($1.to_i)
+      if th == Thread.current
+	@stdout.print "It's the current thread.\n"
+      elsif th.stop?
+	@stdout.print "Already stopped.\n"
+      else
+	thread_list(@thread_list[th])
+	context(th).suspend 
+      end
+
+    when /^resume\s+(\d+)/
+      make_thread_list
+      th = get_thread($1.to_i)
+      if th == Thread.current
+	@stdout.print "It's the current thread.\n"
+      elsif !th.stop?
+	@stdout.print "Already running."
+      else
+	thread_list(@thread_list[th])
+	th.run
+      end
+    end
+  end
+end
+
+stdout.printf "Debug.rb\n"
+stdout.printf "Emacs support available.\n\n"
+set_trace_func proc { |event, file, line, id, binding, klass, *rest|
+  DEBUGGER__.context.trace_func event, file, line, id, binding, klass
+}
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/delegate.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/delegate.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/delegate.rb	(revision 18425)
@@ -0,0 +1,335 @@
+# = delegate -- Support for the Delegation Pattern
+#
+# Documentation by James Edward Gray II and Gavin Sinclair
+#
+# == Introduction
+#
+# This library provides three different ways to delegate method calls to an
+# object.  The easiest to use is SimpleDelegator.  Pass an object to the
+# constructor and all methods supported by the object will be delegated.  This
+# object can be changed later.
+#
+# Going a step further, the top level DelegateClass method allows you to easily
+# setup delegation through class inheritance.  This is considerably more
+# flexible and thus probably the most common use for this library.
+#
+# Finally, if you need full control over the delegation scheme, you can inherit
+# from the abstract class Delegator and customize as needed.  (If you find
+# yourself needing this control, have a look at _forwardable_, also in the
+# standard library.  It may suit your needs better.)
+#
+# == Notes
+#
+# Be advised, RDoc will not detect delegated methods.
+#
+# <b>delegate.rb provides full-class delegation via the
+# DelegateClass() method.  For single-method delegation via
+# def_delegator(), see forwardable.rb.</b>
+#
+# == Examples
+#
+# === SimpleDelegator
+#
+# Here's a simple example that takes advantage of the fact that
+# SimpleDelegator's delegation object can be changed at any time.
+#
+#   class Stats
+#     def initialize
+#       @source = SimpleDelegator.new([])
+#     end
+#     
+#     def stats( records )
+#       @source.__setobj__(records)
+#       	
+#       "Elements:  #{@source.size}\n" +
+#       " Non-Nil:  #{@source.compact.size}\n" +
+#       "  Unique:  #{@source.uniq.size}\n"
+#     end
+#   end
+#   
+#   s = Stats.new
+#   puts s.stats(%w{James Edward Gray II})
+#   puts
+#   puts s.stats([1, 2, 3, nil, 4, 5, 1, 2])
+#
+# <i>Prints:</i>
+#
+#   Elements:  4
+#    Non-Nil:  4
+#     Unique:  4
+# 
+#   Elements:  8
+#    Non-Nil:  7
+#     Unique:  6
+#
+# === DelegateClass()
+#
+# Here's a sample of use from <i>tempfile.rb</i>.
+#
+# A _Tempfile_ object is really just a _File_ object with a few special rules
+# about storage location and/or when the File should be deleted.  That makes for
+# an almost textbook perfect example of how to use delegation.
+#
+#   class Tempfile < DelegateClass(File)
+#     # constant and class member data initialization...
+#   
+#     def initialize(basename, tmpdir=Dir::tmpdir)
+#       # build up file path/name in var tmpname...
+#     
+#       @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)
+#     
+#       # ...
+#     
+#       super(@tmpfile)
+#     
+#       # below this point, all methods of File are supported...
+#     end
+#   
+#     # ...
+#   end
+#
+# === Delegator
+#
+# SimpleDelegator's implementation serves as a nice example here.
+#
+#    class SimpleDelegator < Delegator
+#      def initialize(obj)
+#        super             # pass obj to Delegator constructor, required
+#        @_sd_obj = obj    # store obj for future use
+#      end
+# 
+#      def __getobj__
+#        @_sd_obj          # return object we are delegating to, required
+#      end
+# 
+#      def __setobj__(obj)
+#        @_sd_obj = obj    # change delegation object, a feature we're providing
+#      end
+# 
+#      # ...
+#    end
+
+#
+# Delegator is an abstract class used to build delegator pattern objects from
+# subclasses.  Subclasses should redefine \_\_getobj\_\_.  For a concrete
+# implementation, see SimpleDelegator.
+#
+class Delegator
+
+  #
+  # Pass in the _obj_ to delegate method calls to.  All methods supported by
+  # _obj_ will be delegated to.
+  #
+  def initialize(obj)
+    preserved = ::Kernel.public_instance_methods(false)
+    preserved -= ["to_s","to_a","inspect","==","=~","==="]
+    for t in self.class.ancestors
+      preserved |= t.public_instance_methods(false)
+      preserved |= t.private_instance_methods(false)
+      preserved |= t.protected_instance_methods(false)
+      break if t == Delegator
+    end
+    preserved << "singleton_method_added"
+    for method in obj.methods
+      next if preserved.include? method
+      begin
+	eval <<-EOS
+	  def self.#{method}(*args, &block)
+	    begin
+	      __getobj__.__send__(:#{method}, *args, &block)
+	    rescue Exception
+	      $@.delete_if{|s| /:in `__getobj__'$/ =~ s} #`
+	      $@.delete_if{|s| /^\\(eval\\):/ =~ s}
+	      Kernel::raise
+	    end
+	  end
+	EOS
+      rescue SyntaxError
+        raise NameError, "invalid identifier %s" % method, caller(4)
+      end
+    end
+  end
+  alias initialize_methods initialize
+
+  # Handles the magic of delegation through \_\_getobj\_\_.
+  def method_missing(m, *args)
+    target = self.__getobj__
+    unless target.respond_to?(m)
+      super(m, *args)
+    end
+    target.__send__(m, *args)
+  end
+
+  # 
+  # Checks for a method provided by this the delegate object by fowarding the 
+  # call through \_\_getobj\_\_.
+  # 
+  def respond_to?(m)
+    return true if super
+    return self.__getobj__.respond_to?(m)
+  end
+
+  #
+  # This method must be overridden by subclasses and should return the object
+  # method calls are being delegated to.
+  #
+  def __getobj__
+    raise NotImplementedError, "need to define `__getobj__'"
+  end
+
+  # Serialization support for the object returned by \_\_getobj\_\_.
+  def marshal_dump
+    __getobj__
+  end
+  # Reinitializes delegation from a serialized object.
+  def marshal_load(obj)
+    initialize_methods(obj)
+    __setobj__(obj)
+  end
+end
+
+#
+# A concrete implementation of Delegator, this class provides the means to
+# delegate all supported method calls to the object passed into the constructor
+# and even to change the object being delegated to at a later time with
+# \_\_setobj\_\_ .
+#
+class SimpleDelegator<Delegator
+
+  # Pass in the _obj_ you would like to delegate method calls to.
+  def initialize(obj)
+    super
+    @_sd_obj = obj
+  end
+
+  # Returns the current object method calls are being delegated to.
+  def __getobj__
+    @_sd_obj
+  end
+
+  #
+  # Changes the delegate object to _obj_.
+  #
+  # It's important to note that this does *not* cause SimpleDelegator's methods
+  # to change.  Because of this, you probably only want to change delegation
+  # to objects of the same type as the original delegate.
+  #
+  # Here's an example of changing the delegation object.
+  #
+  #   names = SimpleDelegator.new(%w{James Edward Gray II})
+  #   puts names[1]    # => Edward
+  #   names.__setobj__(%w{Gavin Sinclair})
+  #   puts names[1]    # => Sinclair
+  #
+  def __setobj__(obj)
+    raise ArgumentError, "cannot delegate to self" if self.equal?(obj)
+    @_sd_obj = obj
+  end
+
+  # Clone support for the object returned by \_\_getobj\_\_.
+  def clone
+    super
+    __setobj__(__getobj__.clone)
+  end
+  # Duplication support for the object returned by \_\_getobj\_\_.
+  def dup(obj)
+    super
+    __setobj__(__getobj__.dup)
+  end
+end
+
+# :stopdoc:
+# backward compatibility ^_^;;;
+Delegater = Delegator
+SimpleDelegater = SimpleDelegator
+# :startdoc:
+
+#
+# The primary interface to this library.  Use to setup delegation when defining
+# your class.
+#
+#   class MyClass < DelegateClass( ClassToDelegateTo )    # Step 1
+#     def initiaize
+#       super(obj_of_ClassToDelegateTo)                   # Step 2
+#     end
+#   end
+#
+def DelegateClass(superclass)
+  klass = Class.new
+  methods = superclass.public_instance_methods(true)
+  methods -= ::Kernel.public_instance_methods(false)
+  methods |= ["to_s","to_a","inspect","==","=~","==="]
+  klass.module_eval {
+    def initialize(obj)  # :nodoc:
+      @_dc_obj = obj
+    end
+    def method_missing(m, *args)  # :nodoc:
+      unless @_dc_obj.respond_to?(m)
+        super(m, *args)
+      end
+      @_dc_obj.__send__(m, *args)
+    end
+    def respond_to?(m)  # :nodoc:
+      return true if super
+      return @_dc_obj.respond_to?(m)
+    end
+    def __getobj__  # :nodoc:
+      @_dc_obj
+    end
+    def __setobj__(obj)  # :nodoc:
+      raise ArgumentError, "cannot delegate to self" if self.equal?(obj)
+      @_dc_obj = obj
+    end
+    def clone  # :nodoc:
+      super
+      __setobj__(__getobj__.clone)
+    end
+    def dup  # :nodoc:
+      super
+      __setobj__(__getobj__.dup)
+    end
+  }
+  for method in methods
+    begin
+      klass.module_eval <<-EOS
+        def #{method}(*args, &block)
+	  begin
+	    @_dc_obj.__send__(:#{method}, *args, &block)
+	  rescue
+	    $@[0,2] = nil
+	    raise
+	  end
+	end
+      EOS
+    rescue SyntaxError
+      raise NameError, "invalid identifier %s" % method, caller(3)
+    end
+  end
+  return klass
+end
+
+# :enddoc:
+
+if __FILE__ == $0
+  class ExtArray<DelegateClass(Array)
+    def initialize()
+      super([])
+    end
+  end
+
+  ary = ExtArray.new
+  p ary.class
+  ary.push 25
+  p ary
+
+  foo = Object.new
+  def foo.test
+    25
+  end
+  def foo.error
+    raise 'this is OK'
+  end
+  foo2 = SimpleDelegator.new(foo)
+  p foo.test == foo2.test	# => true
+  foo2.error			# raise error!
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/digest.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/digest.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/digest.rb	(revision 18425)
@@ -0,0 +1,48 @@
+require 'digest.so'
+
+module Digest
+  def self.const_missing(name)
+    case name
+    when :SHA256, :SHA384, :SHA512
+      lib = 'digest/sha2.so'
+    else
+      lib = File.join('digest', name.to_s.downcase)
+    end
+
+    begin
+      require lib
+    rescue LoadError => e
+      raise LoadError, "library not found for class Digest::#{name} -- #{lib}"
+    end
+
+    Digest.const_get(name)
+  end
+
+  class ::Digest::Class
+    # creates a digest object and reads a given file, _name_.
+    # 
+    #  p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest
+    #  # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534"
+    def self.file(name)
+      new.file(name)
+    end
+  end
+
+  module Instance
+    # updates the digest with the contents of a given file _name_ and
+    # returns self.
+    def file(name)
+      File.open(name, "rb") {|f|
+        buf = ""
+        while f.read(16384, buf)
+          update buf
+        end
+      }
+      self
+    end
+  end
+end
+
+def Digest(name)
+  Digest.const_get(name)
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/digest/sha2.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/digest/sha2.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/digest/sha2.rb	(revision 18425)
@@ -0,0 +1,73 @@
+#--
+# sha2.rb - defines Digest::SHA2 class which wraps up the SHA256,
+#           SHA384, and SHA512 classes.
+#++
+# Copyright (c) 2006 Akinori MUSHA <knu@iDaemons.org>
+#
+# All rights reserved.  You can redistribute and/or modify it under the same
+# terms as Ruby.
+#
+#   $Id: sha2.rb 11708 2007-02-12 23:01:19Z shyouhei $
+
+require 'digest'
+
+module Digest
+  #
+  # A meta digest provider class for SHA256, SHA384 and SHA512.
+  #
+  class SHA2 < Digest::Class
+    # call-seq:
+    #     Digest::SHA2.new(bitlen = 256) -> digest_obj
+    #
+    # Creates a new SHA2 hash object with a given bit length.
+    def initialize(bitlen = 256)
+      case bitlen
+      when 256
+        @sha2 = Digest::SHA256.new
+      when 384
+        @sha2 = Digest::SHA384.new
+      when 512
+        @sha2 = Digest::SHA512.new
+      else
+        raise ArgumentError, "unsupported bit length: %s" % bitlen.inspect
+      end
+      @bitlen = bitlen
+    end
+
+    # :nodoc:
+    def reset
+      @sha2.reset
+      self
+    end
+
+    # :nodoc:
+    def update(str)
+      @sha2.update(str)
+      self
+    end
+    alias << update
+
+    def finish
+      @sha2.digest!
+    end
+    private :finish
+
+    def block_length
+      @sha2.block_length
+    end
+
+    def digest_length
+      @sha2.digest_length
+    end
+
+    # :nodoc:
+    def initialize_copy(other)
+      @sha2 = other.instance_eval { @sha2.clone }
+    end
+
+    # :nodoc:
+    def inspect
+      "#<%s:%d %s>" % [self.class.name, @bitlen, hexdigest]
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/dl/import.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/dl/import.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/dl/import.rb	(revision 18425)
@@ -0,0 +1,225 @@
+# -*- ruby -*-
+
+require 'dl'
+require 'dl/types'
+
+module DL
+  module Importable
+    LIB_MAP = {}
+
+    module Internal
+      def init_types()
+	@types ||= ::DL::Types.new
+      end
+
+      def init_sym()
+	@SYM ||= {}
+      end
+
+      def [](name)
+	return @SYM[name.to_s][0]
+      end
+
+      def dlload(*libnames)
+	if( !defined?(@LIBS) )
+	  @LIBS = []
+	end
+	libnames.each{|libname|
+	  if( !LIB_MAP[libname] )
+	    LIB_MAP[libname] = DL.dlopen(libname)
+	  end
+	  @LIBS.push(LIB_MAP[libname])
+	}
+      end
+      alias dllink :dlload
+
+      def parse_cproto(proto)
+	proto = proto.gsub(/\s+/, " ").strip
+	case proto
+	when /^([\d\w\*_\s]+)\(([\d\w\*_\s\,\[\]]*)\)$/
+	  ret = $1
+	  args = $2.strip()
+	  ret = ret.split(/\s+/)
+	  args = args.split(/\s*,\s*/)
+	  func = ret.pop()
+	  if( func =~ /^\*/ )
+	    func.gsub!(/^\*+/,"")
+	    ret.push("*")
+	  end
+	  ret  = ret.join(" ")
+	  return [func, ret, args]
+	else
+	  raise(RuntimeError,"can't parse the function prototype: #{proto}")
+	end
+      end
+
+      # example:
+      #   extern "int strlen(char*)"
+      #
+      def extern(proto)
+	func,ret,args = parse_cproto(proto)
+	return import(func, ret, args)
+      end
+
+      # example:
+      #   callback "int method_name(int, char*)"
+      #
+      def callback(proto)
+	func,ret,args = parse_cproto(proto)
+
+	init_types()
+	init_sym()
+
+	rty,renc,rdec = @types.encode_return_type(ret)
+        if( !rty )
+          raise(TypeError, "unsupported type: #{ret}")
+        end
+	ty,enc,dec = encode_argument_types(args)
+	symty = rty + ty
+
+	module_eval("module_function :#{func}")
+	sym = module_eval([
+	  "DL::callback(\"#{symty}\"){|*args|",
+	  "  sym,rdec,enc,dec  = @SYM['#{func}']",
+	  "  args = enc.call(args) if enc",
+	  "  r,rs = #{func}(*args)",
+	  "  r  = renc.call(r) if rdec",
+	  "  rs = dec.call(rs) if (dec && rs)",
+	  "  @retval = r",
+	  "  @args   = rs",
+	  "  r",
+	  "}",
+	].join("\n"))
+
+	@SYM[func] = [sym,rdec,enc,dec]
+
+	return sym
+      end
+
+      # example:
+      #  typealias("uint", "unsigned int")
+      #
+      def typealias(alias_type, ty1, enc1=nil, dec1=nil, ty2=nil, enc2=nil, dec2=nil)
+	init_types()
+	@types.typealias(alias_type, ty1, enc1, dec1,
+                                     ty2||ty1, enc2, dec2)
+      end
+
+      # example:
+      #  symbol "foo_value"
+      #  symbol "foo_func", "IIP"
+      #
+      def symbol(name, ty = nil)
+	sym = nil
+	@LIBS.each{|lib|
+	  begin
+	    if( ty )
+	      sym = lib[name, ty]
+	    else
+	      sym = lib[name]
+	    end
+	  rescue
+	    next
+	  end
+	}
+	if( !sym )
+	  raise(RuntimeError, "can't find the symbol `#{name}'")
+	end
+	return sym
+      end
+
+      # example:
+      #   import("get_length", "int", ["void*", "int"])
+      #
+      def import(name, rettype, argtypes = nil)
+	init_types()
+	init_sym()
+
+	rty,_,rdec = @types.encode_return_type(rettype)
+        if( !rty )
+          raise(TypeError, "unsupported type: #{rettype}")
+        end
+	ty,enc,dec = encode_argument_types(argtypes)
+	symty = rty + ty
+
+	sym = symbol(name, symty)
+
+	mname = name.dup
+	if( ?A <= mname[0] && mname[0] <= ?Z )
+	  mname[0,1] = mname[0,1].downcase
+	end
+	@SYM[mname] = [sym,rdec,enc,dec]
+	
+	module_eval [
+	  "def #{mname}(*args)",
+	  "  sym,rdec,enc,dec  = @SYM['#{mname}']",
+	  "  args = enc.call(args) if enc",
+	  if( $DEBUG )
+	    "  p \"[DL] call #{mname} with \#{args.inspect}\""
+	  else
+	    ""
+	  end,
+	  "  r,rs = sym.call(*args)",
+	  if( $DEBUG )
+	    "  p \"[DL] retval=\#{r.inspect} args=\#{rs.inspect}\""
+	  else
+	    ""
+	  end,
+	  "  r  = rdec.call(r) if rdec",
+	  "  rs = dec.call(rs) if dec",
+	  "  @retval = r",
+	  "  @args   = rs",
+	  "  return r",
+	  "end",
+	  "module_function :#{mname}",
+	].join("\n")
+
+	return sym
+      end
+
+      def _args_
+	return @args
+      end
+
+      def _retval_
+	return @retval
+      end
+
+      def encode_argument_types(tys)
+	init_types()
+	encty = []
+	enc = nil
+	dec = nil
+	tys.each_with_index{|ty,idx|
+	  ty,c1,c2 = @types.encode_argument_type(ty)
+          if( !ty )
+            raise(TypeError, "unsupported type: #{ty}")
+          end
+	  encty.push(ty)
+	  if( enc )
+	    if( c1 )
+	      conv1 = enc
+	      enc = proc{|v| v = conv1.call(v); v[idx] = c1.call(v[idx]); v}
+	    end
+	  else
+	    if( c1 )
+	      enc = proc{|v| v[idx] = c1.call(v[idx]); v}
+	    end
+	  end
+	  if( dec )
+	    if( c2 )
+	      conv2 = dec
+	      dec = proc{|v| v = conv2.call(v); v[idx] = c2.call(v[idx]); v}
+	    end
+	  else
+	    if( c2 )
+	      dec = proc{|v| v[idx] = c2.call(v[idx]); v}
+	    end
+	  end
+	}
+	return [encty.join, enc, dec]
+      end
+    end # end of Internal
+    include Internal
+  end # end of Importable
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/dl/struct.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/dl/struct.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/dl/struct.rb	(revision 18425)
@@ -0,0 +1,149 @@
+# -*- ruby -*-
+
+require 'dl'
+require 'dl/import'
+
+module DL
+  module Importable
+    module Internal
+      def define_struct(contents)
+	init_types()
+	Struct.new(@types, contents)
+      end
+      alias struct define_struct
+
+      def define_union(contents)
+	init_types()
+	Union.new(@types, contents)
+      end
+      alias union define_union
+
+      class Memory
+	def initialize(ptr, names, ty, len, enc, dec)
+	  @ptr = ptr
+	  @names = names
+	  @ty    = ty
+	  @len   = len
+	  @enc   = enc
+	  @dec   = dec
+
+	  # define methods
+	  @names.each{|name|
+	    instance_eval [
+	      "def #{name}",
+	      "  v = @ptr[\"#{name}\"]",
+	      "  if( @len[\"#{name}\"] )",
+	      "    v = v.collect{|x| @dec[\"#{name}\"] ? @dec[\"#{name}\"].call(x) : x }",
+              "  else",
+	      "    v = @dec[\"#{name}\"].call(v) if @dec[\"#{name}\"]",
+	      "  end",
+	      "  return v",
+	      "end",
+	      "def #{name}=(v)",
+	      "  if( @len[\"#{name}\"] )",
+	      "    v = v.collect{|x| @enc[\"#{name}\"] ? @enc[\"#{name}\"].call(x) : x }",
+	      "  else",
+	      "    v = @enc[\"#{name}\"].call(v) if @enc[\"#{name}\"]",
+              "  end",
+	      "  @ptr[\"#{name}\"] = v",
+	      "  return v",
+	      "end",
+	    ].join("\n")
+	  }
+	end
+
+	def to_ptr
+	  return @ptr
+	end
+
+	def size
+	  return @ptr.size
+	end
+      end
+
+      class Struct
+	def initialize(types, contents)
+	  @names = []
+	  @ty   = {}
+	  @len  = {}
+	  @enc  = {}
+	  @dec  = {}
+	  @size = 0
+	  @tys  = ""
+	  @types = types
+	  parse(contents)
+	end
+
+	def size
+	  return @size
+	end
+
+	def members
+	  return @names
+	end
+
+	# ptr must be a PtrData object.
+	def new(ptr)
+	  ptr.struct!(@tys, *@names)
+	  mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
+	  return mem
+	end
+
+	def malloc(size = nil)
+	  if( !size )
+	    size = @size
+	  end
+	  ptr = DL::malloc(size)
+	  return new(ptr)
+	end
+
+	def parse(contents)
+	  contents.each{|elem|
+	    name,ty,num,enc,dec = parse_elem(elem)
+	    @names.push(name)
+	    @ty[name]  = ty
+	    @len[name] = num
+	    @enc[name] = enc
+	    @dec[name] = dec
+	    if( num )
+	      @tys += "#{ty}#{num}"
+	    else
+	      @tys += ty
+	    end
+	  }
+	  @size = DL.sizeof(@tys)
+	end
+	
+	def parse_elem(elem)
+	  elem.strip!
+	  case elem
+	  when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)$/
+	    ty = ($1 + $2).strip
+	    name = $3
+	    num = nil;
+	  when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)\[(\d+)\]$/
+	    ty = ($1 + $2).strip
+	    name = $3
+	    num = $4.to_i
+	  else
+	    raise(RuntimeError, "invalid element: #{elem}")
+	  end
+	  ty,enc,dec = @types.encode_struct_type(ty)
+          if( !ty )
+            raise(TypeError, "unsupported type: #{ty}")
+          end
+	  return [name,ty,num,enc,dec]
+	end
+      end  # class Struct
+      
+      class Union < Struct
+	def new
+	  ptr = DL::malloc(@size)
+	  ptr.union!(@tys, *@names)
+	  mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
+	  return mem
+	end
+      end
+    end  # module Internal
+  end  # module Importable
+end  # module DL
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/dl/types.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/dl/types.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/dl/types.rb	(revision 18425)
@@ -0,0 +1,245 @@
+# -*- ruby -*-
+
+require 'dl'
+
+module DL
+  class Types
+    TYPES = [
+      # FORMAT:
+      # ["alias name",
+      #  "type name", encoding_method, decoding_method,   for function prototypes
+      #  "type name", encoding_method, decoding_method]   for structures (not implemented)
+      
+      # for Windows
+      ["DWORD",  "unsigned long", nil, nil,
+                 "unsigned long", nil, nil],
+      ["PDWORD", "unsigned long *", nil, nil,
+                 "unsigned long *", nil, nil],
+      ["WORD",   "unsigned short", nil, nil,
+                 "unsigned short", nil, nil],
+      ["PWORD",  "unsigned int *", nil, nil,
+                 "unsigned int *", nil, nil],
+      ["BYTE",   "unsigned char",   nil, nil,
+                 "unsigned char", nil, nil],
+      ["PBYTE",  "unsigned char *", nil, nil,
+                 "unsigned char *", nil, nil],
+      ["BOOL",   "ibool", nil, nil,
+                 "ibool", nil, nil],
+      ["ATOM",   "int", nil, nil,
+                 "int", nil, nil],
+      ["BYTE",   "unsigned char", nil, nil,
+                 "unsigned char", nil, nil],
+      ["PBYTE",  "unsigned char *", nil, nil,
+                 "unsigned char *", nil, nil],
+      ["UINT",   "unsigned int", nil, nil,
+                 "unsigned int", nil, nil],
+      ["ULONG",  "unsigned long", nil, nil,
+                 "unsigned long", nil, nil],
+      ["UCHAR",  "unsigned char", nil, nil,
+                 "unsigned char", nil, nil],
+      ["HANDLE", "unsigned long", nil, nil,
+                 "unsigned long", nil, nil],
+      ["PHANDLE","void*", nil, nil,
+                 "void*", nil, nil],
+      ["PVOID",  "void*", nil, nil,
+                 "void*", nil, nil],
+      ["LPCSTR", "char*", nil, nil,
+                 "char*", nil, nil],
+      ["HDC",    "unsigned int", nil, nil,
+                 "unsigned int", nil, nil],
+      ["HWND",   "unsigned int", nil, nil,
+                 "unsigned int", nil, nil],
+      
+      # Others
+      ["uint",   "unsigned int", nil, nil,
+                 "unsigned int", nil, nil],
+      ["u_int",  "unsigned int", nil, nil,
+                 "unsigned int", nil, nil],
+      ["ulong",  "unsigned long", nil, nil,
+                 "unsigned long", nil, nil],
+      ["u_long", "unsigned long", nil, nil,
+                 "unsigned long", nil, nil],
+
+      # DL::Importable primitive types
+      ["ibool",
+        "I",
+	proc{|v| v ? 1 : 0},
+	proc{|v| (v != 0) ? true : false},
+        "I",
+	proc{|v| v ? 1 : 0 },
+	proc{|v| (v != 0) ? true : false} ],
+      ["cbool",
+        "C",
+	proc{|v| v ? 1 : 0},
+	proc{|v| (v != 0) ? true : false},
+        "C",
+	proc{|v,len| v ? 1 : 0},
+	proc{|v,len| (v != 0) ? true : false}],
+      ["lbool",
+        "L",
+	proc{|v| v ? 1 : 0},
+	proc{|v| (v != 0) ? true : false},
+        "L",
+	proc{|v,len| v ? 1 : 0},
+	proc{|v,len| (v != 0) ? true : false}],
+      ["unsigned char",
+        "C",
+	proc{|v| [v].pack("C").unpack("c")[0]},
+	proc{|v| [v].pack("c").unpack("C")[0]},
+        "C",
+	proc{|v| [v].pack("C").unpack("c")[0]},
+	proc{|v| [v].pack("c").unpack("C")[0]}],
+      ["unsigned short",
+        "H",
+	proc{|v| [v].pack("S").unpack("s")[0]},
+	proc{|v| [v].pack("s").unpack("S")[0]},
+        "H",
+	proc{|v| [v].pack("S").unpack("s")[0]},
+	proc{|v| [v].pack("s").unpack("S")[0]}],
+      ["unsigned int",
+        "I",
+	proc{|v| [v].pack("I").unpack("i")[0]},
+	proc{|v| [v].pack("i").unpack("I")[0]},
+        "I",
+	proc{|v| [v].pack("I").unpack("i")[0]},
+	proc{|v| [v].pack("i").unpack("I")[0]}],
+      ["unsigned long",
+        "L",
+	proc{|v| [v].pack("L").unpack("l")[0]},
+	proc{|v| [v].pack("l").unpack("L")[0]},
+        "L",
+	proc{|v| [v].pack("L").unpack("l")[0]},
+	proc{|v| [v].pack("l").unpack("L")[0]}],
+      ["unsigned char ref",
+        "c",
+	proc{|v| [v].pack("C").unpack("c")[0]},
+	proc{|v| [v].pack("c").unpack("C")[0]},
+	nil, nil, nil],
+      ["unsigned int ref",
+        "i",
+	proc{|v| [v].pack("I").unpack("i")[0]},
+	proc{|v| [v].pack("i").unpack("I")[0]},
+	nil, nil, nil],
+      ["unsigned long ref",
+        "l",
+	proc{|v| [v].pack("L").unpack("l")[0]},
+	proc{|v| [v].pack("l").unpack("L")[0]},
+	nil, nil, nil],
+      ["char ref",  "c", nil, nil,
+                    nil, nil, nil],
+      ["short ref", "h", nil, nil,
+                    nil, nil, nil],
+      ["int ref",   "i", nil, nil,
+                    nil, nil, nil],
+      ["long ref",  "l", nil, nil,
+                    nil, nil, nil],
+      ["float ref", "f", nil, nil,
+                    nil, nil, nil],
+      ["double ref","d", nil, nil,
+                    nil, nil, nil],
+      ["char",   "C", nil, nil,
+                 "C", nil, nil],
+      ["short",  "H", nil, nil,
+                 "H", nil, nil],
+      ["int",    "I", nil, nil,
+                 "I", nil, nil],
+      ["long",   "L", nil, nil,
+                 "L", nil, nil],
+      ["float",  "F", nil, nil,
+                 "F", nil, nil],
+      ["double", "D", nil, nil,
+                 "D", nil, nil],
+      [/^char\s*\*$/,"s",nil, nil,
+                     "S",nil, nil],
+      [/^const char\s*\*$/,"S",nil, nil,
+                           "S",nil, nil],
+      [/^.+\*$/,   "P", nil, nil,
+                   "P", nil, nil],
+      [/^.+\[\]$/, "a", nil, nil,
+                   "a", nil, nil],
+      ["void",   "0", nil, nil,
+                 nil, nil, nil],
+    ]
+
+    def initialize
+      init_types()
+    end
+
+    def typealias(ty1, ty2, enc=nil, dec=nil, ty3=nil, senc=nil, sdec=nil)
+      @TYDEFS.unshift([ty1, ty2, enc, dec, ty3, senc, sdec])
+    end
+
+    def init_types
+      @TYDEFS = TYPES.dup
+    end
+
+    def encode_argument_type(alias_type)
+      proc_encode = nil
+      proc_decode = nil
+      @TYDEFS.each{|aty,ty,enc,dec,_,_,_|
+	if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
+	  alias_type = alias_type.gsub(aty,ty) if ty
+          alias_type.strip! if alias_type
+	  if( proc_encode )
+	    if( enc )
+	      conv1 = proc_encode
+	      proc_encode = proc{|v| enc.call(conv1.call(v))}
+	    end
+	  else
+	    if( enc )
+	      proc_encode = enc
+	    end
+	  end
+	  if( proc_decode )
+	    if( dec )
+	      conv2 = proc_decode
+	      proc_decode = proc{|v| dec.call(conv2.call(v))}
+	    end
+	  else
+	    if( dec )
+	      proc_decode = dec
+	    end
+	  end
+	end
+      }
+      return [alias_type, proc_encode, proc_decode]
+    end
+
+    def encode_return_type(ty)
+      ty, enc, dec = encode_argument_type(ty)
+      return [ty, enc, dec]
+    end
+
+    def encode_struct_type(alias_type)
+      proc_encode = nil
+      proc_decode = nil
+      @TYDEFS.each{|aty,_,_,_,ty,enc,dec|
+	if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
+	  alias_type = alias_type.gsub(aty,ty) if ty
+          alias_type.strip! if alias_type
+	  if( proc_encode )
+	    if( enc )
+	      conv1 = proc_encode
+	      proc_encode = proc{|v| enc.call(conv1.call(v))}
+	    end
+	  else
+	    if( enc )
+	      proc_encode = enc
+	    end
+	  end
+	  if( proc_decode )
+	    if( dec )
+	      conv2 = proc_decode
+	      proc_decode = proc{|v| dec.call(conv2.call(v))}
+	    end
+	  else
+	    if( dec )
+	      proc_decode = dec
+	    end
+	  end
+	end
+      }
+      return [alias_type, proc_encode, proc_decode]
+    end
+  end # end of Types
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/dl/win32.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/dl/win32.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/dl/win32.rb	(revision 18425)
@@ -0,0 +1,25 @@
+# -*- ruby -*-
+
+require 'dl'
+
+class Win32API
+  DLL = {}
+
+  def initialize(dllname, func, import, export = "0")
+    prototype = (export + import.to_s).tr("VPpNnLlIi", "0SSI")
+    handle = DLL[dllname] ||= DL::Handle.new(dllname)
+    @sym = handle.sym(func, prototype)
+  end
+
+  def call(*args)
+    import = @sym.proto.split("", 2)[1]
+    args.each_with_index do |x, i|
+      args[i] = nil if x == 0 and import[i] == ?S
+      args[i], = [x].pack("I").unpack("i") if import[i] == ?I
+    end
+    ret, = @sym.call(*args)
+    return ret || 0
+  end
+
+  alias Call call
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb.rb	(revision 18425)
@@ -0,0 +1,2 @@
+require 'drb/drb'
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/acl.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/acl.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/acl.rb	(revision 18425)
@@ -0,0 +1,146 @@
+# acl-2.0 - simple Access Control List
+#
+# Copyright (c) 2000,2002,2003 Masatoshi SEKI
+#
+# acl.rb is copyrighted free software by Masatoshi SEKI.
+# You can redistribute it and/or modify it under the same terms as Ruby.
+
+require 'ipaddr'
+
+class ACL
+  VERSION=["2.0.0"]
+  class ACLEntry
+    def initialize(str)
+      if str == '*' or str == 'all'
+	@pat = [:all]
+      elsif str.include?('*')
+        @pat = [:name, dot_pat(str)]
+      else
+	begin
+	  @pat = [:ip, IPAddr.new(str)]
+	rescue ArgumentError
+	  @pat = [:name, dot_pat(str)]
+	end
+      end
+    end
+
+    private
+    def dot_pat_str(str)
+      list = str.split('.').collect { |s|
+	(s == '*') ? '.+' : s
+      }
+      list.join("\\.")
+    end
+
+    private
+    def dot_pat(str)
+      exp = "^" + dot_pat_str(str) + "$"
+      Regexp.new(exp)
+    end
+
+    public
+    def match(addr)
+      case @pat[0]
+      when :all
+	true
+      when :ip
+	begin
+	  ipaddr = IPAddr.new(addr[3])
+	  ipaddr = ipaddr.ipv4_mapped if @pat[1].ipv6? && ipaddr.ipv4?
+	rescue ArgumentError
+	  return false
+	end
+	(@pat[1].include?(ipaddr)) ? true : false
+      when :name
+	(@pat[1] =~ addr[2]) ? true : false
+      else
+	false
+      end
+    end
+  end
+
+  class ACLList
+    def initialize
+      @list = []
+    end
+
+    public
+    def match(addr)
+      @list.each do |e|
+	return true if e.match(addr)
+      end
+      false
+    end
+
+    public
+    def add(str)
+      @list.push(ACLEntry.new(str))
+    end
+  end
+
+  DENY_ALLOW = 0
+  ALLOW_DENY = 1
+
+  def initialize(list=nil, order = DENY_ALLOW)
+    @order = order
+    @deny = ACLList.new
+    @allow = ACLList.new
+    install_list(list) if list
+  end
+
+  public
+  def allow_socket?(soc)
+    allow_addr?(soc.peeraddr)
+  end
+
+  public
+  def allow_addr?(addr)
+    case @order
+    when DENY_ALLOW
+      return true if @allow.match(addr)
+      return false if @deny.match(addr)
+      return true
+    when ALLOW_DENY
+      return false if @deny.match(addr)
+      return true if @allow.match(addr)
+      return false
+    else
+      false
+    end
+  end
+
+  public
+  def install_list(list)
+    i = 0
+    while i < list.size
+      permission, domain = list.slice(i,2)
+      case permission.downcase
+      when 'allow'
+	@allow.add(domain)
+      when 'deny'
+	@deny.add(domain)
+      else
+	raise "Invalid ACL entry #{list.to_s}"
+      end
+      i += 2
+    end
+  end
+end
+
+if __FILE__ == $0
+  # example
+  list = %w(deny all
+	    allow 192.168.1.1
+            allow ::ffff:192.168.1.2
+            allow 192.168.1.3
+            )
+
+  addr = ["AF_INET", 10, "lc630", "192.168.1.3"]
+
+  acl = ACL.new
+  p acl.allow_addr?(addr)
+
+  acl = ACL.new(list, ACL::DENY_ALLOW)
+  p acl.allow_addr?(addr)
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/drb.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/drb.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/drb.rb	(revision 18425)
@@ -0,0 +1,1763 @@
+#
+# = drb/drb.rb
+#
+# Distributed Ruby: _dRuby_ version 2.0.4
+#
+# Copyright (c) 1999-2003 Masatoshi SEKI.  You can redistribute it and/or
+# modify it under the same terms as Ruby.
+#
+# Author:: Masatoshi SEKI
+#
+# Documentation:: William Webber (william@williamwebber.com)
+#
+# == Overview
+#
+# dRuby is a distributed object system for Ruby.  It allows an object in one
+# Ruby process to invoke methods on an object in another Ruby process on the
+# same or a different machine.
+#
+# The Ruby standard library contains the core classes of the dRuby package.
+# However, the full package also includes access control lists and the
+# Rinda tuple-space distributed task management system, as well as a 
+# large number of samples.  The full dRuby package can be downloaded from
+# the dRuby home page (see *References*).
+#
+# For an introduction and examples of usage see the documentation to the
+# DRb module.
+#
+# == References
+#
+# [http://www2a.biglobe.ne.jp/~seki/ruby/druby.html]
+#    The dRuby home page, in Japanese.  Contains the full dRuby package
+#    and links to other Japanese-language sources.
+#
+# [http://www2a.biglobe.ne.jp/~seki/ruby/druby.en.html]
+#    The English version of the dRuby home page.
+#
+# [http://www.chadfowler.com/ruby/drb.html]
+#    A quick tutorial introduction to using dRuby by Chad Fowler.
+#
+# [http://www.linux-mag.com/2002-09/ruby_05.html]
+#   A tutorial introduction to dRuby in Linux Magazine by Dave Thomas.
+#   Includes a discussion of Rinda.
+#
+# [http://www.eng.cse.dmu.ac.uk/~hgs/ruby/dRuby/]
+#   Links to English-language Ruby material collected by Hugh Sasse.
+#
+# [http://www.rubycentral.com/book/ospace.html]
+#   The chapter from *Programming* *Ruby* by Dave Thomas and Andy Hunt
+#   which discusses dRuby.
+#
+# [http://www.clio.ne.jp/home/web-i31s/Flotuard/Ruby/PRC2K_seki/dRuby.en.html]
+#   Translation of presentation on Ruby by Masatoshi Seki.
+
+require 'socket'
+require 'thread'
+require 'fcntl'
+require 'drb/eq'
+
+#
+# == Overview
+#
+# dRuby is a distributed object system for Ruby.  It is written in
+# pure Ruby and uses its own protocol.  No add-in services are needed
+# beyond those provided by the Ruby runtime, such as TCP sockets.  It
+# does not rely on or interoperate with other distributed object
+# systems such as CORBA, RMI, or .NET.
+#
+# dRuby allows methods to be called in one Ruby process upon a Ruby
+# object located in another Ruby process, even on another machine.
+# References to objects can be passed between processes.  Method
+# arguments and return values are dumped and loaded in marshalled
+# format.  All of this is done transparently to both the caller of the
+# remote method and the object that it is called upon.
+#
+# An object in a remote process is locally represented by a
+# DRb::DRbObject instance.  This acts as a sort of proxy for the
+# remote object.  Methods called upon this DRbObject instance are
+# forwarded to its remote object.  This is arranged dynamically at run
+# time.  There are no statically declared interfaces for remote
+# objects, such as CORBA's IDL.
+#
+# dRuby calls made into a process are handled by a DRb::DRbServer
+# instance within that process.  This reconstitutes the method call,
+# invokes it upon the specified local object, and returns the value to
+# the remote caller.  Any object can receive calls over dRuby.  There
+# is no need to implement a special interface, or mixin special
+# functionality.  Nor, in the general case, does an object need to
+# explicitly register itself with a DRbServer in order to receive
+# dRuby calls.
+#
+# One process wishing to make dRuby calls upon another process must
+# somehow obtain an initial reference to an object in the remote
+# process by some means other than as the return value of a remote
+# method call, as there is initially no remote object reference it can
+# invoke a method upon.  This is done by attaching to the server by
+# URI.  Each DRbServer binds itself to a URI such as
+# 'druby://example.com:8787'.  A DRbServer can have an object attached
+# to it that acts as the server's *front* *object*.  A DRbObject can
+# be explicitly created from the server's URI.  This DRbObject's
+# remote object will be the server's front object.  This front object
+# can then return references to other Ruby objects in the DRbServer's
+# process.
+#
+# Method calls made over dRuby behave largely the same as normal Ruby
+# method calls made within a process.  Method calls with blocks are
+# supported, as are raising exceptions.  In addition to a method's
+# standard errors, a dRuby call may also raise one of the
+# dRuby-specific errors, all of which are subclasses of DRb::DRbError.
+#
+# Any type of object can be passed as an argument to a dRuby call or
+# returned as its return value.  By default, such objects are dumped
+# or marshalled at the local end, then loaded or unmarshalled at the
+# remote end.  The remote end therefore receives a copy of the local
+# object, not a distributed reference to it; methods invoked upon this
+# copy are executed entirely in the remote process, not passed on to
+# the local original.  This has semantics similar to pass-by-value.
+#
+# However, if an object cannot be marshalled, a dRuby reference to it
+# is passed or returned instead.  This will turn up at the remote end
+# as a DRbObject instance.  All methods invoked upon this remote proxy
+# are forwarded to the local object, as described in the discussion of
+# DRbObjects.  This has semantics similar to the normal Ruby
+# pass-by-reference.
+# 
+# The easiest way to signal that we want an otherwise marshallable
+# object to be passed or returned as a DRbObject reference, rather
+# than marshalled and sent as a copy, is to include the
+# DRb::DRbUndumped mixin module.
+#
+# dRuby supports calling remote methods with blocks.  As blocks (or
+# rather the Proc objects that represent them) are not marshallable,
+# the block executes in the local, not the remote, context.  Each
+# value yielded to the block is passed from the remote object to the
+# local block, then the value returned by each block invocation is
+# passed back to the remote execution context to be collected, before
+# the collected values are finally returned to the local context as
+# the return value of the method invocation.
+# 
+# == Examples of usage
+#
+# For more dRuby samples, see the +samples+ directory in the full
+# dRuby distribution.
+#
+# === dRuby in client/server mode
+#
+# This illustrates setting up a simple client-server drb
+# system.  Run the server and client code in different terminals,
+# starting the server code first.
+#
+# ==== Server code
+#    
+#   require 'drb/drb'
+#     
+#   # The URI for the server to connect to
+#   URI="druby://localhost:8787" 
+#     
+#   class TimeServer
+#     
+#     def get_current_time
+#       return Time.now
+#     end
+#     
+#   end
+#     
+#   # The object that handles requests on the server
+#   FRONT_OBJECT=TimeServer.new
+#
+#   $SAFE = 1   # disable eval() and friends
+#   
+#   DRb.start_service(URI, FRONT_OBJECT)
+#   # Wait for the drb server thread to finish before exiting.
+#   DRb.thread.join
+#
+# ==== Client code
+#     
+#   require 'drb/drb'
+#   
+#   # The URI to connect to
+#   SERVER_URI="druby://localhost:8787"
+#
+#   # Start a local DRbServer to handle callbacks.
+#   #
+#   # Not necessary for this small example, but will be required
+#   # as soon as we pass a non-marshallable object as an argument
+#   # to a dRuby call.
+#   DRb.start_service
+#   
+#   timeserver = DRbObject.new_with_uri(SERVER_URI)
+#   puts timeserver.get_current_time 
+#
+# === Remote objects under dRuby
+#
+# This example illustrates returning a reference to an object
+# from a dRuby call.  The Logger instances live in the server
+# process.  References to them are returned to the client process,
+# where methods can be invoked upon them.  These methods are 
+# executed in the server process.
+#
+# ==== Server code
+#   
+#   require 'drb/drb'
+#   
+#   URI="druby://localhost:8787"
+#   
+#   class Logger
+#
+#       # Make dRuby send Logger instances as dRuby references,
+#       # not copies.
+#       include DRb::DRbUndumped
+#   
+#       def initialize(n, fname)
+#           @name = n
+#           @filename = fname
+#       end
+#   
+#       def log(message)
+#           File.open(@filename, "a") do |f|
+#               f.puts("#{Time.now}: #{@name}: #{message}")
+#           end
+#       end
+#   
+#   end
+#   
+#   # We have a central object for creating and retrieving loggers.
+#   # This retains a local reference to all loggers created.  This
+#   # is so an existing logger can be looked up by name, but also
+#   # to prevent loggers from being garbage collected.  A dRuby
+#   # reference to an object is not sufficient to prevent it being
+#   # garbage collected!
+#   class LoggerFactory
+#   
+#       def initialize(bdir)
+#           @basedir = bdir
+#           @loggers = {}
+#       end
+#   
+#       def get_logger(name)
+#           if !@loggers.has_key? name
+#               # make the filename safe, then declare it to be so
+#               fname = name.gsub(/[.\/]/, "_").untaint
+#               @loggers[name] = Logger.new(name, @basedir + "/" + fname)
+#           end
+#           return @loggers[name]
+#       end
+#   
+#   end
+#   
+#   FRONT_OBJECT=LoggerFactory.new("/tmp/dlog")
+#
+#   $SAFE = 1   # disable eval() and friends
+#   
+#   DRb.start_service(URI, FRONT_OBJECT)
+#   DRb.thread.join
+#
+# ==== Client code
+#
+#   require 'drb/drb'
+#   
+#   SERVER_URI="druby://localhost:8787"
+#
+#   DRb.start_service
+#   
+#   log_service=DRbObject.new_with_uri(SERVER_URI)
+#   
+#   ["loga", "logb", "logc"].each do |logname|
+#   
+#       logger=log_service.get_logger(logname)
+#   
+#       logger.log("Hello, world!")
+#       logger.log("Goodbye, world!")
+#       logger.log("=== EOT ===")
+#   
+#   end
+#
+# == Security
+#
+# As with all network services, security needs to be considered when
+# using dRuby.  By allowing external access to a Ruby object, you are
+# not only allowing outside clients to call the methods you have
+# defined for that object, but by default to execute arbitrary Ruby
+# code on your server.  Consider the following:
+#
+#    # !!! UNSAFE CODE !!!
+#    ro = DRbObject::new_with_uri("druby://your.server.com:8989")
+#    class << ro
+#      undef :instance_eval  # force call to be passed to remote object
+#    end
+#    ro.instance_eval("`rm -rf *`")
+#
+# The dangers posed by instance_eval and friends are such that a
+# DRbServer should generally be run with $SAFE set to at least 
+# level 1.  This will disable eval() and related calls on strings 
+# passed across the wire.  The sample usage code given above follows 
+# this practice.
+#
+# A DRbServer can be configured with an access control list to
+# selectively allow or deny access from specified IP addresses.  The
+# main druby distribution provides the ACL class for this purpose.  In
+# general, this mechanism should only be used alongside, rather than
+# as a replacement for, a good firewall.
+#
+# == dRuby internals
+#
+# dRuby is implemented using three main components: a remote method
+# call marshaller/unmarshaller; a transport protocol; and an
+# ID-to-object mapper.  The latter two can be directly, and the first
+# indirectly, replaced, in order to provide different behaviour and
+# capabilities.
+#
+# Marshalling and unmarshalling of remote method calls is performed by
+# a DRb::DRbMessage instance.  This uses the Marshal module to dump
+# the method call before sending it over the transport layer, then
+# reconstitute it at the other end.  There is normally no need to
+# replace this component, and no direct way is provided to do so.
+# However, it is possible to implement an alternative marshalling
+# scheme as part of an implementation of the transport layer.
+#
+# The transport layer is responsible for opening client and server
+# network connections and forwarding dRuby request across them.
+# Normally, it uses DRb::DRbMessage internally to manage marshalling
+# and unmarshalling.  The transport layer is managed by
+# DRb::DRbProtocol.  Multiple protocols can be installed in
+# DRbProtocol at the one time; selection between them is determined by
+# the scheme of a dRuby URI.  The default transport protocol is
+# selected by the scheme 'druby:', and implemented by
+# DRb::DRbTCPSocket.  This uses plain TCP/IP sockets for
+# communication.  An alternative protocol, using UNIX domain sockets,
+# is implemented by DRb::DRbUNIXSocket in the file drb/unix.rb, and
+# selected by the scheme 'drbunix:'.  A sample implementation over
+# HTTP can be found in the samples accompanying the main dRuby
+# distribution.
+#
+# The ID-to-object mapping component maps dRuby object ids to the
+# objects they refer to, and vice versa.  The implementation to use
+# can be specified as part of a DRb::DRbServer's configuration.  The
+# default implementation is provided by DRb::DRbIdConv.  It uses an
+# object's ObjectSpace id as its dRuby id.  This means that the dRuby
+# reference to that object only remains meaningful for the lifetime of
+# the object's process and the lifetime of the object within that
+# process.  A modified implementation is provided by DRb::TimerIdConv
+# in the file drb/timeridconv.rb.  This implementation retains a local
+# reference to all objects exported over dRuby for a configurable
+# period of time (defaulting to ten minutes), to prevent them being
+# garbage-collected within this time.  Another sample implementation
+# is provided in sample/name.rb in the main dRuby distribution.  This
+# allows objects to specify their own id or "name".  A dRuby reference
+# can be made persistent across processes by having each process
+# register an object using the same dRuby name.
+#
+module DRb
+
+  # Superclass of all errors raised in the DRb module.
+  class DRbError < RuntimeError; end
+
+  # Error raised when an error occurs on the underlying communication
+  # protocol.
+  class DRbConnError < DRbError; end
+
+  # Class responsible for converting between an object and its id.
+  #
+  # This, the default implementation, uses an object's local ObjectSpace
+  # __id__ as its id.  This means that an object's identification over
+  # drb remains valid only while that object instance remains alive 
+  # within the server runtime.
+  #
+  # For alternative mechanisms, see DRb::TimerIdConv in rdb/timeridconv.rb
+  # and DRbNameIdConv in sample/name.rb in the full drb distribution.
+  class DRbIdConv
+
+    # Convert an object reference id to an object.
+    #
+    # This implementation looks up the reference id in the local object
+    # space and returns the object it refers to.
+    def to_obj(ref)
+      ObjectSpace._id2ref(ref)
+    end
+    
+    # Convert an object into a reference id.
+    #
+    # This implementation returns the object's __id__ in the local
+    # object space.
+    def to_id(obj)
+      obj.nil? ? nil : obj.__id__
+    end
+  end
+
+  # Mixin module making an object undumpable or unmarshallable.
+  #
+  # If an object which includes this module is returned by method
+  # called over drb, then the object remains in the server space
+  # and a reference to the object is returned, rather than the
+  # object being marshalled and moved into the client space.
+  module DRbUndumped 
+    def _dump(dummy)  # :nodoc:
+      raise TypeError, 'can\'t dump'
+    end
+  end
+
+  # Error raised by the DRb module when an attempt is made to refer to
+  # the context's current drb server but the context does not have one.
+  # See #current_server.
+  class DRbServerNotFound < DRbError; end
+
+  # Error raised by the DRbProtocol module when it cannot find any
+  # protocol implementation support the scheme specified in a URI.
+  class DRbBadURI < DRbError; end
+
+  # Error raised by a dRuby protocol when it doesn't support the
+  # scheme specified in a URI.  See DRb::DRbProtocol.
+  class DRbBadScheme < DRbError; end
+
+  # An exception wrapping a DRb::DRbUnknown object
+  class DRbUnknownError < DRbError
+
+    # Create a new DRbUnknownError for the DRb::DRbUnknown object +unknown+
+    def initialize(unknown)
+      @unknown = unknown
+      super(unknown.name)
+    end
+
+    # Get the wrapped DRb::DRbUnknown object.
+    attr_reader :unknown
+
+    def self._load(s)  # :nodoc:
+      Marshal::load(s)
+    end
+    
+    def _dump(lv) # :nodoc:
+      Marshal::dump(@unknown)
+    end
+  end
+
+  # An exception wrapping an error object
+  class DRbRemoteError < DRbError
+    def initialize(error)
+      @reason = error.class.to_s
+      super("#{error.message} (#{error.class})")
+      set_backtrace(error.backtrace)
+    end
+
+    # the class of the error, as a string.
+    attr_reader :reason
+  end
+
+  # Class wrapping a marshalled object whose type is unknown locally.
+  #
+  # If an object is returned by a method invoked over drb, but the
+  # class of the object is unknown in the client namespace, or
+  # the object is a constant unknown in the client namespace, then
+  # the still-marshalled object is returned wrapped in a DRbUnknown instance.
+  #
+  # If this object is passed as an argument to a method invoked over
+  # drb, then the wrapped object is passed instead.
+  #
+  # The class or constant name of the object can be read from the
+  # +name+ attribute.  The marshalled object is held in the +buf+
+  # attribute.
+  class DRbUnknown
+    
+    # Create a new DRbUnknown object.
+    #
+    # +buf+ is a string containing a marshalled object that could not
+    # be unmarshalled.  +err+ is the error message that was raised 
+    # when the unmarshalling failed.  It is used to determine the
+    # name of the unmarshalled object.
+    def initialize(err, buf)
+      case err.to_s
+      when /uninitialized constant (\S+)/
+	@name = $1
+      when /undefined class\/module (\S+)/
+	@name = $1
+      else
+	@name = nil
+      end
+      @buf = buf
+    end
+
+    # The name of the unknown thing.
+    #
+    # Class name for unknown objects; variable name for unknown
+    # constants.
+    attr_reader :name
+
+    # Buffer contained the marshalled, unknown object.
+    attr_reader :buf
+
+    def self._load(s) # :nodoc:
+      begin
+	Marshal::load(s)
+      rescue NameError, ArgumentError
+	DRbUnknown.new($!, s)
+      end
+    end
+
+    def _dump(lv) # :nodoc:
+      @buf
+    end
+
+    # Attempt to load the wrapped marshalled object again.
+    #
+    # If the class of the object is now known locally, the object
+    # will be unmarshalled and returned.  Otherwise, a new 
+    # but identical DRbUnknown object will be returned.
+    def reload
+      self.class._load(@buf)
+    end
+
+    # Create a DRbUnknownError exception containing this object.
+    def exception
+      DRbUnknownError.new(self)
+    end
+  end
+
+  class DRbArray
+    def initialize(ary)
+      @ary = ary.collect { |obj| 
+	if obj.kind_of? DRbUndumped
+	  DRbObject.new(obj)
+	else
+	  begin
+	    Marshal.dump(obj)
+	    obj
+	  rescue
+	    DRbObject.new(obj)
+	  end
+	end
+      }
+    end
+
+    def self._load(s)
+      Marshal::load(s)
+    end
+
+    def _dump(lv)
+      Marshal.dump(@ary)
+    end
+  end
+
+  # Handler for sending and receiving drb messages.
+  #
+  # This takes care of the low-level marshalling and unmarshalling
+  # of drb requests and responses sent over the wire between server
+  # and client.  This relieves the implementor of a new drb
+  # protocol layer with having to deal with these details.
+  #
+  # The user does not have to directly deal with this object in
+  # normal use.
+  class DRbMessage
+    def initialize(config) # :nodoc:
+      @load_limit = config[:load_limit]
+      @argc_limit = config[:argc_limit]
+    end
+
+    def dump(obj, error=false)  # :nodoc:
+      obj = make_proxy(obj, error) if obj.kind_of? DRbUndumped
+      begin
+	str = Marshal::dump(obj)
+      rescue
+	str = Marshal::dump(make_proxy(obj, error))
+      end
+      [str.size].pack('N') + str
+    end
+
+    def load(soc)  # :nodoc:
+      begin
+        sz = soc.read(4)	# sizeof (N)
+      rescue
+        raise(DRbConnError, $!.message, $!.backtrace)
+      end
+      raise(DRbConnError, 'connection closed') if sz.nil?
+      raise(DRbConnError, 'premature header') if sz.size < 4
+      sz = sz.unpack('N')[0]
+      raise(DRbConnError, "too large packet #{sz}") if @load_limit < sz
+      begin
+        str = soc.read(sz)
+      rescue
+        raise(DRbConnError, $!.message, $!.backtrace)
+      end
+      raise(DRbConnError, 'connection closed') if str.nil?
+      raise(DRbConnError, 'premature marshal format(can\'t read)') if str.size < sz
+      Thread.exclusive do
+        begin
+          save = Thread.current[:drb_untaint]
+          Thread.current[:drb_untaint] = []
+          Marshal::load(str)
+        rescue NameError, ArgumentError
+          DRbUnknown.new($!, str)
+        ensure
+          Thread.current[:drb_untaint].each do |x|
+            x.untaint
+          end
+          Thread.current[:drb_untaint] = save
+        end
+      end
+    end
+
+    def send_request(stream, ref, msg_id, arg, b) # :nodoc:
+      ary = []
+      ary.push(dump(ref.__drbref))
+      ary.push(dump(msg_id.id2name))
+      ary.push(dump(arg.length))
+      arg.each do |e|
+	ary.push(dump(e))
+      end
+      ary.push(dump(b))
+      stream.write(ary.join(''))
+    rescue
+      raise(DRbConnError, $!.message, $!.backtrace)
+    end
+    
+    def recv_request(stream) # :nodoc:
+      ref = load(stream)
+      ro = DRb.to_obj(ref)
+      msg = load(stream)
+      argc = load(stream)
+      raise ArgumentError, 'too many arguments' if @argc_limit < argc
+      argv = Array.new(argc, nil)
+      argc.times do |n|
+	argv[n] = load(stream)
+      end
+      block = load(stream)
+      return ro, msg, argv, block
+    end
+
+    def send_reply(stream, succ, result)  # :nodoc:
+      stream.write(dump(succ) + dump(result, !succ))
+    rescue
+      raise(DRbConnError, $!.message, $!.backtrace)
+    end
+
+    def recv_reply(stream)  # :nodoc:
+      succ = load(stream)
+      result = load(stream)
+      [succ, result]
+    end
+
+    private
+    def make_proxy(obj, error=false)
+      if error
+        DRbRemoteError.new(obj)
+      else
+        DRbObject.new(obj)
+      end
+    end
+  end
+
+  # Module managing the underlying network protocol(s) used by drb.
+  #
+  # By default, drb uses the DRbTCPSocket protocol.  Other protocols
+  # can be defined.  A protocol must define the following class methods:
+  #
+  #   [open(uri, config)] Open a client connection to the server at +uri+,
+  #                       using configuration +config+.  Return a protocol
+  #                       instance for this connection.
+  #   [open_server(uri, config)] Open a server listening at +uri+,
+  #                              using configuration +config+.  Return a
+  #                              protocol instance for this listener.
+  #   [uri_option(uri, config)] Take a URI, possibly containing an option
+  #                             component (e.g. a trailing '?param=val'), 
+  #                             and return a [uri, option] tuple.
+  #
+  # All of these methods should raise a DRbBadScheme error if the URI 
+  # does not identify the protocol they support (e.g. "druby:" for
+  # the standard Ruby protocol).  This is how the DRbProtocol module,
+  # given a URI, determines which protocol implementation serves that
+  # protocol.
+  #
+  # The protocol instance returned by #open_server must have the
+  # following methods:
+  #
+  # [accept] Accept a new connection to the server.  Returns a protocol
+  #          instance capable of communicating with the client.
+  # [close] Close the server connection.
+  # [uri] Get the URI for this server.
+  #
+  # The protocol instance returned by #open must have the following methods:
+  #
+  # [send_request (ref, msg_id, arg, b)] 
+  #      Send a request to +ref+ with the given message id and arguments.
+  #      This is most easily implemented by calling DRbMessage.send_request,
+  #      providing a stream that sits on top of the current protocol.
+  # [recv_reply]
+  #      Receive a reply from the server and return it as a [success-boolean,
+  #      reply-value] pair.  This is most easily implemented by calling
+  #      DRb.recv_reply, providing a stream that sits on top of the 
+  #      current protocol.
+  # [alive?]
+  #      Is this connection still alive?
+  # [close]
+  #      Close this connection.
+  #
+  # The protocol instance returned by #open_server().accept() must have
+  # the following methods:
+  #
+  # [recv_request]
+  #     Receive a request from the client and return a [object, message,
+  #     args, block] tuple.  This is most easily implemented by calling
+  #     DRbMessage.recv_request, providing a stream that sits on top of
+  #     the current protocol.
+  # [send_reply(succ, result)]
+  #     Send a reply to the client.  This is most easily implemented
+  #     by calling DRbMessage.send_reply, providing a stream that sits
+  #     on top of the current protocol.
+  # [close]
+  #     Close this connection.
+  #
+  # A new protocol is registered with the DRbProtocol module using
+  # the add_protocol method.
+  #
+  # For examples of other protocols, see DRbUNIXSocket in drb/unix.rb,
+  # and HTTP0 in sample/http0.rb and sample/http0serv.rb in the full
+  # drb distribution.
+  module DRbProtocol
+
+    # Add a new protocol to the DRbProtocol module.
+    def add_protocol(prot)
+      @protocol.push(prot)
+    end
+    module_function :add_protocol
+
+    # Open a client connection to +uri+ with the configuration +config+.
+    #
+    # The DRbProtocol module asks each registered protocol in turn to
+    # try to open the URI.  Each protocol signals that it does not handle that
+    # URI by raising a DRbBadScheme error.  If no protocol recognises the
+    # URI, then a DRbBadURI error is raised.  If a protocol accepts the
+    # URI, but an error occurs in opening it, a DRbConnError is raised.
+    def open(uri, config, first=true) 
+      @protocol.each do |prot|
+	begin
+	  return prot.open(uri, config)
+	rescue DRbBadScheme
+	rescue DRbConnError
+	  raise($!)
+	rescue
+	  raise(DRbConnError, "#{uri} - #{$!.inspect}")
+	end
+      end
+      if first && (config[:auto_load] != false)
+	auto_load(uri, config)
+	return open(uri, config, false)
+      end
+      raise DRbBadURI, 'can\'t parse uri:' + uri
+    end
+    module_function :open
+
+    # Open a server listening for connections at +uri+ with 
+    # configuration +config+.
+    #
+    # The DRbProtocol module asks each registered protocol in turn to
+    # try to open a server at the URI.  Each protocol signals that it does 
+    # not handle that URI by raising a DRbBadScheme error.  If no protocol 
+    # recognises the URI, then a DRbBadURI error is raised.  If a protocol 
+    # accepts the URI, but an error occurs in opening it, the underlying 
+    # error is passed on to the caller.
+    def open_server(uri, config, first=true)
+      @protocol.each do |prot|
+	begin
+	  return prot.open_server(uri, config)
+	rescue DRbBadScheme
+	end
+      end
+      if first && (config[:auto_load] != false)
+	auto_load(uri, config)
+	return open_server(uri, config, false)
+      end
+      raise DRbBadURI, 'can\'t parse uri:' + uri
+    end
+    module_function :open_server
+
+    # Parse +uri+ into a [uri, option] pair.
+    #
+    # The DRbProtocol module asks each registered protocol in turn to
+    # try to parse the URI.  Each protocol signals that it does not handle that
+    # URI by raising a DRbBadScheme error.  If no protocol recognises the
+    # URI, then a DRbBadURI error is raised.  
+    def uri_option(uri, config, first=true)
+      @protocol.each do |prot|
+	begin
+	  uri, opt = prot.uri_option(uri, config)
+	  # opt = nil if opt == ''
+	  return uri, opt
+	rescue DRbBadScheme
+	end
+      end
+      if first && (config[:auto_load] != false)
+	auto_load(uri, config)
+        return uri_option(uri, config, false)
+      end
+      raise DRbBadURI, 'can\'t parse uri:' + uri
+    end
+    module_function :uri_option
+
+    def auto_load(uri, config)  # :nodoc:
+      if uri =~ /^drb([a-z0-9]+):/
+	require("drb/#{$1}") rescue nil
+      end
+    end
+    module_function :auto_load
+  end
+
+  # The default drb protocol.
+  #
+  # Communicates over a TCP socket.
+  class DRbTCPSocket
+    private
+    def self.parse_uri(uri)
+      if uri =~ /^druby:\/\/(.*?):(\d+)(\?(.*))?$/
+	host = $1
+	port = $2.to_i
+	option = $4
+	[host, port, option]
+      else
+	raise(DRbBadScheme, uri) unless uri =~ /^druby:/
+	raise(DRbBadURI, 'can\'t parse uri:' + uri)
+      end
+    end
+
+    public
+
+    # Open a client connection to +uri+ using configuration +config+.
+    def self.open(uri, config)
+      host, port, option = parse_uri(uri)
+      host.untaint
+      port.untaint
+      soc = TCPSocket.open(host, port)
+      self.new(uri, soc, config)
+    end
+
+    def self.getservername
+      host = Socket::gethostname
+      begin
+        Socket::gethostbyname(host)[0]
+      rescue
+        'localhost'
+      end
+    end
+
+    def self.open_server_inaddr_any(host, port)
+      infos = Socket::getaddrinfo(host, nil, 
+                                  Socket::AF_UNSPEC,
+                                  Socket::SOCK_STREAM, 
+                                  0,
+                                  Socket::AI_PASSIVE)
+      family = infos.collect { |af, *_| af }.uniq
+      case family
+      when ['AF_INET']
+        return TCPServer.open('0.0.0.0', port)
+      when ['AF_INET6']
+        return TCPServer.open('::', port)
+      else
+        return TCPServer.open(port)
+      end
+    end
+
+    # Open a server listening for connections at +uri+ using 
+    # configuration +config+.
+    def self.open_server(uri, config)
+      uri = 'druby://:0' unless uri
+      host, port, opt = parse_uri(uri)
+      if host.size == 0
+        host = getservername
+        soc = open_server_inaddr_any(host, port)
+      else
+	soc = TCPServer.open(host, port)
+      end
+      port = soc.addr[1] if port == 0
+      uri = "druby://#{host}:#{port}"
+      self.new(uri, soc, config)
+    end
+
+    # Parse +uri+ into a [uri, option] pair.
+    def self.uri_option(uri, config)
+      host, port, option = parse_uri(uri)
+      return "druby://#{host}:#{port}", option
+    end
+
+    # Create a new DRbTCPSocket instance.
+    #
+    # +uri+ is the URI we are connected to.
+    # +soc+ is the tcp socket we are bound to.  +config+ is our
+    # configuration.
+    def initialize(uri, soc, config={})
+      @uri = uri
+      @socket = soc
+      @config = config
+      @acl = config[:tcp_acl]
+      @msg = DRbMessage.new(config)
+      set_sockopt(@socket)
+    end
+
+    # Get the URI that we are connected to.
+    attr_reader :uri
+
+    # Get the address of our TCP peer (the other end of the socket
+    # we are bound to.
+    def peeraddr
+      @socket.peeraddr
+    end
+    
+    # Get the socket.
+    def stream; @socket; end
+
+    # On the client side, send a request to the server.
+    def send_request(ref, msg_id, arg, b)
+      @msg.send_request(stream, ref, msg_id, arg, b)
+    end
+    
+    # On the server side, receive a request from the client.
+    def recv_request
+      @msg.recv_request(stream)
+    end
+
+    # On the server side, send a reply to the client.
+    def send_reply(succ, result)
+      @msg.send_reply(stream, succ, result)
+    end
+
+    # On the client side, receive a reply from the server.
+    def recv_reply
+      @msg.recv_reply(stream)
+    end
+
+    public
+
+    # Close the connection.
+    #
+    # If this is an instance returned by #open_server, then this stops
+    # listening for new connections altogether.  If this is an instance
+    # returned by #open or by #accept, then it closes this particular
+    # client-server session.
+    def close
+      if @socket
+	@socket.close
+	@socket = nil
+      end
+    end
+    
+    # On the server side, for an instance returned by #open_server, 
+    # accept a client connection and return a new instance to handle
+    # the server's side of this client-server session.
+    def accept
+      while true
+	s = @socket.accept
+	break if (@acl ? @acl.allow_socket?(s) : true) 
+	s.close
+      end
+      self.class.new(nil, s, @config)
+    end
+
+    # Check to see if this connection is alive.
+    def alive?
+      return false unless @socket
+      if IO.select([@socket], nil, nil, 0)
+	close
+	return false
+      end
+      true
+    end
+
+    def set_sockopt(soc) # :nodoc:
+      soc.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
+      soc.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::FD_CLOEXEC
+    end
+  end
+
+  module DRbProtocol
+    @protocol = [DRbTCPSocket] # default
+  end
+
+  class DRbURIOption  # :nodoc:  I don't understand the purpose of this class...
+    def initialize(option)
+      @option = option.to_s
+    end
+    attr :option
+    def to_s; @option; end
+    
+    def ==(other)
+      return false unless DRbURIOption === other
+      @option == other.option
+    end
+    
+    def hash
+      @option.hash
+    end
+    
+    alias eql? ==
+  end
+
+  # Object wrapping a reference to a remote drb object.
+  #
+  # Method calls on this object are relayed to the remote
+  # object that this object is a stub for.
+  class DRbObject
+
+    # Unmarshall a marshalled DRbObject.
+    #
+    # If the referenced object is located within the local server, then
+    # the object itself is returned.  Otherwise, a new DRbObject is
+    # created to act as a stub for the remote referenced object.
+    def self._load(s)
+      uri, ref = Marshal.load(s)
+      
+      if DRb.here?(uri)
+	obj = DRb.to_obj(ref)
+        if ((! obj.tainted?) && Thread.current[:drb_untaint])
+          Thread.current[:drb_untaint].push(obj)
+        end
+        return obj
+      end
+
+      self.new_with(uri, ref)
+    end
+
+    def self.new_with(uri, ref)
+      it = self.allocate
+      it.instance_variable_set('@uri', uri)
+      it.instance_variable_set('@ref', ref)
+      it
+    end
+
+    # Create a new DRbObject from a URI alone.
+    def self.new_with_uri(uri)
+      self.new(nil, uri)
+    end
+
+    # Marshall this object.
+    #
+    # The URI and ref of the object are marshalled.
+    def _dump(lv)
+      Marshal.dump([@uri, @ref])
+    end
+
+    # Create a new remote object stub.
+    #
+    # +obj+ is the (local) object we want to create a stub for.  Normally
+    # this is +nil+.  +uri+ is the URI of the remote object that this
+    # will be a stub for.
+    def initialize(obj, uri=nil)
+      @uri = nil
+      @ref = nil
+      if obj.nil?
+	return if uri.nil?
+	@uri, option = DRbProtocol.uri_option(uri, DRb.config)
+	@ref = DRbURIOption.new(option) unless option.nil?
+      else
+	@uri = uri ? uri : (DRb.uri rescue nil)
+	@ref = obj ? DRb.to_id(obj) : nil
+      end
+    end
+
+    # Get the URI of the remote object.
+    def __drburi 
+      @uri
+    end
+
+    # Get the reference of the object, if local.
+    def __drbref
+      @ref
+    end
+
+    undef :to_s
+    undef :to_a if respond_to?(:to_a)
+
+    def respond_to?(msg_id, priv=false)
+      case msg_id
+      when :_dump
+        true
+      when :marshal_dump
+        false
+      else
+        method_missing(:respond_to?, msg_id, priv)
+      end
+    end
+
+    # Routes method calls to the referenced object.
+    def method_missing(msg_id, *a, &b)
+      if DRb.here?(@uri)
+	obj = DRb.to_obj(@ref)
+	DRb.current_server.check_insecure_method(obj, msg_id)
+	return obj.__send__(msg_id, *a, &b) 
+      end
+
+      succ, result = self.class.with_friend(@uri) do
+        DRbConn.open(@uri) do |conn|
+          conn.send_message(self, msg_id, a, b)
+        end
+      end
+
+      if succ
+        return result
+      elsif DRbUnknown === result
+        raise result
+      else
+        bt = self.class.prepare_backtrace(@uri, result)
+	result.set_backtrace(bt + caller)
+        raise result
+      end
+    end
+
+    def self.with_friend(uri)
+      friend = DRb.fetch_server(uri)
+      return yield() unless friend
+      
+      save = Thread.current['DRb']
+      Thread.current['DRb'] = { 'server' => friend }
+      return yield
+    ensure
+      Thread.current['DRb'] = save if friend
+    end
+
+    def self.prepare_backtrace(uri, result)
+      prefix = "(#{uri}) "
+      bt = []
+      result.backtrace.each do |x|
+        break if /`__send__'$/ =~ x 
+        if /^\(druby:\/\// =~ x
+          bt.push(x)
+        else
+          bt.push(prefix + x)
+        end
+      end
+      bt
+    end
+
+    def pretty_print(q)   # :nodoc:
+      q.pp_object(self)
+    end
+
+    def pretty_print_cycle(q)   # :nodoc:
+      q.object_address_group(self) {
+        q.breakable
+        q.text '...'
+      }
+    end
+  end
+
+  # Class handling the connection between a DRbObject and the
+  # server the real object lives on.
+  #
+  # This class maintains a pool of connections, to reduce the
+  # overhead of starting and closing down connections for each
+  # method call.
+  #
+  # This class is used internally by DRbObject.  The user does
+  # not normally need to deal with it directly.
+  class DRbConn
+    POOL_SIZE = 16  # :nodoc:
+    @mutex = Mutex.new
+    @pool = []
+
+    def self.open(remote_uri)  # :nodoc:
+      begin
+	conn = nil
+
+	@mutex.synchronize do
+	  #FIXME
+	  new_pool = []
+	  @pool.each do |c|
+	    if conn.nil? and c.uri == remote_uri
+	      conn = c if c.alive?
+	    else
+	      new_pool.push c
+	    end
+	  end
+	  @pool = new_pool
+	end
+
+	conn = self.new(remote_uri) unless conn
+	succ, result = yield(conn)
+	return succ, result
+
+      ensure
+	if conn
+	  if succ
+	    @mutex.synchronize do
+	      @pool.unshift(conn)
+	      @pool.pop.close while @pool.size > POOL_SIZE
+	    end
+	  else
+	    conn.close
+	  end
+	end
+      end
+    end
+
+    def initialize(remote_uri)  # :nodoc:
+      @uri = remote_uri
+      @protocol = DRbProtocol.open(remote_uri, DRb.config)
+    end
+    attr_reader :uri  # :nodoc:
+
+    def send_message(ref, msg_id, arg, block)  # :nodoc:
+      @protocol.send_request(ref, msg_id, arg, block)
+      @protocol.recv_reply
+    end
+
+    def close  # :nodoc:
+      @protocol.close
+      @protocol = nil
+    end
+
+    def alive?  # :nodoc:
+      @protocol.alive?
+    end
+  end
+
+  # Class representing a drb server instance.
+  #
+  # A DRbServer must be running in the local process before any incoming
+  # dRuby calls can be accepted, or any local objects can be passed as
+  # dRuby references to remote processes, even if those local objects are
+  # never actually called remotely. You do not need to start a DRbServer
+  # in the local process if you are only making outgoing dRuby calls
+  # passing marshalled parameters.
+  #
+  # Unless multiple servers are being used, the local DRbServer is normally
+  # started by calling DRb.start_service.
+  class DRbServer
+    @@acl = nil
+    @@idconv = DRbIdConv.new
+    @@secondary_server = nil
+    @@argc_limit = 256
+    @@load_limit = 256 * 102400
+    @@verbose = false
+    @@safe_level = 0
+
+    # Set the default value for the :argc_limit option.
+    #
+    # See #new().  The initial default value is 256.
+    def self.default_argc_limit(argc)
+      @@argc_limit = argc
+    end
+
+    # Set the default value for the :load_limit option.
+    #
+    # See #new().  The initial default value is 25 MB.
+    def self.default_load_limit(sz)
+      @@load_limit = sz
+    end
+
+    # Set the default value for the :acl option.
+    #
+    # See #new().  The initial default value is nil.
+    def self.default_acl(acl)
+      @@acl = acl
+    end
+
+    # Set the default value for the :id_conv option.
+    #
+    # See #new().  The initial default value is a DRbIdConv instance.
+    def self.default_id_conv(idconv)
+      @@idconv = idconv
+    end
+
+    def self.default_safe_level(level)
+      @@safe_level = level
+    end
+
+    # Set the default value of the :verbose option.
+    #
+    # See #new().  The initial default value is false.
+    def self.verbose=(on)
+      @@verbose = on
+    end
+    
+    # Get the default value of the :verbose option.
+    def self.verbose
+      @@verbose
+    end
+
+    def self.make_config(hash={})  # :nodoc:
+      default_config = { 
+	:idconv => @@idconv,
+	:verbose => @@verbose,
+	:tcp_acl => @@acl,
+	:load_limit => @@load_limit,
+	:argc_limit => @@argc_limit,
+        :safe_level => @@safe_level
+      }
+      default_config.update(hash)
+    end
+
+    # Create a new DRbServer instance.
+    #
+    # +uri+ is the URI to bind to.  This is normally of the form
+    # 'druby://<hostname>:<port>' where <hostname> is a hostname of
+    # the local machine.  If nil, then the system's default hostname
+    # will be bound to, on a port selected by the system; these value
+    # can be retrieved from the +uri+ attribute.  'druby:' specifies
+    # the default dRuby transport protocol: another protocol, such
+    # as 'drbunix:', can be specified instead.
+    #
+    # +front+ is the front object for the server, that is, the object
+    # to which remote method calls on the server will be passed.  If
+    # nil, then the server will not accept remote method calls.
+    #
+    # If +config_or_acl+ is a hash, it is the configuration to
+    # use for this server.  The following options are recognised:
+    #
+    # :idconv :: an id-to-object conversion object.  This defaults
+    #            to an instance of the class DRb::DRbIdConv.
+    # :verbose :: if true, all unsuccessful remote calls on objects
+    #             in the server will be logged to $stdout. false
+    #             by default.
+    # :tcp_acl :: the access control list for this server.  See
+    #             the ACL class from the main dRuby distribution.
+    # :load_limit :: the maximum message size in bytes accepted by
+    #                the server.  Defaults to 25 MB (26214400).
+    # :argc_limit :: the maximum number of arguments to a remote
+    #                method accepted by the server.  Defaults to
+    #                256.
+    #
+    # The default values of these options can be modified on
+    # a class-wide basis by the class methods #default_argc_limit,
+    # #default_load_limit, #default_acl, #default_id_conv,
+    # and #verbose=
+    #
+    # If +config_or_acl+ is not a hash, but is not nil, it is
+    # assumed to be the access control list for this server.
+    # See the :tcp_acl option for more details.
+    #
+    # If no other server is currently set as the primary server,
+    # this will become the primary server.
+    #
+    # The server will immediately start running in its own thread.
+    def initialize(uri=nil, front=nil, config_or_acl=nil)
+      if Hash === config_or_acl
+	config = config_or_acl.dup
+      else
+	acl = config_or_acl || @@acl
+	config = {
+	  :tcp_acl => acl
+	}
+      end
+
+      @config = self.class.make_config(config)
+
+      @protocol = DRbProtocol.open_server(uri, @config)
+      @uri = @protocol.uri
+
+      @front = front
+      @idconv = @config[:idconv]
+      @safe_level = @config[:safe_level]
+
+      @grp = ThreadGroup.new
+      @thread = run
+
+      DRb.regist_server(self)
+    end
+
+    # The URI of this DRbServer.
+    attr_reader :uri
+
+    # The main thread of this DRbServer.
+    #
+    # This is the thread that listens for and accepts connections
+    # from clients, not that handles each client's request-response
+    # session.
+    attr_reader :thread
+
+    # The front object of the DRbServer.
+    # 
+    # This object receives remote method calls made on the server's
+    # URI alone, with an object id.
+    attr_reader :front
+
+    # The configuration of this DRbServer
+    attr_reader :config
+
+    attr_reader :safe_level
+
+    # Set whether to operate in verbose mode.
+    #
+    # In verbose mode, failed calls are logged to stdout.
+    def verbose=(v); @config[:verbose]=v; end
+
+    # Get whether the server is in verbose mode.
+    #
+    # In verbose mode, failed calls are logged to stdout.
+    def verbose; @config[:verbose]; end
+
+    # Is this server alive?
+    def alive?
+      @thread.alive?
+    end
+
+    # Stop this server.
+    def stop_service
+      DRb.remove_server(self)
+      if  Thread.current['DRb'] && Thread.current['DRb']['server'] == self
+        Thread.current['DRb']['stop_service'] = true
+      else
+        @thread.kill
+      end
+    end
+
+    # Convert a dRuby reference to the local object it refers to.
+    def to_obj(ref)
+      return front if ref.nil?
+      return front[ref.to_s] if DRbURIOption === ref
+      @idconv.to_obj(ref)
+    end
+
+    # Convert a local object to a dRuby reference.
+    def to_id(obj)
+      return nil if obj.__id__ == front.__id__
+      @idconv.to_id(obj)
+    end
+
+    private
+    def kill_sub_thread
+      Thread.new do
+	grp = ThreadGroup.new
+	grp.add(Thread.current)
+	list = @grp.list
+	while list.size > 0
+	  list.each do |th|
+	    th.kill if th.alive?
+	  end
+	  list = @grp.list
+	end
+      end
+    end
+
+    def run
+      Thread.start do
+	begin
+	  while true
+	    main_loop
+	  end
+	ensure
+	  @protocol.close if @protocol
+	  kill_sub_thread
+	end
+      end
+    end
+
+    # List of insecure methods.
+    #
+    # These methods are not callable via dRuby.
+    INSECURE_METHOD = [
+      :__send__
+    ]
+
+    # Has a method been included in the list of insecure methods?
+    def insecure_method?(msg_id)
+      INSECURE_METHOD.include?(msg_id)
+    end
+
+    # Coerce an object to a string, providing our own representation if
+    # to_s is not defined for the object.
+    def any_to_s(obj)
+      obj.to_s + ":#{obj.class}"
+    rescue
+      sprintf("#<%s:0x%lx>", obj.class, obj.__id__)      
+    end
+
+    # Check that a method is callable via dRuby.
+    #
+    # +obj+ is the object we want to invoke the method on. +msg_id+ is the
+    # method name, as a Symbol.
+    #
+    # If the method is an insecure method (see #insecure_method?) a 
+    # SecurityError is thrown.  If the method is private or undefined,
+    # a NameError is thrown.
+    def check_insecure_method(obj, msg_id)
+      return true if Proc === obj && msg_id == :__drb_yield
+      raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class
+      raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id)
+      
+      if obj.private_methods.include?(msg_id.to_s)
+	desc = any_to_s(obj)
+        raise NoMethodError, "private method `#{msg_id}' called for #{desc}"
+      elsif obj.protected_methods.include?(msg_id.to_s)
+	desc = any_to_s(obj)
+        raise NoMethodError, "protected method `#{msg_id}' called for #{desc}"
+      else
+        true
+      end
+    end
+    public :check_insecure_method
+    
+    class InvokeMethod  # :nodoc:
+      def initialize(drb_server, client)
+	@drb_server = drb_server
+        @safe_level = drb_server.safe_level
+	@client = client
+      end
+
+      def perform
+	@result = nil
+	@succ = false
+	setup_message
+
+        if $SAFE < @safe_level
+          info = Thread.current['DRb']
+          if @block
+            @result = Thread.new {
+              Thread.current['DRb'] = info
+              $SAFE = @safe_level
+              perform_with_block
+            }.value
+          else
+            @result = Thread.new { 
+              Thread.current['DRb'] = info
+              $SAFE = @safe_level
+              perform_without_block
+            }.value
+          end
+        else
+          if @block
+            @result = perform_with_block
+          else
+            @result = perform_without_block
+          end
+        end
+	@succ = true
+	if @msg_id == :to_ary && @result.class == Array
+	  @result = DRbArray.new(@result) 
+	end
+	return @succ, @result
+      rescue StandardError, ScriptError, Interrupt
+	@result = $!
+	return @succ, @result
+      end
+
+      private
+      def init_with_client
+	obj, msg, argv, block = @client.recv_request
+        @obj = obj
+        @msg_id = msg.intern
+        @argv = argv
+        @block = block
+      end
+      
+      def check_insecure_method
+        @drb_server.check_insecure_method(@obj, @msg_id)
+      end
+
+      def setup_message
+	init_with_client
+	check_insecure_method
+      end
+      
+      def perform_without_block
+	if Proc === @obj && @msg_id == :__drb_yield
+          if @argv.size == 1
+	    ary = @argv
+	  else
+	    ary = [@argv]
+	  end
+	  ary.collect(&@obj)[0]
+	else
+	  @obj.__send__(@msg_id, *@argv)
+	end
+      end
+
+    end
+
+    if RUBY_VERSION >= '1.8'
+      require 'drb/invokemethod'
+      class InvokeMethod
+        include InvokeMethod18Mixin
+      end
+    else
+      require 'drb/invokemethod16'
+      class InvokeMethod
+        include InvokeMethod16Mixin
+      end
+    end
+
+    # The main loop performed by a DRbServer's internal thread.
+    #
+    # Accepts a connection from a client, and starts up its own
+    # thread to handle it.  This thread loops, receiving requests
+    # from the client, invoking them on a local object, and
+    # returning responses, until the client closes the connection
+    # or a local method call fails.
+    def main_loop
+      Thread.start(@protocol.accept) do |client|
+	@grp.add Thread.current
+	Thread.current['DRb'] = { 'client' => client ,
+	                          'server' => self }
+	loop do
+	  begin
+	    succ = false
+	    invoke_method = InvokeMethod.new(self, client)
+	    succ, result = invoke_method.perform
+	    if !succ && verbose
+	      p result
+	      result.backtrace.each do |x|
+		puts x
+	      end
+	    end
+	    client.send_reply(succ, result) rescue nil
+	  ensure
+            client.close unless succ
+            if Thread.current['DRb']['stop_service']
+              Thread.new { stop_service }
+            end
+            break unless succ
+	  end
+	end
+      end
+    end
+  end
+
+  @primary_server = nil
+
+  # Start a dRuby server locally.
+  #
+  # The new dRuby server will become the primary server, even
+  # if another server is currently the primary server.
+  #
+  # +uri+ is the URI for the server to bind to.  If nil,
+  # the server will bind to random port on the default local host
+  # name and use the default dRuby protocol.
+  #
+  # +front+ is the server's front object.  This may be nil.
+  #
+  # +config+ is the configuration for the new server.  This may
+  # be nil.
+  #
+  # See DRbServer::new.
+  def start_service(uri=nil, front=nil, config=nil)
+    @primary_server = DRbServer.new(uri, front, config)
+  end
+  module_function :start_service
+
+  # The primary local dRuby server.
+  #
+  # This is the server created by the #start_service call.  
+  attr_accessor :primary_server
+  module_function :primary_server=, :primary_server
+
+  # Get the 'current' server.
+  #
+  # In the context of execution taking place within the main
+  # thread of a dRuby server (typically, as a result of a remote
+  # call on the server or one of its objects), the current
+  # server is that server.  Otherwise, the current server is
+  # the primary server.
+  #
+  # If the above rule fails to find a server, a DRbServerNotFound
+  # error is raised.
+  def current_server
+    drb = Thread.current['DRb'] 
+    server = (drb && drb['server']) ? drb['server'] : @primary_server 
+    raise DRbServerNotFound unless server
+    return server
+  end
+  module_function :current_server
+
+  # Stop the local dRuby server.
+  #
+  # This operates on the primary server.  If there is no primary
+  # server currently running, it is a noop.
+  def stop_service
+    @primary_server.stop_service if @primary_server
+    @primary_server = nil
+  end
+  module_function :stop_service
+
+  # Get the URI defining the local dRuby space.
+  #
+  # This is the URI of the current server.  See #current_server.
+  def uri
+    current_server.uri
+  end
+  module_function :uri
+
+  # Is +uri+ the URI for the current local server?
+  def here?(uri)
+    (current_server.uri rescue nil) == uri
+  end
+  module_function :here?
+
+  # Get the configuration of the current server.
+  #
+  # If there is no current server, this returns the default configuration.
+  # See #current_server and DRbServer::make_config.
+  def config
+    current_server.config
+  rescue
+    DRbServer.make_config
+  end
+  module_function :config
+  
+  # Get the front object of the current server.
+  #
+  # This raises a DRbServerNotFound error if there is no current server.
+  # See #current_server.
+  def front
+    current_server.front
+  end
+  module_function :front
+
+  # Convert a reference into an object using the current server.
+  #
+  # This raises a DRbServerNotFound error if there is no current server.
+  # See #current_server.
+  def to_obj(ref)
+    current_server.to_obj(ref)
+  end
+
+  # Get a reference id for an object using the current server.
+  #
+  # This raises a DRbServerNotFound error if there is no current server.
+  # See #current_server.
+  def to_id(obj)
+    current_server.to_id(obj)
+  end
+  module_function :to_id
+  module_function :to_obj
+
+  # Get the thread of the primary server.
+  #
+  # This returns nil if there is no primary server.  See #primary_server.
+  def thread
+    @primary_server ? @primary_server.thread : nil
+  end
+  module_function :thread
+
+  # Set the default id conv object.
+  #
+  # See DRbServer#default_id_conv.
+  def install_id_conv(idconv)
+    DRbServer.default_id_conv(idconv)
+  end
+  module_function :install_id_conv
+
+  # Set the default acl.
+  #
+  # See DRb::DRbServer.default_acl.
+  def install_acl(acl)
+    DRbServer.default_acl(acl)
+  end
+  module_function :install_acl
+
+  @server = {}
+  def regist_server(server)
+    @server[server.uri] = server
+    Thread.exclusive do
+      @primary_server = server unless @primary_server
+    end
+  end
+  module_function :regist_server
+
+  def remove_server(server)
+    @server.delete(server.uri)
+  end
+  module_function :remove_server
+  
+  def fetch_server(uri)
+    @server[uri]
+  end
+  module_function :fetch_server
+end
+
+DRbObject = DRb::DRbObject
+DRbUndumped = DRb::DRbUndumped
+DRbIdConv = DRb::DRbIdConv
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/eq.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/eq.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/eq.rb	(revision 18425)
@@ -0,0 +1,16 @@
+require 'drb/drb'
+
+module DRb
+  class DRbObject
+    def ==(other)
+      return false unless DRbObject === other
+     (@ref == other.__drbref) && (@uri == other.__drburi)
+    end
+
+    def hash
+      [@uri, @ref].hash
+    end
+
+    alias eql? ==
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/extserv.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/extserv.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/extserv.rb	(revision 18425)
@@ -0,0 +1,64 @@
+=begin
+ external service
+ 	Copyright (c) 2000,2002 Masatoshi SEKI 
+=end
+
+require 'drb/drb'
+
+module DRb
+  class ExtServ
+    include DRbUndumped
+
+    def initialize(there, name, server=nil)
+      @server = server || DRb::primary_server
+      @name = name
+      ro = DRbObject.new(nil, there)
+      @invoker = ro.regist(name, DRbObject.new(self, @server.uri))
+    end
+    attr_reader :server
+
+    def front
+      DRbObject.new(nil, @server.uri)
+    end
+
+    def stop_service
+      @invoker.unregist(@name)
+      server = @server
+      @server = nil
+      server.stop_service
+      true
+    end
+
+    def alive?
+      @server ? @server.alive? : false
+    end
+  end
+end
+
+if __FILE__ == $0
+  class Foo
+    include DRbUndumped
+
+    def initialize(str)
+      @str = str
+    end
+
+    def hello(it)
+      "#{it}: #{self}"
+    end
+
+    def to_s
+      @str
+    end
+  end
+
+  cmd = ARGV.shift
+  case cmd
+  when 'itest1', 'itest2'
+    front = Foo.new(cmd)
+    manager = DRb::DRbServer.new(nil, front)
+    es = DRb::ExtServ.new(ARGV.shift, ARGV.shift, manager)
+    es.server.thread.join
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/extservm.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/extservm.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/extservm.rb	(revision 18425)
@@ -0,0 +1,96 @@
+=begin
+ external service manager
+ 	Copyright (c) 2000 Masatoshi SEKI 
+=end
+
+require 'drb/drb'
+require 'thread'
+
+module DRb
+  class ExtServManager
+    include DRbUndumped
+
+    @@command = {}
+
+    def self.command
+      @@command
+    end
+
+    def self.command=(cmd)
+      @@command = cmd
+    end
+      
+    def initialize
+      @servers = {}
+      @waiting = []
+      @queue = Queue.new
+      @thread = invoke_thread
+      @uri = nil
+    end
+    attr_accessor :uri
+
+    def service(name)
+      while true
+	server = nil
+	Thread.exclusive do
+	  server = @servers[name] if @servers[name]
+	end
+	return server if server && server.alive?
+	invoke_service(name)
+      end
+    end
+
+    def regist(name, ro)
+      ary = nil
+      Thread.exclusive do
+	@servers[name] = ro
+	ary = @waiting
+	@waiting = []
+      end
+      ary.each do |th|
+	begin
+	  th.run
+	rescue ThreadError
+	end
+      end
+      self
+    end
+    
+    def unregist(name)
+      Thread.exclusive do
+	@servers.delete(name)
+      end
+    end
+
+    private
+    def invoke_thread
+      Thread.new do
+	while true
+	  name = @queue.pop
+	  invoke_service_command(name, @@command[name])
+	end
+      end
+    end
+
+    def invoke_service(name)
+      Thread.critical = true
+      @waiting.push Thread.current
+      @queue.push name
+      Thread.stop
+    end
+
+    def invoke_service_command(name, command)
+      raise "invalid command. name: #{name}" unless command
+      Thread.exclusive do
+	return if @servers.include?(name)
+	@servers[name] = false
+      end
+      uri = @uri || DRb.uri
+      if RUBY_PLATFORM =~ /mswin32/ && /NT/ =~ ENV["OS"]
+        system(%Q'cmd /c start "ruby" /b #{command} #{uri} #{name}')
+      else
+	system("#{command} #{uri} #{name} &")
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/gw.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/gw.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/gw.rb	(revision 18425)
@@ -0,0 +1,122 @@
+require 'drb/drb'
+require 'monitor'
+
+module DRb
+  class GWIdConv < DRbIdConv
+    def to_obj(ref)
+      if Array === ref && ref[0] == :DRbObject
+        return DRbObject.new_with(ref[1], ref[2])
+      end
+      super(ref)
+    end
+  end
+
+  class GW
+    include MonitorMixin
+    def initialize
+      super()
+      @hash = {}
+    end
+
+    def [](key)
+      synchronize do
+        @hash[key]
+      end
+    end
+
+    def []=(key, v)
+      synchronize do
+        @hash[key] = v
+      end
+    end
+  end
+
+  class DRbObject
+    def self._load(s)
+      uri, ref = Marshal.load(s)
+      if DRb.uri == uri
+        return ref ? DRb.to_obj(ref) : DRb.front
+      end
+
+      self.new_with(DRb.uri, [:DRbObject, uri, ref])
+    end
+
+    def _dump(lv)
+      if DRb.uri == @uri
+        if Array === @ref && @ref[0] == :DRbObject
+          Marshal.dump([@ref[1], @ref[2]])
+        else
+          Marshal.dump([@uri, @ref]) # ??
+        end
+      else
+        Marshal.dump([DRb.uri, [:DRbObject, @uri, @ref]])
+      end
+    end
+  end
+end
+
+=begin
+DRb.install_id_conv(DRb::GWIdConv.new)
+
+front = DRb::GW.new
+
+s1 = DRb::DRbServer.new('drbunix:/tmp/gw_b_a', front)
+s2 = DRb::DRbServer.new('drbunix:/tmp/gw_b_c', front)
+
+s1.thread.join
+s2.thread.join
+=end
+
+=begin
+# foo.rb
+
+require 'drb/drb'
+
+class Foo
+  include DRbUndumped
+  def initialize(name, peer=nil)
+    @name = name
+    @peer = peer
+  end
+
+  def ping(obj)
+    puts "#{@name}: ping: #{obj.inspect}"
+    @peer.ping(self) if @peer
+  end
+end
+=end
+
+=begin
+# gw_a.rb
+require 'drb/unix'
+require 'foo'
+
+obj = Foo.new('a')
+DRb.start_service("drbunix:/tmp/gw_a", obj)
+
+robj = DRbObject.new_with_uri('drbunix:/tmp/gw_b_a')
+robj[:a] = obj
+
+DRb.thread.join
+=end
+
+=begin
+# gw_c.rb
+require 'drb/unix'
+require 'foo'
+
+foo = Foo.new('c', nil)
+
+DRb.start_service("drbunix:/tmp/gw_c", nil)
+
+robj = DRbObject.new_with_uri("drbunix:/tmp/gw_b_c")
+
+puts "c->b"
+a = robj[:a]
+sleep 2
+
+a.ping(foo)
+
+DRb.thread.join
+=end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/invokemethod.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/invokemethod.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/invokemethod.rb	(revision 18425)
@@ -0,0 +1,36 @@
+# for ruby-1.8.0
+
+module DRb
+  class DRbServer
+    module InvokeMethod18Mixin
+      def block_yield(x)
+	if x.size == 1 && x[0].class == Array
+	  x[0] = DRbArray.new(x[0])
+	end
+        block_value = @block.call(*x)
+      end
+      
+      def perform_with_block
+        @obj.__send__(@msg_id, *@argv) do |*x|
+          jump_error = nil
+          begin
+            block_value = block_yield(x)
+          rescue LocalJumpError
+            jump_error = $!
+          end
+          if jump_error
+            case jump_error.reason
+            when :retry
+              retry
+            when :break
+              break(jump_error.exit_value)
+            else
+              raise jump_error
+            end
+          end
+          block_value
+        end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/observer.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/observer.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/observer.rb	(revision 18425)
@@ -0,0 +1,22 @@
+require 'observer'
+
+module DRb
+  module DRbObservable
+    include Observable
+
+    def notify_observers(*arg)
+      if defined? @observer_state and @observer_state
+	if defined? @observer_peers
+	  for i in @observer_peers.dup
+	    begin
+	      i.update(*arg)
+	    rescue
+	      delete_observer(i)
+	    end
+	  end
+	end
+	@observer_state = false
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/ssl.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/ssl.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/ssl.rb	(revision 18425)
@@ -0,0 +1,190 @@
+require 'socket'
+require 'openssl'
+require 'drb/drb'
+require 'singleton'
+
+module DRb
+
+  class DRbSSLSocket < DRbTCPSocket
+
+    class SSLConfig
+
+      DEFAULT = {
+	:SSLCertificate       => nil,
+	:SSLPrivateKey        => nil,
+	:SSLClientCA          => nil,
+	:SSLCACertificatePath => nil,
+	:SSLCACertificateFile => nil,
+	:SSLVerifyMode        => ::OpenSSL::SSL::VERIFY_NONE, 
+	:SSLVerifyDepth       => nil,
+	:SSLVerifyCallback    => nil,   # custom verification
+        :SSLCertificateStore  => nil,
+	# Must specify if you use auto generated certificate.
+	:SSLCertName          => nil,   # e.g. [["CN","fqdn.example.com"]]
+	:SSLCertComment       => "Generated by Ruby/OpenSSL"
+      }
+
+      def initialize(config)
+	@config  = config
+        @cert    = config[:SSLCertificate]
+        @pkey    = config[:SSLPrivateKey]
+        @ssl_ctx = nil
+      end
+
+      def [](key); 
+	@config[key] || DEFAULT[key]
+      end
+
+      def connect(tcp)
+	ssl = ::OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx)
+	ssl.sync = true
+	ssl.connect
+	ssl
+      end
+      
+      def accept(tcp)
+	ssl = OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx)
+	ssl.sync = true
+	ssl.accept
+	ssl
+      end
+      
+      def setup_certificate
+        if @cert && @pkey
+          return
+        end
+
+	rsa = OpenSSL::PKey::RSA.new(512){|p, n|
+	  next unless self[:verbose]
+	  case p
+	  when 0; $stderr.putc "."  # BN_generate_prime
+	  when 1; $stderr.putc "+"  # BN_generate_prime
+	  when 2; $stderr.putc "*"  # searching good prime,
+	                            # n = #of try,
+                          	    # but also data from BN_generate_prime
+	  when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q,
+                         	    # but also data from BN_generate_prime
+	  else;   $stderr.putc "*"  # BN_generate_prime
+	  end
+	}
+
+	cert = OpenSSL::X509::Certificate.new
+	cert.version = 3
+	cert.serial = 0
+	name = OpenSSL::X509::Name.new(self[:SSLCertName])
+	cert.subject = name
+	cert.issuer = name
+	cert.not_before = Time.now
+	cert.not_after = Time.now + (365*24*60*60)
+	cert.public_key = rsa.public_key
+	
+	ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
+	cert.extensions = [
+	  ef.create_extension("basicConstraints","CA:FALSE"),
+	  ef.create_extension("subjectKeyIdentifier", "hash") ]
+	ef.issuer_certificate = cert
+	cert.add_extension(ef.create_extension("authorityKeyIdentifier",
+					       "keyid:always,issuer:always"))
+	if comment = self[:SSLCertComment]
+	  cert.add_extension(ef.create_extension("nsComment", comment))
+	end
+	cert.sign(rsa, OpenSSL::Digest::SHA1.new)
+	
+	@cert = cert
+        @pkey = rsa
+      end
+
+      def setup_ssl_context
+        ctx = ::OpenSSL::SSL::SSLContext.new
+        ctx.cert            = @cert
+        ctx.key             = @pkey
+	ctx.client_ca       = self[:SSLClientCA]
+	ctx.ca_path         = self[:SSLCACertificatePath]
+	ctx.ca_file         = self[:SSLCACertificateFile]
+	ctx.verify_mode     = self[:SSLVerifyMode]
+	ctx.verify_depth    = self[:SSLVerifyDepth]
+	ctx.verify_callback = self[:SSLVerifyCallback]
+        ctx.cert_store      = self[:SSLCertificateStore]
+        @ssl_ctx = ctx
+      end
+    end
+
+    def self.parse_uri(uri)
+      if uri =~ /^drbssl:\/\/(.*?):(\d+)(\?(.*))?$/
+	host = $1
+	port = $2.to_i
+	option = $4
+	[host, port, option]
+      else
+	raise(DRbBadScheme, uri) unless uri =~ /^drbssl:/
+	raise(DRbBadURI, 'can\'t parse uri:' + uri)
+      end
+    end
+
+    def self.open(uri, config)
+      host, port, option = parse_uri(uri)
+      host.untaint
+      port.untaint
+      soc = TCPSocket.open(host, port)
+      ssl_conf = SSLConfig::new(config)
+      ssl_conf.setup_ssl_context
+      ssl = ssl_conf.connect(soc)
+      self.new(uri, ssl, ssl_conf, true)
+    end
+
+    def self.open_server(uri, config)
+      uri = 'drbssl://:0' unless uri
+      host, port, opt = parse_uri(uri)
+      if host.size == 0
+        host = getservername
+        soc = open_server_inaddr_any(host, port)
+      else
+	soc = TCPServer.open(host, port)
+      end
+      port = soc.addr[1] if port == 0
+      @uri = "drbssl://#{host}:#{port}"
+      
+      ssl_conf = SSLConfig.new(config)
+      ssl_conf.setup_certificate
+      ssl_conf.setup_ssl_context
+      self.new(@uri, soc, ssl_conf, false)
+    end
+
+    def self.uri_option(uri, config)
+      host, port, option = parse_uri(uri)
+      return "drbssl://#{host}:#{port}", option
+    end
+
+    def initialize(uri, soc, config, is_established)
+      @ssl = is_established ? soc : nil
+      super(uri, soc.to_io, config)
+    end
+    
+    def stream; @ssl; end
+
+    def close
+      if @ssl
+	@ssl.close
+	@ssl = nil
+      end
+      super
+    end
+      
+    def accept
+      begin
+      while true
+	soc = @socket.accept
+	break if (@acl ? @acl.allow_socket?(soc) : true) 
+	soc.close
+      end
+      ssl = @config.accept(soc)
+      self.class.new(uri, ssl, @config, true)
+      rescue OpenSSL::SSL::SSLError
+	warn("#{__FILE__}:#{__LINE__}: warning: #{$!.message} (#{$!.class})") if @config[:verbose]
+	retry
+      end
+    end
+  end
+  
+  DRbProtocol.add_protocol(DRbSSLSocket)
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/timeridconv.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/timeridconv.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/timeridconv.rb	(revision 18425)
@@ -0,0 +1,91 @@
+require 'drb/drb'
+require 'monitor'
+
+module DRb
+  class TimerIdConv < DRbIdConv
+    class TimerHolder2
+      include MonitorMixin
+
+      class InvalidIndexError < RuntimeError; end
+
+      def initialize(timeout=600)
+	super()
+	@sentinel = Object.new
+	@gc = {}
+	@curr = {}
+	@renew = {}
+	@timeout = timeout
+	@keeper = keeper
+      end
+
+      def add(obj)
+	synchronize do 
+	  key = obj.__id__
+	  @curr[key] = obj
+	  return key
+	end
+      end
+
+      def fetch(key, dv=@sentinel)
+	synchronize do 
+	  obj = peek(key)
+	  if obj == @sentinel
+	    return dv unless dv == @sentinel
+	    raise InvalidIndexError
+	  end
+	  @renew[key] = obj # KeepIt
+	  return obj
+	end
+      end
+
+      def include?(key)
+	synchronize do 
+	  obj = peek(key)
+	  return false if obj == @sentinel
+	  true
+	end
+      end
+
+      def peek(key)
+	synchronize do 
+	  return @curr.fetch(key, @renew.fetch(key, @gc.fetch(key, @sentinel)))
+	end
+      end
+
+      private
+      def alternate
+	synchronize do
+	  @gc = @curr       # GCed
+	  @curr = @renew
+	  @renew = {}
+	end
+      end
+
+      def keeper
+	Thread.new do
+	  loop do
+	    size = alternate
+	    sleep(@timeout)
+	  end
+	end
+      end
+    end
+
+    def initialize(timeout=600)
+      @holder = TimerHolder2.new(timeout)
+    end
+
+    def to_obj(ref)
+      return super if ref.nil?
+      @holder.fetch(ref)
+    rescue TimerHolder2::InvalidIndexError
+      raise "invalid reference"
+    end
+
+    def to_id(obj)
+      return @holder.add(obj)
+    end
+  end
+end
+
+# DRb.install_id_conv(TimerIdConv.new)
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/unix.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/unix.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/drb/unix.rb	(revision 18425)
@@ -0,0 +1,108 @@
+require 'socket'
+require 'drb/drb'
+require 'tmpdir'
+
+raise(LoadError, "UNIXServer is required") unless defined?(UNIXServer)
+
+module DRb
+
+  class DRbUNIXSocket < DRbTCPSocket
+    def self.parse_uri(uri)
+      if /^drbunix:(.*?)(\?(.*))?$/ =~ uri 
+	filename = $1
+	option = $3
+	[filename, option]
+      else
+	raise(DRbBadScheme, uri) unless uri =~ /^drbunix:/
+	raise(DRbBadURI, 'can\'t parse uri:' + uri)
+      end
+    end
+
+    def self.open(uri, config)
+      filename, option = parse_uri(uri)
+      filename.untaint
+      soc = UNIXSocket.open(filename)
+      self.new(uri, soc, config)
+    end
+
+    def self.open_server(uri, config)
+      filename, option = parse_uri(uri)
+      if filename.size == 0
+	soc = temp_server
+        filename = soc.path
+	uri = 'drbunix:' + soc.path
+      else
+	soc = UNIXServer.open(filename)
+      end
+      owner = config[:UNIXFileOwner]
+      group = config[:UNIXFileGroup]
+      if owner || group
+        require 'etc'
+        owner = Etc.getpwnam( owner ).uid  if owner
+        group = Etc.getgrnam( group ).gid  if group
+        File.chown owner, group, filename
+      end
+      mode = config[:UNIXFileMode]
+      File.chmod(mode, filename) if mode
+
+      self.new(uri, soc, config, true)
+    end
+
+    def self.uri_option(uri, config)
+      filename, option = parse_uri(uri)
+      return "drbunix:#{filename}", option
+    end
+
+    def initialize(uri, soc, config={}, server_mode = false)
+      super(uri, soc, config)
+      set_sockopt(@socket)
+      @server_mode = server_mode
+      @acl = nil
+    end
+    
+    # import from tempfile.rb
+    Max_try = 10
+    private
+    def self.temp_server
+      tmpdir = Dir::tmpdir
+      n = 0
+      while true
+	begin
+	  tmpname = sprintf('%s/druby%d.%d', tmpdir, $$, n)
+	  lock = tmpname + '.lock'
+	  unless File.exist?(tmpname) or File.exist?(lock)
+	    Dir.mkdir(lock)
+	    break
+	  end
+	rescue
+	  raise "cannot generate tempfile `%s'" % tmpname if n >= Max_try
+	  #sleep(1)
+	end
+	n += 1
+      end
+      soc = UNIXServer.new(tmpname)
+      Dir.rmdir(lock)
+      soc
+    end
+
+    public
+    def close
+      return unless @socket
+      path = @socket.path if @server_mode
+      @socket.close
+      File.unlink(path) if @server_mode
+      @socket = nil
+    end
+
+    def accept
+      s = @socket.accept
+      self.class.new(nil, s, @config)
+    end
+
+    def set_sockopt(soc)
+      soc.fcntl(Fcntl::F_SETFL, Fcntl::FD_CLOEXEC) if defined? Fcntl::FD_CLOEXEC
+    end
+  end
+
+  DRbProtocol.add_protocol(DRbUNIXSocket)
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/e2mmap.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/e2mmap.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/e2mmap.rb	(revision 18425)
@@ -0,0 +1,195 @@
+#
+#   e2mmap.rb - for ruby 1.1
+#   	$Release Version: 2.0$
+#   	$Revision: 1.10 $
+#   	$Date: 1999/02/17 12:33:17 $
+#   	by Keiju ISHITSUKA
+#
+# --
+#   Usage:
+#
+# U1)
+#   class Foo
+#     extend Exception2MessageMapper
+#     def_e2message ExistingExceptionClass, "message..."
+#     def_exception :NewExceptionClass, "message..."[, superclass]
+#     ...
+#   end
+#
+# U2)
+#   module Error
+#     extend Exception2MessageMapper
+#     def_e2meggage ExistingExceptionClass, "message..."
+#     def_exception :NewExceptionClass, "message..."[, superclass]
+#     ...
+#   end
+#   class Foo
+#     include Error
+#     ...
+#   end
+#
+#   foo = Foo.new
+#   foo.Fail ....
+#
+# U3)
+#   module Error
+#     extend Exception2MessageMapper
+#     def_e2message ExistingExceptionClass, "message..."
+#     def_exception :NewExceptionClass, "message..."[, superclass]
+#     ...
+#   end
+#   class Foo
+#     extend Exception2MessageMapper
+#     include Error
+#     ...
+#   end
+#
+#   Foo.Fail NewExceptionClass, arg...
+#   Foo.Fail ExistingExceptionClass, arg...
+#
+#
+fail "Use Ruby 1.1" if VERSION < "1.1"
+
+module Exception2MessageMapper
+  @RCS_ID='-$Id: e2mmap.rb,v 1.10 1999/02/17 12:33:17 keiju Exp keiju $-'
+
+  E2MM = Exception2MessageMapper
+
+  def E2MM.extend_object(cl)
+    super
+    cl.bind(self) unless cl == E2MM
+  end
+  
+  # backward compatibility
+  def E2MM.extend_to(b)
+    c = eval("self", b)
+    c.extend(self)
+  end
+
+  def bind(cl)
+    self.module_eval %[
+      def Raise(err = nil, *rest)
+	Exception2MessageMapper.Raise(self.class, err, *rest)
+      end
+      alias Fail Raise
+
+      def self.included(mod)
+	mod.extend Exception2MessageMapper
+      end
+    ]
+  end
+
+  # Fail(err, *rest)
+  #	err:	exception
+  #	rest:	message arguments
+  #
+  def Raise(err = nil, *rest)
+    E2MM.Raise(self, err, *rest)
+  end
+  alias Fail Raise
+
+  # backward compatibility
+  alias fail! fail
+  def fail(err = nil, *rest)
+    begin 
+      E2MM.Fail(self, err, *rest)
+    rescue E2MM::ErrNotRegisteredException
+      super
+    end
+  end
+  class << self
+    public :fail
+  end
+
+  
+  # def_e2message(c, m)
+  #	    c:  exception
+  #	    m:  message_form
+  #	define exception c with message m.
+  #
+  def def_e2message(c, m)
+    E2MM.def_e2message(self, c, m)
+  end
+  
+  # def_exception(n, m, s)
+  #	    n:  exception_name
+  #	    m:  message_form
+  #	    s:	superclass(default: StandardError)
+  #	define exception named ``c'' with message m.
+  #
+  def def_exception(n, m, s = StandardError)
+    E2MM.def_exception(self, n, m, s)
+  end
+
+  #
+  # Private definitions.
+  #
+  # {[class, exp] => message, ...}
+  @MessageMap = {}
+
+  # E2MM.def_exception(k, e, m)
+  #	    k:  class to define exception under.
+  #	    e:  exception
+  #	    m:  message_form
+  #	define exception c with message m.
+  #
+  def E2MM.def_e2message(k, c, m)
+    E2MM.instance_eval{@MessageMap[[k, c]] = m}
+    c
+  end
+  
+  # E2MM.def_exception(k, n, m, s)
+  #	    k:  class to define exception under.
+  #	    n:  exception_name
+  #	    m:  message_form
+  #	    s:	superclass(default: StandardError)
+  #	define exception named ``c'' with message m.
+  #
+  def E2MM.def_exception(k, n, m, s = StandardError)
+    n = n.id2name if n.kind_of?(Fixnum)
+    e = Class.new(s)
+    E2MM.instance_eval{@MessageMap[[k, e]] = m}
+    k.const_set(n, e)
+  end
+
+  # Fail(klass, err, *rest)
+  #	klass:  class to define exception under.
+  #	err:	exception
+  #	rest:	message arguments
+  #
+  def E2MM.Raise(klass = E2MM, err = nil, *rest)
+    if form = e2mm_message(klass, err)
+      $! = err.new(sprintf(form, *rest))
+      $@ = caller(1) if $@.nil?
+      #p $@
+      #p __FILE__
+      $@.shift if $@[0] =~ /^#{Regexp.quote(__FILE__)}:/
+      raise
+    else
+      E2MM.Fail E2MM, ErrNotRegisteredException, err.inspect
+    end
+  end
+  class <<E2MM
+    alias Fail Raise
+  end
+
+  def E2MM.e2mm_message(klass, exp)
+    for c in klass.ancestors
+      if mes = @MessageMap[[c,exp]]
+	#p mes
+	m = klass.instance_eval('"' + mes + '"')
+	return m
+      end
+    end
+    nil
+  end
+  class <<self
+    alias message e2mm_message
+  end
+
+  E2MM.def_exception(E2MM, 
+		     :ErrNotRegisteredException, 
+		     "not registerd exception(%s)")
+end
+
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/erb.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/erb.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/erb.rb	(revision 18425)
@@ -0,0 +1,826 @@
+# = ERB -- Ruby Templating
+#
+# Author:: Masatoshi SEKI
+# Documentation:: James Edward Gray II and Gavin Sinclair
+#
+# See ERB for primary documentation and ERB::Util for a couple of utility
+# routines.
+#
+# Copyright (c) 1999-2000,2002,2003 Masatoshi SEKI
+#
+# You can redistribute it and/or modify it under the same terms as Ruby.
+
+#
+# = ERB -- Ruby Templating
+#
+# == Introduction
+#
+# ERB provides an easy to use but powerful templating system for Ruby.  Using
+# ERB, actual Ruby code can be added to any plain text document for the
+# purposes of generating document information details and/or flow control.
+#
+# A very simple example is this:
+# 
+#   require 'erb'
+#
+#   x = 42
+#   template = ERB.new <<-EOF
+#     The value of x is: <%= x %>
+#   EOF
+#   puts template.result(binding)
+#
+# <em>Prints:</em> The value of x is: 42
+#
+# More complex examples are given below.
+#
+#
+# == Recognized Tags
+#
+# ERB recognizes certain tags in the provided template and converts them based
+# on the rules below:
+#
+#   <% Ruby code -- inline with output %>
+#   <%= Ruby expression -- replace with result %>
+#   <%# comment -- ignored -- useful in testing %>
+#   % a line of Ruby code -- treated as <% line %> (optional -- see ERB.new)
+#   %% replaced with % if first thing on a line and % processing is used
+#   <%% or %%> -- replace with <% or %> respectively
+#
+# All other text is passed through ERB filtering unchanged.
+#
+#
+# == Options
+#
+# There are several settings you can change when you use ERB:
+# * the nature of the tags that are recognized;
+# * the value of <tt>$SAFE</tt> under which the template is run;
+# * the binding used to resolve local variables in the template.
+#
+# See the ERB.new and ERB#result methods for more detail.
+#
+#
+# == Examples
+#
+# === Plain Text
+#
+# ERB is useful for any generic templating situation.  Note that in this example, we use the
+# convenient "% at start of line" tag, and we quote the template literally with
+# <tt>%q{...}</tt> to avoid trouble with the backslash.
+#
+#   require "erb"
+#   
+#   # Create template.
+#   template = %q{
+#     From:  James Edward Gray II <james@grayproductions.net>
+#     To:  <%= to %>
+#     Subject:  Addressing Needs
+#   
+#     <%= to[/\w+/] %>:
+#   
+#     Just wanted to send a quick note assuring that your needs are being
+#     addressed.
+#   
+#     I want you to know that my team will keep working on the issues,
+#     especially:
+#   
+#     <%# ignore numerous minor requests -- focus on priorities %>
+#     % priorities.each do |priority|
+#       * <%= priority %>
+#     % end
+#   
+#     Thanks for your patience.
+#   
+#     James Edward Gray II
+#   }.gsub(/^  /, '')
+#   
+#   message = ERB.new(template, 0, "%<>")
+#   
+#   # Set up template data.
+#   to = "Community Spokesman <spokesman@ruby_community.org>"
+#   priorities = [ "Run Ruby Quiz",
+#                  "Document Modules",
+#                  "Answer Questions on Ruby Talk" ]
+#   
+#   # Produce result.
+#   email = message.result
+#   puts email
+#
+# <i>Generates:</i>
+#
+#   From:  James Edward Gray II <james@grayproductions.net>
+#   To:  Community Spokesman <spokesman@ruby_community.org>
+#   Subject:  Addressing Needs
+#   
+#   Community:
+#   
+#   Just wanted to send a quick note assuring that your needs are being addressed.
+#   
+#   I want you to know that my team will keep working on the issues, especially:
+#   
+#       * Run Ruby Quiz
+#       * Document Modules
+#       * Answer Questions on Ruby Talk
+#   
+#   Thanks for your patience.
+#   
+#   James Edward Gray II
+#
+# === Ruby in HTML
+#
+# ERB is often used in <tt>.rhtml</tt> files (HTML with embedded Ruby).  Notice the need in
+# this example to provide a special binding when the template is run, so that the instance
+# variables in the Product object can be resolved.
+#
+#   require "erb"
+#   
+#   # Build template data class.
+#   class Product
+#     def initialize( code, name, desc, cost )
+#       @code = code
+#       @name = name
+#       @desc = desc
+#       @cost = cost
+#        	
+#       @features = [ ]
+#     end
+#   
+#     def add_feature( feature )
+#       @features << feature
+#     end
+#   
+#     # Support templating of member data.
+#     def get_binding
+#       binding
+#     end
+#   
+#     # ...
+#   end
+#   
+#   # Create template.
+#   template = %{
+#     <html>
+#       <head><title>Ruby Toys -- <%= @name %></title></head>
+#       <body>
+#   
+#         <h1><%= @name %> (<%= @code %>)</h1>
+#         <p><%= @desc %></p>
+#   
+#         <ul>
+#           <% @features.each do |f| %>
+#             <li><b><%= f %></b></li>
+#           <% end %>
+#         </ul>
+#   
+#         <p>
+#           <% if @cost < 10 %>
+#             <b>Only <%= @cost %>!!!</b>
+#           <% else %>
+#              Call for a price, today!
+#           <% end %>
+#         </p>
+#    
+#       </body>
+#     </html>
+#   }.gsub(/^  /, '')
+#   
+#   rhtml = ERB.new(template)
+#   
+#   # Set up template data.
+#   toy = Product.new( "TZ-1002",
+#                      "Rubysapien",
+#                      "Geek's Best Friend!  Responds to Ruby commands...",
+#                      999.95 )
+#   toy.add_feature("Listens for verbal commands in the Ruby language!")
+#   toy.add_feature("Ignores Perl, Java, and all C variants.")
+#   toy.add_feature("Karate-Chop Action!!!")
+#   toy.add_feature("Matz signature on left leg.")
+#   toy.add_feature("Gem studded eyes... Rubies, of course!")
+#   
+#   # Produce result.
+#   rhtml.run(toy.get_binding)
+#
+# <i>Generates (some blank lines removed):</i>
+#
+#    <html>
+#      <head><title>Ruby Toys -- Rubysapien</title></head>
+#      <body>
+#    
+#        <h1>Rubysapien (TZ-1002)</h1>
+#        <p>Geek's Best Friend!  Responds to Ruby commands...</p>
+#    
+#        <ul>
+#            <li><b>Listens for verbal commands in the Ruby language!</b></li>
+#            <li><b>Ignores Perl, Java, and all C variants.</b></li>
+#            <li><b>Karate-Chop Action!!!</b></li>
+#            <li><b>Matz signature on left leg.</b></li>
+#            <li><b>Gem studded eyes... Rubies, of course!</b></li>
+#        </ul>
+#    
+#        <p>
+#             Call for a price, today!
+#        </p>
+#    
+#      </body>
+#    </html>
+#
+# 
+# == Notes
+#
+# There are a variety of templating solutions available in various Ruby projects:
+# * ERB's big brother, eRuby, works the same but is written in C for speed;
+# * Amrita (smart at producing HTML/XML);
+# * cs/Template (written in C for speed);
+# * RDoc, distributed with Ruby, uses its own template engine, which can be reused elsewhere;
+# * and others; search the RAA.
+#
+# Rails, the web application framework, uses ERB to create views.
+#
+class ERB
+  Revision = '$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $' 	#'
+
+  # Returns revision information for the erb.rb module.
+  def self.version
+    "erb.rb [2.0.4 #{ERB::Revision.split[1]}]"
+  end
+end
+
+#--
+# ERB::Compiler
+class ERB
+  class Compiler # :nodoc:
+    class PercentLine # :nodoc:
+      def initialize(str)
+        @value = str
+      end
+      attr_reader :value
+      alias :to_s :value
+    end
+
+    class Scanner # :nodoc:
+      SplitRegexp = /(<%%)|(%%>)|(<%=)|(<%#)|(<%)|(%>)|(\n)/
+
+      @scanner_map = {}
+      def self.regist_scanner(klass, trim_mode, percent)
+	@scanner_map[[trim_mode, percent]] = klass
+      end
+
+      def self.default_scanner=(klass)
+	@default_scanner = klass
+      end
+
+      def self.make_scanner(src, trim_mode, percent)
+	klass = @scanner_map.fetch([trim_mode, percent], @default_scanner)
+	klass.new(src, trim_mode, percent)
+      end
+
+      def initialize(src, trim_mode, percent)
+	@src = src
+	@stag = nil
+      end
+      attr_accessor :stag
+
+      def scan; end
+    end
+
+    class TrimScanner < Scanner # :nodoc:
+      TrimSplitRegexp = /(<%%)|(%%>)|(<%=)|(<%#)|(<%)|(%>\n)|(%>)|(\n)/
+
+      def initialize(src, trim_mode, percent)
+	super
+	@trim_mode = trim_mode
+	@percent = percent
+	if @trim_mode == '>'
+	  @scan_line = self.method(:trim_line1)
+	elsif @trim_mode == '<>'
+	  @scan_line = self.method(:trim_line2)
+	elsif @trim_mode == '-'
+	  @scan_line = self.method(:explicit_trim_line)
+	else
+	  @scan_line = self.method(:scan_line)
+	end
+      end
+      attr_accessor :stag
+      
+      def scan(&block)
+	@stag = nil
+	if @percent
+	  @src.each do |line|
+	    percent_line(line, &block)
+	  end
+	else
+	  @src.each do |line|
+	    @scan_line.call(line, &block)
+	  end
+	end
+	nil
+      end
+
+      def percent_line(line, &block)
+	if @stag || line[0] != ?%
+	  return @scan_line.call(line, &block)
+	end
+
+	line[0] = ''
+	if line[0] == ?%
+	  @scan_line.call(line, &block)
+	else
+          yield(PercentLine.new(line.chomp))
+	end
+      end
+
+      def scan_line(line)
+	line.split(SplitRegexp).each do |token|
+	  next if token.empty?
+	  yield(token)
+	end
+      end
+
+      def trim_line1(line)
+	line.split(TrimSplitRegexp).each do |token|
+	  next if token.empty?
+	  if token == "%>\n"
+	    yield('%>')
+	    yield(:cr)
+	    break
+	  end
+	  yield(token)
+	end
+      end
+
+      def trim_line2(line)
+	head = nil
+	line.split(TrimSplitRegexp).each do |token|
+	  next if token.empty?
+	  head = token unless head
+	  if token == "%>\n"
+	    yield('%>')
+	    if  is_erb_stag?(head)
+	      yield(:cr)
+	    else
+	      yield("\n")
+	    end
+	    break
+	  end
+	  yield(token)
+	end
+      end
+
+      ExplicitTrimRegexp = /(^[ \t]*<%-)|(-%>\n?\z)|(<%-)|(-%>)|(<%%)|(%%>)|(<%=)|(<%#)|(<%)|(%>)|(\n)/
+      def explicit_trim_line(line)
+	line.split(ExplicitTrimRegexp).each do |token|
+	  next if token.empty?
+	  if @stag.nil? && /[ \t]*<%-/ =~ token
+	    yield('<%')
+	  elsif @stag && /-%>\n/ =~ token
+	    yield('%>')
+	    yield(:cr)
+	  elsif @stag && token == '-%>'
+	    yield('%>')
+	  else
+	    yield(token)
+	  end
+	end
+      end
+
+      ERB_STAG = %w(<%= <%# <%)
+      def is_erb_stag?(s)
+	ERB_STAG.member?(s)
+      end
+    end
+
+    Scanner.default_scanner = TrimScanner
+
+    class SimpleScanner < Scanner # :nodoc:
+      def scan
+	@src.each do |line|
+	  line.split(SplitRegexp).each do |token|
+	    next if token.empty?
+	    yield(token)
+	  end
+	end
+      end
+    end
+    
+    Scanner.regist_scanner(SimpleScanner, nil, false)
+
+    begin
+      require 'strscan'
+      class SimpleScanner2 < Scanner # :nodoc:
+        def scan
+          stag_reg = /(.*?)(<%%|<%=|<%#|<%|\n|\z)/
+          etag_reg = /(.*?)(%%>|%>|\n|\z)/
+          scanner = StringScanner.new(@src)
+          while ! scanner.eos?
+            scanner.scan(@stag ? etag_reg : stag_reg)
+            text = scanner[1]
+            elem = scanner[2]
+            yield(text) unless text.empty?
+            yield(elem) unless elem.empty?
+          end
+        end
+      end
+      Scanner.regist_scanner(SimpleScanner2, nil, false)
+
+      class PercentScanner < Scanner # :nodoc:
+	def scan
+	  new_line = true
+          stag_reg = /(.*?)(<%%|<%=|<%#|<%|\n|\z)/
+          etag_reg = /(.*?)(%%>|%>|\n|\z)/
+          scanner = StringScanner.new(@src)
+          while ! scanner.eos?
+	    if new_line && @stag.nil?
+	      if scanner.scan(/%%/)
+		yield('%')
+		new_line = false
+		next
+	      elsif scanner.scan(/%/)
+		yield(PercentLine.new(scanner.scan(/.*?(\n|\z)/).chomp))
+		next
+	      end
+	    end
+	    scanner.scan(@stag ? etag_reg : stag_reg)
+            text = scanner[1]
+            elem = scanner[2]
+            yield(text) unless text.empty?
+            yield(elem) unless elem.empty?
+	    new_line = (elem == "\n")
+          end
+        end
+      end
+      Scanner.regist_scanner(PercentScanner, nil, true)
+
+      class ExplicitScanner < Scanner # :nodoc:
+	def scan
+	  new_line = true
+          stag_reg = /(.*?)(<%%|<%=|<%#|<%-|<%|\n|\z)/
+          etag_reg = /(.*?)(%%>|-%>|%>|\n|\z)/
+          scanner = StringScanner.new(@src)
+          while ! scanner.eos?
+	    if new_line && @stag.nil? && scanner.scan(/[ \t]*<%-/)
+	      yield('<%')
+	      new_line = false
+	      next
+	    end
+	    scanner.scan(@stag ? etag_reg : stag_reg)
+            text = scanner[1]
+            elem = scanner[2]
+	    new_line = (elem == "\n")
+            yield(text) unless text.empty?
+	    if elem == '-%>'
+	      yield('%>')
+	      if scanner.scan(/(\n|\z)/)
+		yield(:cr)
+		new_line = true
+	      end
+	    elsif elem == '<%-'
+	      yield('<%')
+	    else
+	      yield(elem) unless elem.empty?
+	    end
+          end
+        end
+      end
+      Scanner.regist_scanner(ExplicitScanner, '-', false)
+
+    rescue LoadError
+    end
+
+    class Buffer # :nodoc:
+      def initialize(compiler)
+	@compiler = compiler
+	@line = []
+	@script = ""
+	@compiler.pre_cmd.each do |x|
+	  push(x)
+	end
+      end
+      attr_reader :script
+
+      def push(cmd)
+	@line << cmd
+      end
+      
+      def cr
+	@script << (@line.join('; '))
+	@line = []
+	@script << "\n"
+      end
+      
+      def close
+	return unless @line
+	@compiler.post_cmd.each do |x|
+	  push(x)
+	end
+	@script << (@line.join('; '))
+	@line = nil
+      end
+    end
+
+    def compile(s)
+      out = Buffer.new(self)
+
+      content = ''
+      scanner = make_scanner(s)
+      scanner.scan do |token|
+	if scanner.stag.nil?
+	  case token
+          when PercentLine
+	    out.push("#{@put_cmd} #{content.dump}") if content.size > 0
+	    content = ''
+            out.push(token.to_s)
+            out.cr
+	  when :cr
+	    out.cr
+	  when '<%', '<%=', '<%#'
+	    scanner.stag = token
+	    out.push("#{@put_cmd} #{content.dump}") if content.size > 0
+	    content = ''
+	  when "\n"
+	    content << "\n"
+	    out.push("#{@put_cmd} #{content.dump}")
+	    out.cr
+	    content = ''
+	  when '<%%'
+	    content << '<%'
+	  else
+	    content << token
+	  end
+	else
+	  case token
+	  when '%>'
+	    case scanner.stag
+	    when '<%'
+	      if content[-1] == ?\n
+		content.chop!
+		out.push(content)
+		out.cr
+	      else
+		out.push(content)
+	      end
+	    when '<%='
+	      out.push("#{@insert_cmd}((#{content}).to_s)")
+	    when '<%#'
+	      # out.push("# #{content.dump}")
+	    end
+	    scanner.stag = nil
+	    content = ''
+	  when '%%>'
+	    content << '%>'
+	  else
+	    content << token
+	  end
+	end
+      end
+      out.push("#{@put_cmd} #{content.dump}") if content.size > 0
+      out.close
+      out.script
+    end
+
+    def prepare_trim_mode(mode)
+      case mode
+      when 1
+	return [false, '>']
+      when 2
+	return [false, '<>']
+      when 0
+	return [false, nil]
+      when String
+	perc = mode.include?('%')
+	if mode.include?('-')
+	  return [perc, '-']
+	elsif mode.include?('<>')
+	  return [perc, '<>']
+	elsif mode.include?('>')
+	  return [perc, '>']
+	else
+	  [perc, nil]
+	end
+      else
+	return [false, nil]
+      end
+    end
+
+    def make_scanner(src)
+      Scanner.make_scanner(src, @trim_mode, @percent)
+    end
+
+    def initialize(trim_mode)
+      @percent, @trim_mode = prepare_trim_mode(trim_mode)
+      @put_cmd = 'print'
+      @insert_cmd = @put_cmd
+      @pre_cmd = []
+      @post_cmd = []
+    end
+    attr_reader :percent, :trim_mode
+    attr_accessor :put_cmd, :insert_cmd, :pre_cmd, :post_cmd
+  end
+end
+
+#--
+# ERB
+class ERB
+  #
+  # Constructs a new ERB object with the template specified in _str_.
+  # 
+  # An ERB object works by building a chunk of Ruby code that will output
+  # the completed template when run. If _safe_level_ is set to a non-nil value,
+  # ERB code will be run in a separate thread with <b>$SAFE</b> set to the
+  # provided level.
+  # 
+  # If _trim_mode_ is passed a String containing one or more of the following
+  # modifiers, ERB will adjust its code generation as listed:
+  # 
+  # 	%  enables Ruby code processing for lines beginning with %
+  # 	<> omit newline for lines starting with <% and ending in %>
+  # 	>  omit newline for lines ending in %>
+  # 
+  # _eoutvar_ can be used to set the name of the variable ERB will build up
+  # its output in.  This is useful when you need to run multiple ERB
+  # templates through the same binding and/or when you want to control where
+  # output ends up.  Pass the name of the variable to be used inside a String.
+  #
+  # === Example
+  #
+  #  require "erb"
+  #  
+  #  # build data class
+  #  class Listings
+  #    PRODUCT = { :name => "Chicken Fried Steak",
+  #                :desc => "A well messages pattie, breaded and fried.",
+  #                :cost => 9.95 }
+  #  
+  #    attr_reader :product, :price
+  #    
+  #    def initialize( product = "", price = "" )
+  #      @product = product
+  #      @price = price
+  #    end
+  #    
+  #    def build
+  #      b = binding
+  #      # create and run templates, filling member data variebles
+  #      ERB.new(<<-'END_PRODUCT'.gsub(/^\s+/, ""), 0, "", "@product").result b
+  #        <%= PRODUCT[:name] %>
+  #        <%= PRODUCT[:desc] %>
+  #      END_PRODUCT
+  #      ERB.new(<<-'END_PRICE'.gsub(/^\s+/, ""), 0, "", "@price").result b
+  #        <%= PRODUCT[:name] %> -- <%= PRODUCT[:cost] %>
+  #        <%= PRODUCT[:desc] %>
+  #      END_PRICE
+  #    end
+  #  end
+  #  
+  #  # setup template data
+  #  listings = Listings.new
+  #  listings.build
+  #  
+  #  puts listings.product + "\n" + listings.price
+  #
+  # _Generates_
+  #
+  #  Chicken Fried Steak
+  #  A well messages pattie, breaded and fried.
+  #  
+  #  Chicken Fried Steak -- 9.95
+  #  A well messages pattie, breaded and fried.
+  #  
+  def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout')
+    @safe_level = safe_level
+    compiler = ERB::Compiler.new(trim_mode)
+    set_eoutvar(compiler, eoutvar)
+    @src = compiler.compile(str)
+    @filename = nil
+  end
+
+  # The Ruby code generated by ERB
+  attr_reader :src
+
+  # The optional _filename_ argument passed to Kernel#eval when the ERB code
+  # is run
+  attr_accessor :filename
+
+  #
+  # Can be used to set _eoutvar_ as described in ERB#new.  It's probably easier
+  # to just use the constructor though, since calling this method requires the
+  # setup of an ERB _compiler_ object.
+  #
+  def set_eoutvar(compiler, eoutvar = '_erbout')
+    compiler.put_cmd = "#{eoutvar}.concat"
+    compiler.insert_cmd = "#{eoutvar}.concat"
+
+    cmd = []
+    cmd.push "#{eoutvar} = ''"
+    
+    compiler.pre_cmd = cmd
+
+    cmd = []
+    cmd.push(eoutvar)
+
+    compiler.post_cmd = cmd
+  end
+
+  # Generate results and print them. (see ERB#result)
+  def run(b=TOPLEVEL_BINDING)
+    print self.result(b)
+  end
+
+  #
+  # Executes the generated ERB code to produce a completed template, returning
+  # the results of that code.  (See ERB#new for details on how this process can
+  # be affected by _safe_level_.)
+  # 
+  # _b_ accepts a Binding or Proc object which is used to set the context of
+  # code evaluation.
+  #
+  def result(b=TOPLEVEL_BINDING)
+    if @safe_level
+      th = Thread.start { 
+	$SAFE = @safe_level
+	eval(@src, b, (@filename || '(erb)'), 1)
+      }
+      return th.value
+    else
+      return eval(@src, b, (@filename || '(erb)'), 1)
+    end
+  end
+
+  def def_method(mod, methodname, fname='(ERB)')  # :nodoc:
+    mod.module_eval("def #{methodname}\n" + self.src + "\nend\n", fname, 0)
+  end
+
+  def def_module(methodname='erb')  # :nodoc:
+    mod = Module.new
+    def_method(mod, methodname)
+    mod
+  end
+
+  def def_class(superklass=Object, methodname='result')  # :nodoc:
+    cls = Class.new(superklass)
+    def_method(cls, methodname)
+    cls
+  end
+end
+
+#--
+# ERB::Util
+class ERB
+  # A utility module for conversion routines, often handy in HTML generation.
+  module Util
+    public
+    #
+    # A utility method for escaping HTML tag characters in _s_.
+    # 
+    # 	require "erb"
+    # 	include ERB::Util
+    # 	
+    # 	puts html_escape("is a > 0 & a < 10?")
+    # 
+    # _Generates_
+    # 
+    # 	is a &gt; 0 &amp; a &lt; 10?
+    #
+    def html_escape(s)
+      s.to_s.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
+    end
+    alias h html_escape
+    module_function :h
+    module_function :html_escape
+    
+    #
+    # A utility method for encoding the String _s_ as a URL.
+    # 
+    # 	require "erb"
+    # 	include ERB::Util
+    # 	
+    # 	puts url_encode("Programming Ruby:  The Pragmatic Programmer's Guide")
+    # 
+    # _Generates_
+    # 
+    # 	Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
+    #
+    def url_encode(s)
+      s.to_s.gsub(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) }
+    end
+    alias u url_encode
+    module_function :u
+    module_function :url_encode
+  end
+end
+
+#--
+# ERB::DefMethod
+class ERB
+  module DefMethod  # :nodoc:
+    public
+    def def_erb_method(methodname, erb)
+      if erb.kind_of? String
+	fname = erb
+	File.open(fname) {|f| erb = ERB.new(f.read) }
+	erb.def_method(self, methodname, fname)
+      else
+	erb.def_method(self, methodname)
+      end
+    end
+    module_function :def_erb_method
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/eregex.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/eregex.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/eregex.rb	(revision 18425)
@@ -0,0 +1,37 @@
+# this is just a proof of concept toy.
+
+class RegOr
+  def initialize(re1, re2)
+    @re1 = re1
+    @re2 = re2
+  end
+
+  def =~ (str)
+    @re1 =~ str or @re2 =~ str
+  end
+end
+
+class RegAnd
+  def initialize(re1, re2)
+    @re1 = re1
+    @re2 = re2
+  end
+
+  def =~ (str)
+    @re1 =~ str and @re2 =~ str
+  end
+end
+
+class Regexp
+  def |(other)
+    RegOr.new(self, other)
+  end
+  def &(other)
+    RegAnd.new(self, other)
+  end
+end
+
+if __FILE__ == $0
+  p "abc" =~ /b/|/c/
+  p "abc" =~ /b/&/c/
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/expect.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/expect.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/expect.rb	(revision 18425)
@@ -0,0 +1,36 @@
+$expect_verbose = false
+
+class IO
+  def expect(pat,timeout=9999999)
+    buf = ''
+    case pat
+    when String
+      e_pat = Regexp.new(Regexp.quote(pat))
+    when Regexp
+      e_pat = pat
+    end
+    while true
+      if IO.select([self],nil,nil,timeout).nil? then
+        result = nil
+        break
+      end
+      c = getc.chr
+      buf << c
+      if $expect_verbose
+        STDOUT.print c
+        STDOUT.flush
+      end
+      if mat=e_pat.match(buf) then
+        result = [buf,*mat.to_a[1..-1]]
+        break
+      end
+    end
+    if block_given? then
+      yield result
+    else
+      return result
+    end
+    nil
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/fileutils.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/fileutils.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/fileutils.rb	(revision 18425)
@@ -0,0 +1,1591 @@
+# 
+# = fileutils.rb
+# 
+# Copyright (c) 2000-2006 Minero Aoki
+# 
+# This program is free software.
+# You can distribute/modify this program under the same terms of ruby.
+# 
+# == module FileUtils
+# 
+# Namespace for several file utility methods for copying, moving, removing, etc.
+# 
+# === Module Functions
+# 
+#   cd(dir, options)
+#   cd(dir, options) {|dir| .... }
+#   pwd()
+#   mkdir(dir, options)
+#   mkdir(list, options)
+#   mkdir_p(dir, options)
+#   mkdir_p(list, options)
+#   rmdir(dir, options)
+#   rmdir(list, options)
+#   ln(old, new, options)
+#   ln(list, destdir, options)
+#   ln_s(old, new, options)
+#   ln_s(list, destdir, options)
+#   ln_sf(src, dest, options)
+#   cp(src, dest, options)
+#   cp(list, dir, options)
+#   cp_r(src, dest, options)
+#   cp_r(list, dir, options)
+#   mv(src, dest, options)
+#   mv(list, dir, options)
+#   rm(list, options)
+#   rm_r(list, options)
+#   rm_rf(list, options)
+#   install(src, dest, mode = <src's>, options)
+#   chmod(mode, list, options)
+#   chmod_R(mode, list, options)
+#   chown(user, group, list, options)
+#   chown_R(user, group, list, options)
+#   touch(list, options)
+#
+# The <tt>options</tt> parameter is a hash of options, taken from the list
+# <tt>:force</tt>, <tt>:noop</tt>, <tt>:preserve</tt>, and <tt>:verbose</tt>.
+# <tt>:noop</tt> means that no changes are made.  The other two are obvious.
+# Each method documents the options that it honours.
+#
+# All methods that have the concept of a "source" file or directory can take
+# either one file or a list of files in that argument.  See the method
+# documentation for examples.
+#
+# There are some `low level' methods, which do not accept any option:
+#
+#   copy_entry(src, dest, preserve = false, dereference = false)
+#   copy_file(src, dest, preserve = false, dereference = true)
+#   copy_stream(srcstream, deststream)
+#   remove_entry(path, force = false)
+#   remove_entry_secure(path, force = false)
+#   remove_file(path, force = false)
+#   compare_file(path_a, path_b)
+#   compare_stream(stream_a, stream_b)
+#   uptodate?(file, cmp_list)
+#
+# == module FileUtils::Verbose
+# 
+# This module has all methods of FileUtils module, but it outputs messages
+# before acting.  This equates to passing the <tt>:verbose</tt> flag to methods
+# in FileUtils.
+# 
+# == module FileUtils::NoWrite
+# 
+# This module has all methods of FileUtils module, but never changes
+# files/directories.  This equates to passing the <tt>:noop</tt> flag to methods
+# in FileUtils.
+# 
+# == module FileUtils::DryRun
+# 
+# This module has all methods of FileUtils module, but never changes
+# files/directories.  This equates to passing the <tt>:noop</tt> and
+# <tt>:verbose</tt> flags to methods in FileUtils.
+# 
+
+module FileUtils
+
+  def self.private_module_function(name)   #:nodoc:
+    module_function name
+    private_class_method name
+  end
+
+  # This hash table holds command options.
+  OPT_TABLE = {}   #:nodoc: internal use only
+
+  #
+  # Options: (none)
+  #
+  # Returns the name of the current directory.
+  #
+  def pwd
+    Dir.pwd
+  end
+  module_function :pwd
+
+  alias getwd pwd
+  module_function :getwd
+
+  #
+  # Options: verbose
+  # 
+  # Changes the current directory to the directory +dir+.
+  # 
+  # If this method is called with block, resumes to the old
+  # working directory after the block execution finished.
+  # 
+  #   FileUtils.cd('/', :verbose => true)   # chdir and report it
+  # 
+  def cd(dir, options = {}, &block) # :yield: dir
+    fu_check_options options, OPT_TABLE['cd']
+    fu_output_message "cd #{dir}" if options[:verbose]
+    Dir.chdir(dir, &block)
+    fu_output_message 'cd -' if options[:verbose] and block
+  end
+  module_function :cd
+
+  alias chdir cd
+  module_function :chdir
+
+  OPT_TABLE['cd']    =
+  OPT_TABLE['chdir'] = [:verbose]
+
+  #
+  # Options: (none)
+  # 
+  # Returns true if +newer+ is newer than all +old_list+.
+  # Non-existent files are older than any file.
+  # 
+  #   FileUtils.uptodate?('hello.o', %w(hello.c hello.h)) or \
+  #       system 'make hello.o'
+  # 
+  def uptodate?(new, old_list, options = nil)
+    raise ArgumentError, 'uptodate? does not accept any option' if options
+
+    return false unless File.exist?(new)
+    new_time = File.mtime(new)
+    old_list.each do |old|
+      if File.exist?(old)
+        return false unless new_time > File.mtime(old)
+      end
+    end
+    true
+  end
+  module_function :uptodate?
+
+  #
+  # Options: mode noop verbose
+  # 
+  # Creates one or more directories.
+  # 
+  #   FileUtils.mkdir 'test'
+  #   FileUtils.mkdir %w( tmp data )
+  #   FileUtils.mkdir 'notexist', :noop => true  # Does not really create.
+  #   FileUtils.mkdir 'tmp', :mode => 0700
+  # 
+  def mkdir(list, options = {})
+    fu_check_options options, OPT_TABLE['mkdir']
+    list = fu_list(list)
+    fu_output_message "mkdir #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}" if options[:verbose]
+    return if options[:noop]
+
+    list.each do |dir|
+      fu_mkdir dir, options[:mode]
+    end
+  end
+  module_function :mkdir
+
+  OPT_TABLE['mkdir'] = [:mode, :noop, :verbose]
+
+  #
+  # Options: mode noop verbose
+  # 
+  # Creates a directory and all its parent directories.
+  # For example,
+  # 
+  #   FileUtils.mkdir_p '/usr/local/lib/ruby'
+  # 
+  # causes to make following directories, if it does not exist.
+  #     * /usr
+  #     * /usr/local
+  #     * /usr/local/lib
+  #     * /usr/local/lib/ruby
+  #
+  # You can pass several directories at a time in a list.
+  # 
+  def mkdir_p(list, options = {})
+    fu_check_options options, OPT_TABLE['mkdir_p']
+    list = fu_list(list)
+    fu_output_message "mkdir -p #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}" if options[:verbose]
+    return *list if options[:noop]
+
+    list.map {|path| path.sub(%r</\z>, '') }.each do |path|
+      # optimize for the most common case
+      begin
+        fu_mkdir path, options[:mode]
+        next
+      rescue SystemCallError
+        next if File.directory?(path)
+      end
+
+      stack = []
+      until path == stack.last   # dirname("/")=="/", dirname("C:/")=="C:/"
+        stack.push path
+        path = File.dirname(path)
+      end
+      stack.reverse_each do |path|
+        begin
+          fu_mkdir path, options[:mode]
+        rescue SystemCallError => err
+          raise unless File.directory?(path)
+        end
+      end
+    end
+
+    return *list
+  end
+  module_function :mkdir_p
+
+  alias mkpath    mkdir_p
+  alias makedirs  mkdir_p
+  module_function :mkpath
+  module_function :makedirs
+
+  OPT_TABLE['mkdir_p']  =
+  OPT_TABLE['mkpath']   =
+  OPT_TABLE['makedirs'] = [:mode, :noop, :verbose]
+
+  def fu_mkdir(path, mode)   #:nodoc:
+    path = path.sub(%r</\z>, '')
+    if mode
+      Dir.mkdir path, mode
+      File.chmod mode, path
+    else
+      Dir.mkdir path
+    end
+  end
+  private_module_function :fu_mkdir
+
+  #
+  # Options: noop, verbose
+  # 
+  # Removes one or more directories.
+  # 
+  #   FileUtils.rmdir 'somedir'
+  #   FileUtils.rmdir %w(somedir anydir otherdir)
+  #   # Does not really remove directory; outputs message.
+  #   FileUtils.rmdir 'somedir', :verbose => true, :noop => true
+  # 
+  def rmdir(list, options = {})
+    fu_check_options options, OPT_TABLE['rmdir']
+    list = fu_list(list)
+    fu_output_message "rmdir #{list.join ' '}" if options[:verbose]
+    return if options[:noop]
+    list.each do |dir|
+      Dir.rmdir dir.sub(%r</\z>, '')
+    end
+  end
+  module_function :rmdir
+
+  OPT_TABLE['rmdir'] = [:noop, :verbose]
+
+  #
+  # Options: force noop verbose
+  #
+  # <b><tt>ln(old, new, options = {})</tt></b>
+  #
+  # Creates a hard link +new+ which points to +old+.
+  # If +new+ already exists and it is a directory, creates a link +new/old+.
+  # If +new+ already exists and it is not a directory, raises Errno::EEXIST.
+  # But if :force option is set, overwrite +new+.
+  # 
+  #   FileUtils.ln 'gcc', 'cc', :verbose => true
+  #   FileUtils.ln '/usr/bin/emacs21', '/usr/bin/emacs'
+  # 
+  # <b><tt>ln(list, destdir, options = {})</tt></b>
+  # 
+  # Creates several hard links in a directory, with each one pointing to the
+  # item in +list+.  If +destdir+ is not a directory, raises Errno::ENOTDIR.
+  # 
+  #   include FileUtils
+  #   cd '/sbin'
+  #   FileUtils.ln %w(cp mv mkdir), '/bin'   # Now /sbin/cp and /bin/cp are linked.
+  # 
+  def ln(src, dest, options = {})
+    fu_check_options options, OPT_TABLE['ln']
+    fu_output_message "ln#{options[:force] ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
+    return if options[:noop]
+    fu_each_src_dest0(src, dest) do |s,d|
+      remove_file d, true if options[:force]
+      File.link s, d
+    end
+  end
+  module_function :ln
+
+  alias link ln
+  module_function :link
+
+  OPT_TABLE['ln']   =
+  OPT_TABLE['link'] = [:force, :noop, :verbose]
+
+  #
+  # Options: force noop verbose
+  #
+  # <b><tt>ln_s(old, new, options = {})</tt></b>
+  # 
+  # Creates a symbolic link +new+ which points to +old+.  If +new+ already
+  # exists and it is a directory, creates a symbolic link +new/old+.  If +new+
+  # already exists and it is not a directory, raises Errno::EEXIST.  But if
+  # :force option is set, overwrite +new+.
+  # 
+  #   FileUtils.ln_s '/usr/bin/ruby', '/usr/local/bin/ruby'
+  #   FileUtils.ln_s 'verylongsourcefilename.c', 'c', :force => true
+  # 
+  # <b><tt>ln_s(list, destdir, options = {})</tt></b>
+  # 
+  # Creates several symbolic links in a directory, with each one pointing to the
+  # item in +list+.  If +destdir+ is not a directory, raises Errno::ENOTDIR.
+  #
+  # If +destdir+ is not a directory, raises Errno::ENOTDIR.
+  # 
+  #   FileUtils.ln_s Dir.glob('bin/*.rb'), '/home/aamine/bin'
+  # 
+  def ln_s(src, dest, options = {})
+    fu_check_options options, OPT_TABLE['ln_s']
+    fu_output_message "ln -s#{options[:force] ? 'f' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
+    return if options[:noop]
+    fu_each_src_dest0(src, dest) do |s,d|
+      remove_file d, true if options[:force]
+      File.symlink s, d
+    end
+  end
+  module_function :ln_s
+
+  alias symlink ln_s
+  module_function :symlink
+
+  OPT_TABLE['ln_s']    =
+  OPT_TABLE['symlink'] = [:force, :noop, :verbose]
+
+  #
+  # Options: noop verbose
+  # 
+  # Same as
+  #   #ln_s(src, dest, :force)
+  # 
+  def ln_sf(src, dest, options = {})
+    fu_check_options options, OPT_TABLE['ln_sf']
+    options = options.dup
+    options[:force] = true
+    ln_s src, dest, options
+  end
+  module_function :ln_sf
+
+  OPT_TABLE['ln_sf'] = [:noop, :verbose]
+
+  #
+  # Options: preserve noop verbose
+  #
+  # Copies a file content +src+ to +dest+.  If +dest+ is a directory,
+  # copies +src+ to +dest/src+.
+  #
+  # If +src+ is a list of files, then +dest+ must be a directory.
+  #
+  #   FileUtils.cp 'eval.c', 'eval.c.org'
+  #   FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6'
+  #   FileUtils.cp %w(cgi.rb complex.rb date.rb), '/usr/lib/ruby/1.6', :verbose => true
+  #   FileUtils.cp 'symlink', 'dest'   # copy content, "dest" is not a symlink
+  # 
+  def cp(src, dest, options = {})
+    fu_check_options options, OPT_TABLE['cp']
+    fu_output_message "cp#{options[:preserve] ? ' -p' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
+    return if options[:noop]
+    fu_each_src_dest(src, dest) do |s, d|
+      copy_file s, d, options[:preserve]
+    end
+  end
+  module_function :cp
+
+  alias copy cp
+  module_function :copy
+
+  OPT_TABLE['cp']   =
+  OPT_TABLE['copy'] = [:preserve, :noop, :verbose]
+
+  #
+  # Options: preserve noop verbose dereference_root remove_destination
+  # 
+  # Copies +src+ to +dest+. If +src+ is a directory, this method copies
+  # all its contents recursively. If +dest+ is a directory, copies
+  # +src+ to +dest/src+.
+  #
+  # +src+ can be a list of files.
+  # 
+  #   # Installing ruby library "mylib" under the site_ruby
+  #   FileUtils.rm_r site_ruby + '/mylib', :force
+  #   FileUtils.cp_r 'lib/', site_ruby + '/mylib'
+  # 
+  #   # Examples of copying several files to target directory.
+  #   FileUtils.cp_r %w(mail.rb field.rb debug/), site_ruby + '/tmail'
+  #   FileUtils.cp_r Dir.glob('*.rb'), '/home/aamine/lib/ruby', :noop => true, :verbose => true
+  #
+  #   # If you want to copy all contents of a directory instead of the
+  #   # directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
+  #   # use following code.
+  #   FileUtils.cp_r 'src/.', 'dest'     # cp_r('src', 'dest') makes src/dest,
+  #                                      # but this doesn't.
+  # 
+  def cp_r(src, dest, options = {})
+    fu_check_options options, OPT_TABLE['cp_r']
+    fu_output_message "cp -r#{options[:preserve] ? 'p' : ''}#{options[:remove_destination] ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
+    return if options[:noop]
+    options[:dereference_root] = true unless options.key?(:dereference_root)
+    fu_each_src_dest(src, dest) do |s, d|
+      copy_entry s, d, options[:preserve], options[:dereference_root], options[:remove_destination]
+    end
+  end
+  module_function :cp_r
+
+  OPT_TABLE['cp_r'] = [:preserve, :noop, :verbose,
+                       :dereference_root, :remove_destination]
+
+  #
+  # Copies a file system entry +src+ to +dest+.
+  # If +src+ is a directory, this method copies its contents recursively.
+  # This method preserves file types, c.f. symlink, directory...
+  # (FIFO, device files and etc. are not supported yet)
+  #
+  # Both of +src+ and +dest+ must be a path name.
+  # +src+ must exist, +dest+ must not exist.
+  #
+  # If +preserve+ is true, this method preserves owner, group, permissions
+  # and modified time.
+  #
+  # If +dereference_root+ is true, this method dereference tree root.
+  #
+  # If +remove_destination+ is true, this method removes each destination file before copy.
+  #
+  def copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)
+    Entry_.new(src, nil, dereference_root).traverse do |ent|
+      destent = Entry_.new(dest, ent.rel, false)
+      File.unlink destent.path if remove_destination && File.file?(destent.path)
+      ent.copy destent.path
+      ent.copy_metadata destent.path if preserve
+    end
+  end
+  module_function :copy_entry
+
+  #
+  # Copies file contents of +src+ to +dest+.
+  # Both of +src+ and +dest+ must be a path name.
+  #
+  def copy_file(src, dest, preserve = false, dereference = true)
+    ent = Entry_.new(src, nil, dereference)
+    ent.copy_file dest
+    ent.copy_metadata dest if preserve
+  end
+  module_function :copy_file
+
+  #
+  # Copies stream +src+ to +dest+.
+  # +src+ must respond to #read(n) and
+  # +dest+ must respond to #write(str).
+  #
+  def copy_stream(src, dest)
+    fu_copy_stream0 src, dest, fu_stream_blksize(src, dest)
+  end
+  module_function :copy_stream
+
+  #
+  # Options: force noop verbose
+  # 
+  # Moves file(s) +src+ to +dest+.  If +file+ and +dest+ exist on the different
+  # disk partition, the file is copied instead.
+  # 
+  #   FileUtils.mv 'badname.rb', 'goodname.rb'
+  #   FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', :force => true  # no error
+  # 
+  #   FileUtils.mv %w(junk.txt dust.txt), '/home/aamine/.trash/'
+  #   FileUtils.mv Dir.glob('test*.rb'), 'test', :noop => true, :verbose => true
+  # 
+  def mv(src, dest, options = {})
+    fu_check_options options, OPT_TABLE['mv']
+    fu_output_message "mv#{options[:force] ? ' -f' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
+    return if options[:noop]
+    fu_each_src_dest(src, dest) do |s, d|
+      destent = Entry_.new(d, nil, true)
+      begin
+        if destent.exist?
+          if destent.directory?
+            raise Errno::EEXIST, dest
+          else
+            destent.remove_file if rename_cannot_overwrite_file?
+          end
+        end
+        begin
+          File.rename s, d
+        rescue Errno::EXDEV
+          copy_entry s, d, true
+          if options[:secure]
+            remove_entry_secure s, options[:force]
+          else
+            remove_entry s, options[:force]
+          end
+        end
+      rescue SystemCallError
+        raise unless options[:force]
+      end
+    end
+  end
+  module_function :mv
+
+  alias move mv
+  module_function :move
+
+  OPT_TABLE['mv']   =
+  OPT_TABLE['move'] = [:force, :noop, :verbose, :secure]
+
+  def rename_cannot_overwrite_file?   #:nodoc:
+    /djgpp|cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
+  end
+  private_module_function :rename_cannot_overwrite_file?
+
+  #
+  # Options: force noop verbose
+  # 
+  # Remove file(s) specified in +list+.  This method cannot remove directories.
+  # All StandardErrors are ignored when the :force option is set.
+  # 
+  #   FileUtils.rm %w( junk.txt dust.txt )
+  #   FileUtils.rm Dir.glob('*.so')
+  #   FileUtils.rm 'NotExistFile', :force => true   # never raises exception
+  # 
+  def rm(list, options = {})
+    fu_check_options options, OPT_TABLE['rm']
+    list = fu_list(list)
+    fu_output_message "rm#{options[:force] ? ' -f' : ''} #{list.join ' '}" if options[:verbose]
+    return if options[:noop]
+
+    list.each do |path|
+      remove_file path, options[:force]
+    end
+  end
+  module_function :rm
+
+  alias remove rm
+  module_function :remove
+
+  OPT_TABLE['rm']     =
+  OPT_TABLE['remove'] = [:force, :noop, :verbose]
+
+  #
+  # Options: noop verbose
+  # 
+  # Equivalent to
+  #
+  #   #rm(list, :force => true)
+  #
+  def rm_f(list, options = {})
+    fu_check_options options, OPT_TABLE['rm_f']
+    options = options.dup
+    options[:force] = true
+    rm list, options
+  end
+  module_function :rm_f
+
+  alias safe_unlink rm_f
+  module_function :safe_unlink
+
+  OPT_TABLE['rm_f']        =
+  OPT_TABLE['safe_unlink'] = [:noop, :verbose]
+
+  #
+  # Options: force noop verbose secure
+  # 
+  # remove files +list+[0] +list+[1]... If +list+[n] is a directory,
+  # removes its all contents recursively. This method ignores
+  # StandardError when :force option is set.
+  # 
+  #   FileUtils.rm_r Dir.glob('/tmp/*')
+  #   FileUtils.rm_r '/', :force => true          #  :-)
+  #
+  # WARNING: This method causes local vulnerability
+  # if one of parent directories or removing directory tree are world
+  # writable (including /tmp, whose permission is 1777), and the current
+  # process has strong privilege such as Unix super user (root), and the
+  # system has symbolic link.  For secure removing, read the documentation
+  # of #remove_entry_secure carefully, and set :secure option to true.
+  # Default is :secure=>false.
+  #
+  # NOTE: This method calls #remove_entry_secure if :secure option is set.
+  # See also #remove_entry_secure.
+  # 
+  def rm_r(list, options = {})
+    fu_check_options options, OPT_TABLE['rm_r']
+    # options[:secure] = true unless options.key?(:secure)
+    list = fu_list(list)
+    fu_output_message "rm -r#{options[:force] ? 'f' : ''} #{list.join ' '}" if options[:verbose]
+    return if options[:noop]
+    list.each do |path|
+      if options[:secure]
+        remove_entry_secure path, options[:force]
+      else
+        remove_entry path, options[:force]
+      end
+    end
+  end
+  module_function :rm_r
+
+  OPT_TABLE['rm_r'] = [:force, :noop, :verbose, :secure]
+
+  #
+  # Options: noop verbose secure
+  # 
+  # Equivalent to
+  #
+  #   #rm_r(list, :force => true)
+  #
+  # WARNING: This method causes local vulnerability.
+  # Read the documentation of #rm_r first.
+  # 
+  def rm_rf(list, options = {})
+    fu_check_options options, OPT_TABLE['rm_rf']
+    options = options.dup
+    options[:force] = true
+    rm_r list, options
+  end
+  module_function :rm_rf
+
+  alias rmtree rm_rf
+  module_function :rmtree
+
+  OPT_TABLE['rm_rf']  =
+  OPT_TABLE['rmtree'] = [:noop, :verbose, :secure]
+
+  #
+  # This method removes a file system entry +path+.  +path+ shall be a
+  # regular file, a directory, or something.  If +path+ is a directory,
+  # remove it recursively.  This method is required to avoid TOCTTOU
+  # (time-of-check-to-time-of-use) local security vulnerability of #rm_r.
+  # #rm_r causes security hole when:
+  #
+  #   * Parent directory is world writable (including /tmp).
+  #   * Removing directory tree includes world writable directory.
+  #   * The system has symbolic link.
+  #
+  # To avoid this security hole, this method applies special preprocess.
+  # If +path+ is a directory, this method chown(2) and chmod(2) all
+  # removing directories.  This requires the current process is the
+  # owner of the removing whole directory tree, or is the super user (root).
+  #
+  # WARNING: You must ensure that *ALL* parent directories are not
+  # world writable.  Otherwise this method does not work.
+  # Only exception is temporary directory like /tmp and /var/tmp,
+  # whose permission is 1777.
+  #
+  # WARNING: Only the owner of the removing directory tree, or Unix super
+  # user (root) should invoke this method.  Otherwise this method does not
+  # work.
+  #
+  # For details of this security vulnerability, see Perl's case:
+  #
+  #   http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448
+  #   http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452
+  #
+  # For fileutils.rb, this vulnerability is reported in [ruby-dev:26100].
+  #
+  def remove_entry_secure(path, force = false)
+    unless fu_have_symlink?
+      remove_entry path, force
+      return
+    end
+    fullpath = File.expand_path(path)
+    st = File.lstat(fullpath)
+    unless st.directory?
+      File.unlink fullpath
+      return
+    end
+    # is a directory.
+    parent_st = File.stat(File.dirname(fullpath))
+    unless fu_world_writable?(parent_st)
+      remove_entry path, force
+      return
+    end
+    unless parent_st.sticky?
+      raise ArgumentError, "parent directory is world writable, FileUtils#remove_entry_secure does not work; abort: #{path.inspect} (parent directory mode #{'%o' % parent_st.mode})"
+    end
+    # freeze tree root
+    euid = Process.euid
+    File.open(fullpath + '/.') {|f|
+      unless fu_stat_identical_entry?(st, f.stat)
+        # symlink (TOC-to-TOU attack?)
+        File.unlink fullpath
+        return
+      end
+      f.chown euid, -1
+      f.chmod 0700
+    }
+    # ---- tree root is frozen ----
+    root = Entry_.new(path)
+    root.preorder_traverse do |ent|
+      if ent.directory?
+        ent.chown euid, -1
+        ent.chmod 0700
+      end
+    end
+    root.postorder_traverse do |ent|
+      begin
+        ent.remove
+      rescue
+        raise unless force
+      end
+    end
+  rescue
+    raise unless force
+  end
+  module_function :remove_entry_secure
+
+  def fu_world_writable?(st)
+    (st.mode & 0002) != 0
+  end
+  private_module_function :fu_world_writable?
+
+  def fu_have_symlink?   #:nodoc
+    File.symlink nil, nil
+  rescue NotImplementedError
+    return false
+  rescue
+    return true
+  end
+  private_module_function :fu_have_symlink?
+
+  def fu_stat_identical_entry?(a, b)   #:nodoc:
+    a.dev == b.dev and a.ino == b.ino
+  end
+  private_module_function :fu_stat_identical_entry?
+
+  #
+  # This method removes a file system entry +path+.
+  # +path+ might be a regular file, a directory, or something.
+  # If +path+ is a directory, remove it recursively.
+  #
+  # See also #remove_entry_secure.
+  #
+  def remove_entry(path, force = false)
+    Entry_.new(path).postorder_traverse do |ent|
+      begin
+        ent.remove
+      rescue
+        raise unless force
+      end
+    end
+  rescue
+    raise unless force
+  end
+  module_function :remove_entry
+
+  #
+  # Removes a file +path+.
+  # This method ignores StandardError if +force+ is true.
+  #
+  def remove_file(path, force = false)
+    Entry_.new(path).remove_file
+  rescue
+    raise unless force
+  end
+  module_function :remove_file
+
+  #
+  # Removes a directory +dir+ and its contents recursively.
+  # This method ignores StandardError if +force+ is true.
+  #
+  def remove_dir(path, force = false)
+    remove_entry path, force   # FIXME?? check if it is a directory
+  end
+  module_function :remove_dir
+
+  #
+  # Returns true if the contents of a file A and a file B are identical.
+  # 
+  #   FileUtils.compare_file('somefile', 'somefile')  #=> true
+  #   FileUtils.compare_file('/bin/cp', '/bin/mv')    #=> maybe false
+  #
+  def compare_file(a, b)
+    return false unless File.size(a) == File.size(b)
+    File.open(a, 'rb') {|fa|
+      File.open(b, 'rb') {|fb|
+        return compare_stream(fa, fb)
+      }
+    }
+  end
+  module_function :compare_file
+
+  alias identical? compare_file
+  alias cmp compare_file
+  module_function :identical?
+  module_function :cmp
+
+  #
+  # Returns true if the contents of a stream +a+ and +b+ are identical.
+  #
+  def compare_stream(a, b)
+    bsize = fu_stream_blksize(a, b)
+    sa = sb = nil
+    while sa == sb
+      sa = a.read(bsize)
+      sb = b.read(bsize)
+      unless sa and sb
+        if sa.nil? and sb.nil?
+          return true
+        end
+      end
+    end
+    false
+  end
+  module_function :compare_stream
+
+  #
+  # Options: mode preserve noop verbose
+  # 
+  # If +src+ is not same as +dest+, copies it and changes the permission
+  # mode to +mode+.  If +dest+ is a directory, destination is +dest+/+src+.
+  # This method removes destination before copy.
+  # 
+  #   FileUtils.install 'ruby', '/usr/local/bin/ruby', :mode => 0755, :verbose => true
+  #   FileUtils.install 'lib.rb', '/usr/local/lib/ruby/site_ruby', :verbose => true
+  # 
+  def install(src, dest, options = {})
+    fu_check_options options, OPT_TABLE['install']
+    fu_output_message "install -c#{options[:preserve] && ' -p'}#{options[:mode] ? (' -m 0%o' % options[:mode]) : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
+    return if options[:noop]
+    fu_each_src_dest(src, dest) do |s, d|
+      unless File.exist?(d) and compare_file(s, d)
+        remove_file d, true
+        st = File.stat(s) if options[:preserve]
+        copy_file s, d
+        File.utime st.atime, st.mtime, d if options[:preserve]
+        File.chmod options[:mode], d if options[:mode]
+      end
+    end
+  end
+  module_function :install
+
+  OPT_TABLE['install'] = [:mode, :preserve, :noop, :verbose]
+
+  #
+  # Options: noop verbose
+  # 
+  # Changes permission bits on the named files (in +list+) to the bit pattern
+  # represented by +mode+.
+  # 
+  #   FileUtils.chmod 0755, 'somecommand'
+  #   FileUtils.chmod 0644, %w(my.rb your.rb his.rb her.rb)
+  #   FileUtils.chmod 0755, '/usr/bin/ruby', :verbose => true
+  # 
+  def chmod(mode, list, options = {})
+    fu_check_options options, OPT_TABLE['chmod']
+    list = fu_list(list)
+    fu_output_message sprintf('chmod %o %s', mode, list.join(' ')) if options[:verbose]
+    return if options[:noop]
+    list.each do |path|
+      Entry_.new(path).chmod mode
+    end
+  end
+  module_function :chmod
+
+  OPT_TABLE['chmod'] = [:noop, :verbose]
+
+  #
+  # Options: noop verbose force
+  # 
+  # Changes permission bits on the named files (in +list+)
+  # to the bit pattern represented by +mode+.
+  # 
+  #   FileUtils.chmod_R 0700, "/tmp/app.#{$$}"
+  # 
+  def chmod_R(mode, list, options = {})
+    fu_check_options options, OPT_TABLE['chmod_R']
+    list = fu_list(list)
+    fu_output_message sprintf('chmod -R%s %o %s',
+                              (options[:force] ? 'f' : ''),
+                              mode, list.join(' ')) if options[:verbose]
+    return if options[:noop]
+    list.each do |root|
+      Entry_.new(root).traverse do |ent|
+        begin
+          ent.chmod mode
+        rescue
+          raise unless options[:force]
+        end
+      end
+    end
+  end
+  module_function :chmod_R
+
+  OPT_TABLE['chmod_R'] = [:noop, :verbose, :force]
+
+  #
+  # Options: noop verbose
+  # 
+  # Changes owner and group on the named files (in +list+)
+  # to the user +user+ and the group +group+.  +user+ and +group+
+  # may be an ID (Integer/String) or a name (String).
+  # If +user+ or +group+ is nil, this method does not change
+  # the attribute.
+  # 
+  #   FileUtils.chown 'root', 'staff', '/usr/local/bin/ruby'
+  #   FileUtils.chown nil, 'bin', Dir.glob('/usr/bin/*'), :verbose => true
+  # 
+  def chown(user, group, list, options = {})
+    fu_check_options options, OPT_TABLE['chown']
+    list = fu_list(list)
+    fu_output_message sprintf('chown %s%s',
+                              [user,group].compact.join(':') + ' ',
+                              list.join(' ')) if options[:verbose]
+    return if options[:noop]
+    uid = fu_get_uid(user)
+    gid = fu_get_gid(group)
+    list.each do |path|
+      Entry_.new(path).chown uid, gid
+    end
+  end
+  module_function :chown
+
+  OPT_TABLE['chown'] = [:noop, :verbose]
+
+  #
+  # Options: noop verbose force
+  # 
+  # Changes owner and group on the named files (in +list+)
+  # to the user +user+ and the group +group+ recursively.
+  # +user+ and +group+ may be an ID (Integer/String) or
+  # a name (String).  If +user+ or +group+ is nil, this
+  # method does not change the attribute.
+  # 
+  #   FileUtils.chown_R 'www', 'www', '/var/www/htdocs'
+  #   FileUtils.chown_R 'cvs', 'cvs', '/var/cvs', :verbose => true
+  # 
+  def chown_R(user, group, list, options = {})
+    fu_check_options options, OPT_TABLE['chown_R']
+    list = fu_list(list)
+    fu_output_message sprintf('chown -R%s %s%s',
+                              (options[:force] ? 'f' : ''),
+                              [user,group].compact.join(':') + ' ',
+                              list.join(' ')) if options[:verbose]
+    return if options[:noop]
+    uid = fu_get_uid(user)
+    gid = fu_get_gid(group)
+    return unless uid or gid
+    list.each do |root|
+      Entry_.new(root).traverse do |ent|
+        begin
+          ent.chown uid, gid
+        rescue
+          raise unless options[:force]
+        end
+      end
+    end
+  end
+  module_function :chown_R
+
+  OPT_TABLE['chown_R'] = [:noop, :verbose, :force]
+
+  begin
+    require 'etc'
+
+    def fu_get_uid(user)   #:nodoc:
+      return nil unless user
+      user = user.to_s
+      if /\A\d+\z/ =~ user
+      then user.to_i
+      else Etc.getpwnam(user).uid
+      end
+    end
+    private_module_function :fu_get_uid
+
+    def fu_get_gid(group)   #:nodoc:
+      return nil unless group
+      if /\A\d+\z/ =~ group
+      then group.to_i
+      else Etc.getgrnam(group).gid
+      end
+    end
+    private_module_function :fu_get_gid
+
+  rescue LoadError
+    # need Win32 support???
+
+    def fu_get_uid(user)   #:nodoc:
+      user    # FIXME
+    end
+    private_module_function :fu_get_uid
+
+    def fu_get_gid(group)   #:nodoc:
+      group   # FIXME
+    end
+    private_module_function :fu_get_gid
+  end
+
+  #
+  # Options: noop verbose
+  # 
+  # Updates modification time (mtime) and access time (atime) of file(s) in
+  # +list+.  Files are created if they don't exist.
+  # 
+  #   FileUtils.touch 'timestamp'
+  #   FileUtils.touch Dir.glob('*.c');  system 'make'
+  # 
+  def touch(list, options = {})
+    fu_check_options options, OPT_TABLE['touch']
+    list = fu_list(list)
+    created = nocreate = options[:nocreate]
+    t = options[:mtime]
+    if options[:verbose]
+      fu_output_message "touch #{nocreate ? ' -c' : ''}#{t ? t.strftime(' -t %Y%m%d%H%M.%S') : ''}#{list.join ' '}"
+    end
+    return if options[:noop]
+    list.each do |path|
+      created = nocreate
+      begin
+        File.utime(t, t, path)
+      rescue Errno::ENOENT
+        raise if created
+        File.open(path, 'a') {
+          ;
+        }
+        created = true
+        retry if t
+      end
+    end
+  end
+  module_function :touch
+
+  OPT_TABLE['touch'] = [:noop, :verbose, :mtime, :nocreate]
+
+  private
+
+  module StreamUtils_
+    private
+
+    def fu_windows?
+      /mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
+    end
+
+    def fu_copy_stream0(src, dest, blksize)   #:nodoc:
+      # FIXME: readpartial?
+      while s = src.read(blksize)
+        dest.write s
+      end
+    end
+
+    def fu_stream_blksize(*streams)
+      streams.each do |s|
+        next unless s.respond_to?(:stat)
+        size = fu_blksize(s.stat)
+        return size if size
+      end
+      fu_default_blksize()
+    end
+
+    def fu_blksize(st)
+      s = st.blksize
+      return nil unless s
+      return nil if s == 0
+      s
+    end
+
+    def fu_default_blksize
+      1024
+    end
+  end
+
+  include StreamUtils_
+  extend StreamUtils_
+
+  class Entry_   #:nodoc: internal use only
+    include StreamUtils_
+
+    def initialize(a, b = nil, deref = false)
+      @prefix = @rel = @path = nil
+      if b
+        @prefix = a
+        @rel = b
+      else
+        @path = a
+      end
+      @deref = deref
+      @stat = nil
+      @lstat = nil
+    end
+
+    def inspect
+      "\#<#{self.class} #{path()}>"
+    end
+
+    def path
+      if @path
+        @path.to_str
+      else
+        join(@prefix, @rel)
+      end
+    end
+
+    def prefix
+      @prefix || @path
+    end
+
+    def rel
+      @rel
+    end
+
+    def dereference?
+      @deref
+    end
+
+    def exist?
+      lstat! ? true : false
+    end
+
+    def file?
+      s = lstat!
+      s and s.file?
+    end
+
+    def directory?
+      s = lstat!
+      s and s.directory?
+    end
+
+    def symlink?
+      s = lstat!
+      s and s.symlink?
+    end
+
+    def chardev?
+      s = lstat!
+      s and s.chardev?
+    end
+
+    def blockdev?
+      s = lstat!
+      s and s.blockdev?
+    end
+
+    def socket?
+      s = lstat!
+      s and s.socket?
+    end
+
+    def pipe?
+      s = lstat!
+      s and s.pipe?
+    end
+
+    S_IF_DOOR = 0xD000
+
+    def door?
+      s = lstat!
+      s and (s.mode & 0xF000 == S_IF_DOOR)
+    end
+
+    def entries
+      Dir.entries(path())\
+          .reject {|n| n == '.' or n == '..' }\
+          .map {|n| Entry_.new(prefix(), join(rel(), n.untaint)) }
+    end
+
+    def stat
+      return @stat if @stat
+      if lstat() and lstat().symlink?
+        @stat = File.stat(path())
+      else
+        @stat = lstat()
+      end
+      @stat
+    end
+
+    def stat!
+      return @stat if @stat
+      if lstat! and lstat!.symlink?
+        @stat = File.stat(path())
+      else
+        @stat = lstat!
+      end
+      @stat
+    rescue SystemCallError
+      nil
+    end
+
+    def lstat
+      if dereference?
+        @lstat ||= File.stat(path())
+      else
+        @lstat ||= File.lstat(path())
+      end
+    end
+
+    def lstat!
+      lstat()
+    rescue SystemCallError
+      nil
+    end
+
+    def chmod(mode)
+      if symlink?
+        File.lchmod mode, path() if have_lchmod?
+      else
+        File.chmod mode, path()
+      end
+    end
+
+    def chown(uid, gid)
+      if symlink?
+        File.lchown uid, gid, path() if have_lchown?
+      else
+        File.chown uid, gid, path()
+      end
+    end
+
+    def copy(dest)
+      case
+      when file?
+        copy_file dest
+      when directory?
+        begin
+          Dir.mkdir dest
+        rescue
+          raise unless File.directory?(dest)
+        end
+      when symlink?
+        File.symlink File.readlink(path()), dest
+      when chardev?
+        raise "cannot handle device file" unless File.respond_to?(:mknod)
+        mknod dest, ?c, 0666, lstat().rdev
+      when blockdev?
+        raise "cannot handle device file" unless File.respond_to?(:mknod)
+        mknod dest, ?b, 0666, lstat().rdev
+      when socket?
+        raise "cannot handle socket" unless File.respond_to?(:mknod)
+        mknod dest, nil, lstat().mode, 0
+      when pipe?
+        raise "cannot handle FIFO" unless File.respond_to?(:mkfifo)
+        mkfifo dest, 0666
+      when door?
+        raise "cannot handle door: #{path()}"
+      else
+        raise "unknown file type: #{path()}"
+      end
+    end
+
+    def copy_file(dest)
+      st = stat()
+      File.open(path(),  'rb') {|r|
+        File.open(dest, 'wb', st.mode) {|w|
+          fu_copy_stream0 r, w, (fu_blksize(st) || fu_default_blksize())
+        }
+      }
+    end
+
+    def copy_metadata(path)
+      st = lstat()
+      File.utime st.atime, st.mtime, path
+      begin
+        File.chown st.uid, st.gid, path
+      rescue Errno::EPERM
+        # clear setuid/setgid
+        File.chmod st.mode & 01777, path
+      else
+        File.chmod st.mode, path
+      end
+    end
+
+    def remove
+      if directory?
+        remove_dir1
+      else
+        remove_file
+      end
+    end
+
+    def remove_dir1
+      platform_support {
+        Dir.rmdir path().sub(%r</\z>, '')
+      }
+    end
+
+    def remove_file
+      platform_support {
+        File.unlink path
+      }
+    end
+
+    def platform_support
+      return yield unless fu_windows?
+      first_time_p = true
+      begin
+        yield
+      rescue Errno::ENOENT
+        raise
+      rescue => err
+        if first_time_p
+          first_time_p = false
+          begin
+            File.chmod 0700, path()   # Windows does not have symlink
+            retry
+          rescue SystemCallError
+          end
+        end
+        raise err
+      end
+    end
+
+    def preorder_traverse
+      stack = [self]
+      while ent = stack.pop
+        yield ent
+        stack.concat ent.entries.reverse if ent.directory?
+      end
+    end
+
+    alias traverse preorder_traverse
+
+    def postorder_traverse
+      if directory?
+        entries().each do |ent|
+          ent.postorder_traverse do |e|
+            yield e
+          end
+        end
+      end
+      yield self
+    end
+
+    private
+
+    $fileutils_rb_have_lchmod = nil
+
+    def have_lchmod?
+      # This is not MT-safe, but it does not matter.
+      if $fileutils_rb_have_lchmod == nil
+        $fileutils_rb_have_lchmod = check_have_lchmod?
+      end
+      $fileutils_rb_have_lchmod
+    end
+
+    def check_have_lchmod?
+      return false unless File.respond_to?(:lchmod)
+      File.lchmod 0
+      return true
+    rescue NotImplementedError
+      return false
+    end
+
+    $fileutils_rb_have_lchown = nil
+
+    def have_lchown?
+      # This is not MT-safe, but it does not matter.
+      if $fileutils_rb_have_lchown == nil
+        $fileutils_rb_have_lchown = check_have_lchown?
+      end
+      $fileutils_rb_have_lchown
+    end
+
+    def check_have_lchown?
+      return false unless File.respond_to?(:lchown)
+      File.lchown nil, nil
+      return true
+    rescue NotImplementedError
+      return false
+    end
+
+    def join(dir, base)
+      return dir.to_str if not base or base == '.'
+      return base.to_str if not dir or dir == '.'
+      File.join(dir, base)
+    end
+  end   # class Entry_
+
+  def fu_list(arg)   #:nodoc:
+    [arg].flatten.map {|path| path.to_str }
+  end
+  private_module_function :fu_list
+
+  def fu_each_src_dest(src, dest)   #:nodoc:
+    fu_each_src_dest0(src, dest) do |s, d|
+      raise ArgumentError, "same file: #{s} and #{d}" if fu_same?(s, d)
+      yield s, d
+    end
+  end
+  private_module_function :fu_each_src_dest
+
+  def fu_each_src_dest0(src, dest)   #:nodoc:
+    if src.is_a?(Array)
+      src.each do |s|
+        s = s.to_str
+        yield s, File.join(dest, File.basename(s))
+      end
+    else
+      src = src.to_str
+      if File.directory?(dest)
+        yield src, File.join(dest, File.basename(src))
+      else
+        yield src, dest.to_str
+      end
+    end
+  end
+  private_module_function :fu_each_src_dest0
+
+  def fu_same?(a, b)   #:nodoc:
+    if fu_have_st_ino?
+      st1 = File.stat(a)
+      st2 = File.stat(b)
+      st1.dev == st2.dev and st1.ino == st2.ino
+    else
+      File.expand_path(a) == File.expand_path(b)
+    end
+  rescue Errno::ENOENT
+    return false
+  end
+  private_module_function :fu_same?
+
+  def fu_have_st_ino?   #:nodoc:
+    not fu_windows?
+  end
+  private_module_function :fu_have_st_ino?
+
+  def fu_check_options(options, optdecl)   #:nodoc:
+    h = options.dup
+    optdecl.each do |opt|
+      h.delete opt
+    end
+    raise ArgumentError, "no such option: #{h.keys.join(' ')}" unless h.empty?
+  end
+  private_module_function :fu_check_options
+
+  def fu_update_option(args, new)   #:nodoc:
+    if args.last.is_a?(Hash)
+      args[-1] = args.last.dup.update(new)
+    else
+      args.push new
+    end
+    args
+  end
+  private_module_function :fu_update_option
+
+  @fileutils_output = $stderr
+  @fileutils_label  = ''
+
+  def fu_output_message(msg)   #:nodoc:
+    @fileutils_output ||= $stderr
+    @fileutils_label  ||= ''
+    @fileutils_output.puts @fileutils_label + msg
+  end
+  private_module_function :fu_output_message
+
+  #
+  # Returns an Array of method names which have any options.
+  #
+  #   p FileUtils.commands  #=> ["chmod", "cp", "cp_r", "install", ...]
+  #
+  def FileUtils.commands
+    OPT_TABLE.keys
+  end
+
+  #
+  # Returns an Array of option names.
+  #
+  #   p FileUtils.options  #=> ["noop", "force", "verbose", "preserve", "mode"]
+  #
+  def FileUtils.options
+    OPT_TABLE.values.flatten.uniq.map {|sym| sym.to_s }
+  end
+
+  #
+  # Returns true if the method +mid+ have an option +opt+.
+  #
+  #   p FileUtils.have_option?(:cp, :noop)     #=> true
+  #   p FileUtils.have_option?(:rm, :force)    #=> true
+  #   p FileUtils.have_option?(:rm, :perserve) #=> false
+  #
+  def FileUtils.have_option?(mid, opt)
+    li = OPT_TABLE[mid.to_s] or raise ArgumentError, "no such method: #{mid}"
+    li.include?(opt)
+  end
+
+  #
+  # Returns an Array of option names of the method +mid+.
+  #
+  #   p FileUtils.options(:rm)  #=> ["noop", "verbose", "force"]
+  #
+  def FileUtils.options_of(mid)
+    OPT_TABLE[mid.to_s].map {|sym| sym.to_s }
+  end
+
+  #
+  # Returns an Array of method names which have the option +opt+.
+  #
+  #   p FileUtils.collect_method(:preserve) #=> ["cp", "cp_r", "copy", "install"]
+  #
+  def FileUtils.collect_method(opt)
+    OPT_TABLE.keys.select {|m| OPT_TABLE[m].include?(opt) }
+  end
+
+  METHODS = singleton_methods() - %w( private_module_function
+      commands options have_option? options_of collect_method )
+
+  # 
+  # This module has all methods of FileUtils module, but it outputs messages
+  # before acting.  This equates to passing the <tt>:verbose</tt> flag to
+  # methods in FileUtils.
+  # 
+  module Verbose
+    include FileUtils
+    @fileutils_output  = $stderr
+    @fileutils_label   = ''
+    ::FileUtils.collect_method(:verbose).each do |name|
+      module_eval(<<-EOS, __FILE__, __LINE__ + 1)
+        def #{name}(*args)
+          super(*fu_update_option(args, :verbose => true))
+        end
+        private :#{name}
+      EOS
+    end
+    extend self
+    class << self
+      ::FileUtils::METHODS.each do |m|
+        public m
+      end
+    end
+  end
+
+  # 
+  # This module has all methods of FileUtils module, but never changes
+  # files/directories.  This equates to passing the <tt>:noop</tt> flag
+  # to methods in FileUtils.
+  # 
+  module NoWrite
+    include FileUtils
+    @fileutils_output  = $stderr
+    @fileutils_label   = ''
+    ::FileUtils.collect_method(:noop).each do |name|
+      module_eval(<<-EOS, __FILE__, __LINE__ + 1)
+        def #{name}(*args)
+          super(*fu_update_option(args, :noop => true))
+        end
+        private :#{name}
+      EOS
+    end
+    extend self
+    class << self
+      ::FileUtils::METHODS.each do |m|
+        public m
+      end
+    end
+  end
+
+  # 
+  # This module has all methods of FileUtils module, but never changes
+  # files/directories, with printing message before acting.
+  # This equates to passing the <tt>:noop</tt> and <tt>:verbose</tt> flag
+  # to methods in FileUtils.
+  # 
+  module DryRun
+    include FileUtils
+    @fileutils_output  = $stderr
+    @fileutils_label   = ''
+    ::FileUtils.collect_method(:noop).each do |name|
+      module_eval(<<-EOS, __FILE__, __LINE__ + 1)
+        def #{name}(*args)
+          super(*fu_update_option(args, :noop => true, :verbose => true))
+        end
+        private :#{name}
+      EOS
+    end
+    extend self
+    class << self
+      ::FileUtils::METHODS.each do |m|
+        public m
+      end
+    end
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/finalize.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/finalize.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/finalize.rb	(revision 18425)
@@ -0,0 +1,193 @@
+#--
+#   finalizer.rb - 
+#   	$Release Version: 0.3$
+#   	$Revision: 1.4 $
+#   	$Date: 1998/02/27 05:34:33 $
+#   	by Keiju ISHITSUKA
+#++
+#
+# Usage:
+#
+# add dependency R_method(obj, dependant)
+#   add(obj, dependant, method = :finalize, *opt)
+#   add_dependency(obj, dependant, method = :finalize, *opt)
+#
+# delete dependency R_method(obj, dependant)
+#   delete(obj_or_id, dependant, method = :finalize)
+#   delete_dependency(obj_or_id, dependant, method = :finalize)
+#
+# delete dependency R_*(obj, dependant)
+#   delete_all_dependency(obj_or_id, dependant)
+#
+# delete dependency R_method(*, dependant)
+#   delete_by_dependant(dependant, method = :finalize)
+#
+# delete dependency R_*(*, dependant)
+#   delete_all_by_dependant(dependant)
+#
+# delete all dependency R_*(*, *)
+#   delete_all
+#
+# finalize the dependant connected by dependency R_method(obj, dependtant).
+#   finalize(obj_or_id, dependant, method = :finalize)
+#   finalize_dependency(obj_or_id, dependant, method = :finalize)
+#
+# finalize all dependants connected by dependency R_*(obj, dependtant).
+#   finalize_all_dependency(obj_or_id, dependant)
+#
+# finalize the dependant connected by dependency R_method(*, dependtant).
+#   finalize_by_dependant(dependant, method = :finalize)
+#
+# finalize all dependants connected by dependency R_*(*, dependant).
+#   finalize_all_by_dependant(dependant)
+#
+# finalize all dependency registered to the Finalizer.
+#   finalize_all
+#
+# stop invoking Finalizer on GC.
+#   safe{..}
+#
+
+module Finalizer
+  RCS_ID='-$Id: finalize.rb,v 1.4 1998/02/27 05:34:33 keiju Exp keiju $-'
+
+  class <<self
+    # @dependency: {id => [[dependant, method, *opt], ...], ...}
+
+    # add dependency R_method(obj, dependant)
+    def add_dependency(obj, dependant, method = :finalize, *opt)
+      ObjectSpace.call_finalizer(obj)
+      method = method.intern unless method.kind_of?(Integer)
+      assoc = [dependant, method].concat(opt)
+      if dep = @dependency[obj.object_id]
+	dep.push assoc
+      else
+	@dependency[obj.object_id] = [assoc]
+      end
+    end
+    alias add add_dependency
+
+    # delete dependency R_method(obj, dependant)
+    def delete_dependency(id, dependant, method = :finalize)
+      id = id.object_id unless id.kind_of?(Integer)
+      method = method.intern unless method.kind_of?(Integer)
+      for assoc in @dependency[id]
+	assoc.delete_if do
+	  |d, m, *o|
+	  d == dependant && m == method
+	end
+	@dependency.delete(id) if assoc.empty?
+      end
+    end
+    alias delete delete_dependency
+
+    # delete dependency R_*(obj, dependant)
+    def delete_all_dependency(id, dependant)
+      id = id.object_id unless id.kind_of?(Integer)
+      method = method.intern unless method.kind_of?(Integer)
+      for assoc in @dependency[id]
+	assoc.delete_if do
+	  |d, m, *o|
+	  d == dependant
+	end
+	@dependency.delete(id) if assoc.empty?
+      end
+    end
+
+    # delete dependency R_method(*, dependant)
+    def delete_by_dependant(dependant, method = :finalize)
+      method = method.intern unless method.kind_of?(Integer)
+      for id in @dependency.keys
+	delete(id, dependant, method)
+      end
+    end
+
+    # delete dependency R_*(*, dependant)
+    def delete_all_by_dependant(dependant)
+      for id in @dependency.keys
+	delete_all_dependency(id, dependant)
+      end
+    end
+
+    # finalize the depandant connected by dependency R_method(obj, dependtant)
+    def finalize_dependency(id, dependant, method = :finalize)
+      id = id.object_id unless id.kind_of?(Integer)
+      method = method.intern unless method.kind_of?(Integer)
+      for assocs in @dependency[id]
+	assocs.delete_if do
+	  |d, m, *o|
+	  d.send(m, id, *o) if ret = d == dependant && m == method
+	  ret
+	end
+	@dependency.delete(id) if assoc.empty?
+      end
+    end
+    alias finalize finalize_dependency
+
+    # finalize all dependants connected by dependency R_*(obj, dependtant)
+    def finalize_all_dependency(id, dependant)
+      id = id.object_id unless id.kind_of?(Integer)
+      method = method.intern unless method.kind_of?(Integer)
+      for assoc in @dependency[id]
+	assoc.delete_if do
+	  |d, m, *o|
+	  d.send(m, id, *o) if ret = d == dependant
+	end
+	@dependency.delete(id) if assoc.empty?
+      end
+    end
+
+    # finalize the dependant connected by dependency R_method(*, dependtant)
+    def finalize_by_dependant(dependant, method = :finalize)
+      method = method.intern unless method.kind_of?(Integer)
+      for id in @dependency.keys
+	finalize(id, dependant, method)
+      end
+    end
+
+    # finalize all dependants connected by dependency R_*(*, dependtant)
+    def finalize_all_by_dependant(dependant)
+      for id in @dependency.keys
+	finalize_all_dependency(id, dependant)
+      end
+    end
+
+    # finalize all dependants registered to the Finalizer.
+    def finalize_all
+      for id, assocs in @dependency
+	for dependant, method, *opt in assocs
+	  dependant.send(method, id, *opt)
+	end
+	assocs.clear
+      end
+    end
+
+    # method to call finalize_* safely.
+    def safe
+      old_status = Thread.critical
+      Thread.critical = true
+      ObjectSpace.remove_finalizer(@proc)
+      begin
+	yield
+      ensure
+	ObjectSpace.add_finalizer(@proc)
+	Thread.critical = old_status
+      end
+    end
+
+    private
+
+    # registering function to ObjectSpace#add_finalizer
+    def final_of(id)
+      if assocs = @dependency.delete(id)
+	for dependant, method, *opt in assocs
+	  dependant.send(method, id, *opt)
+	end
+      end
+    end
+
+  end
+  @dependency = Hash.new
+  @proc = proc{|id| final_of(id)}
+  ObjectSpace.add_finalizer(@proc)
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/find.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/find.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/find.rb	(revision 18425)
@@ -0,0 +1,79 @@
+#
+# find.rb: the Find module for processing all files under a given directory.
+#
+
+#
+# The +Find+ module supports the top-down traversal of a set of file paths.
+#
+# For example, to total the size of all files under your home directory,
+# ignoring anything in a "dot" directory (e.g. $HOME/.ssh):
+#
+#   require 'find'
+#
+#   total_size = 0
+#
+#   Find.find(ENV["HOME"]) do |path|
+#     if FileTest.directory?(path)
+#       if File.basename(path)[0] == ?.
+#         Find.prune       # Don't look any further into this directory.
+#       else
+#         next
+#       end
+#     else
+#       total_size += FileTest.size(path)
+#     end
+#   end
+#
+module Find
+
+  #
+  # Calls the associated block with the name of every file and directory listed
+  # as arguments, then recursively on their subdirectories, and so on.
+  #
+  # See the +Find+ module documentation for an example.
+  #
+  def find(*paths) # :yield: path
+    paths.collect!{|d| d.dup}
+    while file = paths.shift
+      catch(:prune) do
+	yield file.dup.taint
+        next unless File.exist? file
+	begin
+	  if File.lstat(file).directory? then
+	    d = Dir.open(file)
+	    begin
+	      for f in d
+		next if f == "." or f == ".."
+		if File::ALT_SEPARATOR and file =~ /^(?:[\/\\]|[A-Za-z]:[\/\\]?)$/ then
+		  f = file + f
+		elsif file == "/" then
+		  f = "/" + f
+		else
+		  f = File.join(file, f)
+		end
+		paths.unshift f.untaint
+	      end
+	    ensure
+	      d.close
+	    end
+	  end
+        rescue Errno::ENOENT, Errno::EACCES
+	end
+      end
+    end
+  end
+
+  #
+  # Skips the current file or directory, restarting the loop with the next
+  # entry. If the current file is a directory, that directory will not be
+  # recursively entered. Meaningful only within the block associated with
+  # Find::find.
+  #
+  # See the +Find+ module documentation for an example.
+  #
+  def prune
+    throw :prune
+  end
+
+  module_function :find, :prune
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/forwardable.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/forwardable.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/forwardable.rb	(revision 18425)
@@ -0,0 +1,218 @@
+# = forwardable - Support for the Delegation Pattern
+#
+#    $Release Version: 1.1$
+#    $Revision: 11708 $
+#    $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#    by Keiju ISHITSUKA(keiju@ishitsuka.com)
+#
+#    Documentation by James Edward Gray II and Gavin Sinclair
+#
+# == Introduction
+#
+# This library allows you delegate method calls to an object, on a method by
+# method basis.  You can use Forwardable to setup this delegation at the class
+# level, or SingleForwardable to handle it at the object level.
+#
+# == Notes
+#
+# Be advised, RDoc will not detect delegated methods.
+#
+# <b>forwardable.rb provides single-method delegation via the
+# def_delegator() and def_delegators() methods.  For full-class
+# delegation via DelegateClass(), see delegate.rb.</b>
+#
+# == Examples
+#
+# === Forwardable
+#
+# Forwardable makes building a new class based on existing work, with a proper
+# interface, almost trivial.  We want to rely on what has come before obviously,
+# but with delegation we can take just the methods we need and even rename them
+# as appropriate.  In many cases this is preferable to inheritance, which gives
+# us the entire old interface, even if much of it isn't needed.
+#
+#   class Queue
+#     extend Forwardable
+#     
+#     def initialize
+#       @q = [ ]    # prepare delegate object
+#     end
+#     
+#     # setup prefered interface, enq() and deq()...
+#     def_delegator :@q, :push, :enq
+#     def_delegator :@q, :shift, :deq
+#     
+#     # support some general Array methods that fit Queues well
+#     def_delegators :@q, :clear, :first, :push, :shift, :size
+#   end
+# 
+#   q = Queue.new
+#   q.enq 1, 2, 3, 4, 5
+#   q.push 6
+# 
+#   q.shift    # => 1
+#   while q.size > 0
+#     puts q.deq
+#   end
+# 
+#   q.enq "Ruby", "Perl", "Python"
+#   puts q.first
+#   q.clear
+#   puts q.first
+#
+# <i>Prints:</i>
+#
+#   2
+#   3
+#   4
+#   5
+#   6
+#   Ruby
+#   nil
+#
+# === SingleForwardable
+#
+#    printer = String.new
+#    printer.extend SingleForwardable        # prepare object for delegation
+#    printer.def_delegator "STDOUT", "puts"  # add delegation for STDOUT.puts()
+#    printer.puts "Howdy!"
+#
+# <i>Prints:</i>
+#
+#    Howdy!
+
+#
+# The Forwardable module provides delegation of specified
+# methods to a designated object, using the methods #def_delegator
+# and #def_delegators.
+#
+# For example, say you have a class RecordCollection which
+# contains an array <tt>@records</tt>.  You could provide the lookup method
+# #record_number(), which simply calls #[] on the <tt>@records</tt>
+# array, like this:
+#
+#   class RecordCollection
+#     extend Forwardable
+#     def_delegator :@records, :[], :record_number
+#   end
+#
+# Further, if you wish to provide the methods #size, #<<, and #map,
+# all of which delegate to @records, this is how you can do it:
+#
+#   class RecordCollection
+#     # extend Forwardable, but we did that above
+#     def_delegators :@records, :size, :<<, :map
+#   end
+#
+# Also see the example at forwardable.rb.
+#
+module Forwardable
+
+  @debug = nil
+  class<<self
+    # force Forwardable to show up in stack backtraces of delegated methods
+    attr_accessor :debug
+  end
+
+  #
+  # Shortcut for defining multiple delegator methods, but with no
+  # provision for using a different name.  The following two code
+  # samples have the same effect:
+  #
+  #   def_delegators :@records, :size, :<<, :map
+  #
+  #   def_delegator :@records, :size
+  #   def_delegator :@records, :<<
+  #   def_delegator :@records, :map
+  #
+  # See the examples at Forwardable and forwardable.rb.
+  #
+  def def_instance_delegators(accessor, *methods)
+    for method in methods
+      def_instance_delegator(accessor, method)
+    end
+  end
+
+  #
+  # Defines a method _method_ which delegates to _obj_ (i.e. it calls
+  # the method of the same name in _obj_).  If _new_name_ is
+  # provided, it is used as the name for the delegate method.
+  #
+  # See the examples at Forwardable and forwardable.rb.
+  #
+  def def_instance_delegator(accessor, method, ali = method)
+    accessor = accessor.id2name if accessor.kind_of?(Integer)
+    method = method.id2name if method.kind_of?(Integer)
+    ali = ali.id2name if ali.kind_of?(Integer)
+
+    module_eval(<<-EOS, "(__FORWARDABLE__)", 1)
+      def #{ali}(*args, &block)
+	begin
+	  #{accessor}.__send__(:#{method}, *args, &block)
+	rescue Exception
+	  $@.delete_if{|s| /^\\(__FORWARDABLE__\\):/ =~ s} unless Forwardable::debug
+	  Kernel::raise
+	end
+      end
+    EOS
+  end
+
+  alias def_delegators def_instance_delegators
+  alias def_delegator def_instance_delegator
+end
+
+#
+# The SingleForwardable module provides delegation of specified
+# methods to a designated object, using the methods #def_delegator
+# and #def_delegators.  This module is similar to Forwardable, but it works on
+# objects themselves, instead of their defining classes.
+#
+# Also see the example at forwardable.rb.
+#
+module SingleForwardable
+  #
+  # Shortcut for defining multiple delegator methods, but with no
+  # provision for using a different name.  The following two code
+  # samples have the same effect:
+  #
+  #   single_forwardable.def_delegators :@records, :size, :<<, :map
+  #
+  #   single_forwardable.def_delegator :@records, :size
+  #   single_forwardable.def_delegator :@records, :<<
+  #   single_forwardable.def_delegator :@records, :map
+  #
+  # See the example at forwardable.rb.
+  #
+  def def_singleton_delegators(accessor, *methods)
+    for method in methods
+      def_singleton_delegator(accessor, method)
+    end
+  end
+
+  #
+  # Defines a method _method_ which delegates to _obj_ (i.e. it calls
+  # the method of the same name in _obj_).  If _new_name_ is
+  # provided, it is used as the name for the delegate method.
+  #
+  # See the example at forwardable.rb.
+  #
+  def def_singleton_delegator(accessor, method, ali = method)
+    accessor = accessor.id2name if accessor.kind_of?(Integer)
+    method = method.id2name if method.kind_of?(Integer)
+    ali = ali.id2name if ali.kind_of?(Integer)
+
+    instance_eval(<<-EOS, "(__FORWARDABLE__)", 1)
+       def #{ali}(*args, &block)
+	 begin
+	   #{accessor}.__send__(:#{method}, *args,&block)
+	 rescue Exception
+	   $@.delete_if{|s| /^\\(__FORWARDABLE__\\):/ =~ s} unless Forwardable::debug
+	   Kernel::raise
+	 end
+       end
+    EOS
+  end
+
+  alias def_delegators def_singleton_delegators
+  alias def_delegator def_singleton_delegator
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/ftools.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/ftools.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/ftools.rb	(revision 18425)
@@ -0,0 +1,261 @@
+# 
+# = ftools.rb: Extra tools for the File class
+#
+# Author:: WATANABE, Hirofumi
+# Documentation:: Zachary Landau
+#
+# This library can be distributed under the terms of the Ruby license.
+# You can freely distribute/modify this library.
+#
+# It is included in the Ruby standard library.
+#
+# == Description
+#
+# ftools adds several (class, not instance) methods to the File class, for
+# copying, moving, deleting, installing, and comparing files, as well as
+# creating a directory path.  See the File class for details.
+#
+# FileUtils contains all or nearly all the same functionality and more, and
+# is a recommended option over ftools 
+#
+# When you
+#
+#   require 'ftools'
+#
+# then the File class aquires some utility methods for copying, moving, and
+# deleting files, and more.
+#
+# See the method descriptions below, and consider using FileUtils as it is
+# more comprehensive.
+#
+class File
+end
+
+class << File
+
+  BUFSIZE = 8 * 1024
+
+  #
+  # If +to+ is a valid directory, +from+ will be appended to +to+, adding
+  # and escaping backslashes as necessary. Otherwise, +to+ will be returned.
+  # Useful for appending +from+ to +to+ only if the filename was not specified
+  # in +to+. 
+  #
+  def catname(from, to)
+    if directory? to
+      join to.sub(%r([/\\]$), ''), basename(from)
+    else
+      to
+    end
+  end
+
+  #
+  # Copies a file +from+ to +to+. If +to+ is a directory, copies +from+
+  # to <tt>to/from</tt>.
+  #
+  def syscopy(from, to)
+    to = catname(from, to)
+
+    fmode = stat(from).mode
+    tpath = to
+    not_exist = !exist?(tpath)
+
+    from = open(from, "rb")
+    to = open(to, "wb")
+
+    begin
+      while true
+	to.syswrite from.sysread(BUFSIZE)
+      end
+    rescue EOFError
+      ret = true
+    rescue
+      ret = false
+    ensure
+      to.close
+      from.close
+    end
+    chmod(fmode, tpath) if not_exist
+    ret
+  end
+
+  #
+  # Copies a file +from+ to +to+ using #syscopy. If +to+ is a directory,
+  # copies +from+ to <tt>to/from</tt>. If +verbose+ is true, <tt>from -> to</tt>
+  # is printed.
+  #
+  def copy(from, to, verbose = false)
+    $stderr.print from, " -> ", catname(from, to), "\n" if verbose
+    syscopy from, to
+  end
+
+  alias cp copy
+
+  #
+  # Moves a file +from+ to +to+ using #syscopy. If +to+ is a directory,
+  # copies from +from+ to <tt>to/from</tt>. If +verbose+ is true, <tt>from ->
+  # to</tt> is printed.
+  #
+  def move(from, to, verbose = false)
+    to = catname(from, to)
+    $stderr.print from, " -> ", to, "\n" if verbose
+
+    if RUBY_PLATFORM =~ /djgpp|(cyg|ms|bcc)win|mingw/ and file? to
+      unlink to
+    end
+    fstat = stat(from)
+    begin
+      rename from, to
+    rescue
+      begin
+        symlink readlink(from), to and unlink from
+      rescue
+	from_stat = stat(from)
+	syscopy from, to and unlink from
+	utime(from_stat.atime, from_stat.mtime, to)
+	begin
+	  chown(fstat.uid, fstat.gid, to)
+	rescue
+	end
+      end
+    end
+  end
+
+  alias mv move
+
+  #
+  # Returns +true+ if and only if the contents of files +from+ and +to+ are
+  # identical. If +verbose+ is +true+, <tt>from <=> to</tt> is printed.
+  #
+  def compare(from, to, verbose = false)
+    $stderr.print from, " <=> ", to, "\n" if verbose
+
+    return false if stat(from).size != stat(to).size
+
+    from = open(from, "rb")
+    to = open(to, "rb")
+
+    ret = false
+    fr = tr = ''
+
+    begin
+      while fr == tr
+	fr = from.read(BUFSIZE)
+	if fr
+	  tr = to.read(fr.size)
+	else
+	  ret = to.read(BUFSIZE)
+	  ret = !ret || ret.length == 0
+	  break
+	end
+      end
+    rescue
+      ret = false
+    ensure
+      to.close
+      from.close
+    end
+    ret
+  end
+
+  alias cmp compare
+
+  #
+  # Removes a list of files. Each parameter should be the name of the file to
+  # delete. If the last parameter isn't a String, verbose mode will be enabled.
+  # Returns the number of files deleted.
+  #
+  def safe_unlink(*files)
+    verbose = if files[-1].is_a? String then false else files.pop end
+    files.each do |file|
+      begin
+        unlink file
+        $stderr.print "removing ", file, "\n" if verbose
+      rescue Errno::EACCES # for Windows
+        continue if symlink? file
+        begin
+          mode = stat(file).mode
+          o_chmod mode | 0200, file
+          unlink file
+          $stderr.print "removing ", file, "\n" if verbose
+        rescue
+          o_chmod mode, file rescue nil
+        end
+      rescue
+      end
+    end
+  end
+
+  alias rm_f safe_unlink
+
+  #
+  # Creates a directory and all its parent directories.
+  # For example,
+  #
+  #	File.makedirs '/usr/lib/ruby'
+  #
+  # causes the following directories to be made, if they do not exist.
+  #	* /usr
+  #	* /usr/lib
+  #	* /usr/lib/ruby
+  #
+  # You can pass several directories, each as a parameter. If the last
+  # parameter isn't a String, verbose mode will be enabled.
+  #
+  def makedirs(*dirs)
+    verbose = if dirs[-1].is_a? String then false else dirs.pop end
+    mode = 0755
+    for dir in dirs
+      parent = dirname(dir)
+      next if parent == dir or directory? dir
+      makedirs parent unless directory? parent
+      $stderr.print "mkdir ", dir, "\n" if verbose
+      if basename(dir) != ""
+        begin
+          Dir.mkdir dir, mode
+        rescue SystemCallError
+          raise unless directory? dir
+        end
+      end
+    end
+  end
+
+  alias mkpath makedirs
+
+  alias o_chmod chmod
+
+  vsave, $VERBOSE = $VERBOSE, false
+
+  #
+  # Changes permission bits on +files+ to the bit pattern represented
+  # by +mode+. If the last parameter isn't a String, verbose mode will
+  # be enabled.
+  #
+  #   File.chmod 0755, 'somecommand'
+  #   File.chmod 0644, 'my.rb', 'your.rb', true
+  #
+  def chmod(mode, *files)
+    verbose = if files[-1].is_a? String then false else files.pop end
+    $stderr.printf "chmod %04o %s\n", mode, files.join(" ") if verbose
+    o_chmod mode, *files
+  end
+  $VERBOSE = vsave
+
+  #
+  # If +src+ is not the same as +dest+, copies it and changes the permission
+  # mode to +mode+. If +dest+ is a directory, destination is <tt>dest/src</tt>.
+  # If +mode+ is not set, default is used. If +verbose+ is set to true, the
+  # name of each file copied will be printed.
+  #
+  def install(from, to, mode = nil, verbose = false)
+    to = catname(from, to)
+    unless exist? to and cmp from, to
+      safe_unlink to if exist? to
+      cp from, to, verbose
+      chmod mode, to, verbose if mode
+    end
+  end
+
+end
+
+# vi:set sw=2:
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/generator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/generator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/generator.rb	(revision 18425)
@@ -0,0 +1,380 @@
+#!/usr/bin/env ruby
+#--
+# $Idaemons: /home/cvs/rb/generator.rb,v 1.8 2001/10/03 08:54:32 knu Exp $
+# $RoughId: generator.rb,v 1.10 2003/10/14 19:36:58 knu Exp $
+# $Id: generator.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#++
+#
+# = generator.rb: convert an internal iterator to an external one
+#
+# Copyright (c) 2001,2003 Akinori MUSHA <knu@iDaemons.org>
+#
+# All rights reserved.  You can redistribute and/or modify it under
+# the same terms as Ruby.
+#
+# == Overview
+#
+# This library provides the Generator class, which converts an
+# internal iterator (i.e. an Enumerable object) to an external
+# iterator.  In that form, you can roll many iterators independently.
+#
+# The SyncEnumerator class, which is implemented using Generator,
+# makes it easy to roll many Enumerable objects synchronously.
+#
+# See the respective classes for examples of usage.
+
+
+#
+# Generator converts an internal iterator (i.e. an Enumerable object)
+# to an external iterator.
+#
+# Note that it is not very fast since it is implemented using
+# continuations, which are currently slow.
+#
+# == Example
+#
+#   require 'generator'
+#
+#   # Generator from an Enumerable object
+#   g = Generator.new(['A', 'B', 'C', 'Z'])
+#
+#   while g.next?
+#     puts g.next
+#   end
+#
+#   # Generator from a block
+#   g = Generator.new { |g|
+#     for i in 'A'..'C'
+#       g.yield i
+#     end
+#
+#     g.yield 'Z'
+#   }
+#
+#   # The same result as above
+#   while g.next?
+#     puts g.next
+#   end
+#   
+class Generator
+  include Enumerable
+
+  # Creates a new generator either from an Enumerable object or from a
+  # block.
+  #
+  # In the former, block is ignored even if given.
+  #
+  # In the latter, the given block is called with the generator
+  # itself, and expected to call the +yield+ method for each element.
+  def initialize(enum = nil, &block)
+    if enum
+      @block = proc { |g|
+	enum.each { |x| g.yield x }
+      }
+    else
+      @block = block
+    end
+
+    @index = 0
+    @queue = []
+    @cont_next = @cont_yield = @cont_endp = nil
+
+    if @cont_next = callcc { |c| c }
+      @block.call(self)
+
+      @cont_endp.call(nil) if @cont_endp
+    end
+
+    self
+  end
+
+  # Yields an element to the generator.
+  def yield(value)
+    if @cont_yield = callcc { |c| c }
+      @queue << value
+      @cont_next.call(nil)
+    end
+
+    self
+  end
+
+  # Returns true if the generator has reached the end.
+  def end?()
+    if @cont_endp = callcc { |c| c }
+      @cont_yield.nil? && @queue.empty?
+    else
+      @queue.empty?
+    end
+  end
+
+  # Returns true if the generator has not reached the end yet.
+  def next?()
+    !end?
+  end
+
+  # Returns the current index (position) counting from zero.
+  def index()
+    @index
+  end
+
+  # Returns the current index (position) counting from zero.
+  def pos()
+    @index
+  end
+
+  # Returns the element at the current position and moves forward.
+  def next()
+    if end?
+      raise EOFError, "no more elements available"
+    end
+
+    if @cont_next = callcc { |c| c }
+      @cont_yield.call(nil) if @cont_yield
+    end
+
+    @index += 1
+
+    @queue.shift
+  end
+
+  # Returns the element at the current position.
+  def current()
+    if @queue.empty?
+      raise EOFError, "no more elements available"
+    end
+
+    @queue.first
+  end
+
+  # Rewinds the generator.
+  def rewind()
+    initialize(nil, &@block) if @index.nonzero?
+
+    self
+  end
+
+  # Rewinds the generator and enumerates the elements.
+  def each
+    rewind
+
+    until end?
+      yield self.next
+    end
+
+    self
+  end
+end
+
+#
+# SyncEnumerator creates an Enumerable object from multiple Enumerable
+# objects and enumerates them synchronously.
+#
+# == Example
+#
+#   require 'generator'
+#
+#   s = SyncEnumerator.new([1,2,3], ['a', 'b', 'c'])
+#
+#   # Yields [1, 'a'], [2, 'b'], and [3,'c']
+#   s.each { |row| puts row.join(', ') }
+#
+class SyncEnumerator
+  include Enumerable
+
+  # Creates a new SyncEnumerator which enumerates rows of given
+  # Enumerable objects.
+  def initialize(*enums)
+    @gens = enums.map { |e| Generator.new(e) }
+  end
+
+  # Returns the number of enumerated Enumerable objects, i.e. the size
+  # of each row.
+  def size
+    @gens.size
+  end
+
+  # Returns the number of enumerated Enumerable objects, i.e. the size
+  # of each row.
+  def length
+    @gens.length
+  end
+
+  # Returns true if the given nth Enumerable object has reached the
+  # end.  If no argument is given, returns true if any of the
+  # Enumerable objects has reached the end.
+  def end?(i = nil)
+    if i.nil?
+      @gens.detect { |g| g.end? } ? true : false
+    else
+      @gens[i].end?
+    end
+  end
+
+  # Enumerates rows of the Enumerable objects.
+  def each
+    @gens.each { |g| g.rewind }
+
+    loop do
+      count = 0
+
+      ret = @gens.map { |g|
+	if g.end?
+	  count += 1
+	  nil
+	else
+	  g.next
+	end
+      }
+
+      if count == @gens.size
+	break
+      end
+
+      yield ret
+    end
+
+    self
+  end
+end
+
+if $0 == __FILE__
+  eval DATA.read, nil, $0, __LINE__+4
+end
+
+__END__
+
+require 'test/unit'
+
+class TC_Generator < Test::Unit::TestCase
+  def test_block1
+    g = Generator.new { |g|
+      # no yield's
+    }
+
+    assert_equal(0, g.pos)
+    assert_raises(EOFError) { g.current }
+  end
+
+  def test_block2
+    g = Generator.new { |g|
+      for i in 'A'..'C'
+        g.yield i
+      end
+
+      g.yield 'Z'
+    }
+
+    assert_equal(0, g.pos)
+    assert_equal('A', g.current)
+
+    assert_equal(true, g.next?)
+    assert_equal(0, g.pos)
+    assert_equal('A', g.current)
+    assert_equal(0, g.pos)
+    assert_equal('A', g.next)
+
+    assert_equal(1, g.pos)
+    assert_equal(true, g.next?)
+    assert_equal(1, g.pos)
+    assert_equal('B', g.current)
+    assert_equal(1, g.pos)
+    assert_equal('B', g.next)
+
+    assert_equal(g, g.rewind)
+
+    assert_equal(0, g.pos)
+    assert_equal('A', g.current)
+
+    assert_equal(true, g.next?)
+    assert_equal(0, g.pos)
+    assert_equal('A', g.current)
+    assert_equal(0, g.pos)
+    assert_equal('A', g.next)
+
+    assert_equal(1, g.pos)
+    assert_equal(true, g.next?)
+    assert_equal(1, g.pos)
+    assert_equal('B', g.current)
+    assert_equal(1, g.pos)
+    assert_equal('B', g.next)
+
+    assert_equal(2, g.pos)
+    assert_equal(true, g.next?)
+    assert_equal(2, g.pos)
+    assert_equal('C', g.current)
+    assert_equal(2, g.pos)
+    assert_equal('C', g.next)
+
+    assert_equal(3, g.pos)
+    assert_equal(true, g.next?)
+    assert_equal(3, g.pos)
+    assert_equal('Z', g.current)
+    assert_equal(3, g.pos)
+    assert_equal('Z', g.next)
+
+    assert_equal(4, g.pos)
+    assert_equal(false, g.next?)
+    assert_raises(EOFError) { g.next }
+  end
+
+  def test_each
+    a = [5, 6, 7, 8, 9]
+
+    g = Generator.new(a)
+
+    i = 0
+
+    g.each { |x|
+      assert_equal(a[i], x)
+
+      i += 1
+
+      break if i == 3
+    }
+
+    assert_equal(3, i)
+
+    i = 0
+
+    g.each { |x|
+      assert_equal(a[i], x)
+
+      i += 1
+    }
+
+    assert_equal(5, i)
+  end
+end
+
+class TC_SyncEnumerator < Test::Unit::TestCase
+  def test_each
+    r = ['a'..'f', 1..10, 10..20]
+    ra = r.map { |x| x.to_a }
+
+    a = (0...(ra.map {|x| x.size}.max)).map { |i| ra.map { |x| x[i] } }
+
+    s = SyncEnumerator.new(*r)
+
+    i = 0
+
+    s.each { |x|
+      assert_equal(a[i], x)
+
+      i += 1
+
+      break if i == 3
+    }
+
+    assert_equal(3, i)
+
+    i = 0
+
+    s.each { |x|
+      assert_equal(a[i], x)
+
+      i += 1
+    }
+
+    assert_equal(a.size, i)
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/getoptlong.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/getoptlong.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/getoptlong.rb	(revision 18425)
@@ -0,0 +1,621 @@
+#
+# GetoptLong for Ruby
+#
+# Copyright (C) 1998, 1999, 2000  Motoyuki Kasahara.
+#
+# You may redistribute and/or modify this library under the same license
+# terms as Ruby.
+#
+# See GetoptLong for documentation.
+#
+# Additional documents and the latest version of `getoptlong.rb' can be
+# found at http://www.sra.co.jp/people/m-kasahr/ruby/getoptlong/
+
+# The GetoptLong class allows you to parse command line options similarly to
+# the GNU getopt_long() C library call. Note, however, that GetoptLong is a 
+# pure Ruby implementation.
+#
+# GetoptLong allows for POSIX-style options like <tt>--file</tt> as well 
+# as single letter options like <tt>-f</tt>
+#
+# The empty option <tt>--</tt> (two minus symbols) is used to end option
+# processing. This can be particularly important if options have optional
+# arguments.
+#
+# Here is a simple example of usage:
+#
+#     # == Synopsis
+#     #
+#     # hello: greets user, demonstrates command line parsing
+#     #
+#     # == Usage
+#     #
+#     # hello [OPTION] ... DIR
+#     #
+#     # -h, --help:
+#     #    show help
+#     #
+#     # --repeat x, -n x:
+#     #    repeat x times
+#     #
+#     # --name [name]:
+#     #    greet user by name, if name not supplied default is John
+#     #
+#     # DIR: The directory in which to issue the greeting.
+#     
+#     require 'getoptlong'
+#     require 'rdoc/usage'
+#     
+#     opts = GetoptLong.new(
+#       [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
+#       [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ],
+#       [ '--name', GetoptLong::OPTIONAL_ARGUMENT ]
+#     )
+#     
+#     dir = nil
+#     name = nil
+#     repetitions = 1
+#     opts.each do |opt, arg|
+#       case opt
+#         when '--help'
+#           RDoc::usage
+#         when '--repeat'
+#           repetitions = arg.to_i
+#         when '--name'
+#           if arg == ''
+#             name = 'John'
+#           else
+#             name = arg
+#           end
+#       end
+#     end
+#     
+#     if ARGV.length != 1
+#       puts "Missing dir argument (try --help)"
+#       exit 0
+#     end
+#     
+#     dir = ARGV.shift
+#     
+#     Dir.chdir(dir)
+#     for i in (1..repetitions)
+#       print "Hello"
+#       if name
+#         print ", #{name}"
+#       end
+#       puts
+#     end
+#
+# Example command line:
+#
+#     hello -n 6 --name -- /tmp
+#
+class GetoptLong
+  #
+  # Orderings.
+  #
+  ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2]
+
+  #
+  # Argument flags.
+  #
+  ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1,
+    OPTIONAL_ARGUMENT = 2]
+
+  #
+  # Status codes.
+  #
+  STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0, 1, 2
+
+  #
+  # Error types.
+  #
+  class Error  < StandardError; end
+  class AmbigousOption   < Error; end
+  class NeedlessArgument < Error; end
+  class MissingArgument  < Error; end
+  class InvalidOption    < Error; end
+
+  #
+  # Set up option processing.
+  #
+  # The options to support are passed to new() as an array of arrays.
+  # Each sub-array contains any number of String option names which carry 
+  # the same meaning, and one of the following flags:
+  #
+  # GetoptLong::NO_ARGUMENT :: Option does not take an argument.
+  #
+  # GetoptLong::REQUIRED_ARGUMENT :: Option always takes an argument.
+  #
+  # GetoptLong::OPTIONAL_ARGUMENT :: Option may or may not take an argument.
+  #
+  # The first option name is considered to be the preferred (canonical) name.
+  # Other than that, the elements of each sub-array can be in any order.
+  #
+  def initialize(*arguments)
+    #
+    # Current ordering.
+    #
+    if ENV.include?('POSIXLY_CORRECT')
+      @ordering = REQUIRE_ORDER
+    else
+      @ordering = PERMUTE
+    end
+
+    #
+    # Hash table of option names.
+    # Keys of the table are option names, and their values are canonical
+    # names of the options.
+    #
+    @canonical_names = Hash.new
+
+    #
+    # Hash table of argument flags.
+    # Keys of the table are option names, and their values are argument
+    # flags of the options.
+    #
+    @argument_flags = Hash.new
+
+    #
+    # Whether error messages are output to $deferr.
+    #
+    @quiet = FALSE
+
+    #
+    # Status code.
+    #
+    @status = STATUS_YET
+
+    #
+    # Error code.
+    #
+    @error = nil
+
+    #
+    # Error message.
+    #
+    @error_message = nil
+
+    #
+    # Rest of catenated short options.
+    #
+    @rest_singles = ''
+
+    #
+    # List of non-option-arguments.
+    # Append them to ARGV when option processing is terminated.
+    #
+    @non_option_arguments = Array.new
+
+    if 0 < arguments.length
+      set_options(*arguments)
+    end
+  end
+
+  #
+  # Set the handling of the ordering of options and arguments.
+  # A RuntimeError is raised if option processing has already started.
+  #
+  # The supplied value must be a member of GetoptLong::ORDERINGS. It alters
+  # the processing of options as follows:
+  #
+  # <b>REQUIRE_ORDER</b> :
+  # 
+  # Options are required to occur before non-options.
+  #
+  # Processing of options ends as soon as a word is encountered that has not
+  # been preceded by an appropriate option flag.
+  #
+  # For example, if -a and -b are options which do not take arguments,
+  # parsing command line arguments of '-a one -b two' would result in 
+  # 'one', '-b', 'two' being left in ARGV, and only ('-a', '') being 
+  # processed as an option/arg pair.
+  #
+  # This is the default ordering, if the environment variable
+  # POSIXLY_CORRECT is set. (This is for compatibility with GNU getopt_long.)
+  #
+  # <b>PERMUTE</b> :
+  #  
+  # Options can occur anywhere in the command line parsed. This is the 
+  # default behavior.
+  #
+  # Every sequence of words which can be interpreted as an option (with or
+  # without argument) is treated as an option; non-option words are skipped.
+  #
+  # For example, if -a does not require an argument and -b optionally takes
+  # an argument, parsing '-a one -b two three' would result in ('-a','') and
+  # ('-b', 'two') being processed as option/arg pairs, and 'one','three'
+  # being left in ARGV.
+  #
+  # If the ordering is set to PERMUTE but the environment variable
+  # POSIXLY_CORRECT is set, REQUIRE_ORDER is used instead. This is for
+  # compatibility with GNU getopt_long.
+  #
+  # <b>RETURN_IN_ORDER</b> :
+  #
+  # All words on the command line are processed as options. Words not 
+  # preceded by a short or long option flag are passed as arguments
+  # with an option of '' (empty string).
+  #
+  # For example, if -a requires an argument but -b does not, a command line
+  # of '-a one -b two three' would result in option/arg pairs of ('-a', 'one')
+  # ('-b', ''), ('', 'two'), ('', 'three') being processed.
+  #
+  def ordering=(ordering)
+    #
+    # The method is failed if option processing has already started.
+    #
+    if @status != STATUS_YET
+      set_error(ArgumentError, "argument error")
+      raise RuntimeError,
+	"invoke ordering=, but option processing has already started"
+    end
+
+    #
+    # Check ordering.
+    #
+    if !ORDERINGS.include?(ordering)
+      raise ArgumentError, "invalid ordering `#{ordering}'"
+    end
+    if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT')
+      @ordering = REQUIRE_ORDER
+    else
+      @ordering = ordering
+    end
+  end
+
+  #
+  # Return ordering.
+  #
+  attr_reader :ordering
+
+  #
+  # Set options. Takes the same argument as GetoptLong.new.
+  #
+  # Raises a RuntimeError if option processing has already started.
+  #
+  def set_options(*arguments)
+    #
+    # The method is failed if option processing has already started.
+    #
+    if @status != STATUS_YET
+      raise RuntimeError, 
+	"invoke set_options, but option processing has already started"
+    end
+
+    #
+    # Clear tables of option names and argument flags.
+    #
+    @canonical_names.clear
+    @argument_flags.clear
+
+    arguments.each do |arg|
+      #
+      # Each argument must be an Array.
+      #
+      if !arg.is_a?(Array)
+	raise ArgumentError, "the option list contains non-Array argument"
+      end
+
+      #
+      # Find an argument flag and it set to `argument_flag'.
+      #
+      argument_flag = nil
+      arg.each do |i|
+	if ARGUMENT_FLAGS.include?(i)
+	  if argument_flag != nil
+	    raise ArgumentError, "too many argument-flags"
+	  end
+	  argument_flag = i
+	end
+      end
+      raise ArgumentError, "no argument-flag" if argument_flag == nil
+
+      canonical_name = nil
+      arg.each do |i|
+	#
+	# Check an option name.
+	#
+	next if i == argument_flag
+	begin
+	  if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/
+	    raise ArgumentError, "an invalid option `#{i}'"
+	  end
+	  if (@canonical_names.include?(i))
+	    raise ArgumentError, "option redefined `#{i}'"
+	  end
+	rescue
+	  @canonical_names.clear
+	  @argument_flags.clear
+	  raise
+	end
+
+	#
+	# Register the option (`i') to the `@canonical_names' and 
+	# `@canonical_names' Hashes.
+	#
+	if canonical_name == nil
+	  canonical_name = i
+	end
+	@canonical_names[i] = canonical_name
+	@argument_flags[i] = argument_flag
+      end
+      raise ArgumentError, "no option name" if canonical_name == nil
+    end
+    return self
+  end
+
+  #
+  # Set/Unset `quiet' mode.
+  #
+  attr_writer :quiet
+
+  #
+  # Return the flag of `quiet' mode.
+  #
+  attr_reader :quiet
+
+  #
+  # `quiet?' is an alias of `quiet'.
+  #
+  alias quiet? quiet
+
+  #
+  # Explicitly terminate option processing.
+  #
+  def terminate
+    return nil if @status == STATUS_TERMINATED
+    raise RuntimeError, "an error has occured" if @error != nil
+
+    @status = STATUS_TERMINATED
+    @non_option_arguments.reverse_each do |argument|
+      ARGV.unshift(argument)
+    end
+
+    @canonical_names = nil
+    @argument_flags = nil
+    @rest_singles = nil
+    @non_option_arguments = nil
+
+    return self
+  end
+
+  #
+  # Returns true if option processing has terminated, false otherwise.
+  #
+  def terminated?
+    return @status == STATUS_TERMINATED
+  end
+
+  #
+  # Set an error (protected).
+  #
+  def set_error(type, message)
+    $deferr.print("#{$0}: #{message}\n") if !@quiet
+
+    @error = type
+    @error_message = message
+    @canonical_names = nil
+    @argument_flags = nil
+    @rest_singles = nil
+    @non_option_arguments = nil
+
+    raise type, message
+  end
+  protected :set_error
+
+  #
+  # Examine whether an option processing is failed.
+  #
+  attr_reader :error
+
+  #
+  # `error?' is an alias of `error'.
+  #
+  alias error? error
+
+  # Return the appropriate error message in POSIX-defined format.
+  # If no error has occurred, returns nil.
+  #
+  def error_message
+    return @error_message
+  end
+
+  #
+  # Get next option name and its argument, as an Array of two elements.
+  #
+  # The option name is always converted to the first (preferred)
+  # name given in the original options to GetoptLong.new.
+  #
+  # Example: ['--option', 'value']
+  #
+  # Returns nil if the processing is complete (as determined by
+  # STATUS_TERMINATED).
+  #
+  def get
+    option_name, option_argument = nil, ''
+
+    #
+    # Check status.
+    #
+    return nil if @error != nil
+    case @status
+    when STATUS_YET
+      @status = STATUS_STARTED
+    when STATUS_TERMINATED
+      return nil
+    end
+
+    #
+    # Get next option argument.
+    #
+    if 0 < @rest_singles.length
+      argument = '-' + @rest_singles
+    elsif (ARGV.length == 0)
+      terminate
+      return nil
+    elsif @ordering == PERMUTE
+      while 0 < ARGV.length && ARGV[0] !~ /^-./
+	@non_option_arguments.push(ARGV.shift)
+      end
+      if ARGV.length == 0
+	terminate
+	return nil
+      end
+      argument = ARGV.shift
+    elsif @ordering == REQUIRE_ORDER 
+      if (ARGV[0] !~ /^-./)
+	terminate
+	return nil
+      end
+      argument = ARGV.shift
+    else
+      argument = ARGV.shift
+    end
+
+    #
+    # Check the special argument `--'.
+    # `--' indicates the end of the option list.
+    #
+    if argument == '--' && @rest_singles.length == 0
+      terminate
+      return nil
+    end
+
+    #
+    # Check for long and short options.
+    #
+    if argument =~ /^(--[^=]+)/ && @rest_singles.length == 0
+      #
+      # This is a long style option, which start with `--'.
+      #
+      pattern = $1
+      if @canonical_names.include?(pattern)
+	option_name = pattern
+      else
+	#
+	# The option `option_name' is not registered in `@canonical_names'.
+	# It may be an abbreviated.
+	#
+	match_count = 0
+	@canonical_names.each_key do |key|
+	  if key.index(pattern) == 0
+	    option_name = key
+	    match_count += 1
+	  end
+	end
+	if 2 <= match_count
+	  set_error(AmbigousOption, "option `#{argument}' is ambiguous")
+	elsif match_count == 0
+	  set_error(InvalidOption, "unrecognized option `#{argument}'")
+	end
+      end
+
+      #
+      # Check an argument to the option.
+      #
+      if @argument_flags[option_name] == REQUIRED_ARGUMENT
+	if argument =~ /=(.*)$/
+	  option_argument = $1
+	elsif 0 < ARGV.length
+	  option_argument = ARGV.shift
+	else
+	  set_error(MissingArgument,
+	            "option `#{argument}' requires an argument")
+	end
+      elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
+	if argument =~ /=(.*)$/
+	  option_argument = $1
+	elsif 0 < ARGV.length && ARGV[0] !~ /^-./
+	  option_argument = ARGV.shift
+	else
+	  option_argument = ''
+	end
+      elsif argument =~ /=(.*)$/
+	set_error(NeedlessArgument,
+		  "option `#{option_name}' doesn't allow an argument")
+      end
+
+    elsif argument =~ /^(-(.))(.*)/
+      #
+      # This is a short style option, which start with `-' (not `--').
+      # Short options may be catenated (e.g. `-l -g' is equivalent to
+      # `-lg').
+      #
+      option_name, ch, @rest_singles = $1, $2, $3
+
+      if @canonical_names.include?(option_name)
+	#
+	# The option `option_name' is found in `@canonical_names'.
+	# Check its argument.
+	#
+	if @argument_flags[option_name] == REQUIRED_ARGUMENT
+	  if 0 < @rest_singles.length
+	    option_argument = @rest_singles
+	    @rest_singles = ''
+	  elsif 0 < ARGV.length
+	    option_argument = ARGV.shift
+	  else
+	    # 1003.2 specifies the format of this message.
+	    set_error(MissingArgument, "option requires an argument -- #{ch}")
+	  end
+	elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
+	  if 0 < @rest_singles.length
+	    option_argument = @rest_singles
+	    @rest_singles = ''
+	  elsif 0 < ARGV.length && ARGV[0] !~ /^-./
+	    option_argument = ARGV.shift
+	  else
+	    option_argument = ''
+	  end
+	end
+      else
+	#
+	# This is an invalid option.
+	# 1003.2 specifies the format of this message.
+	#
+	if ENV.include?('POSIXLY_CORRECT')
+	  set_error(InvalidOption, "illegal option -- #{ch}")
+	else
+	  set_error(InvalidOption, "invalid option -- #{ch}")
+	end
+      end
+    else
+      #
+      # This is a non-option argument.
+      # Only RETURN_IN_ORDER falled into here.
+      #
+      return '', argument
+    end
+
+    return @canonical_names[option_name], option_argument
+  end
+
+  #
+  # `get_option' is an alias of `get'.
+  #
+  alias get_option get
+
+  # Iterator version of `get'.
+  #
+  # The block is called repeatedly with two arguments:
+  # The first is the option name.
+  # The second is the argument which followed it (if any). 
+  # Example: ('--opt', 'value')
+  #
+  # The option name is always converted to the first (preferred)
+  # name given in the original options to GetoptLong.new.
+  #
+  def each
+    loop do
+      option_name, option_argument = get_option
+      break if option_name == nil
+      yield option_name, option_argument
+    end
+  end
+
+  #
+  # `each_option' is an alias of `each'.
+  #
+  alias each_option each
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/getopts.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/getopts.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/getopts.rb	(revision 18425)
@@ -0,0 +1,127 @@
+#
+#               getopts.rb - 
+#                       $Release Version: $
+#                       $Revision: 11708 $
+#                       $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#                       by Yasuo OHBA(SHL Japan Inc. Technology Dept.)
+#
+# --
+# this is obsolete; use getoptlong
+#
+# 2000-03-21
+# modified by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+#
+# 2002-03-05
+# rewritten by Akinori MUSHA <knu@ruby-lang.org>
+#
+
+warn "Warning:#{caller[0].sub(/:in `.*'\z/, '')}: getopts is deprecated after Ruby 1.8.1; use optparse instead" if caller[0] and $VERBOSE
+
+$RCS_ID=%q$Header$
+
+# getopts is obsolete. Use GetoptLong.
+
+def getopts(single_options, *options)
+  boolopts = {}
+  valopts = {}
+
+  #
+  # set defaults
+  #
+  single_options.scan(/.:?/) do |opt|
+    if opt.size == 1
+      boolopts[opt] = false
+    else
+      valopts[opt[0, 1]] = nil
+    end
+  end if single_options
+
+  options.each do |arg|
+    opt, val = arg.split(':', 2)
+
+    if val
+      valopts[opt] = val.empty? ? nil : val
+    else
+      boolopts[opt] = false
+    end
+  end
+
+  #
+  # scan
+  #
+  c = 0
+  argv = ARGV
+
+  while arg = argv.shift
+    case arg
+    when /\A--(.*)/
+      if $1.empty?			# xinit -- -bpp 24
+	break
+      end
+
+      opt, val = $1.split('=', 2)
+
+      if opt.size == 1
+	argv.unshift arg
+	return nil
+      elsif valopts.key? opt		# imclean --src +trash
+	valopts[opt] = val || argv.shift or return nil
+      elsif boolopts.key? opt		# ruby --verbose
+	boolopts[opt] = true
+      else
+	argv.unshift arg
+	return nil
+      end
+
+      c += 1
+    when /\A-(.+)/
+      opts = $1
+
+      until opts.empty?
+	opt = opts.slice!(0, 1)
+
+	if valopts.key? opt
+	  val = opts
+
+	  if val.empty?			# ruby -e 'p $:'
+	    valopts[opt] = argv.shift or return nil
+	  else				# cc -ohello ...
+	    valopts[opt] = val
+	  end
+
+	  c += 1
+	  break
+	elsif boolopts.key? opt
+	  boolopts[opt] = true		# ruby -h
+	  c += 1
+	else
+	  argv.unshift arg
+	  return nil
+	end
+      end
+    else
+      argv.unshift arg
+      break
+    end
+  end
+
+  #
+  # set
+  #
+  $OPT = {}
+
+  boolopts.each do |opt, val|
+    $OPT[opt] = val
+
+    sopt = opt.gsub(/[^A-Za-z0-9_]/, '_')
+    eval "$OPT_#{sopt} = val"
+  end
+  valopts.each do |opt, val|
+    $OPT[opt] = val
+
+    sopt = opt.gsub(/[^A-Za-z0-9_]/, '_')
+    eval "$OPT_#{sopt} = val"
+  end
+
+  c
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/gserver.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/gserver.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/gserver.rb	(revision 18425)
@@ -0,0 +1,253 @@
+#
+# Copyright (C) 2001 John W. Small All Rights Reserved
+#
+# Author::        John W. Small
+# Documentation:: Gavin Sinclair
+# Licence::       Freeware.
+#
+# See the class GServer for documentation.
+#
+
+require "socket"
+require "thread"
+
+#
+# GServer implements a generic server, featuring thread pool management,
+# simple logging, and multi-server management.  See HttpServer in 
+# <tt>xmlrpc/httpserver.rb</tt> in the Ruby standard library for an example of
+# GServer in action.
+#
+# Any kind of application-level server can be implemented using this class.
+# It accepts multiple simultaneous connections from clients, up to an optional
+# maximum number.  Several _services_ (i.e. one service per TCP port) can be
+# run simultaneously, and stopped at any time through the class method
+# <tt>GServer.stop(port)</tt>.  All the threading issues are handled, saving
+# you the effort.  All events are optionally logged, but you can provide your
+# own event handlers if you wish.
+#
+# === Example
+#
+# Using GServer is simple.  Below we implement a simple time server, run it,
+# query it, and shut it down.  Try this code in +irb+:
+#
+#   require 'gserver'
+#
+#   #
+#   # A server that returns the time in seconds since 1970.
+#   # 
+#   class TimeServer < GServer
+#     def initialize(port=10001, *args)
+#       super(port, *args)
+#     end
+#     def serve(io)
+#       io.puts(Time.now.to_i)
+#     end
+#   end
+#
+#   # Run the server with logging enabled (it's a separate thread).
+#   server = TimeServer.new
+#   server.audit = true                  # Turn logging on.
+#   server.start 
+#
+#   # *** Now point your browser to http://localhost:10001 to see it working ***
+#
+#   # See if it's still running. 
+#   GServer.in_service?(10001)           # -> true
+#   server.stopped?                      # -> false
+#
+#   # Shut the server down gracefully.
+#   server.shutdown
+#   
+#   # Alternatively, stop it immediately.
+#   GServer.stop(10001)
+#   # or, of course, "server.stop".
+#
+# All the business of accepting connections and exception handling is taken
+# care of.  All we have to do is implement the method that actually serves the
+# client.
+#
+# === Advanced
+#
+# As the example above shows, the way to use GServer is to subclass it to
+# create a specific server, overriding the +serve+ method.  You can override
+# other methods as well if you wish, perhaps to collect statistics, or emit
+# more detailed logging.
+#
+#   connecting
+#   disconnecting
+#   starting
+#   stopping
+#
+# The above methods are only called if auditing is enabled.
+#
+# You can also override +log+ and +error+ if, for example, you wish to use a
+# more sophisticated logging system.
+#
+class GServer
+
+  DEFAULT_HOST = "127.0.0.1"
+
+  def serve(io)
+  end
+
+  @@services = {}   # Hash of opened ports, i.e. services
+  @@servicesMutex = Mutex.new
+
+  def GServer.stop(port, host = DEFAULT_HOST)
+    @@servicesMutex.synchronize {
+      @@services[host][port].stop
+    }
+  end
+
+  def GServer.in_service?(port, host = DEFAULT_HOST)
+    @@services.has_key?(host) and
+      @@services[host].has_key?(port)
+  end
+
+  def stop
+    @connectionsMutex.synchronize  {
+      if @tcpServerThread
+        @tcpServerThread.raise "stop"
+      end
+    }
+  end
+
+  def stopped?
+    @tcpServerThread == nil
+  end
+
+  def shutdown
+    @shutdown = true
+  end
+
+  def connections
+    @connections.size
+  end
+
+  def join
+    @tcpServerThread.join if @tcpServerThread
+  end
+
+  attr_reader :port, :host, :maxConnections
+  attr_accessor :stdlog, :audit, :debug
+
+  def connecting(client)
+    addr = client.peeraddr
+    log("#{self.class.to_s} #{@host}:#{@port} client:#{addr[1]} " +
+        "#{addr[2]}<#{addr[3]}> connect")
+    true
+  end
+
+  def disconnecting(clientPort)
+    log("#{self.class.to_s} #{@host}:#{@port} " +
+      "client:#{clientPort} disconnect")
+  end
+
+  protected :connecting, :disconnecting
+
+  def starting()
+    log("#{self.class.to_s} #{@host}:#{@port} start")
+  end
+
+  def stopping()
+    log("#{self.class.to_s} #{@host}:#{@port} stop")
+  end
+
+  protected :starting, :stopping
+
+  def error(detail)
+    log(detail.backtrace.join("\n"))
+  end
+
+  def log(msg)
+    if @stdlog
+      @stdlog.puts("[#{Time.new.ctime}] %s" % msg)
+      @stdlog.flush
+    end
+  end
+
+  protected :error, :log
+
+  def initialize(port, host = DEFAULT_HOST, maxConnections = 4,
+    stdlog = $stderr, audit = false, debug = false)
+    @tcpServerThread = nil
+    @port = port
+    @host = host
+    @maxConnections = maxConnections
+    @connections = []
+    @connectionsMutex = Mutex.new
+    @connectionsCV = ConditionVariable.new
+    @stdlog = stdlog
+    @audit = audit
+    @debug = debug
+  end
+
+  def start(maxConnections = -1)
+    raise "running" if !stopped?
+    @shutdown = false
+    @maxConnections = maxConnections if maxConnections > 0
+    @@servicesMutex.synchronize  {
+      if GServer.in_service?(@port,@host)
+        raise "Port already in use: #{host}:#{@port}!"
+      end
+      @tcpServer = TCPServer.new(@host,@port)
+      @port = @tcpServer.addr[1]
+      @@services[@host] = {} unless @@services.has_key?(@host)
+      @@services[@host][@port] = self;
+    }
+    @tcpServerThread = Thread.new {
+      begin
+        starting if @audit
+        while !@shutdown
+          @connectionsMutex.synchronize  {
+             while @connections.size >= @maxConnections
+               @connectionsCV.wait(@connectionsMutex)
+             end
+          }
+          client = @tcpServer.accept
+          @connections << Thread.new(client)  { |myClient|
+            begin
+              myPort = myClient.peeraddr[1]
+              serve(myClient) if !@audit or connecting(myClient)
+            rescue => detail
+              error(detail) if @debug
+            ensure
+              begin
+                myClient.close
+              rescue
+              end
+              @connectionsMutex.synchronize {
+                @connections.delete(Thread.current)
+                @connectionsCV.signal
+              }
+              disconnecting(myPort) if @audit
+            end
+          }
+        end
+      rescue => detail
+        error(detail) if @debug
+      ensure
+        begin
+          @tcpServer.close
+        rescue
+        end
+        if @shutdown
+          @connectionsMutex.synchronize  {
+             while @connections.size > 0
+               @connectionsCV.wait(@connectionsMutex)
+             end
+          }
+        else
+          @connections.each { |c| c.raise "stop" }
+        end
+        @tcpServerThread = nil
+        @@servicesMutex.synchronize  {
+          @@services[@host].delete(@port)
+        }
+        stopping if @audit
+      end
+    }
+    self
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/config.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/config.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/config.h	(revision 18425)
@@ -0,0 +1,177 @@
+#define PACKAGE_NAME ""
+#define PACKAGE_TARNAME ""
+#define PACKAGE_VERSION ""
+#define PACKAGE_STRING ""
+#define PACKAGE_BUGREPORT ""
+#define USE_BUILTIN_FRAME_ADDRESS 1
+#define STDC_HEADERS 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_UNISTD_H 1
+#define _FILE_OFFSET_BITS 64
+#define HAVE_LONG_LONG 1
+#define HAVE_OFF_T 1
+#define SIZEOF_INT 4
+#define SIZEOF_SHORT 2
+#define SIZEOF_LONG 4
+#define SIZEOF_LONG_LONG 8
+#define SIZEOF___INT64 0
+#define SIZEOF_OFF_T 8
+#define SIZEOF_VOIDP 4
+#define SIZEOF_FLOAT 4
+#define SIZEOF_DOUBLE 8
+#define SIZEOF_TIME_T 4
+#define rb_pid_t pid_t
+#define rb_gid_t gid_t
+#define rb_uid_t uid_t
+#define HAVE_PROTOTYPES 1
+#define TOKEN_PASTE(x,y) x##y
+#define HAVE_STDARG_PROTOTYPES 1
+#define NORETURN(x) __attribute__ ((noreturn)) x
+#define NOINLINE(x) __attribute__ ((noinline)) x
+#define HAVE_DECL_SYS_NERR 1
+#define HAVE_LIBCRYPT 1
+#define HAVE_LIBDL 1
+#define HAVE_DIRENT_H 1
+#define STDC_HEADERS 1
+#define HAVE_SYS_WAIT_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_SYS_FILE_H 1
+#define HAVE_SYS_IOCTL_H 1
+#define HAVE_SYS_SYSCALL_H 1
+#define HAVE_FCNTL_H 1
+#define HAVE_SYS_FCNTL_H 1
+#define HAVE_SYS_SELECT_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TIMES_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYSCALL_H 1
+#define HAVE_PWD_H 1
+#define HAVE_GRP_H 1
+#define HAVE_A_OUT_H 1
+#define HAVE_UTIME_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_SYS_RESOURCE_H 1
+#define HAVE_NETINET_IN_SYSTM_H 1
+#define HAVE_FLOAT_H 1
+#define HAVE_PTHREAD_H 1
+#define HAVE_UCONTEXT_H 1
+#define SIZEOF_RLIM_T 8
+#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
+#define HAVE_ST_BLKSIZE 1
+#define HAVE_STRUCT_STAT_ST_BLOCKS 1
+#define HAVE_ST_BLOCKS 1
+#define HAVE_STRUCT_STAT_ST_RDEV 1
+#define HAVE_ST_RDEV 1
+#define GETGROUPS_T gid_t
+#define RETSIGTYPE void
+#define HAVE_ALLOCA_H 1
+#define HAVE_ALLOCA 1
+#define HAVE_FSEEKO 1
+#define HAVE_FTELLO 1
+#define HAVE_DUP2 1
+#define HAVE_MEMMOVE 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_STRERROR 1
+#define HAVE_STRFTIME 1
+#define HAVE_STRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOUL 1
+#define HAVE_CRYPT 1
+#define HAVE_FLOCK 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_ISNAN 1
+#define HAVE_FINITE 1
+#define HAVE_ISINF 1
+#define HAVE_HYPOT 1
+#define HAVE_ACOSH 1
+#define HAVE_ERF 1
+#define HAVE_FMOD 1
+#define HAVE_KILLPG 1
+#define HAVE_WAIT4 1
+#define HAVE_WAITPID 1
+#define HAVE_SYSCALL 1
+#define HAVE_CHROOT 1
+#define HAVE_FSYNC 1
+#define HAVE_GETCWD 1
+#define HAVE_EACCESS 1
+#define HAVE_TRUNCATE 1
+#define HAVE_TIMES 1
+#define HAVE_UTIMES 1
+#define HAVE_FCNTL 1
+#define HAVE_LOCKF 1
+#define HAVE_LSTAT 1
+#define HAVE_SYMLINK 1
+#define HAVE_LINK 1
+#define HAVE_READLINK 1
+#define HAVE_SETITIMER 1
+#define HAVE_SETEUID 1
+#define HAVE_SETREUID 1
+#define HAVE_SETRESUID 1
+#define HAVE_SETEGID 1
+#define HAVE_SETREGID 1
+#define HAVE_SETRESGID 1
+#define HAVE_PAUSE 1
+#define HAVE_LCHOWN 1
+#define HAVE_GETPGRP 1
+#define HAVE_SETPGRP 1
+#define HAVE_GETPGID 1
+#define HAVE_SETPGID 1
+#define HAVE_INITGROUPS 1
+#define HAVE_GETGROUPS 1
+#define HAVE_SETGROUPS 1
+#define HAVE_GETPRIORITY 1
+#define HAVE_GETRLIMIT 1
+#define HAVE_SETRLIMIT 1
+#define HAVE_SYSCONF 1
+#define HAVE_DLOPEN 1
+#define HAVE_SIGPROCMASK 1
+#define HAVE_SIGACTION 1
+#define HAVE__SETJMP 1
+#define HAVE_SETSID 1
+#define HAVE_TELLDIR 1
+#define HAVE_SEEKDIR 1
+#define HAVE_FCHMOD 1
+#define HAVE_MKTIME 1
+#define HAVE_TIMEGM 1
+#define HAVE_COSH 1
+#define HAVE_SINH 1
+#define HAVE_TANH 1
+#define HAVE_SETUID 1
+#define HAVE_SETGID 1
+#define HAVE_SETENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_STRUCT_TM_TM_ZONE 1
+#define HAVE_TM_ZONE 1
+#define HAVE_STRUCT_TM_TM_GMTOFF 1
+#define HAVE_DAYLIGHT 1
+#define NEGATIVE_TIME_T 1
+#define POSIX_SIGNAL 1
+#define GETPGRP_VOID 1
+#define SETPGRP_VOID 1
+#define RSHIFT(x,y) ((x)>>(int)y)
+#define FILE_READPTR _IO_read_ptr
+#define FILE_READEND _IO_read_end
+#define HUGE_ST_INO 1
+#define HAVE__SC_CLK_TCK 1
+#define STACK_GROW_DIRECTION -1
+#define DEFAULT_KCODE KCODE_NONE
+#define USE_ELF 1
+#define DLEXT_MAXLEN 3
+#define DLEXT ".so"
+#define RUBY_LIB "/research/code/gsdl-video-import/trunk/installed/cmdline/lib/ruby/1.8"
+#define RUBY_SITE_LIB "/research/code/gsdl-video-import/trunk/installed/cmdline/lib/ruby/site_ruby"
+#define RUBY_SITE_LIB2 "/research/code/gsdl-video-import/trunk/installed/cmdline/lib/ruby/site_ruby/1.8"
+#define RUBY_PLATFORM "i686-linux"
+#define RUBY_ARCHLIB "/research/code/gsdl-video-import/trunk/installed/cmdline/lib/ruby/1.8/i686-linux"
+#define RUBY_SITE_ARCHLIB "/research/code/gsdl-video-import/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/i686-linux"
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/defines.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/defines.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/defines.h	(revision 18425)
@@ -0,0 +1,264 @@
+/************************************************
+
+  defines.h -
+
+  $Author: knu $
+  $Date: 2007-02-25 02:52:08 +0900 (Sun, 25 Feb 2007) $
+  created at: Wed May 18 00:21:44 JST 1994
+
+************************************************/
+#ifndef DEFINES_H
+#define DEFINES_H
+
+#define RUBY
+
+#ifdef __cplusplus
+# ifndef  HAVE_PROTOTYPES
+#  define HAVE_PROTOTYPES 1
+# endif
+# ifndef  HAVE_STDARG_PROTOTYPES
+#  define HAVE_STDARG_PROTOTYPES 1
+# endif
+#endif
+
+#undef _
+#ifdef HAVE_PROTOTYPES
+# define _(args) args
+#else
+# define _(args) ()
+#endif
+
+#undef __
+#ifdef HAVE_STDARG_PROTOTYPES
+# define __(args) args
+#else
+# define __(args) ()
+#endif
+
+#ifdef __cplusplus
+#define ANYARGS ...
+#else
+#define ANYARGS
+#endif
+
+#define xmalloc ruby_xmalloc
+#define xcalloc ruby_xcalloc
+#define xrealloc ruby_xrealloc
+#define xfree ruby_xfree
+
+void *xmalloc _((long));
+void *xcalloc _((long,long));
+void *xrealloc _((void*,long));
+void xfree _((void*));
+
+#if SIZEOF_LONG_LONG > 0
+# define LONG_LONG long long
+#elif SIZEOF___INT64 > 0
+# define HAVE_LONG_LONG 1
+# define LONG_LONG __int64
+# undef SIZEOF_LONG_LONG
+# define SIZEOF_LONG_LONG SIZEOF___INT64
+#endif
+
+#if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
+# define BDIGIT unsigned int
+# define SIZEOF_BDIGITS SIZEOF_INT
+# define BDIGIT_DBL unsigned LONG_LONG
+# define BDIGIT_DBL_SIGNED LONG_LONG
+#elif SIZEOF_INT*2 <= SIZEOF_LONG
+# define BDIGIT unsigned int
+# define SIZEOF_BDIGITS SIZEOF_INT
+# define BDIGIT_DBL unsigned long
+# define BDIGIT_DBL_SIGNED long
+#elif SIZEOF_SHORT*2 <= SIZEOF_LONG
+# define BDIGIT unsigned short
+# define SIZEOF_BDIGITS SIZEOF_SHORT
+# define BDIGIT_DBL unsigned long
+# define BDIGIT_DBL_SIGNED long
+#else
+# define BDIGIT unsigned short
+# define SIZEOF_BDIGITS (SIZEOF_LONG/2)
+# define BDIGIT_DBL unsigned long
+# define BDIGIT_DBL_SIGNED long
+#endif
+
+#ifdef __CYGWIN__
+#undef _WIN32
+#endif
+
+#if defined(MSDOS) || defined(_WIN32) || defined(__human68k__) || defined(__EMX__)
+#define DOSISH 1
+#ifndef _WIN32_WCE
+# define DOSISH_DRIVE_LETTER
+#endif
+#endif
+
+/* define RUBY_USE_EUC/SJIS for default kanji-code */
+#ifndef DEFAULT_KCODE
+#if defined(DOSISH) || defined(__CYGWIN__) || defined(__MACOS__) || defined(OS2)
+#define DEFAULT_KCODE KCODE_SJIS
+#else
+#define DEFAULT_KCODE KCODE_EUC
+#endif
+#endif
+
+#ifdef __NeXT__
+/* NextStep, OpenStep, Rhapsody */
+#ifndef S_IRUSR
+#define S_IRUSR 0000400        /* read permission, owner */
+#endif
+#ifndef S_IRGRP
+#define S_IRGRP 0000040        /* read permission, group */
+#endif
+#ifndef S_IROTH
+#define S_IROTH 0000004        /* read permission, other */
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR 0000200        /* write permission, owner */
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP 0000020        /* write permission, group */
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH 0000002        /* write permission, other */
+#endif
+#ifndef S_IXUSR
+#define S_IXUSR 0000100        /* execute/search permission, owner */
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0000010        /* execute/search permission, group */
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0000001        /* execute/search permission, other */
+#endif
+#ifndef S_IRWXU
+#define S_IRWXU 0000700        /* read, write, execute permissions, owner */
+#endif
+#ifndef S_IRWXG
+#define S_IRWXG 0000070        /* read, write, execute permissions, group */
+#endif
+#ifndef S_IRWXO
+#define S_IRWXO 0000007        /* read, write, execute permissions, other */
+#endif
+#ifndef S_ISBLK
+#define S_ISBLK(mode)  (((mode) & (0170000)) == (0060000))
+#endif
+#ifndef S_ISCHR
+#define S_ISCHR(mode)  (((mode) & (0170000)) == (0020000))
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(mode)  (((mode) & (0170000)) == (0040000))
+#endif
+#ifndef S_ISFIFO
+#define S_ISFIFO(mode) (((mode) & (0170000)) == (0010000))
+#endif
+#ifndef S_ISREG
+#define S_ISREG(mode)  (((mode) & (0170000)) == (0100000))
+#endif
+/* Do not trust WORDS_BIGENDIAN from configure since -arch compiler flag may
+   result in a different endian.  Instead trust __BIG_ENDIAN__ and
+   __LITTLE_ENDIAN__ which are set correctly by -arch. */
+#undef WORDS_BIGENDIAN
+#ifdef __BIG_ENDIAN__
+#define WORDS_BIGENDIAN
+#endif
+#ifndef __APPLE__
+/* NextStep, OpenStep (but not Rhapsody) */
+#ifndef GETPGRP_VOID
+#define GETPGRP_VOID 1
+#endif
+#ifndef WNOHANG
+#define WNOHANG 01
+#endif
+#ifndef WUNTRACED
+#define WUNTRACED 02
+#endif
+#ifndef X_OK
+#define X_OK 1
+#endif
+#endif /* __APPLE__ */
+#endif /* NeXT */
+
+#ifdef _WIN32
+#include "win32/win32.h"
+#endif
+
+#if defined(__VMS)
+#include "vms.h"
+#endif
+
+#if defined(__BEOS__)
+#include <net/socket.h> /* intern.h needs fd_set definition */
+#endif
+
+#ifdef RUBY_EXPORT
+#undef RUBY_EXTERN
+#endif
+
+#ifndef RUBY_EXTERN
+#define RUBY_EXTERN extern
+#endif
+
+#ifndef EXTERN
+#define EXTERN RUBY_EXTERN	/* deprecated */
+#endif
+
+#ifndef RUBY_MBCHAR_MAXSIZE
+#define RUBY_MBCHAR_MAXSIZE INT_MAX
+        /* MB_CUR_MAX will not work well in C locale */
+#endif
+
+#if defined(sparc) || defined(__sparc__)
+static inline void
+flush_register_windows(void)
+{
+    asm
+#ifdef __GNUC__
+	volatile
+#endif
+# if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__)
+	("flushw")
+# elif defined(linux) || defined(__linux__)
+	("ta  0x83")
+# else /* Solaris, OpenBSD, NetBSD, etc. */
+	("ta  0x03")
+# endif /* trap always to flush register windows if we are on a Sparc system */
+	;
+}
+#  define FLUSH_REGISTER_WINDOWS flush_register_windows()
+#elif defined(__ia64)
+void *rb_ia64_bsp(void);
+void rb_ia64_flushrs(void);
+#  define FLUSH_REGISTER_WINDOWS rb_ia64_flushrs()
+#else
+#  define FLUSH_REGISTER_WINDOWS ((void)0)
+#endif
+
+#if defined(DOSISH)
+#define PATH_SEP ";"
+#elif defined(riscos)
+#define PATH_SEP ","
+#else
+#define PATH_SEP ":"
+#endif
+#define PATH_SEP_CHAR PATH_SEP[0]
+
+#if defined(__human68k__)
+#define PATH_ENV "path"
+#else
+#define PATH_ENV "PATH"
+#endif
+
+#if defined(DOSISH) && !defined(__human68k__) && !defined(__EMX__)
+#define ENV_IGNORECASE
+#endif
+
+#ifndef DLEXT_MAXLEN
+#define DLEXT_MAXLEN 4
+#endif
+
+#ifndef RUBY_PLATFORM
+#define RUBY_PLATFORM "unknown-unknown"
+#endif
+
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/digest.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/digest.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/digest.h	(revision 18425)
@@ -0,0 +1,32 @@
+/************************************************
+
+  digest.h - header file for ruby digest modules
+
+  $Author: shyouhei $
+  created at: Fri May 25 08:54:56 JST 2001
+
+
+  Copyright (C) 2001-2006 Akinori MUSHA
+
+  $RoughId: digest.h,v 1.3 2001/07/13 15:38:27 knu Exp $
+  $Id: digest.h 11708 2007-02-12 23:01:19Z shyouhei $
+
+************************************************/
+
+#include "ruby.h"
+
+#define RUBY_DIGEST_API_VERSION	2
+
+typedef void (*rb_digest_hash_init_func_t)(void *);
+typedef void (*rb_digest_hash_update_func_t)(void *, unsigned char *, size_t);
+typedef void (*rb_digest_hash_finish_func_t)(void *, unsigned char *);
+
+typedef struct {
+    int api_version;
+    size_t digest_len;
+    size_t block_len;
+    size_t ctx_size;
+    rb_digest_hash_init_func_t init_func;
+    rb_digest_hash_update_func_t update_func;
+    rb_digest_hash_finish_func_t finish_func;
+} rb_digest_metadata_t;
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/dl.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/dl.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/dl.h	(revision 18425)
@@ -0,0 +1,313 @@
+/* -*- C -*-
+ * $Id: dl.h 11708 2007-02-12 23:01:19Z shyouhei $
+ */
+
+#ifndef RUBY_DL_H
+#define RUBY_DL_H
+
+#include <ruby.h>
+#include <dlconfig.h>
+
+#if defined(HAVE_DLFCN_H)
+# include <dlfcn.h>
+# /* some stranger systems may not define all of these */
+#ifndef RTLD_LAZY
+#define RTLD_LAZY 0
+#endif
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL 0
+#endif
+#ifndef RTLD_NOW
+#define RTLD_NOW 0
+#endif
+#else
+# if defined(HAVE_WINDOWS_H)
+#   include <windows.h>
+#   define dlclose(ptr) FreeLibrary((HINSTANCE)ptr)
+#   define dlopen(name,flag) ((void*)LoadLibrary(name))
+#   define dlerror()    "unknown error"
+#   define dlsym(handle,name) ((void*)GetProcAddress(handle,name))
+#   define RTLD_LAZY -1
+#   define RTLD_NOW  -1
+#   define RTLD_GLOBAL -1
+# endif
+#endif
+
+#if !defined(StringValue)
+# define StringValue(v) if(TYPE(v) != T_STRING) v = rb_str_to_str(v)
+#endif
+#if !defined(StringValuePtr)
+# define StringValuePtr(v) RSTRING((TYPE(v) == T_STRING) ? (v) : rb_str_to_str(v))->ptr
+#endif
+
+#ifdef DEBUG
+#define DEBUG_CODE(b) {printf("DEBUG:%d\n",__LINE__);b;}
+#define DEBUG_CODE2(b1,b2) {printf("DEBUG:%d\n",__LINE__);b1;}
+#else
+#define DEBUG_CODE(b)
+#define DEBUG_CODE2(b1,b2) b2
+#endif
+
+#define VOID_DLTYPE   0x00
+#define CHAR_DLTYPE   0x01
+#define SHORT_DLTYPE  0x02
+#define INT_DLTYPE    0x03
+#define LONG_DLTYPE   0x04
+#define FLOAT_DLTYPE  0x05
+#define DOUBLE_DLTYPE 0x06
+#define VOIDP_DLTYPE  0x07
+
+#define ARG_TYPE(x,i) (((x) & (0x07 << ((i)*3))) >> ((i)*3))
+#define PUSH_ARG(x,t) do{x <<= 3; x |= t;}while(0)
+#define PUSH_0(x) PUSH_ARG(x,VOID_DLTYPE)
+
+#if SIZEOF_INT == SIZEOF_LONG
+# define PUSH_I(x) PUSH_ARG(x,LONG_DLTYPE)
+# define ANY2I(x)  x.l
+# define DLINT(x)  (long)x
+#else
+# define PUSH_I(x) PUSH_ARG(x,INT_DLTYPE)
+# define ANY2I(x)  x.i
+# define DLINT(x)  (int)x
+#endif
+#define PUSH_L(x) PUSH_ARG(x,LONG_DLTYPE)
+#define ANY2L(x)  x.l
+#define DLLONG(x) (long)x
+
+#if defined(WITH_TYPE_FLOAT)
+# if SIZEOF_FLOAT == SIZEOF_DOUBLE
+#   define PUSH_F(x) PUSH_ARG(x,DOUBLE_DLTYPE)
+#   define ANY2F(x)  (x.d)
+#   define DLFLOAT(x) ((double)x)
+# else
+#   define PUSH_F(x) PUSH_ARG(x,FLOAT_DLTYPE)
+#   define ANY2F(x)  (x.f)
+#   define DLFLOAT(x) ((float)x)
+# endif
+#else
+# define PUSH_F(x) PUSH_ARG(x,DOUBLE_DLTYPE)
+# define ANY2F(x)  (x.d)
+# define DLFLOAT(x) ((double)x)
+#endif
+#define PUSH_D(x) PUSH_ARG(x,DOUBLE_DLTYPE)
+#define ANY2D(x)  (x.d)
+#define DLDOUBLE(x) ((double)x)
+
+#if SIZEOF_INT == SIZEOF_VOIDP && SIZEOF_INT != SIZEOF_LONG
+# define PUSH_P(x) PUSH_ARG(x,INT_DLTYPE)
+# define ANY2P(x)  (x.i)
+# define DLVOIDP(x) ((int)x)
+#elif SIZEOF_LONG == SIZEOF_VOIDP
+# define PUSH_P(x) PUSH_ARG(x,LONG_DLTYPE)
+# define ANY2P(x)  (x.l)
+# define DLVOIDP(x) ((long)x)
+#else
+# define PUSH_P(x) PUSH_ARG(x,VOIDP_DLTYPE)
+# define ANY2P(x)  (x.p)
+# define DLVOIDP(x) ((void*)p)
+#endif
+
+#if defined(WITH_TYPE_CHAR)
+# define PUSH_C(x) PUSH_ARG(x,CHAR_DLTYPE)
+# define ANY2C(x)  (x.c)
+# define DLCHAR(x) ((char)x)
+#else
+# define PUSH_C(x) PUSH_I(x)
+# define ANY2C(x)  ANY2I(x)
+# define DLCHAR(x) DLINT(x)
+#endif
+
+#if defined(WITH_TYPE_SHORT)
+# define PUSH_H(x) PUSH_ARG(x,SHORT_DLTYPE)
+# define ANY2H(x)  (x.h)
+# define DLSHORT(x) ((short)x)
+#else
+# define PUSH_H(x) PUSH_I(x)
+# define ANY2H(x)  ANY2I(x)
+# define DLSHORT(x) DLINT(x)
+#endif
+
+#define PUSH_S(x) PUSH_P(x)
+#define ANY2S(x) ANY2P(x)
+#define DLSTR(x) DLVOIDP(x)
+
+#define CBPUSH_0(x) PUSH_0(x)
+#define CBPUSH_C(x) PUSH_C(x)
+#define CBPUSH_H(x) PUSH_H(x)
+#define CBPUSH_I(x) PUSH_I(x)
+#define CBPUSH_L(x) PUSH_L(x)
+#define CBPUSH_F(x) PUSH_F(x)
+#define CBPUSH_D(x) PUSH_D(x)
+#if defined(WITH_CBTYPE_VOIDP)
+# define CBPUSH_P(x) PUSH_ARG(x,VOIDP_DLTYPE)
+#else
+# define CBPUSH_P(x) PUSH_P(x)
+#endif
+
+
+#if defined(USE_INLINE_ASM)
+# if defined(__i386__) && defined(__GNUC__)
+#   define DLSTACK
+#   define DLSTACK_METHOD "asm"
+#   define DLSTACK_REVERSE
+#   define DLSTACK_PROTO
+#   define DLSTACK_ARGS
+#   define DLSTACK_START(sym)
+#   define DLSTACK_END(sym)
+#   define DLSTACK_PUSH_C(x) asm volatile ("pushl %0" :: "g" (x));
+#   define DLSTACK_PUSH_H(x) asm volatile ("pushl %0" :: "g" (x));
+#   define DLSTACK_PUSH_I(x) asm volatile ("pushl %0" :: "g" (x));
+#   define DLSTACK_PUSH_L(x) asm volatile ("pushl %0" :: "g" (x));
+#   define DLSTACK_PUSH_P(x) asm volatile ("pushl %0" :: "g" (x));
+#   define DLSTACK_PUSH_F(x) asm volatile ("flds %0"::"g"(x));\
+                             asm volatile ("subl $4,%esp");\
+                             asm volatile ("fstps (%esp)");
+#   define DLSTACK_PUSH_D(x) asm volatile ("fldl %0"::"g"(x));\
+                             asm volatile ("subl $8,%esp");\
+                             asm volatile ("fstpl (%esp)")
+# else
+# error --with-asm is not supported on this machine
+# endif
+#elif defined(USE_DLSTACK)
+# define DLSTACK
+# define DLSTACK_GUARD
+# define DLSTACK_METHOD "dl"
+# define DLSTACK_PROTO long,long,long,long,long,\
+                       long,long,long,long,long,\
+                       long,long,long,long,long
+# define DLSTACK_ARGS  stack[0],stack[1],stack[2],stack[3],stack[4],\
+                       stack[5],stack[6],stack[7],stack[8],stack[9],\
+                       stack[10],stack[11],stack[12],stack[13],stack[14]
+# define DLSTACK_SIZE  (sizeof(long)*15)
+# define DLSTACK_START(sym)
+# define DLSTACK_END(sym)
+# define DLSTACK_PUSH_C(x)  {long v=(long)x; memcpy(sp,&v,sizeof(long)); sp++;}
+# define DLSTACK_PUSH_H(x)  {long v=(long)x; memcpy(sp,&v,sizeof(long)); sp++;}
+# define DLSTACK_PUSH_I(x)  {long v=(long)x; memcpy(sp,&v,sizeof(long)); sp++;}
+# define DLSTACK_PUSH_L(x)  memcpy(sp,&x,sizeof(long)); sp++;
+# define DLSTACK_PUSH_P(x)  memcpy(sp,&x,sizeof(void*)); sp++;
+# define DLSTACK_PUSH_F(x)  memcpy(sp,&x,sizeof(float)); sp+=sizeof(float)/sizeof(long);
+# define DLSTACK_PUSH_D(x)  memcpy(sp,&x,sizeof(double)); sp+=sizeof(double)/sizeof(long);
+#else
+# define DLSTACK_METHOD "none"
+#endif
+
+extern VALUE rb_mDL;
+extern VALUE rb_mDLMemorySpace;
+extern VALUE rb_cDLHandle;
+extern VALUE rb_cDLSymbol;
+extern VALUE rb_cDLPtrData;
+extern VALUE rb_cDLStructData;
+
+extern VALUE rb_eDLError;
+extern VALUE rb_eDLTypeError;
+
+#if defined(LONG2NUM) && (SIZEOF_LONG == SIZEOF_VOIDP)
+# define DLLONG2NUM(x) LONG2NUM((long)x)
+# define DLNUM2LONG(x) (long)(NUM2LONG(x))
+#else
+# define DLLONG2NUM(x) INT2NUM((long)x)
+# define DLNUM2LONG(x) (long)(NUM2INT(x))
+#endif
+
+typedef struct { char c; void *x; } s_voidp;
+typedef struct { char c; short x; } s_short;
+typedef struct { char c; int x; } s_int;
+typedef struct { char c; long x; } s_long;
+typedef struct { char c; float x; } s_float;
+typedef struct { char c; double x; } s_double;
+
+#define ALIGN_VOIDP  (sizeof(s_voidp) - sizeof(void *))
+#define ALIGN_SHORT  (sizeof(s_short) - sizeof(short))
+#define ALIGN_INT    (sizeof(s_int) - sizeof(int))
+#define ALIGN_LONG   (sizeof(s_long) - sizeof(long))
+#define ALIGN_FLOAT  (sizeof(s_float) - sizeof(float))
+#define ALIGN_DOUBLE (sizeof(s_double) - sizeof(double))
+
+/* for compatibility */
+#define VOIDP_ALIGN  ALIGN_VOIDP
+#define SHORT_ALIGN  ALIGN_SHORT
+#define INT_ALIGN    ALIGN_INT
+#define LONG_ALIGN   ALIGN_LONG
+#define FLOAT_ALIGN  ALIGN_FLOAT
+#define DOUBLE_ALIGN ALIGN_DOUBLE
+
+#define DLALIGN(ptr,offset,align) {\
+  while( (((unsigned long)((char *)ptr + offset)) % align) != 0 ) offset++;\
+}
+
+typedef void (*freefunc_t)(void *);
+#define DLFREEFUNC(func) ((freefunc_t)(func))
+
+typedef union {
+  void*  p;
+  char   c;
+  short  h;
+  int    i;
+  long   l;
+  float  f;
+  double d;
+  char  *s;
+} ANY_TYPE;
+
+struct dl_handle {
+  void *ptr;
+  int  open;
+  int  enable_close;
+};
+
+struct sym_data {
+  void *func;
+  char *name;
+  char *type;
+  int  len;
+};
+
+enum DLPTR_CTYPE {
+  DLPTR_CTYPE_UNKNOWN,
+  DLPTR_CTYPE_STRUCT,
+  DLPTR_CTYPE_UNION
+};
+
+struct ptr_data {
+  void *ptr;       /* a pointer to the data */
+  freefunc_t free; /* free() */
+  char *stype;      /* array of type specifiers */
+  int  *ssize;      /* size[i] = sizeof(type[i]) > 0 */
+  int  slen;   /* the number of type specifiers */
+  ID   *ids;
+  int  ids_num;
+  int  ctype; /* DLPTR_CTYPE_UNKNOWN, DLPTR_CTYPE_STRUCT, DLPTR_CTYPE_UNION */
+  long size;
+};
+
+#define RDLPTR(obj)  ((struct ptr_data *)(DATA_PTR(obj)))
+#define RDLSYM(obj)  ((struct sym_data *)(DATA_PTR(obj)))
+
+void dlfree(void*);
+void *dlmalloc(size_t);
+void *dlrealloc(void*,size_t);
+char *dlstrdup(const char *);
+size_t dlsizeof(const char *);
+
+void *rb_ary2cary(char t, VALUE ary, long *size);
+
+/*
+void rb_dlmem_delete(void *ptr);
+void rb_dlmem_aset(void *ptr, VALUE obj);
+VALUE rb_dlmem_aref(void *ptr);
+*/
+
+void dlptr_free(struct ptr_data *data);
+void dlptr_init(VALUE val);
+
+VALUE rb_dlptr_new(void *ptr, long size, freefunc_t func);
+VALUE rb_dlptr_new2(VALUE klass, void *ptr, long size, freefunc_t func);
+VALUE rb_dlptr_malloc(long size, freefunc_t func);
+void *rb_dlptr2cptr(VALUE val);
+
+VALUE rb_dlsym_new(void (*func)(), const char *name, const char *type);
+freefunc_t rb_dlsym2csym(VALUE val);
+
+
+#endif /* RUBY_DL_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/dlconfig.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/dlconfig.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/dlconfig.h	(revision 18425)
@@ -0,0 +1,19 @@
+#ifndef DLCONFIG_H
+#define DLCONFIG_H
+#define MAX_ARG           0
+#define MAX_CALLBACK 10
+#define CALLBACK_TYPES 8
+#define USE_DLSTACK
+#define WITH_TYPE_CHAR
+#define WITH_TYPE_SHORT
+#define WITH_TYPE_LONG
+#define WITH_TYPE_DOUBLE
+#define WITH_TYPE_FLOAT
+#if !defined(HAVE_DLFCN_H)
+# define HAVE_DLFCN_H
+#endif
+#if !defined(HAVE_DLERROR)
+# define HAVE_DLERROR
+#endif
+
+#endif /* DLCONFIG_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/dln.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/dln.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/dln.h	(revision 18425)
@@ -0,0 +1,40 @@
+/**********************************************************************
+
+  dln.h -
+
+  $Author: shyouhei $
+  $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+  created at: Wed Jan 19 16:53:09 JST 1994
+
+  Copyright (C) 1993-2003 Yukihiro Matsumoto
+
+**********************************************************************/
+
+#ifndef DLN_H
+#define DLN_H
+
+#ifdef __cplusplus
+# ifndef  HAVE_PROTOTYPES
+#  define HAVE_PROTOTYPES 1
+# endif
+# ifndef  HAVE_STDARG_PROTOTYPES
+#  define HAVE_STDARG_PROTOTYPES 1
+# endif
+#endif
+
+#undef _
+#ifdef HAVE_PROTOTYPES
+# define _(args) args
+#else
+# define _(args) ()
+#endif
+
+char *dln_find_exe _((const char*,const char*));
+char *dln_find_file _((const char*,const char*));
+
+#ifdef USE_DLN_A_OUT
+extern char *dln_argv0;
+#endif
+
+void *dln_load _((const char*));
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/env.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/env.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/env.h	(revision 18425)
@@ -0,0 +1,60 @@
+/**********************************************************************
+
+  env.h -
+
+  $Author: knu $
+  $Date: 2007-03-03 16:30:46 +0900 (Sat, 03 Mar 2007) $
+  created at: Mon Jul 11 11:53:03 JST 1994
+
+  Copyright (C) 1993-2003 Yukihiro Matsumoto
+
+**********************************************************************/
+
+#ifndef ENV_H
+#define ENV_H
+
+extern struct FRAME {
+    VALUE self;
+    int argc;
+    ID last_func;
+    ID orig_func;
+    VALUE last_class;
+    struct FRAME *prev;
+    struct FRAME *tmp;
+    struct RNode *node;
+    int iter;
+    int flags;
+    unsigned long uniq;
+} *ruby_frame;
+
+void rb_gc_mark_frame _((struct FRAME *));
+
+#define FRAME_DMETH  1
+#define FRAME_FUNC   2
+
+extern struct SCOPE {
+    struct RBasic super;
+    ID *local_tbl;
+    VALUE *local_vars;
+    int flags;
+} *ruby_scope;
+
+#define SCOPE_ALLOCA  0
+#define SCOPE_MALLOC  1
+#define SCOPE_NOSTACK 2
+#define SCOPE_DONT_RECYCLE 4
+#define SCOPE_CLONE   8
+
+extern int ruby_in_eval;
+
+extern VALUE ruby_class;
+
+struct RVarmap {
+    struct RBasic super;
+    ID id;
+    VALUE val;
+    struct RVarmap *next;
+};
+extern struct RVarmap *ruby_dyna_vars;
+
+#endif /* ENV_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/intern.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/intern.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/intern.h	(revision 18425)
@@ -0,0 +1,505 @@
+/**********************************************************************
+
+  intern.h -
+
+  $Author: knu $
+  $Date: 2007-03-11 17:31:53 +0900 (Sun, 11 Mar 2007) $
+  created at: Thu Jun 10 14:22:17 JST 1993
+
+  Copyright (C) 1993-2003 Yukihiro Matsumoto
+  Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
+  Copyright (C) 2000  Information-technology Promotion Agency, Japan
+
+**********************************************************************/
+
+/* 
+ * Functions and variables that are used by more than one source file of
+ * the kernel.
+ */
+
+#define ID_ALLOCATOR 1
+
+/* array.c */
+void rb_mem_clear _((register VALUE*, register long));
+VALUE rb_assoc_new _((VALUE, VALUE));
+VALUE rb_check_array_type _((VALUE));
+VALUE rb_ary_new _((void));
+VALUE rb_ary_new2 _((long));
+VALUE rb_ary_new3 __((long,...));
+VALUE rb_ary_new4 _((long, const VALUE *));
+VALUE rb_ary_freeze _((VALUE));
+VALUE rb_ary_aref _((int, VALUE*, VALUE));
+void rb_ary_store _((VALUE, long, VALUE));
+VALUE rb_ary_dup _((VALUE));
+VALUE rb_ary_to_ary _((VALUE));
+VALUE rb_ary_to_s _((VALUE));
+VALUE rb_ary_push _((VALUE, VALUE));
+VALUE rb_ary_pop _((VALUE));
+VALUE rb_ary_shift _((VALUE));
+VALUE rb_ary_unshift _((VALUE, VALUE));
+VALUE rb_ary_entry _((VALUE, long));
+VALUE rb_ary_each _((VALUE));
+VALUE rb_ary_join _((VALUE, VALUE));
+VALUE rb_ary_print_on _((VALUE, VALUE));
+VALUE rb_ary_reverse _((VALUE));
+VALUE rb_ary_sort _((VALUE));
+VALUE rb_ary_sort_bang _((VALUE));
+VALUE rb_ary_delete _((VALUE, VALUE));
+VALUE rb_ary_delete_at _((VALUE, long));
+VALUE rb_ary_clear _((VALUE));
+VALUE rb_ary_plus _((VALUE, VALUE));
+VALUE rb_ary_concat _((VALUE, VALUE));
+VALUE rb_ary_assoc _((VALUE, VALUE));
+VALUE rb_ary_rassoc _((VALUE, VALUE));
+VALUE rb_ary_includes _((VALUE, VALUE));
+VALUE rb_ary_cmp _((VALUE, VALUE));
+VALUE rb_protect_inspect _((VALUE(*)(ANYARGS),VALUE,VALUE));
+VALUE rb_inspecting_p _((VALUE));
+VALUE rb_check_array_value _((VALUE));
+VALUE rb_values_at _((VALUE, long, int, VALUE*, VALUE(*) _((VALUE,long))));
+/* bignum.c */
+VALUE rb_big_clone _((VALUE));
+void rb_big_2comp _((VALUE));
+VALUE rb_big_norm _((VALUE));
+VALUE rb_uint2big _((unsigned long));
+VALUE rb_int2big _((long));
+VALUE rb_uint2inum _((unsigned long));
+VALUE rb_int2inum _((long));
+VALUE rb_cstr_to_inum _((const char*, int, int));
+VALUE rb_str_to_inum _((VALUE, int, int));
+VALUE rb_cstr2inum _((const char*, int));
+VALUE rb_str2inum _((VALUE, int));
+VALUE rb_big2str _((VALUE, int));
+VALUE rb_big2str0 _((VALUE, int, int));
+long rb_big2long _((VALUE));
+#define rb_big2int(x) rb_big2long(x)
+unsigned long rb_big2ulong _((VALUE));
+#define rb_big2uint(x) rb_big2ulong(x)
+#if HAVE_LONG_LONG
+VALUE rb_ll2inum _((LONG_LONG));
+VALUE rb_ull2inum _((unsigned LONG_LONG));
+LONG_LONG rb_big2ll _((VALUE));
+unsigned LONG_LONG rb_big2ull _((VALUE));
+#endif  /* HAVE_LONG_LONG */
+void rb_quad_pack _((char*,VALUE));
+VALUE rb_quad_unpack _((const char*,int));
+VALUE rb_dbl2big _((double));
+double rb_big2dbl _((VALUE));
+VALUE rb_big_plus _((VALUE, VALUE));
+VALUE rb_big_minus _((VALUE, VALUE));
+VALUE rb_big_mul _((VALUE, VALUE));
+VALUE rb_big_divmod _((VALUE, VALUE));
+VALUE rb_big_pow _((VALUE, VALUE));
+VALUE rb_big_and _((VALUE, VALUE));
+VALUE rb_big_or _((VALUE, VALUE));
+VALUE rb_big_xor _((VALUE, VALUE));
+VALUE rb_big_lshift _((VALUE, VALUE));
+VALUE rb_big_rand _((VALUE, double*));
+/* class.c */
+VALUE rb_class_boot _((VALUE));
+VALUE rb_class_new _((VALUE));
+VALUE rb_mod_init_copy _((VALUE, VALUE));
+VALUE rb_class_init_copy _((VALUE, VALUE));
+VALUE rb_singleton_class_clone _((VALUE));
+void rb_singleton_class_attached _((VALUE,VALUE));
+VALUE rb_make_metaclass _((VALUE, VALUE));
+void rb_check_inheritable _((VALUE));
+VALUE rb_class_inherited _((VALUE, VALUE));
+VALUE rb_define_class_id _((ID, VALUE));
+VALUE rb_module_new _((void));
+VALUE rb_define_module_id _((ID));
+VALUE rb_mod_included_modules _((VALUE));
+VALUE rb_mod_include_p _((VALUE, VALUE));
+VALUE rb_mod_ancestors _((VALUE));
+VALUE rb_class_instance_methods _((int, VALUE*, VALUE));
+VALUE rb_class_public_instance_methods _((int, VALUE*, VALUE));
+VALUE rb_class_protected_instance_methods _((int, VALUE*, VALUE));
+VALUE rb_class_private_instance_methods _((int, VALUE*, VALUE));
+VALUE rb_obj_singleton_methods _((int, VALUE*, VALUE));
+void rb_define_method_id _((VALUE, ID, VALUE (*)(ANYARGS), int));
+void rb_frozen_class_p _((VALUE));
+void rb_undef _((VALUE, ID));
+void rb_define_protected_method _((VALUE, const char*, VALUE (*)(ANYARGS), int));
+void rb_define_private_method _((VALUE, const char*, VALUE (*)(ANYARGS), int));
+void rb_define_singleton_method _((VALUE, const char*, VALUE(*)(ANYARGS), int));
+VALUE rb_singleton_class _((VALUE));
+/* compar.c */
+int rb_cmpint _((VALUE, VALUE, VALUE));
+NORETURN(void rb_cmperr _((VALUE, VALUE)));
+/* enum.c */
+/* error.c */
+RUBY_EXTERN int ruby_nerrs;
+VALUE rb_exc_new _((VALUE, const char*, long));
+VALUE rb_exc_new2 _((VALUE, const char*));
+VALUE rb_exc_new3 _((VALUE, VALUE));
+NORETURN(void rb_loaderror __((const char*, ...)));
+NORETURN(void rb_name_error __((ID, const char*, ...)));
+NORETURN(void rb_invalid_str _((const char*, const char*)));
+void rb_compile_error __((const char*, ...));
+void rb_compile_error_append __((const char*, ...));
+NORETURN(void rb_load_fail _((const char*)));
+NORETURN(void rb_error_frozen _((const char*)));
+void rb_check_frozen _((VALUE));
+/* eval.c */
+RUBY_EXTERN struct RNode *ruby_current_node;
+void ruby_set_current_source _((void));
+NORETURN(void rb_exc_raise _((VALUE)));
+NORETURN(void rb_exc_fatal _((VALUE)));
+VALUE rb_f_exit _((int,VALUE*));
+VALUE rb_f_abort _((int,VALUE*));
+void rb_remove_method _((VALUE, const char*));
+#define rb_disable_super(klass, name) ((void)0)
+#define rb_enable_super(klass, name) ((void)0)
+#define HAVE_RB_DEFINE_ALLOC_FUNC 1
+void rb_define_alloc_func _((VALUE, VALUE (*)(VALUE)));
+void rb_undef_alloc_func _((VALUE));
+void rb_clear_cache _((void));
+void rb_clear_cache_by_class _((VALUE));
+void rb_alias _((VALUE, ID, ID));
+void rb_attr _((VALUE,ID,int,int,int));
+int rb_method_boundp _((VALUE, ID, int));
+VALUE rb_dvar_defined _((ID));
+VALUE rb_dvar_curr _((ID));
+VALUE rb_dvar_ref _((ID));
+void rb_dvar_asgn _((ID, VALUE));
+void rb_dvar_push _((ID, VALUE));
+VALUE *rb_svar _((int));
+VALUE rb_eval_cmd _((VALUE, VALUE, int));
+int rb_obj_respond_to _((VALUE, ID, int));
+int rb_respond_to _((VALUE, ID));
+void rb_interrupt _((void));
+VALUE rb_apply _((VALUE, ID, VALUE));
+void rb_backtrace _((void));
+ID rb_frame_last_func _((void));
+VALUE rb_obj_instance_eval _((int, VALUE*, VALUE));
+VALUE rb_mod_module_eval _((int, VALUE*, VALUE));
+void rb_load _((VALUE, int));
+void rb_load_protect _((VALUE, int, int*));
+NORETURN(void rb_jump_tag _((int)));
+int rb_provided _((const char*));
+void rb_provide _((const char*));
+VALUE rb_f_require _((VALUE, VALUE));
+VALUE rb_require_safe _((VALUE, int));
+void rb_obj_call_init _((VALUE, int, VALUE*));
+VALUE rb_class_new_instance _((int, VALUE*, VALUE));
+VALUE rb_block_proc _((void));
+VALUE rb_f_lambda _((void));
+VALUE rb_proc_new _((VALUE (*)(ANYARGS/* VALUE yieldarg[, VALUE procarg] */), VALUE));
+VALUE rb_protect _((VALUE (*)(VALUE), VALUE, int*));
+void rb_set_end_proc _((void (*)(VALUE), VALUE));
+void rb_mark_end_proc _((void));
+void rb_exec_end_proc _((void));
+void ruby_finalize _((void));
+NORETURN(void ruby_stop _((int)));
+int ruby_cleanup _((int));
+int ruby_exec _((void));
+void rb_gc_mark_threads _((void));
+void rb_thread_start_timer _((void));
+void rb_thread_stop_timer _((void));
+void rb_thread_schedule _((void));
+void rb_thread_wait_fd _((int));
+int rb_thread_fd_writable _((int));
+void rb_thread_fd_close _((int));
+int rb_thread_alone _((void));
+void rb_thread_polling _((void));
+void rb_thread_sleep _((int));
+void rb_thread_sleep_forever _((void));
+VALUE rb_thread_stop _((void));
+VALUE rb_thread_wakeup _((VALUE));
+VALUE rb_thread_run _((VALUE));
+VALUE rb_thread_kill _((VALUE));
+VALUE rb_thread_create _((VALUE (*)(ANYARGS), void*));
+void rb_thread_interrupt _((void));
+void rb_thread_trap_eval _((VALUE, int, int));
+void rb_thread_signal_raise _((int));
+void rb_thread_signal_exit _((void));
+int rb_thread_select _((int, fd_set *, fd_set *, fd_set *, struct timeval *));
+void rb_thread_wait_for _((struct timeval));
+VALUE rb_thread_current _((void));
+VALUE rb_thread_main _((void));
+VALUE rb_thread_local_aref _((VALUE, ID));
+VALUE rb_thread_local_aset _((VALUE, ID, VALUE));
+void rb_thread_atfork _((void));
+VALUE rb_funcall_rescue __((VALUE, ID, int, ...));
+/* file.c */
+VALUE rb_file_s_expand_path _((int, VALUE *));
+VALUE rb_file_expand_path _((VALUE, VALUE));
+void rb_file_const _((const char*, VALUE));
+int rb_find_file_ext _((VALUE*, const char* const*));
+VALUE rb_find_file _((VALUE));
+char *rb_path_next _((const char *));
+char *rb_path_skip_prefix _((const char *));
+char *rb_path_last_separator _((const char *));
+char *rb_path_end _((const char *));
+VALUE rb_file_directory_p _((VALUE,VALUE));
+/* gc.c */
+NORETURN(void rb_memerror __((void)));
+int ruby_stack_check _((void));
+int ruby_stack_length _((VALUE**));
+char *rb_source_filename _((const char*));
+void rb_gc_mark_locations _((VALUE*, VALUE*));
+void rb_mark_tbl _((struct st_table*));
+void rb_mark_hash _((struct st_table*));
+void rb_gc_mark_maybe _((VALUE));
+void rb_gc_mark _((VALUE));
+void rb_gc_force_recycle _((VALUE));
+void rb_gc _((void));
+void rb_gc_copy_finalizer _((VALUE,VALUE));
+void rb_gc_finalize_deferred _((void));
+void rb_gc_call_finalizer_at_exit _((void));
+VALUE rb_gc_enable _((void));
+VALUE rb_gc_disable _((void));
+VALUE rb_gc_start _((void));
+/* hash.c */
+void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long));
+void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE));
+VALUE rb_hash _((VALUE));
+VALUE rb_hash_new _((void));
+VALUE rb_hash_freeze _((VALUE));
+VALUE rb_hash_aref _((VALUE, VALUE));
+VALUE rb_hash_aset _((VALUE, VALUE, VALUE));
+VALUE rb_hash_delete_if _((VALUE));
+VALUE rb_hash_delete _((VALUE,VALUE));
+int rb_path_check _((char*));
+int rb_env_path_tainted _((void));
+/* io.c */
+#define rb_defout rb_stdout
+RUBY_EXTERN VALUE rb_fs;
+RUBY_EXTERN VALUE rb_output_fs;
+RUBY_EXTERN VALUE rb_rs;
+RUBY_EXTERN VALUE rb_default_rs;
+RUBY_EXTERN VALUE rb_output_rs;
+VALUE rb_io_write _((VALUE, VALUE));
+VALUE rb_io_gets _((VALUE));
+VALUE rb_io_getc _((VALUE));
+VALUE rb_io_ungetc _((VALUE, VALUE));
+VALUE rb_io_close _((VALUE));
+VALUE rb_io_eof _((VALUE));
+VALUE rb_io_binmode _((VALUE));
+VALUE rb_io_addstr _((VALUE, VALUE));
+VALUE rb_io_printf _((int, VALUE*, VALUE));
+VALUE rb_io_print _((int, VALUE*, VALUE));
+VALUE rb_io_puts _((int, VALUE*, VALUE));
+VALUE rb_file_open _((const char*, const char*));
+VALUE rb_gets _((void));
+void rb_write_error _((const char*));
+void rb_write_error2 _((const char*, long));
+/* marshal.c */
+VALUE rb_marshal_dump _((VALUE, VALUE));
+VALUE rb_marshal_load _((VALUE));
+/* numeric.c */
+void rb_num_zerodiv _((void));
+VALUE rb_num_coerce_bin _((VALUE, VALUE));
+VALUE rb_num_coerce_cmp _((VALUE, VALUE));
+VALUE rb_num_coerce_relop _((VALUE, VALUE));
+VALUE rb_float_new _((double));
+VALUE rb_num2fix _((VALUE));
+VALUE rb_fix2str _((VALUE, int));
+VALUE rb_dbl_cmp _((double, double));
+/* object.c */
+int rb_eql _((VALUE, VALUE));
+VALUE rb_any_to_s _((VALUE));
+VALUE rb_inspect _((VALUE));
+VALUE rb_obj_is_instance_of _((VALUE, VALUE));
+VALUE rb_obj_is_kind_of _((VALUE, VALUE));
+VALUE rb_obj_alloc _((VALUE));
+VALUE rb_obj_clone _((VALUE));
+VALUE rb_obj_dup _((VALUE));
+VALUE rb_obj_init_copy _((VALUE,VALUE));
+VALUE rb_obj_taint _((VALUE));
+VALUE rb_obj_tainted _((VALUE));
+VALUE rb_obj_untaint _((VALUE));
+VALUE rb_obj_freeze _((VALUE));
+VALUE rb_obj_id _((VALUE));
+VALUE rb_obj_class _((VALUE));
+VALUE rb_class_real _((VALUE));
+VALUE rb_class_inherited_p _((VALUE, VALUE));
+VALUE rb_convert_type _((VALUE,int,const char*,const char*));
+VALUE rb_check_convert_type _((VALUE,int,const char*,const char*));
+VALUE rb_to_int _((VALUE));
+VALUE rb_Integer _((VALUE));
+VALUE rb_Float _((VALUE));
+VALUE rb_String _((VALUE));
+VALUE rb_Array _((VALUE));
+double rb_cstr_to_dbl _((const char*, int));
+double rb_str_to_dbl _((VALUE, int));
+/* parse.y */
+RUBY_EXTERN int   ruby_sourceline;
+RUBY_EXTERN char *ruby_sourcefile;
+int ruby_yyparse _((void));
+ID rb_id_attrset _((ID));
+void rb_parser_append_print _((void));
+void rb_parser_while_loop _((int, int));
+int ruby_parser_stack_on_heap _((void));
+void rb_gc_mark_parser _((void));
+int rb_is_const_id _((ID));
+int rb_is_instance_id _((ID));
+int rb_is_class_id _((ID));
+int rb_is_local_id _((ID));
+int rb_is_junk_id _((ID));
+int rb_symname_p _((const char*));
+int rb_sym_interned_p _((VALUE));
+VALUE rb_backref_get _((void));
+void rb_backref_set _((VALUE));
+VALUE rb_lastline_get _((void));
+void rb_lastline_set _((VALUE));
+VALUE rb_sym_all_symbols _((void));
+/* process.c */
+int rb_proc_exec _((const char*));
+VALUE rb_f_exec _((int,VALUE*));
+int rb_waitpid _((int,int*,int));
+void rb_syswait _((int));
+VALUE rb_proc_times _((VALUE));
+VALUE rb_detach_process _((int));
+/* range.c */
+VALUE rb_range_new _((VALUE, VALUE, int));
+VALUE rb_range_beg_len _((VALUE, long*, long*, long, int));
+VALUE rb_length_by_each _((VALUE));
+/* re.c */
+int rb_memcmp _((const void*,const void*,long));
+int rb_memcicmp _((const void*,const void*,long));
+long rb_memsearch _((const void*,long,const void*,long));
+VALUE rb_reg_nth_defined _((int, VALUE));
+VALUE rb_reg_nth_match _((int, VALUE));
+VALUE rb_reg_last_match _((VALUE));
+VALUE rb_reg_match_pre _((VALUE));
+VALUE rb_reg_match_post _((VALUE));
+VALUE rb_reg_match_last _((VALUE));
+VALUE rb_reg_new _((const char*, long, int));
+VALUE rb_reg_match _((VALUE, VALUE));
+VALUE rb_reg_match2 _((VALUE));
+int rb_reg_options _((VALUE));
+void rb_set_kcode _((const char*));
+const char* rb_get_kcode _((void));
+void rb_kcode_set_option _((VALUE));
+void rb_kcode_reset_option _((void));
+/* ruby.c */
+RUBY_EXTERN VALUE rb_argv;
+RUBY_EXTERN VALUE rb_argv0;
+void rb_load_file _((const char*));
+void ruby_script _((const char*));
+void ruby_prog_init _((void));
+void ruby_set_argv _((int, char**));
+void ruby_process_options _((int, char**));
+void ruby_load_script _((void));
+void ruby_init_loadpath _((void));
+void ruby_incpush _((const char*));
+/* signal.c */
+VALUE rb_f_kill _((int, VALUE*));
+void rb_gc_mark_trap_list _((void));
+#ifdef POSIX_SIGNAL
+#define posix_signal ruby_posix_signal
+void posix_signal _((int, RETSIGTYPE (*)(int)));
+#endif
+void rb_trap_exit _((void));
+void rb_trap_exec _((void));
+const char *ruby_signal_name _((int));
+void ruby_default_signal _((int));
+/* sprintf.c */
+VALUE rb_f_sprintf _((int, VALUE*));
+/* string.c */
+VALUE rb_str_new _((const char*, long));
+VALUE rb_str_new2 _((const char*));
+VALUE rb_str_new3 _((VALUE));
+VALUE rb_str_new4 _((VALUE));
+VALUE rb_str_new5 _((VALUE, const char*, long));
+VALUE rb_tainted_str_new _((const char*, long));
+VALUE rb_tainted_str_new2 _((const char*));
+VALUE rb_str_buf_new _((long));
+VALUE rb_str_buf_new2 _((const char*));
+VALUE rb_str_buf_append _((VALUE, VALUE));
+VALUE rb_str_buf_cat _((VALUE, const char*, long));
+VALUE rb_str_buf_cat2 _((VALUE, const char*));
+VALUE rb_obj_as_string _((VALUE));
+VALUE rb_check_string_type _((VALUE));
+VALUE rb_str_dup _((VALUE));
+VALUE rb_str_locktmp _((VALUE));
+VALUE rb_str_unlocktmp _((VALUE));
+VALUE rb_str_dup_frozen _((VALUE));
+VALUE rb_str_plus _((VALUE, VALUE));
+VALUE rb_str_times _((VALUE, VALUE));
+VALUE rb_str_substr _((VALUE, long, long));
+void rb_str_modify _((VALUE));
+VALUE rb_str_freeze _((VALUE));
+VALUE rb_str_resize _((VALUE, long));
+VALUE rb_str_cat _((VALUE, const char*, long));
+VALUE rb_str_cat2 _((VALUE, const char*));
+VALUE rb_str_append _((VALUE, VALUE));
+VALUE rb_str_concat _((VALUE, VALUE));
+int rb_str_hash _((VALUE));
+int rb_str_cmp _((VALUE, VALUE));
+VALUE rb_str_upto _((VALUE, VALUE, int));
+void rb_str_update _((VALUE, long, long, VALUE));
+VALUE rb_str_inspect _((VALUE));
+VALUE rb_str_dump _((VALUE));
+VALUE rb_str_split _((VALUE, const char*));
+void rb_str_associate _((VALUE, VALUE));
+VALUE rb_str_associated _((VALUE));
+void rb_str_setter _((VALUE, ID, VALUE*));
+VALUE rb_str_intern _((VALUE));
+/* struct.c */
+VALUE rb_struct_new __((VALUE, ...));
+VALUE rb_struct_define __((const char*, ...));
+VALUE rb_struct_alloc _((VALUE, VALUE));
+VALUE rb_struct_aref _((VALUE, VALUE));
+VALUE rb_struct_aset _((VALUE, VALUE, VALUE));
+VALUE rb_struct_getmember _((VALUE, ID));
+VALUE rb_struct_iv_get _((VALUE, char*));
+VALUE rb_struct_s_members _((VALUE));
+VALUE rb_struct_members _((VALUE));
+/* time.c */
+VALUE rb_time_new _((time_t, time_t));
+/* variable.c */
+VALUE rb_mod_name _((VALUE));
+VALUE rb_class_path _((VALUE));
+void rb_set_class_path _((VALUE, VALUE, const char*));
+VALUE rb_path2class _((const char*));
+void rb_name_class _((VALUE, ID));
+VALUE rb_class_name _((VALUE));
+void rb_autoload _((VALUE, ID, const char*));
+VALUE rb_autoload_load _((VALUE, ID));
+VALUE rb_autoload_p _((VALUE, ID));
+void rb_gc_mark_global_tbl _((void));
+VALUE rb_f_trace_var _((int, VALUE*));
+VALUE rb_f_untrace_var _((int, VALUE*));
+VALUE rb_f_global_variables _((void));
+void rb_alias_variable _((ID, ID));
+struct st_table* rb_generic_ivar_table _((VALUE));
+void rb_copy_generic_ivar _((VALUE,VALUE));
+void rb_mark_generic_ivar _((VALUE));
+void rb_mark_generic_ivar_tbl _((void));
+void rb_free_generic_ivar _((VALUE));
+VALUE rb_ivar_get _((VALUE, ID));
+VALUE rb_ivar_set _((VALUE, ID, VALUE));
+VALUE rb_ivar_defined _((VALUE, ID));
+VALUE rb_iv_set _((VALUE, const char*, VALUE));
+VALUE rb_iv_get _((VALUE, const char*));
+VALUE rb_attr_get _((VALUE, ID));
+VALUE rb_obj_instance_variables _((VALUE));
+VALUE rb_obj_remove_instance_variable _((VALUE, VALUE));
+void *rb_mod_const_at _((VALUE, void*));
+void *rb_mod_const_of _((VALUE, void*));
+VALUE rb_const_list _((void*));
+VALUE rb_mod_constants _((VALUE));
+VALUE rb_mod_remove_const _((VALUE, VALUE));
+int rb_const_defined _((VALUE, ID));
+int rb_const_defined_at _((VALUE, ID));
+int rb_const_defined_from _((VALUE, ID));
+VALUE rb_const_get _((VALUE, ID));
+VALUE rb_const_get_at _((VALUE, ID));
+VALUE rb_const_get_from _((VALUE, ID));
+void rb_const_set _((VALUE, ID, VALUE));
+VALUE rb_mod_constants _((VALUE));
+VALUE rb_mod_const_missing _((VALUE,VALUE));
+VALUE rb_cvar_defined _((VALUE, ID));
+#define RB_CVAR_SET_4ARGS 1
+void rb_cvar_set _((VALUE, ID, VALUE, int));
+VALUE rb_cvar_get _((VALUE, ID));
+void rb_cv_set _((VALUE, const char*, VALUE));
+VALUE rb_cv_get _((VALUE, const char*));
+void rb_define_class_variable _((VALUE, const char*, VALUE));
+VALUE rb_mod_class_variables _((VALUE));
+VALUE rb_mod_remove_cvar _((VALUE, VALUE));
+/* version.c */
+void ruby_show_version _((void));
+void ruby_show_copyright _((void));
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/missing.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/missing.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/missing.h	(revision 18425)
@@ -0,0 +1,142 @@
+/************************************************
+
+  missing.h - prototype for *.c in ./missing, and
+  	      for missing timeval struct
+
+  $Author: shyouhei $
+  $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+  created at: Sat May 11 23:46:03 JST 2002
+
+************************************************/
+
+#ifndef MISSING_H
+#define MISSING_H
+
+#if defined(HAVE_SYS_TIME_H)
+#  include <sys/time.h>
+#elif !defined(_WIN32)
+#  define time_t long
+struct timeval {
+    time_t tv_sec;	/* seconds */
+    time_t tv_usec;	/* microseconds */
+};
+#endif
+#if defined(HAVE_SYS_TYPES_H)
+#  include <sys/types.h>
+#endif
+
+#ifndef HAVE_ACOSH
+extern double acosh _((double));
+extern double asinh _((double));
+extern double atanh _((double));
+#endif
+
+#ifndef HAVE_CRYPT
+extern char *crypt _((char *, char *));
+#endif
+
+#ifndef HAVE_DUP2
+extern int dup2 _((int, int));
+#endif
+
+#ifndef HAVE_EACCESS
+extern int eaccess _((const char*, int));
+#endif
+
+#ifndef HAVE_FINITE
+extern int finite _((double));
+#endif
+
+#ifndef HAVE_FLOCK
+extern int flock _((int, int));
+#endif
+
+/*
+#ifndef HAVE_FREXP
+extern double frexp _((double, int *));
+#endif
+*/
+
+#ifndef HAVE_HYPOT
+extern double hypot _((double, double));
+#endif
+
+#ifndef HAVE_ERF
+extern double erf _((double));
+extern double erfc _((double));
+#endif
+
+#ifndef HAVE_ISINF
+# if defined(HAVE_FINITE) && defined(HAVE_ISNAN)
+# define isinf(x) (!finite(x) && !isnan(x))
+# else
+extern int isinf _((double));
+# endif
+#endif
+
+#ifndef HAVE_ISNAN
+extern int isnan _((double));
+#endif
+
+/*
+#ifndef HAVE_MEMCMP
+extern int memcmp _((char *, char *, int));
+#endif
+*/
+
+#ifndef HAVE_MEMMOVE
+extern void *memmove _((void *, void *, int));
+#endif
+
+/*
+#ifndef HAVE_MODF
+extern double modf _((double, double *));
+#endif
+*/
+
+#ifndef HAVE_STRCASECMP
+extern int strcasecmp _((char *, char *));
+#endif
+
+#ifndef HAVE_STRNCASECMP
+extern int strncasecmp _((char *, char *, int));
+#endif
+
+#ifndef HAVE_STRCHR
+extern char *strchr _((char *, int));
+extern char *strrchr _((char *, int));
+#endif
+
+#ifndef HAVE_STRERROR
+extern char *strerror _((int));
+#endif
+
+#ifndef HAVE_STRFTIME
+extern size_t strftime _((char *, size_t, const char *, const struct tm *));
+#endif
+
+#ifndef HAVE_STRSTR
+extern char *strstr _((char *, char *));
+#endif
+
+/*
+#ifndef HAVE_STRTOL
+extern long strtol _((char *, char **, int));
+#endif
+*/
+
+#ifndef HAVE_STRTOUL
+extern unsigned long strtoul _((char *, char **, int));
+#endif
+
+#ifndef HAVE_VSNPRINTF
+# ifdef HAVE_STDARG_PROTOTYPES
+#  include <stdarg.h>
+# else
+#  include <varargs.h>
+# endif
+extern int snprintf __((char *, size_t n, char const *, ...));
+extern int vsnprintf _((char *, size_t n, char const *, va_list));
+#endif
+
+#endif /* MISSING_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/node.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/node.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/node.h	(revision 18425)
@@ -0,0 +1,474 @@
+/**********************************************************************
+
+  node.h -
+
+  $Author: shyouhei $
+  $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+  created at: Fri May 28 15:14:02 JST 1993
+
+  Copyright (C) 1993-2003 Yukihiro Matsumoto
+
+**********************************************************************/
+
+#ifndef NODE_H
+#define NODE_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+enum node_type {
+    NODE_METHOD,
+    NODE_FBODY,
+    NODE_CFUNC,
+    NODE_SCOPE,
+    NODE_BLOCK,
+    NODE_IF,
+    NODE_CASE,
+    NODE_WHEN,
+    NODE_OPT_N,
+    NODE_WHILE,
+    NODE_UNTIL,
+    NODE_ITER,
+    NODE_FOR,
+    NODE_BREAK,
+    NODE_NEXT,
+    NODE_REDO,
+    NODE_RETRY,
+    NODE_BEGIN,
+    NODE_RESCUE,
+    NODE_RESBODY,
+    NODE_ENSURE,
+    NODE_AND,
+    NODE_OR,
+    NODE_NOT,
+    NODE_MASGN,
+    NODE_LASGN,
+    NODE_DASGN,
+    NODE_DASGN_CURR,
+    NODE_GASGN,
+    NODE_IASGN,
+    NODE_CDECL,
+    NODE_CVASGN,
+    NODE_CVDECL,
+    NODE_OP_ASGN1,
+    NODE_OP_ASGN2,
+    NODE_OP_ASGN_AND,
+    NODE_OP_ASGN_OR,
+    NODE_CALL,
+    NODE_FCALL,
+    NODE_VCALL,
+    NODE_SUPER,
+    NODE_ZSUPER,
+    NODE_ARRAY,
+    NODE_ZARRAY,
+    NODE_HASH,
+    NODE_RETURN,
+    NODE_YIELD,
+    NODE_LVAR,
+    NODE_DVAR,
+    NODE_GVAR,
+    NODE_IVAR,
+    NODE_CONST,
+    NODE_CVAR,
+    NODE_NTH_REF,
+    NODE_BACK_REF,
+    NODE_MATCH,
+    NODE_MATCH2,
+    NODE_MATCH3,
+    NODE_LIT,
+    NODE_STR,
+    NODE_DSTR,
+    NODE_XSTR,
+    NODE_DXSTR,
+    NODE_EVSTR,
+    NODE_DREGX,
+    NODE_DREGX_ONCE,
+    NODE_ARGS,
+    NODE_ARGSCAT,
+    NODE_ARGSPUSH,
+    NODE_SPLAT,
+    NODE_TO_ARY,
+    NODE_SVALUE,
+    NODE_BLOCK_ARG,
+    NODE_BLOCK_PASS,
+    NODE_DEFN,
+    NODE_DEFS,
+    NODE_ALIAS,
+    NODE_VALIAS,
+    NODE_UNDEF,
+    NODE_CLASS,
+    NODE_MODULE,
+    NODE_SCLASS,
+    NODE_COLON2,
+    NODE_COLON3,
+    NODE_CREF,
+    NODE_DOT2,
+    NODE_DOT3,
+    NODE_FLIP2,
+    NODE_FLIP3,
+    NODE_ATTRSET,
+    NODE_SELF,
+    NODE_NIL,
+    NODE_TRUE,
+    NODE_FALSE,
+    NODE_DEFINED,
+    NODE_NEWLINE,
+    NODE_POSTEXE,
+    NODE_ALLOCA,
+    NODE_DMETHOD,
+    NODE_BMETHOD,
+    NODE_MEMO,
+    NODE_IFUNC,
+    NODE_DSYM,
+    NODE_ATTRASGN,
+    NODE_LAST
+};
+
+typedef struct RNode {
+    unsigned long flags;
+    char *nd_file;
+    union {
+	struct RNode *node;
+	ID id;
+	VALUE value;
+	VALUE (*cfunc)(ANYARGS);
+	ID *tbl;
+    } u1;
+    union {
+	struct RNode *node;
+	ID id;
+	long argc;
+	VALUE value;
+    } u2;
+    union {
+	struct RNode *node;
+	ID id;
+	long state;
+	struct global_entry *entry;
+	long cnt;
+	VALUE value;
+    } u3;
+} NODE;
+
+extern NODE *ruby_cref;
+extern NODE *ruby_top_cref;
+
+#define RNODE(obj)  (R_CAST(RNode)(obj))
+
+#define nd_type(n) ((int)(((RNODE(n))->flags>>FL_USHIFT)&0xff))
+#define nd_set_type(n,t) \
+    RNODE(n)->flags=((RNODE(n)->flags&~FL_UMASK)|(((t)<<FL_USHIFT)&FL_UMASK))
+
+#define NODE_LSHIFT (FL_USHIFT+8)
+#define NODE_LMASK  (((long)1<<(sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT))-1)
+#define nd_line(n) ((unsigned int)(((RNODE(n))->flags>>NODE_LSHIFT)&NODE_LMASK))
+#define nd_set_line(n,l) \
+    RNODE(n)->flags=((RNODE(n)->flags&~(-1<<NODE_LSHIFT))|(((l)&NODE_LMASK)<<NODE_LSHIFT))
+
+#define nd_head  u1.node
+#define nd_alen  u2.argc
+#define nd_next  u3.node
+
+#define nd_cond  u1.node
+#define nd_body  u2.node
+#define nd_else  u3.node
+
+#define nd_orig  u3.value
+
+#define nd_resq  u2.node
+#define nd_ensr  u3.node
+
+#define nd_1st   u1.node
+#define nd_2nd   u2.node
+
+#define nd_stts  u1.node
+
+#define nd_entry u3.entry
+#define nd_vid   u1.id
+#define nd_cflag u2.id
+#define nd_cval  u3.value
+
+#define nd_cnt   u3.cnt
+#define nd_tbl   u1.tbl
+
+#define nd_var   u1.node
+#define nd_ibdy  u2.node
+#define nd_iter  u3.node
+
+#define nd_value u2.node
+#define nd_aid   u3.id
+
+#define nd_lit   u1.value
+
+#define nd_frml  u1.node
+#define nd_rest  u2.node
+#define nd_opt   u1.node
+
+#define nd_recv  u1.node
+#define nd_mid   u2.id
+#define nd_args  u3.node
+
+#define nd_noex  u1.id
+#define nd_defn  u3.node
+
+#define nd_cfnc  u1.cfunc
+#define nd_argc  u2.argc
+
+#define nd_cpath u1.node
+#define nd_super u3.node
+
+#define nd_modl  u1.id
+#define nd_clss  u1.value
+
+#define nd_beg   u1.node
+#define nd_end   u2.node
+#define nd_state u3.state
+#define nd_rval  u2.value
+
+#define nd_nth   u2.argc
+
+#define nd_tag   u1.id
+#define nd_tval  u2.value
+
+#define NEW_NODE(t,a0,a1,a2) rb_node_newnode((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))
+
+#define NEW_METHOD(n,x) NEW_NODE(NODE_METHOD,x,n,0)
+#define NEW_FBODY(n,i,o) NEW_NODE(NODE_FBODY,n,i,o)
+#define NEW_DEFN(i,a,d,p) NEW_NODE(NODE_DEFN,p,i,NEW_RFUNC(a,d))
+#define NEW_DEFS(r,i,a,d) NEW_NODE(NODE_DEFS,r,i,NEW_RFUNC(a,d))
+#define NEW_CFUNC(f,c) NEW_NODE(NODE_CFUNC,f,c,0)
+#define NEW_IFUNC(f,c) NEW_NODE(NODE_IFUNC,f,c,0)
+#define NEW_RFUNC(b1,b2) NEW_SCOPE(block_append(b1,b2))
+#define NEW_SCOPE(b) NEW_NODE(NODE_SCOPE,local_tbl(),0,(b))
+#define NEW_BLOCK(a) NEW_NODE(NODE_BLOCK,a,0,0)
+#define NEW_IF(c,t,e) NEW_NODE(NODE_IF,c,t,e)
+#define NEW_UNLESS(c,t,e) NEW_IF(c,e,t)
+#define NEW_CASE(h,b) NEW_NODE(NODE_CASE,h,b,0)
+#define NEW_WHEN(c,t,e) NEW_NODE(NODE_WHEN,c,t,e)
+#define NEW_OPT_N(b) NEW_NODE(NODE_OPT_N,0,b,0)
+#define NEW_WHILE(c,b,n) NEW_NODE(NODE_WHILE,c,b,n)
+#define NEW_UNTIL(c,b,n) NEW_NODE(NODE_UNTIL,c,b,n)
+#define NEW_FOR(v,i,b) NEW_NODE(NODE_FOR,v,b,i)
+#define NEW_ITER(v,i,b) NEW_NODE(NODE_ITER,v,b,i)
+#define NEW_BREAK(s) NEW_NODE(NODE_BREAK,s,0,0)
+#define NEW_NEXT(s) NEW_NODE(NODE_NEXT,s,0,0)
+#define NEW_REDO() NEW_NODE(NODE_REDO,0,0,0)
+#define NEW_RETRY() NEW_NODE(NODE_RETRY,0,0,0)
+#define NEW_BEGIN(b) NEW_NODE(NODE_BEGIN,0,b,0)
+#define NEW_RESCUE(b,res,e) NEW_NODE(NODE_RESCUE,b,res,e)
+#define NEW_RESBODY(a,ex,n) NEW_NODE(NODE_RESBODY,n,ex,a)
+#define NEW_ENSURE(b,en) NEW_NODE(NODE_ENSURE,b,0,en)
+#define NEW_RETURN(s) NEW_NODE(NODE_RETURN,s,0,0)
+#define NEW_YIELD(a,s) NEW_NODE(NODE_YIELD,a,0,s)
+#define NEW_LIST(a)  NEW_ARRAY(a)
+#define NEW_ARRAY(a) NEW_NODE(NODE_ARRAY,a,1,0)
+#define NEW_ZARRAY() NEW_NODE(NODE_ZARRAY,0,0,0)
+#define NEW_HASH(a)  NEW_NODE(NODE_HASH,a,0,0)
+#define NEW_NOT(a)   NEW_NODE(NODE_NOT,0,a,0)
+#define NEW_MASGN(l,r)   NEW_NODE(NODE_MASGN,l,0,r)
+#define NEW_GASGN(v,val) NEW_NODE(NODE_GASGN,v,val,rb_global_entry(v))
+#define NEW_LASGN(v,val) NEW_NODE(NODE_LASGN,v,val,local_cnt(v))
+#define NEW_DASGN(v,val) NEW_NODE(NODE_DASGN,v,val,0)
+#define NEW_DASGN_CURR(v,val) NEW_NODE(NODE_DASGN_CURR,v,val,0)
+#define NEW_IASGN(v,val) NEW_NODE(NODE_IASGN,v,val,0)
+#define NEW_CDECL(v,val,path) NEW_NODE(NODE_CDECL,v,val,path)
+#define NEW_CVASGN(v,val) NEW_NODE(NODE_CVASGN,v,val,0)
+#define NEW_CVDECL(v,val) NEW_NODE(NODE_CVDECL,v,val,0)
+#define NEW_OP_ASGN1(p,id,a) NEW_NODE(NODE_OP_ASGN1,p,id,a)
+#define NEW_OP_ASGN2(r,i,o,val) NEW_NODE(NODE_OP_ASGN2,r,val,NEW_OP_ASGN22(i,o))
+#define NEW_OP_ASGN22(i,o) NEW_NODE(NODE_OP_ASGN2,i,o,rb_id_attrset(i))
+#define NEW_OP_ASGN_OR(i,val) NEW_NODE(NODE_OP_ASGN_OR,i,val,0)
+#define NEW_OP_ASGN_AND(i,val) NEW_NODE(NODE_OP_ASGN_AND,i,val,0)
+#define NEW_GVAR(v) NEW_NODE(NODE_GVAR,v,0,rb_global_entry(v))
+#define NEW_LVAR(v) NEW_NODE(NODE_LVAR,v,0,local_cnt(v))
+#define NEW_DVAR(v) NEW_NODE(NODE_DVAR,v,0,0)
+#define NEW_IVAR(v) NEW_NODE(NODE_IVAR,v,0,0)
+#define NEW_CONST(v) NEW_NODE(NODE_CONST,v,0,0)
+#define NEW_CVAR(v) NEW_NODE(NODE_CVAR,v,0,0)
+#define NEW_NTH_REF(n)  NEW_NODE(NODE_NTH_REF,0,n,local_cnt('~'))
+#define NEW_BACK_REF(n) NEW_NODE(NODE_BACK_REF,0,n,local_cnt('~'))
+#define NEW_MATCH(c) NEW_NODE(NODE_MATCH,c,0,0)
+#define NEW_MATCH2(n1,n2) NEW_NODE(NODE_MATCH2,n1,n2,0)
+#define NEW_MATCH3(r,n2) NEW_NODE(NODE_MATCH3,r,n2,0)
+#define NEW_LIT(l) NEW_NODE(NODE_LIT,l,0,0)
+#define NEW_STR(s) NEW_NODE(NODE_STR,s,0,0)
+#define NEW_DSTR(s) NEW_NODE(NODE_DSTR,s,1,0)
+#define NEW_XSTR(s) NEW_NODE(NODE_XSTR,s,0,0)
+#define NEW_DXSTR(s) NEW_NODE(NODE_DXSTR,s,0,0)
+#define NEW_DSYM(s) NEW_NODE(NODE_DSYM,s,0,0)
+#define NEW_EVSTR(n) NEW_NODE(NODE_EVSTR,0,(n),0)
+#define NEW_CALL(r,m,a) NEW_NODE(NODE_CALL,r,m,a)
+#define NEW_FCALL(m,a) NEW_NODE(NODE_FCALL,0,m,a)
+#define NEW_VCALL(m) NEW_NODE(NODE_VCALL,0,m,0)
+#define NEW_SUPER(a) NEW_NODE(NODE_SUPER,0,0,a)
+#define NEW_ZSUPER() NEW_NODE(NODE_ZSUPER,0,0,0)
+#define NEW_ARGS(f,o,r) NEW_NODE(NODE_ARGS,o,r,f)
+#define NEW_ARGSCAT(a,b) NEW_NODE(NODE_ARGSCAT,a,b,0)
+#define NEW_ARGSPUSH(a,b) NEW_NODE(NODE_ARGSPUSH,a,b,0)
+#define NEW_SPLAT(a) NEW_NODE(NODE_SPLAT,a,0,0)
+#define NEW_TO_ARY(a) NEW_NODE(NODE_TO_ARY,a,0,0)
+#define NEW_SVALUE(a) NEW_NODE(NODE_SVALUE,a,0,0)
+#define NEW_BLOCK_ARG(v) NEW_NODE(NODE_BLOCK_ARG,v,0,local_cnt(v))
+#define NEW_BLOCK_PASS(b) NEW_NODE(NODE_BLOCK_PASS,0,b,0)
+#define NEW_ALIAS(n,o) NEW_NODE(NODE_ALIAS,n,o,0)
+#define NEW_VALIAS(n,o) NEW_NODE(NODE_VALIAS,n,o,0)
+#define NEW_UNDEF(i) NEW_NODE(NODE_UNDEF,0,i,0)
+#define NEW_CLASS(n,b,s) NEW_NODE(NODE_CLASS,n,NEW_SCOPE(b),(s))
+#define NEW_SCLASS(r,b) NEW_NODE(NODE_SCLASS,r,NEW_SCOPE(b),0)
+#define NEW_MODULE(n,b) NEW_NODE(NODE_MODULE,n,NEW_SCOPE(b),0)
+#define NEW_COLON2(c,i) NEW_NODE(NODE_COLON2,c,i,0)
+#define NEW_COLON3(i) NEW_NODE(NODE_COLON3,0,i,0)
+#define NEW_CREF(c) (NEW_NODE(NODE_CREF,0,0,c))
+#define NEW_DOT2(b,e) NEW_NODE(NODE_DOT2,b,e,0)
+#define NEW_DOT3(b,e) NEW_NODE(NODE_DOT3,b,e,0)
+#define NEW_ATTRSET(a) NEW_NODE(NODE_ATTRSET,a,0,0)
+#define NEW_SELF() NEW_NODE(NODE_SELF,0,0,0)
+#define NEW_NIL() NEW_NODE(NODE_NIL,0,0,0)
+#define NEW_TRUE() NEW_NODE(NODE_TRUE,0,0,0)
+#define NEW_FALSE() NEW_NODE(NODE_FALSE,0,0,0)
+#define NEW_DEFINED(e) NEW_NODE(NODE_DEFINED,e,0,0)
+#define NEW_NEWLINE(n) NEW_NODE(NODE_NEWLINE,0,0,n)
+#define NEW_PREEXE(b) NEW_SCOPE(b)
+#define NEW_POSTEXE() NEW_NODE(NODE_POSTEXE,0,0,0)
+#define NEW_DMETHOD(b) NEW_NODE(NODE_DMETHOD,0,0,b)
+#define NEW_BMETHOD(b) NEW_NODE(NODE_BMETHOD,0,0,b)
+#define NEW_ATTRASGN(r,m,a) NEW_NODE(NODE_ATTRASGN,r,m,a)
+
+#define NOEX_PUBLIC    0
+#define NOEX_NOSUPER   1
+#define NOEX_PRIVATE   2
+#define NOEX_PROTECTED 4 
+#define NOEX_MASK      6 
+
+#define NOEX_UNDEF     NOEX_NOSUPER
+
+NODE *rb_compile_cstr _((const char*, const char*, int, int));
+NODE *rb_compile_string _((const char*, VALUE, int));
+NODE *rb_compile_file _((const char*, VALUE, int));
+
+void rb_add_method _((VALUE, ID, NODE *, int));
+NODE *rb_node_newnode _((enum node_type,VALUE,VALUE,VALUE));
+
+NODE* rb_method_node _((VALUE klass, ID id));
+
+struct global_entry *rb_global_entry _((ID));
+VALUE rb_gvar_get _((struct global_entry *));
+VALUE rb_gvar_set _((struct global_entry *, VALUE));
+VALUE rb_gvar_defined _((struct global_entry *));
+
+typedef unsigned int rb_event_t;
+
+#define RUBY_EVENT_NONE     0x00
+#define RUBY_EVENT_LINE     0x01
+#define RUBY_EVENT_CLASS    0x02
+#define RUBY_EVENT_END      0x04
+#define RUBY_EVENT_CALL     0x08
+#define RUBY_EVENT_RETURN   0x10
+#define RUBY_EVENT_C_CALL   0x20
+#define RUBY_EVENT_C_RETURN 0x40
+#define RUBY_EVENT_RAISE    0x80
+#define RUBY_EVENT_ALL      0xff
+
+typedef void (*rb_event_hook_func_t) _((rb_event_t,NODE*,VALUE,ID,VALUE));
+void rb_add_event_hook _((rb_event_hook_func_t,rb_event_t));
+int rb_remove_event_hook _((rb_event_hook_func_t));
+
+#if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)
+#include <ucontext.h>
+#define USE_CONTEXT
+#endif
+#include <setjmp.h>
+#include "st.h"
+
+#ifdef USE_CONTEXT
+typedef struct {
+    ucontext_t context;
+    volatile int status;
+} rb_jmpbuf_t[1];
+#else
+typedef jmp_buf rb_jmpbuf_t;
+#endif
+
+enum thread_status {
+    THREAD_TO_KILL,
+    THREAD_RUNNABLE,
+    THREAD_STOPPED,
+    THREAD_KILLED,
+};
+
+typedef struct thread * rb_thread_t;
+
+struct thread {
+    struct thread *next, *prev;
+    rb_jmpbuf_t context;
+#if (defined _WIN32 && !defined _WIN32_WCE) || defined __CYGWIN__
+    unsigned long win32_exception_list;
+#endif
+
+    VALUE result;
+
+    long   stk_len;
+    long   stk_max;
+    VALUE *stk_ptr;
+    VALUE *stk_pos;
+#ifdef __ia64
+    long   bstr_len;
+    long   bstr_max;
+    VALUE *bstr_ptr;
+    VALUE *bstr_pos;
+#endif
+
+    struct FRAME *frame;
+    struct SCOPE *scope;
+    struct RVarmap *dyna_vars;
+    struct BLOCK *block;
+    struct iter *iter;
+    struct tag *tag;
+    VALUE klass;
+    VALUE wrapper;
+    NODE *cref;
+
+    int flags;		/* misc. states (vmode/rb_trap_immediate/raised) */
+
+    NODE *node;
+
+    int tracing;
+    VALUE errinfo;
+    VALUE last_status;
+    VALUE last_line;
+    VALUE last_match;
+
+    int safe;
+
+    enum thread_status status;
+    int wait_for;
+    int fd;
+    fd_set readfds;
+    fd_set writefds;
+    fd_set exceptfds;
+    int select_value;
+    double delay;
+    rb_thread_t join;
+
+    int abort;
+    int priority;
+    VALUE thgroup;
+
+    st_table *locals;
+
+    VALUE thread;
+
+    VALUE sandbox;
+};
+
+extern VALUE (*ruby_sandbox_save)(struct thread *); 
+extern VALUE (*ruby_sandbox_restore)(struct thread *); 
+extern rb_thread_t curr_thread;
+extern rb_thread_t main_thread;
+
+#if defined(__cplusplus)
+}  /* extern "C" { */
+#endif
+
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/rbconfig.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/rbconfig.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/rbconfig.rb	(revision 18425)
@@ -0,0 +1,178 @@
+
+# This file was created by mkconfig.rb when ruby was built.  Any
+# changes made to this file will be lost the next time ruby is built.
+
+module Config
+  RUBY_VERSION == "1.8.6" or
+    raise "ruby lib version (1.8.6) doesn't match executable version (#{RUBY_VERSION})"
+
+  TOPDIR = File.dirname(__FILE__).chomp!("/lib/ruby/1.8/i686-linux")
+  DESTDIR = '' unless defined? DESTDIR
+  CONFIG = {}
+  CONFIG["DESTDIR"] = DESTDIR
+  CONFIG["INSTALL"] = '/usr/bin/install -c'
+  CONFIG["prefix"] = (TOPDIR || DESTDIR + "/research/code/gsdl-video-import/trunk/installed/cmdline")
+  CONFIG["EXEEXT"] = ""
+  CONFIG["ruby_install_name"] = "ruby"
+  CONFIG["RUBY_INSTALL_NAME"] = "ruby"
+  CONFIG["RUBY_SO_NAME"] = "ruby"
+  CONFIG["SHELL"] = "/bin/sh"
+  CONFIG["PATH_SEPARATOR"] = ":"
+  CONFIG["PACKAGE_NAME"] = ""
+  CONFIG["PACKAGE_TARNAME"] = ""
+  CONFIG["PACKAGE_VERSION"] = ""
+  CONFIG["PACKAGE_STRING"] = ""
+  CONFIG["PACKAGE_BUGREPORT"] = ""
+  CONFIG["exec_prefix"] = "$(prefix)"
+  CONFIG["bindir"] = "$(exec_prefix)/bin"
+  CONFIG["sbindir"] = "$(exec_prefix)/sbin"
+  CONFIG["libexecdir"] = "$(exec_prefix)/libexec"
+  CONFIG["datarootdir"] = "$(prefix)/share"
+  CONFIG["datadir"] = "$(datarootdir)"
+  CONFIG["sysconfdir"] = "$(prefix)/etc"
+  CONFIG["sharedstatedir"] = "$(prefix)/com"
+  CONFIG["localstatedir"] = "$(prefix)/var"
+  CONFIG["includedir"] = "$(prefix)/include"
+  CONFIG["oldincludedir"] = "/usr/include"
+  CONFIG["docdir"] = "$(datarootdir)/doc/$(PACKAGE)"
+  CONFIG["infodir"] = "$(datarootdir)/info"
+  CONFIG["htmldir"] = "$(docdir)"
+  CONFIG["dvidir"] = "$(docdir)"
+  CONFIG["pdfdir"] = "$(docdir)"
+  CONFIG["psdir"] = "$(docdir)"
+  CONFIG["libdir"] = "$(exec_prefix)/lib"
+  CONFIG["localedir"] = "$(datarootdir)/locale"
+  CONFIG["mandir"] = "$(datarootdir)/man"
+  CONFIG["ECHO_C"] = ""
+  CONFIG["ECHO_N"] = "-n"
+  CONFIG["ECHO_T"] = ""
+  CONFIG["LIBS"] = "-ldl -lcrypt -lm "
+  CONFIG["build_alias"] = ""
+  CONFIG["host_alias"] = ""
+  CONFIG["target_alias"] = ""
+  CONFIG["MAJOR"] = "1"
+  CONFIG["MINOR"] = "8"
+  CONFIG["TEENY"] = "6"
+  CONFIG["build"] = "i686-pc-linux-gnu"
+  CONFIG["build_cpu"] = "i686"
+  CONFIG["build_vendor"] = "pc"
+  CONFIG["build_os"] = "linux-gnu"
+  CONFIG["host"] = "i686-pc-linux-gnu"
+  CONFIG["host_cpu"] = "i686"
+  CONFIG["host_vendor"] = "pc"
+  CONFIG["host_os"] = "linux-gnu"
+  CONFIG["target"] = "i686-pc-linux-gnu"
+  CONFIG["target_cpu"] = "i686"
+  CONFIG["target_vendor"] = "pc"
+  CONFIG["target_os"] = "linux"
+  CONFIG["CC"] = "gcc"
+  CONFIG["CFLAGS"] = "-g -O2"
+  CONFIG["LDFLAGS"] = " -rdynamic -Wl,-export-dynamic"
+  CONFIG["CPPFLAGS"] = ""
+  CONFIG["OBJEXT"] = "o"
+  CONFIG["CPP"] = "gcc -E"
+  CONFIG["GREP"] = "/bin/grep"
+  CONFIG["EGREP"] = "/bin/grep -E"
+  CONFIG["GNU_LD"] = "yes"
+  CONFIG["CPPOUTFILE"] = "-o conftest.i"
+  CONFIG["OUTFLAG"] = "-o "
+  CONFIG["YACC"] = "bison -y"
+  CONFIG["YFLAGS"] = ""
+  CONFIG["RANLIB"] = "ranlib"
+  CONFIG["AR"] = "ar"
+  CONFIG["AS"] = "as"
+  CONFIG["ASFLAGS"] = ""
+  CONFIG["NM"] = ""
+  CONFIG["WINDRES"] = ""
+  CONFIG["DLLWRAP"] = ""
+  CONFIG["OBJDUMP"] = ""
+  CONFIG["LN_S"] = "ln -s"
+  CONFIG["SET_MAKE"] = ""
+  CONFIG["INSTALL_PROGRAM"] = "$(INSTALL)"
+  CONFIG["INSTALL_SCRIPT"] = "$(INSTALL)"
+  CONFIG["INSTALL_DATA"] = "$(INSTALL) -m 644"
+  CONFIG["RM"] = "rm -f"
+  CONFIG["CP"] = "cp"
+  CONFIG["MAKEDIRS"] = "mkdir -p"
+  CONFIG["ALLOCA"] = ""
+  CONFIG["DLDFLAGS"] = ""
+  CONFIG["ARCH_FLAG"] = ""
+  CONFIG["STATIC"] = ""
+  CONFIG["CCDLFLAGS"] = " -fPIC"
+  CONFIG["LDSHARED"] = "$(CC) -shared"
+  CONFIG["DLEXT"] = "so"
+  CONFIG["DLEXT2"] = ""
+  CONFIG["LIBEXT"] = "a"
+  CONFIG["LINK_SO"] = ""
+  CONFIG["LIBPATHFLAG"] = " -L'%1$-s'"
+  CONFIG["RPATHFLAG"] = " -Wl,-R'%1$-s'"
+  CONFIG["LIBPATHENV"] = "LD_LIBRARY_PATH"
+  CONFIG["TRY_LINK"] = ""
+  CONFIG["STRIP"] = "strip -S -x"
+  CONFIG["EXTSTATIC"] = ""
+  CONFIG["setup"] = "Setup"
+  CONFIG["MINIRUBY"] = "./miniruby$(EXEEXT)"
+  CONFIG["PREP"] = "miniruby$(EXEEXT)"
+  CONFIG["RUNRUBY"] = "$(MINIRUBY) $(srcdir)/runruby.rb --extout=$(EXTOUT) --"
+  CONFIG["EXTOUT"] = ".ext"
+  CONFIG["ARCHFILE"] = ""
+  CONFIG["RDOCTARGET"] = ""
+  CONFIG["XCFLAGS"] = " -DRUBY_EXPORT"
+  CONFIG["XLDFLAGS"] = " -L."
+  CONFIG["LIBRUBY_LDSHARED"] = "$(CC) -shared"
+  CONFIG["LIBRUBY_DLDFLAGS"] = ""
+  CONFIG["rubyw_install_name"] = ""
+  CONFIG["RUBYW_INSTALL_NAME"] = ""
+  CONFIG["LIBRUBY_A"] = "lib$(RUBY_SO_NAME)-static.a"
+  CONFIG["LIBRUBY_SO"] = "lib$(RUBY_SO_NAME).so.$(MAJOR).$(MINOR).$(TEENY)"
+  CONFIG["LIBRUBY_ALIASES"] = "lib$(RUBY_SO_NAME).so"
+  CONFIG["LIBRUBY"] = "$(LIBRUBY_A)"
+  CONFIG["LIBRUBYARG"] = "$(LIBRUBYARG_STATIC)"
+  CONFIG["LIBRUBYARG_STATIC"] = "-l$(RUBY_SO_NAME)-static"
+  CONFIG["LIBRUBYARG_SHARED"] = "-Wl,-R -Wl,$(libdir) -L$(libdir) -L. "
+  CONFIG["SOLIBS"] = ""
+  CONFIG["DLDLIBS"] = " -lc"
+  CONFIG["ENABLE_SHARED"] = "no"
+  CONFIG["MAINLIBS"] = ""
+  CONFIG["COMMON_LIBS"] = ""
+  CONFIG["COMMON_MACROS"] = ""
+  CONFIG["COMMON_HEADERS"] = ""
+  CONFIG["EXPORT_PREFIX"] = ""
+  CONFIG["MAKEFILES"] = "Makefile"
+  CONFIG["arch"] = "i686-linux"
+  CONFIG["sitearch"] = "i686-linux"
+  CONFIG["sitedir"] = "$(prefix)/lib/ruby/site_ruby"
+  CONFIG["configure_args"] = " '--prefix=/research/code/gsdl-video-import/trunk/installed/cmdline'"
+  CONFIG["NROFF"] = "/usr/bin/nroff"
+  CONFIG["MANTYPE"] = "doc"
+  CONFIG["ruby_version"] = "$(MAJOR).$(MINOR)"
+  CONFIG["rubylibdir"] = "$(libdir)/ruby/$(ruby_version)"
+  CONFIG["archdir"] = "$(rubylibdir)/$(arch)"
+  CONFIG["sitelibdir"] = "$(sitedir)/$(ruby_version)"
+  CONFIG["sitearchdir"] = "$(sitelibdir)/$(sitearch)"
+  CONFIG["topdir"] = File.dirname(__FILE__)
+  MAKEFILE_CONFIG = {}
+  CONFIG.each{|k,v| MAKEFILE_CONFIG[k] = v.dup}
+  def Config::expand(val, config = CONFIG)
+    val.gsub!(/\$\$|\$\(([^()]+)\)|\$\{([^{}]+)\}/) do |var|
+      if !(v = $1 || $2)
+	'$'
+      elsif key = config[v = v[/\A[^:]+(?=(?::(.*?)=(.*))?\z)/]]
+	pat, sub = $1, $2
+	config[v] = false
+	Config::expand(key, config)
+	config[v] = key
+	key = key.gsub(/#{Regexp.quote(pat)}(?=\s|\z)/n) {sub} if pat
+	key
+      else
+	var
+      end
+    end
+    val
+  end
+  CONFIG.each_value do |val|
+    Config::expand(val)
+  end
+end
+RbConfig = Config # compatibility for ruby-1.9
+CROSS_COMPILING = nil unless defined? CROSS_COMPILING
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/re.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/re.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/re.h	(revision 18425)
@@ -0,0 +1,42 @@
+/**********************************************************************
+
+  re.h -
+
+  $Author: shyouhei $
+  $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+  created at: Thu Sep 30 14:18:32 JST 1993
+
+  Copyright (C) 1993-2003 Yukihiro Matsumoto
+
+**********************************************************************/
+
+#ifndef RE_H
+#define RE_H
+
+#include <sys/types.h>
+#include <stdio.h>
+
+#include "regex.h"
+
+typedef struct re_pattern_buffer Regexp;
+
+struct RMatch {
+    struct RBasic basic;
+    VALUE str;
+    struct re_registers *regs;
+};
+
+#define RMATCH(obj)  (R_CAST(RMatch)(obj))
+
+VALUE rb_reg_regcomp _((VALUE));
+long rb_reg_search _((VALUE, VALUE, long, long));
+VALUE rb_reg_regsub _((VALUE, VALUE, struct re_registers *));
+long rb_reg_adjust_startpos _((VALUE, VALUE, long, long));
+void rb_match_busy _((VALUE));
+VALUE rb_reg_quote _((VALUE));
+
+RUBY_EXTERN int ruby_ignorecase;
+
+int rb_reg_mbclen2 _((unsigned int, VALUE));
+#define mbclen2(c,re) rb_reg_mbclen2((c),(re))
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/regex.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/regex.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/regex.h	(revision 18425)
@@ -0,0 +1,221 @@
+/* Definitions for data structures and routines for the regular
+   expression library, version 0.12.
+   Copyright (C) 1985,89,90,91,92,93,95,96,97,98 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 LGPL.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+/* Multi-byte extension added May, 1993 by t^2 (Takahiro Tanimoto)
+   Last change: May 21, 1993 by t^2  */
+/* modified for Ruby by matz@netlab.co.jp */
+
+#ifndef REGEX_H
+#define REGEX_H
+
+/* symbol mangling for ruby */
+#ifdef RUBY
+# define re_adjust_startpos ruby_re_adjust_startpos
+# define re_compile_fastmap ruby_re_compile_fastmap
+# define re_compile_pattern ruby_re_compile_pattern
+# define re_copy_registers ruby_re_copy_registers
+# define re_free_pattern ruby_re_free_pattern
+# define re_free_registers ruby_re_free_registers
+# define re_match ruby_re_match
+# define re_mbcinit ruby_re_mbcinit
+# define re_search ruby_re_search
+# define re_set_casetable ruby_re_set_casetable
+# define register_info_type ruby_register_info_type
+#endif
+
+#include <stddef.h>
+
+/* Define number of parens for which we record the beginnings and ends.
+   This affects how much space the `struct re_registers' type takes up.  */
+#ifndef RE_NREGS
+#define RE_NREGS 10
+#endif
+
+#define BYTEWIDTH 8
+
+#define RE_REG_MAX ((1<<BYTEWIDTH)-1)
+
+/* Maximum number of duplicates an interval can allow.  */
+#ifndef RE_DUP_MAX
+#define RE_DUP_MAX  ((1 << 15) - 1) 
+#endif
+
+
+/* If this bit is set, then character classes are supported; they are:
+     [:alpha:],	[:upper:], [:lower:],  [:digit:], [:alnum:], [:xdigit:],
+     [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
+   If not set, then character classes are not supported.  */
+#define RE_CHAR_CLASSES (1L << 9)
+
+/* match will be done case insensetively */
+#define RE_OPTION_IGNORECASE (1L)
+/* perl-style extended pattern available */
+#define RE_OPTION_EXTENDED   (RE_OPTION_IGNORECASE<<1)
+/* newline will be included for . */
+#define RE_OPTION_MULTILINE  (RE_OPTION_EXTENDED<<1)
+/* ^ and $ ignore newline */
+#define RE_OPTION_SINGLELINE (RE_OPTION_MULTILINE<<1)
+/* search for longest match, in accord with POSIX regexp */
+#define RE_OPTION_LONGEST    (RE_OPTION_SINGLELINE<<1)
+
+#define RE_MAY_IGNORECASE    (RE_OPTION_LONGEST<<1)
+#define RE_OPTIMIZE_ANCHOR   (RE_MAY_IGNORECASE<<1)
+#define RE_OPTIMIZE_EXACTN   (RE_OPTIMIZE_ANCHOR<<1)
+#define RE_OPTIMIZE_NO_BM    (RE_OPTIMIZE_EXACTN<<1)
+#define RE_OPTIMIZE_BMATCH   (RE_OPTIMIZE_NO_BM<<1)
+
+/* For multi-byte char support */
+#define MBCTYPE_ASCII 0
+#define MBCTYPE_EUC 1
+#define MBCTYPE_SJIS 2
+#define MBCTYPE_UTF8 3
+
+extern
+#if defined _WIN32 && !defined __GNUC__ && !defined RUBY_EXPORT
+__declspec(dllimport)
+# endif
+const unsigned char *re_mbctab;
+#if defined(__STDC__)
+void re_mbcinit (int);
+#else
+void re_mbcinit ();
+#endif
+
+#undef ismbchar
+#define ismbchar(c) re_mbctab[(unsigned char)(c)]
+#define mbclen(c)   (re_mbctab[(unsigned char)(c)]+1)
+
+/* Structure used in re_match() */
+
+typedef union
+{
+  unsigned char *word;
+  struct {
+    unsigned is_active : 1;
+    unsigned matched_something : 1;
+  } bits;
+} register_info_type;
+
+/* This data structure is used to represent a compiled pattern.  */
+
+struct re_pattern_buffer
+  {
+    char *buffer;	/* Space holding the compiled pattern commands.  */
+    int allocated;	/* Size of space that `buffer' points to. */
+    int used;		/* Length of portion of buffer actually occupied  */
+    char *fastmap;	/* Pointer to fastmap, if any, or zero if none.  */
+			/* re_search uses the fastmap, if there is one,
+			   to skip over totally implausible characters.  */
+    char *must;	        /* Pointer to exact pattern which strings should have
+			   to be matched.  */
+    int *must_skip;     /* Pointer to exact pattern skip table for bm_search */
+    long options;	/* Flags for options such as extended_pattern. */
+    long re_nsub;	/* Number of subexpressions found by the compiler. */
+    char fastmap_accurate;
+			/* Set to zero when a new pattern is stored,
+			   set to one when the fastmap is updated from it.  */
+    char can_be_null;   /* Set to one by compiling fastmap
+			   if this pattern might match the null string.
+			   It does not necessarily match the null string
+			   in that case, but if this is zero, it cannot.
+			   2 as value means can match null string
+			   but at end of range or before a character
+			   listed in the fastmap.  */
+
+    /* stack & working area for re_match() */
+    unsigned char **regstart;
+    unsigned char **regend;
+    unsigned char **old_regstart;
+    unsigned char **old_regend;
+    register_info_type *reg_info;
+    unsigned char **best_regstart;
+    unsigned char **best_regend;
+  };
+
+typedef struct re_pattern_buffer regex_t;
+
+/* Structure to store register contents data in.
+
+   Pass the address of such a structure as an argument to re_match, etc.,
+   if you want this information back.
+
+   For i from 1 to RE_NREGS - 1, start[i] records the starting index in
+   the string of where the ith subexpression matched, and end[i] records
+   one after the ending index.  start[0] and end[0] are analogous, for
+   the entire pattern.  */
+
+struct re_registers
+  {
+    int allocated;
+    int num_regs;
+    int *beg;
+    int *end;
+  };
+
+/* Type for byte offsets within the string.  POSIX mandates this.  */
+typedef size_t regoff_t;
+
+/* POSIX specification for registers.  Aside from the different names than
+   `re_registers', POSIX uses an array of structures, instead of a
+   structure of arrays.  */
+typedef struct
+{
+  regoff_t rm_so;  /* Byte offset from string's start to substring's start.  */
+  regoff_t rm_eo;  /* Byte offset from string's start to substring's end.  */
+} regmatch_t;
+
+#ifdef __STDC__
+
+extern char *re_compile_pattern (const char *, int, struct re_pattern_buffer *);
+void re_free_pattern (struct re_pattern_buffer *);
+/* Is this really advertised?  */
+extern int re_adjust_startpos (struct re_pattern_buffer *, const char*, int, int, int);
+extern void re_compile_fastmap (struct re_pattern_buffer *);
+extern int re_search (struct re_pattern_buffer *, const char*, int, int, int,
+		      struct re_registers *);
+extern int re_match (struct re_pattern_buffer *, const char *, int, int,
+		     struct re_registers *);
+extern void re_set_casetable (const char *table);
+extern void re_copy_registers (struct re_registers*, struct re_registers*);
+extern void re_free_registers (struct re_registers*);
+
+#ifndef RUBY
+/* 4.2 bsd compatibility.  */
+extern char *re_comp (const char *);
+extern int re_exec (const char *);
+#endif
+
+#else /* !__STDC__ */
+
+extern char *re_compile_pattern ();
+void re_free_regexp ();
+/* Is this really advertised? */
+extern int re_adjust_startpos ();
+extern void re_compile_fastmap ();
+extern int re_search ();
+extern int re_match ();
+extern void re_set_casetable ();
+extern void re_copy_registers ();
+extern void re_free_registers ();
+
+#endif /* __STDC__ */
+
+#endif /* !REGEX_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/ruby.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/ruby.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/ruby.h	(revision 18425)
@@ -0,0 +1,759 @@
+/**********************************************************************
+
+  ruby.h -
+
+  $Author: knu $
+  created at: Thu Jun 10 14:26:32 JST 1993
+
+  Copyright (C) 1993-2003 Yukihiro Matsumoto
+  Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
+  Copyright (C) 2000  Information-technology Promotion Agency, Japan
+
+**********************************************************************/
+
+#ifndef RUBY_H
+#define RUBY_H
+
+#if defined(__cplusplus)
+extern "C" {
+#if 0
+} /* satisfy cc-mode */
+#endif
+#endif
+
+#include "config.h"
+#ifdef RUBY_EXTCONF_H
+#include RUBY_EXTCONF_H
+#endif
+
+#define NORETURN_STYLE_NEW 1
+#ifndef NORETURN
+# define NORETURN(x) x
+#endif
+#ifndef NOINLINE
+# define NOINLINE(x) x
+#endif
+
+#include "defines.h"
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#ifdef HAVE_INTRINSICS_H
+# include <intrinsics.h>
+#endif
+
+#include <stddef.h>
+#include <stdio.h>
+
+/* need to include <ctype.h> to use these macros */
+#ifndef ISPRINT
+#define ISASCII(c) isascii((int)(unsigned char)(c))
+#undef ISPRINT
+#define ISPRINT(c) (ISASCII(c) && isprint((int)(unsigned char)(c)))
+#define ISSPACE(c) (ISASCII(c) && isspace((int)(unsigned char)(c)))
+#define ISUPPER(c) (ISASCII(c) && isupper((int)(unsigned char)(c)))
+#define ISLOWER(c) (ISASCII(c) && islower((int)(unsigned char)(c)))
+#define ISALNUM(c) (ISASCII(c) && isalnum((int)(unsigned char)(c)))
+#define ISALPHA(c) (ISASCII(c) && isalpha((int)(unsigned char)(c)))
+#define ISDIGIT(c) (ISASCII(c) && isdigit((int)(unsigned char)(c)))
+#define ISXDIGIT(c) (ISASCII(c) && isxdigit((int)(unsigned char)(c)))
+#endif
+
+#if defined(HAVE_ALLOCA_H)
+#include <alloca.h>
+#else
+#  ifdef _AIX
+#pragma alloca
+#  endif
+#endif
+
+#if defined(__VMS)
+# pragma builtins
+# define alloca __alloca
+#endif
+
+#if SIZEOF_LONG != SIZEOF_VOIDP
+# error ---->> ruby requires sizeof(void*) == sizeof(long) to be compiled. <<----
+#else
+typedef unsigned long VALUE;
+typedef unsigned long ID;
+#endif
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# ifndef LONG_MAX
+#  ifdef HAVE_LIMITS_H
+#   include <limits.h>
+#  else
+    /* assuming 32bit(2's compliment) long */
+#   define LONG_MAX 2147483647
+#  endif
+# endif
+# ifndef LONG_MIN
+#  define LONG_MIN (-LONG_MAX-1)
+# endif
+# ifndef CHAR_BIT
+#  define CHAR_BIT 8
+# endif
+#endif
+
+#ifdef HAVE_LONG_LONG
+# ifndef LLONG_MAX
+#  ifdef LONG_LONG_MAX
+#   define LLONG_MAX  LONG_LONG_MAX
+#  else
+#   ifdef _I64_MAX
+#    define LLONG_MAX _I64_MAX
+#   else
+    /* assuming 64bit(2's complement) long long */
+#    define LLONG_MAX 9223372036854775807LL
+#   endif
+#  endif
+# endif
+# ifndef LLONG_MIN
+#  ifdef LONG_LONG_MIN
+#   define LLONG_MIN  LONG_LONG_MIN
+#  else
+#   ifdef _I64_MIN
+#    define LLONG_MIN _I64_MIN
+#   else
+#    define LLONG_MIN (-LLONG_MAX-1)
+#   endif
+#  endif
+# endif
+#endif
+
+#define FIXNUM_MAX (LONG_MAX>>1)
+#define FIXNUM_MIN RSHIFT((long)LONG_MIN,1)
+
+#define FIXNUM_FLAG 0x01
+#define INT2FIX(i) ((VALUE)(((long)(i))<<1 | FIXNUM_FLAG))
+#define LONG2FIX(i) INT2FIX(i)
+#define rb_fix_new(v) INT2FIX(v)
+VALUE rb_int2inum _((long));
+#define INT2NUM(v) rb_int2inum(v)
+#define LONG2NUM(v) INT2NUM(v)
+#define rb_int_new(v) rb_int2inum(v)
+VALUE rb_uint2inum _((unsigned long));
+#define UINT2NUM(v) rb_uint2inum(v)
+#define ULONG2NUM(v) UINT2NUM(v)
+#define rb_uint_new(v) rb_uint2inum(v)
+
+#ifdef HAVE_LONG_LONG
+VALUE rb_ll2inum _((LONG_LONG));
+#define LL2NUM(v) rb_ll2inum(v)
+VALUE rb_ull2inum _((unsigned LONG_LONG));
+#define ULL2NUM(v) rb_ull2inum(v)
+#endif
+
+#if SIZEOF_OFF_T > SIZEOF_LONG && defined(HAVE_LONG_LONG)
+# define OFFT2NUM(v) LL2NUM(v)
+#elif SIZEOF_OFF_T == SIZEOF_LONG
+# define OFFT2NUM(v) LONG2NUM(v)
+#else
+# define OFFT2NUM(v) INT2NUM(v)
+#endif
+
+#define FIX2LONG(x) RSHIFT((long)x,1)
+#define FIX2ULONG(x) (((unsigned long)(x))>>1)
+#define FIXNUM_P(f) (((long)(f))&FIXNUM_FLAG)
+#define POSFIXABLE(f) ((f) <= FIXNUM_MAX)
+#define NEGFIXABLE(f) ((f) >= FIXNUM_MIN)
+#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
+
+#define IMMEDIATE_MASK 0x03
+#define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK)
+
+#define SYMBOL_FLAG 0x0e
+#define SYMBOL_P(x) (((VALUE)(x)&0xff)==SYMBOL_FLAG)
+#define ID2SYM(x) ((VALUE)(((long)(x))<<8|SYMBOL_FLAG))
+#define SYM2ID(x) RSHIFT((unsigned long)x,8)
+
+/* special contants - i.e. non-zero and non-fixnum constants */
+#define Qfalse ((VALUE)0)
+#define Qtrue  ((VALUE)2)
+#define Qnil   ((VALUE)4)
+#define Qundef ((VALUE)6)	/* undefined value for placeholder */
+
+#define RTEST(v) (((VALUE)(v) & ~Qnil) != 0)
+#define NIL_P(v) ((VALUE)(v) == Qnil)
+
+#define CLASS_OF(v) rb_class_of((VALUE)(v))
+
+#define T_NONE   0x00
+
+#define T_NIL    0x01
+#define T_OBJECT 0x02
+#define T_CLASS  0x03
+#define T_ICLASS 0x04
+#define T_MODULE 0x05
+#define T_FLOAT  0x06
+#define T_STRING 0x07
+#define T_REGEXP 0x08
+#define T_ARRAY  0x09
+#define T_FIXNUM 0x0a
+#define T_HASH   0x0b
+#define T_STRUCT 0x0c
+#define T_BIGNUM 0x0d
+#define T_FILE   0x0e
+
+#define T_TRUE   0x20
+#define T_FALSE  0x21
+#define T_DATA   0x22
+#define T_MATCH  0x23
+#define T_SYMBOL 0x24
+
+#define T_BLKTAG 0x3b
+#define T_UNDEF  0x3c
+#define T_VARMAP 0x3d
+#define T_SCOPE  0x3e
+#define T_NODE   0x3f
+
+#define T_MASK   0x3f
+
+#define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK)
+
+#define TYPE(x) rb_type((VALUE)(x))
+
+void rb_check_type _((VALUE,int));
+#define Check_Type(v,t) rb_check_type((VALUE)(v),t)
+
+VALUE rb_str_to_str _((VALUE));
+VALUE rb_string_value _((volatile VALUE*));
+char *rb_string_value_ptr _((volatile VALUE*));
+char *rb_string_value_cstr _((volatile VALUE*));
+
+#define StringValue(v) rb_string_value(&(v))
+#define StringValuePtr(v) rb_string_value_ptr(&(v))
+#define StringValueCStr(v) rb_string_value_cstr(&(v))
+
+void rb_check_safe_obj _((VALUE));
+void rb_check_safe_str _((VALUE));
+#define SafeStringValue(v) do {\
+    StringValue(v);\
+    rb_check_safe_obj(v);\
+} while (0)
+/* obsolete macro - use SafeStringValue(v) */
+#define Check_SafeStr(v) rb_check_safe_str((VALUE)(v))
+
+void rb_secure _((int));
+RUBY_EXTERN int ruby_safe_level;
+#define rb_safe_level() (ruby_safe_level)
+void rb_set_safe_level _((int));
+void rb_secure_update _((VALUE));
+
+long rb_num2long _((VALUE));
+unsigned long rb_num2ulong _((VALUE));
+#define NUM2LONG(x) (FIXNUM_P(x)?FIX2LONG(x):rb_num2long((VALUE)x))
+#define NUM2ULONG(x) rb_num2ulong((VALUE)x)
+#if SIZEOF_INT < SIZEOF_LONG
+long rb_num2int _((VALUE));
+#define NUM2INT(x) (FIXNUM_P(x)?FIX2INT(x):rb_num2int((VALUE)x))
+long rb_fix2int _((VALUE));
+#define FIX2INT(x) rb_fix2int((VALUE)x)
+unsigned long rb_num2uint _((VALUE));
+#define NUM2UINT(x) rb_num2uint(x)
+unsigned long rb_fix2uint _((VALUE));
+#define FIX2UINT(x) rb_fix2uint(x)
+#else
+#define NUM2INT(x) ((int)NUM2LONG(x))
+#define NUM2UINT(x) ((unsigned int)NUM2ULONG(x))
+#define FIX2INT(x) ((int)FIX2LONG(x))
+#define FIX2UINT(x) ((unsigned int)FIX2ULONG(x))
+#endif
+
+#ifdef HAVE_LONG_LONG
+LONG_LONG rb_num2ll _((VALUE));
+unsigned LONG_LONG rb_num2ull _((VALUE));
+# define NUM2LL(x) (FIXNUM_P(x)?FIX2LONG(x):rb_num2ll((VALUE)x))
+# define NUM2ULL(x) rb_num2ull((VALUE)x)
+#endif
+
+#if defined(HAVE_LONG_LONG) && SIZEOF_OFF_T > SIZEOF_LONG
+# define NUM2OFFT(x) ((off_t)NUM2LL(x))
+#else
+# define NUM2OFFT(x) NUM2LONG(x)
+#endif
+
+double rb_num2dbl _((VALUE));
+#define NUM2DBL(x) rb_num2dbl((VALUE)(x))
+
+/* obsolete API - use StringValue() */
+char *rb_str2cstr _((VALUE,long*));
+/* obsolete API - use StringValuePtr() */
+#define STR2CSTR(x) rb_str2cstr((VALUE)(x),0)
+
+#define NUM2CHR(x) (((TYPE(x) == T_STRING)&&(RSTRING(x)->len>=1))?\
+                     RSTRING(x)->ptr[0]:(char)(NUM2INT(x)&0xff))
+#define CHR2FIX(x) INT2FIX((long)((x)&0xff))
+
+VALUE rb_newobj _((void));
+#define NEWOBJ(obj,type) type *obj = (type*)rb_newobj()
+#define OBJSETUP(obj,c,t) do {\
+    RBASIC(obj)->flags = (t);\
+    RBASIC(obj)->klass = (c);\
+    if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT);\
+} while (0)
+#define CLONESETUP(clone,obj) do {\
+    OBJSETUP(clone,rb_singleton_class_clone((VALUE)obj),RBASIC(obj)->flags);\
+    rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);\
+    if (FL_TEST(obj, FL_EXIVAR)) rb_copy_generic_ivar((VALUE)clone,(VALUE)obj);\
+} while (0)
+#define DUPSETUP(dup,obj) do {\
+    OBJSETUP(dup,rb_obj_class(obj),(RBASIC(obj)->flags)&(T_MASK|FL_EXIVAR|FL_TAINT));\
+    if (FL_TEST(obj, FL_EXIVAR)) rb_copy_generic_ivar((VALUE)dup,(VALUE)obj);\
+} while (0)
+
+struct RBasic {
+    unsigned long flags;
+    VALUE klass;
+};
+
+struct RObject {
+    struct RBasic basic;
+    struct st_table *iv_tbl;
+};
+
+struct RClass {
+    struct RBasic basic;
+    struct st_table *iv_tbl;
+    struct st_table *m_tbl;
+    VALUE super;
+};
+
+struct RFloat {
+    struct RBasic basic;
+    double value;
+};
+
+#define ELTS_SHARED FL_USER2
+
+struct RString {
+    struct RBasic basic;
+    long len;
+    char *ptr;
+    union {
+	long capa;
+	VALUE shared;
+    } aux;
+};
+#define RSTRING_PTR(s) (RSTRING(s)->ptr)
+#define RSTRING_LEN(s) (RSTRING(s)->len)
+
+struct RArray {
+    struct RBasic basic;
+    long len;
+    union {
+	long capa;
+	VALUE shared;
+    } aux;
+    VALUE *ptr;
+};
+#define RARRAY_PTR(s) (RARRAY(s)->ptr)
+#define RARRAY_LEN(s) (RARRAY(s)->len)
+
+struct RRegexp {
+    struct RBasic basic;
+    struct re_pattern_buffer *ptr;
+    long len;
+    char *str;
+};
+
+struct RHash {
+    struct RBasic basic;
+    struct st_table *tbl;
+    int iter_lev;
+    VALUE ifnone;
+};
+
+struct RFile {
+    struct RBasic basic;
+    struct OpenFile *fptr;
+};
+
+struct RData {
+    struct RBasic basic;
+    void (*dmark) _((void*));
+    void (*dfree) _((void*));
+    void *data;
+};
+
+#define DATA_PTR(dta) (RDATA(dta)->data)
+
+/*
+#define RUBY_DATA_FUNC(func) ((void (*)_((void*)))func)
+*/
+typedef void (*RUBY_DATA_FUNC) _((void*));
+
+VALUE rb_data_object_alloc _((VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC));
+
+#define Data_Wrap_Struct(klass,mark,free,sval)\
+    rb_data_object_alloc(klass,sval,(RUBY_DATA_FUNC)mark,(RUBY_DATA_FUNC)free)
+
+#define Data_Make_Struct(klass,type,mark,free,sval) (\
+    sval = ALLOC(type),\
+    memset(sval, 0, sizeof(type)),\
+    Data_Wrap_Struct(klass,mark,free,sval)\
+)
+
+#define Data_Get_Struct(obj,type,sval) do {\
+    Check_Type(obj, T_DATA); \
+    sval = (type*)DATA_PTR(obj);\
+} while (0)
+
+struct RStruct {
+    struct RBasic basic;
+    long len;
+    VALUE *ptr;
+};
+#define RSTRUCT_LEN(st) (RSTRUCT(st)->len)
+#define RSTRUCT_PTR(st) (RSTRUCT(st)->ptr)
+
+struct RBignum {
+    struct RBasic basic;
+    char sign;
+    long len;
+    void *digits;
+};
+
+#define R_CAST(st)   (struct st*)
+#define RBASIC(obj)  (R_CAST(RBasic)(obj))
+#define ROBJECT(obj) (R_CAST(RObject)(obj))
+#define RCLASS(obj)  (R_CAST(RClass)(obj))
+#define RMODULE(obj) RCLASS(obj)
+#define RFLOAT(obj)  (R_CAST(RFloat)(obj))
+#define RSTRING(obj) (R_CAST(RString)(obj))
+#define RREGEXP(obj) (R_CAST(RRegexp)(obj))
+#define RARRAY(obj)  (R_CAST(RArray)(obj))
+#define RHASH(obj)   (R_CAST(RHash)(obj))
+#define RDATA(obj)   (R_CAST(RData)(obj))
+#define RSTRUCT(obj) (R_CAST(RStruct)(obj))
+#define RBIGNUM(obj) (R_CAST(RBignum)(obj))
+#define RFILE(obj)   (R_CAST(RFile)(obj))
+
+#define FL_SINGLETON FL_USER0
+#define FL_MARK      (1<<6)
+#define FL_FINALIZE  (1<<7)
+#define FL_TAINT     (1<<8)
+#define FL_EXIVAR    (1<<9)
+#define FL_FREEZE    (1<<10)
+
+#define FL_USHIFT    11
+
+#define FL_USER0     (1<<(FL_USHIFT+0))
+#define FL_USER1     (1<<(FL_USHIFT+1))
+#define FL_USER2     (1<<(FL_USHIFT+2))
+#define FL_USER3     (1<<(FL_USHIFT+3))
+#define FL_USER4     (1<<(FL_USHIFT+4))
+#define FL_USER5     (1<<(FL_USHIFT+5))
+#define FL_USER6     (1<<(FL_USHIFT+6))
+#define FL_USER7     (1<<(FL_USHIFT+7))
+
+#define FL_UMASK  (0xff<<FL_USHIFT)
+
+#define SPECIAL_CONST_P(x) (IMMEDIATE_P(x) || !RTEST(x))
+
+#define FL_ABLE(x) (!SPECIAL_CONST_P(x))
+#define FL_TEST(x,f) (FL_ABLE(x)?(RBASIC(x)->flags&(f)):0)
+#define FL_SET(x,f) do {if (FL_ABLE(x)) RBASIC(x)->flags |= (f);} while (0)
+#define FL_UNSET(x,f) do {if (FL_ABLE(x)) RBASIC(x)->flags &= ~(f);} while (0)
+#define FL_REVERSE(x,f) do {if (FL_ABLE(x)) RBASIC(x)->flags ^= (f);} while (0)
+
+#define OBJ_TAINTED(x) FL_TEST((x), FL_TAINT)
+#define OBJ_TAINT(x) FL_SET((x), FL_TAINT)
+#define OBJ_INFECT(x,s) do {if (FL_ABLE(x) && FL_ABLE(s)) RBASIC(x)->flags |= RBASIC(s)->flags & FL_TAINT;} while (0)
+
+#define OBJ_FROZEN(x) FL_TEST((x), FL_FREEZE)
+#define OBJ_FREEZE(x) FL_SET((x), FL_FREEZE)
+
+#define ALLOC_N(type,n) (type*)xmalloc(sizeof(type)*(n))
+#define ALLOC(type) (type*)xmalloc(sizeof(type))
+#define REALLOC_N(var,type,n) (var)=(type*)xrealloc((char*)(var),sizeof(type)*(n))
+
+#define ALLOCA_N(type,n) (type*)alloca(sizeof(type)*(n))
+
+#define MEMZERO(p,type,n) memset((p), 0, sizeof(type)*(n))
+#define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), sizeof(type)*(n))
+#define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(n))
+#define MEMCMP(p1,p2,type,n) memcmp((p1), (p2), sizeof(type)*(n))
+
+void rb_obj_infect _((VALUE,VALUE));
+
+typedef int ruby_glob_func(const char*,VALUE);
+void rb_glob _((const char*,void(*)(const char*,VALUE),VALUE));
+void rb_globi _((const char*,void(*)(const char*,VALUE),VALUE));
+int ruby_brace_expand _((const char*,int,ruby_glob_func*,VALUE));
+int ruby_brace_glob _((const char*,int,ruby_glob_func*,VALUE));
+
+VALUE rb_define_class _((const char*,VALUE));
+VALUE rb_define_module _((const char*));
+VALUE rb_define_class_under _((VALUE, const char*, VALUE));
+VALUE rb_define_module_under _((VALUE, const char*));
+
+void rb_include_module _((VALUE,VALUE));
+void rb_extend_object _((VALUE,VALUE));
+
+void rb_define_variable _((const char*,VALUE*));
+void rb_define_virtual_variable _((const char*,VALUE(*)(ANYARGS),void(*)(ANYARGS)));
+void rb_define_hooked_variable _((const char*,VALUE*,VALUE(*)(ANYARGS),void(*)(ANYARGS)));
+int ruby_glob _((const char*,int,int(*)(const char*,VALUE),VALUE));
+int ruby_globi _((const char*,int,int(*)(const char*,VALUE),VALUE));
+void rb_define_readonly_variable _((const char*,VALUE*));
+void rb_define_const _((VALUE,const char*,VALUE));
+void rb_define_global_const _((const char*,VALUE));
+
+#define RUBY_METHOD_FUNC(func) ((VALUE (*)(ANYARGS))func)
+void rb_define_method _((VALUE,const char*,VALUE(*)(ANYARGS),int));
+void rb_define_module_function _((VALUE,const char*,VALUE(*)(ANYARGS),int));
+void rb_define_global_function _((const char*,VALUE(*)(ANYARGS),int));
+
+void rb_undef_method _((VALUE,const char*));
+void rb_define_alias _((VALUE,const char*,const char*));
+void rb_define_attr _((VALUE,const char*,int,int));
+
+void rb_global_variable _((VALUE*));
+void rb_gc_register_address _((VALUE*));
+void rb_gc_unregister_address _((VALUE*));
+
+ID rb_intern _((const char*));
+char *rb_id2name _((ID));
+ID rb_to_id _((VALUE));
+
+char *rb_class2name _((VALUE));
+char *rb_obj_classname _((VALUE));
+
+void rb_p _((VALUE));
+
+VALUE rb_eval_string _((const char*));
+VALUE rb_eval_string_protect _((const char*, int*));
+VALUE rb_eval_string_wrap _((const char*, int*));
+VALUE rb_funcall __((VALUE, ID, int, ...));
+VALUE rb_funcall2 _((VALUE, ID, int, const VALUE*));
+VALUE rb_funcall3 _((VALUE, ID, int, const VALUE*));
+int rb_scan_args __((int, const VALUE*, const char*, ...));
+VALUE rb_call_super _((int, const VALUE*));
+
+VALUE rb_gv_set _((const char*, VALUE));
+VALUE rb_gv_get _((const char*));
+VALUE rb_iv_get _((VALUE, const char*));
+VALUE rb_iv_set _((VALUE, const char*, VALUE));
+
+VALUE rb_equal _((VALUE,VALUE));
+
+RUBY_EXTERN VALUE ruby_verbose, ruby_debug;
+
+NORETURN(void rb_raise __((VALUE, const char*, ...)));
+NORETURN(void rb_fatal __((const char*, ...)));
+NORETURN(void rb_bug __((const char*, ...)));
+NORETURN(void rb_sys_fail _((const char*)));
+NORETURN(void rb_iter_break _((void)));
+NORETURN(void rb_exit _((int)));
+NORETURN(void rb_notimplement _((void)));
+
+void rb_warning __((const char*, ...));		/* reports if `-w' specified */
+void rb_sys_warning __((const char*, ...));	/* reports if `-w' specified */
+void rb_warn __((const char*, ...));		/* reports always */
+
+VALUE rb_each _((VALUE));
+VALUE rb_yield _((VALUE));
+VALUE rb_yield_values __((int n, ...));
+VALUE rb_yield_splat _((VALUE));
+int rb_block_given_p _((void));
+void rb_need_block _((void));
+VALUE rb_iterate _((VALUE(*)(VALUE),VALUE,VALUE(*)(ANYARGS),VALUE));
+VALUE rb_rescue _((VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE));
+VALUE rb_rescue2 __((VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE,...));
+VALUE rb_ensure _((VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE));
+VALUE rb_catch _((const char*,VALUE(*)(ANYARGS),VALUE));
+NORETURN(void rb_throw _((const char*,VALUE)));
+
+VALUE rb_require _((const char*));
+
+#ifdef __ia64
+void ruby_init_stack(VALUE*, void*);
+#define RUBY_INIT_STACK \
+    VALUE variable_in_this_stack_frame; \
+    ruby_init_stack(&variable_in_this_stack_frame, rb_ia64_bsp());
+#else
+void ruby_init_stack(VALUE*);
+#define RUBY_INIT_STACK \
+    VALUE variable_in_this_stack_frame; \
+    ruby_init_stack(&variable_in_this_stack_frame);
+#endif
+void ruby_init _((void));
+void ruby_options _((int, char**));
+NORETURN(void ruby_run _((void)));
+
+RUBY_EXTERN VALUE rb_mKernel;
+RUBY_EXTERN VALUE rb_mComparable;
+RUBY_EXTERN VALUE rb_mEnumerable;
+RUBY_EXTERN VALUE rb_mPrecision;
+RUBY_EXTERN VALUE rb_mErrno;
+RUBY_EXTERN VALUE rb_mFileTest;
+RUBY_EXTERN VALUE rb_mGC;
+RUBY_EXTERN VALUE rb_mMath;
+RUBY_EXTERN VALUE rb_mProcess;
+
+RUBY_EXTERN VALUE rb_cObject;
+RUBY_EXTERN VALUE rb_cArray;
+RUBY_EXTERN VALUE rb_cBignum;
+RUBY_EXTERN VALUE rb_cBinding;
+RUBY_EXTERN VALUE rb_cClass;
+RUBY_EXTERN VALUE rb_cCont;
+RUBY_EXTERN VALUE rb_cDir;
+RUBY_EXTERN VALUE rb_cData;
+RUBY_EXTERN VALUE rb_cFalseClass;
+RUBY_EXTERN VALUE rb_cFile;
+RUBY_EXTERN VALUE rb_cFixnum;
+RUBY_EXTERN VALUE rb_cFloat;
+RUBY_EXTERN VALUE rb_cHash;
+RUBY_EXTERN VALUE rb_cInteger;
+RUBY_EXTERN VALUE rb_cIO;
+RUBY_EXTERN VALUE rb_cMatch;
+RUBY_EXTERN VALUE rb_cMethod;
+RUBY_EXTERN VALUE rb_cModule;
+RUBY_EXTERN VALUE rb_cNameErrorMesg;
+RUBY_EXTERN VALUE rb_cNilClass;
+RUBY_EXTERN VALUE rb_cNumeric;
+RUBY_EXTERN VALUE rb_cProc;
+RUBY_EXTERN VALUE rb_cRange;
+RUBY_EXTERN VALUE rb_cRegexp;
+RUBY_EXTERN VALUE rb_cStat;
+RUBY_EXTERN VALUE rb_cString;
+RUBY_EXTERN VALUE rb_cStruct;
+RUBY_EXTERN VALUE rb_cSymbol;
+RUBY_EXTERN VALUE rb_cThread;
+RUBY_EXTERN VALUE rb_cTime;
+RUBY_EXTERN VALUE rb_cTrueClass;
+RUBY_EXTERN VALUE rb_cUnboundMethod;
+
+RUBY_EXTERN VALUE rb_eException;
+RUBY_EXTERN VALUE rb_eStandardError;
+RUBY_EXTERN VALUE rb_eSystemExit;
+RUBY_EXTERN VALUE rb_eInterrupt;
+RUBY_EXTERN VALUE rb_eSignal;
+RUBY_EXTERN VALUE rb_eFatal;
+RUBY_EXTERN VALUE rb_eArgError;
+RUBY_EXTERN VALUE rb_eEOFError;
+RUBY_EXTERN VALUE rb_eIndexError;
+RUBY_EXTERN VALUE rb_eRangeError;
+RUBY_EXTERN VALUE rb_eIOError;
+RUBY_EXTERN VALUE rb_eRuntimeError;
+RUBY_EXTERN VALUE rb_eSecurityError;
+RUBY_EXTERN VALUE rb_eSystemCallError;
+RUBY_EXTERN VALUE rb_eThreadError;
+RUBY_EXTERN VALUE rb_eTypeError;
+RUBY_EXTERN VALUE rb_eZeroDivError;
+RUBY_EXTERN VALUE rb_eNotImpError;
+RUBY_EXTERN VALUE rb_eNoMemError;
+RUBY_EXTERN VALUE rb_eNoMethodError;
+RUBY_EXTERN VALUE rb_eFloatDomainError;
+RUBY_EXTERN VALUE rb_eLocalJumpError;
+RUBY_EXTERN VALUE rb_eSysStackError;
+RUBY_EXTERN VALUE rb_eRegexpError;
+
+RUBY_EXTERN VALUE rb_eScriptError;
+RUBY_EXTERN VALUE rb_eNameError;
+RUBY_EXTERN VALUE rb_eSyntaxError;
+RUBY_EXTERN VALUE rb_eLoadError;
+
+RUBY_EXTERN VALUE rb_stdin, rb_stdout, rb_stderr;
+RUBY_EXTERN VALUE ruby_errinfo;
+
+static inline VALUE
+#if defined(HAVE_PROTOTYPES)
+rb_class_of(VALUE obj)
+#else
+rb_class_of(obj)
+    VALUE obj;
+#endif
+{
+    if (FIXNUM_P(obj)) return rb_cFixnum;
+    if (obj == Qnil) return rb_cNilClass;
+    if (obj == Qfalse) return rb_cFalseClass;
+    if (obj == Qtrue) return rb_cTrueClass;
+    if (SYMBOL_P(obj)) return rb_cSymbol;
+
+    return RBASIC(obj)->klass;
+}
+
+static inline int
+#if defined(HAVE_PROTOTYPES)
+rb_type(VALUE obj)
+#else
+rb_type(obj)
+   VALUE obj;
+#endif
+{
+    if (FIXNUM_P(obj)) return T_FIXNUM;
+    if (obj == Qnil) return T_NIL;
+    if (obj == Qfalse) return T_FALSE;
+    if (obj == Qtrue) return T_TRUE;
+    if (obj == Qundef) return T_UNDEF;
+    if (SYMBOL_P(obj)) return T_SYMBOL;
+    return BUILTIN_TYPE(obj);
+}
+
+static inline int
+#if defined(HAVE_PROTOTYPES)
+rb_special_const_p(VALUE obj)
+#else
+rb_special_const_p(obj)
+    VALUE obj;
+#endif
+{
+    if (SPECIAL_CONST_P(obj)) return Qtrue;
+    return Qfalse;
+}
+
+#include "missing.h"
+#include "intern.h"
+
+#if defined(EXTLIB) && defined(USE_DLN_A_OUT)
+/* hook for external modules */
+static char *dln_libs_to_be_linked[] = { EXTLIB, 0 };
+#endif
+
+#if defined(HAVE_LIBPTHREAD)
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+typedef pthread_t rb_nativethread_t;
+# define NATIVETHREAD_CURRENT() pthread_self()
+# define NATIVETHREAD_EQUAL(t1,t2) pthread_equal((t1),(t2))
+# define HAVE_NATIVETHREAD
+
+# define NATIVETHREAD_KILL(th,sig) pthread_kill((th),(sig))
+# define HAVE_NATIVETHREAD_KILL
+#elif defined(_WIN32) || defined(_WIN32_WCE)
+typedef DWORD rb_nativethread_t;
+# define NATIVETHREAD_CURRENT() GetCurrentThreadId()
+# define NATIVETHREAD_EQUAL(t1,t2) ((t1) == (t2))
+# define HAVE_NATIVETHREAD
+#endif
+#ifdef HAVE_NATIVETHREAD
+int is_ruby_native_thread _((void));
+#else
+#define is_ruby_native_thread() (1)
+#endif
+#ifdef HAVE_NATIVETHREAD_KILL
+void ruby_native_thread_kill _((int));
+#endif
+
+#if defined(__cplusplus)
+#if 0
+{ /* satisfy cc-mode */
+#endif
+}  /* extern "C" { */
+#endif
+
+#endif /* ifndef RUBY_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/rubyio.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/rubyio.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/rubyio.h	(revision 18425)
@@ -0,0 +1,88 @@
+/**********************************************************************
+
+  rubyio.h -
+
+  $Author: shyouhei $
+  $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+  created at: Fri Nov 12 16:47:09 JST 1993
+
+  Copyright (C) 1993-2003 Yukihiro Matsumoto
+
+**********************************************************************/
+
+#ifndef RUBYIO_H
+#define RUBYIO_H
+
+#include <stdio.h>
+#include <errno.h>
+
+#if defined(HAVE_STDIO_EXT_H)
+#include <stdio_ext.h>
+#endif
+
+typedef struct OpenFile {
+    FILE *f;			/* stdio ptr for read/write */
+    FILE *f2;			/* additional ptr for rw pipes */
+    int mode;			/* mode flags */
+    int pid;			/* child's pid (for pipes) */
+    int lineno;			/* number of lines read */
+    char *path;			/* pathname for file */
+    void (*finalize) _((struct OpenFile*,int)); /* finalize proc */
+} OpenFile;
+
+#define FMODE_READABLE  1
+#define FMODE_WRITABLE  2
+#define FMODE_READWRITE 3
+#define FMODE_APPEND   64
+#define FMODE_CREATE  128
+#define FMODE_BINMODE   4
+#define FMODE_SYNC      8
+#define FMODE_WBUF     16
+#define FMODE_RBUF     32
+#define FMODE_WSPLIT  0x200
+#define FMODE_WSPLIT_INITIALIZED  0x400
+
+#define GetOpenFile(obj,fp) rb_io_check_closed((fp) = RFILE(rb_io_taint_check(obj))->fptr)
+
+#define MakeOpenFile(obj, fp) do {\
+    if (RFILE(obj)->fptr) {\
+	rb_io_close(obj);\
+	free(RFILE(obj)->fptr);\
+	RFILE(obj)->fptr = 0;\
+    }\
+    fp = 0;\
+    fp = RFILE(obj)->fptr = ALLOC(OpenFile);\
+    fp->f = fp->f2 = NULL;\
+    fp->mode = 0;\
+    fp->pid = 0;\
+    fp->lineno = 0;\
+    fp->path = NULL;\
+    fp->finalize = 0;\
+} while (0)
+
+#define GetReadFile(fptr) ((fptr)->f)
+#define GetWriteFile(fptr) (((fptr)->f2) ? (fptr)->f2 : (fptr)->f)
+
+FILE *rb_fopen _((const char*, const char*));
+FILE *rb_fdopen _((int, const char*));
+int rb_getc _((FILE*));
+long rb_io_fread _((char *, long, FILE *));
+long rb_io_fwrite _((const char *, long, FILE *));
+int  rb_io_mode_flags _((const char*));
+int  rb_io_modenum_flags _((int));
+void rb_io_check_writable _((OpenFile*));
+void rb_io_check_readable _((OpenFile*));
+void rb_io_fptr_finalize _((OpenFile*));
+void rb_io_synchronized _((OpenFile*));
+void rb_io_check_initialized _((OpenFile*));
+void rb_io_check_closed _((OpenFile*));
+int rb_io_wait_readable _((int));
+int rb_io_wait_writable _((int));
+void rb_io_set_nonblock(OpenFile *fptr);
+
+VALUE rb_io_taint_check _((VALUE));
+NORETURN(void rb_eof_error _((void)));
+
+void rb_read_check _((FILE*));
+int rb_read_pending _((FILE*));
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/rubysig.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/rubysig.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/rubysig.h	(revision 18425)
@@ -0,0 +1,105 @@
+/**********************************************************************
+
+  rubysig.h -
+
+  $Author: shyouhei $
+  $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+  created at: Wed Aug 16 01:15:38 JST 1995
+
+  Copyright (C) 1993-2003 Yukihiro Matsumoto
+
+**********************************************************************/
+
+#ifndef SIG_H
+#define SIG_H
+#include <errno.h>
+
+#ifdef _WIN32
+typedef LONG rb_atomic_t;
+
+# define ATOMIC_TEST(var) InterlockedExchange(&(var), 0)
+# define ATOMIC_SET(var, val) InterlockedExchange(&(var), (val))
+# define ATOMIC_INC(var) InterlockedIncrement(&(var))
+# define ATOMIC_DEC(var) InterlockedDecrement(&(var))
+
+/* Windows doesn't allow interrupt while system calls */
+# define TRAP_BEG do {\
+    int saved_errno = 0;\
+    rb_atomic_t trap_immediate = ATOMIC_SET(rb_trap_immediate, 1)
+# define TRAP_END\
+    ATOMIC_SET(rb_trap_immediate, trap_immediate);\
+    saved_errno = errno;\
+    CHECK_INTS;\
+    errno = saved_errno;\
+} while (0)
+# define RUBY_CRITICAL(statements) do {\
+    rb_w32_enter_critical();\
+    statements;\
+    rb_w32_leave_critical();\
+} while (0)
+#else
+typedef int rb_atomic_t;
+
+# define ATOMIC_TEST(var) ((var) ? ((var) = 0, 1) : 0)
+# define ATOMIC_SET(var, val) ((var) = (val))
+# define ATOMIC_INC(var) (++(var))
+# define ATOMIC_DEC(var) (--(var))
+
+# define TRAP_BEG do {\
+    int saved_errno = 0;\
+    int trap_immediate = rb_trap_immediate;\
+    rb_trap_immediate = 1
+# define TRAP_END rb_trap_immediate = trap_immediate;\
+    saved_errno = errno;\
+    CHECK_INTS;\
+    errno = saved_errno;\
+} while (0)
+
+# define RUBY_CRITICAL(statements) do {\
+    int trap_immediate = rb_trap_immediate;\
+    rb_trap_immediate = 0;\
+    statements;\
+    rb_trap_immediate = trap_immediate;\
+} while (0)
+#endif
+RUBY_EXTERN rb_atomic_t rb_trap_immediate;
+
+RUBY_EXTERN int rb_prohibit_interrupt;
+#define DEFER_INTS (rb_prohibit_interrupt++)
+#define ALLOW_INTS do {\
+    rb_prohibit_interrupt--;\
+    CHECK_INTS;\
+} while (0)
+#define ENABLE_INTS (rb_prohibit_interrupt--)
+
+VALUE rb_with_disable_interrupt _((VALUE(*)(ANYARGS),VALUE));
+
+RUBY_EXTERN rb_atomic_t rb_trap_pending;
+void rb_trap_restore_mask _((void));
+
+RUBY_EXTERN int rb_thread_critical;
+void rb_thread_schedule _((void));
+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
+RUBY_EXTERN int rb_thread_pending;
+# define CHECK_INTS do {\
+    if (!(rb_prohibit_interrupt || rb_thread_critical)) {\
+        if (rb_thread_pending) rb_thread_schedule();\
+	if (rb_trap_pending) rb_trap_exec();\
+    }\
+} while (0)
+#else
+/* pseudo preemptive thread switching */
+RUBY_EXTERN int rb_thread_tick;
+#define THREAD_TICK 500
+#define CHECK_INTS do {\
+    if (!(rb_prohibit_interrupt || rb_thread_critical)) {\
+	if (rb_thread_tick-- <= 0) {\
+	    rb_thread_tick = THREAD_TICK;\
+            rb_thread_schedule();\
+	}\
+    }\
+    if (rb_trap_pending) rb_trap_exec();\
+} while (0)
+#endif
+
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/st.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/st.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/st.h	(revision 18425)
@@ -0,0 +1,72 @@
+/* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */
+
+/* @(#) st.h 5.1 89/12/14 */
+
+#ifndef ST_INCLUDED
+
+#define ST_INCLUDED
+
+#if SIZEOF_LONG == SIZEOF_VOIDP
+typedef unsigned long st_data_t;
+#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
+typedef unsigned LONG_LONG st_data_t;
+#else
+# error ---->> st.c requires sizeof(void*) == sizeof(long) to be compiled. <<---
+-
+#endif
+#define ST_DATA_T_DEFINED
+
+typedef struct st_table st_table;
+
+struct st_hash_type {
+    int (*compare)();
+    int (*hash)();
+};
+
+struct st_table {
+    struct st_hash_type *type;
+    int num_bins;
+    int num_entries;
+    struct st_table_entry **bins;
+};
+
+#define st_is_member(table,key) st_lookup(table,key,(st_data_t *)0)
+
+enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK};
+
+#ifndef _
+# define _(args) args
+#endif
+#ifndef ANYARGS
+# ifdef __cplusplus
+#   define ANYARGS ...
+# else
+#   define ANYARGS
+# endif
+#endif
+
+st_table *st_init_table _((struct st_hash_type *));
+st_table *st_init_table_with_size _((struct st_hash_type *, int));
+st_table *st_init_numtable _((void));
+st_table *st_init_numtable_with_size _((int));
+st_table *st_init_strtable _((void));
+st_table *st_init_strtable_with_size _((int));
+int st_delete _((st_table *, st_data_t *, st_data_t *));
+int st_delete_safe _((st_table *, st_data_t *, st_data_t *, st_data_t));
+int st_insert _((st_table *, st_data_t, st_data_t));
+int st_lookup _((st_table *, st_data_t, st_data_t *));
+int st_foreach _((st_table *, int (*)(ANYARGS), st_data_t));
+void st_add_direct _((st_table *, st_data_t, st_data_t));
+void st_free_table _((st_table *));
+void st_cleanup_safe _((st_table *, st_data_t));
+st_table *st_copy _((st_table *));
+
+#define ST_NUMCMP	((int (*)()) 0)
+#define ST_NUMHASH	((int (*)()) -2)
+
+#define st_numcmp	ST_NUMCMP
+#define st_numhash	ST_NUMHASH
+
+int st_strhash();
+
+#endif /* ST_INCLUDED */
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/util.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/util.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/util.h	(revision 18425)
@@ -0,0 +1,67 @@
+/**********************************************************************
+
+  util.h -
+
+  $Author: shyouhei $
+  $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+  created at: Thu Mar  9 11:55:53 JST 1995
+
+  Copyright (C) 1993-2003 Yukihiro Matsumoto
+
+**********************************************************************/
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#ifndef _
+#ifdef __cplusplus
+# ifndef  HAVE_PROTOTYPES
+#  define HAVE_PROTOTYPES 1
+# endif
+# ifndef  HAVE_STDARG_PROTOTYPES
+#  define HAVE_STDARG_PROTOTYPES 1
+# endif
+#endif
+#ifdef HAVE_PROTOTYPES
+# define _(args) args
+#else
+# define _(args) ()
+#endif
+#ifdef HAVE_STDARG_PROTOTYPES
+# define __(args) args
+#else
+# define __(args) ()
+#endif
+#endif
+
+#define scan_oct ruby_scan_oct
+unsigned long scan_oct _((const char*, int, int*));
+#define scan_hex ruby_scan_hex
+unsigned long scan_hex _((const char*, int, int*));
+
+#if defined(MSDOS) || defined(__CYGWIN32__) || defined(_WIN32)
+void ruby_add_suffix();
+#endif
+
+void ruby_qsort _((void*, const int, const int, int (*)(), void*));
+#define qsort(b,n,s,c,d) ruby_qsort(b,n,s,c,d)
+
+void ruby_setenv _((const char*, const char*));
+void ruby_unsetenv _((const char*));
+#undef setenv
+#undef unsetenv
+#define setenv(name,val) ruby_setenv(name,val)
+#define unsetenv(name,val) ruby_unsetenv(name);
+
+char *ruby_strdup _((const char*));
+#undef strdup
+#define strdup(s) ruby_strdup(s)
+
+char *ruby_getcwd _((void));
+#define my_getcwd() ruby_getcwd()
+
+double ruby_strtod _((const char*, char **));
+#undef strtod
+#define strtod(s,e) ruby_strtod(s,e)
+
+#endif /* UTIL_H */
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/version.h
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/version.h	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/i686-linux/version.h	(revision 18425)
@@ -0,0 +1,19 @@
+#define RUBY_VERSION "1.8.6"
+#define RUBY_RELEASE_DATE "2007-03-13"
+#define RUBY_VERSION_CODE 186
+#define RUBY_RELEASE_CODE 20070313
+#define RUBY_PATCHLEVEL 0
+
+#define RUBY_VERSION_MAJOR 1
+#define RUBY_VERSION_MINOR 8
+#define RUBY_VERSION_TEENY 6
+#define RUBY_RELEASE_YEAR 2007
+#define RUBY_RELEASE_MONTH 3
+#define RUBY_RELEASE_DAY 13
+
+#ifdef RUBY_EXTERN
+RUBY_EXTERN const char ruby_version[];
+RUBY_EXTERN const char ruby_release_date[];
+RUBY_EXTERN const char ruby_platform[];
+RUBY_EXTERN const int ruby_patchlevel;
+#endif
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/importenv.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/importenv.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/importenv.rb	(revision 18425)
@@ -0,0 +1,33 @@
+# importenv.rb -- imports environment variables as global variables, Perlish ;(
+#
+# Usage:
+#
+#  require 'importenv'
+#  p $USER
+#  $USER = "matz"
+#  p ENV["USER"]
+
+warn "Warning:#{caller[0].sub(/:in `.*'\z/, '')}: importenv is deprecated after Ruby 1.8.1 (no replacement)"
+
+for k,v in ENV
+  next unless /^[a-zA-Z][_a-zA-Z0-9]*/ =~ k
+  eval <<EOS
+  $#{k} = v
+  trace_var "$#{k}", proc{|v|
+    ENV[%q!#{k}!] = v
+    $#{k} = v
+    if v == nil
+      untrace_var "$#{k}"
+    end
+  }
+EOS
+end
+
+if __FILE__ == $0
+  p $TERM
+  $TERM = nil
+  p $TERM
+  p ENV["TERM"]
+  $TERM = "foo"
+  p ENV["TERM"]
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/io/nonblock.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/io/nonblock.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/io/nonblock.rb	(revision 18425)
@@ -0,0 +1,23 @@
+require "fcntl"
+class IO
+  def nonblock?
+    (fcntl(Fcntl::F_GETFL) & File::NONBLOCK) != 0
+  end
+
+  def nonblock=(nb)
+    f = fcntl(Fcntl::F_GETFL)
+    if nb
+      f |= File::NONBLOCK
+    else
+      f &= ~File::NONBLOCK
+    end
+    fcntl(Fcntl::F_SETFL, f)
+  end
+
+  def nonblock(nb = true)
+    nb, self.nonblock = nonblock?, nb
+    yield
+  ensure
+    self.nonblock = nb
+  end
+end if defined?(Fcntl::F_GETFL)
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/ipaddr.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/ipaddr.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/ipaddr.rb	(revision 18425)
@@ -0,0 +1,766 @@
+#
+# ipaddr.rb - A class to manipulate an IP address
+#
+# Copyright (c) 2002 Hajimu UMEMOTO <ume@mahoroba.org>.
+# All rights reserved.
+#
+# You can redistribute and/or modify it under the same terms as Ruby.
+#
+# $Id: ipaddr.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+# TODO:
+#   - scope_id support
+require 'socket'
+
+unless Socket.const_defined? "AF_INET6"
+  class Socket
+    AF_INET6 = Object.new
+  end
+
+  class << IPSocket
+    def valid_v4?(addr)
+      if /\A(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\Z/ =~ addr
+        return $~.captures.all? {|i| i.to_i < 256}
+      end
+      return false
+    end
+
+    def valid_v6?(addr)
+      # IPv6 (normal)
+      return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*\Z/ =~ addr
+      return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*)?\Z/ =~ addr
+      return true if /\A::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*)?\Z/ =~ addr
+      # IPv6 (IPv4 compat)
+      return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*:/ =~ addr && valid_v4?($')
+      return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*:)?/ =~ addr && valid_v4?($')
+      return true if /\A::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*:)?/ =~ addr && valid_v4?($')
+
+      false
+    end
+
+    def valid?(addr)
+      valid_v4?(addr) || valid_v6?(addr)
+    end
+
+    alias getaddress_orig getaddress
+    def getaddress(s)
+      if valid?(s)
+        s
+      elsif /\A[-A-Za-z\d.]+\Z/ =~ s
+        getaddress_orig(s)
+      else
+        raise ArgumentError, "invalid address"
+      end
+    end
+  end
+end
+
+# IPAddr provides a set of methods to manipulate an IP address.  Both IPv4 and
+# IPv6 are supported.
+#
+# == Example
+#
+#   require 'ipaddr'
+#   
+#   ipaddr1 = IPAddr.new "3ffe:505:2::1"
+#   
+#   p ipaddr1			#=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0001/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>
+#   
+#   p ipaddr1.to_s		#=> "3ffe:505:2::1"
+#   
+#   ipaddr2 = ipaddr1.mask(48)	#=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0000/ffff:ffff:ffff:0000:0000:0000:0000:0000>
+#   
+#   p ipaddr2.to_s		#=> "3ffe:505:2::"
+#   
+#   ipaddr3 = IPAddr.new "192.168.2.0/24"
+#   
+#   p ipaddr3			#=> #<IPAddr: IPv4:192.168.2.0/255.255.255.0>
+
+class IPAddr
+
+  IN4MASK = 0xffffffff
+  IN6MASK = 0xffffffffffffffffffffffffffffffff
+  IN6FORMAT = (["%.4x"] * 8).join(':')
+
+  # Returns the address family of this IP address.
+  attr :family
+
+  # Creates a new ipaddr containing the given network byte ordered
+  # string form of an IP address.
+  def IPAddr::new_ntoh(addr)
+    return IPAddr.new(IPAddr::ntop(addr))
+  end
+
+  # Convert a network byte ordered string form of an IP address into
+  # human readable form.
+  def IPAddr::ntop(addr)
+    case addr.size
+    when 4
+      s = addr.unpack('C4').join('.')
+    when 16
+      s = IN6FORMAT % addr.unpack('n8')
+    else
+      raise ArgumentError, "unsupported address family"
+    end
+    return s
+  end
+
+  # Returns a new ipaddr built by bitwise AND.
+  def &(other)
+    return self.clone.set(@addr & other.to_i)
+  end
+
+  # Returns a new ipaddr built by bitwise OR.
+  def |(other)
+    return self.clone.set(@addr | other.to_i)
+  end
+
+  # Returns a new ipaddr built by bitwise right-shift.
+  def >>(num)
+    return self.clone.set(@addr >> num)
+  end
+
+  # Returns a new ipaddr built by bitwise left shift.
+  def <<(num)
+    return self.clone.set(addr_mask(@addr << num))
+  end
+
+  # Returns a new ipaddr built by bitwise negation.
+  def ~
+    return self.clone.set(addr_mask(~@addr))
+  end
+
+  # Returns true if two ipaddr are equal.
+  def ==(other)
+    if other.kind_of?(IPAddr) && @family != other.family
+      return false
+    end
+    return (@addr == other.to_i)
+  end
+
+  # Returns a new ipaddr built by masking IP address with the given
+  # prefixlen/netmask. (e.g. 8, 64, "255.255.255.0", etc.)
+  def mask(prefixlen)
+    return self.clone.mask!(prefixlen)
+  end
+
+  # Returns true if the given ipaddr is in the range.
+  #
+  # e.g.:
+  #   require 'ipaddr'
+  #   net1 = IPAddr.new("192.168.2.0/24")
+  #   p net1.include?(IPAddr.new("192.168.2.0"))	#=> true
+  #   p net1.include?(IPAddr.new("192.168.2.255"))	#=> true
+  #   p net1.include?(IPAddr.new("192.168.3.0"))	#=> false
+  def include?(other)
+    if ipv4_mapped?
+      if (@mask_addr >> 32) != 0xffffffffffffffffffffffff
+	return false
+      end
+      mask_addr = (@mask_addr & IN4MASK)
+      addr = (@addr & IN4MASK)
+      family = Socket::AF_INET
+    else
+      mask_addr = @mask_addr
+      addr = @addr
+      family = @family
+    end
+    if other.kind_of?(IPAddr)
+      if other.ipv4_mapped?
+	other_addr = (other.to_i & IN4MASK)
+	other_family = Socket::AF_INET
+      else
+	other_addr = other.to_i
+	other_family = other.family
+      end
+    else # Not IPAddr - assume integer in same family as us
+      other_addr   = other.to_i
+      other_family = family
+    end
+
+    if family != other_family
+      return false
+    end
+    return ((addr & mask_addr) == (other_addr & mask_addr))
+  end
+  alias === include?
+
+  # Returns the integer representation of the ipaddr.
+  def to_i
+    return @addr
+  end
+
+  # Returns a string containing the IP address representation.
+  def to_s
+    str = to_string
+    return str if ipv4?
+
+    str.gsub!(/\b0{1,3}([\da-f]+)\b/i, '\1')
+    loop do
+      break if str.sub!(/\A0:0:0:0:0:0:0:0\Z/, '::')
+      break if str.sub!(/\b0:0:0:0:0:0:0\b/, ':')
+      break if str.sub!(/\b0:0:0:0:0:0\b/, ':')
+      break if str.sub!(/\b0:0:0:0:0\b/, ':')
+      break if str.sub!(/\b0:0:0:0\b/, ':')
+      break if str.sub!(/\b0:0:0\b/, ':')
+      break if str.sub!(/\b0:0\b/, ':')
+      break
+    end
+    str.sub!(/:{3,}/, '::')
+
+    if /\A::(ffff:)?([\da-f]{1,4}):([\da-f]{1,4})\Z/i =~ str
+      str = sprintf('::%s%d.%d.%d.%d', $1, $2.hex / 256, $2.hex % 256, $3.hex / 256, $3.hex % 256)
+    end
+
+    str
+  end
+
+  # Returns a string containing the IP address representation in
+  # canonical form.
+  def to_string
+    return _to_string(@addr)
+  end
+
+  # Returns a network byte ordered string form of the IP address.
+  def hton
+    case @family
+    when Socket::AF_INET
+      return [@addr].pack('N')
+    when Socket::AF_INET6
+      return (0..7).map { |i|
+	(@addr >> (112 - 16 * i)) & 0xffff
+      }.pack('n8')
+    else
+      raise "unsupported address family"
+    end
+  end
+
+  # Returns true if the ipaddr is an IPv4 address.
+  def ipv4?
+    return @family == Socket::AF_INET
+  end
+
+  # Returns true if the ipaddr is an IPv6 address.
+  def ipv6?
+    return @family == Socket::AF_INET6
+  end
+
+  # Returns true if the ipaddr is an IPv4-mapped IPv6 address.
+  def ipv4_mapped?
+    return ipv6? && (@addr >> 32) == 0xffff
+  end
+
+  # Returns true if the ipaddr is an IPv4-compatible IPv6 address.
+  def ipv4_compat?
+    if !ipv6? || (@addr >> 32) != 0
+      return false
+    end
+    a = (@addr & IN4MASK)
+    return a != 0 && a != 1
+  end
+
+  # Returns a new ipaddr built by converting the native IPv4 address
+  # into an IPv4-mapped IPv6 address.
+  def ipv4_mapped
+    if !ipv4?
+      raise ArgumentError, "not an IPv4 address"
+    end
+    return self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6)
+  end
+
+  # Returns a new ipaddr built by converting the native IPv4 address
+  # into an IPv4-compatible IPv6 address.
+  def ipv4_compat
+    if !ipv4?
+      raise ArgumentError, "not an IPv4 address"
+    end
+    return self.clone.set(@addr, Socket::AF_INET6)
+  end
+
+  # Returns a new ipaddr built by converting the IPv6 address into a
+  # native IPv4 address.  If the IP address is not an IPv4-mapped or
+  # IPv4-compatible IPv6 address, returns self.
+  def native
+    if !ipv4_mapped? && !ipv4_compat?
+      return self
+    end
+    return self.clone.set(@addr & IN4MASK, Socket::AF_INET)
+  end
+
+  # Returns a string for DNS reverse lookup.  It returns a string in
+  # RFC3172 form for an IPv6 address.
+  def reverse
+    case @family
+    when Socket::AF_INET
+      return _reverse + ".in-addr.arpa"
+    when Socket::AF_INET6
+      return ip6_arpa
+    else
+      raise "unsupported address family"
+    end
+  end
+
+  # Returns a string for DNS reverse lookup compatible with RFC3172.
+  def ip6_arpa
+    if !ipv6?
+      raise ArgumentError, "not an IPv6 address"
+    end
+    return _reverse + ".ip6.arpa"
+  end
+
+  # Returns a string for DNS reverse lookup compatible with RFC1886.
+  def ip6_int
+    if !ipv6?
+      raise ArgumentError, "not an IPv6 address"
+    end
+    return _reverse + ".ip6.int"
+  end
+
+  # Returns a string containing a human-readable representation of the
+  # ipaddr. ("#<IPAddr: family:address/mask>")
+  def inspect
+    case @family
+    when Socket::AF_INET
+      af = "IPv4"
+    when Socket::AF_INET6
+      af = "IPv6"
+    else
+      raise "unsupported address family"
+    end
+    return sprintf("#<%s: %s:%s/%s>", self.class.name,
+		   af, _to_string(@addr), _to_string(@mask_addr))
+  end
+
+  protected
+
+  def set(addr, *family)
+    case family[0] ? family[0] : @family
+    when Socket::AF_INET
+      if addr < 0 || addr > IN4MASK
+	raise ArgumentError, "invalid address"
+      end
+    when Socket::AF_INET6
+      if addr < 0 || addr > IN6MASK
+	raise ArgumentError, "invalid address"
+      end
+    else
+      raise ArgumentError, "unsupported address family"
+    end
+    @addr = addr
+    if family[0]
+      @family = family[0]
+    end
+    return self
+  end
+
+  def mask!(mask)
+    if mask.kind_of?(String)
+      if mask =~ /^\d+$/
+	prefixlen = mask.to_i
+      else
+	m = IPAddr.new(mask)
+	if m.family != @family
+	  raise ArgumentError, "address family is not same"
+	end
+	@mask_addr = m.to_i
+	@addr &= @mask_addr
+	return self
+      end
+    else
+      prefixlen = mask
+    end
+    case @family
+    when Socket::AF_INET
+      if prefixlen < 0 || prefixlen > 32
+	raise ArgumentError, "invalid length"
+      end
+      masklen = 32 - prefixlen
+      @mask_addr = ((IN4MASK >> masklen) << masklen)
+    when Socket::AF_INET6
+      if prefixlen < 0 || prefixlen > 128
+	raise ArgumentError, "invalid length"
+      end
+      masklen = 128 - prefixlen
+      @mask_addr = ((IN6MASK >> masklen) << masklen)
+    else
+      raise "unsupported address family"
+    end
+    @addr = ((@addr >> masklen) << masklen)
+    return self
+  end
+
+  private
+
+  # Creates a new ipaddr containing the given human readable form of
+  # an IP address.  It also accepts `address/prefixlen' and
+  # `address/mask'.  When prefixlen or mask is specified, it returns a
+  # masked ipaddr.  IPv6 address may beenclosed with `[' and `]'.
+  #
+  # Although an address family is determined automatically from a
+  # specified address, you can specify an address family explicitly by
+  # the optional second argument.
+  def initialize(addr = '::', family = Socket::AF_UNSPEC)
+    if !addr.kind_of?(String)
+      if family != Socket::AF_INET6 && family != Socket::AF_INET
+	raise ArgumentError, "unsupported address family"
+      end
+      set(addr, family)
+      @mask_addr = (family == Socket::AF_INET) ? IN4MASK : IN6MASK
+      return
+    end
+    prefix, prefixlen = addr.split('/')
+    if prefix =~ /^\[(.*)\]$/i
+      prefix = $1
+      family = Socket::AF_INET6
+    end
+    # It seems AI_NUMERICHOST doesn't do the job.
+    #Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil,
+    #		       Socket::AI_NUMERICHOST)
+    begin
+      IPSocket.getaddress(prefix)		# test if address is vaild
+    rescue
+      raise ArgumentError, "invalid address"
+    end
+    @addr = @family = nil
+    if family == Socket::AF_UNSPEC || family == Socket::AF_INET
+      @addr = in_addr(prefix)
+      if @addr
+	@family = Socket::AF_INET
+      end
+    end
+    if !@addr && (family == Socket::AF_UNSPEC || family == Socket::AF_INET6)
+      @addr = in6_addr(prefix)
+      @family = Socket::AF_INET6
+    end
+    if family != Socket::AF_UNSPEC && @family != family
+      raise ArgumentError, "address family unmatch"
+    end
+    if prefixlen
+      mask!(prefixlen)
+    else
+      @mask_addr = (family == Socket::AF_INET) ? IN4MASK : IN6MASK
+    end
+  end
+
+  def in_addr(addr)
+    if addr =~ /^\d+\.\d+\.\d+\.\d+$/
+      n = 0
+      addr.split('.').each { |i|
+	n <<= 8
+	n += i.to_i
+      }
+      return n
+    end
+    return nil
+  end
+
+  def in6_addr(left)
+    case left
+    when /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i
+      return in_addr($1) + 0xffff00000000
+    when /^::(\d+\.\d+\.\d+\.\d+)$/i
+      return in_addr($1)
+    when /[^0-9a-f:]/i
+      raise ArgumentError, "invalid address"
+    when /^(.*)::(.*)$/
+      left, right = $1, $2
+    else
+      right = ''
+    end
+    l = left.split(':')
+    r = right.split(':')
+    rest = 8 - l.size - r.size
+    if rest < 0
+      return nil
+    end
+    a = [l, Array.new(rest, '0'), r].flatten!
+    n = 0
+    a.each { |i|
+      n <<= 16
+      n += i.hex
+    }
+    return n
+  end
+
+  def addr_mask(addr)
+    case @family
+    when Socket::AF_INET
+      addr &= IN4MASK
+    when Socket::AF_INET6
+      addr &= IN6MASK
+    else
+      raise "unsupported address family"
+    end
+    return addr
+  end
+
+  def _reverse
+    case @family
+    when Socket::AF_INET
+      return (0..3).map { |i|
+	(@addr >> (8 * i)) & 0xff
+      }.join('.')
+    when Socket::AF_INET6
+      return ("%.32x" % @addr).reverse!.gsub!(/.(?!$)/, '\&.')
+    else
+      raise "unsupported address family"
+    end
+  end
+
+  def _to_string(addr)
+    case @family
+    when Socket::AF_INET
+      return (0..3).map { |i|
+	(addr >> (24 - 8 * i)) & 0xff
+      }.join('.')
+    when Socket::AF_INET6
+      return (("%.32x" % addr).gsub!(/.{4}(?!$)/, '\&:'))
+    else
+      raise "unsupported address family"
+    end
+  end
+
+end
+
+if $0 == __FILE__
+  eval DATA.read, nil, $0, __LINE__+4
+end
+
+__END__
+
+require 'test/unit'
+require 'test/unit/ui/console/testrunner'
+
+class TC_IPAddr < Test::Unit::TestCase
+  def test_s_new
+    assert_nothing_raised {
+      IPAddr.new("3FFE:505:ffff::/48")
+      IPAddr.new("0:0:0:1::")
+      IPAddr.new("2001:200:300::/48")
+    }
+
+    a = IPAddr.new
+    assert_equal("::", a.to_s)
+    assert_equal("0000:0000:0000:0000:0000:0000:0000:0000", a.to_string)
+    assert_equal(Socket::AF_INET6, a.family)
+
+    a = IPAddr.new("0123:4567:89ab:cdef:0ABC:DEF0:1234:5678")
+    assert_equal("123:4567:89ab:cdef:abc:def0:1234:5678", a.to_s)
+    assert_equal("0123:4567:89ab:cdef:0abc:def0:1234:5678", a.to_string)
+    assert_equal(Socket::AF_INET6, a.family)
+
+    a = IPAddr.new("3ffe:505:2::/48")
+    assert_equal("3ffe:505:2::", a.to_s)
+    assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0000", a.to_string)
+    assert_equal(Socket::AF_INET6, a.family)
+    assert_equal(false, a.ipv4?)
+    assert_equal(true, a.ipv6?)
+    assert_equal("#<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0000/ffff:ffff:ffff:0000:0000:0000:0000:0000>", a.inspect)
+
+    a = IPAddr.new("3ffe:505:2::/ffff:ffff:ffff::")
+    assert_equal("3ffe:505:2::", a.to_s)
+    assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0000", a.to_string)
+    assert_equal(Socket::AF_INET6, a.family)
+
+    a = IPAddr.new("0.0.0.0")
+    assert_equal("0.0.0.0", a.to_s)
+    assert_equal("0.0.0.0", a.to_string)
+    assert_equal(Socket::AF_INET, a.family)
+
+    a = IPAddr.new("192.168.1.2")
+    assert_equal("192.168.1.2", a.to_s)
+    assert_equal("192.168.1.2", a.to_string)
+    assert_equal(Socket::AF_INET, a.family)
+    assert_equal(true, a.ipv4?)
+    assert_equal(false, a.ipv6?)
+
+    a = IPAddr.new("192.168.1.2/24")
+    assert_equal("192.168.1.0", a.to_s)
+    assert_equal("192.168.1.0", a.to_string)
+    assert_equal(Socket::AF_INET, a.family)
+    assert_equal("#<IPAddr: IPv4:192.168.1.0/255.255.255.0>", a.inspect)
+
+    a = IPAddr.new("192.168.1.2/255.255.255.0")
+    assert_equal("192.168.1.0", a.to_s)
+    assert_equal("192.168.1.0", a.to_string)
+    assert_equal(Socket::AF_INET, a.family)
+
+    assert_equal("0:0:0:1::", IPAddr.new("0:0:0:1::").to_s)
+    assert_equal("2001:200:300::", IPAddr.new("2001:200:300::/48").to_s)
+
+    assert_equal("2001:200:300::", IPAddr.new("[2001:200:300::]/48").to_s)
+
+    [
+      ["fe80::1%fxp0"],
+      ["::1/255.255.255.0"],
+      ["::1:192.168.1.2/120"],
+      [IPAddr.new("::1").to_i],
+      ["::ffff:192.168.1.2/120", Socket::AF_INET],
+      ["[192.168.1.2]/120"],
+    ].each { |args|
+      assert_raises(ArgumentError) {
+	IPAddr.new(*args)
+      }
+    }
+  end
+
+  def test_s_new_ntoh
+    addr = ''
+    IPAddr.new("1234:5678:9abc:def0:1234:5678:9abc:def0").hton.each_byte { |c|
+      addr += sprintf("%02x", c)
+    }
+    assert_equal("123456789abcdef0123456789abcdef0", addr)
+    addr = ''
+    IPAddr.new("123.45.67.89").hton.each_byte { |c|
+      addr += sprintf("%02x", c)
+    }
+    assert_equal(sprintf("%02x%02x%02x%02x", 123, 45, 67, 89), addr)
+    a = IPAddr.new("3ffe:505:2::")
+    assert_equal("3ffe:505:2::", IPAddr.new_ntoh(a.hton).to_s)
+    a = IPAddr.new("192.168.2.1")
+    assert_equal("192.168.2.1", IPAddr.new_ntoh(a.hton).to_s)
+  end
+
+  def test_ipv4_compat
+    a = IPAddr.new("::192.168.1.2")
+    assert_equal("::192.168.1.2", a.to_s)
+    assert_equal("0000:0000:0000:0000:0000:0000:c0a8:0102", a.to_string)
+    assert_equal(Socket::AF_INET6, a.family)
+    assert_equal(true, a.ipv4_compat?)
+    b = a.native
+    assert_equal("192.168.1.2", b.to_s)
+    assert_equal(Socket::AF_INET, b.family)
+    assert_equal(false, b.ipv4_compat?)
+
+    a = IPAddr.new("192.168.1.2")
+    b = a.ipv4_compat
+    assert_equal("::192.168.1.2", b.to_s)
+    assert_equal(Socket::AF_INET6, b.family)
+  end
+
+  def test_ipv4_mapped
+    a = IPAddr.new("::ffff:192.168.1.2")
+    assert_equal("::ffff:192.168.1.2", a.to_s)
+    assert_equal("0000:0000:0000:0000:0000:ffff:c0a8:0102", a.to_string)
+    assert_equal(Socket::AF_INET6, a.family)
+    assert_equal(true, a.ipv4_mapped?)
+    b = a.native
+    assert_equal("192.168.1.2", b.to_s)
+    assert_equal(Socket::AF_INET, b.family)
+    assert_equal(false, b.ipv4_mapped?)
+
+    a = IPAddr.new("192.168.1.2")
+    b = a.ipv4_mapped
+    assert_equal("::ffff:192.168.1.2", b.to_s)
+    assert_equal(Socket::AF_INET6, b.family)
+  end
+
+  def test_reverse
+    assert_equal("f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.5.0.5.0.e.f.f.3.ip6.arpa", IPAddr.new("3ffe:505:2::f").reverse)
+    assert_equal("1.2.168.192.in-addr.arpa", IPAddr.new("192.168.2.1").reverse)
+  end
+
+  def test_ip6_arpa
+    assert_equal("f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.5.0.5.0.e.f.f.3.ip6.arpa", IPAddr.new("3ffe:505:2::f").ip6_arpa)
+    assert_raises(ArgumentError) {
+      IPAddr.new("192.168.2.1").ip6_arpa
+    }
+  end
+
+  def test_ip6_int
+    assert_equal("f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.5.0.5.0.e.f.f.3.ip6.int", IPAddr.new("3ffe:505:2::f").ip6_int)
+    assert_raises(ArgumentError) {
+      IPAddr.new("192.168.2.1").ip6_int
+    }
+  end
+
+  def test_to_s
+    assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0001", IPAddr.new("3ffe:505:2::1").to_string)
+    assert_equal("3ffe:505:2::1", IPAddr.new("3ffe:505:2::1").to_s)
+  end
+end
+
+class TC_Operator < Test::Unit::TestCase
+
+  IN6MASK32  = "ffff:ffff::"
+  IN6MASK128 = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
+
+  def setup
+    @in6_addr_any = IPAddr.new()
+    @a = IPAddr.new("3ffe:505:2::/48")
+    @b = IPAddr.new("0:0:0:1::")
+    @c = IPAddr.new(IN6MASK32)
+  end
+  alias set_up setup
+
+  def test_or
+    assert_equal("3ffe:505:2:1::", (@a | @b).to_s)
+    a = @a
+    a |= @b
+    assert_equal("3ffe:505:2:1::", a.to_s)
+    assert_equal("3ffe:505:2::", @a.to_s)
+    assert_equal("3ffe:505:2:1::",
+		 (@a | 0x00000000000000010000000000000000).to_s)
+  end
+
+  def test_and
+    assert_equal("3ffe:505::", (@a & @c).to_s)
+    a = @a
+    a &= @c
+    assert_equal("3ffe:505::", a.to_s)
+    assert_equal("3ffe:505:2::", @a.to_s)
+    assert_equal("3ffe:505::", (@a & 0xffffffff000000000000000000000000).to_s)
+  end
+
+  def test_shift_right
+    assert_equal("0:3ffe:505:2::", (@a >> 16).to_s)
+    a = @a
+    a >>= 16
+    assert_equal("0:3ffe:505:2::", a.to_s)
+    assert_equal("3ffe:505:2::", @a.to_s)
+  end
+
+  def test_shift_left
+    assert_equal("505:2::", (@a << 16).to_s)
+    a = @a
+    a <<= 16
+    assert_equal("505:2::", a.to_s)
+    assert_equal("3ffe:505:2::", @a.to_s)
+  end
+
+  def test_carrot
+    a = ~@in6_addr_any
+    assert_equal(IN6MASK128, a.to_s)
+    assert_equal("::", @in6_addr_any.to_s)
+  end
+
+  def test_equal
+    assert_equal(true, @a == IPAddr.new("3ffe:505:2::"))
+    assert_equal(false, @a == IPAddr.new("3ffe:505:3::"))
+    assert_equal(true, @a != IPAddr.new("3ffe:505:3::"))
+    assert_equal(false, @a != IPAddr.new("3ffe:505:2::"))
+  end
+
+  def test_mask
+    a = @a.mask(32)
+    assert_equal("3ffe:505::", a.to_s)
+    assert_equal("3ffe:505:2::", @a.to_s)
+  end
+
+  def test_include?
+    assert_equal(true, @a.include?(IPAddr.new("3ffe:505:2::")))
+    assert_equal(true, @a.include?(IPAddr.new("3ffe:505:2::1")))
+    assert_equal(false, @a.include?(IPAddr.new("3ffe:505:3::")))
+    net1 = IPAddr.new("192.168.2.0/24")
+    assert_equal(true, net1.include?(IPAddr.new("192.168.2.0")))
+    assert_equal(true, net1.include?(IPAddr.new("192.168.2.255")))
+    assert_equal(false, net1.include?(IPAddr.new("192.168.3.0")))
+    # test with integer parameter
+    int = (192 << 24) + (168 << 16) + (2 << 8) + 13
+
+    assert_equal(true, net1.include?(int))
+    assert_equal(false, net1.include?(int+255))
+
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb.rb	(revision 18425)
@@ -0,0 +1,342 @@
+#
+#   irb.rb - irb main module
+#   	$Release Version: 0.9.5 $
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#
+#
+require "e2mmap"
+
+require "irb/init"
+require "irb/context"
+require "irb/extend-command"
+#require "irb/workspace"
+
+require "irb/ruby-lex"
+require "irb/input-method"
+require "irb/locale"
+
+STDOUT.sync = true
+
+module IRB
+  @RCS_ID='-$Id: irb.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+  class Abort < Exception;end
+
+  #
+  @CONF = {}
+
+  def IRB.conf
+    @CONF
+  end
+
+  # IRB version method
+  def IRB.version
+    if v = @CONF[:VERSION] then return v end
+
+    require "irb/version"
+    rv = @RELEASE_VERSION.sub(/\.0/, "")
+    @CONF[:VERSION] = format("irb %s(%s)", rv, @LAST_UPDATE_DATE)
+  end
+
+  def IRB.CurrentContext
+    IRB.conf[:MAIN_CONTEXT]
+  end
+
+  # initialize IRB and start TOP_LEVEL irb
+  def IRB.start(ap_path = nil)
+    $0 = File::basename(ap_path, ".rb") if ap_path
+
+    IRB.setup(ap_path)
+
+    if @CONF[:SCRIPT]
+      irb = Irb.new(nil, @CONF[:SCRIPT])
+    else
+      irb = Irb.new
+    end
+
+    @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
+    @CONF[:MAIN_CONTEXT] = irb.context
+
+    trap("SIGINT") do
+      irb.signal_handle
+    end
+    
+    catch(:IRB_EXIT) do
+      irb.eval_input
+    end
+#    print "\n"
+  end
+
+  def IRB.irb_exit(irb, ret)
+    throw :IRB_EXIT, ret
+  end
+
+  def IRB.irb_abort(irb, exception = Abort)
+    if defined? Thread
+      irb.context.thread.raise exception, "abort then interrupt!!"
+    else
+      raise exception, "abort then interrupt!!"
+    end
+  end
+
+  #
+  # irb interpriter main routine 
+  #
+  class Irb
+    def initialize(workspace = nil, input_method = nil, output_method = nil)
+      @context = Context.new(self, workspace, input_method, output_method)
+      @context.main.extend ExtendCommandBundle
+      @signal_status = :IN_IRB
+
+      @scanner = RubyLex.new
+      @scanner.exception_on_syntax_error = false
+    end
+    attr_reader :context
+    attr_accessor :scanner
+
+    def eval_input
+      @scanner.set_prompt do
+	|ltype, indent, continue, line_no|
+	if ltype
+	  f = @context.prompt_s
+	elsif continue
+	  f = @context.prompt_c
+	elsif indent > 0
+	  f = @context.prompt_n
+	else @context.prompt_i
+	  f = @context.prompt_i
+	end
+	f = "" unless f
+	if @context.prompting?
+	  @context.io.prompt = p = prompt(f, ltype, indent, line_no)
+	else
+	  @context.io.prompt = p = ""
+	end
+	if @context.auto_indent_mode
+	  unless ltype
+            ind = prompt(@context.prompt_i, ltype, indent, line_no)[/.*\z/].size +
+	      indent * 2 - p.size
+	    ind += 2 if continue
+	    @context.io.prompt = p + " " * ind if ind > 0
+	  end
+	end
+      end
+       
+      @scanner.set_input(@context.io) do
+	signal_status(:IN_INPUT) do
+	  if l = @context.io.gets
+	    print l if @context.verbose?
+	  else
+	    if @context.ignore_eof? and @context.io.readable_atfer_eof?
+	      l = "\n"
+	      if @context.verbose?
+		printf "Use \"exit\" to leave %s\n", @context.ap_name
+	      end
+	    end
+	  end
+	  l
+	end
+      end
+
+      @scanner.each_top_level_statement do |line, line_no|
+	signal_status(:IN_EVAL) do
+	  begin
+            line.untaint
+	    @context.evaluate(line, line_no)
+	    output_value if @context.echo?
+	  rescue StandardError, ScriptError, Abort
+	    $! = RuntimeError.new("unknown exception raised") unless $!
+	    print $!.class, ": ", $!, "\n"
+	    if  $@[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && $!.class.to_s !~ /^IRB/
+	      irb_bug = true 
+	    else
+	      irb_bug = false
+	    end
+	    
+	    messages = []
+	    lasts = []
+	    levels = 0
+	    for m in $@
+	      m = @context.workspace.filter_backtrace(m) unless irb_bug
+	      if m
+		if messages.size < @context.back_trace_limit
+		  messages.push "\tfrom "+m
+		else
+		  lasts.push "\tfrom "+m
+		  if lasts.size > @context.back_trace_limit
+		    lasts.shift 
+		    levels += 1
+		  end
+		end
+	      end
+	    end
+	    print messages.join("\n"), "\n"
+	    unless lasts.empty?
+	      printf "... %d levels...\n", levels if levels > 0
+	      print lasts.join("\n")
+	    end
+	    print "Maybe IRB bug!!\n" if irb_bug
+	  end
+          if $SAFE > 2
+            warn "Error: irb does not work for $SAFE level higher than 2"
+            exit 1
+          end
+	end
+      end
+    end
+
+    def suspend_name(path = nil, name = nil)
+      @context.irb_path, back_path = path, @context.irb_path if path
+      @context.irb_name, back_name = name, @context.irb_name if name
+      begin
+	yield back_path, back_name
+      ensure
+	@context.irb_path = back_path if path
+	@context.irb_name = back_name if name
+      end
+    end
+
+    def suspend_workspace(workspace)
+      @context.workspace, back_workspace = workspace, @context.workspace
+      begin
+	yield back_workspace
+      ensure
+	@context.workspace = back_workspace
+      end
+    end
+
+    def suspend_input_method(input_method)
+      back_io = @context.io
+      @context.instance_eval{@io = input_method}
+      begin
+	yield back_io
+      ensure
+	@context.instance_eval{@io = back_io}
+      end
+    end
+
+    def suspend_context(context)
+      @context, back_context = context, @context
+      begin
+	yield back_context
+      ensure
+	@context = back_context
+      end
+    end
+
+    def signal_handle
+      unless @context.ignore_sigint?
+	print "\nabort!!\n" if @context.verbose?
+	exit
+      end
+
+      case @signal_status
+      when :IN_INPUT
+	print "^C\n"
+	raise RubyLex::TerminateLineInput
+      when :IN_EVAL
+	IRB.irb_abort(self)
+      when :IN_LOAD
+	IRB.irb_abort(self, LoadAbort)
+      when :IN_IRB
+	# ignore
+      else
+	# ignore other cases as well
+      end
+    end
+
+    def signal_status(status)
+      return yield if @signal_status == :IN_LOAD
+
+      signal_status_back = @signal_status
+      @signal_status = status
+      begin
+	yield
+      ensure
+	@signal_status = signal_status_back
+      end
+    end
+
+    def prompt(prompt, ltype, indent, line_no)
+      p = prompt.dup
+      p.gsub!(/%([0-9]+)?([a-zA-Z])/) do
+	case $2
+	when "N"
+	  @context.irb_name
+	when "m"
+	  @context.main.to_s
+	when "M"
+	  @context.main.inspect
+	when "l"
+	  ltype
+	when "i"
+	  if $1 
+	    format("%" + $1 + "d", indent)
+	  else
+	    indent.to_s
+	  end
+	when "n"
+	  if $1 
+	    format("%" + $1 + "d", line_no)
+	  else
+	    line_no.to_s
+	  end
+	when "%"
+	  "%"
+	end
+      end
+      p
+    end
+
+    def output_value
+      if @context.inspect?
+        printf @context.return_format, @context.last_value.inspect
+      else
+        printf @context.return_format, @context.last_value
+      end
+    end
+
+    def inspect
+      ary = []
+      for iv in instance_variables
+	case iv
+	when "@signal_status"
+	  ary.push format("%s=:%s", iv, @signal_status.id2name)
+	when "@context"
+	  ary.push format("%s=%s", iv, eval(iv).__to_s__)
+	else
+	  ary.push format("%s=%s", iv, eval(iv))
+	end
+      end
+      format("#<%s: %s>", self.class, ary.join(", "))
+    end
+  end
+
+  # Singleton method
+  def @CONF.inspect
+    IRB.version unless self[:VERSION]
+
+    array = []
+    for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name}
+      case k
+      when :MAIN_CONTEXT, :__TMP__EHV__
+	array.push format("CONF[:%s]=...myself...", k.id2name)
+      when :PROMPT
+	s = v.collect{
+	  |kk, vv|
+	  ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"}
+	  format(":%s=>{%s}", kk.id2name, ss.join(", "))
+	}
+	array.push format("CONF[:%s]={%s}", k.id2name, s.join(", "))
+      else
+	array.push format("CONF[:%s]=%s", k.id2name, v.inspect)
+      end
+    end
+    array.join("\n")
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/chws.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/chws.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/chws.rb	(revision 18425)
@@ -0,0 +1,33 @@
+#
+#   change-ws.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+require "irb/cmd/nop.rb"
+require "irb/ext/change-ws.rb"
+
+module IRB
+  module ExtendCommand
+
+    class CurrentWorkingWorkspace<Nop
+      def execute(*obj)
+	irb_context.main
+      end
+    end
+
+    class ChangeWorkspace<Nop
+      def execute(*obj)
+	irb_context.change_workspace(*obj)
+	irb_context.main
+      end
+    end
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/fork.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/fork.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/fork.rb	(revision 18425)
@@ -0,0 +1,39 @@
+#
+#   fork.rb - 
+#   	$Release Version: 0.9.5 $
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+@RCS_ID='-$Id: fork.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+
+module IRB
+  module ExtendCommand
+    class Fork<Nop
+      def execute(&block)
+	pid = send ExtendCommand.irb_original_method_name("fork")
+	unless pid 
+	  class<<self
+	    alias_method :exit, ExtendCommand.irb_original_method_name('exit')
+	  end
+	  if iterator?
+	    begin
+	      yield
+	    ensure
+	      exit
+	    end
+	  end
+	end
+	pid
+      end
+    end
+  end
+end
+
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/help.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/help.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/help.rb	(revision 18425)
@@ -0,0 +1,34 @@
+#
+#   help.rb - helper using ri
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#
+# --
+#
+#   
+#
+
+require 'rdoc/ri/ri_driver'
+
+module IRB
+  module ExtendCommand
+    module Help
+      begin
+        @ri = RiDriver.new
+      rescue SystemExit
+      else
+        def self.execute(context, *names)
+          names.each do |name|
+            begin
+              @ri.get_info_for(name.to_s)
+            rescue RiError
+              puts $!.message
+            end
+          end
+          nil
+        end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/load.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/load.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/load.rb	(revision 18425)
@@ -0,0 +1,67 @@
+#
+#   load.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+require "irb/cmd/nop.rb"
+require "irb/ext/loader"
+
+module IRB
+  module ExtendCommand
+    class Load<Nop
+      include IrbLoader
+
+      def execute(file_name, priv = nil)
+#	return ruby_load(file_name) unless IRB.conf[:USE_LOADER]
+	return irb_load(file_name, priv)
+      end
+    end
+
+    class Require<Nop
+      include IrbLoader
+      
+      def execute(file_name)
+#	return ruby_require(file_name) unless IRB.conf[:USE_LOADER]
+
+	rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
+	return false if $".find{|f| f =~ rex}
+
+	case file_name
+	when /\.rb$/
+	  begin
+	    if irb_load(file_name)
+	      $".push file_name
+	      return true
+	    end
+	  rescue LoadError
+	  end
+	when /\.(so|o|sl)$/
+	  return ruby_require(file_name)
+	end
+	
+	begin
+	  irb_load(f = file_name + ".rb")
+	  $".push f
+	  return true
+	rescue LoadError
+	  return ruby_require(file_name)
+	end
+      end
+    end
+
+    class Source<Nop
+      include IrbLoader
+      def execute(file_name)
+	source_file(file_name)
+      end
+    end
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/nop.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/nop.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/nop.rb	(revision 18425)
@@ -0,0 +1,39 @@
+#
+#   nop.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+module IRB
+  module ExtendCommand
+    class Nop
+      
+      @RCS_ID='-$Id: nop.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+      def self.execute(conf, *opts)
+	command = new(conf)
+	command.execute(*opts)
+      end
+
+      def initialize(conf)
+	@irb_context = conf
+      end
+
+      attr_reader :irb_context
+
+      def irb
+	@irb_context.irb
+      end
+
+      def execute(*opts)
+	#nop
+      end
+    end
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/pushws.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/pushws.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/pushws.rb	(revision 18425)
@@ -0,0 +1,39 @@
+#
+#   change-ws.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+require "irb/cmd/nop.rb"
+require "irb/ext/workspaces.rb"
+
+module IRB
+  module ExtendCommand
+    class Workspaces<Nop
+      def execute(*obj)
+	irb_context.workspaces.collect{|ws| ws.main}
+      end
+    end
+
+    class PushWorkspace<Workspaces
+      def execute(*obj)
+	irb_context.push_workspace(*obj)
+	super
+      end
+    end
+
+    class PopWorkspace<Workspaces
+      def execute(*obj)
+	irb_context.pop_workspace(*obj)
+	super
+      end
+    end
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/subirb.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/subirb.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/cmd/subirb.rb	(revision 18425)
@@ -0,0 +1,43 @@
+#!/usr/local/bin/ruby
+#
+#   multi.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+require "irb/cmd/nop.rb"
+require "irb/ext/multi-irb"
+
+module IRB
+  module ExtendCommand
+    class IrbCommand<Nop
+      def execute(*obj)
+	IRB.irb(nil, *obj)
+      end
+    end
+
+    class Jobs<Nop
+      def execute
+	IRB.JobManager
+      end
+    end
+
+    class Foreground<Nop
+      def execute(key)
+	IRB.JobManager.switch(key)
+      end
+    end
+
+    class Kill<Nop
+      def execute(*keys)
+	IRB.JobManager.kill(*keys)
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/completion.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/completion.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/completion.rb	(revision 18425)
@@ -0,0 +1,205 @@
+#
+#   irb/completor.rb - 
+#   	$Release Version: 0.9$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ishitsuka.com)
+#       From Original Idea of shugo@ruby-lang.org
+#
+
+require "readline"
+
+module IRB
+  module InputCompletor
+
+    @RCS_ID='-$Id: completion.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+    ReservedWords = [
+      "BEGIN", "END",
+      "alias", "and", 
+      "begin", "break", 
+      "case", "class",
+      "def", "defined", "do",
+      "else", "elsif", "end", "ensure",
+      "false", "for", 
+      "if", "in", 
+      "module", 
+      "next", "nil", "not",
+      "or", 
+      "redo", "rescue", "retry", "return",
+      "self", "super",
+      "then", "true",
+      "undef", "unless", "until",
+      "when", "while",
+      "yield",
+    ]
+      
+    CompletionProc = proc { |input|
+      bind = IRB.conf[:MAIN_CONTEXT].workspace.binding
+      
+#      puts "input: #{input}"
+
+      case input
+      when /^(\/[^\/]*\/)\.([^.]*)$/
+	# Regexp
+	receiver = $1
+	message = Regexp.quote($2)
+
+	candidates = Regexp.instance_methods(true)
+	select_message(receiver, message, candidates)
+
+      when /^([^\]]*\])\.([^.]*)$/
+	# Array
+	receiver = $1
+	message = Regexp.quote($2)
+
+	candidates = Array.instance_methods(true)
+	select_message(receiver, message, candidates)
+
+      when /^([^\}]*\})\.([^.]*)$/
+	# Proc or Hash
+	receiver = $1
+	message = Regexp.quote($2)
+
+	candidates = Proc.instance_methods(true) | Hash.instance_methods(true)
+	select_message(receiver, message, candidates)
+	
+      when /^(:[^:.]*)$/
+ 	# Symbol
+	if Symbol.respond_to?(:all_symbols)
+	  sym = $1
+	  candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name}
+	  candidates.grep(/^#{sym}/)
+	else
+	  []
+	end
+
+      when /^::([A-Z][^:\.\(]*)$/
+	# Absolute Constant or class methods
+	receiver = $1
+	candidates = Object.constants
+	candidates.grep(/^#{receiver}/).collect{|e| "::" + e}
+
+      when /^(((::)?[A-Z][^:.\(]*)+)::?([^:.]*)$/
+	# Constant or class methods
+	receiver = $1
+	message = Regexp.quote($4)
+	begin
+	  candidates = eval("#{receiver}.constants | #{receiver}.methods", bind)
+	rescue Exception
+	  candidates = []
+	end
+	candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e}
+
+      when /^(:[^:.]+)\.([^.]*)$/
+	# Symbol
+	receiver = $1
+	message = Regexp.quote($2)
+
+	candidates = Symbol.instance_methods(true)
+	select_message(receiver, message, candidates)
+
+      when /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/
+	# Numeric
+	receiver = $1
+	message = Regexp.quote($5)
+
+	begin
+	  candidates = eval(receiver, bind).methods
+	rescue Exception
+	  candidates = []
+	end
+	select_message(receiver, message, candidates)
+
+      when /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/
+	# Numeric(0xFFFF)
+	receiver = $1
+	message = Regexp.quote($2)
+
+	begin
+	  candidates = eval(receiver, bind).methods
+	rescue Exception
+	  candidates = []
+	end
+	select_message(receiver, message, candidates)
+
+      when /^(\$[^.]*)$/
+	candidates = global_variables.grep(Regexp.new(Regexp.quote($1)))
+
+#      when /^(\$?(\.?[^.]+)+)\.([^.]*)$/
+      when /^((\.?[^.]+)+)\.([^.]*)$/
+	# variable
+	receiver = $1
+	message = Regexp.quote($3)
+
+	gv = eval("global_variables", bind)
+	lv = eval("local_variables", bind)
+	cv = eval("self.class.constants", bind)
+	
+	if (gv | lv | cv).include?(receiver)
+	  # foo.func and foo is local var.
+	  candidates = eval("#{receiver}.methods", bind)
+	elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver
+	  # Foo::Bar.func
+	  begin
+	    candidates = eval("#{receiver}.methods", bind)
+	  rescue Exception
+	    candidates = []
+	  end
+	else
+	  # func1.func2
+	  candidates = []
+	  ObjectSpace.each_object(Module){|m|
+	    begin
+	      name = m.name
+	    rescue Exception
+	      name = ""
+	    end
+	    next if name != "IRB::Context" and 
+	      /^(IRB|SLex|RubyLex|RubyToken)/ =~ name
+	    candidates.concat m.instance_methods(false)
+	  }
+	  candidates.sort!
+	  candidates.uniq!
+	end
+	select_message(receiver, message, candidates)
+
+      when /^\.([^.]*)$/
+	# unknown(maybe String)
+
+	receiver = ""
+	message = Regexp.quote($1)
+
+	candidates = String.instance_methods(true)
+	select_message(receiver, message, candidates)
+
+      else
+	candidates = eval("methods | private_methods | local_variables | self.class.constants", bind)
+			  
+	(candidates|ReservedWords).grep(/^#{Regexp.quote(input)}/)
+      end
+    }
+
+    Operators = ["%", "&", "*", "**", "+",  "-",  "/",
+      "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
+      "[]", "[]=", "^",]
+
+    def self.select_message(receiver, message, candidates)
+      candidates.grep(/^#{message}/).collect do |e|
+	case e
+	when /^[a-zA-Z_]/
+	  receiver + "." + e
+	when /^[0-9]/
+	when *Operators
+	  #receiver + " " + e
+	end
+      end
+    end
+  end
+end
+
+if Readline.respond_to?("basic_word_break_characters=")
+  Readline.basic_word_break_characters= " \t\n\"\\'`><=;|&{("
+end
+Readline.completion_append_character = nil
+Readline.completion_proc = IRB::InputCompletor::CompletionProc
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/context.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/context.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/context.rb	(revision 18425)
@@ -0,0 +1,255 @@
+#
+#   irb/context.rb - irb context
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+require "irb/workspace"
+
+module IRB
+  class Context
+    #
+    # Arguments:
+    #   input_method: nil -- stdin or readline
+    #		      String -- File
+    #		      other -- using this as InputMethod
+    #
+    def initialize(irb, workspace = nil, input_method = nil, output_method = nil)
+      @irb = irb
+      if workspace
+	@workspace = workspace
+      else
+	@workspace = WorkSpace.new
+      end
+      @thread = Thread.current if defined? Thread
+#      @irb_level = 0
+
+      # copy of default configuration
+      @ap_name = IRB.conf[:AP_NAME]
+      @rc = IRB.conf[:RC]
+      @load_modules = IRB.conf[:LOAD_MODULES]
+
+      @use_readline = IRB.conf[:USE_READLINE]
+      @inspect_mode = IRB.conf[:INSPECT_MODE]
+
+      self.math_mode = IRB.conf[:MATH_MODE] if IRB.conf[:MATH_MODE]
+      self.use_tracer = IRB.conf[:USE_TRACER] if IRB.conf[:USE_TRACER]
+      self.use_loader = IRB.conf[:USE_LOADER] if IRB.conf[:USE_LOADER]
+      self.eval_history = IRB.conf[:EVAL_HISTORY] if IRB.conf[:EVAL_HISTORY]
+
+      @ignore_sigint = IRB.conf[:IGNORE_SIGINT]
+      @ignore_eof = IRB.conf[:IGNORE_EOF]
+
+      @back_trace_limit = IRB.conf[:BACK_TRACE_LIMIT]
+      
+      self.prompt_mode = IRB.conf[:PROMPT_MODE]
+
+      if IRB.conf[:SINGLE_IRB] or !defined?(JobManager)
+	@irb_name = IRB.conf[:IRB_NAME]
+      else
+	@irb_name = "irb#"+IRB.JobManager.n_jobs.to_s
+      end
+      @irb_path = "(" + @irb_name + ")"
+
+      case input_method
+      when nil
+	case use_readline?
+	when nil
+	  if (defined?(ReadlineInputMethod) && STDIN.tty? &&
+	      IRB.conf[:PROMPT_MODE] != :INF_RUBY)
+	    @io = ReadlineInputMethod.new
+	  else
+	    @io = StdioInputMethod.new
+	  end
+	when false
+	  @io = StdioInputMethod.new
+	when true
+	  if defined?(ReadlineInputMethod)
+	    @io = ReadlineInputMethod.new
+	  else
+	    @io = StdioInputMethod.new
+	  end
+	end
+
+      when String
+	@io = FileInputMethod.new(input_method)
+	@irb_name = File.basename(input_method)
+	@irb_path = input_method
+      else
+	@io = input_method
+      end
+      self.save_history = IRB.conf[:SAVE_HISTORY] if IRB.conf[:SAVE_HISTORY]
+
+      if output_method
+	@output_method = output_method
+      else
+	@output_method = StdioOutputMethod.new
+      end
+
+      @verbose = IRB.conf[:VERBOSE] 
+      @echo = IRB.conf[:ECHO]
+      if @echo.nil?
+	@echo = true
+      end
+      @debug_level = IRB.conf[:DEBUG_LEVEL]
+    end
+
+    def main
+      @workspace.main
+    end
+
+    attr_reader :workspace_home
+    attr_accessor :workspace
+    attr_reader :thread
+    attr_accessor :io
+    
+    attr_accessor :irb
+    attr_accessor :ap_name
+    attr_accessor :rc
+    attr_accessor :load_modules
+    attr_accessor :irb_name
+    attr_accessor :irb_path
+
+    attr_reader :use_readline
+    attr_reader :inspect_mode
+
+    attr_reader :prompt_mode
+    attr_accessor :prompt_i
+    attr_accessor :prompt_s
+    attr_accessor :prompt_c
+    attr_accessor :prompt_n
+    attr_accessor :auto_indent_mode
+    attr_accessor :return_format
+
+    attr_accessor :ignore_sigint
+    attr_accessor :ignore_eof
+    attr_accessor :echo
+    attr_accessor :verbose
+    attr_reader :debug_level
+
+    attr_accessor :back_trace_limit
+
+    alias use_readline? use_readline
+    alias rc? rc
+    alias ignore_sigint? ignore_sigint
+    alias ignore_eof? ignore_eof
+    alias echo? echo
+
+    def verbose?
+      if @verbose.nil?
+	if defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod) 
+	  false
+	elsif !STDIN.tty? or @io.kind_of?(FileInputMethod)
+	  true
+	else
+	  false
+	end
+      end
+    end
+
+    def prompting?
+      verbose? || (STDIN.tty? && @io.kind_of?(StdioInputMethod) ||
+		(defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod)))
+    end
+
+    attr_reader :last_value
+
+    def set_last_value(value)
+      @last_value = value
+      @workspace.evaluate self, "_ = IRB.CurrentContext.last_value"
+    end
+
+    attr_reader :irb_name
+
+    def prompt_mode=(mode)
+      @prompt_mode = mode
+      pconf = IRB.conf[:PROMPT][mode]
+      @prompt_i = pconf[:PROMPT_I]
+      @prompt_s = pconf[:PROMPT_S]
+      @prompt_c = pconf[:PROMPT_C]
+      @prompt_n = pconf[:PROMPT_N]
+      @return_format = pconf[:RETURN]
+      if ai = pconf.include?(:AUTO_INDENT)
+	@auto_indent_mode = ai
+      else
+	@auto_indent_mode = IRB.conf[:AUTO_INDENT]
+      end
+    end
+    
+    def inspect?
+      @inspect_mode.nil? or @inspect_mode
+    end
+
+    def file_input?
+      @io.class == FileInputMethod
+    end
+
+    def inspect_mode=(opt)
+      if opt
+	@inspect_mode = opt
+      else
+	@inspect_mode = !@inspect_mode
+      end
+      print "Switch to#{unless @inspect_mode; ' non';end} inspect mode.\n" if verbose?
+      @inspect_mode
+    end
+
+    def use_readline=(opt)
+      @use_readline = opt
+      print "use readline module\n" if @use_readline
+    end
+
+    def debug_level=(value)
+      @debug_level = value
+      RubyLex.debug_level = value
+      SLex.debug_level = value
+    end
+
+    def debug?
+      @debug_level > 0
+    end
+
+    def evaluate(line, line_no)
+      @line_no = line_no
+      set_last_value(@workspace.evaluate(self, line, irb_path, line_no))
+#      @workspace.evaluate("_ = IRB.conf[:MAIN_CONTEXT]._")
+#      @_ = @workspace.evaluate(line, irb_path, line_no)
+    end
+
+    alias __exit__ exit
+    def exit(ret = 0)
+      IRB.irb_exit(@irb, ret)
+    end
+
+    NOPRINTING_IVARS = ["@last_value"]
+    NO_INSPECTING_IVARS = ["@irb", "@io"]
+    IDNAME_IVARS = ["@prompt_mode"]
+
+    alias __inspect__ inspect
+    def inspect
+      array = []
+      for ivar in instance_variables.sort{|e1, e2| e1 <=> e2}
+	name = ivar.sub(/^@(.*)$/){$1}
+	val = instance_eval(ivar)
+	case ivar
+	when *NOPRINTING_IVARS
+	  array.push format("conf.%s=%s", name, "...")
+	when *NO_INSPECTING_IVARS
+	  array.push format("conf.%s=%s", name, val.to_s)
+	when *IDNAME_IVARS
+	  array.push format("conf.%s=:%s", name, val.id2name)
+	else
+	  array.push format("conf.%s=%s", name, val.inspect)
+	end
+      end
+      array.join("\n")
+    end
+    alias __to_s__ to_s
+    alias to_s inspect
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/change-ws.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/change-ws.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/change-ws.rb	(revision 18425)
@@ -0,0 +1,62 @@
+#
+#   irb/ext/cb.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+module IRB
+  class Context
+
+    def home_workspace
+      if defined? @home_workspace
+	@home_workspace
+      else
+	@home_workspace = @workspace
+      end
+    end
+
+    def change_workspace(*_main)
+      if _main.empty?
+	@workspace = home_workspace 
+	return main
+      end
+      
+      @workspace = WorkSpace.new(_main[0])
+      
+      if !(class<<main;ancestors;end).include?(ExtendCommandBundle)
+	main.extend ExtendCommandBundle
+      end
+    end
+
+#     def change_binding(*_main)
+#       back = @workspace
+#       @workspace = WorkSpace.new(*_main)
+#       unless _main.empty?
+# 	begin
+# 	  main.extend ExtendCommandBundle
+# 	rescue
+# 	  print "can't change binding to: ", main.inspect, "\n"
+# 	  @workspace = back
+# 	  return nil
+# 	end
+#       end
+#       @irb_level += 1
+#       begin
+# 	catch(:SU_EXIT) do
+# 	  @irb.eval_input
+# 	end
+#       ensure
+# 	@irb_level -= 1
+#  	@workspace = back
+#       end
+#     end
+#     alias change_workspace change_binding
+   end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/history.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/history.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/history.rb	(revision 18425)
@@ -0,0 +1,110 @@
+#
+#   history.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+module IRB
+
+  class Context
+
+    NOPRINTING_IVARS.push "@eval_history_values"
+
+    alias _set_last_value set_last_value
+
+    def set_last_value(value)
+      _set_last_value(value)
+
+#      @workspace.evaluate self, "_ = IRB.CurrentContext.last_value"
+      if @eval_history #and !@eval_history_values.equal?(llv)
+ 	@eval_history_values.push @line_no, @last_value
+ 	@workspace.evaluate self, "__ = IRB.CurrentContext.instance_eval{@eval_history_values}"
+      end
+
+      @last_value
+    end
+
+    attr_reader :eval_history
+    def eval_history=(no)
+      if no
+	if defined?(@eval_history) && @eval_history
+	  @eval_history_values.size(no)
+	else
+	  @eval_history_values = History.new(no)
+	  IRB.conf[:__TMP__EHV__] = @eval_history_values
+	  @workspace.evaluate(self, "__ = IRB.conf[:__TMP__EHV__]")
+	  IRB.conf.delete(:__TMP_EHV__)
+	end
+      else
+	@eval_history_values = nil
+      end
+      @eval_history = no
+    end
+  end
+
+  class History
+    @RCS_ID='-$Id: history.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+    def initialize(size = 16)
+      @size = size
+      @contents = []
+    end
+
+    def size(size)
+      if size != 0 && size < @size 
+	@contents = @contents[@size - size .. @size]
+      end
+      @size = size
+    end
+
+    def [](idx)
+      begin
+	if idx >= 0
+	  @contents.find{|no, val| no == idx}[1]
+	else
+	  @contents[idx][1]
+	end
+      rescue NameError
+	nil
+      end
+    end
+
+    def push(no, val)
+      @contents.push [no, val]
+      @contents.shift if @size != 0 && @contents.size > @size
+    end
+    
+    alias real_inspect inspect
+
+    def inspect
+      if @contents.empty?
+	return real_inspect
+      end
+
+      unless (last = @contents.pop)[1].equal?(self)
+	@contents.push last
+	last = nil
+      end
+      str = @contents.collect{|no, val|
+	if val.equal?(self)
+	  "#{no} ...self-history..."
+	else
+	  "#{no} #{val.inspect}"
+	end
+      }.join("\n")
+      if str == ""
+	str = "Empty."
+      end
+      @contents.push last if last
+      str
+    end
+  end
+end
+
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/loader.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/loader.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/loader.rb	(revision 18425)
@@ -0,0 +1,120 @@
+#
+#   loader.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+
+module IRB
+  class LoadAbort < Exception;end
+
+  module IrbLoader
+    @RCS_ID='-$Id: loader.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+    alias ruby_load load
+    alias ruby_require require
+
+    def irb_load(fn, priv = nil)
+      path = search_file_from_ruby_path(fn)
+      raise LoadError, "No such file to load -- #{fn}" unless path
+
+      load_file(path, priv)
+    end
+
+    def search_file_from_ruby_path(fn)
+      if /^#{Regexp.quote(File::Separator)}/ =~ fn
+	return fn if File.exist?(fn)
+	return nil
+      end
+
+      for path in $:
+	if File.exist?(f = File.join(path, fn))
+	  return f
+	end
+      end
+      return nil
+    end
+
+    def source_file(path)
+      irb.suspend_name(path, File.basename(path)) do
+	irb.suspend_input_method(FileInputMethod.new(path)) do
+	  |back_io|
+	  irb.signal_status(:IN_LOAD) do 
+	    if back_io.kind_of?(FileInputMethod)
+	      irb.eval_input
+	    else
+	      begin
+		irb.eval_input
+	      rescue LoadAbort
+		print "load abort!!\n"
+	      end
+	    end
+	  end
+	end
+      end
+    end
+
+    def load_file(path, priv = nil)
+      irb.suspend_name(path, File.basename(path)) do
+	
+	if priv
+	  ws = WorkSpace.new(Module.new)
+	else
+	  ws = WorkSpace.new
+	end
+	irb.suspend_workspace(ws) do
+	  irb.suspend_input_method(FileInputMethod.new(path)) do
+	    |back_io|
+	    irb.signal_status(:IN_LOAD) do 
+#	      p irb.conf
+	      if back_io.kind_of?(FileInputMethod)
+		irb.eval_input
+	      else
+		begin
+		  irb.eval_input
+		rescue LoadAbort
+		  print "load abort!!\n"
+		end
+	      end
+	    end
+	  end
+	end
+      end
+    end
+
+    def old
+      back_io = @io
+      back_path = @irb_path
+      back_name = @irb_name
+      back_scanner = @irb.scanner
+      begin
+ 	@io = FileInputMethod.new(path)
+ 	@irb_name = File.basename(path)
+	@irb_path = path
+	@irb.signal_status(:IN_LOAD) do
+	  if back_io.kind_of?(FileInputMethod)
+	    @irb.eval_input
+	  else
+	    begin
+	      @irb.eval_input
+	    rescue LoadAbort
+	      print "load abort!!\n"
+	    end
+	  end
+	end
+      ensure
+ 	@io = back_io
+ 	@irb_name = back_name
+ 	@irb_path = back_path
+	@irb.scanner = back_scanner
+      end
+    end
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/math-mode.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/math-mode.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/math-mode.rb	(revision 18425)
@@ -0,0 +1,37 @@
+#
+#   math-mode.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+require "mathn"
+
+module IRB
+  class Context
+    attr_reader :math_mode
+    alias math? math_mode
+
+    def math_mode=(opt)
+      if @math_mode == true && opt == false
+	IRB.fail CantReturnToNormalMode
+	return
+      end
+
+      @math_mode = opt
+      if math_mode
+	main.extend Math
+	print "start math mode\n" if verbose?
+      end
+    end
+
+    def inspect?
+      @inspect_mode.nil? && !@math_mode or @inspect_mode
+    end
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/multi-irb.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/multi-irb.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/multi-irb.rb	(revision 18425)
@@ -0,0 +1,241 @@
+#
+#   irb/multi-irb.rb - multiple irb module
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+IRB.fail CantShiftToMultiIrbMode unless defined?(Thread)
+require "thread"
+
+module IRB
+  # job management class
+  class JobManager
+    @RCS_ID='-$Id: multi-irb.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+    def initialize
+      # @jobs = [[thread, irb],...]
+      @jobs = []
+      @current_job = nil
+    end
+
+    attr_accessor :current_job
+
+    def n_jobs
+      @jobs.size
+    end
+
+    def thread(key)
+      th, irb = search(key)
+      th
+    end
+
+    def irb(key)
+      th, irb = search(key)
+      irb
+    end
+
+    def main_thread
+      @jobs[0][0]
+    end
+
+    def main_irb
+      @jobs[0][1]
+    end
+
+    def insert(irb)
+      @jobs.push [Thread.current, irb]
+    end
+
+    def switch(key)
+      th, irb = search(key)
+      IRB.fail IrbAlreadyDead unless th.alive?
+      IRB.fail IrbSwitchedToCurrentThread if th == Thread.current
+      @current_job = irb
+      th.run
+      Thread.stop
+      @current_job = irb(Thread.current)
+    end
+
+    def kill(*keys)
+      for key in keys
+	th, irb = search(key)
+	IRB.fail IrbAlreadyDead unless th.alive?
+	th.exit
+      end
+    end    
+
+    def search(key)
+      case key
+      when Integer
+	@jobs[key]
+      when Irb
+	@jobs.find{|k, v| v.equal?(key)}
+      when Thread
+	@jobs.assoc(key)
+      else
+	assoc = @jobs.find{|k, v| v.context.main.equal?(key)}
+	IRB.fail NoSuchJob, key if assoc.nil?
+	assoc
+      end
+    end
+
+    def delete(key)
+      case key
+      when Integer
+	IRB.fail NoSuchJob, key unless @jobs[key]
+	@jobs[key] = nil
+      else
+	catch(:EXISTS) do
+	  @jobs.each_index do
+	    |i|
+	    if @jobs[i] and (@jobs[i][0] == key ||
+			     @jobs[i][1] == key ||
+			     @jobs[i][1].context.main.equal?(key))
+	      @jobs[i] = nil
+	      throw :EXISTS
+	    end
+	  end
+	  IRB.fail NoSuchJob, key
+	end
+      end
+      until assoc = @jobs.pop; end unless @jobs.empty?
+      @jobs.push assoc
+    end
+
+    def inspect
+      ary = []
+      @jobs.each_index do
+	|i|
+	th, irb = @jobs[i]
+	next if th.nil?
+
+	if th.alive?
+	  if th.stop?
+	    t_status = "stop"
+	  else
+	    t_status = "running"
+	  end
+	else
+	  t_status = "exited"
+	end
+	ary.push format("#%d->%s on %s (%s: %s)",
+			i, 
+			irb.context.irb_name, 
+			irb.context.main,
+			th,
+			t_status)
+      end
+      ary.join("\n")
+    end
+  end
+
+  @JobManager = JobManager.new
+
+  def IRB.JobManager
+    @JobManager
+  end
+
+  def IRB.CurrentContext
+    IRB.JobManager.irb(Thread.current).context
+  end
+
+  # invoke multi-irb 
+  def IRB.irb(file = nil, *main)
+    workspace = WorkSpace.new(*main)
+    parent_thread = Thread.current
+    Thread.start do
+      begin
+	irb = Irb.new(workspace, file)
+      rescue 
+	print "Subirb can't start with context(self): ", workspace.main.inspect, "\n"
+	print "return to main irb\n"
+	Thread.pass
+	Thread.main.wakeup
+	Thread.exit
+      end
+      @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
+      @JobManager.insert(irb)
+      @JobManager.current_job = irb
+      begin
+	system_exit = false
+	catch(:IRB_EXIT) do
+	  irb.eval_input
+	end
+      rescue SystemExit
+	system_exit = true
+	raise
+	#fail
+      ensure
+	unless system_exit
+	  @JobManager.delete(irb)
+	  if parent_thread.alive?
+	    @JobManager.current_job = @JobManager.irb(parent_thread)
+	    parent_thread.run
+	  else
+	    @JobManager.current_job = @JobManager.main_irb
+	    @JobManager.main_thread.run
+	  end
+	end
+      end
+    end
+    Thread.stop
+    @JobManager.current_job = @JobManager.irb(Thread.current)
+  end
+
+#   class Context
+#     def set_last_value(value)
+#       @last_value = value
+#       @workspace.evaluate "_ = IRB.JobManager.irb(Thread.current).context.last_value"
+#       if @eval_history #and !@__.equal?(@last_value)
+# 	@eval_history_values.push @line_no, @last_value
+# 	@workspace.evaluate "__ = IRB.JobManager.irb(Thread.current).context.instance_eval{@eval_history_values}"
+#       end
+#       @last_value
+#     end
+#   end
+
+#  module ExtendCommand
+#     def irb_context
+#       IRB.JobManager.irb(Thread.current).context
+#     end
+# #    alias conf irb_context
+#   end
+
+  @CONF[:SINGLE_IRB_MODE] = false
+  @JobManager.insert(@CONF[:MAIN_CONTEXT].irb)
+  @JobManager.current_job = @CONF[:MAIN_CONTEXT].irb
+
+  class Irb
+    def signal_handle
+      unless @context.ignore_sigint?
+	print "\nabort!!\n" if @context.verbose?
+	exit
+      end
+
+      case @signal_status
+      when :IN_INPUT
+	print "^C\n"
+	IRB.JobManager.thread(self).raise RubyLex::TerminateLineInput
+      when :IN_EVAL
+	IRB.irb_abort(self)
+      when :IN_LOAD
+	IRB.irb_abort(self, LoadAbort)
+      when :IN_IRB
+	# ignore
+      else
+	# ignore other cases as well
+      end
+    end
+  end
+
+  trap("SIGINT") do
+    @JobManager.current_job.signal_handle
+    Thread.stop
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/save-history.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/save-history.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/save-history.rb	(revision 18425)
@@ -0,0 +1,85 @@
+#!/usr/local/bin/ruby
+#
+#   save-history.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKAkeiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+require "readline"
+
+module IRB
+  module HistorySavingAbility
+    @RCS_ID='-$Id: save-history.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+  end
+
+  class Context
+    def init_save_history
+      unless (class<<@io;self;end).include?(HistorySavingAbility)
+	@io.extend(HistorySavingAbility)
+      end
+    end
+
+    def save_history
+      IRB.conf[:SAVE_HISTORY]
+    end
+
+    def save_history=(val)
+      IRB.conf[:SAVE_HISTORY] = val
+      if val
+	main_context = IRB.conf[:MAIN_CONTEXT]
+	main_context = self unless main_context
+	main_context.init_save_history
+      end
+    end
+
+    def history_file
+      IRB.conf[:HISTORY_FILE]
+    end
+
+    def history_file=(hist)
+      IRB.conf[:HISTORY_FILE] = hist
+    end
+  end
+
+  module HistorySavingAbility
+    include Readline
+
+    def HistorySavingAbility.create_finalizer
+      proc do
+	if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) > 0
+	  if hf = IRB.conf[:HISTORY_FILE]
+	    file = File.expand_path(hf)
+	  end
+	  file = IRB.rc_file("_history") unless file
+	  open(file, 'w' ) do |f|
+	    hist = HISTORY.to_a
+	    f.puts(hist[-num..-1] || hist)
+	  end
+	end
+      end
+    end
+
+    def HistorySavingAbility.extended(obj)
+      ObjectSpace.define_finalizer(obj, HistorySavingAbility.create_finalizer)
+      obj.load_history
+      obj
+    end
+
+    def load_history
+      hist = IRB.conf[:HISTORY_FILE]
+      hist = IRB.rc_file("_history") unless hist
+      if File.exist?(hist)
+	open(hist) do |f|
+	  f.each {|l| HISTORY << l.chomp}
+	end
+      end
+    end
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/tracer.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/tracer.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/tracer.rb	(revision 18425)
@@ -0,0 +1,61 @@
+#
+#   irb/lib/tracer.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+require "tracer"
+
+module IRB
+
+  # initialize tracing function
+  def IRB.initialize_tracer
+    Tracer.verbose = false
+    Tracer.add_filter {
+      |event, file, line, id, binding, *rests|
+      /^#{Regexp.quote(@CONF[:IRB_LIB_PATH])}/ !~ file and
+	File::basename(file) != "irb.rb"
+    }
+  end
+
+  class Context
+    attr_reader :use_tracer
+    alias use_tracer? use_tracer
+
+    def use_tracer=(opt)
+      if opt
+	Tracer.set_get_line_procs(@irb_path) {
+	  |line_no, *rests|
+	  @io.line(line_no)
+	}
+      elsif !opt && @use_tracer
+	Tracer.off
+      end
+      @use_tracer=opt
+    end
+  end
+
+  class WorkSpace
+    alias __evaluate__ evaluate
+    def evaluate(context, statements, file = nil, line = nil)
+      if context.use_tracer? && file != nil && line != nil
+	Tracer.on 
+	begin
+	  __evaluate__(context, statements, file, line)
+	ensure
+	  Tracer.off
+	end
+      else
+	__evaluate__(context, statements, file || __FILE__, line || __LINE__)
+      end
+    end
+  end
+
+  IRB.initialize_tracer
+end
+	
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/use-loader.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/use-loader.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/use-loader.rb	(revision 18425)
@@ -0,0 +1,65 @@
+#
+#   use-loader.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+require "irb/cmd/load"
+require "irb/ext/loader"
+
+class Object
+  alias __original__load__IRB_use_loader__ load
+  alias __original__require__IRB_use_loader__ require
+end
+
+module IRB
+  module ExtendCommandBundle
+    def irb_load(*opts, &b)
+      ExtendCommand::Load.execute(irb_context, *opts, &b)
+    end
+    def irb_require(*opts, &b)
+      ExtendCommand::Require.execute(irb_context, *opts, &b)
+    end
+  end
+
+  class Context
+
+    IRB.conf[:USE_LOADER] = false
+    
+    def use_loader
+      IRB.conf[:USE_LOADER]
+    end
+
+    alias use_loader? use_loader
+
+    def use_loader=(opt)
+
+      if IRB.conf[:USE_LOADER] != opt
+	IRB.conf[:USE_LOADER] = opt
+	if opt
+	  if !$".include?("irb/cmd/load")
+	  end
+	  (class<<@workspace.main;self;end).instance_eval {
+	    alias_method :load, :irb_load
+	    alias_method :require, :irb_require
+	  }
+	else
+	  (class<<@workspace.main;self;end).instance_eval {
+	    alias_method :load, :__original__load__IRB_use_loader__
+	    alias_method :require, :__original__require__IRB_use_loader__
+	  }
+	end
+      end
+      print "Switch to load/require#{unless use_loader; ' non';end} trace mode.\n" if verbose?
+      opt
+    end
+  end
+end
+
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/workspaces.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/workspaces.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ext/workspaces.rb	(revision 18425)
@@ -0,0 +1,56 @@
+#
+#   push-ws.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+module IRB
+  class Context
+
+    def irb_level
+      workspace_stack.size
+    end
+
+    def workspaces
+      if defined? @workspaces
+	@workspaces
+      else
+	@workspaces = []
+      end
+    end
+
+    def push_workspace(*_main)
+      if _main.empty?
+	if workspaces.empty?
+	  print "No other workspace\n"
+	  return nil
+	end
+	ws = workspaces.pop
+	workspaces.push @workspace
+	@workspace = ws
+	return workspaces
+      end
+
+      workspaces.push @workspace
+      @workspace = WorkSpace.new(@workspace.binding, _main[0])
+      if !(class<<main;ancestors;end).include?(ExtendCommandBundle)
+	main.extend ExtendCommandBundle
+      end
+    end
+
+    def pop_workspace
+      if workspaces.empty?
+	print "workspace stack empty\n"
+	return
+      end
+      @workspace = workspaces.pop
+    end
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/extend-command.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/extend-command.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/extend-command.rb	(revision 18425)
@@ -0,0 +1,264 @@
+#
+#   irb/extend-command.rb - irb extend command 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+module IRB
+  #
+  # IRB extended command
+  #
+  module ExtendCommandBundle
+    EXCB = ExtendCommandBundle
+
+    NO_OVERRIDE = 0
+    OVERRIDE_PRIVATE_ONLY = 0x01
+    OVERRIDE_ALL = 0x02
+
+    def irb_exit(ret = 0)
+      irb_context.exit(ret)
+    end
+
+    def irb_context
+      IRB.CurrentContext
+    end
+
+    @ALIASES = [
+      [:context, :irb_context, NO_OVERRIDE],
+      [:conf, :irb_context, NO_OVERRIDE],
+      [:irb_quit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
+      [:exit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
+      [:quit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
+    ]
+
+    @EXTEND_COMMANDS = [
+      [:irb_current_working_workspace, :CurrentWorkingWorkspace, "irb/cmd/chws",
+	[:irb_print_working_workspace, OVERRIDE_ALL],
+	[:irb_cwws, OVERRIDE_ALL],
+	[:irb_pwws, OVERRIDE_ALL],
+#	[:irb_cww, OVERRIDE_ALL],
+#	[:irb_pww, OVERRIDE_ALL],
+	[:cwws, NO_OVERRIDE],
+	[:pwws, NO_OVERRIDE],
+#	[:cww, NO_OVERRIDE],
+#	[:pww, NO_OVERRIDE],
+	[:irb_current_working_binding, OVERRIDE_ALL],
+	[:irb_print_working_binding, OVERRIDE_ALL],
+	[:irb_cwb, OVERRIDE_ALL],
+	[:irb_pwb, OVERRIDE_ALL],
+#	[:cwb, NO_OVERRIDE],
+#	[:pwb, NO_OVERRIDE]
+      ],
+      [:irb_change_workspace, :ChangeWorkspace, "irb/cmd/chws",
+	[:irb_chws, OVERRIDE_ALL],
+#	[:irb_chw, OVERRIDE_ALL],
+	[:irb_cws, OVERRIDE_ALL],
+#	[:irb_cw, OVERRIDE_ALL],
+	[:chws, NO_OVERRIDE],
+#	[:chw, NO_OVERRIDE],
+	[:cws, NO_OVERRIDE],
+#	[:cw, NO_OVERRIDE],
+	[:irb_change_binding, OVERRIDE_ALL],
+	[:irb_cb, OVERRIDE_ALL],
+	[:cb, NO_OVERRIDE]],
+
+      [:irb_workspaces, :Workspaces, "irb/cmd/pushws",
+	[:workspaces, NO_OVERRIDE],
+	[:irb_bindings, OVERRIDE_ALL],
+	[:bindings, NO_OVERRIDE]],
+      [:irb_push_workspace, :PushWorkspace, "irb/cmd/pushws",
+	[:irb_pushws, OVERRIDE_ALL],
+#	[:irb_pushw, OVERRIDE_ALL],
+	[:pushws, NO_OVERRIDE],
+#	[:pushw, NO_OVERRIDE],
+	[:irb_push_binding, OVERRIDE_ALL],
+	[:irb_pushb, OVERRIDE_ALL],
+	[:pushb, NO_OVERRIDE]],
+      [:irb_pop_workspace, :PopWorkspace, "irb/cmd/pushws",
+	[:irb_popws, OVERRIDE_ALL],
+#	[:irb_popw, OVERRIDE_ALL],
+	[:popws, NO_OVERRIDE],
+#	[:popw, NO_OVERRIDE],
+	[:irb_pop_binding, OVERRIDE_ALL],
+	[:irb_popb, OVERRIDE_ALL],
+	[:popb, NO_OVERRIDE]],
+
+      [:irb_load, :Load, "irb/cmd/load"],
+      [:irb_require, :Require, "irb/cmd/load"],
+      [:irb_source, :Source, "irb/cmd/load", 
+	[:source, NO_OVERRIDE]],
+
+      [:irb, :IrbCommand, "irb/cmd/subirb"],
+      [:irb_jobs, :Jobs, "irb/cmd/subirb", 
+	[:jobs, NO_OVERRIDE]],
+      [:irb_fg, :Foreground, "irb/cmd/subirb", 
+	[:fg, NO_OVERRIDE]],
+      [:irb_kill, :Kill, "irb/cmd/subirb", 
+	[:kill, OVERRIDE_PRIVATE_ONLY]],
+
+      [:irb_help, :Help, "irb/cmd/help",
+        [:help, NO_OVERRIDE]],
+
+    ]
+
+    def self.install_extend_commands
+      for args in @EXTEND_COMMANDS
+	def_extend_command(*args)
+      end
+    end
+
+    # aliases = [commans_alias, flag], ...
+    def self.def_extend_command(cmd_name, cmd_class, load_file = nil, *aliases)
+      case cmd_class
+      when Symbol
+	cmd_class = cmd_class.id2name
+      when String
+      when Class
+	cmd_class = cmd_class.name
+      end
+
+      if load_file
+	eval %[
+	  def #{cmd_name}(*opts, &b)
+	    require "#{load_file}"
+	    eval %[
+	      def #{cmd_name}(*opts, &b)
+		ExtendCommand::#{cmd_class}.execute(irb_context, *opts, &b)
+	      end
+	    ]
+	    send :#{cmd_name}, *opts, &b
+	  end
+	]
+      else
+	eval %[
+	  def #{cmd_name}(*opts, &b)
+	    ExtendCommand::#{cmd_class}.execute(irb_context, *opts, &b)
+	  end
+	]
+      end
+
+      for ali, flag in aliases
+	@ALIASES.push [ali, cmd_name, flag]
+      end
+    end
+
+    # override = {NO_OVERRIDE, OVERRIDE_PRIVATE_ONLY, OVERRIDE_ALL}
+    def install_alias_method(to, from, override = NO_OVERRIDE)
+      to = to.id2name unless to.kind_of?(String)
+      from = from.id2name unless from.kind_of?(String)
+
+      if override == OVERRIDE_ALL or
+	  (override == OVERRIDE_PRIVATE_ONLY) && !respond_to?(to) or
+	  (override == NO_OVERRIDE) &&  !respond_to?(to, true)
+	target = self
+	(class<<self;self;end).instance_eval{
+	  if target.respond_to?(to, true) && 
+	      !target.respond_to?(EXCB.irb_original_method_name(to), true)
+	    alias_method(EXCB.irb_original_method_name(to), to) 
+	  end
+	  alias_method to, from
+	}
+      else
+	print "irb: warn: can't alias #{to} from #{from}.\n"
+      end
+    end
+
+    def self.irb_original_method_name(method_name)
+      "irb_" + method_name + "_org"
+    end
+
+    def self.extend_object(obj)
+      unless (class<<obj;ancestors;end).include?(EXCB)
+	super
+	for ali, com, flg in @ALIASES
+	  obj.install_alias_method(ali, com, flg)
+	end
+      end
+    end
+
+    install_extend_commands
+  end
+
+  # extension support for Context
+  module ContextExtender
+    CE = ContextExtender
+
+    @EXTEND_COMMANDS = [
+      [:eval_history=, "irb/ext/history.rb"],
+      [:use_tracer=, "irb/ext/tracer.rb"],
+      [:math_mode=, "irb/ext/math-mode.rb"],
+      [:use_loader=, "irb/ext/use-loader.rb"],
+      [:save_history=, "irb/ext/save-history.rb"],
+    ]
+
+    def self.install_extend_commands
+      for args in @EXTEND_COMMANDS
+	def_extend_command(*args)
+      end
+    end
+
+    def self.def_extend_command(cmd_name, load_file, *aliases)
+      Context.module_eval %[
+        def #{cmd_name}(*opts, &b)
+	  Context.module_eval {remove_method(:#{cmd_name})}
+	  require "#{load_file}"
+	  send :#{cmd_name}, *opts, &b
+	end
+	for ali in aliases
+	  alias_method ali, cmd_name
+	end
+      ]
+    end
+
+    CE.install_extend_commands
+  end
+
+  module MethodExtender
+    def def_pre_proc(base_method, extend_method)
+      base_method = base_method.to_s
+      extend_method = extend_method.to_s
+
+      alias_name = new_alias_name(base_method)
+      module_eval %[
+        alias_method alias_name, base_method
+        def #{base_method}(*opts)
+	  send :#{extend_method}, *opts
+	  send :#{alias_name}, *opts
+	end
+      ]
+    end
+
+    def def_post_proc(base_method, extend_method)
+      base_method = base_method.to_s
+      extend_method = extend_method.to_s
+
+      alias_name = new_alias_name(base_method)
+      module_eval %[
+        alias_method alias_name, base_method
+        def #{base_method}(*opts)
+	  send :#{alias_name}, *opts
+	  send :#{extend_method}, *opts
+	end
+      ]
+    end
+
+    # return #{prefix}#{name}#{postfix}<num>
+    def new_alias_name(name, prefix = "__alias_of__", postfix = "__")
+      base_name = "#{prefix}#{name}#{postfix}"
+      all_methods = instance_methods(true) + private_instance_methods(true)
+      same_methods = all_methods.grep(/^#{Regexp.quote(base_name)}[0-9]*$/)
+      return base_name if same_methods.empty?
+      no = same_methods.size
+      while !same_methods.include?(alias_name = base_name + no)
+	no += 1
+      end
+      alias_name
+    end
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/frame.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/frame.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/frame.rb	(revision 18425)
@@ -0,0 +1,67 @@
+#
+#   frame.rb - 
+#   	$Release Version: 0.9$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
+#
+# --
+#
+#   
+#
+
+require "e2mmap"
+
+module IRB
+  class Frame
+    extend Exception2MessageMapper
+    def_exception :FrameOverflow, "frame overflow"
+    def_exception :FrameUnderflow, "frame underflow"
+
+    INIT_STACK_TIMES = 3
+    CALL_STACK_OFFSET = 3
+
+    def initialize
+      @frames = [TOPLEVEL_BINDING] * INIT_STACK_TIMES
+    end
+
+    def trace_func(event, file, line, id, binding)
+      case event
+      when 'call', 'class'
+	@frames.push binding
+      when 'return', 'end'
+	@frames.pop
+      end
+    end
+
+    def top(n = 0)
+      bind = @frames[-(n + CALL_STACK_OFFSET)]
+      Fail FrameUnderflow unless bind
+      bind
+    end
+
+    def bottom(n = 0)
+      bind = @frames[n]
+      Fail FrameOverflow unless bind
+      bind
+    end
+
+    # singleton functions
+    def Frame.bottom(n = 0)
+      @backtrace.bottom(n)
+    end
+
+    def Frame.top(n = 0)
+      @backtrace.top(n)
+    end
+
+    def Frame.sender
+      eval "self", @backtrace.top
+    end
+
+    @backtrace = Frame.new
+    set_trace_func proc{|event, file, line, id, binding, klass|
+      @backtrace.trace_func(event, file, line, id, binding)
+    }
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/help.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/help.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/help.rb	(revision 18425)
@@ -0,0 +1,33 @@
+#
+#   irb/help.rb - print usase module
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ishitsuka.com)
+#
+# --
+#
+#   
+#
+
+module IRB
+  def IRB.print_usage
+    lc = IRB.conf[:LC_MESSAGES]
+    path = lc.find("irb/help-message")
+    space_line = false
+    File.foreach(path) do
+      |l|
+      if /^\s*$/ =~ l
+	lc.puts l unless space_line
+	space_line = true
+	next
+      end
+      space_line = false
+      
+      l.sub!(/#.*$/, "")
+      next if /^\s*$/ =~ l
+      lc.puts l
+    end
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/init.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/init.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/init.rb	(revision 18425)
@@ -0,0 +1,259 @@
+#
+#   irb/init.rb - irb initialize module
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+module IRB
+
+  # initialize config
+  def IRB.setup(ap_path)
+    IRB.init_config(ap_path)
+    IRB.init_error
+    IRB.parse_opts
+    IRB.run_config
+    IRB.load_modules
+
+    unless @CONF[:PROMPT][@CONF[:PROMPT_MODE]]
+      IRB.fail(UndefinedPromptMode, @CONF[:PROMPT_MODE]) 
+    end
+  end
+
+  # @CONF default setting
+  def IRB.init_config(ap_path)
+    # class instance variables
+    @TRACER_INITIALIZED = false
+
+    # default configurations
+    unless ap_path and @CONF[:AP_NAME]
+      ap_path = File.join(File.dirname(File.dirname(__FILE__)), "irb.rb")
+    end
+    @CONF[:AP_NAME] = File::basename(ap_path, ".rb")
+
+    @CONF[:IRB_NAME] = "irb"
+    @CONF[:IRB_LIB_PATH] = File.dirname(__FILE__)
+
+    @CONF[:RC] = true
+    @CONF[:LOAD_MODULES] = []
+    @CONF[:IRB_RC] = nil
+
+    @CONF[:MATH_MODE] = false
+    @CONF[:USE_READLINE] = false unless defined?(ReadlineInputMethod)
+    @CONF[:INSPECT_MODE] = nil
+    @CONF[:USE_TRACER] = false
+    @CONF[:USE_LOADER] = false
+    @CONF[:IGNORE_SIGINT] = true
+    @CONF[:IGNORE_EOF] = false
+    @CONF[:ECHO] = nil
+    @CONF[:VERBOSE] = nil
+
+    @CONF[:EVAL_HISTORY] = nil
+    @CONF[:SAVE_HISTORY] = nil
+
+    @CONF[:BACK_TRACE_LIMIT] = 16
+
+    @CONF[:PROMPT] = {
+      :NULL => {
+	:PROMPT_I => nil,
+	:PROMPT_N => nil,
+	:PROMPT_S => nil,
+	:PROMPT_C => nil,
+	:RETURN => "%s\n"
+      },
+      :DEFAULT => {
+	:PROMPT_I => "%N(%m):%03n:%i> ",
+	:PROMPT_N => "%N(%m):%03n:%i> ",
+	:PROMPT_S => "%N(%m):%03n:%i%l ",
+	:PROMPT_C => "%N(%m):%03n:%i* ",
+	:RETURN => "=> %s\n"
+      },
+      :CLASSIC => {
+	:PROMPT_I => "%N(%m):%03n:%i> ",
+	:PROMPT_N => "%N(%m):%03n:%i> ",
+	:PROMPT_S => "%N(%m):%03n:%i%l ",
+	:PROMPT_C => "%N(%m):%03n:%i* ",
+	:RETURN => "%s\n"
+      },
+      :SIMPLE => {
+	:PROMPT_I => ">> ",
+	:PROMPT_N => ">> ",
+	:PROMPT_S => nil,
+	:PROMPT_C => "?> ",
+	:RETURN => "=> %s\n"
+      },
+      :INF_RUBY => {
+	:PROMPT_I => "%N(%m):%03n:%i> ",
+#	:PROMPT_N => "%N(%m):%03n:%i> ",
+	:PROMPT_N => nil,
+	:PROMPT_S => nil,
+	:PROMPT_C => nil,
+	:RETURN => "%s\n",
+	:AUTO_INDENT => true
+      },
+      :XMP => {
+	:PROMPT_I => nil,
+	:PROMPT_N => nil,
+	:PROMPT_S => nil,
+	:PROMPT_C => nil,
+	:RETURN => "    ==>%s\n"
+      }
+    }
+
+    @CONF[:PROMPT_MODE] = (STDIN.tty? ? :DEFAULT : :NULL)
+    @CONF[:AUTO_INDENT] = false
+
+    @CONF[:CONTEXT_MODE] = 3 # use binding in function on TOPLEVEL_BINDING
+    @CONF[:SINGLE_IRB] = false
+
+#    @CONF[:LC_MESSAGES] = "en"
+    @CONF[:LC_MESSAGES] = Locale.new
+    
+    @CONF[:DEBUG_LEVEL] = 1
+  end
+
+  def IRB.init_error
+    @CONF[:LC_MESSAGES].load("irb/error.rb")
+  end
+
+  FEATURE_IOPT_CHANGE_VERSION = "1.9.0"
+
+  # option analyzing
+  def IRB.parse_opts
+    load_path = []
+    while opt = ARGV.shift
+      case opt
+      when "-f"
+	@CONF[:RC] = false
+      when "-m"
+	@CONF[:MATH_MODE] = true
+      when "-d"
+	$DEBUG = true
+      when /^-r(.+)?/
+	opt = $1 || ARGV.shift
+	@CONF[:LOAD_MODULES].push opt if opt
+      when /^-I(.+)?/
+        opt = $1 || ARGV.shift
+	load_path.concat(opt.split(File::PATH_SEPARATOR)) if opt
+      when /^-K(.)/
+	$KCODE = $1
+      when "--inspect"
+	@CONF[:INSPECT_MODE] = true
+      when "--noinspect"
+	@CONF[:INSPECT_MODE] = false
+      when "--readline"
+	@CONF[:USE_READLINE] = true
+      when "--noreadline"
+	@CONF[:USE_READLINE] = false
+      when "--echo"
+	@CONF[:ECHO] = true
+      when "--noecho"
+	@CONF[:ECHO] = false
+      when "--verbose"
+	@CONF[:VERBOSE] = true
+      when "--noverbose"
+	@CONF[:VERBOSE] = false
+      when "--prompt-mode", "--prompt"
+	prompt_mode = ARGV.shift.upcase.tr("-", "_").intern
+	@CONF[:PROMPT_MODE] = prompt_mode
+      when "--noprompt"
+	@CONF[:PROMPT_MODE] = :NULL
+      when "--inf-ruby-mode"
+	@CONF[:PROMPT_MODE] = :INF_RUBY
+      when "--sample-book-mode", "--simple-prompt"
+	@CONF[:PROMPT_MODE] = :SIMPLE
+      when "--tracer"
+	@CONF[:USE_TRACER] = true
+      when "--back-trace-limit"
+	@CONF[:BACK_TRACE_LIMIT] = ARGV.shift.to_i
+      when "--context-mode"
+	@CONF[:CONTEXT_MODE] = ARGV.shift.to_i
+      when "--single-irb"
+	@CONF[:SINGLE_IRB] = true
+      when "--irb_debug"
+	@CONF[:DEBUG_LEVEL] = ARGV.shift.to_i
+      when "-v", "--version"
+	print IRB.version, "\n"
+	exit 0
+      when "-h", "--help"
+	require "irb/help"
+	IRB.print_usage
+	exit 0
+      when /^-/
+	IRB.fail UnrecognizedSwitch, opt
+      else
+	@CONF[:SCRIPT] = opt
+	$0 = opt
+	break
+      end
+    end
+    if RUBY_VERSION >= FEATURE_IOPT_CHANGE_VERSION
+      load_path.collect! do |path|
+	/\A\.\// =~ path ? path : File.expand_path(path)
+      end
+    end
+    $LOAD_PATH.unshift(*load_path)
+  end
+
+  # running config
+  def IRB.run_config
+    if @CONF[:RC]
+      begin
+	load rc_file
+      rescue LoadError, Errno::ENOENT
+      rescue
+	print "load error: #{rc_file}\n"
+	print $!.class, ": ", $!, "\n"
+	for err in $@[0, $@.size - 2]
+	  print "\t", err, "\n"
+	end
+      end
+    end
+  end
+
+  IRBRC_EXT = "rc"
+  def IRB.rc_file(ext = IRBRC_EXT)
+    if !@CONF[:RC_NAME_GENERATOR]
+      rc_file_generators do |rcgen|
+	@CONF[:RC_NAME_GENERATOR] ||= rcgen
+	if File.exist?(rcgen.call(IRBRC_EXT))
+	  @CONF[:RC_NAME_GENERATOR] = rcgen
+	  break
+	end
+      end
+    end
+    @CONF[:RC_NAME_GENERATOR].call ext
+  end
+
+  # enumerate possible rc-file base name generators
+  def IRB.rc_file_generators
+    if irbrc = ENV["IRBRC"]
+      yield proc{|rc|  rc == "rc" ? irbrc : irbrc+rc}
+    end
+    if home = ENV["HOME"]
+      yield proc{|rc| home+"/.irb#{rc}"} 
+    end
+    home = Dir.pwd
+    yield proc{|rc| home+"/.irb#{rc}"}
+    yield proc{|rc| home+"/irb#{rc.sub(/\A_?/, '.')}"}
+    yield proc{|rc| home+"/_irb#{rc}"}
+    yield proc{|rc| home+"/$irb#{rc}"}
+  end
+
+  # loading modules
+  def IRB.load_modules
+    for m in @CONF[:LOAD_MODULES]
+      begin
+	require m
+      rescue
+	print $@[0], ":", $!.class, ": ", $!, "\n"
+      end
+    end
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/input-method.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/input-method.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/input-method.rb	(revision 18425)
@@ -0,0 +1,120 @@
+#
+#   irb/input-method.rb - input methods used irb
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+module IRB
+  # 
+  # InputMethod
+  #	StdioInputMethod
+  #	FileInputMethod
+  #	(ReadlineInputMethod)
+  #
+  STDIN_FILE_NAME = "(line)"
+  class InputMethod
+    @RCS_ID='-$Id: input-method.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+    def initialize(file = STDIN_FILE_NAME)
+      @file_name = file
+    end
+    attr_reader :file_name
+
+    attr_accessor :prompt
+    
+    def gets
+      IRB.fail NotImplementedError, "gets"
+    end
+    public :gets
+
+    def readable_atfer_eof?
+      false
+    end
+  end
+  
+  class StdioInputMethod < InputMethod
+    def initialize
+      super
+      @line_no = 0
+      @line = []
+    end
+
+    def gets
+      print @prompt
+      @line[@line_no += 1] = $stdin.gets
+    end
+
+    def eof?
+      $stdin.eof?
+    end
+
+    def readable_atfer_eof?
+      true
+    end
+
+    def line(line_no)
+      @line[line_no]
+    end
+  end
+  
+  class FileInputMethod < InputMethod
+    def initialize(file)
+      super
+      @io = open(file)
+    end
+    attr_reader :file_name
+
+    def eof?
+      @io.eof?
+    end
+
+    def gets
+      print @prompt
+      l = @io.gets
+#      print @prompt, l
+      l
+    end
+  end
+
+  begin
+    require "readline"
+    class ReadlineInputMethod < InputMethod
+      include Readline 
+      def initialize
+	super
+
+	@line_no = 0
+	@line = []
+	@eof = false
+      end
+
+      def gets
+	if l = readline(@prompt, false)
+          HISTORY.push(l) if !l.empty?
+	  @line[@line_no += 1] = l + "\n"
+	else
+	  @eof = true
+	  l
+	end
+      end
+
+      def eof?
+	@eof
+      end
+
+      def readable_atfer_eof?
+	true
+      end
+
+      def line(line_no)
+	@line[line_no]
+      end
+    end
+  rescue LoadError
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/lc/error.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/lc/error.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/lc/error.rb	(revision 18425)
@@ -0,0 +1,30 @@
+#
+#   irb/lc/error.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+require "e2mmap"
+
+module IRB
+
+  # exceptions
+  extend Exception2MessageMapper
+  def_exception :UnrecognizedSwitch, "Unrecognized switch: %s"
+  def_exception :NotImplementedError, "Need to define `%s'"
+  def_exception :CantReturnToNormalMode, "Can't return to normal mode."
+  def_exception :IllegalParameter, "Illegal parameter(%s)."
+  def_exception :IrbAlreadyDead, "Irb is already dead."
+  def_exception :IrbSwitchedToCurrentThread, "Switched to current thread."
+  def_exception :NoSuchJob, "No such job(%s)."
+  def_exception :CantShiftToMultiIrbMode, "Can't shift to multi irb mode."
+  def_exception :CantChangeBinding, "Can't change binding to (%s)."
+  def_exception :UndefinedPromptMode, "Undefined prompt mode(%s)."
+
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/lc/help-message
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/lc/help-message	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/lc/help-message	(revision 18425)
@@ -0,0 +1,35 @@
+#
+#   irb/lc/help-message.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+Usage:  irb.rb [options] [programfile] [arguments]
+  -f		    Suppress read of ~/.irbrc 
+  -m		    Bc mode (load mathn, fraction or matrix are available)
+  -d                Set $DEBUG to true (same as `ruby -d')
+  -r load-module    Same as `ruby -r'
+  -I path           Specify $LOAD_PATH directory
+  --inspect	    Use `inspect' for output (default except for bc mode)
+  --noinspect	    Don't use inspect for output
+  --readline	    Use Readline extension module
+  --noreadline	    Don't use Readline extension module
+  --prompt prompt-mode
+  --prompt-mode prompt-mode
+		    Switch prompt mode. Pre-defined prompt modes are
+		    `default', `simple', `xmp' and `inf-ruby'
+  --inf-ruby-mode   Use prompt appropriate for inf-ruby-mode on emacs. 
+		    Suppresses --readline. 
+  --simple-prompt   Simple prompt mode
+  --noprompt	    No prompt mode
+  --tracer	    Display trace for each execution of commands.
+  --back-trace-limit n
+		    Display backtrace top n and tail n. The default
+		    value is 16. 
+  --irb_debug n	    Set internal debug level to n (not for popular use)
+  -v, --version	    Print the version of irb
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/lc/ja/error.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/lc/ja/error.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/lc/ja/error.rb	(revision 18425)
@@ -0,0 +1,27 @@
+#
+#   irb/lc/ja/error.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+require "e2mmap"
+
+module IRB
+  # exceptions
+  extend Exception2MessageMapper
+  def_exception :UnrecognizedSwitch, '$B%9%$%C%A(B(%s)$B$,J,$j$^$;$s(B'
+  def_exception :NotImplementedError, '`%s\'$B$NDj5A$,I,MW$G$9(B'
+  def_exception :CantReturnToNormalMode, 'Normal$B%b!<%I$KLa$l$^$;$s(B.'
+  def_exception :IllegalParameter, '$B%Q%i%a!<%?(B(%s)$B$,4V0c$C$F$$$^$9(B.'
+  def_exception :IrbAlreadyDead, 'Irb$B$O4{$K;`$s$G$$$^$9(B.'
+  def_exception :IrbSwitchedToCurrentThread, '$B%+%l%s%H%9%l%C%I$K@Z$jBX$o$j$^$7$?(B.'
+  def_exception :NoSuchJob, '$B$=$N$h$&$J%8%g%V(B(%s)$B$O$"$j$^$;$s(B.'
+  def_exception :CantShiftToMultiIrbMode, 'multi-irb mode$B$K0\$l$^$;$s(B.'
+  def_exception :CantChangeBinding, '$B%P%$%s%G%#%s%0(B(%s)$B$KJQ99$G$-$^$;$s(B.'
+  def_exception :UndefinedPromptMode, '$B%W%m%s%W%H%b!<%I(B(%s)$B$ODj5A$5$l$F$$$^$;$s(B.'
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/lc/ja/help-message
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/lc/ja/help-message	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/lc/ja/help-message	(revision 18425)
@@ -0,0 +1,36 @@
+#
+#   irb/lc/ja/help-message.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+Usage:  irb.rb [options] [programfile] [arguments]
+  -f		    ~/.irbrc $B$rFI$_9~$^$J$$(B.
+  -m		    bc$B%b!<%I(B($BJ,?t(B, $B9TNs$N7W;;$,$G$-$k(B)
+  -d                $DEBUG $B$r(Btrue$B$K$9$k(B(ruby -d $B$HF1$8(B)
+  -r load-module    ruby -r $B$HF1$8(B.
+  -I path           $LOAD_PATH $B$K(B path $B$rDI2C$9$k(B.
+  --inspect	    $B7k2L=PNO$K(Binspect$B$rMQ$$$k(B(bc$B%b!<%I0J30$O%G%U%)%k%H(B). 
+  --noinspect	    $B7k2L=PNO$K(Binspect$B$rMQ$$$J$$(B.
+  --readline	    readline$B%i%$%V%i%j$rMxMQ$9$k(B.
+  --noreadline	    readline$B%i%$%V%i%j$rMxMQ$7$J$$(B. 
+  --prompt prompt-mode/--prompt-mode prompt-mode
+		    $B%W%m%s%W%H%b!<%I$r@ZBX$($^$9(B. $B8=:_Dj5A$5$l$F$$$k%W(B
+		    $B%m%s%W%H%b!<%I$O(B, default, simple, xmp, inf-ruby$B$,(B
+		    $BMQ0U$5$l$F$$$^$9(B. 
+  --inf-ruby-mode   emacs$B$N(Binf-ruby-mode$BMQ$N%W%m%s%W%HI=<($r9T$J$&(B. $BFC(B
+		    $B$K;XDj$,$J$$8B$j(B, readline$B%i%$%V%i%j$O;H$o$J$/$J$k(B.
+  --simple-prompt   $BHs>o$K%7%s%W%k$J%W%m%s%W%H$rMQ$$$k%b!<%I$G$9(B.
+  --noprompt	    $B%W%m%s%W%HI=<($r9T$J$o$J$$(B.
+  --tracer	    $B%3%^%s%I<B9T;~$K%H%l!<%9$r9T$J$&(B.
+  --back-trace-limit n
+		    $B%P%C%/%H%l!<%9I=<($r%P%C%/%H%l!<%9$NF,$+$i(B n, $B8e$m(B
+		    $B$+$i(Bn$B$@$19T$J$&(B. $B%G%U%)%k%H$O(B16 
+  --irb_debug n	    irb$B$N%G%P%C%0%G%P%C%0%l%Y%k$r(Bn$B$K@_Dj$9$k(B($BMxMQ$7$J(B
+		    $B$$J}$,L5Fq$G$7$g$&(B).
+  -v, --version	    irb$B$N%P!<%8%g%s$rI=<($9$k(B
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/locale.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/locale.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/locale.rb	(revision 18425)
@@ -0,0 +1,184 @@
+#
+#   irb/locale.rb - internationalization module
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+autoload :Kconv, "kconv"
+
+module IRB
+  class Locale
+    @RCS_ID='-$Id: locale.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+    JPDefaultLocale = "ja"
+    LOCALE_DIR = "/lc/"
+
+    def initialize(locale = nil)
+      @lang = locale || ENV["IRB_LANG"] || ENV["LC_MESSAGES"] || ENV["LC_ALL"] || ENV["LANG"] || "C" 
+    end
+
+    attr_reader :lang
+
+    def lc2kconv(lang)
+      case lang
+      when "ja_JP.ujis", "ja_JP.euc", "ja_JP.eucJP"
+        Kconv::EUC
+      when "ja_JP.sjis", "ja_JP.SJIS"
+        Kconv::SJIS
+      when /ja_JP.utf-?8/i
+	Kconv::UTF8
+      end
+    end
+    private :lc2kconv
+
+    def String(mes)
+      mes = super(mes)
+      case @lang
+      when /^ja/
+	mes = Kconv::kconv(mes, lc2kconv(@lang))
+      else
+	mes
+      end
+      mes
+    end
+
+    def format(*opts)
+      String(super(*opts))
+    end
+
+    def gets(*rs)
+      String(super(*rs))
+    end
+
+    def readline(*rs)
+      String(super(*rs))
+    end
+
+    def print(*opts)
+      ary = opts.collect{|opt| String(opt)}
+      super(*ary)
+    end
+
+    def printf(*opts)
+      s = format(*opts)
+      print s
+    end
+
+    def puts(*opts)
+      ary = opts.collect{|opt| String(opt)}
+      super(*ary)
+    end
+
+    def require(file, priv = nil)
+      rex = Regexp.new("lc/#{Regexp.quote(file)}\.(so|o|sl|rb)?")
+      return false if $".find{|f| f =~ rex}
+
+      case file
+      when /\.rb$/
+	begin
+	  load(file, priv)
+	  $".push file
+	  return true
+	rescue LoadError
+	end
+      when /\.(so|o|sl)$/
+	return super
+      end
+
+      begin
+	load(f = file + ".rb")
+	$".push f  #"
+	return true
+      rescue LoadError
+	return ruby_require(file)
+      end
+    end
+
+    alias toplevel_load load
+    
+    def load(file, priv=nil)
+      dir = File.dirname(file)
+      dir = "" if dir == "."
+      base = File.basename(file)
+
+      if /^ja(_JP)?$/ =~ @lang
+ 	back, @lang = @lang, "C"
+      end
+      begin
+	if dir[0] == ?/ #/
+	  lc_path = search_file(dir, base)
+	  return real_load(lc_path, priv) if lc_path
+	end
+	
+	for path in $:
+	  lc_path = search_file(path + "/" + dir, base)
+	  return real_load(lc_path, priv) if lc_path
+	end
+      ensure
+	@lang = back if back
+      end
+      raise LoadError, "No such file to load -- #{file}"
+    end 
+
+    def real_load(path, priv)
+      src = self.String(File.read(path))
+      if priv
+	eval("self", TOPLEVEL_BINDING).extend(Module.new {eval(src, nil, path)})
+      else
+	eval(src, TOPLEVEL_BINDING, path)
+      end
+    end
+    private :real_load
+
+    def find(file , paths = $:)
+      dir = File.dirname(file)
+      dir = "" if dir == "."
+      base = File.basename(file)
+      if dir[0] == ?/ #/
+	  return lc_path = search_file(dir, base)
+      else
+	for path in $:
+	  if lc_path = search_file(path + "/" + dir, base)
+	    return lc_path
+	  end
+	end
+      end
+      nil
+    end
+
+    def search_file(path, file)
+      if File.exist?(p1 = path + lc_path(file, "C"))
+	if File.exist?(p2 = path + lc_path(file))
+	  return p2
+	else
+	end
+	return p1
+      else
+      end
+      nil
+    end
+    private :search_file
+
+    def lc_path(file = "", lc = @lang)
+      case lc
+      when "C"
+	LOCALE_DIR + file
+      when /^ja/
+	LOCALE_DIR + "ja/" + file
+      else
+	LOCALE_DIR + @lang + "/" + file
+      end
+    end
+    private :lc_path
+  end
+end
+
+
+
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/notifier.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/notifier.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/notifier.rb	(revision 18425)
@@ -0,0 +1,145 @@
+#
+#   notifier.rb - optput methods used by irb 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+require "e2mmap"
+require "irb/output-method"
+
+module IRB
+  module Notifier
+    extend Exception2MessageMapper
+    def_exception :ErrUndefinedNotifier, 
+      "undefined notifier level: %d is specified"
+    def_exception :ErrUnrecognizedLevel, 
+      "unrecognized notifier level: %s is specified"
+
+    def def_notifier(prefix = "", output_method = StdioOutputMethod.new)
+      CompositeNotifier.new(prefix, output_method)
+    end
+    module_function :def_notifier
+  
+    class AbstructNotifier
+      def initialize(prefix, base_notifier)
+	@prefix = prefix
+	@base_notifier = base_notifier
+      end
+
+      attr_reader :prefix
+
+      def notify?
+	true
+      end
+
+      def print(*opts)
+	@base_notifier.print prefix, *opts if notify?
+      end
+
+      def printn(*opts)
+	@base_notifier.printn prefix, *opts if notify?
+      end
+
+      def printf(format, *opts)
+	@base_notifier.printf(prefix + format, *opts) if notify?
+      end
+
+      def puts(*objs)
+	if notify?
+	  @base_notifier.puts(*objs.collect{|obj| prefix + obj.to_s})
+	end
+      end
+
+      def pp(*objs)
+	if notify?
+	  @base_notifier.ppx @prefix, *objs
+	end
+      end
+
+      def ppx(prefix, *objs)
+	if notify?
+	  @base_notifier.ppx @prefix+prefix, *objs
+	end
+      end
+
+      def exec_if
+	yield(@base_notifier) if notify?
+      end
+    end
+
+    class CompositeNotifier<AbstructNotifier
+      def initialize(prefix, base_notifier)
+	super
+
+	@notifiers = [D_NOMSG]
+	@level_notifier = D_NOMSG
+      end
+
+      attr_reader :notifiers
+
+      def def_notifier(level, prefix = "")
+	notifier = LeveledNotifier.new(self, level, prefix)
+	@notifiers[level] = notifier
+	notifier
+      end
+
+      attr_reader :level_notifier
+      alias level level_notifier
+
+      def level_notifier=(value)
+	case value
+	when AbstructNotifier
+	  @level_notifier = value
+	when Integer
+	  l = @notifiers[value]
+	  Notifier.Raise ErrUndefinedNotifer, value unless l
+	  @level_notifier = l
+	else
+	  Notifier.Raise ErrUnrecognizedLevel, value unless l
+	end
+      end
+
+      alias level= level_notifier=
+    end
+
+    class LeveledNotifier<AbstructNotifier
+      include Comparable
+
+      def initialize(base, level, prefix)
+	super(prefix, base)
+	
+	@level = level
+      end
+
+      attr_reader :level
+
+      def <=>(other)
+	@level <=> other.level
+      end
+      
+      def notify?
+	@base_notifier.level >= self
+      end
+    end
+
+    class NoMsgNotifier<LeveledNotifier
+      def initialize
+	@base_notifier = nil
+	@level = 0
+	@prefix = ""
+      end
+
+      def notify?
+	false
+      end
+    end
+
+    D_NOMSG = NoMsgNotifier.new
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/output-method.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/output-method.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/output-method.rb	(revision 18425)
@@ -0,0 +1,85 @@
+#
+#   output-method.rb - optput methods used by irb 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+require "e2mmap"
+
+module IRB
+  # OutputMethod
+  #   StdioOutputMethod
+
+  class OutputMethod
+    @RCS_ID='-$Id: output-method.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+    def print(*opts)
+      IRB.fail NotImplementError, "print"
+    end
+
+    def printn(*opts)
+      print opts.join(" "), "\n"
+    end
+
+    # extend printf
+    def printf(format, *opts)
+      if /(%*)%I/ =~ format
+	format, opts = parse_printf_format(format, opts)
+      end
+      print sprintf(format, *opts)
+    end
+
+    # %
+    # <¥Õ¥é¥°>  [#0- +]
+    # <ºÇŸ®¥Õ¥£¡Œ¥ë¥ÉÉý> (\*|\*[1-9][0-9]*\$|[1-9][0-9]*)
+    # <ÀºÅÙ>.(\*|\*[1-9][0-9]*\$|[1-9][0-9]*|)?
+    # #<Ä¹€µœ€ÀµÊž»ú>(hh|h|l|ll|L|q|j|z|t)
+    # <ÊÑŽ¹œ€ÀµÊž»ú>[diouxXeEfgGcsb%] 
+    def parse_printf_format(format, opts)
+      return format, opts if $1.size % 2 == 1
+    end
+
+    def foo(format)
+      pos = 0
+      inspects = []
+      format.scan(/%[#0\-+ ]?(\*(?=[^0-9])|\*[1-9][0-9]*\$|[1-9][0-9]*(?=[^0-9]))?(\.(\*(?=[^0-9])|\*[1-9][0-9]*\$|[1-9][0-9]*(?=[^0-9])))?(([1-9][0-9]*\$)*)([diouxXeEfgGcsb%])/) {|f, p, pp, pos, new_pos, c|
+	puts [f, p, pp, pos, new_pos, c].join("!")
+	pos = new_pos if new_pos
+	if c == "I"
+	  inspects.push pos.to_i 
+	  (f||"")+(p||"")+(pp||"")+(pos||"")+"s"
+	else
+	  $&
+	end
+      }
+    end
+
+    def puts(*objs)
+      for obj in objs
+	print(*obj)
+	print "\n"
+      end
+    end
+
+    def pp(*objs)
+      puts(*objs.collect{|obj| obj.inspect})
+    end
+
+    def ppx(prefix, *objs)
+      puts(*objs.collect{|obj| prefix+obj.inspect})
+    end
+
+  end
+
+  class StdioOutputMethod<OutputMethod
+    def print(*opts)
+      STDOUT.print(*opts)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ruby-lex.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ruby-lex.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ruby-lex.rb	(revision 18425)
@@ -0,0 +1,1149 @@
+#
+#   irb/ruby-lex.rb - ruby lexcal analizer
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+require "e2mmap"
+require "irb/slex"
+require "irb/ruby-token"
+
+class RubyLex
+  @RCS_ID='-$Id: ruby-lex.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+  extend Exception2MessageMapper
+  def_exception(:AlreadyDefinedToken, "Already defined token(%s)")
+  def_exception(:TkReading2TokenNoKey, "key nothing(key='%s')")
+  def_exception(:TkSymbol2TokenNoKey, "key nothing(key='%s')")
+  def_exception(:TkReading2TokenDuplicateError, 
+		"key duplicate(token_n='%s', key='%s')")
+  def_exception(:SyntaxError, "%s")
+
+  def_exception(:TerminateLineInput, "Terminate Line Input")
+  
+  include RubyToken
+
+  class << self
+    attr_accessor :debug_level
+    def debug?
+      @debug_level > 0
+    end
+  end
+  @debug_level = 0
+
+  def initialize
+    lex_init
+    set_input(STDIN)
+
+    @seek = 0
+    @exp_line_no = @line_no = 1
+    @base_char_no = 0
+    @char_no = 0
+    @rests = []
+    @readed = []
+    @here_readed = []
+
+    @indent = 0
+    @indent_stack = []
+    @lex_state = EXPR_BEG
+    @space_seen = false
+    @here_header = false
+    
+    @continue = false
+    @line = ""
+
+    @skip_space = false
+    @readed_auto_clean_up = false
+    @exception_on_syntax_error = true
+
+    @prompt = nil
+  end
+
+  attr_accessor :skip_space
+  attr_accessor :readed_auto_clean_up
+  attr_accessor :exception_on_syntax_error
+
+  attr_reader :seek
+  attr_reader :char_no
+  attr_reader :line_no
+  attr_reader :indent
+
+  # io functions
+  def set_input(io, p = nil, &block)
+    @io = io
+    if p.respond_to?(:call)
+      @input = p
+    elsif block_given?
+      @input = block
+    else
+      @input = Proc.new{@io.gets}
+    end
+  end
+
+  def get_readed
+    if idx = @readed.reverse.index("\n")
+      @base_char_no = idx
+    else
+      @base_char_no += @readed.size
+    end
+    
+    readed = @readed.join("")
+    @readed = []
+    readed
+  end
+
+  def getc
+    while @rests.empty?
+#      return nil unless buf_input
+      @rests.push nil unless buf_input
+    end
+    c = @rests.shift
+    if @here_header
+      @here_readed.push c
+    else
+      @readed.push c
+    end
+    @seek += 1
+    if c == "\n"
+      @line_no += 1 
+      @char_no = 0
+    else
+      @char_no += 1
+    end
+    c
+  end
+
+  def gets
+    l = ""
+    while c = getc
+      l.concat(c)
+      break if c == "\n"
+    end
+    return nil if l == "" and c.nil?
+    l
+  end
+
+  def eof?
+    @io.eof?
+  end
+
+  def getc_of_rests
+    if @rests.empty?
+      nil
+    else
+      getc
+    end
+  end
+
+  def ungetc(c = nil)
+    if @here_readed.empty?
+      c2 = @readed.pop
+    else
+      c2 = @here_readed.pop
+    end
+    c = c2 unless c
+    @rests.unshift c #c = 
+      @seek -= 1
+    if c == "\n"
+      @line_no -= 1 
+      if idx = @readed.reverse.index("\n")
+	@char_no = @readed.size - idx
+      else
+	@char_no = @base_char_no + @readed.size
+      end
+    else
+      @char_no -= 1
+    end
+  end
+
+  def peek_equal?(str)
+    chrs = str.split(//)
+    until @rests.size >= chrs.size
+      return false unless buf_input
+    end
+    @rests[0, chrs.size] == chrs
+  end
+
+  def peek_match?(regexp)
+    while @rests.empty?
+      return false unless buf_input
+    end
+    regexp =~ @rests.join("")
+  end
+
+  def peek(i = 0)
+    while @rests.size <= i
+      return nil unless buf_input
+    end
+    @rests[i]
+  end
+
+  def buf_input
+    prompt
+    line = @input.call
+    return nil unless line
+    @rests.concat line.split(//)
+    true
+  end
+  private :buf_input
+
+  def set_prompt(p = nil, &block)
+    p = block if block_given?
+    if p.respond_to?(:call)
+      @prompt = p
+    else
+      @prompt = Proc.new{print p}
+    end
+  end
+
+  def prompt
+    if @prompt
+      @prompt.call(@ltype, @indent, @continue, @line_no)
+    end
+  end
+
+  def initialize_input
+    @ltype = nil
+    @quoted = nil
+    @indent = 0
+    @indent_stack = []
+    @lex_state = EXPR_BEG
+    @space_seen = false
+    @here_header = false
+    
+    @continue = false
+    prompt
+
+    @line = ""
+    @exp_line_no = @line_no
+  end
+  
+  def each_top_level_statement
+    initialize_input
+    catch(:TERM_INPUT) do
+      loop do
+	begin
+	  @continue = false
+	  prompt
+	  unless l = lex
+	    throw :TERM_INPUT if @line == ''
+	  else
+	    #p l
+	    @line.concat l
+	    if @ltype or @continue or @indent > 0
+	      next
+	    end
+	  end
+	  if @line != "\n"
+	    yield @line, @exp_line_no
+	  end
+	  break unless l
+	  @line = ''
+	  @exp_line_no = @line_no
+
+	  @indent = 0
+	  @indent_stack = []
+	  prompt
+	rescue TerminateLineInput
+	  initialize_input
+	  prompt
+	  get_readed
+	end
+      end
+    end
+  end
+
+  def lex
+    until (((tk = token).kind_of?(TkNL) || tk.kind_of?(TkEND_OF_SCRIPT)) &&
+	     !@continue or
+	     tk.nil?)
+      #p tk
+      #p @lex_state
+      #p self
+    end
+    line = get_readed
+    #      print self.inspect
+    if line == "" and tk.kind_of?(TkEND_OF_SCRIPT) || tk.nil?
+      nil
+    else
+      line
+    end
+  end
+
+  def token
+    #      require "tracer"
+    #      Tracer.on
+    @prev_seek = @seek
+    @prev_line_no = @line_no
+    @prev_char_no = @char_no
+    begin
+      begin
+	tk = @OP.match(self)
+	@space_seen = tk.kind_of?(TkSPACE)
+      rescue SyntaxError
+	raise if @exception_on_syntax_error
+	tk = TkError.new(@seek, @line_no, @char_no)
+      end
+    end while @skip_space and tk.kind_of?(TkSPACE)
+    if @readed_auto_clean_up
+      get_readed
+    end
+    #      Tracer.off
+    tk
+  end
+  
+  ENINDENT_CLAUSE = [
+    "case", "class", "def", "do", "for", "if",
+    "module", "unless", "until", "while", "begin" #, "when"
+  ]
+  DEINDENT_CLAUSE = ["end" #, "when"
+  ]
+
+  PERCENT_LTYPE = {
+    "q" => "\'",
+    "Q" => "\"",
+    "x" => "\`",
+    "r" => "/",
+    "w" => "]",
+    "W" => "]",
+    "s" => ":"
+  }
+  
+  PERCENT_PAREN = {
+    "{" => "}",
+    "[" => "]",
+    "<" => ">",
+    "(" => ")"
+  }
+
+  Ltype2Token = {
+    "\'" => TkSTRING,
+    "\"" => TkSTRING,
+    "\`" => TkXSTRING,
+    "/" => TkREGEXP,
+    "]" => TkDSTRING,
+    ":" => TkSYMBOL
+  }
+  DLtype2Token = {
+    "\"" => TkDSTRING,
+    "\`" => TkDXSTRING,
+    "/" => TkDREGEXP,
+  }
+
+  def lex_init()
+    @OP = IRB::SLex.new
+    @OP.def_rules("\0", "\004", "\032") do |op, io|
+      Token(TkEND_OF_SCRIPT)
+    end
+
+    @OP.def_rules(" ", "\t", "\f", "\r", "\13") do |op, io|
+      @space_seen = true
+      while getc =~ /[ \t\f\r\13]/; end
+      ungetc
+      Token(TkSPACE)
+    end
+
+    @OP.def_rule("#") do |op, io|
+      identify_comment
+    end
+
+    @OP.def_rule("=begin",
+		 proc{|op, io| @prev_char_no == 0 && peek(0) =~ /\s/}) do 
+      |op, io|
+      @ltype = "="
+      until getc == "\n"; end
+      until peek_equal?("=end") && peek(4) =~ /\s/
+	until getc == "\n"; end
+      end
+      gets
+      @ltype = nil
+      Token(TkRD_COMMENT)
+    end
+
+    @OP.def_rule("\n") do |op, io|
+      print "\\n\n" if RubyLex.debug?
+      case @lex_state
+      when EXPR_BEG, EXPR_FNAME, EXPR_DOT
+	@continue = true
+      else
+	@continue = false
+	@lex_state = EXPR_BEG
+	until (@indent_stack.empty? || 
+	       [TkLPAREN, TkLBRACK, TkLBRACE, 
+		 TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last))
+	  @indent_stack.pop
+	end
+      end
+      @here_header = false
+      @here_readed = []
+      Token(TkNL)
+    end
+
+    @OP.def_rules("*", "**",	
+		  "=", "==", "===", 
+		  "=~", "<=>",	
+		  "<", "<=",
+		  ">", ">=", ">>") do
+      |op, io|
+      case @lex_state
+      when EXPR_FNAME, EXPR_DOT
+	@lex_state = EXPR_ARG
+      else
+	@lex_state = EXPR_BEG
+      end
+      Token(op)
+    end
+
+    @OP.def_rules("!", "!=", "!~") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      Token(op)
+    end
+
+    @OP.def_rules("<<") do
+      |op, io|
+      tk = nil
+      if @lex_state != EXPR_END && @lex_state != EXPR_CLASS &&
+	  (@lex_state != EXPR_ARG || @space_seen)
+	c = peek(0)
+	if /\S/ =~ c && (/["'`]/ =~ c || /[\w_]/ =~ c || c == "-")
+	  tk = identify_here_document
+	end
+      end
+      unless tk
+	tk = Token(op)
+	case @lex_state
+	when EXPR_FNAME, EXPR_DOT
+	  @lex_state = EXPR_ARG
+	else
+	  @lex_state = EXPR_BEG
+	end
+      end
+      tk
+    end
+
+    @OP.def_rules("'", '"') do
+      |op, io|
+      identify_string(op)
+    end
+
+    @OP.def_rules("`") do
+      |op, io|
+      if @lex_state == EXPR_FNAME
+	@lex_state = EXPR_END
+	Token(op)
+      else
+	identify_string(op)
+      end
+    end
+
+    @OP.def_rules('?') do
+      |op, io|
+      if @lex_state == EXPR_END
+	@lex_state = EXPR_BEG
+	Token(TkQUESTION)
+      else
+	ch = getc
+	if @lex_state == EXPR_ARG && ch =~ /\s/
+	  ungetc
+	  @lex_state = EXPR_BEG;
+	  Token(TkQUESTION)
+	else
+	  if (ch == '\\') 
+	    read_escape
+	  end
+	  @lex_state = EXPR_END
+	  Token(TkINTEGER)
+	end
+      end
+    end
+
+    @OP.def_rules("&", "&&", "|", "||") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      Token(op)
+    end
+    
+    @OP.def_rules("+=", "-=", "*=", "**=", 
+		  "&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      op =~ /^(.*)=$/
+      Token(TkOPASGN, $1)
+    end
+
+    @OP.def_rule("+@", proc{|op, io| @lex_state == EXPR_FNAME}) do
+      |op, io|
+      @lex_state = EXPR_ARG
+      Token(op)
+    end
+
+    @OP.def_rule("-@", proc{|op, io| @lex_state == EXPR_FNAME}) do
+      |op, io|
+      @lex_state = EXPR_ARG
+      Token(op)
+    end
+
+    @OP.def_rules("+", "-") do
+      |op, io|
+      catch(:RET) do
+	if @lex_state == EXPR_ARG
+	  if @space_seen and peek(0) =~ /[0-9]/
+	    throw :RET, identify_number
+	  else
+	    @lex_state = EXPR_BEG
+	  end
+	elsif @lex_state != EXPR_END and peek(0) =~ /[0-9]/
+	  throw :RET, identify_number
+	else
+	  @lex_state = EXPR_BEG
+	end
+	Token(op)
+      end
+    end
+
+    @OP.def_rule(".") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      if peek(0) =~ /[0-9]/
+	ungetc
+	identify_number
+      else
+	# for "obj.if" etc.
+	@lex_state = EXPR_DOT
+	Token(TkDOT)
+      end
+    end
+
+    @OP.def_rules("..", "...") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      Token(op)
+    end
+
+    lex_int2
+  end
+  
+  def lex_int2
+    @OP.def_rules("]", "}", ")") do
+      |op, io|
+      @lex_state = EXPR_END
+      @indent -= 1
+      @indent_stack.pop
+      Token(op)
+    end
+
+    @OP.def_rule(":") do
+      |op, io|
+      if @lex_state == EXPR_END || peek(0) =~ /\s/
+	@lex_state = EXPR_BEG
+	Token(TkCOLON)
+      else
+	@lex_state = EXPR_FNAME;
+	Token(TkSYMBEG)
+      end
+    end
+
+    @OP.def_rule("::") do
+       |op, io|
+#      p @lex_state.id2name, @space_seen
+      if @lex_state == EXPR_BEG or @lex_state == EXPR_ARG && @space_seen
+	@lex_state = EXPR_BEG
+	Token(TkCOLON3)
+      else
+	@lex_state = EXPR_DOT
+	Token(TkCOLON2)
+      end
+    end
+
+    @OP.def_rule("/") do
+      |op, io|
+      if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+	identify_string(op)
+      elsif peek(0) == '='
+	getc
+	@lex_state = EXPR_BEG
+	Token(TkOPASGN, "/") #/)
+      elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
+	identify_string(op)
+      else 
+	@lex_state = EXPR_BEG
+	Token("/") #/)
+      end
+    end
+
+    @OP.def_rules("^") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      Token("^")
+    end
+
+    #       @OP.def_rules("^=") do
+    # 	@lex_state = EXPR_BEG
+    # 	Token(OP_ASGN, :^)
+    #       end
+    
+    @OP.def_rules(",") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      Token(op)
+    end
+
+    @OP.def_rules(";") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      until (@indent_stack.empty? || 
+	     [TkLPAREN, TkLBRACK, TkLBRACE, 
+	       TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last))
+	@indent_stack.pop
+      end
+      Token(op)
+    end
+
+    @OP.def_rule("~") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      Token("~")
+    end
+
+    @OP.def_rule("~@", proc{|op, io| @lex_state == EXPR_FNAME}) do
+      |op, io|
+      @lex_state = EXPR_BEG
+      Token("~")
+    end
+    
+    @OP.def_rule("(") do
+      |op, io|
+      @indent += 1
+      if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+	@lex_state = EXPR_BEG
+	tk_c = TkfLPAREN
+      else
+	@lex_state = EXPR_BEG
+	tk_c = TkLPAREN
+      end
+      @indent_stack.push tk_c
+      tk = Token(tk_c)
+    end
+
+    @OP.def_rule("[]", proc{|op, io| @lex_state == EXPR_FNAME}) do
+      |op, io|
+      @lex_state = EXPR_ARG
+      Token("[]")
+    end
+
+    @OP.def_rule("[]=", proc{|op, io| @lex_state == EXPR_FNAME}) do
+      |op, io|
+      @lex_state = EXPR_ARG
+      Token("[]=")
+    end
+
+    @OP.def_rule("[") do
+      |op, io|
+      @indent += 1
+      if @lex_state == EXPR_FNAME
+	tk_c = TkfLBRACK
+      else
+	if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+	  tk_c = TkLBRACK
+	elsif @lex_state == EXPR_ARG && @space_seen
+	  tk_c = TkLBRACK
+	else
+	  tk_c = TkfLBRACK
+	end
+	@lex_state = EXPR_BEG
+      end
+      @indent_stack.push tk_c
+      Token(tk_c)
+    end
+
+    @OP.def_rule("{") do
+      |op, io|
+      @indent += 1
+      if @lex_state != EXPR_END && @lex_state != EXPR_ARG
+	tk_c = TkLBRACE
+      else
+	tk_c = TkfLBRACE
+      end
+      @lex_state = EXPR_BEG
+      @indent_stack.push tk_c
+      Token(tk_c)
+    end
+
+    @OP.def_rule('\\') do
+      |op, io|
+      if getc == "\n"
+	@space_seen = true
+	@continue = true
+	Token(TkSPACE)
+      else
+	ungetc
+	Token("\\")
+      end
+    end
+
+    @OP.def_rule('%') do
+      |op, io|
+      if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+	identify_quotation
+      elsif peek(0) == '='
+	getc
+	Token(TkOPASGN, :%)
+      elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
+	identify_quotation
+      else
+	@lex_state = EXPR_BEG
+	Token("%") #))
+      end
+    end
+
+    @OP.def_rule('$') do
+      |op, io|
+      identify_gvar
+    end
+
+    @OP.def_rule('@') do
+      |op, io|
+      if peek(0) =~ /[\w_@]/
+	ungetc
+	identify_identifier
+      else
+	Token("@")
+      end
+    end
+
+    #       @OP.def_rule("def", proc{|op, io| /\s/ =~ io.peek(0)}) do 
+    # 	|op, io|
+    # 	@indent += 1
+    # 	@lex_state = EXPR_FNAME
+    # #	@lex_state = EXPR_END
+    # #	until @rests[0] == "\n" or @rests[0] == ";"
+    # #	  rests.shift
+    # #	end
+    #       end
+
+    @OP.def_rule("") do
+      |op, io|
+      printf "MATCH: start %s: %s\n", op, io.inspect if RubyLex.debug?
+      if peek(0) =~ /[0-9]/
+	t = identify_number
+      elsif peek(0) =~ /[\w_]/
+	t = identify_identifier
+      end
+      printf "MATCH: end %s: %s\n", op, io.inspect if RubyLex.debug?
+      t
+    end
+    
+    p @OP if RubyLex.debug?
+  end
+  
+  def identify_gvar
+    @lex_state = EXPR_END
+    
+    case ch = getc
+    when /[~_*$?!@\/\\;,=:<>".]/   #"
+      Token(TkGVAR, "$" + ch)
+    when "-"
+      Token(TkGVAR, "$-" + getc)
+    when "&", "`", "'", "+"
+      Token(TkBACK_REF, "$"+ch)
+    when /[1-9]/
+      while getc =~ /[0-9]/; end
+      ungetc
+      Token(TkNTH_REF)
+    when /\w/
+      ungetc
+      ungetc
+      identify_identifier
+    else 
+      ungetc
+      Token("$")
+    end
+  end
+  
+  def identify_identifier
+    token = ""
+    if peek(0) =~ /[$@]/
+      token.concat(c = getc)
+      if c == "@" and peek(0) == "@"
+	token.concat getc
+      end
+    end
+
+    while (ch = getc) =~ /\w|_/
+      print ":", ch, ":" if RubyLex.debug?
+      token.concat ch
+    end
+    ungetc
+    
+    if (ch == "!" || ch == "?") && token[0,1] =~ /\w/ && peek(0) != "="
+      token.concat getc
+    end
+
+    # almost fix token
+
+    case token
+    when /^\$/
+      return Token(TkGVAR, token)
+    when /^\@\@/
+      @lex_state = EXPR_END
+      # p Token(TkCVAR, token)
+      return Token(TkCVAR, token)
+    when /^\@/
+      @lex_state = EXPR_END
+      return Token(TkIVAR, token)
+    end
+    
+    if @lex_state != EXPR_DOT
+      print token, "\n" if RubyLex.debug?
+
+      token_c, *trans = TkReading2Token[token]
+      if token_c
+	# reserved word?
+
+	if (@lex_state != EXPR_BEG &&
+	    @lex_state != EXPR_FNAME &&
+	    trans[1])
+	  # modifiers
+	  token_c = TkSymbol2Token[trans[1]]
+	  @lex_state = trans[0]
+	else
+	  if @lex_state != EXPR_FNAME
+	    if ENINDENT_CLAUSE.include?(token)
+	      # check for ``class = val'' etc.
+	      valid = true
+	      case token
+	      when "class"
+		valid = false unless peek_match?(/^\s*(<<|\w|::)/)
+	      when "def"
+		valid = false if peek_match?(/^\s*(([+-\/*&\|^]|<<|>>|\|\||\&\&)=|\&\&|\|\|)/)
+	      when "do"
+		valid = false if peek_match?(/^\s*([+-\/*]?=|\*|<|>|\&)/)
+	      when *ENINDENT_CLAUSE
+		valid = false if peek_match?(/^\s*([+-\/*]?=|\*|<|>|\&|\|)/)
+	      else
+		# no nothing
+	      end
+	      if valid
+		if token == "do"
+		  if ![TkFOR, TkWHILE, TkUNTIL].include?(@indent_stack.last)
+		    @indent += 1
+		    @indent_stack.push token_c
+		  end
+		else
+		  @indent += 1
+		  @indent_stack.push token_c
+		end
+#		p @indent_stack
+	      end
+
+	    elsif DEINDENT_CLAUSE.include?(token)
+	      @indent -= 1
+	      @indent_stack.pop
+	    end
+	    @lex_state = trans[0]
+	  else
+	    @lex_state = EXPR_END
+	  end
+	end
+	return Token(token_c, token)
+      end
+    end
+
+    if @lex_state == EXPR_FNAME
+      @lex_state = EXPR_END
+      if peek(0) == '='
+	token.concat getc
+      end
+    elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT
+      @lex_state = EXPR_ARG
+    else
+      @lex_state = EXPR_END
+    end
+
+    if token[0, 1] =~ /[A-Z]/
+      return Token(TkCONSTANT, token)
+    elsif token[token.size - 1, 1] =~ /[!?]/
+      return Token(TkFID, token)
+    else
+      return Token(TkIDENTIFIER, token)
+    end
+  end
+
+  def identify_here_document
+    ch = getc
+#    if lt = PERCENT_LTYPE[ch]
+    if ch == "-"
+      ch = getc
+      indent = true
+    end
+    if /['"`]/ =~ ch
+      lt = ch
+      quoted = ""
+      while (c = getc) && c != lt
+	quoted.concat c
+      end
+    else
+      lt = '"'
+      quoted = ch.dup
+      while (c = getc) && c =~ /\w/
+	quoted.concat c
+      end
+      ungetc
+    end
+
+    ltback, @ltype = @ltype, lt
+    reserve = []
+    while ch = getc
+      reserve.push ch
+      if ch == "\\"
+	reserve.push ch = getc
+      elsif ch == "\n"
+	break
+      end
+    end
+
+    @here_header = false
+    while l = gets
+      l = l.sub(/(:?\r)?\n\z/, '')
+      if (indent ? l.strip : l) == quoted
+ 	break
+      end
+    end
+
+    @here_header = true
+    @here_readed.concat reserve
+    while ch = reserve.pop
+      ungetc ch
+    end
+
+    @ltype = ltback
+    @lex_state = EXPR_END
+    Token(Ltype2Token[lt])
+  end
+  
+  def identify_quotation
+    ch = getc
+    if lt = PERCENT_LTYPE[ch]
+      ch = getc
+    elsif ch =~ /\W/
+      lt = "\""
+    else
+      RubyLex.fail SyntaxError, "unknown type of %string"
+    end
+#     if ch !~ /\W/
+#       ungetc
+#       next
+#     end
+    #@ltype = lt
+    @quoted = ch unless @quoted = PERCENT_PAREN[ch]
+    identify_string(lt, @quoted)
+  end
+
+  def identify_number
+    @lex_state = EXPR_END
+
+    if peek(0) == "0" && peek(1) !~ /[.eE]/
+      getc
+      case peek(0)
+      when /[xX]/
+	ch = getc
+	match = /[0-9a-fA-F_]/
+      when /[bB]/
+	ch = getc
+	match = /[01_]/
+      when /[oO]/
+	ch = getc
+	match = /[0-7_]/
+      when /[dD]/
+	ch = getc
+	match = /[0-9_]/
+      when /[0-7]/
+	match = /[0-7_]/
+      when /[89]/
+	RubyLex.fail SyntaxError, "Illegal octal digit"
+      else 
+	return Token(TkINTEGER)
+      end
+      
+      len0 = true
+      non_digit = false
+      while ch = getc
+	if match =~ ch
+	  if ch == "_"
+	    if non_digit
+	      RubyLex.fail SyntaxError, "trailing `#{ch}' in number"
+	    else
+	      non_digit = ch
+	    end
+	  else
+	    non_digit = false
+	    len0 = false
+	  end
+	else
+	  ungetc
+	  if len0
+	    RubyLex.fail SyntaxError, "numeric literal without digits"
+	  end
+	  if non_digit
+	    RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number"
+	  end
+	  break
+	end
+      end
+      return Token(TkINTEGER)
+    end
+    
+    type = TkINTEGER
+    allow_point = true
+    allow_e = true
+    non_digit = false
+    while ch = getc
+      case ch
+      when /[0-9]/
+	non_digit = false
+      when "_"
+	non_digit = ch
+      when allow_point && "."
+	if non_digit
+	  RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number"
+	end
+	type = TkFLOAT
+	if peek(0) !~ /[0-9]/
+	  type = TkINTEGER
+	  ungetc
+	  break
+	end
+	allow_point = false
+      when allow_e && "e", allow_e && "E"
+	if non_digit
+	  RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number"
+	end
+	type = TkFLOAT
+	if peek(0) =~ /[+-]/
+	  getc
+	end
+	allow_e = false
+	allow_point = false
+	non_digit = ch
+      else
+	if non_digit
+	  RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number"
+	end
+	ungetc
+	break
+      end
+    end
+    Token(type)
+  end
+  
+  def identify_string(ltype, quoted = ltype)
+    @ltype = ltype
+    @quoted = quoted
+    subtype = nil
+    begin
+      nest = 0
+      while ch = getc
+	if @quoted == ch and nest == 0
+	  break
+	elsif @ltype != "'" && @ltype != "]" && @ltype != ":" and ch == "#"
+	  subtype = true
+	elsif ch == '\\' #'
+	  read_escape
+	end
+	if PERCENT_PAREN.values.include?(@quoted) 
+	  if PERCENT_PAREN[ch] == @quoted
+	    nest += 1
+	  elsif ch == @quoted
+	    nest -= 1
+	  end
+	end
+      end
+      if @ltype == "/"
+	if peek(0) =~ /i|m|x|o|e|s|u|n/
+	  getc
+	end
+      end
+      if subtype
+	Token(DLtype2Token[ltype])
+      else
+	Token(Ltype2Token[ltype])
+      end
+    ensure
+      @ltype = nil
+      @quoted = nil
+      @lex_state = EXPR_END
+    end
+  end
+  
+  def identify_comment
+    @ltype = "#"
+
+    while ch = getc
+#      if ch == "\\" #"
+#	read_escape
+#      end
+      if ch == "\n"
+	@ltype = nil
+	ungetc
+	break
+      end
+    end
+    return Token(TkCOMMENT)
+  end
+  
+  def read_escape
+    case ch = getc
+    when "\n", "\r", "\f"
+    when "\\", "n", "t", "r", "f", "v", "a", "e", "b", "s" #"
+    when /[0-7]/
+      ungetc ch
+      3.times do
+	case ch = getc
+	when /[0-7]/
+	when nil
+	  break
+	else
+	  ungetc
+	  break
+	end
+      end
+      
+    when "x"
+      2.times do
+	case ch = getc
+	when /[0-9a-fA-F]/
+	when nil
+	  break
+	else
+	  ungetc
+	  break
+	end
+      end
+
+    when "M"
+      if (ch = getc) != '-'
+	ungetc
+      else
+	if (ch = getc) == "\\" #"
+	  read_escape
+	end
+      end
+
+    when "C", "c" #, "^"
+      if ch == "C" and (ch = getc) != "-"
+	ungetc
+      elsif (ch = getc) == "\\" #"
+	read_escape
+      end
+    else
+      # other characters 
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ruby-token.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ruby-token.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ruby-token.rb	(revision 18425)
@@ -0,0 +1,273 @@
+#
+#   irb/ruby-token.rb - ruby tokens 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+module RubyToken
+  EXPR_BEG = :EXPR_BEG
+  EXPR_MID = :EXPR_MID
+  EXPR_END = :EXPR_END
+  EXPR_ARG = :EXPR_ARG
+  EXPR_FNAME = :EXPR_FNAME
+  EXPR_DOT = :EXPR_DOT
+  EXPR_CLASS = :EXPR_CLASS
+
+  # for ruby 1.4X
+  if !defined?(Symbol)
+    Symbol = Integer
+  end
+  
+  class Token
+    def initialize(seek, line_no, char_no)
+      @seek = seek
+      @line_no = line_no
+      @char_no = char_no
+    end
+    attr :seek
+    attr :line_no
+    attr :char_no
+  end
+
+  class TkNode < Token
+    def initialize(seek, line_no, char_no)
+      super
+    end
+    attr :node
+  end
+
+  class TkId < Token
+    def initialize(seek, line_no, char_no, name)
+      super(seek, line_no, char_no)
+      @name = name
+    end
+    attr :name
+  end
+
+  class TkVal < Token
+    def initialize(seek, line_no, char_no, value = nil)
+      super(seek, line_no, char_no)
+      @value = value
+    end
+    attr :value
+  end
+
+  class TkOp < Token
+    attr :name, true
+  end
+
+  class TkOPASGN < TkOp
+    def initialize(seek, line_no, char_no, op)
+      super(seek, line_no, char_no)
+      op = TkReading2Token[op][0] unless op.kind_of?(Symbol)
+      @op = op
+    end
+    attr :op
+  end
+
+  class TkUnknownChar < Token
+    def initialize(seek, line_no, char_no, id)
+      super(seek, line_no, char_no)
+      @name = name
+    end
+    attr :name
+  end
+
+  class TkError < Token
+  end
+
+  def Token(token, value = nil)
+    case token
+    when String
+      if (tk = TkReading2Token[token]).nil?
+	IRB.fail TkReading2TokenNoKey, token
+      end
+      tk = Token(tk[0], value) 
+      if tk.kind_of?(TkOp)
+	tk.name = token
+      end
+      return tk
+    when Symbol
+      if (tk = TkSymbol2Token[token]).nil?
+	IRB.fail TkSymbol2TokenNoKey, token
+      end
+      return Token(tk[0], value) 
+    else 
+      if (token.ancestors & [TkId, TkVal, TkOPASGN, TkUnknownChar]).empty?
+	token.new(@prev_seek, @prev_line_no, @prev_char_no)
+      else
+	token.new(@prev_seek, @prev_line_no, @prev_char_no, value)
+      end
+    end
+  end
+
+  TokenDefinitions = [
+    [:TkCLASS,      TkId,  "class",  EXPR_CLASS],
+    [:TkMODULE,     TkId,  "module", EXPR_BEG],
+    [:TkDEF,	    TkId,  "def",    EXPR_FNAME],
+    [:TkUNDEF,      TkId,  "undef",  EXPR_FNAME],
+    [:TkBEGIN,      TkId,  "begin",  EXPR_BEG],
+    [:TkRESCUE,     TkId,  "rescue", EXPR_MID],
+    [:TkENSURE,     TkId,  "ensure", EXPR_BEG],
+    [:TkEND,	    TkId,  "end",    EXPR_END],
+    [:TkIF,         TkId,  "if",     EXPR_BEG, :TkIF_MOD],
+    [:TkUNLESS,     TkId,  "unless", EXPR_BEG, :TkUNLESS_MOD],
+    [:TkTHEN,	    TkId,  "then",   EXPR_BEG],
+    [:TkELSIF,      TkId,  "elsif",  EXPR_BEG],
+    [:TkELSE,	    TkId,  "else",   EXPR_BEG],
+    [:TkCASE,	    TkId,  "case",   EXPR_BEG],
+    [:TkWHEN,	    TkId,  "when",   EXPR_BEG],
+    [:TkWHILE,      TkId,  "while",  EXPR_BEG, :TkWHILE_MOD],
+    [:TkUNTIL,      TkId,  "until",  EXPR_BEG, :TkUNTIL_MOD],
+    [:TkFOR,	    TkId,  "for",    EXPR_BEG],
+    [:TkBREAK,      TkId,  "break",  EXPR_END],
+    [:TkNEXT,	    TkId,  "next",   EXPR_END],
+    [:TkREDO,	    TkId,  "redo",   EXPR_END],
+    [:TkRETRY,      TkId,  "retry",  EXPR_END],
+    [:TkIN,	    TkId,  "in",     EXPR_BEG],
+    [:TkDO,	    TkId,  "do",     EXPR_BEG],
+    [:TkRETURN,     TkId,  "return", EXPR_MID],
+    [:TkYIELD,      TkId,  "yield",  EXPR_END],
+    [:TkSUPER,      TkId,  "super",  EXPR_END],
+    [:TkSELF,	    TkId,  "self",   EXPR_END],
+    [:TkNIL, 	    TkId,  "nil",    EXPR_END],
+    [:TkTRUE,	    TkId,  "true",   EXPR_END],
+    [:TkFALSE,      TkId,  "false",  EXPR_END],
+    [:TkAND,	    TkId,  "and",    EXPR_BEG],
+    [:TkOR, 	    TkId,  "or",     EXPR_BEG],
+    [:TkNOT,	    TkId,  "not",    EXPR_BEG],
+    [:TkIF_MOD,     TkId],
+    [:TkUNLESS_MOD, TkId],
+    [:TkWHILE_MOD,  TkId],
+    [:TkUNTIL_MOD,  TkId],
+    [:TkALIAS,      TkId,  "alias",    EXPR_FNAME],
+    [:TkDEFINED,    TkId,  "defined?", EXPR_END],
+    [:TklBEGIN,     TkId,  "BEGIN",    EXPR_END],
+    [:TklEND,	    TkId,  "END",      EXPR_END],
+    [:Tk__LINE__,   TkId,  "__LINE__", EXPR_END],
+    [:Tk__FILE__,   TkId,  "__FILE__", EXPR_END],
+
+    [:TkIDENTIFIER, TkId],
+    [:TkFID,	    TkId],
+    [:TkGVAR,	    TkId],
+    [:TkCVAR,	    TkId],
+    [:TkIVAR,	    TkId],
+    [:TkCONSTANT,   TkId],
+
+    [:TkINTEGER,    TkVal],
+    [:TkFLOAT,      TkVal],
+    [:TkSTRING,     TkVal],
+    [:TkXSTRING,    TkVal],
+    [:TkREGEXP,     TkVal],
+    [:TkSYMBOL,     TkVal],
+
+    [:TkDSTRING,    TkNode],
+    [:TkDXSTRING,   TkNode],
+    [:TkDREGEXP,    TkNode],
+    [:TkNTH_REF,    TkNode],
+    [:TkBACK_REF,   TkNode],
+
+    [:TkUPLUS,      TkOp,   "+@"],
+    [:TkUMINUS,     TkOp,   "-@"],
+    [:TkPOW,	    TkOp,   "**"],
+    [:TkCMP,	    TkOp,   "<=>"],
+    [:TkEQ,	    TkOp,   "=="],
+    [:TkEQQ,	    TkOp,   "==="],
+    [:TkNEQ,	    TkOp,   "!="],
+    [:TkGEQ,	    TkOp,   ">="],
+    [:TkLEQ,	    TkOp,   "<="],
+    [:TkANDOP,      TkOp,   "&&"],
+    [:TkOROP,	    TkOp,   "||"],
+    [:TkMATCH,      TkOp,   "=~"],
+    [:TkNMATCH,     TkOp,   "!~"],
+    [:TkDOT2,	    TkOp,   ".."],
+    [:TkDOT3,	    TkOp,   "..."],
+    [:TkAREF,	    TkOp,   "[]"],
+    [:TkASET,	    TkOp,   "[]="],
+    [:TkLSHFT,      TkOp,   "<<"],
+    [:TkRSHFT,      TkOp,   ">>"],
+    [:TkCOLON2,     TkOp],
+    [:TkCOLON3,     TkOp],
+#   [:OPASGN,	    TkOp],               # +=, -=  etc. #
+    [:TkASSOC,      TkOp,   "=>"],
+    [:TkQUESTION,   TkOp,   "?"],	 #?
+    [:TkCOLON,      TkOp,   ":"],        #:
+    
+    [:TkfLPAREN],         # func( #
+    [:TkfLBRACK],         # func[ #
+    [:TkfLBRACE],         # func{ #
+    [:TkSTAR],            # *arg
+    [:TkAMPER],           # &arg #
+    [:TkSYMBEG],          # :SYMBOL
+
+    [:TkGT,	    TkOp,   ">"],
+    [:TkLT,	    TkOp,   "<"],
+    [:TkPLUS,	    TkOp,   "+"],
+    [:TkMINUS,      TkOp,   "-"],
+    [:TkMULT,	    TkOp,   "*"],
+    [:TkDIV,	    TkOp,   "/"],
+    [:TkMOD,	    TkOp,   "%"],
+    [:TkBITOR,      TkOp,   "|"],
+    [:TkBITXOR,     TkOp,   "^"],
+    [:TkBITAND,     TkOp,   "&"],
+    [:TkBITNOT,     TkOp,   "~"],
+    [:TkNOTOP,      TkOp,   "!"],
+
+    [:TkBACKQUOTE,  TkOp,   "`"],
+
+    [:TkASSIGN,     Token,  "="],
+    [:TkDOT,	    Token,  "."],
+    [:TkLPAREN,     Token,  "("],  #(exp)
+    [:TkLBRACK,     Token,  "["],  #[arry]
+    [:TkLBRACE,     Token,  "{"],  #{hash}
+    [:TkRPAREN,     Token,  ")"],
+    [:TkRBRACK,     Token,  "]"],
+    [:TkRBRACE,     Token,  "}"],
+    [:TkCOMMA,      Token,  ","],
+    [:TkSEMICOLON,  Token,  ";"],
+
+    [:TkCOMMENT],
+    [:TkRD_COMMENT],
+    [:TkSPACE],
+    [:TkNL],
+    [:TkEND_OF_SCRIPT],
+
+    [:TkBACKSLASH,  TkUnknownChar,  "\\"],
+    [:TkAT,	    TkUnknownChar,  "@"],
+    [:TkDOLLAR,     TkUnknownChar,  "$"],
+  ]
+
+  # {reading => token_class}
+  # {reading => [token_class, *opt]}
+  TkReading2Token = {}
+  TkSymbol2Token = {}
+
+  def RubyToken.def_token(token_n, super_token = Token, reading = nil, *opts)
+    token_n = token_n.id2name if token_n.kind_of?(Symbol)
+    if RubyToken.const_defined?(token_n)
+      IRB.fail AlreadyDefinedToken, token_n
+    end
+    token_c = eval("class #{token_n} < #{super_token}; end; #{token_n}")
+    
+    if reading
+      if TkReading2Token[reading]
+	IRB.fail TkReading2TokenDuplicateError, token_n, reading
+      end
+      if opts.empty?
+	TkReading2Token[reading] = [token_c]
+      else
+	TkReading2Token[reading] = [token_c].concat(opts)
+      end
+    end
+    TkSymbol2Token[token_n.intern] = token_c
+  end
+
+  for defs in TokenDefinitions
+    def_token(*defs)
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/slex.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/slex.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/slex.rb	(revision 18425)
@@ -0,0 +1,285 @@
+#
+#   irb/slex.rb - symple lex analizer
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+require "e2mmap"
+require "irb/notifier"
+
+module IRB
+  class SLex
+    @RCS_ID='-$Id: slex.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+    extend Exception2MessageMapper
+    def_exception :ErrNodeNothing, "node nothing"
+    def_exception :ErrNodeAlreadyExists, "node already exists"
+
+    DOUT = Notifier::def_notifier("SLex::")
+    D_WARN = DOUT::def_notifier(1, "Warn: ")
+    D_DEBUG = DOUT::def_notifier(2, "Debug: ")
+    D_DETAIL = DOUT::def_notifier(4, "Detail: ")
+    
+    DOUT.level = Notifier::D_NOMSG
+
+    def initialize
+      @head = Node.new("")
+    end
+    
+    def def_rule(token, preproc = nil, postproc = nil, &block)
+      D_DETAIL.pp token
+
+      postproc = block if block_given?
+      node = create(token, preproc, postproc)
+    end
+    
+    def def_rules(*tokens, &block)
+      if block_given?
+	p = block
+      end
+      for token in tokens
+	def_rule(token, nil, p)
+      end
+    end
+    
+    def preproc(token, proc)
+      node = search(token)
+      node.preproc=proc
+    end
+    
+    #$BMW%A%'%C%/(B? 
+    def postproc(token)
+      node = search(token, proc)
+      node.postproc=proc
+    end
+    
+    def search(token)
+      @head.search(token.split(//))
+    end
+
+    def create(token, preproc = nil, postproc = nil)
+      @head.create_subnode(token.split(//), preproc, postproc)
+    end
+    
+    def match(token)
+      case token
+      when Array
+      when String
+	return match(token.split(//))
+      else
+	return @head.match_io(token)
+      end
+      ret = @head.match(token)
+      D_DETAIL.exec_if{D_DEATIL.printf "match end: %s:%s\n", ret, token.inspect}
+      ret
+    end
+    
+    def inspect
+      format("<SLex: @head = %s>", @head.inspect)
+    end
+
+    #----------------------------------------------------------------------
+    #
+    #   class Node - 
+    #
+    #----------------------------------------------------------------------
+    class Node
+      # if postproc is nil, this node is an abstract node.
+      # if postproc is non-nil, this node is a real node.
+      def initialize(preproc = nil, postproc = nil)
+	@Tree = {}
+	@preproc = preproc
+	@postproc = postproc
+      end
+
+      attr_accessor :preproc
+      attr_accessor :postproc
+      
+      def search(chrs, opt = nil)
+	return self if chrs.empty?
+	ch = chrs.shift
+	if node = @Tree[ch]
+	  node.search(chrs, opt)
+	else
+	  if opt
+	    chrs.unshift ch
+	    self.create_subnode(chrs)
+	  else
+	    SLex.fail ErrNodeNothing
+	  end
+	end
+      end
+      
+      def create_subnode(chrs, preproc = nil, postproc = nil)
+	if chrs.empty?
+	  if @postproc
+	    D_DETAIL.pp node
+	    SLex.fail ErrNodeAlreadyExists
+	  else
+	    D_DEBUG.puts "change abstract node to real node."
+	    @preproc = preproc
+	    @postproc = postproc
+	  end
+	  return self
+	end
+	
+	ch = chrs.shift
+	if node = @Tree[ch]
+	  if chrs.empty?
+	    if node.postproc
+	      DebugLogger.pp node
+	      DebugLogger.pp self
+	      DebugLogger.pp ch
+	      DebugLogger.pp chrs
+	      SLex.fail ErrNodeAlreadyExists
+	    else
+	      D_WARN.puts "change abstract node to real node"
+	      node.preproc = preproc
+	      node.postproc = postproc
+	    end
+	  else
+	    node.create_subnode(chrs, preproc, postproc)
+	  end
+	else
+	  if chrs.empty?
+	    node = Node.new(preproc, postproc)
+	  else
+	    node = Node.new
+	    node.create_subnode(chrs, preproc, postproc)
+	  end
+	  @Tree[ch] = node
+	end
+	node
+      end
+
+      #
+      # chrs: String
+      #       character array
+      #       io must have getc()/ungetc(); and ungetc() must be
+      #       able to be called arbitrary number of times. 
+      #
+      def match(chrs, op = "")
+	D_DETAIL.print "match>: ", chrs, "op:", op, "\n"
+	if chrs.empty?
+	  if @preproc.nil? || @preproc.call(op, chrs)
+	    DOUT.printf(D_DETAIL, "op1: %s\n", op)
+	    @postproc.call(op, chrs)
+	  else
+	    nil
+	  end
+	else
+	  ch = chrs.shift
+	  if node = @Tree[ch]
+	    if ret = node.match(chrs, op+ch)
+	      return ret
+	    else
+	      chrs.unshift ch
+	      if @postproc and @preproc.nil? || @preproc.call(op, chrs)
+		DOUT.printf(D_DETAIL, "op2: %s\n", op.inspect)
+		ret = @postproc.call(op, chrs)
+		return ret
+	      else
+		return nil
+	      end
+	    end
+	  else
+	    chrs.unshift ch
+	    if @postproc and @preproc.nil? || @preproc.call(op, chrs)
+	      DOUT.printf(D_DETAIL, "op3: %s\n", op)
+	      @postproc.call(op, chrs)
+	      return ""
+	    else
+	      return nil
+	    end
+	  end
+	end
+      end
+
+      def match_io(io, op = "")
+	if op == ""
+	  ch = io.getc
+	  if ch == nil
+	    return nil
+	  end
+	else
+	  ch = io.getc_of_rests
+	end
+	if ch.nil?
+	  if @preproc.nil? || @preproc.call(op, io)
+	    D_DETAIL.printf("op1: %s\n", op)
+	    @postproc.call(op, io)
+	  else
+	    nil
+	  end
+	else
+	  if node = @Tree[ch]
+	    if ret = node.match_io(io, op+ch)
+	      ret
+	    else
+	      io.ungetc ch
+	      if @postproc and @preproc.nil? || @preproc.call(op, io)
+		DOUT.exec_if{D_DETAIL.printf "op2: %s\n", op.inspect}
+		@postproc.call(op, io)
+	      else
+		nil
+	      end
+	    end
+	  else
+	    io.ungetc ch
+	    if @postproc and @preproc.nil? || @preproc.call(op, io)
+	      D_DETAIL.printf("op3: %s\n", op)
+	      @postproc.call(op, io)
+	    else
+	      nil
+	    end
+	  end
+	end
+      end
+    end
+  end
+end
+
+SLex=IRB::SLex
+
+if $0 == __FILE__
+  #    Tracer.on
+  case $1
+  when "1"
+    tr = SLex.new
+    print "0: ", tr.inspect, "\n"
+    tr.def_rule("=") {print "=\n"}
+    print "1: ", tr.inspect, "\n"
+    tr.def_rule("==") {print "==\n"}
+    print "2: ", tr.inspect, "\n"
+    
+    print "case 1:\n"
+    print tr.match("="), "\n"
+    print "case 2:\n"
+    print tr.match("=="), "\n"
+    print "case 3:\n"
+    print tr.match("=>"), "\n"
+    
+  when "2"
+    tr = SLex.new
+    print "0: ", tr.inspect, "\n"
+    tr.def_rule("=") {print "=\n"}
+    print "1: ", tr.inspect, "\n"
+    tr.def_rule("==", proc{false}) {print "==\n"}
+    print "2: ", tr.inspect, "\n"
+    
+    print "case 1:\n"
+    print tr.match("="), "\n"
+    print "case 2:\n"
+    print tr.match("=="), "\n"
+    print "case 3:\n"
+    print tr.match("=>"), "\n"
+  end
+  exit
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/version.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/version.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/version.rb	(revision 18425)
@@ -0,0 +1,16 @@
+#
+#   irb/version.rb - irb version definition file
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ishitsuka.com)
+#
+# --
+#
+#   
+#
+
+module IRB
+  @RELEASE_VERSION = "0.9.5"
+  @LAST_UPDATE_DATE = "05/04/13"
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/workspace.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/workspace.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/workspace.rb	(revision 18425)
@@ -0,0 +1,107 @@
+#
+#   irb/workspace-binding.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+module IRB
+  class WorkSpace
+    # create new workspace. set self to main if specified, otherwise
+    # inherit main from TOPLEVEL_BINDING.
+    def initialize(*main)
+      if main[0].kind_of?(Binding)
+	@binding = main.shift
+      elsif IRB.conf[:SINGLE_IRB]
+	@binding = TOPLEVEL_BINDING
+      else
+	case IRB.conf[:CONTEXT_MODE]
+	when 0	# binding in proc on TOPLEVEL_BINDING
+	  @binding = eval("proc{binding}.call",
+		      TOPLEVEL_BINDING, 
+		      __FILE__,
+		      __LINE__)
+	when 1	# binding in loaded file
+	  require "tempfile"
+	  f = Tempfile.open("irb-binding")
+	  f.print <<EOF
+	  $binding = binding
+EOF
+	  f.close
+	  load f.path
+	  @binding = $binding
+
+	when 2	# binding in loaded file(thread use)
+	  unless defined? BINDING_QUEUE
+	    require "thread"
+	    
+	    IRB.const_set("BINDING_QUEUE", SizedQueue.new(1))
+	    Thread.abort_on_exception = true
+	    Thread.start do
+	      eval "require \"irb/ws-for-case-2\"", TOPLEVEL_BINDING, __FILE__, __LINE__
+	    end
+	    Thread.pass
+	  end
+	  @binding = BINDING_QUEUE.pop
+
+	when 3	# binging in function on TOPLEVEL_BINDING(default)
+	  @binding = eval("def irb_binding; binding; end; irb_binding",
+		      TOPLEVEL_BINDING, 
+		      __FILE__,
+		      __LINE__ - 3)
+	end
+      end
+      if main.empty?
+	@main = eval("self", @binding)
+      else
+	@main = main[0]
+	IRB.conf[:__MAIN__] = @main
+	case @main
+	when Module
+	  @binding = eval("IRB.conf[:__MAIN__].module_eval('binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
+	else
+	  begin 
+	    @binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
+	  rescue TypeError
+	    IRB.fail CantChangeBinding, @main.inspect
+	  end
+	end
+      end
+      eval("_=nil", @binding)
+    end
+
+    attr_reader :binding
+    attr_reader :main
+
+    def evaluate(context, statements, file = __FILE__, line = __LINE__)
+      eval(statements, @binding, file, line)
+    end
+  
+    # error message manipulator
+    def filter_backtrace(bt)
+      case IRB.conf[:CONTEXT_MODE]
+      when 0
+	return nil if bt =~ /\(irb_local_binding\)/
+      when 1
+	if(bt =~ %r!/tmp/irb-binding! or
+	   bt =~ %r!irb/.*\.rb! or
+	   bt =~ /irb\.rb/)
+	  return nil
+	end
+      when 2
+	return nil if bt =~ /irb\/.*\.rb/
+      when 3
+	return nil if bt =~ /irb\/.*\.rb/
+	bt.sub!(/:\s*in `irb_binding'/){""} 
+      end
+      bt
+    end
+
+    def IRB.delete_caller
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ws-for-case-2.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ws-for-case-2.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/ws-for-case-2.rb	(revision 18425)
@@ -0,0 +1,15 @@
+#
+#   irb/ws-for-case-2.rb - 
+#   	$Release Version: 0.9.5$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
+#
+# --
+#
+#   
+#
+
+while true
+  IRB::BINDING_QUEUE.push b = binding
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/xmp.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/xmp.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/irb/xmp.rb	(revision 18425)
@@ -0,0 +1,86 @@
+#
+#   xmp.rb - irb version of gotoken xmp
+#   	$Release Version: 0.9$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#   
+#
+
+require "irb"
+require "irb/frame"
+
+class XMP
+  @RCS_ID='-$Id: xmp.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
+
+  def initialize(bind = nil)
+    IRB.init_config(nil)
+    #IRB.parse_opts
+    #IRB.load_modules
+
+    IRB.conf[:PROMPT_MODE] = :XMP
+
+    bind = IRB::Frame.top(1) unless bind
+    ws = IRB::WorkSpace.new(bind)
+    @io = StringInputMethod.new
+    @irb = IRB::Irb.new(ws, @io)
+    @irb.context.ignore_sigint = false
+
+#    IRB.conf[:IRB_RC].call(@irb.context) if IRB.conf[:IRB_RC]
+    IRB.conf[:MAIN_CONTEXT] = @irb.context
+  end
+
+  def puts(exps)
+    @io.puts exps
+
+    if @irb.context.ignore_sigint
+      begin
+	trap_proc_b = trap("SIGINT"){@irb.signal_handle}
+	catch(:IRB_EXIT) do
+	  @irb.eval_input
+	end
+      ensure
+	trap("SIGINT", trap_proc_b)
+      end
+    else
+      catch(:IRB_EXIT) do
+	@irb.eval_input
+      end
+    end
+  end
+
+  class StringInputMethod < IRB::InputMethod
+    def initialize
+      super
+      @exps = []
+    end
+
+    def eof?
+      @exps.empty?
+    end
+
+    def gets
+      while l = @exps.shift
+	next if /^\s+$/ =~ l
+	l.concat "\n"
+	print @prompt, l
+	break
+      end
+      l
+    end
+
+    def puts(exps)
+      @exps.concat exps.split(/\n/)
+    end
+  end
+end
+
+def xmp(exps, bind = nil)
+  bind = IRB::Frame.top(1) unless bind
+  xmp = XMP.new(bind)
+  xmp.puts exps
+  xmp
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/jcode.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/jcode.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/jcode.rb	(revision 18425)
@@ -0,0 +1,220 @@
+# jcode.rb - ruby code to handle japanese (EUC/SJIS) string
+
+if $VERBOSE && $KCODE == "NONE"
+  warn "Warning: $KCODE is NONE."
+end
+
+$vsave, $VERBOSE = $VERBOSE, false
+class String
+  warn "feel free for some warnings:\n" if $VERBOSE
+
+  def _regex_quote(str)
+    str.gsub(/(\\[\[\]\-\\])|\\(.)|([\[\]\\])/) do
+      $1 || $2 || '\\' + $3
+    end
+  end
+  private :_regex_quote
+
+  PATTERN_SJIS = '[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]'
+  PATTERN_EUC = '[\xa1-\xfe][\xa1-\xfe]'
+  PATTERN_UTF8 = '[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf][\x80-\xbf]'
+
+  RE_SJIS = Regexp.new(PATTERN_SJIS, 0, 'n')
+  RE_EUC = Regexp.new(PATTERN_EUC, 0, 'n')
+  RE_UTF8 = Regexp.new(PATTERN_UTF8, 0, 'n')
+
+  SUCC = {}
+  SUCC['s'] = Hash.new(1)
+  for i in 0 .. 0x3f
+    SUCC['s'][i.chr] = 0x40 - i
+  end
+  SUCC['s']["\x7e"] = 0x80 - 0x7e
+  SUCC['s']["\xfd"] = 0x100 - 0xfd
+  SUCC['s']["\xfe"] = 0x100 - 0xfe
+  SUCC['s']["\xff"] = 0x100 - 0xff
+  SUCC['e'] = Hash.new(1)
+  for i in 0 .. 0xa0
+    SUCC['e'][i.chr] = 0xa1 - i
+  end
+  SUCC['e']["\xfe"] = 2
+  SUCC['u'] = Hash.new(1)
+  for i in 0 .. 0x7f
+    SUCC['u'][i.chr] = 0x80 - i
+  end
+  SUCC['u']["\xbf"] = 0x100 - 0xbf
+
+  def mbchar?
+    case $KCODE[0]
+    when ?s, ?S
+      self =~ RE_SJIS
+    when ?e, ?E
+      self =~ RE_EUC
+    when ?u, ?U
+      self =~ RE_UTF8
+    else
+      nil
+    end
+  end
+
+  def end_regexp
+    case $KCODE[0]
+    when ?s, ?S
+      /#{PATTERN_SJIS}$/on
+    when ?e, ?E
+      /#{PATTERN_EUC}$/on
+    when ?u, ?U
+      /#{PATTERN_UTF8}$/on
+    else
+      /.$/on
+    end
+  end
+
+  alias original_succ! succ!
+  private :original_succ!
+
+  alias original_succ succ
+  private :original_succ
+
+  def succ!
+    reg = end_regexp
+    if  $KCODE != 'NONE' && self =~ reg
+      succ_table = SUCC[$KCODE[0,1].downcase]
+      begin
+	self[-1] += succ_table[self[-1]]
+	self[-2] += 1 if self[-1] == 0
+      end while self !~ reg
+      self
+    else
+      original_succ!
+    end
+  end
+
+  def succ
+    str = self.dup
+    str.succ! or str
+  end
+
+  private
+
+  def _expand_ch str
+    a = []
+    str.scan(/(?:\\(.)|([^\\]))-(?:\\(.)|([^\\]))|(?:\\(.)|(.))/m) do
+      from = $1 || $2
+      to = $3 || $4
+      one = $5 || $6
+      if one
+	a.push one
+      elsif from.length != to.length
+	next
+      elsif from.length == 1
+	from[0].upto(to[0]) { |c| a.push c.chr }
+      else
+	from.upto(to) { |c| a.push c }
+      end
+    end
+    a
+  end
+
+  def expand_ch_hash from, to
+    h = {}
+    afrom = _expand_ch(from)
+    ato = _expand_ch(to)
+    afrom.each_with_index do |x,i| h[x] = ato[i] || ato[-1] end
+    h
+  end
+
+  HashCache = {}
+  TrPatternCache = {}
+  DeletePatternCache = {}
+  SqueezePatternCache = {}
+
+  public
+
+  def tr!(from, to)
+    return nil if from == ""
+    return self.delete!(from) if to == ""
+
+    pattern = TrPatternCache[from] ||= /[#{_regex_quote(from)}]/
+    if from[0] == ?^
+      last = /.$/.match(to)[0]
+      self.gsub!(pattern, last)
+    else
+      h = HashCache[from + "1-0" + to] ||= expand_ch_hash(from, to)
+      self.gsub!(pattern) do |c| h[c] end
+    end
+  end
+
+  def tr(from, to)
+    (str = self.dup).tr!(from, to) or str
+  end
+
+  def delete!(del)
+    return nil if del == ""
+    self.gsub!(DeletePatternCache[del] ||= /[#{_regex_quote(del)}]+/, '')
+  end
+
+  def delete(del)
+    (str = self.dup).delete!(del) or str
+  end
+
+  def squeeze!(del=nil)
+    return nil if del == ""
+    pattern =
+      if del
+	SqueezePatternCache[del] ||= /([#{_regex_quote(del)}])\1+/
+      else
+	/(.|\n)\1+/
+      end
+    self.gsub!(pattern, '\1')
+  end
+
+  def squeeze(del=nil)
+    (str = self.dup).squeeze!(del) or str
+  end
+
+  def tr_s!(from, to)
+    return self.delete!(from) if to.length == 0
+
+    pattern = SqueezePatternCache[from] ||= /([#{_regex_quote(from)}])\1*/
+    if from[0] == ?^
+      last = /.$/.match(to)[0]
+      self.gsub!(pattern, last)
+    else
+      h = HashCache[from + "1-0" + to] ||= expand_ch_hash(from, to)
+      self.gsub!(pattern) do h[$1] end
+    end
+  end
+
+  def tr_s(from, to)
+    (str = self.dup).tr_s!(from,to) or str
+  end
+
+  def chop!
+    self.gsub!(/(?:.|\r?\n)\z/, '')
+  end
+
+  def chop
+    (str = self.dup).chop! or str
+  end
+
+  def jlength
+    self.gsub(/[^\Wa-zA-Z_\d]/, ' ').length
+  end
+  alias jsize jlength
+
+  def jcount(str)
+    self.delete("^#{str}").jlength
+  end
+
+  def each_char
+    if block_given?
+      scan(/./m) do |x|
+        yield x
+      end
+    else
+      scan(/./m)
+    end
+  end
+
+end
+$VERBOSE = $vsave
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/kconv.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/kconv.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/kconv.rb	(revision 18425)
@@ -0,0 +1,367 @@
+#
+# kconv.rb - Kanji Converter.
+#
+# $Id: kconv.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+# ----
+#
+# kconv.rb implements the Kconv class for Kanji Converter.  Additionally,
+# some methods in String classes are added to allow easy conversion.
+#
+
+require 'nkf'
+
+#
+# Kanji Converter for Ruby.
+#
+module Kconv
+  #
+  # Public Constants
+  #
+  
+  #Constant of Encoding
+  
+  # Auto-Detect
+  AUTO = NKF::AUTO
+  # ISO-2022-JP
+  JIS = NKF::JIS
+  # EUC-JP
+  EUC = NKF::EUC
+  # Shift_JIS
+  SJIS = NKF::SJIS
+  # BINARY
+  BINARY = NKF::BINARY
+  # NOCONV
+  NOCONV = NKF::NOCONV
+  # ASCII
+  ASCII = NKF::ASCII
+  # UTF-8
+  UTF8 = NKF::UTF8
+  # UTF-16
+  UTF16 = NKF::UTF16
+  # UTF-32
+  UTF32 = NKF::UTF32
+  # UNKNOWN
+  UNKNOWN = NKF::UNKNOWN
+
+  #
+  # Private Constants
+  #
+  
+  # Revision of kconv.rb
+  REVISION = %q$Revision: 11708 $
+  
+  #Regexp of Encoding
+  
+  # Regexp of Shift_JIS string (private constant)
+  RegexpShiftjis = /\A(?:
+		       [\x00-\x7f\xa1-\xdf] |
+		       [\x81-\x9f\xe0-\xfc][\x40-\x7e\x80-\xfc] 
+		      )*\z/nx
+
+  # Regexp of EUC-JP string (private constant)
+  RegexpEucjp = /\A(?:
+		    [\x00-\x7f]                         |
+		    \x8e        [\xa1-\xdf]             |
+		    \x8f        [\xa1-\xfe] [\xa1-\xfe] |
+		    [\xa1-\xfe] [\xa1-\xfe]
+		   )*\z/nx
+
+  # Regexp of UTF-8 string (private constant)
+  RegexpUtf8  = /\A(?:
+		    [\x00-\x7f]                                     |
+		    [\xc2-\xdf] [\x80-\xbf]                         |
+		    \xe0        [\xa0-\xbf] [\x80-\xbf]             |
+		    [\xe1-\xef] [\x80-\xbf] [\x80-\xbf]             |
+		    \xf0        [\x90-\xbf] [\x80-\xbf] [\x80-\xbf] |
+		    [\xf1-\xf3] [\x80-\xbf] [\x80-\xbf] [\x80-\xbf] |
+		    \xf4        [\x80-\x8f] [\x80-\xbf] [\x80-\xbf]
+		   )*\z/nx
+
+  #
+  # Public Methods
+  #
+  
+  # call-seq:
+  #    Kconv.kconv(str, out_code, in_code = Kconv::AUTO)
+  #
+  # Convert <code>str</code> to out_code.
+  # <code>out_code</code> and <code>in_code</code> are given as constants of Kconv.
+  #
+  # *Note*
+  # This method decode MIME encoded string and
+  # convert halfwidth katakana to fullwidth katakana.
+  # If you don't want to decode them, use NKF.nkf.
+  def kconv(str, out_code, in_code = AUTO)
+    opt = '-'
+    case in_code
+    when ::NKF::JIS
+      opt << 'J'
+    when ::NKF::EUC
+      opt << 'E'
+    when ::NKF::SJIS
+      opt << 'S'
+    when ::NKF::UTF8
+      opt << 'W'
+    when ::NKF::UTF16
+      opt << 'W16'
+    end
+
+    case out_code
+    when ::NKF::JIS
+      opt << 'j'
+    when ::NKF::EUC
+      opt << 'e'
+    when ::NKF::SJIS
+      opt << 's'
+    when ::NKF::UTF8
+      opt << 'w'
+    when ::NKF::UTF16
+      opt << 'w16'
+    when ::NKF::NOCONV
+      return str
+    end
+
+    opt = '' if opt == '-'
+
+    ::NKF::nkf(opt, str)
+  end
+  module_function :kconv
+
+  #
+  # Encode to
+  #
+
+  # call-seq:
+  #    Kconv.tojis(str)   -> string
+  #
+  # Convert <code>str</code> to ISO-2022-JP
+  #
+  # *Note*
+  # This method decode MIME encoded string and
+  # convert halfwidth katakana to fullwidth katakana.
+  # If you don't want it, use NKF.nkf('-jxm0', str).
+  def tojis(str)
+    ::NKF::nkf('-jm', str)
+  end
+  module_function :tojis
+
+  # call-seq:
+  #    Kconv.toeuc(str)   -> string
+  #
+  # Convert <code>str</code> to EUC-JP
+  #
+  # *Note*
+  # This method decode MIME encoded string and
+  # convert halfwidth katakana to fullwidth katakana.
+  # If you don't want it, use NKF.nkf('-exm0', str).
+  def toeuc(str)
+    ::NKF::nkf('-em', str)
+  end
+  module_function :toeuc
+
+  # call-seq:
+  #    Kconv.tosjis(str)   -> string
+  #
+  # Convert <code>str</code> to Shift_JIS
+  #
+  # *Note*
+  # This method decode MIME encoded string and
+  # convert halfwidth katakana to fullwidth katakana.
+  # If you don't want it, use NKF.nkf('-sxm0', str).
+  def tosjis(str)
+    ::NKF::nkf('-sm', str)
+  end
+  module_function :tosjis
+
+  # call-seq:
+  #    Kconv.toutf8(str)   -> string
+  #
+  # Convert <code>str</code> to UTF-8
+  #
+  # *Note*
+  # This method decode MIME encoded string and
+  # convert halfwidth katakana to fullwidth katakana.
+  # If you don't want it, use NKF.nkf('-wxm0', str).
+  def toutf8(str)
+    ::NKF::nkf('-wm', str)
+  end
+  module_function :toutf8
+
+  # call-seq:
+  #    Kconv.toutf16(str)   -> string
+  #
+  # Convert <code>str</code> to UTF-16
+  #
+  # *Note*
+  # This method decode MIME encoded string and
+  # convert halfwidth katakana to fullwidth katakana.
+  # If you don't want it, use NKF.nkf('-w16xm0', str).
+  def toutf16(str)
+    ::NKF::nkf('-w16m', str)
+  end
+  module_function :toutf16
+
+  #
+  # guess
+  #
+
+  # call-seq:
+  #    Kconv.guess(str)   -> integer
+  #
+  # Guess input encoding by NKF.guess2
+  def guess(str)
+    ::NKF::guess(str)
+  end
+  module_function :guess
+
+  # call-seq:
+  #    Kconv.guess_old(str)   -> integer
+  #
+  # Guess input encoding by NKF.guess1
+  def guess_old(str)
+    ::NKF::guess1(str)
+  end
+  module_function :guess_old
+
+  #
+  # isEncoding
+  #
+
+  # call-seq:
+  #    Kconv.iseuc(str)   -> obj or nil
+  #
+  # Returns whether input encoding is EUC-JP or not.
+  #
+  # *Note* don't expect this return value is MatchData.
+  def iseuc(str)
+    RegexpEucjp.match( str )
+  end
+  module_function :iseuc
+
+  # call-seq:
+  #    Kconv.issjis(str)   -> obj or nil
+  #
+  # Returns whether input encoding is Shift_JIS or not.
+  #
+  # *Note* don't expect this return value is MatchData.
+  def issjis(str)
+    RegexpShiftjis.match( str )
+  end
+  module_function :issjis
+
+  # call-seq:
+  #    Kconv.isutf8(str)   -> obj or nil
+  #
+  # Returns whether input encoding is UTF-8 or not.
+  #
+  # *Note* don't expect this return value is MatchData.
+  def isutf8(str)
+    RegexpUtf8.match( str )
+  end
+  module_function :isutf8
+
+end
+
+class String
+  # call-seq:
+  #    String#kconv(out_code, in_code = Kconv::AUTO)
+  #
+  # Convert <code>self</code> to out_code.
+  # <code>out_code</code> and <code>in_code</code> are given as constants of Kconv.
+  #
+  # *Note*
+  # This method decode MIME encoded string and
+  # convert halfwidth katakana to fullwidth katakana.
+  # If you don't want to decode them, use NKF.nkf.
+  def kconv(out_code, in_code=Kconv::AUTO)
+    Kconv::kconv(self, out_code, in_code)
+  end
+  
+  #
+  # to Encoding
+  #
+  
+  # call-seq:
+  #    String#tojis   -> string
+  #
+  # Convert <code>self</code> to ISO-2022-JP
+  #
+  # *Note*
+  # This method decode MIME encoded string and
+  # convert halfwidth katakana to fullwidth katakana.
+  # If you don't want it, use NKF.nkf('-jxm0', str).
+  def tojis; Kconv.tojis(self) end
+
+  # call-seq:
+  #    String#toeuc   -> string
+  #
+  # Convert <code>self</code> to EUC-JP
+  #
+  # *Note*
+  # This method decode MIME encoded string and
+  # convert halfwidth katakana to fullwidth katakana.
+  # If you don't want it, use NKF.nkf('-exm0', str).
+  def toeuc; Kconv.toeuc(self) end
+
+  # call-seq:
+  #    String#tosjis   -> string
+  #
+  # Convert <code>self</code> to Shift_JIS
+  #
+  # *Note*
+  # This method decode MIME encoded string and
+  # convert halfwidth katakana to fullwidth katakana.
+  # If you don't want it, use NKF.nkf('-sxm0', str).
+  def tosjis; Kconv.tosjis(self) end
+
+  # call-seq:
+  #    String#toutf8   -> string
+  #
+  # Convert <code>self</code> to UTF-8
+  #
+  # *Note*
+  # This method decode MIME encoded string and
+  # convert halfwidth katakana to fullwidth katakana.
+  # If you don't want it, use NKF.nkf('-wxm0', str).
+  def toutf8; Kconv.toutf8(self) end
+
+  # call-seq:
+  #    String#toutf16   -> string
+  #
+  # Convert <code>self</code> to UTF-16
+  #
+  # *Note*
+  # This method decode MIME encoded string and
+  # convert halfwidth katakana to fullwidth katakana.
+  # If you don't want it, use NKF.nkf('-w16xm0', str).
+  def toutf16; Kconv.toutf16(self) end
+
+  #
+  # is Encoding
+  #
+
+  # call-seq:
+  #    String#iseuc   -> obj or nil
+  #
+  # Returns whether <code>self</code>'s encoding is EUC-JP or not.
+  #
+  # *Note* don't expect this return value is MatchData.
+  def iseuc;	Kconv.iseuc(self) end
+
+  # call-seq:
+  #    String#issjis   -> obj or nil
+  #
+  # Returns whether <code>self</code>'s encoding is Shift_JIS or not.
+  #
+  # *Note* don't expect this return value is MatchData.
+  def issjis;	Kconv.issjis(self) end
+
+  # call-seq:
+  #    String#isutf8   -> obj or nil
+  #
+  # Returns whether <code>self</code>'s encoding is UTF-8 or not.
+  #
+  # *Note* don't expect this return value is MatchData.
+  def isutf8;	Kconv.isutf8(self) end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/logger.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/logger.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/logger.rb	(revision 18425)
@@ -0,0 +1,703 @@
+# logger.rb - saimple logging utility
+# Copyright (C) 2000-2003, 2005  NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>.
+
+require 'monitor'
+
+# Simple logging utility.
+#
+# Author:: NAKAMURA, Hiroshi  <nakahiro@sarion.co.jp>
+# Documentation:: NAKAMURA, Hiroshi and Gavin Sinclair
+# License::
+#   You can redistribute it and/or modify it under the same terms of Ruby's
+#   license; either the dual license version in 2003, or any later version.
+# Revision:: $Id: logger.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+# == Description
+#
+# The Logger class provides a simple but sophisticated logging utility that
+# anyone can use because it's included in the Ruby 1.8.x standard library.
+#
+# The HOWTOs below give a code-based overview of Logger's usage, but the basic
+# concept is as follows.  You create a Logger object (output to a file or
+# elsewhere), and use it to log messages.  The messages will have varying
+# levels (+info+, +error+, etc), reflecting their varying importance.  The
+# levels, and their meanings, are:
+#
+# +FATAL+:: an unhandleable error that results in a program crash
+# +ERROR+:: a handleable error condition
+# +WARN+::  a warning
+# +INFO+::  generic (useful) information about system operation
+# +DEBUG+:: low-level information for developers
+#
+# So each message has a level, and the Logger itself has a level, which acts
+# as a filter, so you can control the amount of information emitted from the
+# logger without having to remove actual messages.
+#
+# For instance, in a production system, you may have your logger(s) set to
+# +INFO+ (or +WARN+ if you don't want the log files growing large with
+# repetitive information).  When you are developing it, though, you probably
+# want to know about the program's internal state, and would set them to
+# +DEBUG+.
+#
+# === Example
+#
+# A simple example demonstrates the above explanation:
+#
+#   log = Logger.new(STDOUT)
+#   log.level = Logger::WARN
+#
+#   log.debug("Created logger")
+#   log.info("Program started")
+#   log.warn("Nothing to do!")
+#
+#   begin
+#     File.each_line(path) do |line|
+#       unless line =~ /^(\w+) = (.*)$/
+#         log.error("Line in wrong format: #{line}")
+#       end
+#     end
+#   rescue => err
+#     log.fatal("Caught exception; exiting")
+#     log.fatal(err)
+#   end
+#
+# Because the Logger's level is set to +WARN+, only the warning, error, and
+# fatal messages are recorded.  The debug and info messages are silently
+# discarded.
+#
+# === Features
+#
+# There are several interesting features that Logger provides, like
+# auto-rolling of log files, setting the format of log messages, and
+# specifying a program name in conjunction with the message.  The next section
+# shows you how to achieve these things.
+#
+#
+# == HOWTOs
+#
+# === How to create a logger
+#
+# The options below give you various choices, in more or less increasing
+# complexity.
+#
+# 1. Create a logger which logs messages to STDERR/STDOUT.
+#
+#      logger = Logger.new(STDERR)
+#      logger = Logger.new(STDOUT)
+#
+# 2. Create a logger for the file which has the specified name.
+#
+#      logger = Logger.new('logfile.log')
+#
+# 3. Create a logger for the specified file.
+#
+#      file = File.open('foo.log', File::WRONLY | File::APPEND)
+#      # To create new (and to remove old) logfile, add File::CREAT like;
+#      #   file = open('foo.log', File::WRONLY | File::APPEND | File::CREAT)
+#      logger = Logger.new(file)
+#
+# 4. Create a logger which ages logfile once it reaches a certain size.  Leave
+#    10 "old log files" and each file is about 1,024,000 bytes.
+#
+#      logger = Logger.new('foo.log', 10, 1024000)
+#
+# 5. Create a logger which ages logfile daily/weekly/monthly.
+#
+#      logger = Logger.new('foo.log', 'daily')
+#      logger = Logger.new('foo.log', 'weekly')
+#      logger = Logger.new('foo.log', 'monthly')
+#
+# === How to log a message
+#
+# Notice the different methods (+fatal+, +error+, +info+) being used to log
+# messages of various levels.  Other methods in this family are +warn+ and
+# +debug+.  +add+ is used below to log a message of an arbitrary (perhaps
+# dynamic) level.
+#
+# 1. Message in block.
+#
+#      logger.fatal { "Argument 'foo' not given." }
+#
+# 2. Message as a string.
+#
+#      logger.error "Argument #{ @foo } mismatch."
+#
+# 3. With progname.
+#
+#      logger.info('initialize') { "Initializing..." }
+#
+# 4. With severity.
+#
+#      logger.add(Logger::FATAL) { 'Fatal error!' }
+#
+# === How to close a logger
+#
+#      logger.close
+#
+# === Setting severity threshold
+#
+# 1. Original interface.
+#
+#      logger.sev_threshold = Logger::WARN
+#
+# 2. Log4r (somewhat) compatible interface.
+#
+#      logger.level = Logger::INFO
+#      
+#      DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
+#
+#
+# == Format
+#
+# Log messages are rendered in the output stream in a certain format.  The
+# default format and a sample are shown below:
+#
+# Log format:
+#   SeverityID, [Date Time mSec #pid] SeverityLabel -- ProgName: message
+#
+# Log sample:
+#   I, [Wed Mar 03 02:34:24 JST 1999 895701 #19074]  INFO -- Main: info.
+#
+# You may change the date and time format in this manner:
+#
+#   logger.datetime_format = "%Y-%m-%d %H:%M:%S"
+#         # e.g. "2004-01-03 00:54:26"
+#
+# There is currently no supported way to change the overall format, but you may
+# have some luck hacking the Format constant.
+#
+
+
+class Logger
+  VERSION = "1.2.6"
+  /: (\S+),v (\S+)/ =~ %q$Id: logger.rb 11708 2007-02-12 23:01:19Z shyouhei $
+  ProgName = "#{$1}/#{$2}"
+
+  class Error < RuntimeError; end
+  class ShiftingError < Error; end
+
+  # Logging severity.
+  module Severity
+    DEBUG = 0
+    INFO = 1
+    WARN = 2
+    ERROR = 3
+    FATAL = 4
+    UNKNOWN = 5
+  end
+  include Severity
+
+  # Logging severity threshold (e.g. <tt>Logger::INFO</tt>).
+  attr_accessor :level
+
+  # Logging program name.
+  attr_accessor :progname
+
+  # Logging date-time format (string passed to +strftime+).
+  def datetime_format=(datetime_format)
+    @default_formatter.datetime_format = datetime_format
+  end
+
+  def datetime_format
+    @default_formatter.datetime_format
+  end
+
+  # Logging formatter.  formatter#call is invoked with 4 arguments; severity,
+  # time, progname and msg for each log.  Bear in mind that time is a Time and
+  # msg is an Object that user passed and it could not be a String.  It is
+  # expected to return a logdev#write-able Object.  Default formatter is used
+  # when no formatter is set.
+  attr_accessor :formatter
+
+  alias sev_threshold level
+  alias sev_threshold= level=
+
+  # Returns +true+ iff the current severity level allows for the printing of
+  # +DEBUG+ messages.
+  def debug?; @level <= DEBUG; end
+
+  # Returns +true+ iff the current severity level allows for the printing of
+  # +INFO+ messages.
+  def info?; @level <= INFO; end
+
+  # Returns +true+ iff the current severity level allows for the printing of
+  # +WARN+ messages.
+  def warn?; @level <= WARN; end
+
+  # Returns +true+ iff the current severity level allows for the printing of
+  # +ERROR+ messages.
+  def error?; @level <= ERROR; end
+
+  # Returns +true+ iff the current severity level allows for the printing of
+  # +FATAL+ messages.
+  def fatal?; @level <= FATAL; end
+
+  #
+  # === Synopsis
+  #
+  #   Logger.new(name, shift_age = 7, shift_size = 1048576)
+  #   Logger.new(name, shift_age = 'weekly')
+  #
+  # === Args
+  #
+  # +logdev+::
+  #   The log device.  This is a filename (String) or IO object (typically
+  #   +STDOUT+, +STDERR+, or an open file).
+  # +shift_age+::
+  #   Number of old log files to keep, *or* frequency of rotation (+daily+,
+  #   +weekly+ or +monthly+).
+  # +shift_size+::
+  #   Maximum logfile size (only applies when +shift_age+ is a number).
+  #
+  # === Description
+  #
+  # Create an instance.
+  #
+  def initialize(logdev, shift_age = 0, shift_size = 1048576)
+    @progname = nil
+    @level = DEBUG
+    @default_formatter = Formatter.new
+    @formatter = nil
+    @logdev = nil
+    if logdev
+      @logdev = LogDevice.new(logdev, :shift_age => shift_age,
+        :shift_size => shift_size)
+    end
+  end
+
+  #
+  # === Synopsis
+  #
+  #   Logger#add(severity, message = nil, progname = nil) { ... }
+  #
+  # === Args
+  #
+  # +severity+::
+  #   Severity.  Constants are defined in Logger namespace: +DEBUG+, +INFO+,
+  #   +WARN+, +ERROR+, +FATAL+, or +UNKNOWN+.
+  # +message+::
+  #   The log message.  A String or Exception.
+  # +progname+::
+  #   Program name string.  Can be omitted.  Treated as a message if no +message+ and
+  #   +block+ are given.
+  # +block+::
+  #   Can be omitted.  Called to get a message string if +message+ is nil.
+  #
+  # === Return
+  #
+  # +true+ if successful, +false+ otherwise.
+  #
+  # When the given severity is not high enough (for this particular logger), log
+  # no message, and return +true+.
+  #
+  # === Description
+  #
+  # Log a message if the given severity is high enough.  This is the generic
+  # logging method.  Users will be more inclined to use #debug, #info, #warn,
+  # #error, and #fatal.
+  #
+  # <b>Message format</b>: +message+ can be any object, but it has to be
+  # converted to a String in order to log it.  Generally, +inspect+ is used
+  # if the given object is not a String.
+  # A special case is an +Exception+ object, which will be printed in detail,
+  # including message, class, and backtrace.  See #msg2str for the
+  # implementation if required.
+  #
+  # === Bugs
+  #
+  # * Logfile is not locked.
+  # * Append open does not need to lock file.
+  # * But on the OS which supports multi I/O, records possibly be mixed.
+  #
+  def add(severity, message = nil, progname = nil, &block)
+    severity ||= UNKNOWN
+    if @logdev.nil? or severity < @level
+      return true
+    end
+    progname ||= @progname
+    if message.nil?
+      if block_given?
+	message = yield
+      else
+	message = progname
+	progname = @progname
+      end
+    end
+    @logdev.write(
+      format_message(format_severity(severity), Time.now, progname, message))
+    true
+  end
+  alias log add
+
+  #
+  # Dump given message to the log device without any formatting.  If no log
+  # device exists, return +nil+.
+  #
+  def <<(msg)
+    unless @logdev.nil?
+      @logdev.write(msg)
+    end
+  end
+
+  #
+  # Log a +DEBUG+ message.
+  #
+  # See #info for more information.
+  #
+  def debug(progname = nil, &block)
+    add(DEBUG, nil, progname, &block)
+  end
+
+  #
+  # Log an +INFO+ message.
+  #
+  # The message can come either from the +progname+ argument or the +block+.  If
+  # both are provided, then the +block+ is used as the message, and +progname+
+  # is used as the program name.
+  #
+  # === Examples
+  #
+  #   logger.info("MainApp") { "Received connection from #{ip}" }
+  #   # ...
+  #   logger.info "Waiting for input from user"
+  #   # ...
+  #   logger.info { "User typed #{input}" }
+  #
+  # You'll probably stick to the second form above, unless you want to provide a
+  # program name (which you can do with <tt>Logger#progname=</tt> as well).
+  #
+  # === Return
+  #
+  # See #add.
+  #
+  def info(progname = nil, &block)
+    add(INFO, nil, progname, &block)
+  end
+
+  #
+  # Log a +WARN+ message.
+  #
+  # See #info for more information.
+  #
+  def warn(progname = nil, &block)
+    add(WARN, nil, progname, &block)
+  end
+
+  #
+  # Log an +ERROR+ message.
+  #
+  # See #info for more information.
+  #
+  def error(progname = nil, &block)
+    add(ERROR, nil, progname, &block)
+  end
+
+  #
+  # Log a +FATAL+ message.
+  #
+  # See #info for more information.
+  #
+  def fatal(progname = nil, &block)
+    add(FATAL, nil, progname, &block)
+  end
+
+  #
+  # Log an +UNKNOWN+ message.  This will be printed no matter what the logger
+  # level.
+  #
+  # See #info for more information.
+  #
+  def unknown(progname = nil, &block)
+    add(UNKNOWN, nil, progname, &block)
+  end
+
+  #
+  # Close the logging device.
+  #
+  def close
+    @logdev.close if @logdev
+  end
+
+private
+
+  # Severity label for logging. (max 5 char)
+  SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY)
+
+  def format_severity(severity)
+    SEV_LABEL[severity] || 'ANY'
+  end
+
+  def format_message(severity, datetime, progname, msg)
+    (@formatter || @default_formatter).call(severity, datetime, progname, msg)
+  end
+
+
+  class Formatter
+    Format = "%s, [%s#%d] %5s -- %s: %s\n"
+
+    attr_accessor :datetime_format
+
+    def initialize
+      @datetime_format = nil
+    end
+
+    def call(severity, time, progname, msg)
+      Format % [severity[0..0], format_datetime(time), $$, severity, progname,
+        msg2str(msg)]
+    end
+
+  private
+
+    def format_datetime(time)
+      if @datetime_format.nil?
+        time.strftime("%Y-%m-%dT%H:%M:%S.") << "%06d " % time.usec
+      else
+        time.strftime(@datetime_format)
+      end
+    end
+
+    def msg2str(msg)
+      case msg
+      when ::String
+        msg
+      when ::Exception
+        "#{ msg.message } (#{ msg.class })\n" <<
+          (msg.backtrace || []).join("\n")
+      else
+        msg.inspect
+      end
+    end
+  end
+
+
+  class LogDevice
+    attr_reader :dev
+    attr_reader :filename
+
+    class LogDeviceMutex
+      include MonitorMixin
+    end
+
+    def initialize(log = nil, opt = {})
+      @dev = @filename = @shift_age = @shift_size = nil
+      @mutex = LogDeviceMutex.new
+      if log.respond_to?(:write) and log.respond_to?(:close)
+	@dev = log
+      else
+	@dev = open_logfile(log)
+	@dev.sync = true
+	@filename = log
+	@shift_age = opt[:shift_age] || 7
+	@shift_size = opt[:shift_size] || 1048576
+      end
+    end
+
+    def write(message)
+      @mutex.synchronize do
+        if @shift_age and @dev.respond_to?(:stat)
+          begin
+            check_shift_log
+          rescue
+            raise Logger::ShiftingError.new("Shifting failed. #{$!}")
+          end
+        end
+        @dev.write(message)
+      end
+    end
+
+    def close
+      @mutex.synchronize do
+        @dev.close
+      end
+    end
+
+  private
+
+    def open_logfile(filename)
+      if (FileTest.exist?(filename))
+     	open(filename, (File::WRONLY | File::APPEND))
+      else
+       	create_logfile(filename)
+      end
+    end
+
+    def create_logfile(filename)
+      logdev = open(filename, (File::WRONLY | File::APPEND | File::CREAT))
+      logdev.sync = true
+      add_log_header(logdev)
+      logdev
+    end
+
+    def add_log_header(file)
+      file.write(
+     	"# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
+    )
+    end
+
+    SiD = 24 * 60 * 60
+
+    def check_shift_log
+      if @shift_age.is_a?(Integer)
+        # Note: always returns false if '0'.
+        if @filename && (@shift_age > 0) && (@dev.stat.size > @shift_size)
+          shift_log_age
+        end
+      else
+        now = Time.now
+        if @dev.stat.mtime <= previous_period_end(now)
+          shift_log_period(now)
+        end
+      end
+    end
+
+    def shift_log_age
+      (@shift_age-3).downto(0) do |i|
+        if FileTest.exist?("#{@filename}.#{i}")
+          File.rename("#{@filename}.#{i}", "#{@filename}.#{i+1}")
+        end
+      end
+      @dev.close
+      File.rename("#{@filename}", "#{@filename}.0")
+      @dev = create_logfile(@filename)
+      return true
+    end
+
+    def shift_log_period(now)
+      postfix = previous_period_end(now).strftime("%Y%m%d")	# YYYYMMDD
+      age_file = "#{@filename}.#{postfix}"
+      if FileTest.exist?(age_file)
+        raise RuntimeError.new("'#{ age_file }' already exists.")
+      end
+      @dev.close
+      File.rename("#{@filename}", age_file)
+      @dev = create_logfile(@filename)
+      return true
+    end
+
+    def previous_period_end(now)
+      case @shift_age
+      when /^daily$/
+        eod(now - 1 * SiD)
+      when /^weekly$/
+        eod(now - ((now.wday + 1) * SiD))
+      when /^monthly$/
+        eod(now - now.mday * SiD)
+      else
+        now
+      end
+    end
+
+    def eod(t)
+      Time.mktime(t.year, t.month, t.mday, 23, 59, 59)
+    end
+  end
+
+
+  #
+  # == Description
+  #
+  # Application -- Add logging support to your application.
+  #
+  # == Usage
+  #
+  # 1. Define your application class as a sub-class of this class.
+  # 2. Override 'run' method in your class to do many things.
+  # 3. Instantiate it and invoke 'start'.
+  #
+  # == Example
+  #
+  #   class FooApp < Application
+  #     def initialize(foo_app, application_specific, arguments)
+  #       super('FooApp') # Name of the application.
+  #     end
+  #
+  #     def run
+  #       ...
+  #       log(WARN, 'warning', 'my_method1')
+  #       ...
+  #       @log.error('my_method2') { 'Error!' }
+  #       ...
+  #     end
+  #   end
+  #
+  #   status = FooApp.new(....).start
+  #
+  class Application
+    include Logger::Severity
+
+    attr_reader :appname
+    attr_reader :logdev
+
+    #
+    # == Synopsis
+    #
+    #   Application.new(appname = '')
+    #
+    # == Args
+    #
+    # +appname+:: Name of the application.
+    #
+    # == Description
+    #
+    # Create an instance.  Log device is +STDERR+ by default.  This can be
+    # changed with #set_log.
+    #
+    def initialize(appname = nil)
+      @appname = appname
+      @log = Logger.new(STDERR)
+      @log.progname = @appname
+      @level = @log.level
+    end
+
+    #
+    # Start the application.  Return the status code.
+    #
+    def start
+      status = -1
+      begin
+	log(INFO, "Start of #{ @appname }.")
+	status = run
+      rescue
+	log(FATAL, "Detected an exception. Stopping ... #{$!} (#{$!.class})\n" << $@.join("\n"))
+      ensure
+	log(INFO, "End of #{ @appname }. (status: #{ status.to_s })")
+      end
+      status
+    end
+
+    #
+    # Sets the log device for this application.  See the class Logger for an
+    # explanation of the arguments.
+    #
+    def set_log(logdev, shift_age = 0, shift_size = 1024000)
+      @log = Logger.new(logdev, shift_age, shift_size)
+      @log.progname = @appname
+      @log.level = @level
+    end
+
+    def log=(logdev)
+      set_log(logdev)
+    end
+
+    #
+    # Set the logging threshold, just like <tt>Logger#level=</tt>.
+    #
+    def level=(level)
+      @level = level
+      @log.level = @level
+    end
+
+    #
+    # See Logger#add.  This application's +appname+ is used.
+    #
+    def log(severity, message = nil, &block)
+      @log.add(severity, message, @appname, &block) if @log
+    end
+
+  private
+
+    def run
+      raise RuntimeError.new('Method run must be defined in the derived class.')
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/mailread.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/mailread.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/mailread.rb	(revision 18425)
@@ -0,0 +1,62 @@
+# The Mail class represents an internet mail message (as per RFC822, RFC2822)
+# with headers and a body. 
+class Mail
+
+  # Create a new Mail where +f+ is either a stream which responds to gets(),
+  # or a path to a file.  If +f+ is a path it will be opened.
+  #
+  # The whole message is read so it can be made available through the #header,
+  # #[] and #body methods.
+  #
+  # The "From " line is ignored if the mail is in mbox format.
+  def initialize(f)
+    unless defined? f.gets
+      f = open(f, "r")
+      opened = true
+    end
+
+    @header = {}
+    @body = []
+    begin
+      while line = f.gets()
+	line.chop!
+	next if /^From /=~line	# skip From-line
+	break if /^$/=~line	# end of header
+
+	if /^(\S+?):\s*(.*)/=~line
+	  (attr = $1).capitalize!
+	  @header[attr] = $2
+	elsif attr
+	  line.sub!(/^\s*/, '')
+	  @header[attr] += "\n" + line
+	end
+      end
+  
+      return unless line
+
+      while line = f.gets()
+	break if /^From /=~line
+	@body.push(line)
+      end
+    ensure
+      f.close if opened
+    end
+  end
+
+  # Return the headers as a Hash.
+  def header
+    return @header
+  end
+
+  # Return the message body as an Array of lines
+  def body
+    return @body
+  end
+
+  # Return the header corresponding to +field+. 
+  #
+  # Matching is case-insensitive.
+  def [](field)
+    @header[field.capitalize]
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/mathn.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/mathn.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/mathn.rb	(revision 18425)
@@ -0,0 +1,308 @@
+#
+#   mathn.rb - 
+#   	$Release Version: 0.5 $
+#   	$Revision: 1.1.1.1.4.1 $
+#   	$Date: 1998/01/16 12:36:05 $
+#   	by Keiju ISHITSUKA(SHL Japan Inc.)
+#
+# --
+#
+#   
+#
+
+require "complex.rb"
+require "rational.rb"
+require "matrix.rb"
+
+class Integer
+
+  def gcd2(int)
+    a = self.abs
+    b = int.abs
+    a, b = b, a if a < b
+    
+    pd_a = a.prime_division
+    pd_b = b.prime_division
+    
+    gcd = 1
+    for pair in pd_a
+      as = pd_b.assoc(pair[0])
+      if as
+	gcd *= as[0] ** [as[1], pair[1]].min
+      end
+    end
+    return gcd
+  end
+  
+  def Integer.from_prime_division(pd)
+    value = 1
+    for prime, index in pd
+      value *= prime**index
+    end
+    value
+  end
+  
+  def prime_division
+    raise ZeroDivisionError if self == 0
+    ps = Prime.new
+    value = self
+    pv = []
+    for prime in ps
+      count = 0
+      while (value1, mod = value.divmod(prime)
+	     mod) == 0
+	value = value1
+	count += 1
+      end
+      if count != 0
+	pv.push [prime, count]
+      end
+      break if prime * prime  >= value
+    end
+    if value > 1
+      pv.push [value, 1]
+    end
+    return pv
+  end
+end
+  
+class Prime
+  include Enumerable
+
+  def initialize
+    @seed = 1
+    @primes = []
+    @counts = []
+  end
+  
+  def succ
+    i = -1
+    size = @primes.size
+    while i < size
+      if i == -1
+	@seed += 1
+	i += 1
+      else
+	while @seed > @counts[i]
+	  @counts[i] += @primes[i]
+	end
+	if @seed != @counts[i]
+	  i += 1
+	else
+	  i = -1
+	end
+      end
+    end
+    @primes.push @seed
+    @counts.push @seed + @seed
+    return @seed
+  end
+  alias next succ
+
+  def each
+    loop do
+      yield succ
+    end
+  end
+end
+
+class Fixnum
+  alias / quo
+end
+
+class Bignum
+  alias / quo
+end
+
+class Rational
+  Unify = true
+
+  def inspect
+    format "%s/%s", numerator.inspect, denominator.inspect
+  end
+
+  alias power! **
+
+  def ** (other)
+    if other.kind_of?(Rational)
+      other2 = other
+      if self < 0
+	return Complex.new!(self, 0) ** other
+      elsif other == 0
+	return Rational(1,1)
+      elsif self == 0
+	return Rational(0,1)
+      elsif self == 1
+	return Rational(1,1)
+      end
+      
+      npd = numerator.prime_division
+      dpd = denominator.prime_division
+      if other < 0
+	other = -other
+	npd, dpd = dpd, npd
+      end
+      
+      for elm in npd
+	elm[1] = elm[1] * other
+	if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
+         return Float(self) ** other2
+	end
+	elm[1] = elm[1].to_i
+      end
+      
+      for elm in dpd
+	elm[1] = elm[1] * other
+	if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
+         return Float(self) ** other2
+	end
+	elm[1] = elm[1].to_i
+      end
+      
+      num = Integer.from_prime_division(npd)
+      den = Integer.from_prime_division(dpd)
+      
+      Rational(num,den)
+      
+    elsif other.kind_of?(Integer)
+      if other > 0
+	num = numerator ** other
+	den = denominator ** other
+      elsif other < 0
+	num = denominator ** -other
+	den = numerator ** -other
+      elsif other == 0
+	num = 1
+	den = 1
+      end
+      Rational.new!(num, den)
+    elsif other.kind_of?(Float)
+      Float(self) ** other
+    else
+      x , y = other.coerce(self)
+      x ** y
+    end
+  end
+
+  def power2(other)
+    if other.kind_of?(Rational)
+      if self < 0
+	return Complex(self, 0) ** other
+      elsif other == 0
+	return Rational(1,1)
+      elsif self == 0
+	return Rational(0,1)
+      elsif self == 1
+	return Rational(1,1)
+      end
+      
+      dem = nil
+      x = self.denominator.to_f.to_i
+      neard = self.denominator.to_f ** (1.0/other.denominator.to_f)
+      loop do
+	if (neard**other.denominator == self.denominator)
+	  dem = neaed
+	  break
+	end
+      end
+      nearn = self.numerator.to_f ** (1.0/other.denominator.to_f)
+      Rational(num,den)
+      
+    elsif other.kind_of?(Integer)
+      if other > 0
+	num = numerator ** other
+	den = denominator ** other
+      elsif other < 0
+	num = denominator ** -other
+	den = numerator ** -other
+      elsif other == 0
+	num = 1
+	den = 1
+      end
+      Rational.new!(num, den)
+    elsif other.kind_of?(Float)
+      Float(self) ** other
+    else
+      x , y = other.coerce(self)
+      x ** y
+    end
+  end
+end
+
+module Math
+  def sqrt(a)
+    if a.kind_of?(Complex)
+      abs = sqrt(a.real*a.real + a.image*a.image)
+#      if not abs.kind_of?(Rational)
+#	return a**Rational(1,2)
+#      end
+      x = sqrt((a.real + abs)/Rational(2))
+      y = sqrt((-a.real + abs)/Rational(2))
+#      if !(x.kind_of?(Rational) and y.kind_of?(Rational))
+#	return a**Rational(1,2)
+#      end
+      if a.image >= 0 
+	Complex(x, y)
+      else
+	Complex(x, -y)
+      end
+    elsif a >= 0
+      rsqrt(a)
+    else
+      Complex(0,rsqrt(-a))
+    end
+  end
+  
+  def rsqrt(a)
+    if a.kind_of?(Float)
+      sqrt!(a)
+    elsif a.kind_of?(Rational)
+      rsqrt(a.numerator)/rsqrt(a.denominator)
+    else
+      src = a
+      max = 2 ** 32
+      byte_a = [src & 0xffffffff]
+      # ruby's bug
+      while (src >= max) and (src >>= 32)
+	byte_a.unshift src & 0xffffffff
+      end
+      
+      answer = 0
+      main = 0
+      side = 0
+      for elm in byte_a
+	main = (main << 32) + elm
+	side <<= 16
+	if answer != 0
+	  if main * 4  < side * side
+	    applo = main.div(side)
+	  else 
+	    applo = ((sqrt!(side * side + 4 * main) - side)/2.0).to_i + 1
+	  end
+	else
+	  applo = sqrt!(main).to_i + 1
+	end
+	
+	while (x = (side + applo) * applo) > main
+	  applo -= 1
+	end
+	main -= x
+	answer = (answer << 16) + applo
+	side += applo * 2
+      end
+      if main == 0
+	answer
+      else
+	sqrt!(a)
+      end
+    end
+  end
+
+  module_function :sqrt
+  module_function :rsqrt
+end
+
+class Complex
+  Unify = true
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/matrix.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/matrix.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/matrix.rb	(revision 18425)
@@ -0,0 +1,1272 @@
+#!/usr/local/bin/ruby
+#--
+#   matrix.rb - 
+#       $Release Version: 1.0$
+#       $Revision: 1.11 $
+#       $Date: 1999/10/06 11:01:53 $
+#       Original Version from Smalltalk-80 version
+#          on July 23, 1985 at 8:37:17 am
+#       by Keiju ISHITSUKA
+#++
+#
+# = matrix.rb
+#
+# An implementation of Matrix and Vector classes.
+#
+# Author:: Keiju ISHITSUKA
+# Documentation:: Gavin Sinclair (sourced from <i>Ruby in a Nutshell</i> (Matsumoto, O'Reilly)) 
+#
+# See classes Matrix and Vector for documentation. 
+#
+
+
+require "e2mmap.rb"
+
+module ExceptionForMatrix # :nodoc:
+  extend Exception2MessageMapper
+  def_e2message(TypeError, "wrong argument type %s (expected %s)")
+  def_e2message(ArgumentError, "Wrong # of arguments(%d for %d)")
+  
+  def_exception("ErrDimensionMismatch", "\#{self.name} dimension mismatch")
+  def_exception("ErrNotRegular", "Not Regular Matrix")
+  def_exception("ErrOperationNotDefined", "This operation(%s) can\\'t defined")
+end
+
+#
+# The +Matrix+ class represents a mathematical matrix, and provides methods for creating
+# special-case matrices (zero, identity, diagonal, singular, vector), operating on them
+# arithmetically and algebraically, and determining their mathematical properties (trace, rank,
+# inverse, determinant).
+#
+# Note that although matrices should theoretically be rectangular, this is not
+# enforced by the class.
+#
+# Also note that the determinant of integer matrices may be incorrectly calculated unless you
+# also <tt>require 'mathn'</tt>.  This may be fixed in the future.
+#
+# == Method Catalogue
+#
+# To create a matrix:
+# * <tt> Matrix[*rows]                  </tt>
+# * <tt> Matrix.[](*rows)               </tt>
+# * <tt> Matrix.rows(rows, copy = true) </tt>
+# * <tt> Matrix.columns(columns)        </tt>
+# * <tt> Matrix.diagonal(*values)       </tt>
+# * <tt> Matrix.scalar(n, value)        </tt>
+# * <tt> Matrix.scalar(n, value)        </tt>
+# * <tt> Matrix.identity(n)             </tt>
+# * <tt> Matrix.unit(n)                 </tt>
+# * <tt> Matrix.I(n)                    </tt>
+# * <tt> Matrix.zero(n)                 </tt>
+# * <tt> Matrix.row_vector(row)         </tt>
+# * <tt> Matrix.column_vector(column)   </tt>
+#
+# To access Matrix elements/columns/rows/submatrices/properties: 
+# * <tt>  [](i, j)                      </tt>
+# * <tt> #row_size                      </tt>
+# * <tt> #column_size                   </tt>
+# * <tt> #row(i)                        </tt>
+# * <tt> #column(j)                     </tt>
+# * <tt> #collect                       </tt>
+# * <tt> #map                           </tt>
+# * <tt> #minor(*param)                 </tt>
+#
+# Properties of a matrix:
+# * <tt> #regular?                      </tt>
+# * <tt> #singular?                     </tt>
+# * <tt> #square?                       </tt>
+#
+# Matrix arithmetic:
+# * <tt>  *(m)                          </tt>
+# * <tt>  +(m)                          </tt>
+# * <tt>  -(m)                          </tt>
+# * <tt> #/(m)                          </tt>
+# * <tt> #inverse                       </tt>
+# * <tt> #inv                           </tt>
+# * <tt>  **                            </tt>
+#
+# Matrix functions:
+# * <tt> #determinant                   </tt>
+# * <tt> #det                           </tt>
+# * <tt> #rank                          </tt>
+# * <tt> #trace                         </tt>
+# * <tt> #tr                            </tt>
+# * <tt> #transpose                     </tt>
+# * <tt> #t                             </tt>
+#
+# Conversion to other data types:
+# * <tt> #coerce(other)                 </tt>
+# * <tt> #row_vectors                   </tt>
+# * <tt> #column_vectors                </tt>
+# * <tt> #to_a                          </tt>
+#
+# String representations:
+# * <tt> #to_s                          </tt>
+# * <tt> #inspect                       </tt>
+#
+class Matrix
+  @RCS_ID='-$Id: matrix.rb,v 1.11 1999/10/06 11:01:53 keiju Exp keiju $-'
+  
+#  extend Exception2MessageMapper
+  include ExceptionForMatrix
+  
+  # instance creations
+  private_class_method :new
+  
+  #
+  # Creates a matrix where each argument is a row.
+  #   Matrix[ [25, 93], [-1, 66] ]
+  #      =>  25 93
+  #          -1 66
+  #
+  def Matrix.[](*rows)
+    new(:init_rows, rows, false)
+  end
+  
+  #
+  # Creates a matrix where +rows+ is an array of arrays, each of which is a row
+  # to the matrix.  If the optional argument +copy+ is false, use the given
+  # arrays as the internal structure of the matrix without copying.
+  #   Matrix.rows([[25, 93], [-1, 66]])
+  #      =>  25 93
+  #          -1 66
+  def Matrix.rows(rows, copy = true)
+    new(:init_rows, rows, copy)
+  end
+  
+  #
+  # Creates a matrix using +columns+ as an array of column vectors.
+  #   Matrix.columns([[25, 93], [-1, 66]])
+  #      =>  25 -1
+  #          93 66
+  #
+  #
+  def Matrix.columns(columns)
+    rows = (0 .. columns[0].size - 1).collect {
+      |i|
+      (0 .. columns.size - 1).collect {
+        |j|
+        columns[j][i]
+      }
+    }
+    Matrix.rows(rows, false)
+  end
+  
+  #
+  # Creates a matrix where the diagonal elements are composed of +values+.
+  #   Matrix.diagonal(9, 5, -3)
+  #     =>  9  0  0
+  #         0  5  0
+  #         0  0 -3
+  #
+  def Matrix.diagonal(*values)
+    size = values.size
+    rows = (0 .. size  - 1).collect {
+      |j|
+      row = Array.new(size).fill(0, 0, size)
+      row[j] = values[j]
+      row
+    }
+    rows(rows, false)
+  end
+  
+  #
+  # Creates an +n+ by +n+ diagonal matrix where each diagonal element is
+  # +value+.
+  #   Matrix.scalar(2, 5)
+  #     => 5 0
+  #        0 5
+  #
+  def Matrix.scalar(n, value)
+    Matrix.diagonal(*Array.new(n).fill(value, 0, n))
+  end
+
+  #
+  # Creates an +n+ by +n+ identity matrix.
+  #   Matrix.identity(2)
+  #     => 1 0
+  #        0 1
+  #
+  def Matrix.identity(n)
+    Matrix.scalar(n, 1)
+  end
+  class << Matrix 
+    alias unit identity
+    alias I identity
+  end
+  
+  #
+  # Creates an +n+ by +n+ zero matrix.
+  #   Matrix.zero(2)
+  #     => 0 0
+  #        0 0
+  #
+  def Matrix.zero(n)
+    Matrix.scalar(n, 0)
+  end
+  
+  #
+  # Creates a single-row matrix where the values of that row are as given in
+  # +row+.
+  #   Matrix.row_vector([4,5,6])
+  #     => 4 5 6
+  #
+  def Matrix.row_vector(row)
+    case row
+    when Vector
+      Matrix.rows([row.to_a], false)
+    when Array
+      Matrix.rows([row.dup], false)
+    else
+      Matrix.rows([[row]], false)
+    end
+  end
+  
+  #
+  # Creates a single-column matrix where the values of that column are as given
+  # in +column+.
+  #   Matrix.column_vector([4,5,6])
+  #     => 4
+  #        5
+  #        6
+  #
+  def Matrix.column_vector(column)
+    case column
+    when Vector
+      Matrix.columns([column.to_a])
+    when Array
+      Matrix.columns([column])
+    else
+      Matrix.columns([[column]])
+    end
+  end
+
+  #
+  # This method is used by the other methods that create matrices, and is of no
+  # use to general users.
+  #
+  def initialize(init_method, *argv)
+    self.send(init_method, *argv)
+  end
+  
+  def init_rows(rows, copy)
+    if copy
+      @rows = rows.collect{|row| row.dup}
+    else
+      @rows = rows
+    end
+    self
+  end
+  private :init_rows
+  
+  #
+  # Returns element (+i+,+j+) of the matrix.  That is: row +i+, column +j+.
+  #
+  def [](i, j)
+    @rows[i][j]
+  end
+
+  #
+  # Returns the number of rows.
+  #
+  def row_size
+    @rows.size
+  end
+  
+  #
+  # Returns the number of columns.  Note that it is possible to construct a
+  # matrix with uneven columns (e.g. Matrix[ [1,2,3], [4,5] ]), but this is
+  # mathematically unsound.  This method uses the first row to determine the
+  # result.
+  #
+  def column_size
+    @rows[0].size
+  end
+
+  #
+  # Returns row vector number +i+ of the matrix as a Vector (starting at 0 like
+  # an array).  When a block is given, the elements of that vector are iterated.
+  #
+  def row(i) # :yield: e
+    if block_given?
+      for e in @rows[i]
+        yield e
+      end
+    else
+      Vector.elements(@rows[i])
+    end
+  end
+
+  #
+  # Returns column vector number +j+ of the matrix as a Vector (starting at 0
+  # like an array).  When a block is given, the elements of that vector are
+  # iterated.
+  #
+  def column(j) # :yield: e
+    if block_given?
+      0.upto(row_size - 1) do
+        |i|
+        yield @rows[i][j]
+      end
+    else
+      col = (0 .. row_size - 1).collect {
+        |i|
+        @rows[i][j]
+      }
+      Vector.elements(col, false)
+    end
+  end
+  
+  #
+  # Returns a matrix that is the result of iteration of the given block over all
+  # elements of the matrix.
+  #   Matrix[ [1,2], [3,4] ].collect { |i| i**2 }
+  #     => 1  4
+  #        9 16
+  #
+  def collect # :yield: e
+    rows = @rows.collect{|row| row.collect{|e| yield e}}
+    Matrix.rows(rows, false)
+  end
+  alias map collect
+  
+  #
+  # Returns a section of the matrix.  The parameters are either:
+  # *  start_row, nrows, start_col, ncols; OR
+  # *  col_range, row_range
+  #
+  #   Matrix.diagonal(9, 5, -3).minor(0..1, 0..2)
+  #     => 9 0 0
+  #        0 5 0
+  #
+  def minor(*param)
+    case param.size
+    when 2
+      from_row = param[0].first
+      size_row = param[0].end - from_row
+      size_row += 1 unless param[0].exclude_end?
+      from_col = param[1].first
+      size_col = param[1].end - from_col
+      size_col += 1 unless param[1].exclude_end?
+    when 4
+      from_row = param[0]
+      size_row = param[1]
+      from_col = param[2]
+      size_col = param[3]
+    else
+      Matrix.Raise ArgumentError, param.inspect
+    end
+    
+    rows = @rows[from_row, size_row].collect{
+      |row|
+      row[from_col, size_col]
+    }
+    Matrix.rows(rows, false)
+  end
+ 
+  #--
+  # TESTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  #++
+
+  #
+  # Returns +true+ if this is a regular matrix.
+  #
+  def regular?
+    square? and rank == column_size
+  end
+  
+  #
+  # Returns +true+ is this is a singular (i.e. non-regular) matrix.
+  #
+  def singular?
+    not regular?
+  end
+
+  #
+  # Returns +true+ is this is a square matrix.  See note in column_size about this
+  # being unreliable, though.
+  #
+  def square?
+    column_size == row_size
+  end
+  
+  #--
+  # OBJECT METHODS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  #++
+
+  #
+  # Returns +true+ if and only if the two matrices contain equal elements.
+  #
+  def ==(other)
+    return false unless Matrix === other
+    
+    other.compare_by_row_vectors(@rows)
+  end
+  alias eql? ==
+  
+  #
+  # Not really intended for general consumption.
+  #
+  def compare_by_row_vectors(rows)
+    return false unless @rows.size == rows.size
+    
+    0.upto(@rows.size - 1) do
+      |i|
+      return false unless @rows[i] == rows[i]
+    end
+    true
+  end
+  
+  #
+  # Returns a clone of the matrix, so that the contents of each do not reference
+  # identical objects.
+  #
+  def clone
+    Matrix.rows(@rows)
+  end
+  
+  #
+  # Returns a hash-code for the matrix.
+  #
+  def hash
+    value = 0
+    for row in @rows
+      for e in row
+        value ^= e.hash
+      end
+    end
+    return value
+  end
+  
+  #--
+  # ARITHMETIC -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  #++
+  
+  #
+  # Matrix multiplication.
+  #   Matrix[[2,4], [6,8]] * Matrix.identity(2)
+  #     => 2 4
+  #        6 8
+  #
+  def *(m) # m is matrix or vector or number
+    case(m)
+    when Numeric
+      rows = @rows.collect {
+        |row|
+        row.collect {
+          |e|
+          e * m
+        }
+      }
+      return Matrix.rows(rows, false)
+    when Vector
+      m = Matrix.column_vector(m)
+      r = self * m
+      return r.column(0)
+    when Matrix
+      Matrix.Raise ErrDimensionMismatch if column_size != m.row_size
+    
+      rows = (0 .. row_size - 1).collect {
+        |i|
+        (0 .. m.column_size - 1).collect {
+          |j|
+          vij = 0
+          0.upto(column_size - 1) do
+            |k|
+            vij += self[i, k] * m[k, j]
+          end
+          vij
+        }
+      }
+      return Matrix.rows(rows, false)
+    else
+      x, y = m.coerce(self)
+      return x * y
+    end
+  end
+  
+  #
+  # Matrix addition.
+  #   Matrix.scalar(2,5) + Matrix[[1,0], [-4,7]]
+  #     =>  6  0
+  #        -4 12
+  #
+  def +(m)
+    case m
+    when Numeric
+      Matrix.Raise ErrOperationNotDefined, "+"
+    when Vector
+      m = Matrix.column_vector(m)
+    when Matrix
+    else
+      x, y = m.coerce(self)
+      return x + y
+    end
+    
+    Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size
+    
+    rows = (0 .. row_size - 1).collect {
+      |i|
+      (0 .. column_size - 1).collect {
+        |j|
+        self[i, j] + m[i, j]
+      }
+    }
+    Matrix.rows(rows, false)
+  end
+
+  #
+  # Matrix subtraction.
+  #   Matrix[[1,5], [4,2]] - Matrix[[9,3], [-4,1]]
+  #     => -8  2
+  #         8  1
+  #
+  def -(m)
+    case m
+    when Numeric
+      Matrix.Raise ErrOperationNotDefined, "-"
+    when Vector
+      m = Matrix.column_vector(m)
+    when Matrix
+    else
+      x, y = m.coerce(self)
+      return x - y
+    end
+    
+    Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size
+    
+    rows = (0 .. row_size - 1).collect {
+      |i|
+      (0 .. column_size - 1).collect {
+        |j|
+        self[i, j] - m[i, j]
+      }
+    }
+    Matrix.rows(rows, false)
+  end
+  
+  #
+  # Matrix division (multiplication by the inverse).
+  #   Matrix[[7,6], [3,9]] / Matrix[[2,9], [3,1]]
+  #     => -7  1
+  #        -3 -6
+  #
+  def /(other)
+    case other
+    when Numeric
+      rows = @rows.collect {
+        |row|
+        row.collect {
+          |e|
+          e / other
+        }
+      }
+      return Matrix.rows(rows, false)
+    when Matrix
+      return self * other.inverse
+    else
+      x, y = other.coerce(self)
+      rerurn x / y
+    end
+  end
+
+  #
+  # Returns the inverse of the matrix.
+  #   Matrix[[1, 2], [2, 1]].inverse
+  #     => -1  1
+  #         0 -1
+  #
+  def inverse
+    Matrix.Raise ErrDimensionMismatch unless square?
+    Matrix.I(row_size).inverse_from(self)
+  end
+  alias inv inverse
+
+  #
+  # Not for public consumption?
+  #
+  def inverse_from(src)
+    size = row_size - 1
+    a = src.to_a
+    
+    for k in 0..size
+      if (akk = a[k][k]) == 0
+        i = k
+        begin
+          Matrix.Raise ErrNotRegular if (i += 1) > size
+        end while a[i][k] == 0
+        a[i], a[k] = a[k], a[i]
+        @rows[i], @rows[k] = @rows[k], @rows[i]
+        akk = a[k][k]
+      end
+      
+      for i in 0 .. size
+        next if i == k
+        q = a[i][k] / akk
+        a[i][k] = 0
+        
+        (k + 1).upto(size) do   
+          |j|
+          a[i][j] -= a[k][j] * q
+        end
+        0.upto(size) do
+          |j|
+          @rows[i][j] -= @rows[k][j] * q
+        end
+      end
+      
+      (k + 1).upto(size) do
+        |j|
+        a[k][j] /= akk
+      end
+      0.upto(size) do
+        |j|
+        @rows[k][j] /= akk
+      end
+    end
+    self
+  end
+  #alias reciprocal inverse
+  
+  #
+  # Matrix exponentiation.  Defined for integer powers only.  Equivalent to
+  # multiplying the matrix by itself N times.
+  #   Matrix[[7,6], [3,9]] ** 2
+  #     => 67 96
+  #        48 99
+  #
+  def ** (other)
+    if other.kind_of?(Integer)
+      x = self
+      if other <= 0
+        x = self.inverse
+        return Matrix.identity(self.column_size) if other == 0
+        other = -other
+      end
+      z = x
+      n = other  - 1
+      while n != 0
+        while (div, mod = n.divmod(2)
+               mod == 0)
+          x = x * x
+          n = div
+        end
+        z *= x
+        n -= 1
+      end
+      z
+    elsif other.kind_of?(Float) || defined?(Rational) && other.kind_of?(Rational)
+      Matrix.Raise ErrOperationNotDefined, "**"
+    else
+      Matrix.Raise ErrOperationNotDefined, "**"
+    end
+  end
+  
+  #--
+  # MATRIX FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  #++
+  
+  #
+  # Returns the determinant of the matrix.  If the matrix is not square, the
+  # result is 0.
+  #   Matrix[[7,6], [3,9]].determinant
+  #     => 63
+  #
+  def determinant
+    return 0 unless square?
+    
+    size = row_size - 1
+    a = to_a
+    
+    det = 1
+    k = 0
+    begin 
+      if (akk = a[k][k]) == 0
+        i = k
+        begin
+          return 0 if (i += 1) > size
+        end while a[i][k] == 0
+        a[i], a[k] = a[k], a[i]
+        akk = a[k][k]
+        det *= -1
+      end
+      (k + 1).upto(size) do
+        |i|
+        q = a[i][k] / akk
+        (k + 1).upto(size) do
+          |j|
+          a[i][j] -= a[k][j] * q
+        end
+      end
+      det *= akk
+    end while (k += 1) <= size
+    det
+  end
+  alias det determinant
+        
+  #
+  # Returns the rank of the matrix.  Beware that using Float values, with their
+  # usual lack of precision, can affect the value returned by this method.  Use
+  # Rational values instead if this is important to you.
+  #   Matrix[[7,6], [3,9]].rank
+  #     => 2
+  #
+  def rank
+    if column_size > row_size
+      a = transpose.to_a
+      a_column_size = row_size
+      a_row_size = column_size
+    else
+      a = to_a
+      a_column_size = column_size
+      a_row_size = row_size
+    end
+    rank = 0
+    k = 0
+    begin
+      if (akk = a[k][k]) == 0
+        i = k
+        exists = true
+        begin
+          if (i += 1) > a_column_size - 1
+            exists = false
+            break
+          end
+        end while a[i][k] == 0
+        if exists
+          a[i], a[k] = a[k], a[i]
+          akk = a[k][k]
+        else
+          i = k
+          exists = true
+          begin
+            if (i += 1) > a_row_size - 1
+              exists = false
+              break
+            end
+          end while a[k][i] == 0
+          if exists
+            k.upto(a_column_size - 1) do
+              |j|
+              a[j][k], a[j][i] = a[j][i], a[j][k]
+            end
+            akk = a[k][k]
+          else
+            next
+          end
+        end
+      end
+      (k + 1).upto(a_row_size - 1) do
+        |i|
+        q = a[i][k] / akk
+        (k + 1).upto(a_column_size - 1) do
+          |j|
+          a[i][j] -= a[k][j] * q
+        end
+      end
+      rank += 1
+    end while (k += 1) <= a_column_size - 1
+    return rank
+  end
+
+  #
+  # Returns the trace (sum of diagonal elements) of the matrix.
+  #   Matrix[[7,6], [3,9]].trace
+  #     => 16
+  #
+  def trace
+    tr = 0
+    0.upto(column_size - 1) do
+      |i|
+      tr += @rows[i][i]
+    end
+    tr
+  end
+  alias tr trace
+  
+  #
+  # Returns the transpose of the matrix.
+  #   Matrix[[1,2], [3,4], [5,6]]
+  #     => 1 2
+  #        3 4
+  #        5 6
+  #   Matrix[[1,2], [3,4], [5,6]].transpose
+  #     => 1 3 5
+  #        2 4 6
+  #
+  def transpose
+    Matrix.columns(@rows)
+  end
+  alias t transpose
+  
+  #--
+  # CONVERTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  #++
+  
+  #
+  # FIXME: describe #coerce.
+  #
+  def coerce(other)
+    case other
+    when Numeric
+      return Scalar.new(other), self
+    else
+      raise TypeError, "#{self.class} can't be coerced into #{other.class}"
+    end
+  end
+
+  #
+  # Returns an array of the row vectors of the matrix.  See Vector.
+  #
+  def row_vectors
+    rows = (0 .. row_size - 1).collect {
+      |i|
+      row(i)
+    }
+    rows
+  end
+  
+  #
+  # Returns an array of the column vectors of the matrix.  See Vector.
+  #
+  def column_vectors
+    columns = (0 .. column_size - 1).collect {
+      |i|
+      column(i)
+    }
+    columns
+  end
+  
+  #
+  # Returns an array of arrays that describe the rows of the matrix.
+  #
+  def to_a
+    @rows.collect{|row| row.collect{|e| e}}
+  end
+  
+  #--
+  # PRINTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  #++
+  
+  #
+  # Overrides Object#to_s
+  #
+  def to_s
+    "Matrix[" + @rows.collect{
+      |row|
+      "[" + row.collect{|e| e.to_s}.join(", ") + "]"
+    }.join(", ")+"]"
+  end
+  
+  #
+  # Overrides Object#inspect
+  #
+  def inspect
+    "Matrix"+@rows.inspect
+  end
+  
+  # Private CLASS
+  
+  class Scalar < Numeric # :nodoc:
+    include ExceptionForMatrix
+    
+    def initialize(value)
+      @value = value
+    end
+    
+    # ARITHMETIC
+    def +(other)
+      case other
+      when Numeric
+        Scalar.new(@value + other)
+      when Vector, Matrix
+        Scalar.Raise WrongArgType, other.class, "Numeric or Scalar"
+      when Scalar
+        Scalar.new(@value + other.value)
+      else
+        x, y = other.coerce(self)
+        x + y
+      end
+    end
+    
+    def -(other)
+      case other
+      when Numeric
+        Scalar.new(@value - other)
+      when Vector, Matrix
+        Scalar.Raise WrongArgType, other.class, "Numeric or Scalar"
+      when Scalar
+        Scalar.new(@value - other.value)
+      else
+        x, y = other.coerce(self)
+        x - y
+      end
+    end
+    
+    def *(other)
+      case other
+      when Numeric
+        Scalar.new(@value * other)
+      when Vector, Matrix
+        other.collect{|e| @value * e}
+      else
+        x, y = other.coerce(self)
+        x * y
+      end
+    end
+    
+    def / (other)
+      case other
+      when Numeric
+        Scalar.new(@value / other)
+      when Vector
+        Scalar.Raise WrongArgType, other.class, "Numeric or Scalar or Matrix"
+      when Matrix
+        self * _M.inverse
+      else
+        x, y = other.coerce(self)
+        x / y
+      end
+    end
+    
+    def ** (other)
+      case other
+      when Numeric
+        Scalar.new(@value ** other)
+      when Vector
+        Scalar.Raise WrongArgType, other.class, "Numeric or Scalar or Matrix"
+      when Matrix
+        other.powered_by(self)
+      else
+        x, y = other.coerce(self)
+        x ** y
+      end
+    end
+  end
+end
+
+
+#
+# The +Vector+ class represents a mathematical vector, which is useful in its own right, and
+# also constitutes a row or column of a Matrix.
+#
+# == Method Catalogue
+#
+# To create a Vector:
+# * <tt>  Vector.[](*array)                   </tt>
+# * <tt>  Vector.elements(array, copy = true) </tt>
+#
+# To access elements:
+# * <tt>  [](i)                               </tt>
+#
+# To enumerate the elements:
+# * <tt> #each2(v)                            </tt>
+# * <tt> #collect2(v)                         </tt>
+#
+# Vector arithmetic:
+# * <tt>  *(x) "is matrix or number"          </tt>
+# * <tt>  +(v)                                </tt>
+# * <tt>  -(v)                                </tt>
+#
+# Vector functions:
+# * <tt> #inner_product(v)                    </tt>
+# * <tt> #collect                             </tt>
+# * <tt> #map                                 </tt>
+# * <tt> #map2(v)                             </tt>
+# * <tt> #r                                   </tt>
+# * <tt> #size                                </tt>
+#
+# Conversion to other data types:
+# * <tt> #covector                            </tt>
+# * <tt> #to_a                                </tt>
+# * <tt> #coerce(other)                       </tt>
+#
+# String representations:
+# * <tt> #to_s                                </tt>
+# * <tt> #inspect                             </tt>
+#
+class Vector
+  include ExceptionForMatrix
+  
+  #INSTANCE CREATION
+  
+  private_class_method :new
+
+  #
+  # Creates a Vector from a list of elements.
+  #   Vector[7, 4, ...]
+  #
+  def Vector.[](*array)
+    new(:init_elements, array, copy = false)
+  end
+  
+  #
+  # Creates a vector from an Array.  The optional second argument specifies
+  # whether the array itself or a copy is used internally.
+  #
+  def Vector.elements(array, copy = true)
+    new(:init_elements, array, copy)
+  end
+  
+  #
+  # For internal use.
+  #
+  def initialize(method, array, copy)
+    self.send(method, array, copy)
+  end
+  
+  #
+  # For internal use.
+  #
+  def init_elements(array, copy)
+    if copy
+      @elements = array.dup
+    else
+      @elements = array
+    end
+  end
+  
+  # ACCESSING
+         
+  #
+  # Returns element number +i+ (starting at zero) of the vector.
+  #
+  def [](i)
+    @elements[i]
+  end
+  
+  #
+  # Returns the number of elements in the vector.
+  #
+  def size
+    @elements.size
+  end
+  
+  #--
+  # ENUMERATIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  #++
+
+  #
+  # Iterate over the elements of this vector and +v+ in conjunction.
+  #
+  def each2(v) # :yield: e1, e2
+    Vector.Raise ErrDimensionMismatch if size != v.size
+    0.upto(size - 1) do
+      |i|
+      yield @elements[i], v[i]
+    end
+  end
+  
+  #
+  # Collects (as in Enumerable#collect) over the elements of this vector and +v+
+  # in conjunction.
+  #
+  def collect2(v) # :yield: e1, e2
+    Vector.Raise ErrDimensionMismatch if size != v.size
+    (0 .. size - 1).collect do
+      |i|
+      yield @elements[i], v[i]
+    end
+  end
+
+  #--
+  # COMPARING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  #++
+
+  #
+  # Returns +true+ iff the two vectors have the same elements in the same order.
+  #
+  def ==(other)
+    return false unless Vector === other
+    
+    other.compare_by(@elements)
+  end
+  alias eqn? ==
+  
+  #
+  # For internal use.
+  #
+  def compare_by(elements)
+    @elements == elements
+  end
+  
+  #
+  # Return a copy of the vector.
+  #
+  def clone
+    Vector.elements(@elements)
+  end
+  
+  #
+  # Return a hash-code for the vector.
+  #
+  def hash
+    @elements.hash
+  end
+  
+  #--
+  # ARITHMETIC -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  #++
+  
+  #
+  # Multiplies the vector by +x+, where +x+ is a number or another vector.
+  #
+  def *(x)
+    case x
+    when Numeric
+      els = @elements.collect{|e| e * x}
+      Vector.elements(els, false)
+    when Matrix
+      Matrix.column_vector(self) * x
+    else
+      s, x = x.coerce(self)
+      s * x
+    end
+  end
+
+  #
+  # Vector addition.
+  #
+  def +(v)
+    case v
+    when Vector
+      Vector.Raise ErrDimensionMismatch if size != v.size
+      els = collect2(v) {
+        |v1, v2|
+        v1 + v2
+      }
+      Vector.elements(els, false)
+    when Matrix
+      Matrix.column_vector(self) + v
+    else
+      s, x = v.coerce(self)
+      s + x
+    end
+  end
+
+  #
+  # Vector subtraction.
+  #
+  def -(v)
+    case v
+    when Vector
+      Vector.Raise ErrDimensionMismatch if size != v.size
+      els = collect2(v) {
+        |v1, v2|
+        v1 - v2
+      }
+      Vector.elements(els, false)
+    when Matrix
+      Matrix.column_vector(self) - v
+    else
+      s, x = v.coerce(self)
+      s - x
+    end
+  end
+  
+  #--
+  # VECTOR FUNCTIONS -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  #++
+  
+  #
+  # Returns the inner product of this vector with the other.
+  #   Vector[4,7].inner_product Vector[10,1]  => 47
+  #
+  def inner_product(v)
+    Vector.Raise ErrDimensionMismatch if size != v.size
+    
+    p = 0
+    each2(v) {
+      |v1, v2|
+      p += v1 * v2
+    }
+    p
+  end
+  
+  #
+  # Like Array#collect.
+  #
+  def collect # :yield: e
+    els = @elements.collect {
+      |v|
+      yield v
+    }
+    Vector.elements(els, false)
+  end
+  alias map collect
+  
+  #
+  # Like Vector#collect2, but returns a Vector instead of an Array.
+  #
+  def map2(v) # :yield: e1, e2
+    els = collect2(v) {
+      |v1, v2|
+      yield v1, v2
+    }
+    Vector.elements(els, false)
+  end
+  
+  #
+  # Returns the modulus (Pythagorean distance) of the vector.
+  #   Vector[5,8,2].r => 9.643650761
+  #
+  def r
+    v = 0
+    for e in @elements
+      v += e*e
+    end
+    return Math.sqrt(v)
+  end
+  
+  #--
+  # CONVERTING
+  #++
+
+  #
+  # Creates a single-row matrix from this vector.
+  #
+  def covector
+    Matrix.row_vector(self)
+  end
+  
+  #
+  # Returns the elements of the vector in an array.
+  #
+  def to_a
+    @elements.dup
+  end
+  
+  #
+  # FIXME: describe Vector#coerce.
+  #
+  def coerce(other)
+    case other
+    when Numeric
+      return Scalar.new(other), self
+    else
+      raise TypeError, "#{self.class} can't be coerced into #{other.class}"
+    end
+  end
+  
+  #--
+  # PRINTING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  #++
+  
+  #
+  # Overrides Object#to_s
+  #
+  def to_s
+    "Vector[" + @elements.join(", ") + "]"
+  end
+  
+  #
+  # Overrides Object#inspect
+  #
+  def inspect
+    str = "Vector"+@elements.inspect
+  end
+end
+
+
+# Documentation comments:
+#  - Matrix#coerce and Vector#coerce need to be documented
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/md5.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/md5.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/md5.rb	(revision 18425)
@@ -0,0 +1,23 @@
+# just for compatibility; requiring "md5" is obsoleted
+#
+# $RoughId: md5.rb,v 1.4 2001/07/13 15:38:27 knu Exp $
+# $Id: md5.rb 12008 2007-03-06 10:12:12Z knu $
+
+require 'digest/md5'
+
+class MD5 < Digest::MD5
+  class << self
+    alias orig_new new
+    def new(str = nil)
+      if str
+        orig_new.update(str)
+      else
+        orig_new
+      end
+    end
+
+    def md5(*args)
+      new(*args)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/mkmf.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/mkmf.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/mkmf.rb	(revision 18425)
@@ -0,0 +1,1540 @@
+# module to create Makefile for extension modules
+# invoke like: ruby -r mkmf extconf.rb
+
+require 'rbconfig'
+require 'fileutils'
+require 'shellwords'
+
+CONFIG = Config::MAKEFILE_CONFIG
+ORIG_LIBPATH = ENV['LIB']
+
+CXX_EXT = %w[cc cxx cpp]
+if /mswin|bccwin|mingw|msdosdjgpp|human|os2/ !~ CONFIG['build_os']
+  CXX_EXT.concat(%w[C])
+end
+SRC_EXT = %w[c m] << CXX_EXT
+$static = $config_h = nil
+$default_static = $static
+
+unless defined? $configure_args
+  $configure_args = {}
+  args = CONFIG["configure_args"]
+  if ENV["CONFIGURE_ARGS"]
+    args << " " << ENV["CONFIGURE_ARGS"]
+  end
+  for arg in Shellwords::shellwords(args)
+    arg, val = arg.split('=', 2)
+    next unless arg
+    arg.tr!('_', '-')
+    if arg.sub!(/^(?!--)/, '--')
+      val or next
+      arg.downcase!
+    end
+    next if /^--(?:top|topsrc|src|cur)dir$/ =~ arg
+    $configure_args[arg] = val || true
+  end
+  for arg in ARGV
+    arg, val = arg.split('=', 2)
+    next unless arg
+    arg.tr!('_', '-')
+    if arg.sub!(/^(?!--)/, '--')
+      val or next
+      arg.downcase!
+    end
+    $configure_args[arg] = val || true
+  end
+end
+
+$libdir = CONFIG["libdir"]
+$rubylibdir = CONFIG["rubylibdir"]
+$archdir = CONFIG["archdir"]
+$sitedir = CONFIG["sitedir"]
+$sitelibdir = CONFIG["sitelibdir"]
+$sitearchdir = CONFIG["sitearchdir"]
+
+$mswin = /mswin/ =~ RUBY_PLATFORM
+$bccwin = /bccwin/ =~ RUBY_PLATFORM
+$mingw = /mingw/ =~ RUBY_PLATFORM
+$cygwin = /cygwin/ =~ RUBY_PLATFORM
+$human = /human/ =~ RUBY_PLATFORM
+$netbsd = /netbsd/ =~ RUBY_PLATFORM
+$os2 = /os2/ =~ RUBY_PLATFORM
+$beos = /beos/ =~ RUBY_PLATFORM
+$solaris = /solaris/ =~ RUBY_PLATFORM
+$dest_prefix_pattern = (File::PATH_SEPARATOR == ';' ? /\A([[:alpha:]]:)?/ : /\A/)
+
+def config_string(key, config = CONFIG)
+  s = config[key] and !s.empty? and block_given? ? yield(s) : s
+end
+
+def dir_re(dir)
+  Regexp.new('\$(?:\('+dir+'\)|\{'+dir+'\})(?:\$(?:\(target_prefix\)|\{target_prefix\}))?')
+end
+
+INSTALL_DIRS = [
+  [dir_re('commondir'), "$(RUBYCOMMONDIR)"],
+  [dir_re("sitedir"), "$(RUBYCOMMONDIR)"],
+  [dir_re('rubylibdir'), "$(RUBYLIBDIR)"],
+  [dir_re('archdir'), "$(RUBYARCHDIR)"],
+  [dir_re('sitelibdir'), "$(RUBYLIBDIR)"],
+  [dir_re('sitearchdir'), "$(RUBYARCHDIR)"]
+]
+
+def install_dirs(target_prefix = nil)
+  if $extout
+    dirs = [
+      ['RUBYCOMMONDIR', '$(extout)/common'],
+      ['RUBYLIBDIR',    '$(RUBYCOMMONDIR)$(target_prefix)'],
+      ['RUBYARCHDIR',   '$(extout)/$(arch)$(target_prefix)'],
+      ['extout',        "#$extout"],
+      ['extout_prefix', "#$extout_prefix"],
+    ]
+  elsif $extmk
+    dirs = [
+      ['RUBYCOMMONDIR', '$(rubylibdir)'],
+      ['RUBYLIBDIR',    '$(rubylibdir)$(target_prefix)'],
+      ['RUBYARCHDIR',   '$(archdir)$(target_prefix)'],
+    ]
+  else
+    dirs = [
+      ['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'],
+      ['RUBYLIBDIR',    '$(sitelibdir)$(target_prefix)'],
+      ['RUBYARCHDIR',   '$(sitearchdir)$(target_prefix)'],
+    ]
+  end
+  dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")]
+  dirs
+end
+
+def map_dir(dir, map = nil)
+  map ||= INSTALL_DIRS
+  map.inject(dir) {|dir, (orig, new)| dir.gsub(orig, new)}
+end
+
+topdir = File.dirname(libdir = File.dirname(__FILE__))
+extdir = File.expand_path("ext", topdir)
+$extmk = File.expand_path($0)[0, extdir.size+1] == extdir+"/"
+if not $extmk and File.exist?(Config::CONFIG["archdir"] + "/ruby.h")
+  $hdrdir = $topdir = Config::CONFIG["archdir"]
+elsif File.exist?(($top_srcdir ||= topdir)  + "/ruby.h") and
+    File.exist?(($topdir ||= Config::CONFIG["topdir"]) + "/config.h")
+  $hdrdir = $top_srcdir
+else
+  abort "can't find header files for ruby."
+end
+
+OUTFLAG = CONFIG['OUTFLAG']
+CPPOUTFILE = CONFIG['CPPOUTFILE']
+
+CONFTEST_C = "conftest.c"
+
+class String
+  def quote
+    /\s/ =~ self ? "\"#{self}\"" : self
+  end
+end
+class Array
+  def quote
+    map {|s| s.quote}
+  end
+end
+
+def rm_f(*files)
+  FileUtils.rm_f(Dir[files.join("\0")])
+end
+
+def modified?(target, times)
+  (t = File.mtime(target)) rescue return nil
+  Array === times or times = [times]
+  t if times.all? {|n| n <= t}
+end
+
+def merge_libs(*libs)
+  libs.inject([]) do |x, y|
+    xy = x & y
+    xn = yn = 0
+    y = y.inject([]) {|ary, e| ary.last == e ? ary : ary << e}
+    y.each_with_index do |v, yi|
+      if xy.include?(v)
+        xi = [x.index(v), xn].max()
+        x[xi, 1] = y[yn..yi]
+        xn, yn = xi + (yi - yn + 1), yi + 1
+      end
+    end
+    x.concat(y[yn..-1] || [])
+  end
+end
+
+module Logging
+  @log = nil
+  @logfile = 'mkmf.log'
+  @orgerr = $stderr.dup
+  @orgout = $stdout.dup
+  @postpone = 0
+
+  def self::open
+    @log ||= File::open(@logfile, 'w')
+    @log.sync = true
+    $stderr.reopen(@log)
+    $stdout.reopen(@log)
+    yield
+  ensure
+    $stderr.reopen(@orgerr)
+    $stdout.reopen(@orgout)
+  end
+
+  def self::message(*s)
+    @log ||= File::open(@logfile, 'w')
+    @log.sync = true
+    @log.printf(*s)
+  end
+
+  def self::logfile file
+    @logfile = file
+    if @log and not @log.closed?
+      @log.flush
+      @log.close
+      @log = nil
+    end
+  end
+  
+  def self::postpone
+    tmplog = "mkmftmp#{@postpone += 1}.log"
+    open do
+      log, *save = @log, @logfile, @orgout, @orgerr
+      @log, @logfile, @orgout, @orgerr = nil, tmplog, log, log
+      begin
+        log.print(open {yield})
+        @log.close
+        File::open(tmplog) {|t| FileUtils.copy_stream(t, log)}
+      ensure
+        @log, @logfile, @orgout, @orgerr = log, *save
+        @postpone -= 1
+        rm_f tmplog
+      end
+    end
+  end
+end
+
+def xsystem command
+  Logging::open do
+    puts command.quote
+    system(command)
+  end
+end
+
+def xpopen command, *mode, &block
+  Logging::open do
+    case mode[0]
+    when nil, /^r/
+      puts "#{command} |"
+    else
+      puts "| #{command}"
+    end
+    IO.popen(command, *mode, &block)
+  end
+end
+
+def log_src(src)
+  src = src.split(/^/)
+  fmt = "%#{src.size.to_s.size}d: %s"
+  Logging::message <<"EOM"
+checked program was:
+/* begin */
+EOM
+  src.each_with_index {|line, no| Logging::message fmt, no+1, line}
+  Logging::message <<"EOM"
+/* end */
+
+EOM
+end
+
+def create_tmpsrc(src)
+  src = yield(src) if block_given?
+  src = src.gsub(/[ \t]+$/, '').gsub(/\A\n+|^\n+$/, '').sub(/[^\n]\z/, "\\&\n")
+  open(CONFTEST_C, "wb") do |cfile|
+    cfile.print src
+  end
+  src
+end
+
+def try_do(src, command, &b)
+  src = create_tmpsrc(src, &b)
+  xsystem(command)
+ensure
+  log_src(src)
+end
+
+def link_command(ldflags, opt="", libpath=$DEFLIBPATH|$LIBPATH)
+  Config::expand(TRY_LINK.dup,
+                 CONFIG.merge('hdrdir' => $hdrdir.quote,
+                              'src' => CONFTEST_C,
+                              'INCFLAGS' => $INCFLAGS,
+                              'CPPFLAGS' => $CPPFLAGS,
+                              'CFLAGS' => "#$CFLAGS",
+                              'ARCH_FLAG' => "#$ARCH_FLAG",
+                              'LDFLAGS' => "#$LDFLAGS #{ldflags}",
+                              'LIBPATH' => libpathflag(libpath),
+                              'LOCAL_LIBS' => "#$LOCAL_LIBS #$libs",
+                              'LIBS' => "#$LIBRUBYARG_STATIC #{opt} #$LIBS"))
+end
+
+def cc_command(opt="")
+  Config::expand("$(CC) #$INCFLAGS #$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_C}",
+		 CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote))
+end
+
+def cpp_command(outfile, opt="")
+  Config::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}",
+		 CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote))
+end
+
+def libpathflag(libpath=$DEFLIBPATH|$LIBPATH)
+  libpath.map{|x|
+    (x == "$(topdir)" ? LIBPATHFLAG : LIBPATHFLAG+RPATHFLAG) % x.quote
+  }.join
+end
+
+def try_link0(src, opt="", &b)
+  try_do(src, link_command("", opt), &b)
+end
+
+def try_link(src, opt="", &b)
+  try_link0(src, opt, &b)
+ensure
+  rm_f "conftest*", "c0x32*"
+end
+
+def try_compile(src, opt="", &b)
+  try_do(src, cc_command(opt), &b)
+ensure
+  rm_f "conftest*"
+end
+
+def try_cpp(src, opt="", &b)
+  try_do(src, cpp_command(CPPOUTFILE, opt), &b)
+ensure
+  rm_f "conftest*"
+end
+
+def cpp_include(header)
+  if header
+    header = [header] unless header.kind_of? Array
+    header.map {|h| "#include <#{h}>\n"}.join
+  else
+    ""
+  end
+end
+
+def with_cppflags(flags)
+  cppflags = $CPPFLAGS
+  $CPPFLAGS = flags
+  ret = yield
+ensure
+  $CPPFLAGS = cppflags unless ret
+end
+
+def with_cflags(flags)
+  cflags = $CFLAGS
+  $CFLAGS = flags
+  ret = yield
+ensure
+  $CFLAGS = cflags unless ret
+end
+
+def with_ldflags(flags)
+  ldflags = $LDFLAGS
+  $LDFLAGS = flags
+  ret = yield
+ensure
+  $LDFLAGS = ldflags unless ret
+end
+
+def try_static_assert(expr, headers = nil, opt = "", &b)
+  headers = cpp_include(headers)
+  try_compile(<<SRC, opt, &b)
+#{COMMON_HEADERS}
+#{headers}
+/*top*/
+int conftest_const[(#{expr}) ? 1 : -1];
+SRC
+end
+
+def try_constant(const, headers = nil, opt = "", &b)
+  includes = cpp_include(headers)
+  if CROSS_COMPILING
+    if try_static_assert("#{const} > 0", headers, opt)
+      # positive constant
+    elsif try_static_assert("#{const} < 0", headers, opt)
+      neg = true
+      const = "-(#{const})"
+    elsif try_static_assert("#{const} == 0", headers, opt)
+      return 0
+    else
+      # not a constant
+      return nil
+    end
+    upper = 1
+    lower = 0
+    until try_static_assert("#{const} <= #{upper}", headers, opt)
+      lower = upper
+      upper <<= 1
+    end
+    return nil unless lower
+    while upper > lower + 1
+      mid = (upper + lower) / 2
+      if try_static_assert("#{const} > #{mid}", headers, opt)
+        lower = mid
+      else
+        upper = mid
+      end
+    end
+    upper = -upper if neg
+    return upper
+  else
+    src = %{#{COMMON_HEADERS}
+#{includes}
+#include <stdio.h>
+/*top*/
+int conftest_const = (int)(#{const});
+int main() {printf("%d\\n", conftest_const); return 0;}
+}
+    if try_link0(src, opt, &b)
+      xpopen("./conftest") do |f|
+        return Integer(f.gets)
+      end
+    end
+  end
+  nil
+end
+
+def try_func(func, libs, headers = nil, &b)
+  headers = cpp_include(headers)
+  try_link(<<"SRC", libs, &b) or try_link(<<"SRC", libs, &b)
+#{COMMON_HEADERS}
+#{headers}
+/*top*/
+int main() { return 0; }
+int t() { void ((*volatile p)()); p = (void ((*)()))#{func}; return 0; }
+SRC
+#{headers}
+/*top*/
+int main() { return 0; }
+int t() { #{func}(); return 0; }
+SRC
+end
+
+def try_var(var, headers = nil, &b)
+  headers = cpp_include(headers)
+  try_compile(<<"SRC", &b)
+#{COMMON_HEADERS}
+#{headers}
+/*top*/
+int main() { return 0; }
+int t() { const volatile void *volatile p; p = (void *)&#{var}; return 0; }
+SRC
+end
+
+def egrep_cpp(pat, src, opt = "", &b)
+  src = create_tmpsrc(src, &b)
+  xpopen(cpp_command('', opt)) do |f|
+    if Regexp === pat
+      puts("    ruby -ne 'print if #{pat.inspect}'")
+      f.grep(pat) {|l|
+	puts "#{f.lineno}: #{l}"
+	return true
+      }
+      false
+    else
+      puts("    egrep '#{pat}'")
+      begin
+	stdin = $stdin.dup
+	$stdin.reopen(f)
+	system("egrep", pat)
+      ensure
+	$stdin.reopen(stdin)
+      end
+    end
+  end
+ensure
+  rm_f "conftest*"
+  log_src(src)
+end
+
+def macro_defined?(macro, src, opt = "", &b)
+  src = src.sub(/[^\n]\z/, "\\&\n")
+  try_compile(src + <<"SRC", opt, &b)
+/*top*/
+#ifndef #{macro}
+# error
+>>>>>> #{macro} undefined <<<<<<
+#endif
+SRC
+end
+
+def try_run(src, opt = "", &b)
+  if try_link0(src, opt, &b)
+    xsystem("./conftest")
+  else
+    nil
+  end
+ensure
+  rm_f "conftest*"
+end
+
+def install_files(mfile, ifiles, map = nil, srcprefix = nil)
+  ifiles or return
+  srcprefix ||= '$(srcdir)'
+  Config::expand(srcdir = srcprefix.dup)
+  dirs = []
+  path = Hash.new {|h, i| h[i] = dirs.push([i])[-1]}
+  ifiles.each do |files, dir, prefix|
+    dir = map_dir(dir, map)
+    prefix = %r|\A#{Regexp.quote(prefix)}/?| if prefix
+    if /\A\.\// =~ files
+      # install files which are in current working directory.
+      files = files[2..-1]
+      len = nil
+    else
+      # install files which are under the $(srcdir).
+      files = File.join(srcdir, files)
+      len = srcdir.size
+    end
+    f = nil
+    Dir.glob(files) do |f|
+      f[0..len] = "" if len
+      d = File.dirname(f)
+      d.sub!(prefix, "") if prefix
+      d = (d.empty? || d == ".") ? dir : File.join(dir, d)
+      f = File.join(srcprefix, f) if len
+      path[d] << f
+    end
+    unless len or f
+      d = File.dirname(files)
+      d.sub!(prefix, "") if prefix
+      d = (d.empty? || d == ".") ? dir : File.join(dir, d)
+      path[d] << files
+    end
+  end
+  dirs
+end
+
+def install_rb(mfile, dest, srcdir = nil)
+  install_files(mfile, [["lib/**/*.rb", dest, "lib"]], nil, srcdir)
+end
+
+def append_library(libs, lib)
+  format(LIBARG, lib) + " " + libs
+end
+
+def message(*s)
+  unless $extmk and not $VERBOSE
+    printf(*s)
+    $stdout.flush
+  end
+end
+
+def checking_for(m, fmt = nil)
+  f = caller[0][/in `(.*)'$/, 1] and f << ": " #` for vim
+  m = "checking #{/\Acheck/ =~ f ? '' : 'for '}#{m}... "
+  message "%s", m
+  a = r = nil
+  Logging::postpone do
+    r = yield
+    a = (fmt ? fmt % r : r ? "yes" : "no") << "\n"
+    "#{f}#{m}-------------------- #{a}\n"
+  end
+  message(a)
+  Logging::message "--------------------\n\n"
+  r
+end
+
+def checking_message(target, place = nil, opt = nil)
+  [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)|
+    if noun
+      [[:to_str], [:join, ","], [:to_s]].each do |meth, *args|
+        if noun.respond_to?(meth)
+          break noun = noun.send(meth, *args)
+        end
+      end
+      msg << " #{pre} #{noun}" unless noun.empty?
+    end
+    msg
+  end
+end
+
+# Returns whether or not +macro+ is defined either in the common header
+# files or within any +headers+ you provide.
+#
+# Any options you pass to +opt+ are passed along to the compiler.
+#
+def have_macro(macro, headers = nil, opt = "", &b)
+  checking_for checking_message(macro, headers, opt) do
+    macro_defined?(macro, cpp_include(headers), opt, &b)
+  end
+end
+
+# Returns whether or not the given entry point +func+ can be found within
+# +lib+.  If +func+ is nil, the 'main()' entry point is used by default.
+# If found, it adds the library to list of libraries to be used when linking
+# your extension.
+#
+# If +headers+ are provided, it will include those header files as the
+# header files it looks in when searching for +func+.
+#
+# Real name of the library to be linked can be altered by
+# '--with-FOOlib' configuration option.
+#
+def have_library(lib, func = nil, headers = nil, &b)
+  func = "main" if !func or func.empty?
+  lib = with_config(lib+'lib', lib)
+  checking_for checking_message("#{func}()", LIBARG%lib) do
+    if COMMON_LIBS.include?(lib)
+      true
+    else
+      libs = append_library($libs, lib)
+      if try_func(func, libs, headers, &b)
+        $libs = libs
+        true
+      else
+        false
+      end
+    end
+  end
+end
+
+# Returns whether or not the entry point +func+ can be found within the library
+# +lib+ in one of the +paths+ specified, where +paths+ is an array of strings.
+# If +func+ is nil , then the main() function is used as the entry point.
+#
+# If +lib+ is found, then the path it was found on is added to the list of
+# library paths searched and linked against.
+#
+def find_library(lib, func, *paths, &b)
+  func = "main" if !func or func.empty?
+  lib = with_config(lib+'lib', lib)
+  paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten
+  checking_for "#{func}() in #{LIBARG%lib}" do
+    libpath = $LIBPATH
+    libs = append_library($libs, lib)
+    begin
+      until r = try_func(func, libs, &b) or paths.empty?
+	$LIBPATH = libpath | [paths.shift]
+      end
+      if r
+	$libs = libs
+	libpath = nil
+      end
+    ensure
+      $LIBPATH = libpath if libpath
+    end
+    r
+  end
+end
+
+# Returns whether or not the function +func+ can be found in the common
+# header files, or within any +headers+ that you provide.  If found, a
+# macro is passed as a preprocessor constant to the compiler using the
+# function name, in uppercase, prepended with 'HAVE_'.
+#
+# For example, if have_func('foo') returned true, then the HAVE_FOO
+# preprocessor macro would be passed to the compiler.
+#
+def have_func(func, headers = nil, &b)
+  checking_for checking_message("#{func}()", headers) do
+    if try_func(func, $libs, headers, &b)
+      $defs.push(format("-DHAVE_%s", func.upcase))
+      true
+    else
+      false
+    end
+  end
+end
+
+# Returns whether or not the variable +var+ can be found in the common
+# header files, or within any +headers+ that you provide.  If found, a
+# macro is passed as a preprocessor constant to the compiler using the
+# variable name, in uppercase, prepended with 'HAVE_'.
+#
+# For example, if have_var('foo') returned true, then the HAVE_FOO
+# preprocessor macro would be passed to the compiler.
+#
+def have_var(var, headers = nil, &b)
+  checking_for checking_message(var, headers) do
+    if try_var(var, headers, &b)
+      $defs.push(format("-DHAVE_%s", var.upcase))
+      true
+    else
+      false
+    end
+  end
+end
+
+# Returns whether or not the given +header+ file can be found on your system.
+# If found, a macro is passed as a preprocessor constant to the compiler using
+# the header file name, in uppercase, prepended with 'HAVE_'.
+#
+# For example, if have_header('foo.h') returned true, then the HAVE_FOO_H
+# preprocessor macro would be passed to the compiler.
+#
+def have_header(header, &b)
+  checking_for header do
+    if try_cpp(cpp_include(header), &b)
+      $defs.push(format("-DHAVE_%s", header.tr("a-z./\055", "A-Z___")))
+      true
+    else
+      false
+    end
+  end
+end
+
+# Instructs mkmf to search for the given +header+ in any of the +paths+
+# provided, and returns whether or not it was found in those paths.
+#
+# If the header is found then the path it was found on is added to the list
+# of included directories that are sent to the compiler (via the -I switch).
+#
+def find_header(header, *paths)
+  header = cpp_include(header)
+  checking_for header do
+    if try_cpp(header)
+      true
+    else
+      found = false
+      paths.each do |dir|
+        opt = "-I#{dir}".quote
+        if try_cpp(header, opt)
+          $INCFLAGS << " " << opt
+          found = true
+          break
+        end
+      end
+      found
+    end
+  end
+end
+
+# Returns whether or not the struct of type +type+ contains +member+.  If
+# it does not, or the struct type can't be found, then false is returned.  You
+# may optionally specify additional +headers+ in which to look for the struct
+# (in addition to the common header files).
+#
+# If found, a macro is passed as a preprocessor constant to the compiler using
+# the member name, in uppercase, prepended with 'HAVE_ST_'.
+#
+# For example, if have_struct_member('foo', 'bar') returned true, then the
+# HAVE_ST_BAR preprocessor macro would be passed to the compiler.
+# 
+def have_struct_member(type, member, headers = nil, &b)
+  checking_for checking_message("#{type}.#{member}", headers) do
+    if try_compile(<<"SRC", &b)
+#{COMMON_HEADERS}
+#{cpp_include(headers)}
+/*top*/
+int main() { return 0; }
+int s = (char *)&((#{type}*)0)->#{member} - (char *)0;
+SRC
+      $defs.push(format("-DHAVE_ST_%s", member.upcase))
+      true
+    else
+      false
+    end
+  end
+end
+
+# Returns whether or not the static type +type+ is defined.  You may
+# optionally pass additional +headers+ to check against in addition to the
+# common header files.
+#
+# You may also pass additional flags to +opt+ which are then passed along to
+# the compiler.
+#
+# If found, a macro is passed as a preprocessor constant to the compiler using
+# the type name, in uppercase, prepended with 'HAVE_TYPE_'.
+#
+# For example, if have_type('foo') returned true, then the HAVE_TYPE_FOO
+# preprocessor macro would be passed to the compiler.
+#
+def have_type(type, headers = nil, opt = "", &b)
+  checking_for checking_message(type, headers, opt) do
+    headers = cpp_include(headers)
+    if try_compile(<<"SRC", opt, &b)
+#{COMMON_HEADERS}
+#{headers}
+/*top*/
+typedef #{type} conftest_type;
+static conftest_type conftestval[sizeof(conftest_type)?1:-1];
+SRC
+      $defs.push(format("-DHAVE_TYPE_%s", type.strip.upcase.tr_s("^A-Z0-9_", "_")))
+      true
+    else
+      false
+    end
+  end
+end
+
+# Returns the size of the given +type+.  You may optionally specify additional
+# +headers+ to search in for the +type+.
+#
+# If found, a macro is passed as a preprocessor constant to the compiler using
+# the type name, in uppercase, prepended with 'SIZEOF_', followed by the type
+# name, followed by '=X' where 'X' is the actual size.
+#
+# For example, if check_sizeof('mystruct') returned 12, then the
+# SIZEOF_MYSTRUCT=12 preprocessor macro would be passed to the compiler.
+#
+def check_sizeof(type, headers = nil, &b)
+  expr = "sizeof(#{type})"
+  fmt = "%d"
+  def fmt.%(x)
+    x ? super : "failed"
+  end
+  checking_for checking_message("size of #{type}", headers), fmt do
+    if size = try_constant(expr, headers, &b)
+      $defs.push(format("-DSIZEOF_%s=%d", type.upcase.tr_s("^A-Z0-9_", "_"), size))
+      size
+    end
+  end
+end
+
+def scalar_ptr_type?(type, member = nil, headers = nil, &b)
+  try_compile(<<"SRC", &b)   # pointer
+#{COMMON_HEADERS}
+#{cpp_include(headers)}
+/*top*/
+volatile #{type} conftestval;
+int main() { return 0; }
+int t() {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));}
+SRC
+end
+
+def scalar_type?(type, member = nil, headers = nil, &b)
+  try_compile(<<"SRC", &b)   # pointer
+#{COMMON_HEADERS}
+#{cpp_include(headers)}
+/*top*/
+volatile #{type} conftestval;
+int main() { return 0; }
+int t() {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));}
+SRC
+end
+
+def what_type?(type, member = nil, headers = nil, &b)
+  m = "#{type}"
+  name = type
+  if member
+    m << "." << member
+    name = "(((#{type} *)0)->#{member})"
+  end
+  fmt = "seems %s"
+  def fmt.%(x)
+    x ? super : "unknown"
+  end
+  checking_for checking_message(m, headers), fmt do
+    if scalar_ptr_type?(type, member, headers, &b)
+      if try_static_assert("sizeof(*#{name}) == 1", headers)
+        "string"
+      end
+    elsif scalar_type?(type, member, headers, &b)
+      if try_static_assert("sizeof(#{name}) > sizeof(long)", headers)
+        "long long"
+      elsif try_static_assert("sizeof(#{name}) > sizeof(int)", headers)
+        "long"
+      elsif try_static_assert("sizeof(#{name}) > sizeof(short)", headers)
+        "int"
+      elsif try_static_assert("sizeof(#{name}) > 1", headers)
+        "short"
+      else
+        "char"
+      end
+    end
+  end
+end
+
+def find_executable0(bin, path = nil)
+  ext = config_string('EXEEXT')
+  if File.expand_path(bin) == bin
+    return bin if File.executable?(bin)
+    ext and File.executable?(file = bin + ext) and return file
+    return nil
+  end
+  if path ||= ENV['PATH']
+    path = path.split(File::PATH_SEPARATOR)
+  else
+    path = %w[/usr/local/bin /usr/ucb /usr/bin /bin]
+  end
+  file = nil
+  path.each do |dir|
+    return file if File.executable?(file = File.join(dir, bin))
+    return file if ext and File.executable?(file << ext)
+  end
+  nil
+end
+
+def find_executable(bin, path = nil)
+  checking_for checking_message(bin, path) do
+    find_executable0(bin, path)
+  end
+end
+
+def arg_config(config, *defaults, &block)
+  $arg_config << [config, *defaults]
+  defaults << nil if !block and defaults.empty?
+  $configure_args.fetch(config.tr('_', '-'), *defaults, &block)
+end
+
+def with_config(config, *defaults)
+  config = config.sub(/^--with[-_]/, '')
+  val = arg_config("--with-"+config) do
+    if arg_config("--without-"+config)
+      false
+    elsif block_given?
+      yield(config, *defaults)
+    else
+      break *defaults
+    end
+  end
+  case val
+  when "yes"
+    true
+  when "no"
+    false
+  else
+    val
+  end
+end
+
+def enable_config(config, *defaults)
+  if arg_config("--enable-"+config)
+    true
+  elsif arg_config("--disable-"+config)
+    false
+  elsif block_given?
+    yield(config, *defaults)
+  else
+    return *defaults
+  end
+end
+
+def create_header(header = "extconf.h")
+  message "creating %s\n", header
+  sym = header.tr("a-z./\055", "A-Z___")
+  hdr = ["#ifndef #{sym}\n#define #{sym}\n"]
+  for line in $defs
+    case line
+    when /^-D([^=]+)(?:=(.*))?/
+      hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0] : 1}\n"
+    when /^-U(.*)/
+      hdr << "#undef #$1\n"
+    end
+  end
+  hdr << "#endif\n"
+  hdr = hdr.join
+  unless (IO.read(header) == hdr rescue false)
+    open(header, "w") do |hfile|
+      hfile.write(hdr)
+    end
+  end
+  $extconf_h = header
+end
+
+# Sets a +target+ name that the user can then use to configure various 'with'
+# options with on the command line by using that name.  For example, if the
+# target is set to "foo", then the user could use the --with-foo-dir command
+# line option.
+#
+# You may pass along additional 'include' or 'lib' defaults via the +idefault+
+# and +ldefault+ parameters, respectively.
+#
+# Note that dir_config only adds to the list of places to search for libraries
+# and include files.  It does not link the libraries into your application.
+#
+def dir_config(target, idefault=nil, ldefault=nil)
+  if dir = with_config(target + "-dir", (idefault unless ldefault))
+    defaults = Array === dir ? dir : dir.split(File::PATH_SEPARATOR)
+    idefault = ldefault = nil
+  end
+
+  idir = with_config(target + "-include", idefault)
+  $arg_config.last[1] ||= "${#{target}-dir}/include"
+  ldir = with_config(target + "-lib", ldefault)
+  $arg_config.last[1] ||= "${#{target}-dir}/lib"
+
+  idirs = idir ? Array === idir ? idir : idir.split(File::PATH_SEPARATOR) : []
+  if defaults
+    idirs.concat(defaults.collect {|dir| dir + "/include"})
+    idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR)
+  end
+  unless idirs.empty?
+    idirs.collect! {|dir| "-I" + dir}
+    idirs -= Shellwords.shellwords($CPPFLAGS)
+    unless idirs.empty?
+      $CPPFLAGS = (idirs.quote << $CPPFLAGS).join(" ")
+    end
+  end
+
+  ldirs = ldir ? Array === ldir ? ldir : ldir.split(File::PATH_SEPARATOR) : []
+  if defaults
+    ldirs.concat(defaults.collect {|dir| dir + "/lib"})
+    ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR)
+  end
+  $LIBPATH = ldirs | $LIBPATH
+
+  [idir, ldir]
+end
+
+def pkg_config(pkg)
+  if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig)
+    # iff package specific config command is given
+    get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
+  elsif ($PKGCONFIG ||= 
+         (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) &&
+         find_executable0(pkgconfig) && pkgconfig) and
+      system("#{$PKGCONFIG} --exists #{pkg}")
+    # default to pkg-config command
+    get = proc {|opt| `#{$PKGCONFIG} --#{opt} #{pkg}`.chomp}
+  elsif find_executable0(pkgconfig = "#{pkg}-config")
+    # default to package specific config command, as a last resort.
+    get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
+  end
+  if get
+    cflags = get['cflags']
+    ldflags = get['libs']
+    libs = get['libs-only-l']
+    ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ")
+    $CFLAGS += " " << cflags
+    $LDFLAGS += " " << ldflags
+    $libs += " " << libs
+    Logging::message "package configuration for %s\n", pkg
+    Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n",
+                     cflags, ldflags, libs
+    [cflags, ldflags, libs]
+  else
+    Logging::message "package configuration for %s is not found\n", pkg
+    nil
+  end
+end
+
+def with_destdir(dir)
+  dir = dir.sub($dest_prefix_pattern, '')
+  /\A\$[\(\{]/ =~ dir ? dir : "$(DESTDIR)"+dir
+end
+
+def winsep(s)
+  s.tr('/', '\\')
+end
+
+def configuration(srcdir)
+  mk = []
+  vpath = %w[$(srcdir) $(topdir) $(hdrdir)]
+  if !CROSS_COMPILING
+    case CONFIG['build_os']
+    when 'cygwin'
+      if CONFIG['target_os'] != 'cygwin'
+        vpath.each {|p| p.sub!(/.*/, '$(shell cygpath -u \&)')}
+      end
+    when 'msdosdjgpp', 'mingw32'
+      CONFIG['PATH_SEPARATOR'] = ';'
+    end
+  end
+  mk << %{
+SHELL = /bin/sh
+
+#### Start of system configuration section. ####
+
+srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {CONFIG[$1||$2]}.quote}
+topdir = #{($extmk ? CONFIG["topdir"] : $topdir).quote}
+hdrdir = #{$extmk ? CONFIG["hdrdir"].quote : '$(topdir)'}
+VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}
+}
+  if destdir = CONFIG["prefix"][$dest_prefix_pattern, 1]
+    mk << "\nDESTDIR = #{destdir}\n"
+  end
+  CONFIG.each do |key, var|
+    next unless /prefix$/ =~ key
+    mk << "#{key} = #{with_destdir(var)}\n"
+  end
+  CONFIG.each do |key, var|
+    next if /^abs_/ =~ key
+    next unless /^(?:src|top|hdr|(.*))dir$/ =~ key and $1
+    mk << "#{key} = #{with_destdir(var)}\n"
+  end
+  if !$extmk and !$configure_args.has_key?('--ruby') and
+      sep = config_string('BUILD_FILE_SEPARATOR')
+    sep = ":/=#{sep}"
+  else
+    sep = ""
+  end
+  extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ")<<" "
+  mk << %{
+CC = #{CONFIG['CC']}
+LIBRUBY = #{CONFIG['LIBRUBY']}
+LIBRUBY_A = #{CONFIG['LIBRUBY_A']}
+LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED
+LIBRUBYARG_STATIC = #$LIBRUBYARG_STATIC
+
+RUBY_EXTCONF_H = #{$extconf_h}
+CFLAGS   = #{$static ? '' : CONFIG['CCDLFLAGS']} #$CFLAGS #$ARCH_FLAG
+INCFLAGS = -I. #$INCFLAGS
+CPPFLAGS = #{extconf_h}#{$CPPFLAGS}
+CXXFLAGS = $(CFLAGS) #{CONFIG['CXXFLAGS']}
+DLDFLAGS = #$LDFLAGS #$DLDFLAGS #$ARCH_FLAG
+LDSHARED = #{CONFIG['LDSHARED']}
+AR = #{CONFIG['AR']}
+EXEEXT = #{CONFIG['EXEEXT']}
+
+RUBY_INSTALL_NAME = #{CONFIG['RUBY_INSTALL_NAME']}
+RUBY_SO_NAME = #{CONFIG['RUBY_SO_NAME']}
+arch = #{CONFIG['arch']}
+sitearch = #{CONFIG['sitearch']}
+ruby_version = #{Config::CONFIG['ruby_version']}
+ruby = #{$ruby}
+RUBY = $(ruby#{sep})
+RM = #{config_string('RM') || '$(RUBY) -run -e rm -- -f'}
+MAKEDIRS = #{config_string('MAKEDIRS') || '@$(RUBY) -run -e mkdir -- -p'}
+INSTALL = #{config_string('INSTALL') || '@$(RUBY) -run -e install -- -vp'}
+INSTALL_PROG = #{config_string('INSTALL_PROG') || '$(INSTALL) -m 0755'}
+INSTALL_DATA = #{config_string('INSTALL_DATA') || '$(INSTALL) -m 0644'}
+COPY = #{config_string('CP') || '@$(RUBY) -run -e cp -- -v'}
+
+#### End of system configuration section. ####
+
+preload = #{$preload ? $preload.join(' ') : ''}
+}
+  if $nmake == ?b
+    mk.each do |x|
+      x.gsub!(/^(MAKEDIRS|INSTALL_(?:PROG|DATA))+\s*=.*\n/) do
+        "!ifndef " + $1 + "\n" +
+        $& +
+	"!endif\n"
+      end
+    end
+  end
+  mk
+end
+
+def dummy_makefile(srcdir)
+  configuration(srcdir) << <<RULES << CLEANINGS
+CLEANFILES = #{$cleanfiles.join(' ')}
+DISTCLEANFILES = #{$distcleanfiles.join(' ')}
+
+all install static install-so install-rb: Makefile
+
+RULES
+end
+
+# Generates the Makefile for your extension, passing along any options and
+# preprocessor constants that you may have generated through other methods.
+#
+# The +target+ name should correspond the name of the global function name
+# defined within your C extension, minus the 'Init_'.  For example, if your
+# C extension is defined as 'Init_foo', then your target would simply be 'foo'.
+#
+# If any '/' characters are present in the target name, only the last name
+# is interpreted as the target name, and the rest are considered toplevel
+# directory names, and the generated Makefile will be altered accordingly to
+# follow that directory structure.
+#
+# For example, if you pass 'test/foo' as a target name, your extension will
+# be installed under the 'test' directory.  This means that in order to
+# load the file within a Ruby program later, that directory structure will
+# have to be followed, e.g. "require 'test/foo'".
+#
+def create_makefile(target, srcprefix = nil)
+  $target = target
+  libpath = $DEFLIBPATH|$LIBPATH
+  message "creating Makefile\n"
+  rm_f "conftest*"
+  if CONFIG["DLEXT"] == $OBJEXT
+    for lib in libs = $libs.split
+      lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
+    end
+    $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
+  end
+
+  if target.include?('/')
+    target_prefix, target = File.split(target)
+    target_prefix[0,0] = '/'
+  else
+    target_prefix = ""
+  end
+
+  srcprefix ||= '$(srcdir)'
+  Config::expand(srcdir = srcprefix.dup)
+
+  if not $objs
+    $objs = []
+    srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
+    for f in srcs
+      obj = File.basename(f, ".*") << ".o"
+      $objs.push(obj) unless $objs.index(obj)
+    end
+  elsif !(srcs = $srcs)
+    srcs = $objs.collect {|obj| obj.sub(/\.o\z/, '.c')}
+  end
+  $srcs = srcs
+  for i in $objs
+    i.sub!(/\.o\z/, ".#{$OBJEXT}")
+  end
+  $objs = $objs.join(" ")
+
+  target = nil if $objs == ""
+
+  if target and EXPORT_PREFIX
+    if File.exist?(File.join(srcdir, target + '.def'))
+      deffile = "$(srcdir)/$(TARGET).def"
+      unless EXPORT_PREFIX.empty?
+        makedef = %{-pe "sub!(/^(?=\\w)/,'#{EXPORT_PREFIX}') unless 1../^EXPORTS$/i"}
+      end
+    else
+      makedef = %{-e "puts 'EXPORTS', '#{EXPORT_PREFIX}Init_$(TARGET)'"}
+    end
+    if makedef
+      $distcleanfiles << '$(DEFFILE)'
+      origdef = deffile
+      deffile = "$(TARGET)-$(arch).def"
+    end
+  end
+  origdef ||= ''
+
+  libpath = libpathflag(libpath)
+
+  dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : ""
+  staticlib = target ? "$(TARGET).#$LIBEXT" : ""
+  mfile = open("Makefile", "wb")
+  mfile.print configuration(srcprefix)
+  mfile.print "
+libpath = #{($DEFLIBPATH|$LIBPATH).join(" ")}
+LIBPATH = #{libpath}
+DEFFILE = #{deffile}
+
+CLEANFILES = #{$cleanfiles.join(' ')}
+DISTCLEANFILES = #{$distcleanfiles.join(' ')}
+
+extout = #{$extout}
+extout_prefix = #{$extout_prefix}
+target_prefix = #{target_prefix}
+LOCAL_LIBS = #{$LOCAL_LIBS}
+LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
+SRCS = #{srcs.collect(&File.method(:basename)).join(' ')}
+OBJS = #{$objs}
+TARGET = #{target}
+DLLIB = #{dllib}
+EXTSTATIC = #{$static || ""}
+STATIC_LIB = #{staticlib unless $static.nil?}
+#{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""}
+"
+  install_dirs.each {|d| mfile.print("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
+  n = ($extout ? '$(RUBYARCHDIR)/' : '') + '$(TARGET).'
+  mfile.print "
+TARGET_SO     = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB)
+CLEANLIBS     = #{n}#{CONFIG['DLEXT']} #{n}il? #{n}tds #{n}map
+CLEANOBJS     = *.#{$OBJEXT} *.#{$LIBEXT} *.s[ol] *.pdb *.exp *.bak
+
+all:		#{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
+static:		$(STATIC_LIB)#{$extout ? " install-rb" : ""}
+"
+  mfile.print CLEANINGS
+  dirs = []
+  mfile.print "install: install-so install-rb\n\n"
+  sodir = (dir = "$(RUBYARCHDIR)").dup
+  mfile.print("install-so: #{dir}\n")
+  if target
+    f = "$(DLLIB)"
+    dest = "#{dir}/#{f}"
+    mfile.print "install-so: #{dest}\n"
+    unless $extout
+      mfile.print "#{dest}: #{f}\n"
+      if (sep = config_string('BUILD_FILE_SEPARATOR'))
+        f.gsub!("/", sep)
+        dir.gsub!("/", sep)
+        sep = ":/="+sep
+        f.gsub!(/(\$\(\w+)(\))/) {$1+sep+$2}
+        f.gsub!(/(\$\{\w+)(\})/) {$1+sep+$2}
+        dir.gsub!(/(\$\(\w+)(\))/) {$1+sep+$2}
+        dir.gsub!(/(\$\{\w+)(\})/) {$1+sep+$2}
+      end
+      mfile.print "\t$(INSTALL_PROG) #{f} #{dir}\n"
+      if defined?($installed_list)
+	mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n"
+      end
+    end
+  end
+  mfile.print("install-rb: pre-install-rb install-rb-default\n")
+  mfile.print("install-rb-default: pre-install-rb-default\n")
+  mfile.print("pre-install-rb: Makefile\n")
+  mfile.print("pre-install-rb-default: Makefile\n")
+  for sfx, i in [["-default", [["lib/**/*.rb", "$(RUBYLIBDIR)", "lib"]]], ["", $INSTALLFILES]]
+    files = install_files(mfile, i, nil, srcprefix) or next
+    for dir, *files in files
+      unless dirs.include?(dir)
+	dirs << dir
+	mfile.print "pre-install-rb#{sfx}: #{dir}\n"
+      end
+      files.each do |f|
+	dest = "#{dir}/#{File.basename(f)}"
+	mfile.print("install-rb#{sfx}: #{dest}\n")
+	mfile.print("#{dest}: #{f}\n\t$(#{$extout ? 'COPY' : 'INSTALL_DATA'}) ")
+	sep = config_string('BUILD_FILE_SEPARATOR')
+	if sep
+	  f = f.gsub("/", sep)
+	  sep = ":/="+sep
+	  f = f.gsub(/(\$\(\w+)(\))/) {$1+sep+$2}
+	  f = f.gsub(/(\$\{\w+)(\})/) {$1+sep+$2}
+	else
+	  sep = ""
+	end
+	mfile.print("#{f} $(@D#{sep})\n")
+	if defined?($installed_list) and !$extout
+	  mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n")
+	end
+      end
+    end
+  end
+  dirs.unshift(sodir) if target and !dirs.include?(sodir)
+  dirs.each {|dir| mfile.print "#{dir}:\n\t$(MAKEDIRS) $@\n"}
+
+  mfile.print <<-SITEINSTALL
+
+site-install: site-install-so site-install-rb
+site-install-so: install-so
+site-install-rb: install-rb
+
+  SITEINSTALL
+
+  return unless target
+
+  mfile.puts SRC_EXT.collect {|ext| ".path.#{ext} = $(VPATH)"} if $nmake == ?b
+  mfile.print ".SUFFIXES: .#{SRC_EXT.join(' .')} .#{$OBJEXT}\n"
+  mfile.print "\n"
+
+  CXX_EXT.each do |ext|
+    COMPILE_RULES.each do |rule|
+      mfile.printf(rule, ext, $OBJEXT)
+      mfile.printf("\n\t%s\n\n", COMPILE_CXX)
+    end
+  end
+  %w[c].each do |ext|
+    COMPILE_RULES.each do |rule|
+      mfile.printf(rule, ext, $OBJEXT)
+      mfile.printf("\n\t%s\n\n", COMPILE_C)
+    end
+  end
+
+  mfile.print "$(RUBYARCHDIR)/" if $extout
+  mfile.print "$(DLLIB): ", (makedef ? "$(DEFFILE) " : ""), "$(OBJS)\n"
+  mfile.print "\t@-$(RM) $@\n"
+  mfile.print "\t@-$(MAKEDIRS) $(@D)\n" if $extout
+  link_so = LINK_SO.gsub(/^/, "\t")
+  mfile.print link_so, "\n\n"
+  unless $static.nil?
+    mfile.print "$(STATIC_LIB): $(OBJS)\n\t"
+    mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)"
+    config_string('RANLIB') do |ranlib|
+      mfile.print "\n\t@-#{ranlib} $(DLLIB) 2> /dev/null || true"
+    end
+  end
+  mfile.print "\n\n"
+  if makedef
+    mfile.print "$(DEFFILE): #{origdef}\n"
+    mfile.print "\t$(RUBY) #{makedef} #{origdef} > $@\n\n"
+  end
+
+  depend = File.join(srcdir, "depend")
+  if File.exist?(depend)
+    suffixes = []
+    depout = []
+    open(depend, "r") do |dfile|
+      mfile.printf "###\n"
+      cont = implicit = nil
+      impconv = proc do
+	COMPILE_RULES.each {|rule| depout << (rule % implicit[0]) << implicit[1]}
+	implicit = nil
+      end
+      ruleconv = proc do |line|
+	if implicit
+	  if /\A\t/ =~ line
+	    implicit[1] << line
+	    next
+	  else
+	    impconv[]
+	  end
+	end
+	if m = /\A\.(\w+)\.(\w+)(?:\s*:)/.match(line)
+	  suffixes << m[1] << m[2]
+	  implicit = [[m[1], m[2]], [m.post_match]]
+	  next
+	elsif RULE_SUBST and /\A(?!\s*\w+\s*=)[$\w][^#]*:/ =~ line
+	  line.gsub!(%r"(\s)(?!\.)([^$(){}+=:\s\/\\,]+)(?=\s|\z)") {$1 + RULE_SUBST % $2}
+	end
+	depout << line
+      end
+      while line = dfile.gets()
+	line.gsub!(/\.o\b/, ".#{$OBJEXT}")
+	line.gsub!(/\$\(hdrdir\)\/config.h/, $config_h) if $config_h
+	if /(?:^|[^\\])(?:\\\\)*\\$/ =~ line
+	  (cont ||= []) << line
+	  next
+	elsif cont
+	  line = (cont << line).join
+	  cont = nil
+	end
+	ruleconv.call(line)
+      end
+      if cont
+	ruleconv.call(cont.join)
+      elsif implicit
+	impconv.call
+      end
+    end
+    unless suffixes.empty?
+      mfile.print ".SUFFIXES: .", suffixes.uniq.join(" ."), "\n\n"
+    end
+    mfile.print depout
+  else
+    headers = %w[ruby.h defines.h]
+    if RULE_SUBST
+      headers.each {|h| h.sub!(/.*/) {|*m| RULE_SUBST % m}}
+    end
+    headers << $config_h if $config_h
+    headers << "$(RUBY_EXTCONF_H)" if $extconf_h
+    mfile.print "$(OBJS): ", headers.join(' '), "\n"
+  end
+
+  $makefile_created = true
+ensure
+  mfile.close if mfile
+end
+
+def init_mkmf(config = CONFIG)
+  $makefile_created = false
+  $arg_config = []
+  $enable_shared = config['ENABLE_SHARED'] == 'yes'
+  $defs = []
+  $extconf_h = nil
+  $CFLAGS = with_config("cflags", arg_config("CFLAGS", config["CFLAGS"])).dup
+  $ARCH_FLAG = with_config("arch_flag", arg_config("ARCH_FLAG", config["ARCH_FLAG"])).dup
+  $CPPFLAGS = with_config("cppflags", arg_config("CPPFLAGS", config["CPPFLAGS"])).dup
+  $LDFLAGS = with_config("ldflags", arg_config("LDFLAGS", config["LDFLAGS"])).dup
+  $INCFLAGS = "-I$(topdir) -I$(hdrdir) -I$(srcdir)"
+  $DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup
+  $LIBEXT = config['LIBEXT'].dup
+  $OBJEXT = config["OBJEXT"].dup
+  $LIBS = "#{config['LIBS']} #{config['DLDLIBS']}"
+  $LIBRUBYARG = ""
+  $LIBRUBYARG_STATIC = config['LIBRUBYARG_STATIC']
+  $LIBRUBYARG_SHARED = config['LIBRUBYARG_SHARED']
+  $DEFLIBPATH = $extmk ? ["$(topdir)"] : CROSS_COMPILING ? [] : ["$(libdir)"]
+  $LIBPATH = []
+  $INSTALLFILES = nil
+
+  $objs = nil
+  $srcs = nil
+  $libs = ""
+  if $enable_shared or Config.expand(config["LIBRUBY"].dup) != Config.expand(config["LIBRUBY_A"].dup)
+    $LIBRUBYARG = config['LIBRUBYARG']
+  end
+
+  $LOCAL_LIBS = ""
+
+  $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || []
+  $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || []
+
+  $extout ||= nil
+  $extout_prefix ||= nil
+
+  $arg_config.clear
+  dir_config("opt")
+end
+
+FailedMessage = <<MESSAGE
+Could not create Makefile due to some reason, probably lack of
+necessary libraries and/or headers.  Check the mkmf.log file for more
+details.  You may need configuration options.
+
+Provided configuration options:
+MESSAGE
+
+def mkmf_failed(path)
+  unless $makefile_created or File.exist?("Makefile")
+    opts = $arg_config.collect {|t, n| "\t#{t}#{n ? "=#{n}" : ""}\n"}
+    abort "*** #{path} failed ***\n" + FailedMessage + opts.join
+  end
+end
+
+init_mkmf
+
+$make = with_config("make-prog", ENV["MAKE"] || "make")
+make, = Shellwords.shellwords($make)
+$nmake = nil
+case
+when $mswin
+  $nmake = ?m if /nmake/i =~ make
+when $bccwin
+  $nmake = ?b if /Borland/i =~ `#{make} -h`
+end
+
+Config::CONFIG["srcdir"] = CONFIG["srcdir"] =
+  $srcdir = arg_config("--srcdir", File.dirname($0))
+$configure_args["--topsrcdir"] ||= $srcdir
+if $curdir = arg_config("--curdir")
+  Config.expand(curdir = $curdir.dup)
+else
+  curdir = $curdir = "."
+end
+unless File.expand_path(Config::CONFIG["topdir"]) == File.expand_path(curdir)
+  CONFIG["topdir"] = $curdir
+  Config::CONFIG["topdir"] = curdir
+end
+$configure_args["--topdir"] ||= $curdir
+$ruby = arg_config("--ruby", File.join(Config::CONFIG["bindir"], CONFIG["ruby_install_name"]))
+
+split = Shellwords.method(:shellwords).to_proc
+
+EXPORT_PREFIX = config_string('EXPORT_PREFIX') {|s| s.strip}
+
+hdr = []
+config_string('COMMON_MACROS') do |s|
+  Shellwords.shellwords(s).each do |w|
+    hdr << "#define " + w.split(/=/, 2).join(" ")
+  end
+end
+config_string('COMMON_HEADERS') do |s|
+  Shellwords.shellwords(s).each {|s| hdr << "#include <#{s}>"}
+end
+COMMON_HEADERS = hdr.join("\n")
+COMMON_LIBS = config_string('COMMON_LIBS', &split) || []
+
+COMPILE_RULES = config_string('COMPILE_RULES', &split) || %w[.%s.%s:]
+RULE_SUBST = config_string('RULE_SUBST')
+COMPILE_C = config_string('COMPILE_C') || '$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<'
+COMPILE_CXX = config_string('COMPILE_CXX') || '$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<'
+TRY_LINK = config_string('TRY_LINK') ||
+  "$(CC) #{OUTFLAG}conftest $(INCFLAGS) $(CPPFLAGS) " \
+  "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
+LINK_SO = config_string('LINK_SO') ||
+  if CONFIG["DLEXT"] == $OBJEXT
+    "ld $(DLDFLAGS) -r -o $@ $(OBJS)\n"
+  else
+    "$(LDSHARED) $(DLDFLAGS) $(LIBPATH) #{OUTFLAG}$@ " \
+    "$(OBJS) $(LOCAL_LIBS) $(LIBS)"
+  end
+LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L"%s"'
+RPATHFLAG = config_string('RPATHFLAG') || ''
+LIBARG = config_string('LIBARG') || '-l%s'
+
+sep = config_string('BUILD_FILE_SEPARATOR') {|sep| ":/=#{sep}" if sep != "/"} || ""
+CLEANINGS = "
+clean:
+		@-$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep})
+
+distclean:	clean
+		@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
+		@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep})
+
+realclean:	distclean
+"
+
+if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0)
+  END {mkmf_failed($0)}
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/monitor.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/monitor.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/monitor.rb	(revision 18425)
@@ -0,0 +1,347 @@
+=begin
+
+= monitor.rb
+
+Copyright (C) 2001  Shugo Maeda <shugo@ruby-lang.org>
+
+This library is distributed under the terms of the Ruby license.
+You can freely distribute/modify this library.
+
+== example
+
+This is a simple example.
+
+  require 'monitor.rb'
+  
+  buf = []
+  buf.extend(MonitorMixin)
+  empty_cond = buf.new_cond
+  
+  # consumer
+  Thread.start do
+    loop do
+      buf.synchronize do
+        empty_cond.wait_while { buf.empty? }
+        print buf.shift
+      end
+    end
+  end
+  
+  # producer
+  while line = ARGF.gets
+    buf.synchronize do
+      buf.push(line)
+      empty_cond.signal
+    end
+  end
+
+The consumer thread waits for the producer thread to push a line
+to buf while buf.empty?, and the producer thread (main thread)
+reads a line from ARGF and push it to buf, then call
+empty_cond.signal.
+
+=end
+  
+
+#
+# Adds monitor functionality to an arbitrary object by mixing the module with
+# +include+.  For example:
+#
+#    require 'monitor.rb'
+#    
+#    buf = []
+#    buf.extend(MonitorMixin)
+#    empty_cond = buf.new_cond
+#    
+#    # consumer
+#    Thread.start do
+#      loop do
+#        buf.synchronize do
+#          empty_cond.wait_while { buf.empty? }
+#          print buf.shift
+#        end
+#      end
+#    end
+#    
+#    # producer
+#    while line = ARGF.gets
+#      buf.synchronize do
+#        buf.push(line)
+#        empty_cond.signal
+#      end
+#    end
+# 
+# The consumer thread waits for the producer thread to push a line
+# to buf while buf.empty?, and the producer thread (main thread)
+# reads a line from ARGF and push it to buf, then call
+# empty_cond.signal.
+#
+module MonitorMixin
+  #
+  # FIXME: This isn't documented in Nutshell.
+  #
+  # Since MonitorMixin.new_cond returns a ConditionVariable, and the example
+  # above calls while_wait and signal, this class should be documented.
+  #
+  class ConditionVariable
+    class Timeout < Exception; end
+    
+    # Create a new timer with the argument timeout, and add the
+    # current thread to the list of waiters.  Then the thread is
+    # stopped.  It will be resumed when a corresponding #signal 
+    # occurs.
+    def wait(timeout = nil)
+      @monitor.instance_eval {mon_check_owner()}
+      timer = create_timer(timeout)
+      
+      Thread.critical = true
+      count = @monitor.instance_eval {mon_exit_for_cond()}
+      @waiters.push(Thread.current)
+
+      begin
+	Thread.stop
+        return true
+      rescue Timeout
+        return false
+      ensure
+	Thread.critical = true
+	if timer && timer.alive?
+	  Thread.kill(timer)
+	end
+	if @waiters.include?(Thread.current)  # interrupted?
+	  @waiters.delete(Thread.current)
+	end
+        @monitor.instance_eval {mon_enter_for_cond(count)}
+	Thread.critical = false
+      end
+    end
+    
+
+    # call #wait while the supplied block returns +true+.
+    def wait_while
+      while yield
+	wait
+      end
+    end
+    
+    # call #wait until the supplied block returns +true+.
+    def wait_until
+      until yield
+	wait
+      end
+    end
+    
+    # Wake up and run the next waiter
+    def signal
+      @monitor.instance_eval {mon_check_owner()}
+      Thread.critical = true
+      t = @waiters.shift
+      t.wakeup if t
+      Thread.critical = false
+      Thread.pass
+    end
+    
+    # Wake up all the waiters.
+    def broadcast
+      @monitor.instance_eval {mon_check_owner()}
+      Thread.critical = true
+      for t in @waiters
+	t.wakeup
+      end
+      @waiters.clear
+      Thread.critical = false
+      Thread.pass
+    end
+    
+    def count_waiters
+      return @waiters.length
+    end
+    
+    private
+
+    def initialize(monitor)
+      @monitor = monitor
+      @waiters = []
+    end
+
+    def create_timer(timeout)
+      if timeout
+	waiter = Thread.current
+	return Thread.start {
+	  Thread.pass
+	  sleep(timeout)
+	  Thread.critical = true
+	  waiter.raise(Timeout.new)
+	}
+      else
+        return nil
+      end
+    end
+  end
+  
+  def self.extend_object(obj)
+    super(obj)
+    obj.instance_eval {mon_initialize()}
+  end
+  
+  #
+  # Attempts to enter exclusive section.  Returns +false+ if lock fails.
+  #
+  def mon_try_enter
+    result = false
+    Thread.critical = true
+    if @mon_owner.nil?
+      @mon_owner = Thread.current
+    end
+    if @mon_owner == Thread.current
+      @mon_count += 1
+      result = true
+    end
+    Thread.critical = false
+    return result
+  end
+  # For backward compatibility
+  alias try_mon_enter mon_try_enter
+
+  #
+  # Enters exclusive section.
+  #
+  def mon_enter
+    Thread.critical = true
+    mon_acquire(@mon_entering_queue)
+    @mon_count += 1
+    Thread.critical = false
+  end
+  
+  #
+  # Leaves exclusive section.
+  #
+  def mon_exit
+    mon_check_owner
+    Thread.critical = true
+    @mon_count -= 1
+    if @mon_count == 0
+      mon_release
+    end
+    Thread.critical = false
+    Thread.pass
+  end
+
+  #
+  # Enters exclusive section and executes the block.  Leaves the exclusive
+  # section automatically when the block exits.  See example under
+  # +MonitorMixin+.
+  #
+  def mon_synchronize
+    mon_enter
+    begin
+      yield
+    ensure
+      mon_exit
+    end
+  end
+  alias synchronize mon_synchronize
+  
+  #
+  # FIXME: This isn't documented in Nutshell.
+  # 
+  # Create a new condition variable for this monitor.
+  # This facilitates control of the monitor with #signal and #wait.
+  #
+  def new_cond
+    return ConditionVariable.new(self)
+  end
+
+  private
+
+  def initialize(*args)
+    super
+    mon_initialize
+  end
+
+  # called by initialize method to set defaults for instance variables.
+  def mon_initialize
+    @mon_owner = nil
+    @mon_count = 0
+    @mon_entering_queue = []
+    @mon_waiting_queue = []
+  end
+
+  # Throw a ThreadError exception if the current thread
+  # does't own the monitor
+  def mon_check_owner
+    if @mon_owner != Thread.current
+      raise ThreadError, "current thread not owner"
+    end
+  end
+
+  def mon_acquire(queue)
+    while @mon_owner && @mon_owner != Thread.current
+      queue.push(Thread.current)
+      Thread.stop
+      Thread.critical = true
+    end
+    @mon_owner = Thread.current
+  end
+
+  def mon_release
+    @mon_owner = nil
+    t = @mon_waiting_queue.shift
+    t = @mon_entering_queue.shift unless t
+    t.wakeup if t
+  end
+
+  def mon_enter_for_cond(count)
+    mon_acquire(@mon_waiting_queue)
+    @mon_count = count
+  end
+
+  def mon_exit_for_cond
+    count = @mon_count
+    @mon_count = 0
+    mon_release
+    return count
+  end
+end
+
+# Monitors provide means of mutual exclusion for Thread programming.
+# A critical region is created by means of the synchronize method,
+# which takes a block.
+# The condition variables (created with #new_cond) may be used 
+# to control the execution of a monitor with #signal and #wait.
+#
+# the Monitor class wraps MonitorMixin, and provides aliases
+#  alias try_enter try_mon_enter
+#  alias enter mon_enter
+#  alias exit mon_exit
+# to access its methods more concisely.
+class Monitor
+  include MonitorMixin
+  alias try_enter try_mon_enter
+  alias enter mon_enter
+  alias exit mon_exit
+end
+
+
+# Documentation comments:
+#  - All documentation comes from Nutshell.
+#  - MonitorMixin.new_cond appears in the example, but is not documented in
+#    Nutshell.
+#  - All the internals (internal modules Accessible and Initializable, class
+#    ConditionVariable) appear in RDoc.  It might be good to hide them, by
+#    making them private, or marking them :nodoc:, etc.
+#  - The entire example from the RD section at the top is replicated in the RDoc
+#    comment for MonitorMixin.  Does the RD section need to remain?
+#  - RDoc doesn't recognise aliases, so we have mon_synchronize documented, but
+#    not synchronize.
+#  - mon_owner is in Nutshell, but appears as an accessor in a separate module
+#    here, so is hard/impossible to RDoc.  Some other useful accessors
+#    (mon_count and some queue stuff) are also in this module, and don't appear
+#    directly in the RDoc output.
+#  - in short, it may be worth changing the code layout in this file to make the
+#    documentation easier
+
+# Local variables:
+# mode: Ruby
+# tab-width: 8
+# End:
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/mutex_m.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/mutex_m.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/mutex_m.rb	(revision 18425)
@@ -0,0 +1,122 @@
+#--
+#   mutex_m.rb - 
+#   	$Release Version: 3.0$
+#   	$Revision: 1.7 $
+#   	$Date: 1998/02/27 04:28:57 $
+#       Original from mutex.rb
+#   	by Keiju ISHITSUKA(keiju@ishitsuka.com)
+#       modified by matz
+#       patched by akira yamada
+#++
+#
+# == Usage
+#
+# Extend an object and use it like a Mutex object:
+#
+#   require "mutex_m.rb"
+#   obj = Object.new
+#   obj.extend Mutex_m
+#   # ...
+#
+# Or, include Mutex_m in a class to have its instances behave like a Mutex
+# object:
+#
+#   class Foo
+#     include Mutex_m
+#     # ...
+#   end
+#   
+#   obj = Foo.new
+
+module Mutex_m
+  def Mutex_m.define_aliases(cl)
+    cl.module_eval %q{
+      alias locked? mu_locked?
+      alias lock mu_lock
+      alias unlock mu_unlock
+      alias try_lock mu_try_lock
+      alias synchronize mu_synchronize
+    }
+  end  
+
+  def Mutex_m.append_features(cl)
+    super
+    define_aliases(cl) unless cl.instance_of?(Module)
+  end
+  
+  def Mutex_m.extend_object(obj)
+    super
+    obj.mu_extended
+  end
+
+  def mu_extended
+    unless (defined? locked? and
+	    defined? lock and
+	    defined? unlock and
+	    defined? try_lock and
+	    defined? synchronize)
+      Mutex_m.define_aliases(class<<self;self;end)
+    end
+    mu_initialize
+  end
+  
+  # locking 
+  def mu_synchronize
+    begin
+      mu_lock
+      yield
+    ensure
+      mu_unlock
+    end
+  end
+  
+  def mu_locked?
+    @mu_locked
+  end
+  
+  def mu_try_lock
+    result = false
+    Thread.critical = true
+    unless @mu_locked
+      @mu_locked = true
+      result = true
+    end
+    Thread.critical = false
+    result
+  end
+  
+  def mu_lock
+    while (Thread.critical = true; @mu_locked)
+      @mu_waiting.push Thread.current
+      Thread.stop
+    end
+    @mu_locked = true
+    Thread.critical = false
+    self
+  end
+  
+  def mu_unlock
+    return unless @mu_locked
+    Thread.critical = true
+    wait = @mu_waiting
+    @mu_waiting = []
+    @mu_locked = false
+    Thread.critical = false
+    for w in wait
+      w.run
+    end
+    self
+  end
+  
+  private
+  
+  def mu_initialize
+    @mu_waiting = []
+    @mu_locked = false;
+  end
+
+  def initialize(*args)
+    mu_initialize
+    super
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/ftp.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/ftp.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/ftp.rb	(revision 18425)
@@ -0,0 +1,923 @@
+# 
+# = net/ftp.rb - FTP Client Library
+# 
+# Written by Shugo Maeda <shugo@ruby-lang.org>.
+#
+# Documentation by Gavin Sinclair, sourced from "Programming Ruby" (Hunt/Thomas)
+# and "Ruby In a Nutshell" (Matsumoto), used with permission.
+# 
+# This library is distributed under the terms of the Ruby license.
+# You can freely distribute/modify this library.
+#
+# It is included in the Ruby standard library.
+#
+# See the Net::FTP class for an overview.
+#
+
+require "socket"
+require "monitor"
+
+module Net
+
+  # :stopdoc:
+  class FTPError < StandardError; end
+  class FTPReplyError < FTPError; end
+  class FTPTempError < FTPError; end 
+  class FTPPermError < FTPError; end 
+  class FTPProtoError < FTPError; end
+  # :startdoc:
+
+  #
+  # This class implements the File Transfer Protocol.  If you have used a
+  # command-line FTP program, and are familiar with the commands, you will be
+  # able to use this class easily.  Some extra features are included to take
+  # advantage of Ruby's style and strengths.
+  #
+  # == Example
+  # 
+  #   require 'net/ftp'
+  #
+  # === Example 1
+  #  
+  #   ftp = Net::FTP.new('ftp.netlab.co.jp')
+  #   ftp.login
+  #   files = ftp.chdir('pub/lang/ruby/contrib')
+  #   files = ftp.list('n*')
+  #   ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024)
+  #   ftp.close
+  #
+  # === Example 2
+  #
+  #   Net::FTP.open('ftp.netlab.co.jp') do |ftp|
+  #     ftp.login
+  #     files = ftp.chdir('pub/lang/ruby/contrib')
+  #     files = ftp.list('n*')
+  #     ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024)
+  #   end
+  #
+  # == Major Methods
+  #
+  # The following are the methods most likely to be useful to users:
+  # - FTP.open
+  # - #getbinaryfile
+  # - #gettextfile
+  # - #putbinaryfile
+  # - #puttextfile
+  # - #chdir
+  # - #nlst
+  # - #size
+  # - #rename
+  # - #delete
+  #
+  class FTP
+    include MonitorMixin
+    
+    # :stopdoc:
+    FTP_PORT = 21
+    CRLF = "\r\n"
+    DEFAULT_BLOCKSIZE = 4096
+    # :startdoc:
+    
+    # When +true+, transfers are performed in binary mode.  Default: +true+.
+    attr_accessor :binary
+
+    # When +true+, the connection is in passive mode.  Default: +false+.
+    attr_accessor :passive
+
+    # When +true+, all traffic to and from the server is written
+    # to +$stdout+.  Default: +false+.
+    attr_accessor :debug_mode
+
+    # Sets or retrieves the +resume+ status, which decides whether incomplete
+    # transfers are resumed or restarted.  Default: +false+.
+    attr_accessor :resume
+
+    # The server's welcome message.
+    attr_reader :welcome
+
+    # The server's last response code.
+    attr_reader :last_response_code
+    alias lastresp last_response_code
+
+    # The server's last response.
+    attr_reader :last_response
+    
+    #
+    # A synonym for <tt>FTP.new</tt>, but with a mandatory host parameter.
+    #
+    # If a block is given, it is passed the +FTP+ object, which will be closed
+    # when the block finishes, or when an exception is raised.
+    #
+    def FTP.open(host, user = nil, passwd = nil, acct = nil)
+      if block_given?
+        ftp = new(host, user, passwd, acct)
+        begin
+          yield ftp
+        ensure
+          ftp.close
+        end
+      else
+        new(host, user, passwd, acct)
+      end
+    end
+    
+    #
+    # Creates and returns a new +FTP+ object. If a +host+ is given, a connection
+    # is made. Additionally, if the +user+ is given, the given user name,
+    # password, and (optionally) account are used to log in.  See #login.
+    #
+    def initialize(host = nil, user = nil, passwd = nil, acct = nil)
+      super()
+      @binary = true
+      @passive = false
+      @debug_mode = false
+      @resume = false
+      if host
+	connect(host)
+	if user
+	  login(user, passwd, acct)
+	end
+      end
+    end
+
+    # Obsolete
+    def return_code
+      $stderr.puts("warning: Net::FTP#return_code is obsolete and do nothing")
+      return "\n"
+    end
+
+    # Obsolete
+    def return_code=(s)
+      $stderr.puts("warning: Net::FTP#return_code= is obsolete and do nothing")
+    end
+
+    def open_socket(host, port)
+      if defined? SOCKSsocket and ENV["SOCKS_SERVER"]
+	@passive = true
+	return SOCKSsocket.open(host, port)
+      else
+	return TCPSocket.open(host, port)
+      end
+    end
+    private :open_socket
+    
+    #
+    # Establishes an FTP connection to host, optionally overriding the default
+    # port. If the environment variable +SOCKS_SERVER+ is set, sets up the
+    # connection through a SOCKS proxy. Raises an exception (typically
+    # <tt>Errno::ECONNREFUSED</tt>) if the connection cannot be established.
+    #
+    def connect(host, port = FTP_PORT)
+      if @debug_mode
+	print "connect: ", host, ", ", port, "\n"
+      end
+      synchronize do
+	@sock = open_socket(host, port)
+	voidresp
+      end
+    end
+
+    #
+    # WRITEME or make private
+    #
+    def set_socket(sock, get_greeting = true)
+      synchronize do
+	@sock = sock
+	if get_greeting
+	  voidresp
+	end
+      end
+    end
+
+    def sanitize(s)
+      if s =~ /^PASS /i
+	return s[0, 5] + "*" * (s.length - 5)
+      else
+	return s
+      end
+    end
+    private :sanitize
+    
+    def putline(line)
+      if @debug_mode
+	print "put: ", sanitize(line), "\n"
+      end
+      line = line + CRLF
+      @sock.write(line)
+    end
+    private :putline
+    
+    def getline
+      line = @sock.readline # if get EOF, raise EOFError
+      line.sub!(/(\r\n|\n|\r)\z/n, "")
+      if @debug_mode
+	print "get: ", sanitize(line), "\n"
+      end
+      return line
+    end
+    private :getline
+    
+    def getmultiline
+      line = getline
+      buff = line
+      if line[3] == ?-
+	  code = line[0, 3]
+	begin
+	  line = getline
+	  buff << "\n" << line
+	end until line[0, 3] == code and line[3] != ?-
+      end
+      return buff << "\n"
+    end
+    private :getmultiline
+    
+    def getresp
+      @last_response = getmultiline
+      @last_response_code = @last_response[0, 3]
+      case @last_response_code
+      when /\A[123]/
+	return @last_response
+      when /\A4/
+	raise FTPTempError, @last_response
+      when /\A5/
+	raise FTPPermError, @last_response
+      else
+	raise FTPProtoError, @last_response
+      end
+    end
+    private :getresp
+    
+    def voidresp
+      resp = getresp
+      if resp[0] != ?2
+	raise FTPReplyError, resp
+      end
+    end
+    private :voidresp
+    
+    #
+    # Sends a command and returns the response.
+    #
+    def sendcmd(cmd)
+      synchronize do
+	putline(cmd)
+	return getresp
+      end
+    end
+    
+    #
+    # Sends a command and expect a response beginning with '2'.
+    #
+    def voidcmd(cmd)
+      synchronize do
+	putline(cmd)
+	voidresp
+      end
+    end
+    
+    def sendport(host, port)
+      af = (@sock.peeraddr)[0]
+      if af == "AF_INET"
+	hbytes = host.split(".")
+	pbytes = [port / 256, port % 256]
+	bytes = hbytes + pbytes
+	cmd = "PORT " + bytes.join(",")
+      elsif af == "AF_INET6"
+	cmd = "EPRT |2|" + host + "|" + sprintf("%d", port) + "|"
+      else
+	raise FTPProtoError, host
+      end
+      voidcmd(cmd)
+    end
+    private :sendport
+    
+    def makeport
+      sock = TCPServer.open(@sock.addr[3], 0)
+      port = sock.addr[1]
+      host = sock.addr[3]
+      resp = sendport(host, port)
+      return sock
+    end
+    private :makeport
+    
+    def makepasv
+      if @sock.peeraddr[0] == "AF_INET"
+	host, port = parse227(sendcmd("PASV"))
+      else
+	host, port = parse229(sendcmd("EPSV"))
+	#     host, port = parse228(sendcmd("LPSV"))
+      end
+      return host, port
+    end
+    private :makepasv
+    
+    def transfercmd(cmd, rest_offset = nil)
+      if @passive
+	host, port = makepasv
+	conn = open_socket(host, port)
+	if @resume and rest_offset
+	  resp = sendcmd("REST " + rest_offset.to_s) 
+	  if resp[0] != ?3
+	    raise FTPReplyError, resp
+	  end
+	end
+	resp = sendcmd(cmd)
+	if resp[0] != ?1
+	  raise FTPReplyError, resp
+	end
+      else
+	sock = makeport
+	if @resume and rest_offset
+	  resp = sendcmd("REST " + rest_offset.to_s) 
+	  if resp[0] != ?3
+	    raise FTPReplyError, resp
+	  end
+	end
+	resp = sendcmd(cmd)
+	if resp[0] != ?1
+	  raise FTPReplyError, resp
+	end
+	conn = sock.accept
+	sock.close
+      end
+      return conn
+    end
+    private :transfercmd
+    
+    def getaddress
+      thishost = Socket.gethostname
+      if not thishost.index(".")
+	thishost = Socket.gethostbyname(thishost)[0]
+      end
+      if ENV.has_key?("LOGNAME")
+	realuser = ENV["LOGNAME"]
+      elsif ENV.has_key?("USER")
+	realuser = ENV["USER"]
+      else
+	realuser = "anonymous"
+      end
+      return realuser + "@" + thishost
+    end
+    private :getaddress
+    
+    #
+    # Logs in to the remote host. The session must have been previously
+    # connected.  If +user+ is the string "anonymous" and the +password+ is
+    # +nil+, a password of <tt>user@host</tt> is synthesized. If the +acct+
+    # parameter is not +nil+, an FTP ACCT command is sent following the
+    # successful login.  Raises an exception on error (typically
+    # <tt>Net::FTPPermError</tt>).
+    #
+    def login(user = "anonymous", passwd = nil, acct = nil)
+      if user == "anonymous" and passwd == nil
+	passwd = getaddress
+      end
+      
+      resp = ""
+      synchronize do
+	resp = sendcmd('USER ' + user)
+	if resp[0] == ?3
+	  resp = sendcmd('PASS ' + passwd)
+	end
+	if resp[0] == ?3
+	  resp = sendcmd('ACCT ' + acct)
+	end
+      end
+      if resp[0] != ?2
+	raise FTPReplyError, resp
+      end
+      @welcome = resp
+    end
+    
+    #
+    # Puts the connection into binary (image) mode, issues the given command,
+    # and fetches the data returned, passing it to the associated block in
+    # chunks of +blocksize+ characters. Note that +cmd+ is a server command
+    # (such as "RETR myfile").
+    #
+    def retrbinary(cmd, blocksize, rest_offset = nil) # :yield: data
+      synchronize do
+	voidcmd("TYPE I")
+	conn = transfercmd(cmd, rest_offset)
+	loop do
+	  data = conn.read(blocksize)
+	  break if data == nil
+	  yield(data)
+	end
+	conn.close
+	voidresp
+      end
+    end
+    
+    #
+    # Puts the connection into ASCII (text) mode, issues the given command, and
+    # passes the resulting data, one line at a time, to the associated block. If
+    # no block is given, prints the lines. Note that +cmd+ is a server command
+    # (such as "RETR myfile").
+    #
+    def retrlines(cmd) # :yield: line
+      synchronize do
+	voidcmd("TYPE A")
+	conn = transfercmd(cmd)
+	loop do
+	  line = conn.gets
+	  break if line == nil
+	  if line[-2, 2] == CRLF
+	    line = line[0 .. -3]
+	  elsif line[-1] == ?\n
+	    line = line[0 .. -2]
+	  end
+	  yield(line)
+	end
+	conn.close
+	voidresp
+      end
+    end
+    
+    #
+    # Puts the connection into binary (image) mode, issues the given server-side
+    # command (such as "STOR myfile"), and sends the contents of the file named
+    # +file+ to the server. If the optional block is given, it also passes it
+    # the data, in chunks of +blocksize+ characters.
+    #
+    def storbinary(cmd, file, blocksize, rest_offset = nil, &block) # :yield: data
+      if rest_offset
+        file.seek(rest_offset, IO::SEEK_SET)
+      end
+      synchronize do
+	voidcmd("TYPE I")
+	conn = transfercmd(cmd, rest_offset)
+	loop do
+	  buf = file.read(blocksize)
+	  break if buf == nil
+	  conn.write(buf)
+	  yield(buf) if block
+	end
+	conn.close
+	voidresp
+      end
+    end
+    
+    #
+    # Puts the connection into ASCII (text) mode, issues the given server-side
+    # command (such as "STOR myfile"), and sends the contents of the file
+    # named +file+ to the server, one line at a time. If the optional block is
+    # given, it also passes it the lines.
+    #
+    def storlines(cmd, file, &block) # :yield: line
+      synchronize do
+	voidcmd("TYPE A")
+	conn = transfercmd(cmd)
+	loop do
+	  buf = file.gets
+	  break if buf == nil
+	  if buf[-2, 2] != CRLF
+	    buf = buf.chomp + CRLF
+	  end
+	  conn.write(buf)
+	  yield(buf) if block
+	end
+	conn.close
+	voidresp
+      end
+    end
+
+    #
+    # Retrieves +remotefile+ in binary mode, storing the result in +localfile+.
+    # If a block is supplied, it is passed the retrieved data in +blocksize+
+    # chunks.
+    #
+    def getbinaryfile(remotefile, localfile = File.basename(remotefile),
+		      blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
+      if @resume
+	rest_offset = File.size?(localfile)
+	f = open(localfile, "a")
+      else
+	rest_offset = nil
+	f = open(localfile, "w")
+      end
+      begin
+	f.binmode
+	retrbinary("RETR " + remotefile, blocksize, rest_offset) do |data|
+	  f.write(data)
+	  yield(data) if block
+	end
+      ensure
+	f.close
+      end
+    end
+    
+    #
+    # Retrieves +remotefile+ in ASCII (text) mode, storing the result in
+    # +localfile+. If a block is supplied, it is passed the retrieved data one
+    # line at a time.
+    #
+    def gettextfile(remotefile, localfile = File.basename(remotefile), &block) # :yield: line
+      f = open(localfile, "w")
+      begin
+	retrlines("RETR " + remotefile) do |line|
+	  f.puts(line)
+	  yield(line) if block
+	end
+      ensure
+	f.close
+      end
+    end
+
+    #
+    # Retrieves +remotefile+ in whatever mode the session is set (text or
+    # binary).  See #gettextfile and #getbinaryfile.
+    #
+    def get(remotefile, localfile = File.basename(remotefile),
+	    blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
+      unless @binary
+	gettextfile(remotefile, localfile, &block)
+      else
+	getbinaryfile(remotefile, localfile, blocksize, &block)
+      end
+    end
+    
+    #
+    # Transfers +localfile+ to the server in binary mode, storing the result in
+    # +remotefile+. If a block is supplied, calls it, passing in the transmitted
+    # data in +blocksize+ chunks.
+    #
+    def putbinaryfile(localfile, remotefile = File.basename(localfile),
+		      blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
+      if @resume
+        begin
+          rest_offset = size(remotefile)
+        rescue Net::FTPPermError
+          rest_offset = nil
+        end
+      else
+	rest_offset = nil
+      end
+      f = open(localfile)
+      begin
+	f.binmode
+	storbinary("STOR " + remotefile, f, blocksize, rest_offset, &block)
+      ensure
+	f.close
+      end
+    end
+    
+    #
+    # Transfers +localfile+ to the server in ASCII (text) mode, storing the result
+    # in +remotefile+. If callback or an associated block is supplied, calls it,
+    # passing in the transmitted data one line at a time.
+    #
+    def puttextfile(localfile, remotefile = File.basename(localfile), &block) # :yield: line
+      f = open(localfile)
+      begin
+	storlines("STOR " + remotefile, f, &block)
+      ensure
+	f.close
+      end
+    end
+
+    #
+    # Transfers +localfile+ to the server in whatever mode the session is set
+    # (text or binary).  See #puttextfile and #putbinaryfile.
+    #
+    def put(localfile, remotefile = File.basename(localfile),
+	    blocksize = DEFAULT_BLOCKSIZE, &block)
+      unless @binary
+	puttextfile(localfile, remotefile, &block)
+      else
+	putbinaryfile(localfile, remotefile, blocksize, &block)
+      end
+    end
+
+    #
+    # Sends the ACCT command.  TODO: more info.
+    #
+    def acct(account)
+      cmd = "ACCT " + account
+      voidcmd(cmd)
+    end
+    
+    #
+    # Returns an array of filenames in the remote directory.
+    #
+    def nlst(dir = nil)
+      cmd = "NLST"
+      if dir
+	cmd = cmd + " " + dir
+      end
+      files = []
+      retrlines(cmd) do |line|
+	files.push(line)
+      end
+      return files
+    end
+    
+    #
+    # Returns an array of file information in the directory (the output is like
+    # `ls -l`).  If a block is given, it iterates through the listing.
+    #
+    def list(*args, &block) # :yield: line
+      cmd = "LIST"
+      args.each do |arg|
+	cmd = cmd + " " + arg
+      end
+      if block
+	retrlines(cmd, &block)
+      else
+	lines = []
+	retrlines(cmd) do |line|
+	  lines << line
+	end
+	return lines
+      end
+    end
+    alias ls list
+    alias dir list
+    
+    #
+    # Renames a file on the server.
+    #
+    def rename(fromname, toname)
+      resp = sendcmd("RNFR " + fromname)
+      if resp[0] != ?3
+	raise FTPReplyError, resp
+      end
+      voidcmd("RNTO " + toname)
+    end
+    
+    #
+    # Deletes a file on the server.
+    #
+    def delete(filename)
+      resp = sendcmd("DELE " + filename)
+      if resp[0, 3] == "250"
+	return
+      elsif resp[0] == ?5
+	raise FTPPermError, resp
+      else
+	raise FTPReplyError, resp
+      end
+    end
+    
+    #
+    # Changes the (remote) directory.
+    #
+    def chdir(dirname)
+      if dirname == ".."
+	begin
+	  voidcmd("CDUP")
+	  return
+	rescue FTPPermError
+	  if $![0, 3] != "500"
+	    raise FTPPermError, $!
+	  end
+	end
+      end
+      cmd = "CWD " + dirname
+      voidcmd(cmd)
+    end
+    
+    #
+    # Returns the size of the given (remote) filename.
+    #
+    def size(filename)
+      voidcmd("TYPE I")
+      resp = sendcmd("SIZE " + filename)
+      if resp[0, 3] != "213" 
+	raise FTPReplyError, resp
+      end
+      return resp[3..-1].strip.to_i
+    end
+    
+    MDTM_REGEXP = /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/  # :nodoc:
+    
+    #
+    # Returns the last modification time of the (remote) file.  If +local+ is
+    # +true+, it is returned as a local time, otherwise it's a UTC time.
+    #
+    def mtime(filename, local = false)
+      str = mdtm(filename)
+      ary = str.scan(MDTM_REGEXP)[0].collect {|i| i.to_i}
+      return local ? Time.local(*ary) : Time.gm(*ary)
+    end
+    
+    #
+    # Creates a remote directory.
+    #
+    def mkdir(dirname)
+      resp = sendcmd("MKD " + dirname)
+      return parse257(resp)
+    end
+    
+    #
+    # Removes a remote directory.
+    #
+    def rmdir(dirname)
+      voidcmd("RMD " + dirname)
+    end
+    
+    #
+    # Returns the current remote directory.
+    #
+    def pwd
+      resp = sendcmd("PWD")
+      return parse257(resp)
+    end
+    alias getdir pwd
+    
+    #
+    # Returns system information.
+    #
+    def system
+      resp = sendcmd("SYST")
+      if resp[0, 3] != "215"
+	raise FTPReplyError, resp
+      end
+      return resp[4 .. -1]
+    end
+    
+    #
+    # Aborts the previous command (ABOR command).
+    #
+    def abort
+      line = "ABOR" + CRLF
+      print "put: ABOR\n" if @debug_mode
+      @sock.send(line, Socket::MSG_OOB)
+      resp = getmultiline
+      unless ["426", "226", "225"].include?(resp[0, 3])
+	raise FTPProtoError, resp
+      end
+      return resp
+    end
+    
+    #
+    # Returns the status (STAT command).
+    #
+    def status
+      line = "STAT" + CRLF
+      print "put: STAT\n" if @debug_mode
+      @sock.send(line, Socket::MSG_OOB)
+      return getresp
+    end
+    
+    #
+    # Issues the MDTM command.  TODO: more info.
+    #
+    def mdtm(filename)
+      resp = sendcmd("MDTM " + filename)
+      if resp[0, 3] == "213"
+	return resp[3 .. -1].strip
+      end
+    end
+    
+    #
+    # Issues the HELP command.
+    #
+    def help(arg = nil)
+      cmd = "HELP"
+      if arg
+	cmd = cmd + " " + arg
+      end
+      sendcmd(cmd)
+    end
+    
+    #
+    # Exits the FTP session.
+    #
+    def quit
+      voidcmd("QUIT")
+    end
+
+    #
+    # Issues a NOOP command.
+    #
+    def noop
+      voidcmd("NOOP")
+    end
+
+    #
+    # Issues a SITE command.
+    #
+    def site(arg)
+      cmd = "SITE " + arg
+      voidcmd(cmd)
+    end
+    
+    #
+    # Closes the connection.  Further operations are impossible until you open
+    # a new connection with #connect.
+    #
+    def close
+      @sock.close if @sock and not @sock.closed?
+    end
+    
+    #
+    # Returns +true+ iff the connection is closed.
+    #
+    def closed?
+      @sock == nil or @sock.closed?
+    end
+    
+    def parse227(resp)
+      if resp[0, 3] != "227"
+	raise FTPReplyError, resp
+      end
+      left = resp.index("(")
+      right = resp.index(")")
+      if left == nil or right == nil
+	raise FTPProtoError, resp
+      end
+      numbers = resp[left + 1 .. right - 1].split(",")
+      if numbers.length != 6
+	raise FTPProtoError, resp
+      end
+      host = numbers[0, 4].join(".")
+      port = (numbers[4].to_i << 8) + numbers[5].to_i
+      return host, port
+    end
+    private :parse227
+    
+    def parse228(resp)
+      if resp[0, 3] != "228"
+	raise FTPReplyError, resp
+      end
+      left = resp.index("(")
+      right = resp.index(")")
+      if left == nil or right == nil
+	raise FTPProtoError, resp
+      end
+      numbers = resp[left + 1 .. right - 1].split(",")
+      if numbers[0] == "4"
+	if numbers.length != 9 || numbers[1] != "4" || numbers[2 + 4] != "2"
+	  raise FTPProtoError, resp
+	end
+	host = numbers[2, 4].join(".")
+	port = (numbers[7].to_i << 8) + numbers[8].to_i
+      elsif numbers[0] == "6"
+	if numbers.length != 21 || numbers[1] != "16" || numbers[2 + 16] != "2"
+	  raise FTPProtoError, resp
+	end
+	v6 = ["", "", "", "", "", "", "", ""]
+	for i in 0 .. 7
+	  v6[i] = sprintf("%02x%02x", numbers[(i * 2) + 2].to_i,
+			  numbers[(i * 2) + 3].to_i)
+	end
+	host = v6[0, 8].join(":")
+	port = (numbers[19].to_i << 8) + numbers[20].to_i
+      end 
+      return host, port
+    end
+    private :parse228
+    
+    def parse229(resp)
+      if resp[0, 3] != "229"
+	raise FTPReplyError, resp
+      end
+      left = resp.index("(")
+      right = resp.index(")")
+      if left == nil or right == nil
+	raise FTPProtoError, resp
+      end
+      numbers = resp[left + 1 .. right - 1].split(resp[left + 1, 1])
+      if numbers.length != 4
+	raise FTPProtoError, resp
+      end
+      port = numbers[3].to_i
+      host = (@sock.peeraddr())[3]
+      return host, port
+    end
+    private :parse229
+    
+    def parse257(resp)
+      if resp[0, 3] != "257"
+	raise FTPReplyError, resp
+      end
+      if resp[3, 2] != ' "'
+	return ""
+      end
+      dirname = ""
+      i = 5
+      n = resp.length
+      while i < n
+	c = resp[i, 1]
+	i = i + 1
+	if c == '"'
+	  if i > n or resp[i, 1] != '"'
+	    break
+	  end
+	  i = i + 1
+	end
+	dirname = dirname + c
+      end
+      return dirname
+    end
+    private :parse257
+  end
+
+end
+
+
+# Documentation comments:
+#  - sourced from pickaxe and nutshell, with improvements (hopefully)
+#  - three methods should be private (search WRITEME)
+#  - two methods need more information (search TODO)
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/ftptls.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/ftptls.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/ftptls.rb	(revision 18425)
@@ -0,0 +1,43 @@
+=begin
+= $RCSfile$ -- SSL/TLS enhancement for Net::HTTP.
+
+= Info
+  'OpenSSL for Ruby 2' project
+  Copyright (C) 2003 Blaz Grilc <farmer@gmx.co.uk>
+  All rights reserved.
+
+= Licence
+  This program is licenced under the same licence as Ruby.
+  (See the file 'LICENCE'.)
+
+= Requirements
+
+= Version
+  $Id: ftptls.rb 11708 2007-02-12 23:01:19Z shyouhei $
+  
+= Notes
+  Tested on FreeBSD 5-CURRENT and 4-STABLE
+  - ruby 1.6.8 (2003-01-17) [i386-freebsd5]
+  - OpenSSL 0.9.7a Feb 19 2003
+  - ruby-openssl-0.2.0.p0
+  tested on ftp server: glftpd 1.30
+=end
+
+require 'socket'
+require 'openssl'
+require 'net/ftp'
+
+module Net
+  class FTPTLS < FTP
+    def login(user = "anonymous", passwd = nil, acct = nil)
+       ctx = OpenSSL::SSL::SSLContext.new('SSLv23')
+       ctx.key = nil
+       ctx.cert = nil
+       voidcmd("AUTH TLS")
+       @sock = OpenSSL::SSL::SSLSocket.new(@sock, ctx)
+       @sock.connect
+       super(user, passwd, acct)
+       voidcmd("PBSZ 0")
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/http.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/http.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/http.rb	(revision 18425)
@@ -0,0 +1,2274 @@
+#
+# = net/http.rb
+#
+# Copyright (c) 1999-2006 Yukihiro Matsumoto
+# Copyright (c) 1999-2006 Minero Aoki
+# Copyright (c) 2001 GOTOU Yuuzou
+# 
+# Written and maintained by Minero Aoki <aamine@loveruby.net>.
+# HTTPS support added by GOTOU Yuuzou <gotoyuzo@notwork.org>.
+#
+# This file is derived from "http-access.rb".
+#
+# Documented by Minero Aoki; converted to RDoc by William Webber.
+# 
+# This program is free software. You can re-distribute and/or
+# modify this program under the same terms of ruby itself ---
+# Ruby Distribution License or GNU General Public License.
+#
+# See Net::HTTP for an overview and examples. 
+# 
+# NOTE: You can find Japanese version of this document here:
+# http://www.ruby-lang.org/ja/man/?cmd=view;name=net%2Fhttp.rb
+# 
+#--
+# $Id: http.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#++ 
+
+require 'net/protocol'
+require 'uri'
+
+module Net   #:nodoc:
+
+  # :stopdoc:
+  class HTTPBadResponse < StandardError; end
+  class HTTPHeaderSyntaxError < StandardError; end
+  # :startdoc:
+
+  # == What Is This Library?
+  # 
+  # This library provides your program functions to access WWW
+  # documents via HTTP, Hyper Text Transfer Protocol version 1.1.
+  # For details of HTTP, refer [RFC2616]
+  # (http://www.ietf.org/rfc/rfc2616.txt).
+  # 
+  # == Examples
+  # 
+  # === Getting Document From WWW Server
+  # 
+  # Example #1: Simple GET+print
+  # 
+  #     require 'net/http'
+  #     Net::HTTP.get_print 'www.example.com', '/index.html'
+  # 
+  # Example #2: Simple GET+print by URL
+  # 
+  #     require 'net/http'
+  #     require 'uri'
+  #     Net::HTTP.get_print URI.parse('http://www.example.com/index.html')
+  # 
+  # Example #3: More generic GET+print
+  # 
+  #     require 'net/http'
+  #     require 'uri'
+  #
+  #     url = URI.parse('http://www.example.com/index.html')
+  #     res = Net::HTTP.start(url.host, url.port) {|http|
+  #       http.get('/index.html')
+  #     }
+  #     puts res.body
+  #
+  # Example #4: More generic GET+print
+  # 
+  #     require 'net/http'
+  #
+  #     url = URI.parse('http://www.example.com/index.html')
+  #     req = Net::HTTP::Get.new(url.path)
+  #     res = Net::HTTP.start(url.host, url.port) {|http|
+  #       http.request(req)
+  #     }
+  #     puts res.body
+  # 
+  # === Posting Form Data
+  # 
+  #     require 'net/http'
+  #     require 'uri'
+  #
+  #     #1: Simple POST
+  #     res = Net::HTTP.post_form(URI.parse('http://www.example.com/search.cgi'),
+  #                               {'q'=>'ruby', 'max'=>'50'})
+  #     puts res.body
+  #
+  #     #2: POST with basic authentication
+  #     res = Net::HTTP.post_form(URI.parse('http://jack:pass@www.example.com/todo.cgi'),
+  #                                         {'from'=>'2005-01-01', 'to'=>'2005-03-31'})
+  #     puts res.body
+  #
+  #     #3: Detailed control
+  #     url = URI.parse('http://www.example.com/todo.cgi')
+  #     req = Net::HTTP::Post.new(url.path)
+  #     req.basic_auth 'jack', 'pass'
+  #     req.set_form_data({'from'=>'2005-01-01', 'to'=>'2005-03-31'}, ';')
+  #     res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
+  #     case res
+  #     when Net::HTTPSuccess, Net::HTTPRedirection
+  #       # OK
+  #     else
+  #       res.error!
+  #     end
+  # 
+  # === Accessing via Proxy
+  # 
+  # Net::HTTP.Proxy creates http proxy class. It has same
+  # methods of Net::HTTP but its instances always connect to
+  # proxy, instead of given host.
+  # 
+  #     require 'net/http'
+  # 
+  #     proxy_addr = 'your.proxy.host'
+  #     proxy_port = 8080
+  #             :
+  #     Net::HTTP::Proxy(proxy_addr, proxy_port).start('www.example.com') {|http|
+  #       # always connect to your.proxy.addr:8080
+  #             :
+  #     }
+  # 
+  # Since Net::HTTP.Proxy returns Net::HTTP itself when proxy_addr is nil,
+  # there's no need to change code if there's proxy or not.
+  # 
+  # There are two additional parameters in Net::HTTP.Proxy which allow to
+  # specify proxy user name and password:
+  # 
+  #     Net::HTTP::Proxy(proxy_addr, proxy_port, proxy_user = nil, proxy_pass = nil)
+  # 
+  # You may use them to work with authorization-enabled proxies:
+  # 
+  #     require 'net/http'
+  #     require 'uri'
+  #     
+  #     proxy_host = 'your.proxy.host'
+  #     proxy_port = 8080
+  #     uri = URI.parse(ENV['http_proxy'])
+  #     proxy_user, proxy_pass = uri.userinfo.split(/:/) if uri.userinfo
+  #     Net::HTTP::Proxy(proxy_host, proxy_port,
+  #                      proxy_user, proxy_pass).start('www.example.com') {|http|
+  #       # always connect to your.proxy.addr:8080 using specified username and password
+  #             :
+  #     }
+  #
+  # Note that net/http never rely on HTTP_PROXY environment variable.
+  # If you want to use proxy, set it explicitly.
+  # 
+  # === Following Redirection
+  # 
+  #     require 'net/http'
+  #     require 'uri'
+  # 
+  #     def fetch(uri_str, limit = 10)
+  #       # You should choose better exception. 
+  #       raise ArgumentError, 'HTTP redirect too deep' if limit == 0
+  # 
+  #       response = Net::HTTP.get_response(URI.parse(uri_str))
+  #       case response
+  #       when Net::HTTPSuccess     then response
+  #       when Net::HTTPRedirection then fetch(response['location'], limit - 1)
+  #       else
+  #         response.error!
+  #       end
+  #     end
+  # 
+  #     print fetch('http://www.ruby-lang.org')
+  # 
+  # Net::HTTPSuccess and Net::HTTPRedirection is a HTTPResponse class.
+  # All HTTPResponse objects belong to its own response class which
+  # indicate HTTP result status. For details of response classes,
+  # see section "HTTP Response Classes".
+  # 
+  # === Basic Authentication
+  # 
+  #     require 'net/http'
+  # 
+  #     Net::HTTP.start('www.example.com') {|http|
+  #       req = Net::HTTP::Get.new('/secret-page.html')
+  #       req.basic_auth 'account', 'password'
+  #       response = http.request(req)
+  #       print response.body
+  #     }
+  # 
+  # === HTTP Request Classes
+  #
+  # Here is HTTP request class hierarchy.
+  #
+  #   Net::HTTPRequest
+  #       Net::HTTP::Get
+  #       Net::HTTP::Head
+  #       Net::HTTP::Post
+  #       Net::HTTP::Put
+  #       Net::HTTP::Proppatch
+  #       Net::HTTP::Lock
+  #       Net::HTTP::Unlock
+  #       Net::HTTP::Options
+  #       Net::HTTP::Propfind
+  #       Net::HTTP::Delete
+  #       Net::HTTP::Move
+  #       Net::HTTP::Copy
+  #       Net::HTTP::Mkcol
+  #       Net::HTTP::Trace
+  #
+  # === HTTP Response Classes
+  #
+  # Here is HTTP response class hierarchy.
+  # All classes are defined in Net module.
+  #
+  #   HTTPResponse
+  #       HTTPUnknownResponse
+  #       HTTPInformation                    # 1xx
+  #           HTTPContinue                       # 100
+  #           HTTPSwitchProtocl                  # 101
+  #       HTTPSuccess                        # 2xx
+  #           HTTPOK                             # 200
+  #           HTTPCreated                        # 201
+  #           HTTPAccepted                       # 202
+  #           HTTPNonAuthoritativeInformation    # 203
+  #           HTTPNoContent                      # 204
+  #           HTTPResetContent                   # 205
+  #           HTTPPartialContent                 # 206
+  #       HTTPRedirection                    # 3xx
+  #           HTTPMultipleChoice                 # 300
+  #           HTTPMovedPermanently               # 301
+  #           HTTPFound                          # 302
+  #           HTTPSeeOther                       # 303
+  #           HTTPNotModified                    # 304
+  #           HTTPUseProxy                       # 305
+  #           HTTPTemporaryRedirect              # 307
+  #       HTTPClientError                    # 4xx
+  #           HTTPBadRequest                     # 400
+  #           HTTPUnauthorized                   # 401
+  #           HTTPPaymentRequired                # 402
+  #           HTTPForbidden                      # 403
+  #           HTTPNotFound                       # 404
+  #           HTTPMethodNotAllowed               # 405
+  #           HTTPNotAcceptable                  # 406
+  #           HTTPProxyAuthenticationRequired    # 407
+  #           HTTPRequestTimeOut                 # 408
+  #           HTTPConflict                       # 409
+  #           HTTPGone                           # 410
+  #           HTTPLengthRequired                 # 411
+  #           HTTPPreconditionFailed             # 412
+  #           HTTPRequestEntityTooLarge          # 413
+  #           HTTPRequestURITooLong              # 414
+  #           HTTPUnsupportedMediaType           # 415
+  #           HTTPRequestedRangeNotSatisfiable   # 416
+  #           HTTPExpectationFailed              # 417
+  #       HTTPServerError                    # 5xx
+  #           HTTPInternalServerError            # 500
+  #           HTTPNotImplemented                 # 501
+  #           HTTPBadGateway                     # 502
+  #           HTTPServiceUnavailable             # 503
+  #           HTTPGatewayTimeOut                 # 504
+  #           HTTPVersionNotSupported            # 505
+  # 
+  # == Switching Net::HTTP versions
+  # 
+  # You can use net/http.rb 1.1 features (bundled with Ruby 1.6)
+  # by calling HTTP.version_1_1. Calling Net::HTTP.version_1_2
+  # allows you to use 1.2 features again.
+  # 
+  #     # example
+  #     Net::HTTP.start {|http1| ...(http1 has 1.2 features)... }
+  # 
+  #     Net::HTTP.version_1_1
+  #     Net::HTTP.start {|http2| ...(http2 has 1.1 features)... }
+  # 
+  #     Net::HTTP.version_1_2
+  #     Net::HTTP.start {|http3| ...(http3 has 1.2 features)... }
+  # 
+  # This function is NOT thread-safe.
+  #
+  class HTTP < Protocol
+
+    # :stopdoc:
+    Revision = %q$Revision: 11708 $.split[1]
+    HTTPVersion = '1.1'
+    @newimpl = true
+    # :startdoc:
+
+    # Turns on net/http 1.2 (ruby 1.8) features.
+    # Defaults to ON in ruby 1.8.
+    #
+    # I strongly recommend to call this method always.
+    #
+    #   require 'net/http'
+    #   Net::HTTP.version_1_2
+    #
+    def HTTP.version_1_2
+      @newimpl = true
+    end
+
+    # Turns on net/http 1.1 (ruby 1.6) features.
+    # Defaults to OFF in ruby 1.8.
+    def HTTP.version_1_1
+      @newimpl = false
+    end
+
+    # true if net/http is in version 1.2 mode.
+    # Defaults to true.
+    def HTTP.version_1_2?
+      @newimpl
+    end
+
+    # true if net/http is in version 1.1 compatible mode.
+    # Defaults to true.
+    def HTTP.version_1_1?
+      not @newimpl
+    end
+
+    class << HTTP
+      alias is_version_1_1? version_1_1?   #:nodoc:
+      alias is_version_1_2? version_1_2?   #:nodoc:
+    end
+
+    #
+    # short cut methods
+    #
+
+    #
+    # Get body from target and output it to +$stdout+.  The
+    # target can either be specified as (+uri+), or as
+    # (+host+, +path+, +port+ = 80); so: 
+    #
+    #    Net::HTTP.get_print URI.parse('http://www.example.com/index.html')
+    #
+    # or:
+    #
+    #    Net::HTTP.get_print 'www.example.com', '/index.html'
+    #
+    def HTTP.get_print(uri_or_host, path = nil, port = nil)
+      get_response(uri_or_host, path, port) {|res|
+        res.read_body do |chunk|
+          $stdout.print chunk
+        end
+      }
+      nil
+    end
+
+    # Send a GET request to the target and return the response
+    # as a string.  The target can either be specified as
+    # (+uri+), or as (+host+, +path+, +port+ = 80); so:
+    # 
+    #    print Net::HTTP.get(URI.parse('http://www.example.com/index.html'))
+    #
+    # or:
+    #
+    #    print Net::HTTP.get('www.example.com', '/index.html')
+    #
+    def HTTP.get(uri_or_host, path = nil, port = nil)
+      get_response(uri_or_host, path, port).body
+    end
+
+    # Send a GET request to the target and return the response
+    # as a Net::HTTPResponse object.  The target can either be specified as
+    # (+uri+), or as (+host+, +path+, +port+ = 80); so:
+    # 
+    #    res = Net::HTTP.get_response(URI.parse('http://www.example.com/index.html'))
+    #    print res.body
+    #
+    # or:
+    #
+    #    res = Net::HTTP.get_response('www.example.com', '/index.html')
+    #    print res.body
+    #
+    def HTTP.get_response(uri_or_host, path = nil, port = nil, &block)
+      if path
+        host = uri_or_host
+        new(host, port || HTTP.default_port).start {|http|
+          return http.request_get(path, &block)
+        }
+      else
+        uri = uri_or_host
+        new(uri.host, uri.port).start {|http|
+          return http.request_get(uri.request_uri, &block)
+        }
+      end
+    end
+
+    # Posts HTML form data to the +URL+.
+    # Form data must be represented as a Hash of String to String, e.g:
+    #
+    #   { "cmd" => "search", "q" => "ruby", "max" => "50" }
+    #
+    # This method also does Basic Authentication iff +URL+.user exists.
+    #
+    # Example:
+    #
+    #   require 'net/http'
+    #   require 'uri'
+    #
+    #   HTTP.post_form URI.parse('http://www.example.com/search.cgi'),
+    #                  { "q" => "ruby", "max" => "50" }
+    #
+    def HTTP.post_form(url, params)
+      req = Post.new(url.path)
+      req.form_data = params
+      req.basic_auth url.user, url.password if url.user
+      new(url.host, url.port).start {|http|
+        http.request(req)
+      }
+    end
+
+    #
+    # HTTP session management
+    #
+
+    # The default port to use for HTTP requests; defaults to 80.
+    def HTTP.default_port
+      http_default_port()
+    end
+
+    # The default port to use for HTTP requests; defaults to 80.
+    def HTTP.http_default_port
+      80
+    end
+
+    # The default port to use for HTTPS requests; defaults to 443.
+    def HTTP.https_default_port
+      443
+    end
+
+    def HTTP.socket_type   #:nodoc: obsolete
+      BufferedIO
+    end
+
+    # creates a new Net::HTTP object and opens its TCP connection and 
+    # HTTP session.  If the optional block is given, the newly 
+    # created Net::HTTP object is passed to it and closed when the 
+    # block finishes.  In this case, the return value of this method
+    # is the return value of the block.  If no block is given, the
+    # return value of this method is the newly created Net::HTTP object
+    # itself, and the caller is responsible for closing it upon completion.
+    def HTTP.start(address, port = nil, p_addr = nil, p_port = nil, p_user = nil, p_pass = nil, &block) # :yield: +http+
+      new(address, port, p_addr, p_port, p_user, p_pass).start(&block)
+    end
+
+    class << HTTP
+      alias newobj new
+    end
+
+    # Creates a new Net::HTTP object.
+    # If +proxy_addr+ is given, creates an Net::HTTP object with proxy support.
+    # This method does not open the TCP connection.
+    def HTTP.new(address, port = nil, p_addr = nil, p_port = nil, p_user = nil, p_pass = nil)
+      h = Proxy(p_addr, p_port, p_user, p_pass).newobj(address, port)
+      h.instance_eval {
+        @newimpl = ::Net::HTTP.version_1_2?
+      }
+      h
+    end
+
+    # Creates a new Net::HTTP object for the specified +address+.
+    # This method does not open the TCP connection.
+    def initialize(address, port = nil)
+      @address = address
+      @port    = (port || HTTP.default_port)
+      @curr_http_version = HTTPVersion
+      @seems_1_0_server = false
+      @close_on_empty_response = false
+      @socket  = nil
+      @started = false
+      @open_timeout = nil
+      @read_timeout = 60
+      @debug_output = nil
+      @use_ssl = false
+      @ssl_context = nil
+    end
+
+    def inspect
+      "#<#{self.class} #{@address}:#{@port} open=#{started?}>"
+    end
+
+    # *WARNING* This method causes serious security hole.
+    # Never use this method in production code.
+    #
+    # Set an output stream for debugging.
+    #
+    #   http = Net::HTTP.new
+    #   http.set_debug_output $stderr
+    #   http.start { .... }
+    #
+    def set_debug_output(output)
+      warn 'Net::HTTP#set_debug_output called after HTTP started' if started?
+      @debug_output = output
+    end
+
+    # The host name to connect to.
+    attr_reader :address
+
+    # The port number to connect to.
+    attr_reader :port
+
+    # Seconds to wait until connection is opened.
+    # If the HTTP object cannot open a connection in this many seconds,
+    # it raises a TimeoutError exception.
+    attr_accessor :open_timeout
+
+    # Seconds to wait until reading one block (by one read(2) call).
+    # If the HTTP object cannot open a connection in this many seconds,
+    # it raises a TimeoutError exception.
+    attr_reader :read_timeout
+
+    # Setter for the read_timeout attribute.
+    def read_timeout=(sec)
+      @socket.read_timeout = sec if @socket
+      @read_timeout = sec
+    end
+
+    # returns true if the HTTP session is started.
+    def started?
+      @started
+    end
+
+    alias active? started?   #:nodoc: obsolete
+
+    attr_accessor :close_on_empty_response
+
+    # returns true if use SSL/TLS with HTTP.
+    def use_ssl?
+      false   # redefined in net/https
+    end
+
+    # Opens TCP connection and HTTP session.
+    # 
+    # When this method is called with block, gives a HTTP object
+    # to the block and closes the TCP connection / HTTP session
+    # after the block executed.
+    #
+    # When called with a block, returns the return value of the
+    # block; otherwise, returns self.
+    #
+    def start  # :yield: http
+      raise IOError, 'HTTP session already opened' if @started
+      if block_given?
+        begin
+          do_start
+          return yield(self)
+        ensure
+          do_finish
+        end
+      end
+      do_start
+      self
+    end
+
+    def do_start
+      connect
+      @started = true
+    end
+    private :do_start
+
+    def connect
+      D "opening connection to #{conn_address()}..."
+      s = timeout(@open_timeout) { TCPSocket.open(conn_address(), conn_port()) }
+      D "opened"
+      if use_ssl?
+        unless @ssl_context.verify_mode
+          warn "warning: peer certificate won't be verified in this SSL session"
+          @ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
+        end
+        s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
+        s.sync_close = true
+      end
+      @socket = BufferedIO.new(s)
+      @socket.read_timeout = @read_timeout
+      @socket.debug_output = @debug_output
+      if use_ssl?
+        if proxy?
+          @socket.writeline sprintf('CONNECT %s:%s HTTP/%s',
+                                    @address, @port, HTTPVersion)
+          @socket.writeline "Host: #{@address}:#{@port}"
+          if proxy_user
+            credential = ["#{proxy_user}:#{proxy_pass}"].pack('m')
+            credential.delete!("\r\n")
+            @socket.writeline "Proxy-Authorization: Basic #{credential}"
+          end
+          @socket.writeline ''
+          HTTPResponse.read_new(@socket).value
+        end
+        s.connect
+      end
+      on_connect
+    end
+    private :connect
+
+    def on_connect
+    end
+    private :on_connect
+
+    # Finishes HTTP session and closes TCP connection.
+    # Raises IOError if not started.
+    def finish
+      raise IOError, 'HTTP session not yet started' unless started?
+      do_finish
+    end
+
+    def do_finish
+      @started = false
+      @socket.close if @socket and not @socket.closed?
+      @socket = nil
+    end
+    private :do_finish
+
+    #
+    # proxy
+    #
+
+    public
+
+    # no proxy
+    @is_proxy_class = false
+    @proxy_addr = nil
+    @proxy_port = nil
+    @proxy_user = nil
+    @proxy_pass = nil
+
+    # Creates an HTTP proxy class.
+    # Arguments are address/port of proxy host and username/password
+    # if authorization on proxy server is required.
+    # You can replace the HTTP class with created proxy class.
+    # 
+    # If ADDRESS is nil, this method returns self (Net::HTTP).
+    # 
+    #     # Example
+    #     proxy_class = Net::HTTP::Proxy('proxy.example.com', 8080)
+    #                     :
+    #     proxy_class.start('www.ruby-lang.org') {|http|
+    #       # connecting proxy.foo.org:8080
+    #                     :
+    #     }
+    # 
+    def HTTP.Proxy(p_addr, p_port = nil, p_user = nil, p_pass = nil)
+      return self unless p_addr
+      delta = ProxyDelta
+      proxyclass = Class.new(self)
+      proxyclass.module_eval {
+        include delta
+        # with proxy
+        @is_proxy_class = true
+        @proxy_address = p_addr
+        @proxy_port    = p_port || default_port()
+        @proxy_user    = p_user
+        @proxy_pass    = p_pass
+      }
+      proxyclass
+    end
+
+    class << HTTP
+      # returns true if self is a class which was created by HTTP::Proxy.
+      def proxy_class?
+        @is_proxy_class
+      end
+
+      attr_reader :proxy_address
+      attr_reader :proxy_port
+      attr_reader :proxy_user
+      attr_reader :proxy_pass
+    end
+
+    # True if self is a HTTP proxy class.
+    def proxy?
+      self.class.proxy_class?
+    end
+
+    # Address of proxy host. If self does not use a proxy, nil.
+    def proxy_address
+      self.class.proxy_address
+    end
+
+    # Port number of proxy host. If self does not use a proxy, nil.
+    def proxy_port
+      self.class.proxy_port
+    end
+
+    # User name for accessing proxy. If self does not use a proxy, nil.
+    def proxy_user
+      self.class.proxy_user
+    end
+
+    # User password for accessing proxy. If self does not use a proxy, nil.
+    def proxy_pass
+      self.class.proxy_pass
+    end
+
+    alias proxyaddr proxy_address   #:nodoc: obsolete
+    alias proxyport proxy_port      #:nodoc: obsolete
+
+    private
+
+    # without proxy
+
+    def conn_address
+      address()
+    end
+
+    def conn_port
+      port()
+    end
+
+    def edit_path(path)
+      path
+    end
+
+    module ProxyDelta   #:nodoc: internal use only
+      private
+
+      def conn_address
+        proxy_address()
+      end
+
+      def conn_port
+        proxy_port()
+      end
+
+      def edit_path(path)
+        use_ssl? ? path : "http://#{addr_port()}#{path}"
+      end
+    end
+
+    #
+    # HTTP operations
+    #
+
+    public
+
+    # Gets data from +path+ on the connected-to host.
+    # +header+ must be a Hash like { 'Accept' => '*/*', ... }.
+    #
+    # In version 1.1 (ruby 1.6), this method returns a pair of objects,
+    # a Net::HTTPResponse object and the entity body string.
+    # In version 1.2 (ruby 1.8), this method returns a Net::HTTPResponse
+    # object.
+    #
+    # If called with a block, yields each fragment of the
+    # entity body in turn as a string as it is read from
+    # the socket.  Note that in this case, the returned response
+    # object will *not* contain a (meaningful) body.
+    #
+    # +dest+ argument is obsolete.
+    # It still works but you must not use it.
+    #
+    # In version 1.1, this method might raise an exception for 
+    # 3xx (redirect). In this case you can get a HTTPResponse object
+    # by "anException.response".
+    #
+    # In version 1.2, this method never raises exception.
+    #
+    #     # version 1.1 (bundled with Ruby 1.6)
+    #     response, body = http.get('/index.html')
+    #
+    #     # version 1.2 (bundled with Ruby 1.8 or later)
+    #     response = http.get('/index.html')
+    #     
+    #     # using block
+    #     File.open('result.txt', 'w') {|f|
+    #       http.get('/~foo/') do |str|
+    #         f.write str
+    #       end
+    #     }
+    #
+    def get(path, initheader = nil, dest = nil, &block) # :yield: +body_segment+
+      res = nil
+      request(Get.new(path, initheader)) {|r|
+        r.read_body dest, &block
+        res = r
+      }
+      unless @newimpl
+        res.value
+        return res, res.body
+      end
+
+      res
+    end
+
+    # Gets only the header from +path+ on the connected-to host.
+    # +header+ is a Hash like { 'Accept' => '*/*', ... }.
+    # 
+    # This method returns a Net::HTTPResponse object.
+    # 
+    # In version 1.1, this method might raise an exception for 
+    # 3xx (redirect). On the case you can get a HTTPResponse object
+    # by "anException.response".
+    # In version 1.2, this method never raises an exception.
+    # 
+    #     response = nil
+    #     Net::HTTP.start('some.www.server', 80) {|http|
+    #       response = http.head('/index.html')
+    #     }
+    #     p response['content-type']
+    #
+    def head(path, initheader = nil) 
+      res = request(Head.new(path, initheader))
+      res.value unless @newimpl
+      res
+    end
+
+    # Posts +data+ (must be a String) to +path+. +header+ must be a Hash
+    # like { 'Accept' => '*/*', ... }.
+    # 
+    # In version 1.1 (ruby 1.6), this method returns a pair of objects, a
+    # Net::HTTPResponse object and an entity body string.
+    # In version 1.2 (ruby 1.8), this method returns a Net::HTTPResponse object.
+    # 
+    # If called with a block, yields each fragment of the
+    # entity body in turn as a string as it are read from
+    # the socket.  Note that in this case, the returned response
+    # object will *not* contain a (meaningful) body.
+    #
+    # +dest+ argument is obsolete.
+    # It still works but you must not use it.
+    # 
+    # In version 1.1, this method might raise an exception for 
+    # 3xx (redirect). In this case you can get an HTTPResponse object
+    # by "anException.response".
+    # In version 1.2, this method never raises exception.
+    # 
+    #     # version 1.1
+    #     response, body = http.post('/cgi-bin/search.rb', 'query=foo')
+    # 
+    #     # version 1.2
+    #     response = http.post('/cgi-bin/search.rb', 'query=foo')
+    # 
+    #     # using block
+    #     File.open('result.txt', 'w') {|f|
+    #       http.post('/cgi-bin/search.rb', 'query=foo') do |str|
+    #         f.write str
+    #       end
+    #     }
+    #
+    # You should set Content-Type: header field for POST.
+    # If no Content-Type: field given, this method uses
+    # "application/x-www-form-urlencoded" by default.
+    #
+    def post(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
+      res = nil
+      request(Post.new(path, initheader), data) {|r|
+        r.read_body dest, &block
+        res = r
+      }
+      unless @newimpl
+        res.value
+        return res, res.body
+      end
+      res
+    end
+
+    def put(path, data, initheader = nil)   #:nodoc:
+      res = request(Put.new(path, initheader), data)
+      res.value unless @newimpl
+      res
+    end
+
+    # Sends a PROPPATCH request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    def proppatch(path, body, initheader = nil)
+      request(Proppatch.new(path, initheader), body)
+    end
+
+    # Sends a LOCK request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    def lock(path, body, initheader = nil)
+      request(Lock.new(path, initheader), body)
+    end
+
+    # Sends a UNLOCK request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    def unlock(path, body, initheader = nil)
+      request(Unlock.new(path, initheader), body)
+    end
+
+    # Sends a OPTIONS request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    def options(path, initheader = nil)
+      request(Options.new(path, initheader))
+    end
+
+    # Sends a PROPFIND request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    def propfind(path, body = nil, initheader = {'Depth' => '0'})
+      request(Propfind.new(path, initheader), body)
+    end
+
+    # Sends a DELETE request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    def delete(path, initheader = {'Depth' => 'Infinity'})
+      request(Delete.new(path, initheader))
+    end
+
+    # Sends a MOVE request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    def move(path, initheader = nil)
+      request(Move.new(path, initheader))
+    end
+
+    # Sends a COPY request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    def copy(path, initheader = nil)
+      request(Copy.new(path, initheader))
+    end
+
+    # Sends a MKCOL request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    def mkcol(path, body = nil, initheader = nil)
+      request(Mkcol.new(path, initheader), body)
+    end
+
+    # Sends a TRACE request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    def trace(path, initheader = nil)
+      request(Trace.new(path, initheader))
+    end
+
+    # Sends a GET request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    # 
+    # When called with a block, yields an HTTPResponse object.
+    # The body of this response will not have been read yet;
+    # the caller can process it using HTTPResponse#read_body,
+    # if desired.
+    #
+    # Returns the response.
+    # 
+    # This method never raises Net::* exceptions.
+    # 
+    #     response = http.request_get('/index.html')
+    #     # The entity body is already read here.
+    #     p response['content-type']
+    #     puts response.body
+    # 
+    #     # using block
+    #     http.request_get('/index.html') {|response|
+    #       p response['content-type']
+    #       response.read_body do |str|   # read body now
+    #         print str
+    #       end
+    #     }
+    #
+    def request_get(path, initheader = nil, &block) # :yield: +response+
+      request(Get.new(path, initheader), &block)
+    end
+
+    # Sends a HEAD request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    #
+    # Returns the response.
+    # 
+    # This method never raises Net::* exceptions.
+    # 
+    #     response = http.request_head('/index.html')
+    #     p response['content-type']
+    #
+    def request_head(path, initheader = nil, &block)
+      request(Head.new(path, initheader), &block)
+    end
+
+    # Sends a POST request to the +path+ and gets a response,
+    # as an HTTPResponse object.
+    # 
+    # When called with a block, yields an HTTPResponse object.
+    # The body of this response will not have been read yet;
+    # the caller can process it using HTTPResponse#read_body,
+    # if desired.
+    #
+    # Returns the response.
+    # 
+    # This method never raises Net::* exceptions.
+    # 
+    #     # example
+    #     response = http.request_post('/cgi-bin/nice.rb', 'datadatadata...')
+    #     p response.status
+    #     puts response.body          # body is already read
+    # 
+    #     # using block
+    #     http.request_post('/cgi-bin/nice.rb', 'datadatadata...') {|response|
+    #       p response.status
+    #       p response['content-type']
+    #       response.read_body do |str|   # read body now
+    #         print str
+    #       end
+    #     }
+    #
+    def request_post(path, data, initheader = nil, &block) # :yield: +response+
+      request Post.new(path, initheader), data, &block
+    end
+
+    def request_put(path, data, initheader = nil, &block)   #:nodoc:
+      request Put.new(path, initheader), data, &block
+    end
+
+    alias get2   request_get    #:nodoc: obsolete
+    alias head2  request_head   #:nodoc: obsolete
+    alias post2  request_post   #:nodoc: obsolete
+    alias put2   request_put    #:nodoc: obsolete
+
+
+    # Sends an HTTP request to the HTTP server.
+    # This method also sends DATA string if DATA is given.
+    #
+    # Returns a HTTPResponse object.
+    # 
+    # This method never raises Net::* exceptions.
+    #
+    #    response = http.send_request('GET', '/index.html')
+    #    puts response.body
+    #
+    def send_request(name, path, data = nil, header = nil)
+      r = HTTPGenericRequest.new(name,(data ? true : false),true,path,header)
+      request r, data
+    end
+
+    # Sends an HTTPRequest object REQUEST to the HTTP server.
+    # This method also sends DATA string if REQUEST is a post/put request.
+    # Giving DATA for get/head request causes ArgumentError.
+    # 
+    # When called with a block, yields an HTTPResponse object.
+    # The body of this response will not have been read yet;
+    # the caller can process it using HTTPResponse#read_body,
+    # if desired.
+    #
+    # Returns a HTTPResponse object.
+    # 
+    # This method never raises Net::* exceptions.
+    #
+    def request(req, body = nil, &block)  # :yield: +response+
+      unless started?
+        start {
+          req['connection'] ||= 'close'
+          return request(req, body, &block)
+        }
+      end
+      if proxy_user()
+        unless use_ssl?
+          req.proxy_basic_auth proxy_user(), proxy_pass()
+        end
+      end
+
+      req.set_body_internal body
+      begin_transport req
+        req.exec @socket, @curr_http_version, edit_path(req.path)
+        begin
+          res = HTTPResponse.read_new(@socket)
+        end while res.kind_of?(HTTPContinue)
+        res.reading_body(@socket, req.response_body_permitted?) {
+          yield res if block_given?
+        }
+      end_transport req, res
+
+      res
+    end
+
+    private
+
+    def begin_transport(req)
+      if @socket.closed?
+        connect
+      end
+      if @seems_1_0_server
+        req['connection'] ||= 'close'
+      end
+      if not req.response_body_permitted? and @close_on_empty_response
+        req['connection'] ||= 'close'
+      end
+      req['host'] ||= addr_port()
+    end
+
+    def end_transport(req, res)
+      @curr_http_version = res.http_version
+      if not res.body and @close_on_empty_response
+        D 'Conn close'
+        @socket.close
+      elsif keep_alive?(req, res)
+        D 'Conn keep-alive'
+        if @socket.closed?
+          D 'Conn (but seems 1.0 server)'
+          @seems_1_0_server = true
+        end
+      else
+        D 'Conn close'
+        @socket.close
+      end
+    end
+
+    def keep_alive?(req, res)
+      return false if /close/i =~ req['connection'].to_s
+      return false if @seems_1_0_server
+      return true  if /keep-alive/i =~ res['connection'].to_s
+      return false if /close/i      =~ res['connection'].to_s
+      return true  if /keep-alive/i =~ res['proxy-connection'].to_s
+      return false if /close/i      =~ res['proxy-connection'].to_s
+      (@curr_http_version == '1.1')
+    end
+
+    #
+    # utils
+    #
+
+    private
+
+    def addr_port
+      if use_ssl?
+        address() + (port == HTTP.https_default_port ? '' : ":#{port()}")
+      else
+        address() + (port == HTTP.http_default_port ? '' : ":#{port()}")
+      end
+    end
+
+    def D(msg)
+      return unless @debug_output
+      @debug_output << msg
+      @debug_output << "\n"
+    end
+
+  end
+
+  HTTPSession = HTTP
+
+
+  #
+  # Header module.
+  #
+  # Provides access to @header in the mixed-into class as a hash-like
+  # object, except with case-insensitive keys.  Also provides
+  # methods for accessing commonly-used header values in a more
+  # convenient format.
+  #
+  module HTTPHeader
+
+    def initialize_http_header(initheader)
+      @header = {}
+      return unless initheader
+      initheader.each do |key, value|
+        warn "net/http: warning: duplicated HTTP header: #{key}" if key?(key) and $VERBOSE
+        @header[key.downcase] = [value.strip]
+      end
+    end
+
+    def size   #:nodoc: obsolete
+      @header.size
+    end
+
+    alias length size   #:nodoc: obsolete
+
+    # Returns the header field corresponding to the case-insensitive key.
+    # For example, a key of "Content-Type" might return "text/html"
+    def [](key)
+      a = @header[key.downcase] or return nil
+      a.join(', ')
+    end
+
+    # Sets the header field corresponding to the case-insensitive key.
+    def []=(key, val)
+      unless val
+        @header.delete key.downcase
+        return val
+      end
+      @header[key.downcase] = [val]
+    end
+
+    # [Ruby 1.8.3]
+    # Adds header field instead of replace.
+    # Second argument +val+ must be a String.
+    # See also #[]=, #[] and #get_fields.
+    #
+    #   request.add_field 'X-My-Header', 'a'
+    #   p request['X-My-Header']              #=> "a"
+    #   p request.get_fields('X-My-Header')   #=> ["a"]
+    #   request.add_field 'X-My-Header', 'b'
+    #   p request['X-My-Header']              #=> "a, b"
+    #   p request.get_fields('X-My-Header')   #=> ["a", "b"]
+    #   request.add_field 'X-My-Header', 'c'
+    #   p request['X-My-Header']              #=> "a, b, c"
+    #   p request.get_fields('X-My-Header')   #=> ["a", "b", "c"]
+    #
+    def add_field(key, val)
+      if @header.key?(key.downcase)
+        @header[key.downcase].push val
+      else
+        @header[key.downcase] = [val]
+      end
+    end
+
+    # [Ruby 1.8.3]
+    # Returns an array of header field strings corresponding to the
+    # case-insensitive +key+.  This method allows you to get duplicated
+    # header fields without any processing.  See also #[].
+    #
+    #   p response.get_fields('Set-Cookie')
+    #     #=> ["session=al98axx; expires=Fri, 31-Dec-1999 23:58:23",
+    #          "query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"]
+    #   p response['Set-Cookie']
+    #     #=> "session=al98axx; expires=Fri, 31-Dec-1999 23:58:23, query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"
+    #
+    def get_fields(key)
+      return nil unless @header[key.downcase]
+      @header[key.downcase].dup
+    end
+
+    # Returns the header field corresponding to the case-insensitive key.
+    # Returns the default value +args+, or the result of the block, or nil,
+    # if there's no header field named key.  See Hash#fetch
+    def fetch(key, *args, &block)   #:yield: +key+
+      a = @header.fetch(key.downcase, *args, &block)
+      a.join(', ')
+    end
+
+    # Iterates for each header names and values.
+    def each_header   #:yield: +key+, +value+
+      @header.each do |k,va|
+        yield k, va.join(', ')
+      end
+    end
+
+    alias each each_header
+
+    # Iterates for each header names.
+    def each_name(&block)   #:yield: +key+
+      @header.each_key(&block)
+    end
+
+    alias each_key each_name
+
+    # Iterates for each capitalized header names.
+    def each_capitalized_name(&block)   #:yield: +key+
+      @header.each_key do |k|
+        yield capitalize(k)
+      end
+    end
+
+    # Iterates for each header values.
+    def each_value   #:yield: +value+
+      @header.each_value do |va|
+        yield va.join(', ')
+      end
+    end
+
+    # Removes a header field.
+    def delete(key)
+      @header.delete(key.downcase)
+    end
+
+    # true if +key+ header exists.
+    def key?(key)
+      @header.key?(key.downcase)
+    end
+
+    # Returns a Hash consist of header names and values.
+    def to_hash
+      @header.dup
+    end
+
+    # As for #each_header, except the keys are provided in capitalized form.
+    def each_capitalized
+      @header.each do |k,v|
+        yield capitalize(k), v.join(', ')
+      end
+    end
+
+    alias canonical_each each_capitalized
+
+    def capitalize(name)
+      name.split(/-/).map {|s| s.capitalize }.join('-')
+    end
+    private :capitalize
+
+    # Returns an Array of Range objects which represents Range: header field,
+    # or +nil+ if there is no such header.
+    def range
+      return nil unless @header['range']
+      self['Range'].split(/,/).map {|spec|
+        m = /bytes\s*=\s*(\d+)?\s*-\s*(\d+)?/i.match(spec) or
+                raise HTTPHeaderSyntaxError, "wrong Range: #{spec}"
+        d1 = m[1].to_i
+        d2 = m[2].to_i
+        if    m[1] and m[2] then  d1..d2
+        elsif m[1]          then  d1..-1
+        elsif          m[2] then -d2..-1
+        else
+          raise HTTPHeaderSyntaxError, 'range is not specified'
+        end
+      }
+    end
+
+    # Set Range: header from Range (arg r) or beginning index and
+    # length from it (arg idx&len).
+    #
+    #   req.range = (0..1023)
+    #   req.set_range 0, 1023
+    #
+    def set_range(r, e = nil)
+      unless r
+        @header.delete 'range'
+        return r
+      end
+      r = (r...r+e) if e
+      case r
+      when Numeric
+        n = r.to_i
+        rangestr = (n > 0 ? "0-#{n-1}" : "-#{-n}")
+      when Range
+        first = r.first
+        last = r.last
+        last -= 1 if r.exclude_end?
+        if last == -1
+          rangestr = (first > 0 ? "#{first}-" : "-#{-first}")
+        else
+          raise HTTPHeaderSyntaxError, 'range.first is negative' if first < 0
+          raise HTTPHeaderSyntaxError, 'range.last is negative' if last < 0
+          raise HTTPHeaderSyntaxError, 'must be .first < .last' if first > last
+          rangestr = "#{first}-#{last}"
+        end
+      else
+        raise TypeError, 'Range/Integer is required'
+      end
+      @header['range'] = ["bytes=#{rangestr}"]
+      r
+    end
+
+    alias range= set_range
+
+    # Returns an Integer object which represents the Content-Length: header field
+    # or +nil+ if that field is not provided.
+    def content_length
+      return nil unless key?('Content-Length')
+      len = self['Content-Length'].slice(/\d+/) or
+          raise HTTPHeaderSyntaxError, 'wrong Content-Length format'
+      len.to_i
+    end
+    
+    def content_length=(len)
+      unless len
+        @header.delete 'content-length'
+        return nil
+      end
+      @header['content-length'] = [len.to_i.to_s]
+    end
+
+    # Returns "true" if the "transfer-encoding" header is present and
+    # set to "chunked".  This is an HTTP/1.1 feature, allowing the 
+    # the content to be sent in "chunks" without at the outset
+    # stating the entire content length.
+    def chunked?
+      return false unless @header['transfer-encoding']
+      field = self['Transfer-Encoding']
+      (/(?:\A|[^\-\w])chunked(?![\-\w])/i =~ field) ? true : false
+    end
+
+    # Returns a Range object which represents Content-Range: header field.
+    # This indicates, for a partial entity body, where this fragment
+    # fits inside the full entity body, as range of byte offsets.
+    def content_range
+      return nil unless @header['content-range']
+      m = %r<bytes\s+(\d+)-(\d+)/(\d+|\*)>i.match(self['Content-Range']) or
+          raise HTTPHeaderSyntaxError, 'wrong Content-Range format'
+      m[1].to_i .. m[2].to_i + 1
+    end
+
+    # The length of the range represented in Content-Range: header.
+    def range_length
+      r = content_range() or return nil
+      r.end - r.begin
+    end
+
+    # Returns a content type string such as "text/html".
+    # This method returns nil if Content-Type: header field does not exist.
+    def content_type
+      return nil unless main_type()
+      if sub_type()
+      then "#{main_type()}/#{sub_type()}"
+      else main_type()
+      end
+    end
+
+    # Returns a content type string such as "text".
+    # This method returns nil if Content-Type: header field does not exist.
+    def main_type
+      return nil unless @header['content-type']
+      self['Content-Type'].split(';').first.to_s.split('/')[0].to_s.strip
+    end
+    
+    # Returns a content type string such as "html".
+    # This method returns nil if Content-Type: header field does not exist
+    # or sub-type is not given (e.g. "Content-Type: text").
+    def sub_type
+      return nil unless @header['content-type']
+      main, sub = *self['Content-Type'].split(';').first.to_s.split('/')
+      return nil unless sub
+      sub.strip
+    end
+
+    # Returns content type parameters as a Hash as like
+    # {"charset" => "iso-2022-jp"}.
+    def type_params
+      result = {}
+      list = self['Content-Type'].to_s.split(';')
+      list.shift
+      list.each do |param|
+        k, v = *param.split('=', 2)
+        result[k.strip] = v.strip
+      end
+      result
+    end
+
+    # Set Content-Type: header field by +type+ and +params+.
+    # +type+ must be a String, +params+ must be a Hash.
+    def set_content_type(type, params = {})
+      @header['content-type'] = [type + params.map{|k,v|"; #{k}=#{v}"}.join('')]
+    end
+
+    alias content_type= set_content_type
+
+    # Set header fields and a body from HTML form data.
+    # +params+ should be a Hash containing HTML form data.
+    # Optional argument +sep+ means data record separator.
+    #
+    # This method also set Content-Type: header field to
+    # application/x-www-form-urlencoded.
+    def set_form_data(params, sep = '&')
+      self.body = params.map {|k,v| "#{urlencode(k.to_s)}=#{urlencode(v.to_s)}" }.join(sep)
+      self.content_type = 'application/x-www-form-urlencoded'
+    end
+
+    alias form_data= set_form_data
+
+    def urlencode(str)
+      str.gsub(/[^a-zA-Z0-9_\.\-]/n) {|s| sprintf('%%%02x', s[0]) }
+    end
+    private :urlencode
+
+    # Set the Authorization: header for "Basic" authorization.
+    def basic_auth(account, password)
+      @header['authorization'] = [basic_encode(account, password)]
+    end
+
+    # Set Proxy-Authorization: header for "Basic" authorization.
+    def proxy_basic_auth(account, password)
+      @header['proxy-authorization'] = [basic_encode(account, password)]
+    end
+
+    def basic_encode(account, password)
+      'Basic ' + ["#{account}:#{password}"].pack('m').delete("\r\n")
+    end
+    private :basic_encode
+
+  end
+
+
+  #
+  # Parent of HTTPRequest class.  Do not use this directly; use
+  # a subclass of HTTPRequest.
+  #
+  # Mixes in the HTTPHeader module.
+  #
+  class HTTPGenericRequest
+
+    include HTTPHeader
+
+    def initialize(m, reqbody, resbody, path, initheader = nil)
+      @method = m
+      @request_has_body = reqbody
+      @response_has_body = resbody
+      raise ArgumentError, "HTTP request path is empty" if path.empty?
+      @path = path
+      initialize_http_header initheader
+      self['Accept'] ||= '*/*'
+      @body = nil
+      @body_stream = nil
+    end
+
+    attr_reader :method
+    attr_reader :path
+
+    def inspect
+      "\#<#{self.class} #{@method}>"
+    end
+
+    def request_body_permitted?
+      @request_has_body
+    end
+
+    def response_body_permitted?
+      @response_has_body
+    end
+
+    def body_exist?
+      warn "Net::HTTPRequest#body_exist? is obsolete; use response_body_permitted?" if $VERBOSE
+      response_body_permitted?
+    end
+
+    attr_reader :body
+
+    def body=(str)
+      @body = str
+      @body_stream = nil
+      str
+    end
+
+    attr_reader :body_stream
+
+    def body_stream=(input)
+      @body = nil
+      @body_stream = input
+      input
+    end
+
+    def set_body_internal(str)   #:nodoc: internal use only
+      raise ArgumentError, "both of body argument and HTTPRequest#body set" if str and (@body or @body_stream)
+      self.body = str if str
+    end
+
+    #
+    # write
+    #
+
+    def exec(sock, ver, path)   #:nodoc: internal use only
+      if @body
+        send_request_with_body sock, ver, path, @body
+      elsif @body_stream
+        send_request_with_body_stream sock, ver, path, @body_stream
+      else
+        write_header sock, ver, path
+      end
+    end
+
+    private
+
+    def send_request_with_body(sock, ver, path, body)
+      self.content_length = body.length
+      delete 'Transfer-Encoding'
+      supply_default_content_type
+      write_header sock, ver, path
+      sock.write body
+    end
+
+    def send_request_with_body_stream(sock, ver, path, f)
+      unless content_length() or chunked?
+        raise ArgumentError,
+            "Content-Length not given and Transfer-Encoding is not `chunked'"
+      end
+      supply_default_content_type
+      write_header sock, ver, path
+      if chunked?
+        while s = f.read(1024)
+          sock.write(sprintf("%x\r\n", s.length) << s << "\r\n")
+        end
+        sock.write "0\r\n\r\n"
+      else
+        while s = f.read(1024)
+          sock.write s
+        end
+      end
+    end
+
+    def supply_default_content_type
+      return if content_type()
+      warn 'net/http: warning: Content-Type did not set; using application/x-www-form-urlencoded' if $VERBOSE
+      set_content_type 'application/x-www-form-urlencoded'
+    end
+
+    def write_header(sock, ver, path)
+      buf = "#{@method} #{path} HTTP/#{ver}\r\n"
+      each_capitalized do |k,v|
+        buf << "#{k}: #{v}\r\n"
+      end
+      buf << "\r\n"
+      sock.write buf
+    end
+  
+  end
+
+
+  # 
+  # HTTP request class. This class wraps request header and entity path.
+  # You *must* use its subclass, Net::HTTP::Get, Post, Head.
+  # 
+  class HTTPRequest < HTTPGenericRequest
+
+    # Creates HTTP request object.
+    def initialize(path, initheader = nil)
+      super self.class::METHOD,
+            self.class::REQUEST_HAS_BODY,
+            self.class::RESPONSE_HAS_BODY,
+            path, initheader
+    end
+  end
+
+
+  class HTTP   # reopen
+    #
+    # HTTP 1.1 methods --- RFC2616
+    #
+
+    class Get < HTTPRequest
+      METHOD = 'GET'
+      REQUEST_HAS_BODY  = false
+      RESPONSE_HAS_BODY = true
+    end
+
+    class Head < HTTPRequest
+      METHOD = 'HEAD'
+      REQUEST_HAS_BODY = false
+      RESPONSE_HAS_BODY = false
+    end
+
+    class Post < HTTPRequest
+      METHOD = 'POST'
+      REQUEST_HAS_BODY = true
+      RESPONSE_HAS_BODY = true
+    end
+
+    class Put < HTTPRequest
+      METHOD = 'PUT'
+      REQUEST_HAS_BODY = true
+      RESPONSE_HAS_BODY = true
+    end
+
+    class Delete < HTTPRequest
+      METHOD = 'DELETE'
+      REQUEST_HAS_BODY = false
+      RESPONSE_HAS_BODY = true
+    end
+
+    class Options < HTTPRequest
+      METHOD = 'OPTIONS'
+      REQUEST_HAS_BODY = false
+      RESPONSE_HAS_BODY = false
+    end
+
+    class Trace < HTTPRequest
+      METHOD = 'TRACE'
+      REQUEST_HAS_BODY = false
+      RESPONSE_HAS_BODY = true
+    end
+
+    #
+    # WebDAV methods --- RFC2518
+    #
+
+    class Propfind < HTTPRequest
+      METHOD = 'PROPFIND'
+      REQUEST_HAS_BODY = true
+      RESPONSE_HAS_BODY = true
+    end
+
+    class Proppatch < HTTPRequest
+      METHOD = 'PROPPATCH'
+      REQUEST_HAS_BODY = true
+      RESPONSE_HAS_BODY = true
+    end
+
+    class Mkcol < HTTPRequest
+      METHOD = 'MKCOL'
+      REQUEST_HAS_BODY = true
+      RESPONSE_HAS_BODY = true
+    end
+
+    class Copy < HTTPRequest
+      METHOD = 'COPY'
+      REQUEST_HAS_BODY = false
+      RESPONSE_HAS_BODY = true
+    end
+
+    class Move < HTTPRequest
+      METHOD = 'MOVE'
+      REQUEST_HAS_BODY = false
+      RESPONSE_HAS_BODY = true
+    end
+
+    class Lock < HTTPRequest
+      METHOD = 'LOCK'
+      REQUEST_HAS_BODY = true
+      RESPONSE_HAS_BODY = true
+    end
+
+    class Unlock < HTTPRequest
+      METHOD = 'UNLOCK'
+      REQUEST_HAS_BODY = true
+      RESPONSE_HAS_BODY = true
+    end
+  end
+
+
+  ###
+  ### Response
+  ###
+
+  # HTTP exception class.
+  # You must use its subclasses.
+  module HTTPExceptions
+    def initialize(msg, res)   #:nodoc:
+      super msg
+      @response = res
+    end
+    attr_reader :response
+    alias data response    #:nodoc: obsolete
+  end
+  class HTTPError < ProtocolError
+    include HTTPExceptions
+  end
+  class HTTPRetriableError < ProtoRetriableError
+    include HTTPExceptions
+  end
+  class HTTPServerException < ProtoServerError
+    # We cannot use the name "HTTPServerError", it is the name of the response.
+    include HTTPExceptions
+  end
+  class HTTPFatalError < ProtoFatalError
+    include HTTPExceptions
+  end
+
+
+  # HTTP response class. This class wraps response header and entity.
+  # Mixes in the HTTPHeader module, which provides access to response
+  # header values both via hash-like methods and individual readers.
+  # Note that each possible HTTP response code defines its own 
+  # HTTPResponse subclass.  These are listed below.
+  # All classes are
+  # defined under the Net module. Indentation indicates inheritance.
+  # 
+  #   xxx        HTTPResponse
+  # 
+  #     1xx        HTTPInformation
+  #       100        HTTPContinue    
+  #       101        HTTPSwitchProtocol
+  # 
+  #     2xx        HTTPSuccess
+  #       200        HTTPOK
+  #       201        HTTPCreated
+  #       202        HTTPAccepted
+  #       203        HTTPNonAuthoritativeInformation
+  #       204        HTTPNoContent
+  #       205        HTTPResetContent
+  #       206        HTTPPartialContent
+  # 
+  #     3xx        HTTPRedirection
+  #       300        HTTPMultipleChoice
+  #       301        HTTPMovedPermanently
+  #       302        HTTPFound
+  #       303        HTTPSeeOther
+  #       304        HTTPNotModified
+  #       305        HTTPUseProxy
+  #       307        HTTPTemporaryRedirect
+  # 
+  #     4xx        HTTPClientError
+  #       400        HTTPBadRequest
+  #       401        HTTPUnauthorized
+  #       402        HTTPPaymentRequired
+  #       403        HTTPForbidden
+  #       404        HTTPNotFound
+  #       405        HTTPMethodNotAllowed
+  #       406        HTTPNotAcceptable
+  #       407        HTTPProxyAuthenticationRequired
+  #       408        HTTPRequestTimeOut
+  #       409        HTTPConflict
+  #       410        HTTPGone
+  #       411        HTTPLengthRequired
+  #       412        HTTPPreconditionFailed
+  #       413        HTTPRequestEntityTooLarge
+  #       414        HTTPRequestURITooLong
+  #       415        HTTPUnsupportedMediaType
+  #       416        HTTPRequestedRangeNotSatisfiable
+  #       417        HTTPExpectationFailed
+  # 
+  #     5xx        HTTPServerError
+  #       500        HTTPInternalServerError
+  #       501        HTTPNotImplemented
+  #       502        HTTPBadGateway
+  #       503        HTTPServiceUnavailable
+  #       504        HTTPGatewayTimeOut
+  #       505        HTTPVersionNotSupported
+  # 
+  #     xxx        HTTPUnknownResponse
+  #
+  class HTTPResponse
+    # true if the response has body.
+    def HTTPResponse.body_permitted?
+      self::HAS_BODY
+    end
+
+    def HTTPResponse.exception_type   # :nodoc: internal use only
+      self::EXCEPTION_TYPE
+    end
+  end   # reopened after
+
+  # :stopdoc:
+
+  class HTTPUnknownResponse < HTTPResponse
+    HAS_BODY = true
+    EXCEPTION_TYPE = HTTPError
+  end
+  class HTTPInformation < HTTPResponse           # 1xx
+    HAS_BODY = false
+    EXCEPTION_TYPE = HTTPError
+  end
+  class HTTPSuccess < HTTPResponse               # 2xx
+    HAS_BODY = true
+    EXCEPTION_TYPE = HTTPError
+  end
+  class HTTPRedirection < HTTPResponse           # 3xx
+    HAS_BODY = true
+    EXCEPTION_TYPE = HTTPRetriableError
+  end
+  class HTTPClientError < HTTPResponse           # 4xx
+    HAS_BODY = true
+    EXCEPTION_TYPE = HTTPServerException   # for backward compatibility
+  end
+  class HTTPServerError < HTTPResponse           # 5xx
+    HAS_BODY = true
+    EXCEPTION_TYPE = HTTPFatalError    # for backward compatibility
+  end
+
+  class HTTPContinue < HTTPInformation           # 100
+    HAS_BODY = false
+  end
+  class HTTPSwitchProtocol < HTTPInformation     # 101
+    HAS_BODY = false
+  end
+
+  class HTTPOK < HTTPSuccess                            # 200
+    HAS_BODY = true
+  end
+  class HTTPCreated < HTTPSuccess                       # 201
+    HAS_BODY = true
+  end
+  class HTTPAccepted < HTTPSuccess                      # 202
+    HAS_BODY = true
+  end
+  class HTTPNonAuthoritativeInformation < HTTPSuccess   # 203
+    HAS_BODY = true
+  end
+  class HTTPNoContent < HTTPSuccess                     # 204
+    HAS_BODY = false
+  end
+  class HTTPResetContent < HTTPSuccess                  # 205
+    HAS_BODY = false
+  end
+  class HTTPPartialContent < HTTPSuccess                # 206
+    HAS_BODY = true
+  end
+
+  class HTTPMultipleChoice < HTTPRedirection     # 300
+    HAS_BODY = true
+  end
+  class HTTPMovedPermanently < HTTPRedirection   # 301
+    HAS_BODY = true
+  end
+  class HTTPFound < HTTPRedirection              # 302
+    HAS_BODY = true
+  end
+  HTTPMovedTemporarily = HTTPFound
+  class HTTPSeeOther < HTTPRedirection           # 303
+    HAS_BODY = true
+  end
+  class HTTPNotModified < HTTPRedirection        # 304
+    HAS_BODY = false
+  end
+  class HTTPUseProxy < HTTPRedirection           # 305
+    HAS_BODY = false
+  end
+  # 306 unused
+  class HTTPTemporaryRedirect < HTTPRedirection  # 307
+    HAS_BODY = true
+  end
+
+  class HTTPBadRequest < HTTPClientError                    # 400
+    HAS_BODY = true
+  end
+  class HTTPUnauthorized < HTTPClientError                  # 401
+    HAS_BODY = true
+  end
+  class HTTPPaymentRequired < HTTPClientError               # 402
+    HAS_BODY = true
+  end
+  class HTTPForbidden < HTTPClientError                     # 403
+    HAS_BODY = true
+  end
+  class HTTPNotFound < HTTPClientError                      # 404
+    HAS_BODY = true
+  end
+  class HTTPMethodNotAllowed < HTTPClientError              # 405
+    HAS_BODY = true
+  end
+  class HTTPNotAcceptable < HTTPClientError                 # 406
+    HAS_BODY = true
+  end
+  class HTTPProxyAuthenticationRequired < HTTPClientError   # 407
+    HAS_BODY = true
+  end
+  class HTTPRequestTimeOut < HTTPClientError                # 408
+    HAS_BODY = true
+  end
+  class HTTPConflict < HTTPClientError                      # 409
+    HAS_BODY = true
+  end
+  class HTTPGone < HTTPClientError                          # 410
+    HAS_BODY = true
+  end
+  class HTTPLengthRequired < HTTPClientError                # 411
+    HAS_BODY = true
+  end
+  class HTTPPreconditionFailed < HTTPClientError            # 412
+    HAS_BODY = true
+  end
+  class HTTPRequestEntityTooLarge < HTTPClientError         # 413
+    HAS_BODY = true
+  end
+  class HTTPRequestURITooLong < HTTPClientError             # 414
+    HAS_BODY = true
+  end
+  HTTPRequestURITooLarge = HTTPRequestURITooLong
+  class HTTPUnsupportedMediaType < HTTPClientError          # 415
+    HAS_BODY = true
+  end
+  class HTTPRequestedRangeNotSatisfiable < HTTPClientError  # 416
+    HAS_BODY = true
+  end
+  class HTTPExpectationFailed < HTTPClientError             # 417
+    HAS_BODY = true
+  end
+
+  class HTTPInternalServerError < HTTPServerError   # 500
+    HAS_BODY = true
+  end
+  class HTTPNotImplemented < HTTPServerError        # 501
+    HAS_BODY = true
+  end
+  class HTTPBadGateway < HTTPServerError            # 502
+    HAS_BODY = true
+  end
+  class HTTPServiceUnavailable < HTTPServerError    # 503
+    HAS_BODY = true
+  end
+  class HTTPGatewayTimeOut < HTTPServerError        # 504
+    HAS_BODY = true
+  end
+  class HTTPVersionNotSupported < HTTPServerError   # 505
+    HAS_BODY = true
+  end
+
+  # :startdoc:
+
+
+  class HTTPResponse   # reopen
+
+    CODE_CLASS_TO_OBJ = {
+      '1' => HTTPInformation,
+      '2' => HTTPSuccess,
+      '3' => HTTPRedirection,
+      '4' => HTTPClientError,
+      '5' => HTTPServerError
+    }
+    CODE_TO_OBJ = {
+      '100' => HTTPContinue,
+      '101' => HTTPSwitchProtocol,
+
+      '200' => HTTPOK,
+      '201' => HTTPCreated,
+      '202' => HTTPAccepted,
+      '203' => HTTPNonAuthoritativeInformation,
+      '204' => HTTPNoContent,
+      '205' => HTTPResetContent,
+      '206' => HTTPPartialContent,
+
+      '300' => HTTPMultipleChoice,
+      '301' => HTTPMovedPermanently,
+      '302' => HTTPFound,
+      '303' => HTTPSeeOther,
+      '304' => HTTPNotModified,
+      '305' => HTTPUseProxy,
+      '307' => HTTPTemporaryRedirect,
+
+      '400' => HTTPBadRequest,
+      '401' => HTTPUnauthorized,
+      '402' => HTTPPaymentRequired,
+      '403' => HTTPForbidden,
+      '404' => HTTPNotFound,
+      '405' => HTTPMethodNotAllowed,
+      '406' => HTTPNotAcceptable,
+      '407' => HTTPProxyAuthenticationRequired,
+      '408' => HTTPRequestTimeOut,
+      '409' => HTTPConflict,
+      '410' => HTTPGone,
+      '411' => HTTPLengthRequired,
+      '412' => HTTPPreconditionFailed,
+      '413' => HTTPRequestEntityTooLarge,
+      '414' => HTTPRequestURITooLong,
+      '415' => HTTPUnsupportedMediaType,
+      '416' => HTTPRequestedRangeNotSatisfiable,
+      '417' => HTTPExpectationFailed,
+
+      '500' => HTTPInternalServerError,
+      '501' => HTTPNotImplemented,
+      '502' => HTTPBadGateway,
+      '503' => HTTPServiceUnavailable,
+      '504' => HTTPGatewayTimeOut,
+      '505' => HTTPVersionNotSupported
+    }
+
+    class << HTTPResponse
+      def read_new(sock)   #:nodoc: internal use only
+        httpv, code, msg = read_status_line(sock)
+        res = response_class(code).new(httpv, code, msg)
+        each_response_header(sock) do |k,v|
+          res.add_field k, v
+        end
+        res
+      end
+
+      private
+
+      def read_status_line(sock)
+        str = sock.readline
+        m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in.match(str) or
+          raise HTTPBadResponse, "wrong status line: #{str.dump}"
+        m.captures
+      end
+
+      def response_class(code)
+        CODE_TO_OBJ[code] or
+        CODE_CLASS_TO_OBJ[code[0,1]] or
+        HTTPUnknownResponse
+      end
+
+      def each_response_header(sock)
+        while true
+          line = sock.readuntil("\n", true).sub(/\s+\z/, '')
+          break if line.empty?
+          m = /\A([^:]+):\s*/.match(line) or
+              raise HTTPBadResponse, 'wrong header line format'
+          yield m[1], m.post_match
+        end
+      end
+    end
+
+    # next is to fix bug in RDoc, where the private inside class << self
+    # spills out.
+    public 
+
+    include HTTPHeader
+
+    def initialize(httpv, code, msg)   #:nodoc: internal use only
+      @http_version = httpv
+      @code         = code
+      @message      = msg
+      initialize_http_header nil
+      @body = nil
+      @read = false
+    end
+
+    # The HTTP version supported by the server.
+    attr_reader :http_version
+
+    # HTTP result code string. For example, '302'.  You can also
+    # determine the response type by which response subclass the
+    # response object is an instance of.
+    attr_reader :code
+
+    # HTTP result message. For example, 'Not Found'.
+    attr_reader :message
+    alias msg message   # :nodoc: obsolete
+
+    def inspect
+      "#<#{self.class} #{@code} #{@message} readbody=#{@read}>"
+    end
+
+    # For backward compatibility.
+    # To allow Net::HTTP 1.1 style assignment
+    # e.g.
+    #    response, body = Net::HTTP.get(....)
+    # 
+    def to_ary
+      warn "net/http.rb: warning: Net::HTTP v1.1 style assignment found at #{caller(1)[0]}; use `response = http.get(...)' instead." if $VERBOSE
+      res = self.dup
+      class << res
+        undef to_ary
+      end
+      [res, res.body]
+    end
+
+    #
+    # response <-> exception relationship
+    #
+
+    def code_type   #:nodoc:
+      self.class
+    end
+
+    def error!   #:nodoc:
+      raise error_type().new(@code + ' ' + @message.dump, self)
+    end
+
+    def error_type   #:nodoc:
+      self.class::EXCEPTION_TYPE
+    end
+
+    # Raises HTTP error if the response is not 2xx.
+    def value
+      error! unless self.kind_of?(HTTPSuccess)
+    end
+
+    #
+    # header (for backward compatibility only; DO NOT USE)
+    #
+
+    def response   #:nodoc:
+      warn "#{caller(1)[0]}: warning: HTTPResponse#response is obsolete" if $VERBOSE
+      self
+    end
+
+    def header   #:nodoc:
+      warn "#{caller(1)[0]}: warning: HTTPResponse#header is obsolete" if $VERBOSE
+      self
+    end
+
+    def read_header   #:nodoc:
+      warn "#{caller(1)[0]}: warning: HTTPResponse#read_header is obsolete" if $VERBOSE
+      self
+    end
+
+    #
+    # body
+    #
+
+    def reading_body(sock, reqmethodallowbody)  #:nodoc: internal use only
+      @socket = sock
+      @body_exist = reqmethodallowbody && self.class.body_permitted?
+      begin
+        yield
+        self.body   # ensure to read body
+      ensure
+        @socket = nil
+      end
+    end
+
+    # Gets entity body.  If the block given, yields it to +block+.
+    # The body is provided in fragments, as it is read in from the socket.
+    #
+    # Calling this method a second or subsequent time will return the
+    # already read string.
+    #
+    #   http.request_get('/index.html') {|res|
+    #     puts res.read_body
+    #   }
+    #
+    #   http.request_get('/index.html') {|res|
+    #     p res.read_body.object_id   # 538149362
+    #     p res.read_body.object_id   # 538149362
+    #   }
+    #
+    #   # using iterator
+    #   http.request_get('/index.html') {|res|
+    #     res.read_body do |segment|
+    #       print segment
+    #     end
+    #   }
+    #
+    def read_body(dest = nil, &block)
+      if @read
+        raise IOError, "#{self.class}\#read_body called twice" if dest or block
+        return @body
+      end
+      to = procdest(dest, block)
+      stream_check
+      if @body_exist
+        read_body_0 to
+        @body = to
+      else
+        @body = nil
+      end
+      @read = true
+
+      @body
+    end
+
+    # Returns the entity body.
+    #
+    # Calling this method a second or subsequent time will return the
+    # already read string.
+    #
+    #   http.request_get('/index.html') {|res|
+    #     puts res.body
+    #   }
+    #
+    #   http.request_get('/index.html') {|res|
+    #     p res.body.object_id   # 538149362
+    #     p res.body.object_id   # 538149362
+    #   }
+    #
+    def body
+      read_body()
+    end
+
+    alias entity body   #:nodoc: obsolete
+
+    private
+
+    def read_body_0(dest)
+      if chunked?
+        read_chunked dest
+        return
+      end
+      clen = content_length()
+      if clen
+        @socket.read clen, dest, true   # ignore EOF
+        return
+      end
+      clen = range_length()
+      if clen
+        @socket.read clen, dest
+        return
+      end
+      @socket.read_all dest
+    end
+
+    def read_chunked(dest)
+      len = nil
+      total = 0
+      while true
+        line = @socket.readline
+        hexlen = line.slice(/[0-9a-fA-F]+/) or
+            raise HTTPBadResponse, "wrong chunk size line: #{line}"
+        len = hexlen.hex
+        break if len == 0
+        @socket.read len, dest; total += len
+        @socket.read 2   # \r\n
+      end
+      until @socket.readline.empty?
+        # none
+      end
+    end
+
+    def stream_check
+      raise IOError, 'attempt to read body out of block' if @socket.closed?
+    end
+
+    def procdest(dest, block)
+      raise ArgumentError, 'both arg and block given for HTTP method' \
+          if dest and block
+      if block
+        ReadAdapter.new(block)
+      else
+        dest || ''
+      end
+    end
+
+  end
+
+
+  # :enddoc:
+
+  #--
+  # for backward compatibility
+  class HTTP
+    ProxyMod = ProxyDelta
+  end
+  module NetPrivate
+    HTTPRequest = ::Net::HTTPRequest
+  end
+
+  HTTPInformationCode = HTTPInformation
+  HTTPSuccessCode     = HTTPSuccess
+  HTTPRedirectionCode = HTTPRedirection
+  HTTPRetriableCode   = HTTPRedirection
+  HTTPClientErrorCode = HTTPClientError
+  HTTPFatalErrorCode  = HTTPClientError
+  HTTPServerErrorCode = HTTPServerError
+  HTTPResponceReceiver = HTTPResponse
+
+end   # module Net
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/https.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/https.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/https.rb	(revision 18425)
@@ -0,0 +1,173 @@
+=begin
+
+= $RCSfile$ -- SSL/TLS enhancement for Net::HTTP.
+
+== Info
+  'OpenSSL for Ruby 2' project
+  Copyright (C) 2001 GOTOU Yuuzou <gotoyuzo@notwork.org>
+  All rights reserved.
+
+== Licence
+  This program is licenced under the same licence as Ruby.
+  (See the file 'LICENCE'.)
+
+== Requirements
+  This program requires Net 1.2.0 or higher version.
+  You can get it from RAA or Ruby's CVS repository.
+
+== Version
+  $Id: https.rb 11708 2007-02-12 23:01:19Z shyouhei $
+  
+  2001-11-06: Contiributed to Ruby/OpenSSL project.
+  2004-03-06: Some code is merged in to net/http.
+
+== Example
+
+Here is a simple HTTP client:
+
+    require 'net/http'
+    require 'uri'
+
+    uri = URI.parse(ARGV[0] || 'http://localhost/')
+    http = Net::HTTP.new(uri.host, uri.port)
+    http.start {
+      http.request_get(uri.path) {|res|
+        print res.body
+      }
+    }
+
+It can be replaced by the following code:
+
+    require 'net/https'
+    require 'uri'
+
+    uri = URI.parse(ARGV[0] || 'https://localhost/')
+    http = Net::HTTP.new(uri.host, uri.port)
+    http.use_ssl = true if uri.scheme == "https"  # enable SSL/TLS
+    http.start {
+      http.request_get(uri.path) {|res|
+        print res.body
+      }
+    }
+
+== class Net::HTTP
+
+=== Instance Methods
+
+: use_ssl?
+    returns true if use SSL/TLS with HTTP.
+
+: use_ssl=((|true_or_false|))
+    sets use_ssl.
+
+: peer_cert
+    return the X.509 certificates the server presented.
+
+: key, key=((|key|))
+    Sets an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
+    (This method is appeared in Michal Rokos's OpenSSL extention.)
+
+: cert, cert=((|cert|))
+    Sets an OpenSSL::X509::Certificate object as client certificate
+    (This method is appeared in Michal Rokos's OpenSSL extention).
+
+: ca_file, ca_file=((|path|))
+    Sets path of a CA certification file in PEM format.
+    The file can contrain several CA certificats.
+
+: ca_path, ca_path=((|path|))
+    Sets path of a CA certification directory containing certifications
+    in PEM format.
+
+: verify_mode, verify_mode=((|mode|))
+    Sets the flags for server the certification verification at
+    begining of SSL/TLS session.
+    OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER is acceptable.
+
+: verify_callback, verify_callback=((|proc|))
+    Sets the verify callback for the server certification verification.
+
+: verify_depth, verify_depth=((|num|))
+    Sets the maximum depth for the certificate chain verification.
+
+: cert_store, cert_store=((|store|))
+    Sets the X509::Store to verify peer certificate.
+
+: ssl_timeout, ssl_timeout=((|sec|))
+    Sets the SSL timeout seconds.
+
+=end
+
+require 'net/http'
+require 'openssl'
+
+module Net
+
+  class HTTP
+    remove_method :use_ssl?
+    def use_ssl?
+      @use_ssl
+    end
+
+    # For backward compatibility.
+    alias use_ssl use_ssl?
+
+    # Turn on/off SSL.
+    # This flag must be set before starting session.
+    # If you change use_ssl value after session started,
+    # a Net::HTTP object raises IOError.
+    def use_ssl=(flag)
+      flag = (flag ? true : false)
+      raise IOError, "use_ssl value changed, but session already started" \
+          if started? and @use_ssl != flag
+      if flag and not @ssl_context
+        @ssl_context = OpenSSL::SSL::SSLContext.new
+      end
+      @use_ssl = flag
+    end
+
+    def self.ssl_context_accessor(name)
+      module_eval(<<-End, __FILE__, __LINE__ + 1)
+        def #{name}
+          return nil unless @ssl_context
+          @ssl_context.#{name}
+        end
+
+        def #{name}=(val)
+          @ssl_context ||= OpenSSL::SSL::SSLContext.new
+          @ssl_context.#{name} = val
+        end
+      End
+    end
+
+    ssl_context_accessor :key
+    ssl_context_accessor :cert
+    ssl_context_accessor :ca_file
+    ssl_context_accessor :ca_path
+    ssl_context_accessor :verify_mode
+    ssl_context_accessor :verify_callback
+    ssl_context_accessor :verify_depth
+    ssl_context_accessor :cert_store
+
+    def ssl_timeout
+      return nil unless @ssl_context
+      @ssl_context.timeout
+    end
+
+    def ssl_timeout=(sec)
+      raise ArgumentError, 'Net::HTTP#ssl_timeout= called but use_ssl=false' \
+          unless use_ssl?
+      @ssl_context ||= OpenSSL::SSL::SSLContext.new
+      @ssl_context.timeout = sec
+    end
+
+    # For backward compatibility
+    alias timeout= ssl_timeout=
+
+    def peer_cert
+      return nil if not use_ssl? or not @socket
+      @socket.io.peer_cert
+    end
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/imap.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/imap.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/imap.rb	(revision 18425)
@@ -0,0 +1,3366 @@
+#
+# = net/imap.rb
+#
+# Copyright (C) 2000  Shugo Maeda <shugo@ruby-lang.org>
+#
+# This library is distributed under the terms of the Ruby license.
+# You can freely distribute/modify this library.
+#
+# Documentation: Shugo Maeda, with RDoc conversion and overview by William
+# Webber.
+#
+# See Net::IMAP for documentation. 
+#
+
+
+require "socket"
+require "monitor"
+require "digest/md5"
+begin
+  require "openssl"
+rescue LoadError
+end
+
+module Net
+
+  #
+  # Net::IMAP implements Internet Message Access Protocol (IMAP) client
+  # functionality.  The protocol is described in [IMAP].
+  #
+  # == IMAP Overview
+  #
+  # An IMAP client connects to a server, and then authenticates
+  # itself using either #authenticate() or #login().  Having
+  # authenticated itself, there is a range of commands
+  # available to it.  Most work with mailboxes, which may be
+  # arranged in an hierarchical namespace, and each of which
+  # contains zero or more messages.  How this is implemented on
+  # the server is implementation-dependent; on a UNIX server, it
+  # will frequently be implemented as a files in mailbox format
+  # within a hierarchy of directories.
+  #
+  # To work on the messages within a mailbox, the client must
+  # first select that mailbox, using either #select() or (for
+  # read-only access) #examine().  Once the client has successfully
+  # selected a mailbox, they enter _selected_ state, and that
+  # mailbox becomes the _current_ mailbox, on which mail-item
+  # related commands implicitly operate.  
+  #
+  # Messages have two sorts of identifiers: message sequence
+  # numbers, and UIDs.  
+  #
+  # Message sequence numbers number messages within a mail box 
+  # from 1 up to the number of items in the mail box.  If new
+  # message arrives during a session, it receives a sequence
+  # number equal to the new size of the mail box.  If messages
+  # are expunged from the mailbox, remaining messages have their
+  # sequence numbers "shuffled down" to fill the gaps.
+  #
+  # UIDs, on the other hand, are permanently guaranteed not to
+  # identify another message within the same mailbox, even if 
+  # the existing message is deleted.  UIDs are required to
+  # be assigned in ascending (but not necessarily sequential)
+  # order within a mailbox; this means that if a non-IMAP client
+  # rearranges the order of mailitems within a mailbox, the
+  # UIDs have to be reassigned.  An IMAP client cannot thus
+  # rearrange message orders.
+  #
+  # == Examples of Usage
+  #
+  # === List sender and subject of all recent messages in the default mailbox
+  #
+  #   imap = Net::IMAP.new('mail.example.com')
+  #   imap.authenticate('LOGIN', 'joe_user', 'joes_password')
+  #   imap.examine('INBOX')
+  #   imap.search(["RECENT"]).each do |message_id|
+  #     envelope = imap.fetch(message_id, "ENVELOPE")[0].attr["ENVELOPE"]
+  #     puts "#{envelope.from[0].name}: \t#{envelope.subject}"
+  #   end
+  #
+  # === Move all messages from April 2003 from "Mail/sent-mail" to "Mail/sent-apr03"
+  #
+  #   imap = Net::IMAP.new('mail.example.com')
+  #   imap.authenticate('LOGIN', 'joe_user', 'joes_password')
+  #   imap.select('Mail/sent-mail')
+  #   if not imap.list('Mail/', 'sent-apr03')
+  #     imap.create('Mail/sent-apr03')
+  #   end
+  #   imap.search(["BEFORE", "30-Apr-2003", "SINCE", "1-Apr-2003"]).each do |message_id|
+  #     imap.copy(message_id, "Mail/sent-apr03")
+  #     imap.store(message_id, "+FLAGS", [:Deleted])
+  #   end
+  #   imap.expunge
+  # 
+  # == Thread Safety
+  #
+  # Net::IMAP supports concurrent threads. For example,
+  # 
+  #   imap = Net::IMAP.new("imap.foo.net", "imap2")
+  #   imap.authenticate("cram-md5", "bar", "password")
+  #   imap.select("inbox")
+  #   fetch_thread = Thread.start { imap.fetch(1..-1, "UID") }
+  #   search_result = imap.search(["BODY", "hello"])
+  #   fetch_result = fetch_thread.value
+  #   imap.disconnect
+  # 
+  # This script invokes the FETCH command and the SEARCH command concurrently.
+  #
+  # == Errors
+  #
+  # An IMAP server can send three different types of responses to indicate
+  # failure:
+  #
+  # NO:: the attempted command could not be successfully completed.  For
+  #      instance, the username/password used for logging in are incorrect;
+  #      the selected mailbox does not exists; etc.  
+  #
+  # BAD:: the request from the client does not follow the server's 
+  #       understanding of the IMAP protocol.  This includes attempting
+  #       commands from the wrong client state; for instance, attempting
+  #       to perform a SEARCH command without having SELECTed a current
+  #       mailbox.  It can also signal an internal server
+  #       failure (such as a disk crash) has occurred.
+  #
+  # BYE:: the server is saying goodbye.  This can be part of a normal
+  #       logout sequence, and can be used as part of a login sequence
+  #       to indicate that the server is (for some reason) unwilling
+  #       to accept our connection.  As a response to any other command,
+  #       it indicates either that the server is shutting down, or that
+  #       the server is timing out the client connection due to inactivity.
+  #
+  # These three error response are represented by the errors
+  # Net::IMAP::NoResponseError, Net::IMAP::BadResponseError, and
+  # Net::IMAP::ByeResponseError, all of which are subclasses of
+  # Net::IMAP::ResponseError.  Essentially, all methods that involve
+  # sending a request to the server can generate one of these errors.
+  # Only the most pertinent instances have been documented below.
+  #
+  # Because the IMAP class uses Sockets for communication, its methods
+  # are also susceptible to the various errors that can occur when
+  # working with sockets.  These are generally represented as
+  # Errno errors.  For instance, any method that involves sending a
+  # request to the server and/or receiving a response from it could
+  # raise an Errno::EPIPE error if the network connection unexpectedly
+  # goes down.  See the socket(7), ip(7), tcp(7), socket(2), connect(2),
+  # and associated man pages.
+  #
+  # Finally, a Net::IMAP::DataFormatError is thrown if low-level data
+  # is found to be in an incorrect format (for instance, when converting
+  # between UTF-8 and UTF-16), and Net::IMAP::ResponseParseError is 
+  # thrown if a server response is non-parseable. 
+  #
+  #
+  # == References
+  #
+  # [[IMAP]]
+  #    M. Crispin, "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1",
+  #    RFC 2060, December 1996.  (Note: since obsoleted by RFC 3501)
+  #
+  # [[LANGUAGE-TAGS]]
+  #    Alvestrand, H., "Tags for the Identification of
+  #    Languages", RFC 1766, March 1995.
+  #
+  # [[MD5]]
+  #    Myers, J., and M. Rose, "The Content-MD5 Header Field", RFC
+  #    1864, October 1995.
+  #
+  # [[MIME-IMB]]
+  #    Freed, N., and N. Borenstein, "MIME (Multipurpose Internet
+  #    Mail Extensions) Part One: Format of Internet Message Bodies", RFC
+  #    2045, November 1996.
+  #
+  # [[RFC-822]]
+  #    Crocker, D., "Standard for the Format of ARPA Internet Text
+  #    Messages", STD 11, RFC 822, University of Delaware, August 1982.
+  #
+  # [[RFC-2087]]
+  #    Myers, J., "IMAP4 QUOTA extension", RFC 2087, January 1997.
+  #
+  # [[RFC-2086]]
+  #    Myers, J., "IMAP4 ACL extension", RFC 2086, January 1997.
+  #
+  # [[RFC-2195]]
+  #    Klensin, J., Catoe, R., and Krumviede, P., "IMAP/POP AUTHorize Extension
+  #    for Simple Challenge/Response", RFC 2195, September 1997.
+  #
+  # [[SORT-THREAD-EXT]]
+  #    Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - SORT and THREAD
+  #    Extensions", draft-ietf-imapext-sort, May 2003.
+  #
+  # [[OSSL]]
+  #    http://www.openssl.org
+  #
+  # [[RSSL]]
+  #    http://savannah.gnu.org/projects/rubypki
+  #
+  # [[UTF7]]
+  #    Goldsmith, D. and Davis, M., "UTF-7: A Mail-Safe Transformation Format of
+  #    Unicode", RFC 2152, May 1997.
+  #
+  class IMAP
+    include MonitorMixin
+    if defined?(OpenSSL)
+      include OpenSSL
+      include SSL
+    end
+
+    #  Returns an initial greeting response from the server.
+    attr_reader :greeting
+
+    # Returns recorded untagged responses.  For example:
+    #
+    #   imap.select("inbox")
+    #   p imap.responses["EXISTS"][-1]
+    #   #=> 2
+    #   p imap.responses["UIDVALIDITY"][-1]
+    #   #=> 968263756
+    attr_reader :responses
+
+    # Returns all response handlers.
+    attr_reader :response_handlers
+
+    # The thread to receive exceptions.
+    attr_accessor :client_thread
+
+    # Flag indicating a message has been seen
+    SEEN = :Seen
+
+    # Flag indicating a message has been answered
+    ANSWERED = :Answered
+
+    # Flag indicating a message has been flagged for special or urgent
+    # attention
+    FLAGGED = :Flagged
+
+    # Flag indicating a message has been marked for deletion.  This
+    # will occur when the mailbox is closed or expunged.
+    DELETED = :Deleted
+
+    # Flag indicating a message is only a draft or work-in-progress version.
+    DRAFT = :Draft
+
+    # Flag indicating that the message is "recent", meaning that this
+    # session is the first session in which the client has been notified
+    # of this message.
+    RECENT = :Recent
+
+    # Flag indicating that a mailbox context name cannot contain
+    # children.
+    NOINFERIORS = :Noinferiors
+
+    # Flag indicating that a mailbox is not selected.
+    NOSELECT = :Noselect
+
+    # Flag indicating that a mailbox has been marked "interesting" by
+    # the server; this commonly indicates that the mailbox contains
+    # new messages.
+    MARKED = :Marked
+
+    # Flag indicating that the mailbox does not contains new messages.
+    UNMARKED = :Unmarked
+
+    # Returns the debug mode.
+    def self.debug
+      return @@debug
+    end
+
+    # Sets the debug mode.
+    def self.debug=(val)
+      return @@debug = val
+    end
+
+    # Adds an authenticator for Net::IMAP#authenticate.  +auth_type+
+    # is the type of authentication this authenticator supports
+    # (for instance, "LOGIN").  The +authenticator+ is an object
+    # which defines a process() method to handle authentication with
+    # the server.  See Net::IMAP::LoginAuthenticator and 
+    # Net::IMAP::CramMD5Authenticator for examples.
+    #
+    # If +auth_type+ refers to an existing authenticator, it will be
+    # replaced by the new one.
+    def self.add_authenticator(auth_type, authenticator)
+      @@authenticators[auth_type] = authenticator
+    end
+
+    # Disconnects from the server.
+    def disconnect
+      @sock.shutdown unless @usessl
+      @receiver_thread.join
+      @sock.close
+    end
+
+    # Returns true if disconnected from the server.
+    def disconnected?
+      return @sock.closed?
+    end
+
+    # Sends a CAPABILITY command, and returns an array of
+    # capabilities that the server supports.  Each capability
+    # is a string.  See [IMAP] for a list of possible
+    # capabilities.
+    #
+    # Note that the Net::IMAP class does not modify its
+    # behaviour according to the capabilities of the server;
+    # it is up to the user of the class to ensure that 
+    # a certain capability is supported by a server before
+    # using it.
+    def capability
+      synchronize do
+        send_command("CAPABILITY")
+        return @responses.delete("CAPABILITY")[-1]
+      end
+    end
+
+    # Sends a NOOP command to the server. It does nothing.
+    def noop
+      send_command("NOOP")
+    end
+
+    # Sends a LOGOUT command to inform the server that the client is
+    # done with the connection.
+    def logout
+      send_command("LOGOUT")
+    end
+
+    # Sends an AUTHENTICATE command to authenticate the client.
+    # The +auth_type+ parameter is a string that represents
+    # the authentication mechanism to be used. Currently Net::IMAP
+    # supports authentication mechanisms:
+    #
+    #   LOGIN:: login using cleartext user and password. 
+    #   CRAM-MD5:: login with cleartext user and encrypted password
+    #              (see [RFC-2195] for a full description).  This
+    #              mechanism requires that the server have the user's
+    #              password stored in clear-text password.
+    #
+    # For both these mechanisms, there should be two +args+: username
+    # and (cleartext) password.  A server may not support one or other
+    # of these mechanisms; check #capability() for a capability of
+    # the form "AUTH=LOGIN" or "AUTH=CRAM-MD5".
+    #
+    # Authentication is done using the appropriate authenticator object:
+    # see @@authenticators for more information on plugging in your own
+    # authenticator.
+    #
+    # For example:
+    #
+    #    imap.authenticate('LOGIN', user, password)
+    #
+    # A Net::IMAP::NoResponseError is raised if authentication fails.
+    def authenticate(auth_type, *args)
+      auth_type = auth_type.upcase
+      unless @@authenticators.has_key?(auth_type)
+        raise ArgumentError,
+          format('unknown auth type - "%s"', auth_type)
+      end
+      authenticator = @@authenticators[auth_type].new(*args)
+      send_command("AUTHENTICATE", auth_type) do |resp|
+        if resp.instance_of?(ContinuationRequest)
+          data = authenticator.process(resp.data.text.unpack("m")[0])
+          s = [data].pack("m").gsub(/\n/, "")
+          send_string_data(s)
+          put_string(CRLF)
+        end
+      end
+    end
+
+    # Sends a LOGIN command to identify the client and carries
+    # the plaintext +password+ authenticating this +user+.  Note
+    # that, unlike calling #authenticate() with an +auth_type+
+    # of "LOGIN", #login() does *not* use the login authenticator.
+    #
+    # A Net::IMAP::NoResponseError is raised if authentication fails.
+    def login(user, password)
+      send_command("LOGIN", user, password)
+    end
+
+    # Sends a SELECT command to select a +mailbox+ so that messages
+    # in the +mailbox+ can be accessed. 
+    #
+    # After you have selected a mailbox, you may retrieve the
+    # number of items in that mailbox from @responses["EXISTS"][-1],
+    # and the number of recent messages from @responses["RECENT"][-1].
+    # Note that these values can change if new messages arrive
+    # during a session; see #add_response_handler() for a way of
+    # detecting this event.
+    #
+    # A Net::IMAP::NoResponseError is raised if the mailbox does not
+    # exist or is for some reason non-selectable.
+    def select(mailbox)
+      synchronize do
+        @responses.clear
+        send_command("SELECT", mailbox)
+      end
+    end
+
+    # Sends a EXAMINE command to select a +mailbox+ so that messages
+    # in the +mailbox+ can be accessed.  Behaves the same as #select(),
+    # except that the selected +mailbox+ is identified as read-only.
+    #
+    # A Net::IMAP::NoResponseError is raised if the mailbox does not
+    # exist or is for some reason non-examinable.
+    def examine(mailbox)
+      synchronize do
+        @responses.clear
+        send_command("EXAMINE", mailbox)
+      end
+    end
+
+    # Sends a CREATE command to create a new +mailbox+.
+    #
+    # A Net::IMAP::NoResponseError is raised if a mailbox with that name
+    # cannot be created.
+    def create(mailbox)
+      send_command("CREATE", mailbox)
+    end
+
+    # Sends a DELETE command to remove the +mailbox+.
+    #
+    # A Net::IMAP::NoResponseError is raised if a mailbox with that name
+    # cannot be deleted, either because it does not exist or because the
+    # client does not have permission to delete it.
+    def delete(mailbox)
+      send_command("DELETE", mailbox)
+    end
+
+    # Sends a RENAME command to change the name of the +mailbox+ to
+    # +newname+.
+    #
+    # A Net::IMAP::NoResponseError is raised if a mailbox with the 
+    # name +mailbox+ cannot be renamed to +newname+ for whatever
+    # reason; for instance, because +mailbox+ does not exist, or
+    # because there is already a mailbox with the name +newname+.
+    def rename(mailbox, newname)
+      send_command("RENAME", mailbox, newname)
+    end
+
+    # Sends a SUBSCRIBE command to add the specified +mailbox+ name to
+    # the server's set of "active" or "subscribed" mailboxes as returned
+    # by #lsub().
+    #
+    # A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
+    # subscribed to, for instance because it does not exist.
+    def subscribe(mailbox)
+      send_command("SUBSCRIBE", mailbox)
+    end
+
+    # Sends a UNSUBSCRIBE command to remove the specified +mailbox+ name
+    # from the server's set of "active" or "subscribed" mailboxes.
+    #
+    # A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
+    # unsubscribed from, for instance because the client is not currently
+    # subscribed to it.
+    def unsubscribe(mailbox)
+      send_command("UNSUBSCRIBE", mailbox)
+    end
+
+    # Sends a LIST command, and returns a subset of names from
+    # the complete set of all names available to the client.
+    # +refname+ provides a context (for instance, a base directory
+    # in a directory-based mailbox hierarchy).  +mailbox+ specifies
+    # a mailbox or (via wildcards) mailboxes under that context.
+    # Two wildcards may be used in +mailbox+: '*', which matches
+    # all characters *including* the hierarchy delimiter (for instance,
+    # '/' on a UNIX-hosted directory-based mailbox hierarchy); and '%',
+    # which matches all characters *except* the hierarchy delimiter.
+    #
+    # If +refname+ is empty, +mailbox+ is used directly to determine
+    # which mailboxes to match.  If +mailbox+ is empty, the root
+    # name of +refname+ and the hierarchy delimiter are returned.
+    #
+    # The return value is an array of +Net::IMAP::MailboxList+. For example:
+    #
+    #   imap.create("foo/bar")
+    #   imap.create("foo/baz")
+    #   p imap.list("", "foo/%")
+    #   #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\ 
+    #        #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\ 
+    #        #<Net::IMAP::MailboxList attr=[:Noinferiors], delim="/", name="foo/baz">]
+    def list(refname, mailbox)
+      synchronize do
+        send_command("LIST", refname, mailbox)
+        return @responses.delete("LIST")
+      end
+    end
+
+    # Sends the GETQUOTAROOT command along with specified +mailbox+.
+    # This command is generally available to both admin and user.
+    # If mailbox exists, returns an array containing objects of
+    # Net::IMAP::MailboxQuotaRoot and Net::IMAP::MailboxQuota.
+    def getquotaroot(mailbox)
+      synchronize do
+        send_command("GETQUOTAROOT", mailbox)
+        result = []
+        result.concat(@responses.delete("QUOTAROOT"))
+        result.concat(@responses.delete("QUOTA"))
+        return result
+      end
+    end
+
+    # Sends the GETQUOTA command along with specified +mailbox+.
+    # If this mailbox exists, then an array containing a
+    # Net::IMAP::MailboxQuota object is returned.  This
+    # command generally is only available to server admin.
+    def getquota(mailbox)
+      synchronize do
+        send_command("GETQUOTA", mailbox)
+        return @responses.delete("QUOTA")
+      end
+    end
+
+    # Sends a SETQUOTA command along with the specified +mailbox+ and
+    # +quota+.  If +quota+ is nil, then quota will be unset for that
+    # mailbox.  Typically one needs to be logged in as server admin
+    # for this to work.  The IMAP quota commands are described in
+    # [RFC-2087].
+    def setquota(mailbox, quota)
+      if quota.nil?
+        data = '()'
+      else
+        data = '(STORAGE ' + quota.to_s + ')'
+      end
+      send_command("SETQUOTA", mailbox, RawData.new(data))
+    end
+
+    # Sends the SETACL command along with +mailbox+, +user+ and the
+    # +rights+ that user is to have on that mailbox.  If +rights+ is nil,
+    # then that user will be stripped of any rights to that mailbox.
+    # The IMAP ACL commands are described in [RFC-2086].
+    def setacl(mailbox, user, rights)
+      if rights.nil? 
+        send_command("SETACL", mailbox, user, "")
+      else
+        send_command("SETACL", mailbox, user, rights)
+      end
+    end
+
+    # Send the GETACL command along with specified +mailbox+.
+    # If this mailbox exists, an array containing objects of
+    # Net::IMAP::MailboxACLItem will be returned.
+    def getacl(mailbox)
+      synchronize do
+        send_command("GETACL", mailbox)
+        return @responses.delete("ACL")[-1]
+      end
+    end
+
+    # Sends a LSUB command, and returns a subset of names from the set
+    # of names that the user has declared as being "active" or
+    # "subscribed".  +refname+ and +mailbox+ are interpreted as 
+    # for #list().
+    # The return value is an array of +Net::IMAP::MailboxList+.
+    def lsub(refname, mailbox)
+      synchronize do
+        send_command("LSUB", refname, mailbox)
+        return @responses.delete("LSUB")
+      end
+    end
+
+    # Sends a STATUS command, and returns the status of the indicated
+    # +mailbox+. +attr+ is a list of one or more attributes that
+    # we are request the status of.  Supported attributes include:
+    #
+    #   MESSAGES:: the number of messages in the mailbox.
+    #   RECENT:: the number of recent messages in the mailbox.
+    #   UNSEEN:: the number of unseen messages in the mailbox.
+    #
+    # The return value is a hash of attributes. For example:
+    #
+    #   p imap.status("inbox", ["MESSAGES", "RECENT"])
+    #   #=> {"RECENT"=>0, "MESSAGES"=>44}
+    #
+    # A Net::IMAP::NoResponseError is raised if status values 
+    # for +mailbox+ cannot be returned, for instance because it
+    # does not exist.
+    def status(mailbox, attr)
+      synchronize do
+        send_command("STATUS", mailbox, attr)
+        return @responses.delete("STATUS")[-1].attr
+      end
+    end
+
+    # Sends a APPEND command to append the +message+ to the end of
+    # the +mailbox+. The optional +flags+ argument is an array of 
+    # flags to initially passing to the new message.  The optional
+    # +date_time+ argument specifies the creation time to assign to the 
+    # new message; it defaults to the current time.
+    # For example:
+    #
+    #   imap.append("inbox", <<EOF.gsub(/\n/, "\r\n"), [:Seen], Time.now)
+    #   Subject: hello
+    #   From: shugo@ruby-lang.org
+    #   To: shugo@ruby-lang.org
+    #   
+    #   hello world
+    #   EOF
+    #
+    # A Net::IMAP::NoResponseError is raised if the mailbox does
+    # not exist (it is not created automatically), or if the flags,
+    # date_time, or message arguments contain errors.
+    def append(mailbox, message, flags = nil, date_time = nil)
+      args = []
+      if flags
+        args.push(flags)
+      end
+      args.push(date_time) if date_time
+      args.push(Literal.new(message))
+      send_command("APPEND", mailbox, *args)
+    end
+
+    # Sends a CHECK command to request a checkpoint of the currently
+    # selected mailbox.  This performs implementation-specific
+    # housekeeping, for instance, reconciling the mailbox's 
+    # in-memory and on-disk state.
+    def check
+      send_command("CHECK")
+    end
+
+    # Sends a CLOSE command to close the currently selected mailbox.
+    # The CLOSE command permanently removes from the mailbox all
+    # messages that have the \Deleted flag set.
+    def close
+      send_command("CLOSE")
+    end
+
+    # Sends a EXPUNGE command to permanently remove from the currently
+    # selected mailbox all messages that have the \Deleted flag set.
+    def expunge
+      synchronize do
+        send_command("EXPUNGE")
+        return @responses.delete("EXPUNGE")
+      end
+    end
+
+    # Sends a SEARCH command to search the mailbox for messages that
+    # match the given searching criteria, and returns message sequence
+    # numbers.  +keys+ can either be a string holding the entire 
+    # search string, or a single-dimension array of search keywords and 
+    # arguments.  The following are some common search criteria;
+    # see [IMAP] section 6.4.4 for a full list.
+    #
+    # <message set>:: a set of message sequence numbers.  ',' indicates
+    #                 an interval, ':' indicates a range.  For instance,
+    #                 '2,10:12,15' means "2,10,11,12,15".
+    #
+    # BEFORE <date>:: messages with an internal date strictly before
+    #                 <date>.  The date argument has a format similar
+    #                 to 8-Aug-2002.
+    #
+    # BODY <string>:: messages that contain <string> within their body.
+    #
+    # CC <string>:: messages containing <string> in their CC field.
+    #
+    # FROM <string>:: messages that contain <string> in their FROM field.
+    #
+    # NEW:: messages with the \Recent, but not the \Seen, flag set.
+    #
+    # NOT <search-key>:: negate the following search key.
+    #
+    # OR <search-key> <search-key>:: "or" two search keys together.
+    #
+    # ON <date>:: messages with an internal date exactly equal to <date>, 
+    #             which has a format similar to 8-Aug-2002.
+    #
+    # SINCE <date>:: messages with an internal date on or after <date>.
+    #
+    # SUBJECT <string>:: messages with <string> in their subject.
+    #
+    # TO <string>:: messages with <string> in their TO field.
+    # 
+    # For example:
+    #
+    #   p imap.search(["SUBJECT", "hello", "NOT", "NEW"])
+    #   #=> [1, 6, 7, 8]
+    def search(keys, charset = nil)
+      return search_internal("SEARCH", keys, charset)
+    end
+
+    # As for #search(), but returns unique identifiers.
+    def uid_search(keys, charset = nil)
+      return search_internal("UID SEARCH", keys, charset)
+    end
+
+    # Sends a FETCH command to retrieve data associated with a message
+    # in the mailbox. The +set+ parameter is a number or an array of
+    # numbers or a Range object. The number is a message sequence
+    # number.  +attr+ is a list of attributes to fetch; see the
+    # documentation for Net::IMAP::FetchData for a list of valid
+    # attributes.
+    # The return value is an array of Net::IMAP::FetchData. For example:
+    #
+    #   p imap.fetch(6..8, "UID")
+    #   #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\ 
+    #        #<Net::IMAP::FetchData seqno=7, attr={"UID"=>99}>, \\ 
+    #        #<Net::IMAP::FetchData seqno=8, attr={"UID"=>100}>]
+    #   p imap.fetch(6, "BODY[HEADER.FIELDS (SUBJECT)]")
+    #   #=> [#<Net::IMAP::FetchData seqno=6, attr={"BODY[HEADER.FIELDS (SUBJECT)]"=>"Subject: test\r\n\r\n"}>]
+    #   data = imap.uid_fetch(98, ["RFC822.SIZE", "INTERNALDATE"])[0]
+    #   p data.seqno
+    #   #=> 6
+    #   p data.attr["RFC822.SIZE"]
+    #   #=> 611
+    #   p data.attr["INTERNALDATE"]
+    #   #=> "12-Oct-2000 22:40:59 +0900"
+    #   p data.attr["UID"]
+    #   #=> 98
+    def fetch(set, attr)
+      return fetch_internal("FETCH", set, attr)
+    end
+
+    # As for #fetch(), but +set+ contains unique identifiers.
+    def uid_fetch(set, attr)
+      return fetch_internal("UID FETCH", set, attr)
+    end
+
+    # Sends a STORE command to alter data associated with messages
+    # in the mailbox, in particular their flags. The +set+ parameter 
+    # is a number or an array of numbers or a Range object. Each number 
+    # is a message sequence number.  +attr+ is the name of a data item 
+    # to store: 'FLAGS' means to replace the message's flag list
+    # with the provided one; '+FLAGS' means to add the provided flags;
+    # and '-FLAGS' means to remove them.  +flags+ is a list of flags.
+    #
+    # The return value is an array of Net::IMAP::FetchData. For example:
+    #
+    #   p imap.store(6..8, "+FLAGS", [:Deleted])
+    #   #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\ 
+    #        #<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\  
+    #        #<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
+    def store(set, attr, flags)
+      return store_internal("STORE", set, attr, flags)
+    end
+
+    # As for #store(), but +set+ contains unique identifiers.
+    def uid_store(set, attr, flags)
+      return store_internal("UID STORE", set, attr, flags)
+    end
+
+    # Sends a COPY command to copy the specified message(s) to the end
+    # of the specified destination +mailbox+. The +set+ parameter is
+    # a number or an array of numbers or a Range object. The number is
+    # a message sequence number.
+    def copy(set, mailbox)
+      copy_internal("COPY", set, mailbox)
+    end
+
+    # As for #copy(), but +set+ contains unique identifiers.
+    def uid_copy(set, mailbox)
+      copy_internal("UID COPY", set, mailbox)
+    end
+
+    # Sends a SORT command to sort messages in the mailbox.
+    # Returns an array of message sequence numbers. For example:
+    #
+    #   p imap.sort(["FROM"], ["ALL"], "US-ASCII")
+    #   #=> [1, 2, 3, 5, 6, 7, 8, 4, 9]
+    #   p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII")
+    #   #=> [6, 7, 8, 1]
+    #
+    # See [SORT-THREAD-EXT] for more details.
+    def sort(sort_keys, search_keys, charset)
+      return sort_internal("SORT", sort_keys, search_keys, charset)
+    end
+
+    # As for #sort(), but returns an array of unique identifiers.
+    def uid_sort(sort_keys, search_keys, charset)
+      return sort_internal("UID SORT", sort_keys, search_keys, charset)
+    end
+
+    # Adds a response handler. For example, to detect when 
+    # the server sends us a new EXISTS response (which normally
+    # indicates new messages being added to the mail box), 
+    # you could add the following handler after selecting the
+    # mailbox.
+    #
+    #   imap.add_response_handler { |resp|
+    #     if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS"
+    #       puts "Mailbox now has #{resp.data} messages"
+    #     end
+    #   }
+    #
+    def add_response_handler(handler = Proc.new)
+      @response_handlers.push(handler)
+    end
+
+    # Removes the response handler.
+    def remove_response_handler(handler)
+      @response_handlers.delete(handler)
+    end
+
+    # As for #search(), but returns message sequence numbers in threaded
+    # format, as a Net::IMAP::ThreadMember tree.  The supported algorithms
+    # are:
+    #
+    # ORDEREDSUBJECT:: split into single-level threads according to subject,
+    #                  ordered by date.
+    # REFERENCES:: split into threads by parent/child relationships determined
+    #              by which message is a reply to which.
+    #
+    # Unlike #search(), +charset+ is a required argument.  US-ASCII
+    # and UTF-8 are sample values.
+    #
+    # See [SORT-THREAD-EXT] for more details.
+    def thread(algorithm, search_keys, charset)
+      return thread_internal("THREAD", algorithm, search_keys, charset)
+    end
+
+    # As for #thread(), but returns unique identifiers instead of 
+    # message sequence numbers.
+    def uid_thread(algorithm, search_keys, charset)
+      return thread_internal("UID THREAD", algorithm, search_keys, charset)
+    end
+
+    # Decode a string from modified UTF-7 format to UTF-8.
+    #
+    # UTF-7 is a 7-bit encoding of Unicode [UTF7].  IMAP uses a
+    # slightly modified version of this to encode mailbox names
+    # containing non-ASCII characters; see [IMAP] section 5.1.3.
+    #
+    # Net::IMAP does _not_ automatically encode and decode
+    # mailbox names to and from utf7.
+    def self.decode_utf7(s)
+      return s.gsub(/&(.*?)-/n) {
+        if $1.empty?
+          "&"
+        else
+          base64 = $1.tr(",", "/")
+          x = base64.length % 4
+          if x > 0
+            base64.concat("=" * (4 - x))
+          end
+          u16tou8(base64.unpack("m")[0])
+        end
+      }
+    end
+
+    # Encode a string from UTF-8 format to modified UTF-7.
+    def self.encode_utf7(s)
+      return s.gsub(/(&)|([^\x20-\x25\x27-\x7e]+)/n) { |x|
+        if $1
+          "&-"
+        else
+          base64 = [u8tou16(x)].pack("m")
+          "&" + base64.delete("=\n").tr("/", ",") + "-"
+        end
+      }
+    end
+
+    private
+
+    CRLF = "\r\n"      # :nodoc:
+    PORT = 143         # :nodoc:
+
+    @@debug = false
+    @@authenticators = {}
+
+    # Creates a new Net::IMAP object and connects it to the specified
+    # +port+ (143 by default) on the named +host+.  If +usessl+ is true, 
+    # then an attempt will
+    # be made to use SSL (now TLS) to connect to the server.  For this
+    # to work OpenSSL [OSSL] and the Ruby OpenSSL [RSSL]
+    # extensions need to be installed.  The +certs+ parameter indicates
+    # the path or file containing the CA cert of the server, and the
+    # +verify+ parameter is for the OpenSSL verification callback.
+    #
+    # The most common errors are:
+    #
+    # Errno::ECONNREFUSED:: connection refused by +host+ or an intervening
+    #                       firewall.
+    # Errno::ETIMEDOUT:: connection timed out (possibly due to packets
+    #                    being dropped by an intervening firewall).
+    # Errno::ENETUNREACH:: there is no route to that network.
+    # SocketError:: hostname not known or other socket error.
+    # Net::IMAP::ByeResponseError:: we connected to the host, but they 
+    #                               immediately said goodbye to us.
+    def initialize(host, port = PORT, usessl = false, certs = nil, verify = false)
+      super()
+      @host = host
+      @port = port
+      @tag_prefix = "RUBY"
+      @tagno = 0
+      @parser = ResponseParser.new
+      @sock = TCPSocket.open(host, port)
+      if usessl
+        unless defined?(OpenSSL)
+          raise "SSL extension not installed"
+        end
+        @usessl = true
+
+        # verify the server.
+        context = SSLContext::new()
+        context.ca_file = certs if certs && FileTest::file?(certs)
+        context.ca_path = certs if certs && FileTest::directory?(certs)
+        context.verify_mode = VERIFY_PEER if verify
+        if defined?(VerifyCallbackProc)
+          context.verify_callback = VerifyCallbackProc 
+        end
+        @sock = SSLSocket.new(@sock, context)
+        @sock.connect   # start ssl session.
+      else
+        @usessl = false
+      end
+      @responses = Hash.new([].freeze)
+      @tagged_responses = {}
+      @response_handlers = []
+      @response_arrival = new_cond
+      @continuation_request = nil
+      @logout_command_tag = nil
+      @debug_output_bol = true
+
+      @greeting = get_response
+      if @greeting.name == "BYE"
+        @sock.close
+        raise ByeResponseError, @greeting.raw_data
+      end
+
+      @client_thread = Thread.current
+      @receiver_thread = Thread.start {
+        receive_responses
+      }
+    end
+
+    def receive_responses
+      while true
+        begin
+          resp = get_response
+        rescue Exception
+          @sock.close
+          @client_thread.raise($!)
+          break
+        end
+        break unless resp
+        begin
+          synchronize do
+            case resp
+            when TaggedResponse
+              @tagged_responses[resp.tag] = resp
+              @response_arrival.broadcast
+              if resp.tag == @logout_command_tag
+                return
+              end
+            when UntaggedResponse
+              record_response(resp.name, resp.data)
+              if resp.data.instance_of?(ResponseText) &&
+                  (code = resp.data.code)
+                record_response(code.name, code.data)
+              end
+              if resp.name == "BYE" && @logout_command_tag.nil?
+                @sock.close
+                raise ByeResponseError, resp.raw_data
+              end
+            when ContinuationRequest
+              @continuation_request = resp
+              @response_arrival.broadcast
+            end
+            @response_handlers.each do |handler|
+              handler.call(resp)
+            end
+          end
+        rescue Exception
+          @client_thread.raise($!)
+        end
+      end
+    end
+
+    def get_tagged_response(tag)
+      until @tagged_responses.key?(tag)
+        @response_arrival.wait
+      end
+      return pick_up_tagged_response(tag)
+    end
+
+    def pick_up_tagged_response(tag)
+      resp = @tagged_responses.delete(tag)
+      case resp.name
+      when /\A(?:NO)\z/ni
+        raise NoResponseError, resp.data.text
+      when /\A(?:BAD)\z/ni
+        raise BadResponseError, resp.data.text
+      else
+        return resp
+      end
+    end
+
+    def get_response
+      buff = ""
+      while true
+        s = @sock.gets(CRLF)
+        break unless s
+        buff.concat(s)
+        if /\{(\d+)\}\r\n/n =~ s
+          s = @sock.read($1.to_i)
+          buff.concat(s)
+        else
+          break
+        end
+      end
+      return nil if buff.length == 0
+      if @@debug
+        $stderr.print(buff.gsub(/^/n, "S: "))
+      end
+      return @parser.parse(buff)
+    end
+
+    def record_response(name, data)
+      unless @responses.has_key?(name)
+        @responses[name] = []
+      end
+      @responses[name].push(data)
+    end
+
+    def send_command(cmd, *args, &block)
+      synchronize do
+        tag = Thread.current[:net_imap_tag] = generate_tag
+        put_string(tag + " " + cmd)
+        args.each do |i|
+          put_string(" ")
+          send_data(i)
+        end
+        put_string(CRLF)
+        if cmd == "LOGOUT"
+          @logout_command_tag = tag
+        end
+        if block
+          add_response_handler(block)
+        end
+        begin
+          return get_tagged_response(tag)
+        ensure
+          if block
+            remove_response_handler(block)
+          end
+        end
+      end
+    end
+
+    def generate_tag
+      @tagno += 1
+      return format("%s%04d", @tag_prefix, @tagno)
+    end
+    
+    def put_string(str)
+      @sock.print(str)
+      if @@debug
+        if @debug_output_bol
+          $stderr.print("C: ")
+        end
+        $stderr.print(str.gsub(/\n(?!\z)/n, "\nC: "))
+        if /\r\n\z/n.match(str)
+          @debug_output_bol = true
+        else
+          @debug_output_bol = false
+        end
+      end
+    end
+
+    def send_data(data)
+      case data
+      when nil
+        put_string("NIL")
+      when String
+        send_string_data(data)
+      when Integer
+        send_number_data(data)
+      when Array
+        send_list_data(data)
+      when Time
+        send_time_data(data)
+      when Symbol
+        send_symbol_data(data)
+      else
+        data.send_data(self)
+      end
+    end
+
+    def send_string_data(str)
+      case str
+      when ""
+        put_string('""')
+      when /[\x80-\xff\r\n]/n
+        # literal
+        send_literal(str)
+      when /[(){ \x00-\x1f\x7f%*"\\]/n
+        # quoted string
+        send_quoted_string(str)
+      else
+        put_string(str)
+      end
+    end
+    
+    def send_quoted_string(str)
+      put_string('"' + str.gsub(/["\\]/n, "\\\\\\&") + '"')
+    end
+
+    def send_literal(str)
+      put_string("{" + str.length.to_s + "}" + CRLF)
+      while @continuation_request.nil? &&
+        !@tagged_responses.key?(Thread.current[:net_imap_tag])
+        @response_arrival.wait
+      end
+      if @continuation_request.nil?
+        pick_up_tagged_response(Thread.current[:net_imap_tag])
+        raise ResponseError.new("expected continuation request")
+      end
+      @continuation_request = nil
+      put_string(str)
+    end
+
+    def send_number_data(num)
+      if num < 0 || num >= 4294967296
+        raise DataFormatError, num.to_s
+      end
+      put_string(num.to_s)
+    end
+
+    def send_list_data(list)
+      put_string("(")
+      first = true
+      list.each do |i|
+        if first
+          first = false
+        else
+          put_string(" ")
+        end
+        send_data(i)
+      end
+      put_string(")")
+    end
+
+    DATE_MONTH = %w(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
+
+    def send_time_data(time)
+      t = time.dup.gmtime
+      s = format('"%2d-%3s-%4d %02d:%02d:%02d +0000"',
+                 t.day, DATE_MONTH[t.month - 1], t.year,
+                 t.hour, t.min, t.sec)
+      put_string(s)
+    end
+
+    def send_symbol_data(symbol)
+      put_string("\\" + symbol.to_s)
+    end
+
+    def search_internal(cmd, keys, charset)
+      if keys.instance_of?(String)
+        keys = [RawData.new(keys)]
+      else
+        normalize_searching_criteria(keys)
+      end
+      synchronize do
+        if charset
+          send_command(cmd, "CHARSET", charset, *keys)
+        else
+          send_command(cmd, *keys)
+        end
+        return @responses.delete("SEARCH")[-1]
+      end
+    end
+
+    def fetch_internal(cmd, set, attr)
+      if attr.instance_of?(String)
+        attr = RawData.new(attr)
+      end
+      synchronize do
+        @responses.delete("FETCH")
+        send_command(cmd, MessageSet.new(set), attr)
+        return @responses.delete("FETCH")
+      end
+    end
+
+    def store_internal(cmd, set, attr, flags)
+      if attr.instance_of?(String)
+        attr = RawData.new(attr)
+      end
+      synchronize do
+        @responses.delete("FETCH")
+        send_command(cmd, MessageSet.new(set), attr, flags)
+        return @responses.delete("FETCH")
+      end
+    end
+
+    def copy_internal(cmd, set, mailbox)
+      send_command(cmd, MessageSet.new(set), mailbox)
+    end
+
+    def sort_internal(cmd, sort_keys, search_keys, charset)
+      if search_keys.instance_of?(String)
+        search_keys = [RawData.new(search_keys)]
+      else
+        normalize_searching_criteria(search_keys)
+      end
+      normalize_searching_criteria(search_keys)
+      synchronize do
+        send_command(cmd, sort_keys, charset, *search_keys)
+        return @responses.delete("SORT")[-1]
+      end
+    end
+
+    def thread_internal(cmd, algorithm, search_keys, charset)
+      if search_keys.instance_of?(String)
+        search_keys = [RawData.new(search_keys)]
+      else
+        normalize_searching_criteria(search_keys)
+      end
+      normalize_searching_criteria(search_keys)
+      send_command(cmd, algorithm, charset, *search_keys)
+      return @responses.delete("THREAD")[-1]
+    end
+
+    def normalize_searching_criteria(keys)
+      keys.collect! do |i|
+        case i
+        when -1, Range, Array
+          MessageSet.new(i)
+        else
+          i
+        end
+      end
+    end
+
+    def self.u16tou8(s)
+      len = s.length
+      if len < 2
+        return ""
+      end
+      buf = ""
+      i = 0
+      while i < len
+        c = s[i] << 8 | s[i + 1]
+        i += 2
+        if c == 0xfeff
+          next
+        elsif c < 0x0080
+          buf.concat(c)
+        elsif c < 0x0800
+          b2 = c & 0x003f
+          b1 = c >> 6
+          buf.concat(b1 | 0xc0)
+          buf.concat(b2 | 0x80)
+        elsif c >= 0xdc00 && c < 0xe000
+          raise DataFormatError, "invalid surrogate detected"
+        elsif c >= 0xd800 && c < 0xdc00
+          if i + 2 > len
+            raise DataFormatError, "invalid surrogate detected"
+          end
+          low = s[i] << 8 | s[i + 1]
+          i += 2
+          if low < 0xdc00 || low > 0xdfff
+            raise DataFormatError, "invalid surrogate detected"
+          end
+          c = (((c & 0x03ff)) << 10 | (low & 0x03ff)) + 0x10000
+          b4 = c & 0x003f
+          b3 = (c >> 6) & 0x003f
+          b2 = (c >> 12) & 0x003f
+          b1 = c >> 18;
+          buf.concat(b1 | 0xf0)
+          buf.concat(b2 | 0x80)
+          buf.concat(b3 | 0x80)
+          buf.concat(b4 | 0x80)
+        else # 0x0800-0xffff
+          b3 = c & 0x003f
+          b2 = (c >> 6) & 0x003f
+          b1 = c >> 12
+          buf.concat(b1 | 0xe0)
+          buf.concat(b2 | 0x80)
+          buf.concat(b3 | 0x80)
+        end
+      end
+      return buf
+    end
+    private_class_method :u16tou8
+
+    def self.u8tou16(s)
+      len = s.length
+      buf = ""
+      i = 0
+      while i < len
+        c = s[i]
+        if (c & 0x80) == 0
+          buf.concat(0x00)
+          buf.concat(c)
+          i += 1
+        elsif (c & 0xe0) == 0xc0 &&
+            len >= 2 &&
+            (s[i + 1] & 0xc0) == 0x80
+          if c == 0xc0 || c == 0xc1
+            raise DataFormatError, format("non-shortest UTF-8 sequence (%02x)", c)
+          end
+          u = ((c & 0x1f) << 6) | (s[i + 1] & 0x3f)
+          buf.concat(u >> 8)
+          buf.concat(u & 0x00ff)
+          i += 2
+        elsif (c & 0xf0) == 0xe0 &&
+            i + 2 < len &&
+            (s[i + 1] & 0xc0) == 0x80 &&
+            (s[i + 2] & 0xc0) == 0x80
+          if c == 0xe0 && s[i + 1] < 0xa0
+            raise DataFormatError, format("non-shortest UTF-8 sequence (%02x)", c)
+          end
+          u = ((c & 0x0f) << 12) | ((s[i + 1] & 0x3f) << 6) | (s[i + 2] & 0x3f)
+          # surrogate chars
+          if u >= 0xd800 && u <= 0xdfff
+            raise DataFormatError, format("none-UTF-16 char detected (%04x)", u)
+          end
+          buf.concat(u >> 8)
+          buf.concat(u & 0x00ff)
+          i += 3
+        elsif (c & 0xf8) == 0xf0 &&
+            i + 3 < len &&
+            (s[i + 1] & 0xc0) == 0x80 &&
+            (s[i + 2] & 0xc0) == 0x80 &&
+            (s[i + 3] & 0xc0) == 0x80
+          if c == 0xf0 && s[i + 1] < 0x90
+            raise DataFormatError, format("non-shortest UTF-8 sequence (%02x)", c)
+          end
+          u = ((c & 0x07) << 18) | ((s[i + 1] & 0x3f) << 12) |
+            ((s[i + 2] & 0x3f) << 6) | (s[i + 3] & 0x3f)
+          if u < 0x10000
+            buf.concat(u >> 8)
+            buf.concat(u & 0x00ff)
+          elsif u < 0x110000
+            high = ((u - 0x10000) >> 10) | 0xd800
+            low = (u & 0x03ff) | 0xdc00
+            buf.concat(high >> 8)
+            buf.concat(high & 0x00ff)
+            buf.concat(low >> 8)
+            buf.concat(low & 0x00ff)
+          else
+            raise DataFormatError, format("none-UTF-16 char detected (%04x)", u)
+          end
+          i += 4
+        else
+          raise DataFormatError, format("illegal UTF-8 sequence (%02x)", c)
+        end
+      end
+      return buf
+    end
+    private_class_method :u8tou16
+
+    class RawData # :nodoc:
+      def send_data(imap)
+        imap.send(:put_string, @data)
+      end
+
+      private
+
+      def initialize(data)
+        @data = data
+      end
+    end
+
+    class Atom # :nodoc:
+      def send_data(imap)
+        imap.send(:put_string, @data)
+      end
+
+      private
+
+      def initialize(data)
+        @data = data
+      end
+    end
+
+    class QuotedString # :nodoc:
+      def send_data(imap)
+        imap.send(:send_quoted_string, @data)
+      end
+
+      private
+
+      def initialize(data)
+        @data = data
+      end
+    end
+
+    class Literal # :nodoc:
+      def send_data(imap)
+        imap.send(:send_literal, @data)
+      end
+
+      private
+
+      def initialize(data)
+        @data = data
+      end
+    end
+
+    class MessageSet # :nodoc:
+      def send_data(imap)
+        imap.send(:put_string, format_internal(@data))
+      end
+
+      private
+
+      def initialize(data)
+        @data = data
+      end
+
+      def format_internal(data)
+        case data
+        when "*"
+          return data
+        when Integer
+          ensure_nz_number(data)
+          if data == -1
+            return "*"
+          else
+            return data.to_s
+          end
+        when Range
+          return format_internal(data.first) +
+            ":" + format_internal(data.last)
+        when Array
+          return data.collect {|i| format_internal(i)}.join(",")
+        when ThreadMember
+          return data.seqno.to_s +
+            ":" + data.children.collect {|i| format_internal(i).join(",")}
+        else
+          raise DataFormatError, data.inspect
+        end
+      end
+
+      def ensure_nz_number(num)
+        if num < -1 || num == 0 || num >= 4294967296
+          msg = "nz_number must be non-zero unsigned 32-bit integer: " +
+                num.inspect
+          raise DataFormatError, msg
+        end
+      end
+    end
+
+    # Net::IMAP::ContinuationRequest represents command continuation requests.
+    # 
+    # The command continuation request response is indicated by a "+" token
+    # instead of a tag.  This form of response indicates that the server is
+    # ready to accept the continuation of a command from the client.  The
+    # remainder of this response is a line of text.
+    # 
+    #   continue_req    ::= "+" SPACE (resp_text / base64)
+    # 
+    # ==== Fields:
+    # 
+    # data:: Returns the data (Net::IMAP::ResponseText).
+    # 
+    # raw_data:: Returns the raw data string.
+    ContinuationRequest = Struct.new(:data, :raw_data)
+
+    # Net::IMAP::UntaggedResponse represents untagged responses.
+    # 
+    # Data transmitted by the server to the client and status responses
+    # that do not indicate command completion are prefixed with the token
+    # "*", and are called untagged responses.
+    # 
+    #   response_data   ::= "*" SPACE (resp_cond_state / resp_cond_bye /
+    #                       mailbox_data / message_data / capability_data)
+    # 
+    # ==== Fields:
+    # 
+    # name:: Returns the name such as "FLAGS", "LIST", "FETCH"....
+    # 
+    # data:: Returns the data such as an array of flag symbols,
+    #         a ((<Net::IMAP::MailboxList>)) object....
+    # 
+    # raw_data:: Returns the raw data string.
+    UntaggedResponse = Struct.new(:name, :data, :raw_data)
+     
+    # Net::IMAP::TaggedResponse represents tagged responses.
+    # 
+    # The server completion result response indicates the success or
+    # failure of the operation.  It is tagged with the same tag as the
+    # client command which began the operation.
+    # 
+    #   response_tagged ::= tag SPACE resp_cond_state CRLF
+    #   
+    #   tag             ::= 1*<any ATOM_CHAR except "+">
+    #   
+    #   resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text
+    # 
+    # ==== Fields:
+    # 
+    # tag:: Returns the tag.
+    # 
+    # name:: Returns the name. the name is one of "OK", "NO", "BAD".
+    # 
+    # data:: Returns the data. See ((<Net::IMAP::ResponseText>)).
+    # 
+    # raw_data:: Returns the raw data string.
+    #
+    TaggedResponse = Struct.new(:tag, :name, :data, :raw_data)
+     
+    # Net::IMAP::ResponseText represents texts of responses.
+    # The text may be prefixed by the response code.
+    # 
+    #   resp_text       ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
+    #                       ;; text SHOULD NOT begin with "[" or "="
+    # 
+    # ==== Fields:
+    # 
+    # code:: Returns the response code. See ((<Net::IMAP::ResponseCode>)).
+    #       
+    # text:: Returns the text.
+    # 
+    ResponseText = Struct.new(:code, :text)
+
+    # 
+    # Net::IMAP::ResponseCode represents response codes.
+    # 
+    #   resp_text_code  ::= "ALERT" / "PARSE" /
+    #                       "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" /
+    #                       "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
+    #                       "UIDVALIDITY" SPACE nz_number /
+    #                       "UNSEEN" SPACE nz_number /
+    #                       atom [SPACE 1*<any TEXT_CHAR except "]">]
+    # 
+    # ==== Fields:
+    # 
+    # name:: Returns the name such as "ALERT", "PERMANENTFLAGS", "UIDVALIDITY"....
+    # 
+    # data:: Returns the data if it exists.
+    #
+    ResponseCode = Struct.new(:name, :data)
+
+    # Net::IMAP::MailboxList represents contents of the LIST response.
+    # 
+    #   mailbox_list    ::= "(" #("\Marked" / "\Noinferiors" /
+    #                       "\Noselect" / "\Unmarked" / flag_extension) ")"
+    #                       SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox
+    # 
+    # ==== Fields:
+    # 
+    # attr:: Returns the name attributes. Each name attribute is a symbol
+    #        capitalized by String#capitalize, such as :Noselect (not :NoSelect).
+    # 
+    # delim:: Returns the hierarchy delimiter
+    # 
+    # name:: Returns the mailbox name.
+    #
+    MailboxList = Struct.new(:attr, :delim, :name)
+
+    # Net::IMAP::MailboxQuota represents contents of GETQUOTA response.
+    # This object can also be a response to GETQUOTAROOT.  In the syntax
+    # specification below, the delimiter used with the "#" construct is a
+    # single space (SPACE).
+    # 
+    #    quota_list      ::= "(" #quota_resource ")"
+    # 
+    #    quota_resource  ::= atom SPACE number SPACE number
+    # 
+    #    quota_response  ::= "QUOTA" SPACE astring SPACE quota_list
+    # 
+    # ==== Fields:
+    # 
+    # mailbox:: The mailbox with the associated quota.
+    # 
+    # usage:: Current storage usage of mailbox.
+    # 
+    # quota:: Quota limit imposed on mailbox.
+    #
+    MailboxQuota = Struct.new(:mailbox, :usage, :quota)
+
+    # Net::IMAP::MailboxQuotaRoot represents part of the GETQUOTAROOT
+    # response. (GETQUOTAROOT can also return Net::IMAP::MailboxQuota.)
+    # 
+    #    quotaroot_response ::= "QUOTAROOT" SPACE astring *(SPACE astring)
+    # 
+    # ==== Fields:
+    # 
+    # mailbox:: The mailbox with the associated quota.
+    # 
+    # quotaroots:: Zero or more quotaroots that effect the quota on the
+    #              specified mailbox.
+    #
+    MailboxQuotaRoot = Struct.new(:mailbox, :quotaroots)
+
+    # Net::IMAP::MailboxACLItem represents response from GETACL.
+    # 
+    #    acl_data        ::= "ACL" SPACE mailbox *(SPACE identifier SPACE rights)
+    # 
+    #    identifier      ::= astring
+    # 
+    #    rights          ::= astring
+    # 
+    # ==== Fields:
+    # 
+    # user:: Login name that has certain rights to the mailbox
+    #        that was specified with the getacl command.
+    # 
+    # rights:: The access rights the indicated user has to the
+    #          mailbox.
+    #
+    MailboxACLItem = Struct.new(:user, :rights)
+
+    # Net::IMAP::StatusData represents contents of the STATUS response.
+    # 
+    # ==== Fields:
+    # 
+    # mailbox:: Returns the mailbox name.
+    # 
+    # attr:: Returns a hash. Each key is one of "MESSAGES", "RECENT", "UIDNEXT",
+    #        "UIDVALIDITY", "UNSEEN". Each value is a number.
+    # 
+    StatusData = Struct.new(:mailbox, :attr)
+
+    # Net::IMAP::FetchData represents contents of the FETCH response.
+    # 
+    # ==== Fields:
+    # 
+    # seqno:: Returns the message sequence number.
+    #         (Note: not the unique identifier, even for the UID command response.)
+    # 
+    # attr:: Returns a hash. Each key is a data item name, and each value is
+    #        its value.
+    # 
+    #        The current data items are:
+    # 
+    #        [BODY]
+    #           A form of BODYSTRUCTURE without extension data.
+    #        [BODY[<section>]<<origin_octet>>]
+    #           A string expressing the body contents of the specified section.
+    #        [BODYSTRUCTURE]
+    #           An object that describes the [MIME-IMB] body structure of a message.
+    #           See Net::IMAP::BodyTypeBasic, Net::IMAP::BodyTypeText,
+    #           Net::IMAP::BodyTypeMessage, Net::IMAP::BodyTypeMultipart.
+    #        [ENVELOPE]
+    #           A Net::IMAP::Envelope object that describes the envelope
+    #           structure of a message.
+    #        [FLAGS]
+    #           A array of flag symbols that are set for this message. flag symbols
+    #           are capitalized by String#capitalize.
+    #        [INTERNALDATE]
+    #           A string representing the internal date of the message.
+    #        [RFC822]
+    #           Equivalent to BODY[].
+    #        [RFC822.HEADER]
+    #           Equivalent to BODY.PEEK[HEADER].
+    #        [RFC822.SIZE]
+    #           A number expressing the [RFC-822] size of the message.
+    #        [RFC822.TEXT]
+    #           Equivalent to BODY[TEXT].
+    #        [UID]
+    #           A number expressing the unique identifier of the message.
+    # 
+    FetchData = Struct.new(:seqno, :attr)
+
+    # Net::IMAP::Envelope represents envelope structures of messages.
+    # 
+    # ==== Fields:
+    # 
+    # date:: Returns a string that represents the date.
+    # 
+    # subject:: Returns a string that represents the subject.
+    # 
+    # from:: Returns an array of Net::IMAP::Address that represents the from.
+    # 
+    # sender:: Returns an array of Net::IMAP::Address that represents the sender.
+    # 
+    # reply_to:: Returns an array of Net::IMAP::Address that represents the reply-to.
+    # 
+    # to:: Returns an array of Net::IMAP::Address that represents the to.
+    # 
+    # cc:: Returns an array of Net::IMAP::Address that represents the cc.
+    # 
+    # bcc:: Returns an array of Net::IMAP::Address that represents the bcc.
+    # 
+    # in_reply_to:: Returns a string that represents the in-reply-to.
+    # 
+    # message_id:: Returns a string that represents the message-id.
+    # 
+    Envelope = Struct.new(:date, :subject, :from, :sender, :reply_to,
+                          :to, :cc, :bcc, :in_reply_to, :message_id)
+
+    # 
+    # Net::IMAP::Address represents electronic mail addresses.
+    # 
+    # ==== Fields:
+    # 
+    # name:: Returns the phrase from [RFC-822] mailbox.
+    # 
+    # route:: Returns the route from [RFC-822] route-addr.
+    # 
+    # mailbox:: nil indicates end of [RFC-822] group.
+    #           If non-nil and host is nil, returns [RFC-822] group name.
+    #           Otherwise, returns [RFC-822] local-part
+    # 
+    # host:: nil indicates [RFC-822] group syntax.
+    #        Otherwise, returns [RFC-822] domain name.
+    #
+    Address = Struct.new(:name, :route, :mailbox, :host)
+
+    # 
+    # Net::IMAP::ContentDisposition represents Content-Disposition fields.
+    # 
+    # ==== Fields:
+    # 
+    # dsp_type:: Returns the disposition type.
+    # 
+    # param:: Returns a hash that represents parameters of the Content-Disposition
+    #         field.
+    # 
+    ContentDisposition = Struct.new(:dsp_type, :param)
+
+    # Net::IMAP::ThreadMember represents a thread-node returned 
+    # by Net::IMAP#thread
+    #
+    # ==== Fields:
+    #
+    # seqno:: The sequence number of this message.
+    #
+    # children:: an array of Net::IMAP::ThreadMember objects for mail
+    # items that are children of this in the thread.
+    #
+    ThreadMember = Struct.new(:seqno, :children)
+
+    # Net::IMAP::BodyTypeBasic represents basic body structures of messages.
+    # 
+    # ==== Fields:
+    # 
+    # media_type:: Returns the content media type name as defined in [MIME-IMB].
+    # 
+    # subtype:: Returns the content subtype name as defined in [MIME-IMB].
+    # 
+    # param:: Returns a hash that represents parameters as defined in [MIME-IMB].
+    # 
+    # content_id:: Returns a string giving the content id as defined in [MIME-IMB].
+    # 
+    # description:: Returns a string giving the content description as defined in
+    #               [MIME-IMB].
+    # 
+    # encoding:: Returns a string giving the content transfer encoding as defined in
+    #            [MIME-IMB].
+    # 
+    # size:: Returns a number giving the size of the body in octets.
+    # 
+    # md5:: Returns a string giving the body MD5 value as defined in [MD5].
+    # 
+    # disposition:: Returns a Net::IMAP::ContentDisposition object giving
+    #               the content disposition.
+    # 
+    # language:: Returns a string or an array of strings giving the body
+    #            language value as defined in [LANGUAGE-TAGS].
+    # 
+    # extension:: Returns extension data.
+    # 
+    # multipart?:: Returns false.
+    # 
+    class BodyTypeBasic < Struct.new(:media_type, :subtype,
+                                     :param, :content_id,
+                                     :description, :encoding, :size,
+                                     :md5, :disposition, :language,
+                                     :extension)
+      def multipart?
+        return false
+      end
+
+      # Obsolete: use +subtype+ instead.  Calling this will
+      # generate a warning message to +stderr+, then return 
+      # the value of +subtype+.
+      def media_subtype
+        $stderr.printf("warning: media_subtype is obsolete.\n")
+        $stderr.printf("         use subtype instead.\n")
+        return subtype
+      end
+    end
+
+    # Net::IMAP::BodyTypeText represents TEXT body structures of messages.
+    # 
+    # ==== Fields:
+    # 
+    # lines:: Returns the size of the body in text lines.
+    # 
+    # And Net::IMAP::BodyTypeText has all fields of Net::IMAP::BodyTypeBasic.
+    # 
+    class BodyTypeText < Struct.new(:media_type, :subtype,
+                                    :param, :content_id,
+                                    :description, :encoding, :size,
+                                    :lines,
+                                    :md5, :disposition, :language,
+                                    :extension)
+      def multipart?
+        return false
+      end
+
+      # Obsolete: use +subtype+ instead.  Calling this will
+      # generate a warning message to +stderr+, then return 
+      # the value of +subtype+.
+      def media_subtype
+        $stderr.printf("warning: media_subtype is obsolete.\n")
+        $stderr.printf("         use subtype instead.\n")
+        return subtype
+      end
+    end
+
+    # Net::IMAP::BodyTypeMessage represents MESSAGE/RFC822 body structures of messages.
+    # 
+    # ==== Fields:
+    # 
+    # envelope:: Returns a Net::IMAP::Envelope giving the envelope structure.
+    # 
+    # body:: Returns an object giving the body structure.
+    # 
+    # And Net::IMAP::BodyTypeMessage has all methods of Net::IMAP::BodyTypeText.
+    #
+    class BodyTypeMessage < Struct.new(:media_type, :subtype,
+                                       :param, :content_id,
+                                       :description, :encoding, :size,
+                                       :envelope, :body, :lines,
+                                       :md5, :disposition, :language,
+                                       :extension)
+      def multipart?
+        return false
+      end
+
+      # Obsolete: use +subtype+ instead.  Calling this will
+      # generate a warning message to +stderr+, then return 
+      # the value of +subtype+.
+      def media_subtype
+        $stderr.printf("warning: media_subtype is obsolete.\n")
+        $stderr.printf("         use subtype instead.\n")
+        return subtype
+      end
+    end
+
+    # Net::IMAP::BodyTypeMultipart represents multipart body structures 
+    # of messages.
+    # 
+    # ==== Fields:
+    # 
+    # media_type:: Returns the content media type name as defined in [MIME-IMB].
+    # 
+    # subtype:: Returns the content subtype name as defined in [MIME-IMB].
+    # 
+    # parts:: Returns multiple parts.
+    # 
+    # param:: Returns a hash that represents parameters as defined in [MIME-IMB].
+    # 
+    # disposition:: Returns a Net::IMAP::ContentDisposition object giving
+    #               the content disposition.
+    # 
+    # language:: Returns a string or an array of strings giving the body
+    #            language value as defined in [LANGUAGE-TAGS].
+    # 
+    # extension:: Returns extension data.
+    # 
+    # multipart?:: Returns true.
+    # 
+    class BodyTypeMultipart < Struct.new(:media_type, :subtype,
+                                         :parts,
+                                         :param, :disposition, :language,
+                                         :extension)
+      def multipart?
+        return true
+      end
+
+      # Obsolete: use +subtype+ instead.  Calling this will
+      # generate a warning message to +stderr+, then return 
+      # the value of +subtype+.
+      def media_subtype
+        $stderr.printf("warning: media_subtype is obsolete.\n")
+        $stderr.printf("         use subtype instead.\n")
+        return subtype
+      end
+    end
+
+    class ResponseParser # :nodoc:
+      def parse(str)
+        @str = str
+        @pos = 0
+        @lex_state = EXPR_BEG
+        @token = nil
+        return response
+      end
+
+      private
+
+      EXPR_BEG          = :EXPR_BEG
+      EXPR_DATA         = :EXPR_DATA
+      EXPR_TEXT         = :EXPR_TEXT
+      EXPR_RTEXT        = :EXPR_RTEXT
+      EXPR_CTEXT        = :EXPR_CTEXT
+
+      T_SPACE   = :SPACE
+      T_NIL     = :NIL
+      T_NUMBER  = :NUMBER
+      T_ATOM    = :ATOM
+      T_QUOTED  = :QUOTED
+      T_LPAR    = :LPAR
+      T_RPAR    = :RPAR
+      T_BSLASH  = :BSLASH
+      T_STAR    = :STAR
+      T_LBRA    = :LBRA
+      T_RBRA    = :RBRA
+      T_LITERAL = :LITERAL
+      T_PLUS    = :PLUS
+      T_PERCENT = :PERCENT
+      T_CRLF    = :CRLF
+      T_EOF     = :EOF
+      T_TEXT    = :TEXT
+
+      BEG_REGEXP = /\G(?:\
+(?# 1:  SPACE   )( +)|\
+(?# 2:  NIL     )(NIL)(?=[\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+])|\
+(?# 3:  NUMBER  )(\d+)(?=[\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+])|\
+(?# 4:  ATOM    )([^\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+]+)|\
+(?# 5:  QUOTED  )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\
+(?# 6:  LPAR    )(\()|\
+(?# 7:  RPAR    )(\))|\
+(?# 8:  BSLASH  )(\\)|\
+(?# 9:  STAR    )(\*)|\
+(?# 10: LBRA    )(\[)|\
+(?# 11: RBRA    )(\])|\
+(?# 12: LITERAL )\{(\d+)\}\r\n|\
+(?# 13: PLUS    )(\+)|\
+(?# 14: PERCENT )(%)|\
+(?# 15: CRLF    )(\r\n)|\
+(?# 16: EOF     )(\z))/ni
+
+      DATA_REGEXP = /\G(?:\
+(?# 1:  SPACE   )( )|\
+(?# 2:  NIL     )(NIL)|\
+(?# 3:  NUMBER  )(\d+)|\
+(?# 4:  QUOTED  )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\
+(?# 5:  LITERAL )\{(\d+)\}\r\n|\
+(?# 6:  LPAR    )(\()|\
+(?# 7:  RPAR    )(\)))/ni
+
+      TEXT_REGEXP = /\G(?:\
+(?# 1:  TEXT    )([^\x00\r\n]*))/ni
+
+      RTEXT_REGEXP = /\G(?:\
+(?# 1:  LBRA    )(\[)|\
+(?# 2:  TEXT    )([^\x00\r\n]*))/ni
+
+      CTEXT_REGEXP = /\G(?:\
+(?# 1:  TEXT    )([^\x00\r\n\]]*))/ni
+
+      Token = Struct.new(:symbol, :value)
+
+      def response
+        token = lookahead
+        case token.symbol
+        when T_PLUS
+          result = continue_req
+        when T_STAR
+          result = response_untagged
+        else
+          result = response_tagged
+        end
+        match(T_CRLF)
+        match(T_EOF)
+        return result
+      end
+
+      def continue_req
+        match(T_PLUS)
+        match(T_SPACE)
+        return ContinuationRequest.new(resp_text, @str)
+      end
+
+      def response_untagged
+        match(T_STAR)
+        match(T_SPACE)
+        token = lookahead
+        if token.symbol == T_NUMBER
+          return numeric_response
+        elsif token.symbol == T_ATOM
+          case token.value
+          when /\A(?:OK|NO|BAD|BYE|PREAUTH)\z/ni
+            return response_cond
+          when /\A(?:FLAGS)\z/ni
+            return flags_response
+          when /\A(?:LIST|LSUB)\z/ni
+            return list_response
+          when /\A(?:QUOTA)\z/ni
+            return getquota_response
+          when /\A(?:QUOTAROOT)\z/ni
+            return getquotaroot_response
+          when /\A(?:ACL)\z/ni
+            return getacl_response
+          when /\A(?:SEARCH|SORT)\z/ni
+            return search_response
+          when /\A(?:THREAD)\z/ni
+            return thread_response
+          when /\A(?:STATUS)\z/ni
+            return status_response
+          when /\A(?:CAPABILITY)\z/ni
+            return capability_response
+          else
+            return text_response
+          end
+        else
+          parse_error("unexpected token %s", token.symbol)
+        end
+      end
+
+      def response_tagged
+        tag = atom
+        match(T_SPACE)
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        return TaggedResponse.new(tag, name, resp_text, @str)
+      end
+
+      def response_cond
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        return UntaggedResponse.new(name, resp_text, @str)
+      end
+
+      def numeric_response
+        n = number
+        match(T_SPACE)
+        token = match(T_ATOM)
+        name = token.value.upcase
+        case name
+        when "EXISTS", "RECENT", "EXPUNGE"
+          return UntaggedResponse.new(name, n, @str)
+        when "FETCH"
+          shift_token
+          match(T_SPACE)
+          data = FetchData.new(n, msg_att)
+          return UntaggedResponse.new(name, data, @str)
+        end
+      end
+
+      def msg_att
+        match(T_LPAR)
+        attr = {}
+        while true
+          token = lookahead
+          case token.symbol
+          when T_RPAR
+            shift_token
+            break
+          when T_SPACE
+            shift_token
+            token = lookahead
+          end
+          case token.value
+          when /\A(?:ENVELOPE)\z/ni
+            name, val = envelope_data
+          when /\A(?:FLAGS)\z/ni
+            name, val = flags_data
+          when /\A(?:INTERNALDATE)\z/ni
+            name, val = internaldate_data
+          when /\A(?:RFC822(?:\.HEADER|\.TEXT)?)\z/ni
+            name, val = rfc822_text
+          when /\A(?:RFC822\.SIZE)\z/ni
+            name, val = rfc822_size
+          when /\A(?:BODY(?:STRUCTURE)?)\z/ni
+            name, val = body_data
+          when /\A(?:UID)\z/ni
+            name, val = uid_data
+          else
+            parse_error("unknown attribute `%s'", token.value)
+          end
+          attr[name] = val
+        end
+        return attr
+      end
+
+      def envelope_data
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        return name, envelope
+      end
+
+      def envelope
+        @lex_state = EXPR_DATA
+        token = lookahead
+        if token.symbol == T_NIL
+          shift_token
+          result = nil
+        else
+          match(T_LPAR)
+          date = nstring
+          match(T_SPACE)
+          subject = nstring
+          match(T_SPACE)
+          from = address_list
+          match(T_SPACE)
+          sender = address_list
+          match(T_SPACE)
+          reply_to = address_list
+          match(T_SPACE)
+          to = address_list
+          match(T_SPACE)
+          cc = address_list
+          match(T_SPACE)
+          bcc = address_list
+          match(T_SPACE)
+          in_reply_to = nstring
+          match(T_SPACE)
+          message_id = nstring
+          match(T_RPAR)
+          result = Envelope.new(date, subject, from, sender, reply_to,
+                                to, cc, bcc, in_reply_to, message_id)
+        end
+        @lex_state = EXPR_BEG
+        return result
+      end
+
+      def flags_data
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        return name, flag_list
+      end
+
+      def internaldate_data
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        token = match(T_QUOTED)
+        return name, token.value
+      end
+
+      def rfc822_text
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        return name, nstring
+      end
+
+      def rfc822_size
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        return name, number
+      end
+
+      def body_data
+        token = match(T_ATOM)
+        name = token.value.upcase
+        token = lookahead
+        if token.symbol == T_SPACE
+          shift_token
+          return name, body
+        end
+        name.concat(section)
+        token = lookahead
+        if token.symbol == T_ATOM
+          name.concat(token.value)
+          shift_token
+        end
+        match(T_SPACE)
+        data = nstring
+        return name, data
+      end
+
+      def body
+        @lex_state = EXPR_DATA
+        token = lookahead
+        if token.symbol == T_NIL
+          shift_token
+          result = nil
+        else
+          match(T_LPAR)
+          token = lookahead
+          if token.symbol == T_LPAR
+            result = body_type_mpart
+          else
+            result = body_type_1part
+          end
+          match(T_RPAR)
+        end
+        @lex_state = EXPR_BEG
+        return result
+      end
+
+      def body_type_1part
+        token = lookahead
+        case token.value
+        when /\A(?:TEXT)\z/ni
+          return body_type_text
+        when /\A(?:MESSAGE)\z/ni
+          return body_type_msg
+        else
+          return body_type_basic
+        end
+      end
+
+      def body_type_basic
+        mtype, msubtype = media_type
+        token = lookahead
+        if token.symbol == T_RPAR
+          return BodyTypeBasic.new(mtype, msubtype)
+        end
+        match(T_SPACE)
+        param, content_id, desc, enc, size = body_fields
+        md5, disposition, language, extension = body_ext_1part
+        return BodyTypeBasic.new(mtype, msubtype,
+                                 param, content_id,
+                                 desc, enc, size,
+                                 md5, disposition, language, extension)
+      end
+
+      def body_type_text
+        mtype, msubtype = media_type
+        match(T_SPACE)
+        param, content_id, desc, enc, size = body_fields
+        match(T_SPACE)
+        lines = number
+        md5, disposition, language, extension = body_ext_1part
+        return BodyTypeText.new(mtype, msubtype,
+                                param, content_id,
+                                desc, enc, size,
+                                lines,
+                                md5, disposition, language, extension)
+      end
+
+      def body_type_msg
+        mtype, msubtype = media_type
+        match(T_SPACE)
+        param, content_id, desc, enc, size = body_fields
+        match(T_SPACE)
+        env = envelope
+        match(T_SPACE)
+        b = body
+        match(T_SPACE)
+        lines = number
+        md5, disposition, language, extension = body_ext_1part
+        return BodyTypeMessage.new(mtype, msubtype,
+                                   param, content_id,
+                                   desc, enc, size,
+                                   env, b, lines,
+                                   md5, disposition, language, extension)
+      end
+
+      def body_type_mpart
+        parts = []
+        while true
+          token = lookahead
+          if token.symbol == T_SPACE
+            shift_token
+            break
+          end
+          parts.push(body)
+        end
+        mtype = "MULTIPART"
+        msubtype = case_insensitive_string
+        param, disposition, language, extension = body_ext_mpart
+        return BodyTypeMultipart.new(mtype, msubtype, parts,
+                                     param, disposition, language,
+                                     extension)
+      end
+
+      def media_type
+        mtype = case_insensitive_string
+        match(T_SPACE)
+        msubtype = case_insensitive_string
+        return mtype, msubtype
+      end
+
+      def body_fields
+        param = body_fld_param
+        match(T_SPACE)
+        content_id = nstring
+        match(T_SPACE)
+        desc = nstring
+        match(T_SPACE)
+        enc = case_insensitive_string
+        match(T_SPACE)
+        size = number
+        return param, content_id, desc, enc, size
+      end
+
+      def body_fld_param
+        token = lookahead
+        if token.symbol == T_NIL
+          shift_token
+          return nil
+        end
+        match(T_LPAR)
+        param = {}
+        while true
+          token = lookahead
+          case token.symbol
+          when T_RPAR
+            shift_token
+            break
+          when T_SPACE
+            shift_token
+          end
+          name = case_insensitive_string
+          match(T_SPACE)
+          val = string
+          param[name] = val
+        end
+        return param
+      end
+
+      def body_ext_1part
+        token = lookahead
+        if token.symbol == T_SPACE
+          shift_token
+        else
+          return nil
+        end
+        md5 = nstring
+
+        token = lookahead
+        if token.symbol == T_SPACE
+          shift_token
+        else
+          return md5
+        end
+        disposition = body_fld_dsp
+
+        token = lookahead
+        if token.symbol == T_SPACE
+          shift_token
+        else
+          return md5, disposition
+        end
+        language = body_fld_lang
+
+        token = lookahead
+        if token.symbol == T_SPACE
+          shift_token
+        else
+          return md5, disposition, language
+        end
+
+        extension = body_extensions
+        return md5, disposition, language, extension
+      end
+
+      def body_ext_mpart
+        token = lookahead
+        if token.symbol == T_SPACE
+          shift_token
+        else
+          return nil
+        end
+        param = body_fld_param
+
+        token = lookahead
+        if token.symbol == T_SPACE
+          shift_token
+        else
+          return param
+        end
+        disposition = body_fld_dsp
+        match(T_SPACE)
+        language = body_fld_lang
+
+        token = lookahead
+        if token.symbol == T_SPACE
+          shift_token
+        else
+          return param, disposition, language
+        end
+
+        extension = body_extensions
+        return param, disposition, language, extension
+      end
+
+      def body_fld_dsp
+        token = lookahead
+        if token.symbol == T_NIL
+          shift_token
+          return nil
+        end
+        match(T_LPAR)
+        dsp_type = case_insensitive_string
+        match(T_SPACE)
+        param = body_fld_param
+        match(T_RPAR)
+        return ContentDisposition.new(dsp_type, param)
+      end
+
+      def body_fld_lang
+        token = lookahead
+        if token.symbol == T_LPAR
+          shift_token
+          result = []
+          while true
+            token = lookahead
+            case token.symbol
+            when T_RPAR
+              shift_token
+              return result
+            when T_SPACE
+              shift_token
+            end
+            result.push(case_insensitive_string)
+          end
+        else
+          lang = nstring
+          if lang
+            return lang.upcase
+          else
+            return lang
+          end
+        end
+      end
+
+      def body_extensions
+        result = []
+        while true
+          token = lookahead
+          case token.symbol
+          when T_RPAR
+            return result
+          when T_SPACE
+            shift_token
+          end
+          result.push(body_extension)
+        end
+      end
+
+      def body_extension
+        token = lookahead
+        case token.symbol
+        when T_LPAR
+          shift_token
+          result = body_extensions
+          match(T_RPAR)
+          return result
+        when T_NUMBER
+          return number
+        else
+          return nstring
+        end
+      end
+
+      def section
+        str = ""
+        token = match(T_LBRA)
+        str.concat(token.value)
+        token = match(T_ATOM, T_NUMBER, T_RBRA)
+        if token.symbol == T_RBRA
+          str.concat(token.value)
+          return str
+        end
+        str.concat(token.value)
+        token = lookahead
+        if token.symbol == T_SPACE
+          shift_token
+          str.concat(token.value)
+          token = match(T_LPAR)
+          str.concat(token.value)
+          while true
+            token = lookahead
+            case token.symbol
+            when T_RPAR
+              str.concat(token.value)
+              shift_token
+              break
+            when T_SPACE
+              shift_token
+              str.concat(token.value)
+            end
+            str.concat(format_string(astring))
+          end
+        end
+        token = match(T_RBRA)
+        str.concat(token.value)
+        return str
+      end
+
+      def format_string(str)
+        case str
+        when ""
+          return '""'
+        when /[\x80-\xff\r\n]/n
+          # literal
+          return "{" + str.length.to_s + "}" + CRLF + str
+        when /[(){ \x00-\x1f\x7f%*"\\]/n
+          # quoted string
+          return '"' + str.gsub(/["\\]/n, "\\\\\\&") + '"'
+        else
+          # atom
+          return str
+        end
+      end
+
+      def uid_data
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        return name, number
+      end
+
+      def text_response
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        @lex_state = EXPR_TEXT
+        token = match(T_TEXT)
+        @lex_state = EXPR_BEG
+        return UntaggedResponse.new(name, token.value)
+      end
+
+      def flags_response
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        return UntaggedResponse.new(name, flag_list, @str)
+      end
+
+      def list_response
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        return UntaggedResponse.new(name, mailbox_list, @str)
+      end
+
+      def mailbox_list
+        attr = flag_list
+        match(T_SPACE)
+        token = match(T_QUOTED, T_NIL)
+        if token.symbol == T_NIL
+          delim = nil
+        else
+          delim = token.value
+        end
+        match(T_SPACE)
+        name = astring
+        return MailboxList.new(attr, delim, name)
+      end
+
+      def getquota_response
+        # If quota never established, get back
+        # `NO Quota root does not exist'.
+        # If quota removed, get `()' after the
+        # folder spec with no mention of `STORAGE'.
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        mailbox = astring
+        match(T_SPACE)
+        match(T_LPAR)
+        token = lookahead
+        case token.symbol
+        when T_RPAR
+          shift_token
+          data = MailboxQuota.new(mailbox, nil, nil)
+          return UntaggedResponse.new(name, data, @str)
+        when T_ATOM
+          shift_token
+          match(T_SPACE)
+          token = match(T_NUMBER)
+          usage = token.value
+          match(T_SPACE)
+          token = match(T_NUMBER)
+          quota = token.value
+          match(T_RPAR)
+          data = MailboxQuota.new(mailbox, usage, quota)
+          return UntaggedResponse.new(name, data, @str)
+        else
+          parse_error("unexpected token %s", token.symbol)
+        end
+      end
+
+      def getquotaroot_response
+        # Similar to getquota, but only admin can use getquota.
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        mailbox = astring
+        quotaroots = []
+        while true
+          token = lookahead
+          break unless token.symbol == T_SPACE
+          shift_token
+          quotaroots.push(astring)
+        end
+        data = MailboxQuotaRoot.new(mailbox, quotaroots)
+        return UntaggedResponse.new(name, data, @str)
+      end
+
+      def getacl_response
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        mailbox = astring
+        data = []
+        token = lookahead
+        if token.symbol == T_SPACE
+          shift_token
+          while true
+            token = lookahead
+            case token.symbol
+            when T_CRLF
+              break
+            when T_SPACE
+              shift_token
+            end
+            user = astring
+            match(T_SPACE)
+            rights = astring
+            ##XXX data.push([user, rights])
+            data.push(MailboxACLItem.new(user, rights))
+          end
+        end
+        return UntaggedResponse.new(name, data, @str)
+      end
+
+      def search_response
+        token = match(T_ATOM)
+        name = token.value.upcase
+        token = lookahead
+        if token.symbol == T_SPACE
+          shift_token
+          data = []
+          while true
+            token = lookahead
+            case token.symbol
+            when T_CRLF
+              break
+            when T_SPACE
+              shift_token
+            end
+            data.push(number)
+          end
+        else
+          data = []
+        end
+        return UntaggedResponse.new(name, data, @str)
+      end
+
+      def thread_response
+        token = match(T_ATOM)
+        name = token.value.upcase
+        token = lookahead
+
+        if token.symbol == T_SPACE
+          threads = []
+
+          while true
+            shift_token
+            token = lookahead
+
+            case token.symbol
+            when T_LPAR
+              threads << thread_branch(token)
+            when T_CRLF
+              break
+            end
+          end
+        else
+          # no member
+          threads = []
+        end
+
+        return UntaggedResponse.new(name, threads, @str)
+      end
+
+      def thread_branch(token)
+        rootmember = nil
+        lastmember = nil
+        
+        while true
+          shift_token    # ignore first T_LPAR
+          token = lookahead
+          
+          case token.symbol
+          when T_NUMBER
+            # new member
+            newmember = ThreadMember.new(number, [])
+            if rootmember.nil?
+              rootmember = newmember
+            else    
+              lastmember.children << newmember
+            end     
+            lastmember = newmember
+          when T_SPACE 
+            # do nothing 
+          when T_LPAR
+            if rootmember.nil?
+              # dummy member
+              lastmember = rootmember = ThreadMember.new(nil, [])
+            end     
+            
+            lastmember.children << thread_branch(token)
+          when T_RPAR
+            break   
+          end     
+        end
+        
+        return rootmember
+      end
+
+      def status_response
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        mailbox = astring
+        match(T_SPACE)
+        match(T_LPAR)
+        attr = {}
+        while true
+          token = lookahead
+          case token.symbol
+          when T_RPAR
+            shift_token
+            break
+          when T_SPACE
+            shift_token
+          end
+          token = match(T_ATOM)
+          key = token.value.upcase
+          match(T_SPACE)
+          val = number
+          attr[key] = val
+        end
+        data = StatusData.new(mailbox, attr)
+        return UntaggedResponse.new(name, data, @str)
+      end
+
+      def capability_response
+        token = match(T_ATOM)
+        name = token.value.upcase
+        match(T_SPACE)
+        data = []
+        while true
+          token = lookahead
+          case token.symbol
+          when T_CRLF
+            break
+          when T_SPACE
+            shift_token
+          end
+          data.push(atom.upcase)
+        end
+        return UntaggedResponse.new(name, data, @str)
+      end
+
+      def resp_text
+        @lex_state = EXPR_RTEXT
+        token = lookahead
+        if token.symbol == T_LBRA
+          code = resp_text_code
+        else
+          code = nil
+        end
+        token = match(T_TEXT)
+        @lex_state = EXPR_BEG
+        return ResponseText.new(code, token.value)
+      end
+
+      def resp_text_code
+        @lex_state = EXPR_BEG
+        match(T_LBRA)
+        token = match(T_ATOM)
+        name = token.value.upcase
+        case name
+        when /\A(?:ALERT|PARSE|READ-ONLY|READ-WRITE|TRYCREATE|NOMODSEQ)\z/n
+          result = ResponseCode.new(name, nil)
+        when /\A(?:PERMANENTFLAGS)\z/n
+          match(T_SPACE)
+          result = ResponseCode.new(name, flag_list)
+        when /\A(?:UIDVALIDITY|UIDNEXT|UNSEEN)\z/n
+          match(T_SPACE)
+          result = ResponseCode.new(name, number)
+        else
+          match(T_SPACE)
+          @lex_state = EXPR_CTEXT
+          token = match(T_TEXT)
+          @lex_state = EXPR_BEG
+          result = ResponseCode.new(name, token.value)
+        end
+        match(T_RBRA)
+        @lex_state = EXPR_RTEXT
+        return result
+      end
+
+      def address_list
+        token = lookahead
+        if token.symbol == T_NIL
+          shift_token
+          return nil
+        else
+          result = []
+          match(T_LPAR)
+          while true
+            token = lookahead
+            case token.symbol
+            when T_RPAR
+              shift_token
+              break
+            when T_SPACE
+              shift_token
+            end
+            result.push(address)
+          end
+          return result
+        end
+      end
+
+      ADDRESS_REGEXP = /\G\
+(?# 1: NAME     )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \
+(?# 2: ROUTE    )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \
+(?# 3: MAILBOX  )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)") \
+(?# 4: HOST     )(?:NIL|"((?:[^\x80-\xff\x00\r\n"\\]|\\["\\])*)")\
+\)/ni
+
+      def address
+        match(T_LPAR)
+        if @str.index(ADDRESS_REGEXP, @pos)
+          # address does not include literal.
+          @pos = $~.end(0)
+          name = $1
+          route = $2
+          mailbox = $3
+          host = $4
+          for s in [name, route, mailbox, host]
+            if s
+              s.gsub!(/\\(["\\])/n, "\\1")
+            end
+          end
+        else
+          name = nstring
+          match(T_SPACE)
+          route = nstring
+          match(T_SPACE)
+          mailbox = nstring
+          match(T_SPACE)
+          host = nstring
+          match(T_RPAR)
+        end
+        return Address.new(name, route, mailbox, host)
+      end
+
+#        def flag_list
+#       result = []
+#       match(T_LPAR)
+#       while true
+#         token = lookahead
+#         case token.symbol
+#         when T_RPAR
+#           shift_token
+#           break
+#         when T_SPACE
+#           shift_token
+#         end
+#         result.push(flag)
+#       end
+#       return result
+#        end
+
+#        def flag
+#       token = lookahead
+#       if token.symbol == T_BSLASH
+#         shift_token
+#         token = lookahead
+#         if token.symbol == T_STAR
+#           shift_token
+#           return token.value.intern
+#         else
+#           return atom.intern
+#         end
+#       else
+#         return atom
+#       end
+#        end
+
+      FLAG_REGEXP = /\
+(?# FLAG        )\\([^\x80-\xff(){ \x00-\x1f\x7f%"\\]+)|\
+(?# ATOM        )([^\x80-\xff(){ \x00-\x1f\x7f%*"\\]+)/n
+
+      def flag_list
+        if @str.index(/\(([^)]*)\)/ni, @pos)
+          @pos = $~.end(0)
+          return $1.scan(FLAG_REGEXP).collect { |flag, atom|
+            atom || flag.capitalize.intern
+          }
+        else
+          parse_error("invalid flag list")
+        end
+      end
+
+      def nstring
+        token = lookahead
+        if token.symbol == T_NIL
+          shift_token
+          return nil
+        else
+          return string
+        end
+      end
+
+      def astring
+        token = lookahead
+        if string_token?(token)
+          return string
+        else
+          return atom
+        end
+      end
+
+      def string
+        token = lookahead
+        if token.symbol == T_NIL
+          shift_token
+          return nil
+        end
+        token = match(T_QUOTED, T_LITERAL)
+        return token.value
+      end
+
+      STRING_TOKENS = [T_QUOTED, T_LITERAL, T_NIL]
+
+      def string_token?(token)
+        return STRING_TOKENS.include?(token.symbol)
+      end
+
+      def case_insensitive_string
+        token = lookahead
+        if token.symbol == T_NIL
+          shift_token
+          return nil
+        end
+        token = match(T_QUOTED, T_LITERAL)
+        return token.value.upcase
+      end
+
+      def atom
+        result = ""
+        while true
+          token = lookahead
+          if atom_token?(token)
+            result.concat(token.value)
+            shift_token
+          else
+            if result.empty?
+              parse_error("unexpected token %s", token.symbol)
+            else
+              return result
+            end
+          end
+        end
+      end
+
+      ATOM_TOKENS = [
+        T_ATOM,
+        T_NUMBER,
+        T_NIL,
+        T_LBRA,
+        T_RBRA,
+        T_PLUS
+      ]
+
+      def atom_token?(token)
+        return ATOM_TOKENS.include?(token.symbol)
+      end
+
+      def number
+        token = lookahead
+        if token.symbol == T_NIL
+          shift_token
+          return nil
+        end
+        token = match(T_NUMBER)
+        return token.value.to_i
+      end
+
+      def nil_atom
+        match(T_NIL)
+        return nil
+      end
+
+      def match(*args)
+        token = lookahead
+        unless args.include?(token.symbol)
+          parse_error('unexpected token %s (expected %s)',
+                      token.symbol.id2name,
+                      args.collect {|i| i.id2name}.join(" or "))
+        end
+        shift_token
+        return token
+      end
+
+      def lookahead
+        unless @token
+          @token = next_token
+        end
+        return @token
+      end
+
+      def shift_token
+        @token = nil
+      end
+
+      def next_token
+        case @lex_state
+        when EXPR_BEG
+          if @str.index(BEG_REGEXP, @pos)
+            @pos = $~.end(0)
+            if $1
+              return Token.new(T_SPACE, $+)
+            elsif $2
+              return Token.new(T_NIL, $+)
+            elsif $3
+              return Token.new(T_NUMBER, $+)
+            elsif $4
+              return Token.new(T_ATOM, $+)
+            elsif $5
+              return Token.new(T_QUOTED,
+                               $+.gsub(/\\(["\\])/n, "\\1"))
+            elsif $6
+              return Token.new(T_LPAR, $+)
+            elsif $7
+              return Token.new(T_RPAR, $+)
+            elsif $8
+              return Token.new(T_BSLASH, $+)
+            elsif $9
+              return Token.new(T_STAR, $+)
+            elsif $10
+              return Token.new(T_LBRA, $+)
+            elsif $11
+              return Token.new(T_RBRA, $+)
+            elsif $12
+              len = $+.to_i
+              val = @str[@pos, len]
+              @pos += len
+              return Token.new(T_LITERAL, val)
+            elsif $13
+              return Token.new(T_PLUS, $+)
+            elsif $14
+              return Token.new(T_PERCENT, $+)
+            elsif $15
+              return Token.new(T_CRLF, $+)
+            elsif $16
+              return Token.new(T_EOF, $+)
+            else
+              parse_error("[Net::IMAP BUG] BEG_REGEXP is invalid")
+            end
+          else
+            @str.index(/\S*/n, @pos)
+            parse_error("unknown token - %s", $&.dump)
+          end
+        when EXPR_DATA
+          if @str.index(DATA_REGEXP, @pos)
+            @pos = $~.end(0)
+            if $1
+              return Token.new(T_SPACE, $+)
+            elsif $2
+              return Token.new(T_NIL, $+)
+            elsif $3
+              return Token.new(T_NUMBER, $+)
+            elsif $4
+              return Token.new(T_QUOTED,
+                               $+.gsub(/\\(["\\])/n, "\\1"))
+            elsif $5
+              len = $+.to_i
+              val = @str[@pos, len]
+              @pos += len
+              return Token.new(T_LITERAL, val)
+            elsif $6
+              return Token.new(T_LPAR, $+)
+            elsif $7
+              return Token.new(T_RPAR, $+)
+            else
+              parse_error("[Net::IMAP BUG] BEG_REGEXP is invalid")
+            end
+          else
+            @str.index(/\S*/n, @pos)
+            parse_error("unknown token - %s", $&.dump)
+          end
+        when EXPR_TEXT
+          if @str.index(TEXT_REGEXP, @pos)
+            @pos = $~.end(0)
+            if $1
+              return Token.new(T_TEXT, $+)
+            else
+              parse_error("[Net::IMAP BUG] TEXT_REGEXP is invalid")
+            end
+          else
+            @str.index(/\S*/n, @pos)
+            parse_error("unknown token - %s", $&.dump)
+          end
+        when EXPR_RTEXT
+          if @str.index(RTEXT_REGEXP, @pos)
+            @pos = $~.end(0)
+            if $1
+              return Token.new(T_LBRA, $+)
+            elsif $2
+              return Token.new(T_TEXT, $+)
+            else
+              parse_error("[Net::IMAP BUG] RTEXT_REGEXP is invalid")
+            end
+          else
+            @str.index(/\S*/n, @pos)
+            parse_error("unknown token - %s", $&.dump)
+          end
+        when EXPR_CTEXT
+          if @str.index(CTEXT_REGEXP, @pos)
+            @pos = $~.end(0)
+            if $1
+              return Token.new(T_TEXT, $+)
+            else
+              parse_error("[Net::IMAP BUG] CTEXT_REGEXP is invalid")
+            end
+          else
+            @str.index(/\S*/n, @pos) #/
+            parse_error("unknown token - %s", $&.dump)
+          end
+        else
+          parse_error("illegal @lex_state - %s", @lex_state.inspect)
+        end
+      end
+
+      def parse_error(fmt, *args)
+        if IMAP.debug
+          $stderr.printf("@str: %s\n", @str.dump)
+          $stderr.printf("@pos: %d\n", @pos)
+          $stderr.printf("@lex_state: %s\n", @lex_state)
+          if @token.symbol
+            $stderr.printf("@token.symbol: %s\n", @token.symbol)
+            $stderr.printf("@token.value: %s\n", @token.value.inspect)
+          end
+        end
+        raise ResponseParseError, format(fmt, *args)
+      end
+    end
+
+    # Authenticator for the "LOGIN" authentication type.  See
+    # #authenticate().
+    class LoginAuthenticator
+      def process(data)
+        case @state
+        when STATE_USER
+          @state = STATE_PASSWORD
+          return @user
+        when STATE_PASSWORD
+          return @password
+        end
+      end
+
+      private
+
+      STATE_USER = :USER
+      STATE_PASSWORD = :PASSWORD
+
+      def initialize(user, password)
+        @user = user
+        @password = password
+        @state = STATE_USER
+      end
+    end
+    add_authenticator "LOGIN", LoginAuthenticator
+
+    # Authenticator for the "CRAM-MD5" authentication type.  See
+    # #authenticate().
+    class CramMD5Authenticator
+      def process(challenge)
+        digest = hmac_md5(challenge, @password)
+        return @user + " " + digest
+      end
+
+      private
+
+      def initialize(user, password)
+        @user = user
+        @password = password
+      end
+
+      def hmac_md5(text, key)
+        if key.length > 64
+          key = Digest::MD5.digest(key)
+        end
+
+        k_ipad = key + "\0" * (64 - key.length)
+        k_opad = key + "\0" * (64 - key.length)
+        for i in 0..63
+          k_ipad[i] ^= 0x36
+          k_opad[i] ^= 0x5c
+        end
+
+        digest = Digest::MD5.digest(k_ipad + text)
+
+        return Digest::MD5.hexdigest(k_opad + digest)
+      end
+    end
+    add_authenticator "CRAM-MD5", CramMD5Authenticator
+
+    # Superclass of IMAP errors.
+    class Error < StandardError
+    end
+
+    # Error raised when data is in the incorrect format.
+    class DataFormatError < Error
+    end
+
+    # Error raised when a response from the server is non-parseable.
+    class ResponseParseError < Error
+    end
+
+    # Superclass of all errors used to encapsulate "fail" responses
+    # from the server.
+    class ResponseError < Error
+    end
+
+    # Error raised upon a "NO" response from the server, indicating
+    # that the client command could not be completed successfully.
+    class NoResponseError < ResponseError
+    end
+
+    # Error raised upon a "BAD" response from the server, indicating
+    # that the client command violated the IMAP protocol, or an internal
+    # server failure has occurred.
+    class BadResponseError < ResponseError
+    end
+
+    # Error raised upon a "BYE" response from the server, indicating 
+    # that the client is not being allowed to login, or has been timed
+    # out due to inactivity.
+    class ByeResponseError < ResponseError
+    end
+  end
+end
+
+if __FILE__ == $0
+  # :enddoc:
+  require "getoptlong"
+
+  $stdout.sync = true
+  $port = nil
+  $user = ENV["USER"] || ENV["LOGNAME"]
+  $auth = "login"
+  $ssl = false
+
+  def usage
+    $stderr.print <<EOF
+usage: #{$0} [options] <host>
+
+  --help                        print this message
+  --port=PORT                   specifies port
+  --user=USER                   specifies user
+  --auth=AUTH                   specifies auth type
+  --ssl                         use ssl
+EOF
+  end
+
+  def get_password
+    print "password: "
+    system("stty", "-echo")
+    begin
+      return gets.chop
+    ensure
+      system("stty", "echo")
+      print "\n"
+    end
+  end
+
+  def get_command
+    printf("%s@%s> ", $user, $host)
+    if line = gets
+      return line.strip.split(/\s+/)
+    else
+      return nil
+    end
+  end
+
+  parser = GetoptLong.new
+  parser.set_options(['--debug', GetoptLong::NO_ARGUMENT],
+                     ['--help', GetoptLong::NO_ARGUMENT],
+                     ['--port', GetoptLong::REQUIRED_ARGUMENT],
+                     ['--user', GetoptLong::REQUIRED_ARGUMENT],
+                     ['--auth', GetoptLong::REQUIRED_ARGUMENT],
+                     ['--ssl', GetoptLong::NO_ARGUMENT])
+  begin
+    parser.each_option do |name, arg|
+      case name
+      when "--port"
+        $port = arg
+      when "--user"
+        $user = arg
+      when "--auth"
+        $auth = arg
+      when "--ssl"
+        $ssl = true
+      when "--debug"
+        Net::IMAP.debug = true
+      when "--help"
+        usage
+        exit(1)
+      end
+    end
+  rescue
+    usage
+    exit(1)
+  end
+
+  $host = ARGV.shift
+  unless $host
+    usage
+    exit(1)
+  end
+  $port ||= $ssl ? 993 : 143
+    
+  imap = Net::IMAP.new($host, $port, $ssl)
+  begin
+    password = get_password
+    imap.authenticate($auth, $user, password)
+    while true
+      cmd, *args = get_command
+      break unless cmd
+      begin
+        case cmd
+        when "list"
+          for mbox in imap.list("", args[0] || "*")
+            if mbox.attr.include?(Net::IMAP::NOSELECT)
+              prefix = "!"
+            elsif mbox.attr.include?(Net::IMAP::MARKED)
+              prefix = "*"
+            else
+              prefix = " "
+            end
+            print prefix, mbox.name, "\n"
+          end
+        when "select"
+          imap.select(args[0] || "inbox")
+          print "ok\n"
+        when "close"
+          imap.close
+          print "ok\n"
+        when "summary"
+          unless messages = imap.responses["EXISTS"][-1]
+            puts "not selected"
+            next
+          end
+          if messages > 0
+            for data in imap.fetch(1..-1, ["ENVELOPE"])
+              print data.seqno, ": ", data.attr["ENVELOPE"].subject, "\n"
+            end
+          else
+            puts "no message"
+          end
+        when "fetch"
+          if args[0]
+            data = imap.fetch(args[0].to_i, ["RFC822.HEADER", "RFC822.TEXT"])[0]
+            puts data.attr["RFC822.HEADER"]
+            puts data.attr["RFC822.TEXT"]
+          else
+            puts "missing argument"
+          end
+        when "logout", "exit", "quit"
+          break
+        when "help", "?"
+          print <<EOF
+list [pattern]                  list mailboxes
+select [mailbox]                select mailbox
+close                           close mailbox
+summary                         display summary
+fetch [msgno]                   display message
+logout                          logout
+help, ?                         display help message
+EOF
+        else
+          print "unknown command: ", cmd, "\n"
+        end
+      rescue Net::IMAP::Error
+        puts $!
+      end
+    end
+  ensure
+    imap.logout
+    imap.disconnect
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/pop.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/pop.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/pop.rb	(revision 18425)
@@ -0,0 +1,879 @@
+# = net/pop.rb
+#
+# Copyright (c) 1999-2003 Yukihiro Matsumoto.
+#
+# Copyright (c) 1999-2003 Minero Aoki.
+# 
+# Written & maintained by Minero Aoki <aamine@loveruby.net>.
+#
+# Documented by William Webber and Minero Aoki.
+# 
+# This program is free software. You can re-distribute and/or
+# modify this program under the same terms as Ruby itself,
+# Ruby Distribute License or GNU General Public License.
+# 
+# NOTE: You can find Japanese version of this document in
+# the doc/net directory of the standard ruby interpreter package.
+# 
+#   $Id: pop.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+# See Net::POP3 for documentation.
+#
+
+require 'net/protocol'
+require 'digest/md5'
+
+module Net
+
+  # Non-authentication POP3 protocol error
+  # (reply code "-ERR", except authentication).
+  class POPError < ProtocolError; end
+
+  # POP3 authentication error.
+  class POPAuthenticationError < ProtoAuthError; end
+
+  # Unexpected response from the server.
+  class POPBadResponse < POPError; end
+
+  #
+  # = Net::POP3
+  #
+  # == What is This Library?
+  # 
+  # This library provides functionality for retrieving 
+  # email via POP3, the Post Office Protocol version 3. For details
+  # of POP3, see [RFC1939] (http://www.ietf.org/rfc/rfc1939.txt).
+  # 
+  # == Examples
+  # 
+  # === Retrieving Messages 
+  # 
+  # This example retrieves messages from the server and deletes them 
+  # on the server.
+  #
+  # Messages are written to files named 'inbox/1', 'inbox/2', ....
+  # Replace 'pop.example.com' with your POP3 server address, and
+  # 'YourAccount' and 'YourPassword' with the appropriate account
+  # details.
+  # 
+  #     require 'net/pop'
+  # 
+  #     pop = Net::POP3.new('pop.example.com')
+  #     pop.start('YourAccount', 'YourPassword')             # (1)
+  #     if pop.mails.empty?
+  #       puts 'No mail.'
+  #     else
+  #       i = 0
+  #       pop.each_mail do |m|   # or "pop.mails.each ..."   # (2)
+  #         File.open("inbox/#{i}", 'w') do |f|
+  #           f.write m.pop
+  #         end
+  #         m.delete
+  #         i += 1
+  #       end
+  #       puts "#{pop.mails.size} mails popped."
+  #     end
+  #     pop.finish                                           # (3)
+  # 
+  # 1. Call Net::POP3#start and start POP session.
+  # 2. Access messages by using POP3#each_mail and/or POP3#mails.
+  # 3. Close POP session by calling POP3#finish or use the block form of #start.
+  # 
+  # === Shortened Code
+  # 
+  # The example above is very verbose. You can shorten the code by using
+  # some utility methods. First, the block form of Net::POP3.start can
+  # be used instead of POP3.new, POP3#start and POP3#finish.
+  # 
+  #     require 'net/pop'
+  # 
+  #     Net::POP3.start('pop.example.com', 110,
+  #                     'YourAccount', 'YourPassword') do |pop|
+  #       if pop.mails.empty?
+  #         puts 'No mail.'
+  #       else
+  #         i = 0
+  #         pop.each_mail do |m|   # or "pop.mails.each ..."
+  #           File.open("inbox/#{i}", 'w') do |f|
+  #             f.write m.pop
+  #           end
+  #           m.delete
+  #           i += 1
+  #         end
+  #         puts "#{pop.mails.size} mails popped."
+  #       end
+  #     end
+  # 
+  # POP3#delete_all is an alternative for #each_mail and #delete.
+  # 
+  #     require 'net/pop'
+  # 
+  #     Net::POP3.start('pop.example.com', 110,
+  #                     'YourAccount', 'YourPassword') do |pop|
+  #       if pop.mails.empty?
+  #         puts 'No mail.'
+  #       else
+  #         i = 1
+  #         pop.delete_all do |m|
+  #           File.open("inbox/#{i}", 'w') do |f|
+  #             f.write m.pop
+  #           end
+  #           i += 1
+  #         end
+  #       end
+  #     end
+  # 
+  # And here is an even shorter example.
+  # 
+  #     require 'net/pop'
+  # 
+  #     i = 0
+  #     Net::POP3.delete_all('pop.example.com', 110,
+  #                          'YourAccount', 'YourPassword') do |m|
+  #       File.open("inbox/#{i}", 'w') do |f|
+  #         f.write m.pop
+  #       end
+  #       i += 1
+  #     end
+  # 
+  # === Memory Space Issues
+  # 
+  # All the examples above get each message as one big string.
+  # This example avoids this.
+  # 
+  #     require 'net/pop'
+  # 
+  #     i = 1
+  #     Net::POP3.delete_all('pop.example.com', 110,
+  #                          'YourAccount', 'YourPassword') do |m|
+  #       File.open("inbox/#{i}", 'w') do |f|
+  #         m.pop do |chunk|    # get a message little by little.
+  #           f.write chunk
+  #         end
+  #         i += 1
+  #       end
+  #     end
+  # 
+  # === Using APOP
+  # 
+  # The net/pop library supports APOP authentication.
+  # To use APOP, use the Net::APOP class instead of the Net::POP3 class.
+  # You can use the utility method, Net::POP3.APOP(). For example:
+  # 
+  #     require 'net/pop'
+  # 
+  #     # Use APOP authentication if $isapop == true
+  #     pop = Net::POP3.APOP($is_apop).new('apop.example.com', 110)
+  #     pop.start(YourAccount', 'YourPassword') do |pop|
+  #       # Rest of the code is the same.
+  #     end
+  # 
+  # === Fetch Only Selected Mail Using 'UIDL' POP Command
+  # 
+  # If your POP server provides UIDL functionality,
+  # you can grab only selected mails from the POP server.
+  # e.g.
+  # 
+  #     def need_pop?( id )
+  #       # determine if we need pop this mail...
+  #     end
+  # 
+  #     Net::POP3.start('pop.example.com', 110,
+  #                     'Your account', 'Your password') do |pop|
+  #       pop.mails.select { |m| need_pop?(m.unique_id) }.each do |m|
+  #         do_something(m.pop)
+  #       end
+  #     end
+  # 
+  # The POPMail#unique_id() method returns the unique-id of the message as a
+  # String. Normally the unique-id is a hash of the message.
+  # 
+  class POP3 < Protocol
+
+    Revision = %q$Revision: 11708 $.split[1]
+
+    #
+    # Class Parameters
+    #
+
+    # The default port for POP3 connections, port 110
+    def POP3.default_port
+      110
+    end
+
+    def POP3.socket_type   #:nodoc: obsolete
+      Net::InternetMessageIO
+    end
+
+    #
+    # Utilities
+    #
+
+    # Returns the APOP class if +isapop+ is true; otherwise, returns
+    # the POP class.  For example:
+    #
+    #     # Example 1
+    #     pop = Net::POP3::APOP($is_apop).new(addr, port)
+    #
+    #     # Example 2
+    #     Net::POP3::APOP($is_apop).start(addr, port) do |pop|
+    #       ....
+    #     end
+    #
+    def POP3.APOP( isapop )
+      isapop ? APOP : POP3
+    end
+
+    # Starts a POP3 session and iterates over each POPMail object,
+    # yielding it to the +block+.
+    # This method is equivalent to:
+    #
+    #     Net::POP3.start(address, port, account, password) do |pop|
+    #       pop.each_mail do |m|
+    #         yield m
+    #       end
+    #     end
+    #
+    # This method raises a POPAuthenticationError if authentication fails.
+    #
+    # === Example
+    #
+    #     Net::POP3.foreach('pop.example.com', 110,
+    #                       'YourAccount', 'YourPassword') do |m|
+    #       file.write m.pop
+    #       m.delete if $DELETE
+    #     end
+    #
+    def POP3.foreach( address, port = nil,
+                      account = nil, password = nil,
+                      isapop = false, &block )  # :yields: message
+      start(address, port, account, password, isapop) {|pop|
+        pop.each_mail(&block)
+      }
+    end
+
+    # Starts a POP3 session and deletes all messages on the server.
+    # If a block is given, each POPMail object is yielded to it before
+    # being deleted.
+    #
+    # This method raises a POPAuthenticationError if authentication fails.
+    #
+    # === Example
+    #
+    #     Net::POP3.delete_all('pop.example.com', 110,
+    #                          'YourAccount', 'YourPassword') do |m|
+    #       file.write m.pop
+    #     end
+    #
+    def POP3.delete_all( address, port = nil,
+                         account = nil, password = nil,
+                         isapop = false, &block )
+      start(address, port, account, password, isapop) {|pop|
+        pop.delete_all(&block)
+      }
+    end
+
+    # Opens a POP3 session, attempts authentication, and quits.
+    #
+    # This method raises POPAuthenticationError if authentication fails.
+    #
+    # === Example: normal POP3
+    #
+    #     Net::POP3.auth_only('pop.example.com', 110,
+    #                         'YourAccount', 'YourPassword')
+    #
+    # === Example: APOP
+    #
+    #     Net::POP3.auth_only('pop.example.com', 110,
+    #                         'YourAccount', 'YourPassword', true)
+    #
+    def POP3.auth_only( address, port = nil,
+                        account = nil, password = nil,
+                        isapop = false )
+      new(address, port, isapop).auth_only account, password
+    end
+
+    # Starts a pop3 session, attempts authentication, and quits.
+    # This method must not be called while POP3 session is opened.
+    # This method raises POPAuthenticationError if authentication fails.
+    def auth_only( account, password )
+      raise IOError, 'opening previously opened POP session' if started?
+      start(account, password) {
+        ;
+      }
+    end
+
+    #
+    # Session management
+    #
+
+    # Creates a new POP3 object and open the connection.  Equivalent to 
+    #
+    #   Net::POP3.new(address, port, isapop).start(account, password)
+    #
+    # If +block+ is provided, yields the newly-opened POP3 object to it,
+    # and automatically closes it at the end of the session.
+    #
+    # === Example
+    #
+    #    Net::POP3.start(addr, port, account, password) do |pop|
+    #      pop.each_mail do |m|
+    #        file.write m.pop
+    #        m.delete
+    #      end
+    #    end
+    #
+    def POP3.start( address, port = nil,
+                    account = nil, password = nil,
+                    isapop = false, &block ) # :yield: pop
+      new(address, port, isapop).start(account, password, &block)
+    end
+
+    # Creates a new POP3 object.
+    #
+    # +address+ is the hostname or ip address of your POP3 server.
+    #
+    # The optional +port+ is the port to connect to; it defaults to 110.
+    #
+    # The optional +isapop+ specifies whether this connection is going
+    # to use APOP authentication; it defaults to +false+.
+    #
+    # This method does *not* open the TCP connection.
+    def initialize( addr, port = nil, isapop = false )
+      @address = addr
+      @port = port || self.class.default_port
+      @apop = isapop
+
+      @command = nil
+      @socket = nil
+      @started = false
+      @open_timeout = 30
+      @read_timeout = 60
+      @debug_output = nil
+
+      @mails = nil
+      @n_mails = nil
+      @n_bytes = nil
+    end
+
+    # Does this instance use APOP authentication?
+    def apop?
+      @apop
+    end
+
+    # Provide human-readable stringification of class state.
+    def inspect
+      "#<#{self.class} #{@address}:#{@port} open=#{@started}>"
+    end
+
+    # *WARNING*: This method causes a serious security hole.
+    # Use this method only for debugging.
+    #
+    # Set an output stream for debugging.
+    #
+    # === Example
+    #
+    #   pop = Net::POP.new(addr, port)
+    #   pop.set_debug_output $stderr
+    #   pop.start(account, passwd) do |pop|
+    #     ....
+    #   end
+    #
+    def set_debug_output( arg )
+      @debug_output = arg
+    end
+
+    # The address to connect to.
+    attr_reader :address
+
+    # The port number to connect to.
+    attr_reader :port
+
+    # Seconds to wait until a connection is opened.
+    # If the POP3 object cannot open a connection within this time,
+    # it raises a TimeoutError exception.
+    attr_accessor :open_timeout
+
+    # Seconds to wait until reading one block (by one read(1) call).
+    # If the POP3 object cannot complete a read() within this time,
+    # it raises a TimeoutError exception.
+    attr_reader :read_timeout
+
+    # Set the read timeout.
+    def read_timeout=( sec )
+      @command.socket.read_timeout = sec if @command
+      @read_timeout = sec
+    end
+
+    # +true+ if the POP3 session has started.
+    def started?
+      @started
+    end
+
+    alias active? started?   #:nodoc: obsolete
+
+    # Starts a POP3 session.
+    #
+    # When called with block, gives a POP3 object to the block and
+    # closes the session after block call finishes.
+    #
+    # This method raises a POPAuthenticationError if authentication fails.
+    def start( account, password ) # :yield: pop
+      raise IOError, 'POP session already started' if @started
+
+      if block_given?
+        begin
+          do_start account, password
+          return yield(self)
+        ensure
+          do_finish
+        end
+      else
+        do_start account, password
+        return self
+      end
+    end
+
+    def do_start( account, password )
+      @socket = self.class.socket_type.old_open(@address, @port,
+                                   @open_timeout, @read_timeout, @debug_output)
+      on_connect
+      @command = POP3Command.new(@socket)
+      if apop?
+        @command.apop account, password
+      else
+        @command.auth account, password
+      end
+      @started = true
+    ensure
+      do_finish if not @started
+    end
+    private :do_start
+
+    def on_connect
+    end
+    private :on_connect
+
+    # Finishes a POP3 session and closes TCP connection.
+    def finish
+      raise IOError, 'POP session not yet started' unless started?
+      do_finish
+    end
+
+    def do_finish
+      @mails = nil
+      @command.quit if @command
+    ensure
+      @started = false
+      @command = nil
+      @socket.close if @socket and not @socket.closed?
+      @socket = nil
+    end
+    private :do_finish
+
+    def command
+      raise IOError, 'POP session not opened yet' \
+                                      if not @socket or @socket.closed?
+      @command
+    end
+    private :command
+
+    #
+    # POP protocol wrapper
+    #
+
+    # Returns the number of messages on the POP server.
+    def n_mails
+      return @n_mails if @n_mails
+      @n_mails, @n_bytes = command().stat
+      @n_mails
+    end
+
+    # Returns the total size in bytes of all the messages on the POP server.
+    def n_bytes
+      return @n_bytes if @n_bytes
+      @n_mails, @n_bytes = command().stat
+      @n_bytes
+    end
+
+    # Returns an array of Net::POPMail objects, representing all the
+    # messages on the server.  This array is renewed when the session
+    # restarts; otherwise, it is fetched from the server the first time
+    # this method is called (directly or indirectly) and cached.
+    #
+    # This method raises a POPError if an error occurs.
+    def mails
+      return @mails.dup if @mails
+      if n_mails() == 0
+        # some popd raises error for LIST on the empty mailbox.
+        @mails = []
+        return []
+      end
+
+      @mails = command().list.map {|num, size|
+        POPMail.new(num, size, self, command())
+      }
+      @mails.dup
+    end
+
+    # Yields each message to the passed-in block in turn.
+    # Equivalent to:
+    # 
+    #   pop3.mails.each do |popmail|
+    #     ....
+    #   end
+    #
+    # This method raises a POPError if an error occurs.
+    def each_mail( &block )  # :yield: message
+      mails().each(&block)
+    end
+
+    alias each each_mail
+
+    # Deletes all messages on the server.
+    #
+    # If called with a block, yields each message in turn before deleting it.
+    #
+    # === Example
+    #
+    #     n = 1
+    #     pop.delete_all do |m|
+    #       File.open("inbox/#{n}") do |f|
+    #         f.write m.pop
+    #       end
+    #       n += 1
+    #     end
+    #
+    # This method raises a POPError if an error occurs.
+    #
+    def delete_all # :yield: message
+      mails().each do |m|
+        yield m if block_given?
+        m.delete unless m.deleted?
+      end
+    end
+
+    # Resets the session.  This clears all "deleted" marks from messages.
+    #
+    # This method raises a POPError if an error occurs.
+    def reset
+      command().rset
+      mails().each do |m|
+        m.instance_eval {
+          @deleted = false
+        }
+      end
+    end
+
+    def set_all_uids   #:nodoc: internal use only (called from POPMail#uidl)
+      command().uidl.each do |num, uid|
+        @mails.find {|m| m.number == num }.uid = uid
+      end
+    end
+
+  end   # class POP3
+
+  # class aliases
+  POP = POP3
+  POPSession  = POP3
+  POP3Session = POP3
+
+  #
+  # This class is equivalent to POP3, except that it uses APOP authentication.
+  #
+  class APOP < POP3
+    # Always returns true.
+    def apop?
+      true
+    end
+  end
+
+  # class aliases
+  APOPSession = APOP
+
+  #
+  # This class represents a message which exists on the POP server.
+  # Instances of this class are created by the POP3 class; they should
+  # not be directly created by the user.
+  #
+  class POPMail
+
+    def initialize( num, len, pop, cmd )   #:nodoc:
+      @number = num
+      @length = len
+      @pop = pop
+      @command = cmd
+      @deleted = false
+      @uid = nil
+    end
+
+    # The sequence number of the message on the server.
+    attr_reader :number
+
+    # The length of the message in octets.
+    attr_reader :length
+    alias size length
+
+    # Provide human-readable stringification of class state.
+    def inspect
+      "#<#{self.class} #{@number}#{@deleted ? ' deleted' : ''}>"
+    end
+
+    #
+    # This method fetches the message.  If called with a block, the
+    # message is yielded to the block one chunk at a time.  If called
+    # without a block, the message is returned as a String.  The optional 
+    # +dest+ argument will be prepended to the returned String; this
+    # argument is essentially obsolete.
+    #
+    # === Example without block
+    #
+    #     POP3.start('pop.example.com', 110,
+    #                'YourAccount, 'YourPassword') do |pop|
+    #       n = 1
+    #       pop.mails.each do |popmail|
+    #         File.open("inbox/#{n}", 'w') do |f|
+    #           f.write popmail.pop              
+    #         end
+    #         popmail.delete
+    #         n += 1
+    #       end
+    #     end
+    #
+    # === Example with block
+    #
+    #     POP3.start('pop.example.com', 110,
+    #                'YourAccount, 'YourPassword') do |pop|
+    #       n = 1
+    #       pop.mails.each do |popmail|
+    #         File.open("inbox/#{n}", 'w') do |f|
+    #           popmail.pop do |chunk|            ####
+    #             f.write chunk
+    #           end
+    #         end
+    #         n += 1
+    #       end
+    #     end
+    #
+    # This method raises a POPError if an error occurs.
+    #
+    def pop( dest = '', &block ) # :yield: message_chunk
+      if block_given?
+        @command.retr(@number, &block)
+        nil
+      else
+        @command.retr(@number) do |chunk|
+          dest << chunk
+        end
+        dest
+      end
+    end
+
+    alias all pop    #:nodoc: obsolete
+    alias mail pop   #:nodoc: obsolete
+
+    # Fetches the message header and +lines+ lines of body. 
+    #
+    # The optional +dest+ argument is obsolete.
+    #
+    # This method raises a POPError if an error occurs.
+    def top( lines, dest = '' )
+      @command.top(@number, lines) do |chunk|
+        dest << chunk
+      end
+      dest
+    end
+
+    # Fetches the message header.     
+    #
+    # The optional +dest+ argument is obsolete.
+    #
+    # This method raises a POPError if an error occurs.
+    def header( dest = '' )
+      top(0, dest)
+    end
+
+    # Marks a message for deletion on the server.  Deletion does not
+    # actually occur until the end of the session; deletion may be
+    # cancelled for _all_ marked messages by calling POP3#reset().
+    #
+    # This method raises a POPError if an error occurs.
+    #
+    # === Example
+    #
+    #     POP3.start('pop.example.com', 110,
+    #                'YourAccount, 'YourPassword') do |pop|
+    #       n = 1
+    #       pop.mails.each do |popmail|
+    #         File.open("inbox/#{n}", 'w') do |f|
+    #           f.write popmail.pop
+    #         end
+    #         popmail.delete         ####
+    #         n += 1
+    #       end
+    #     end
+    #
+    def delete
+      @command.dele @number
+      @deleted = true
+    end
+
+    alias delete! delete    #:nodoc: obsolete
+
+    # True if the mail has been deleted.
+    def deleted?
+      @deleted
+    end
+
+    # Returns the unique-id of the message.
+    # Normally the unique-id is a hash string of the message.
+    #
+    # This method raises a POPError if an error occurs.
+    def unique_id
+      return @uid if @uid
+      @pop.set_all_uids
+      @uid
+    end
+
+    alias uidl unique_id
+
+    def uid=( uid )   #:nodoc: internal use only (used from POP3#set_all_uids)
+      @uid = uid
+    end
+
+  end   # class POPMail
+
+
+  class POP3Command   #:nodoc: internal use only
+
+    def initialize( sock )
+      @socket = sock
+      @error_occured = false
+      res = check_response(critical { recv_response() })
+      @apop_stamp = res.slice(/<.+>/)
+    end
+
+    def inspect
+      "#<#{self.class} socket=#{@socket}>"
+    end
+
+    def auth( account, password )
+      check_response_auth(critical {
+        check_response_auth(get_response('USER %s', account))
+        get_response('PASS %s', password)
+      })
+    end
+
+    def apop( account, password )
+      raise POPAuthenticationError, 'not APOP server; cannot login' \
+                                                      unless @apop_stamp
+      check_response_auth(critical {
+        get_response('APOP %s %s',
+                     account,
+                     Digest::MD5.hexdigest(@apop_stamp + password))
+      })
+    end
+
+    def list
+      critical {
+        getok 'LIST'
+        list = []
+        @socket.each_list_item do |line|
+          m = /\A(\d+)[ \t]+(\d+)/.match(line) or
+                  raise POPBadResponse, "bad response: #{line}"
+          list.push  [m[1].to_i, m[2].to_i]
+        end
+        return list
+      }
+    end
+
+    def stat
+      res = check_response(critical { get_response('STAT') })
+      m = /\A\+OK\s+(\d+)\s+(\d+)/.match(res) or
+              raise POPBadResponse, "wrong response format: #{res}"
+      [m[1].to_i, m[2].to_i]
+    end
+
+    def rset
+      check_response(critical { get_response 'RSET' })
+    end
+
+    def top( num, lines = 0, &block )
+      critical {
+        getok('TOP %d %d', num, lines)
+        @socket.each_message_chunk(&block)
+      }
+    end
+
+    def retr( num, &block )
+      critical {
+        getok('RETR %d', num)
+        @socket.each_message_chunk(&block)
+      }
+    end
+    
+    def dele( num )
+      check_response(critical { get_response('DELE %d', num) })
+    end
+
+    def uidl( num = nil )
+      if num
+        res = check_response(critical { get_response('UIDL %d', num) })
+        return res.split(/ /)[1]
+      else
+        critical {
+          getok('UIDL')
+          table = {}
+          @socket.each_list_item do |line|
+            num, uid = line.split
+            table[num.to_i] = uid
+          end
+          return table
+        }
+      end
+    end
+
+    def quit
+      check_response(critical { get_response('QUIT') })
+    end
+
+    private
+
+    def getok( fmt, *fargs )
+      @socket.writeline sprintf(fmt, *fargs)
+      check_response(recv_response())
+    end
+
+    def get_response( fmt, *fargs )
+      @socket.writeline sprintf(fmt, *fargs)
+      recv_response()
+    end
+
+    def recv_response
+      @socket.readline
+    end
+
+    def check_response( res )
+      raise POPError, res unless /\A\+OK/i === res
+      res
+    end
+
+    def check_response_auth( res )
+      raise POPAuthenticationError, res unless /\A\+OK/i === res
+      res
+    end
+
+    def critical
+      return '+OK dummy ok response' if @error_occured
+      begin
+        return yield()
+      rescue Exception
+        @error_occured = true
+        raise
+      end
+    end
+
+  end   # class POP3Command
+
+end   # module Net
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/protocol.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/protocol.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/protocol.rb	(revision 18425)
@@ -0,0 +1,390 @@
+#
+# = net/protocol.rb
+#
+#--
+# Copyright (c) 1999-2005 Yukihiro Matsumoto
+# Copyright (c) 1999-2005 Minero Aoki
+#
+# written and maintained by Minero Aoki <aamine@loveruby.net>
+#
+# This program is free software. You can re-distribute and/or
+# modify this program under the same terms as Ruby itself,
+# Ruby Distribute License or GNU General Public License.
+#
+# $Id: protocol.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#++
+#
+# WARNING: This file is going to remove.
+# Do not rely on the implementation written in this file.
+#
+
+require 'socket'
+require 'timeout'
+
+module Net # :nodoc:
+
+  class Protocol   #:nodoc: internal use only
+    private
+    def Protocol.protocol_param(name, val)
+      module_eval(<<-End, __FILE__, __LINE__ + 1)
+        def #{name}
+          #{val}
+        end
+      End
+    end
+  end
+
+
+  class ProtocolError          < StandardError; end
+  class ProtoSyntaxError       < ProtocolError; end
+  class ProtoFatalError        < ProtocolError; end
+  class ProtoUnknownError      < ProtocolError; end
+  class ProtoServerError       < ProtocolError; end
+  class ProtoAuthError         < ProtocolError; end
+  class ProtoCommandError      < ProtocolError; end
+  class ProtoRetriableError    < ProtocolError; end
+  ProtocRetryError = ProtoRetriableError
+
+
+  class BufferedIO   #:nodoc: internal use only
+    def initialize(io)
+      @io = io
+      @read_timeout = 60
+      @debug_output = nil
+      @rbuf = ''
+    end
+
+    attr_reader :io
+    attr_accessor :read_timeout
+    attr_accessor :debug_output
+
+    def inspect
+      "#<#{self.class} io=#{@io}>"
+    end
+
+    def closed?
+      @io.closed?
+    end
+
+    def close
+      @io.close
+    end
+
+    #
+    # Read
+    #
+
+    public
+
+    def read(len, dest = '', ignore_eof = false)
+      LOG "reading #{len} bytes..."
+      read_bytes = 0
+      begin
+        while read_bytes + @rbuf.size < len
+          dest << (s = rbuf_consume(@rbuf.size))
+          read_bytes += s.size
+          rbuf_fill
+        end
+        dest << (s = rbuf_consume(len - read_bytes))
+        read_bytes += s.size
+      rescue EOFError
+        raise unless ignore_eof
+      end
+      LOG "read #{read_bytes} bytes"
+      dest
+    end
+
+    def read_all(dest = '')
+      LOG 'reading all...'
+      read_bytes = 0
+      begin
+        while true
+          dest << (s = rbuf_consume(@rbuf.size))
+          read_bytes += s.size
+          rbuf_fill
+        end
+      rescue EOFError
+        ;
+      end
+      LOG "read #{read_bytes} bytes"
+      dest
+    end
+
+    def readuntil(terminator, ignore_eof = false)
+      begin
+        until idx = @rbuf.index(terminator)
+          rbuf_fill
+        end
+        return rbuf_consume(idx + terminator.size)
+      rescue EOFError
+        raise unless ignore_eof
+        return rbuf_consume(@rbuf.size)
+      end
+    end
+        
+    def readline
+      readuntil("\n").chop
+    end
+
+    private
+
+    def rbuf_fill
+      timeout(@read_timeout) {
+        @rbuf << @io.sysread(1024)
+      }
+    end
+
+    def rbuf_consume(len)
+      s = @rbuf.slice!(0, len)
+      @debug_output << %Q[-> #{s.dump}\n] if @debug_output
+      s
+    end
+
+    #
+    # Write
+    #
+
+    public
+
+    def write(str)
+      writing {
+        write0 str
+      }
+    end
+
+    def writeline(str)
+      writing {
+        write0 str + "\r\n"
+      }
+    end
+
+    private
+
+    def writing
+      @written_bytes = 0
+      @debug_output << '<- ' if @debug_output
+      yield
+      @debug_output << "\n" if @debug_output
+      bytes = @written_bytes
+      @written_bytes = nil
+      bytes
+    end
+
+    def write0(str)
+      @debug_output << str.dump if @debug_output
+      len = @io.write(str)
+      @written_bytes += len
+      len
+    end
+
+    #
+    # Logging
+    #
+
+    private
+
+    def LOG_off
+      @save_debug_out = @debug_output
+      @debug_output = nil
+    end
+
+    def LOG_on
+      @debug_output = @save_debug_out
+    end
+
+    def LOG(msg)
+      return unless @debug_output
+      @debug_output << msg + "\n"
+    end
+  end
+
+
+  class InternetMessageIO < BufferedIO   #:nodoc: internal use only
+    def InternetMessageIO.old_open(addr, port,
+        open_timeout = nil, read_timeout = nil, debug_output = nil)
+      debug_output << "opening connection to #{addr}...\n" if debug_output
+      s = timeout(open_timeout) { TCPsocket.new(addr, port) }
+      io = new(s)
+      io.read_timeout = read_timeout
+      io.debug_output = debug_output
+      io
+    end
+
+    def initialize(io)
+      super
+      @wbuf = nil
+    end
+
+    #
+    # Read
+    #
+
+    def each_message_chunk
+      LOG 'reading message...'
+      LOG_off()
+      read_bytes = 0
+      while (line = readuntil("\r\n")) != ".\r\n"
+        read_bytes += line.size
+        yield line.sub(/\A\./, '')
+      end
+      LOG_on()
+      LOG "read message (#{read_bytes} bytes)"
+    end
+  
+    # *library private* (cannot handle 'break')
+    def each_list_item
+      while (str = readuntil("\r\n")) != ".\r\n"
+        yield str.chop
+      end
+    end
+
+    def write_message_0(src)
+      prev = @written_bytes
+      each_crlf_line(src) do |line|
+        write0 line.sub(/\A\./, '..')
+      end
+      @written_bytes - prev
+    end
+
+    #
+    # Write
+    #
+
+    def write_message(src)
+      LOG "writing message from #{src.class}"
+      LOG_off()
+      len = writing {
+        using_each_crlf_line {
+          write_message_0 src
+        }
+      }
+      LOG_on()
+      LOG "wrote #{len} bytes"
+      len
+    end
+
+    def write_message_by_block(&block)
+      LOG 'writing message from block'
+      LOG_off()
+      len = writing {
+        using_each_crlf_line {
+          begin
+            block.call(WriteAdapter.new(self, :write_message_0))
+          rescue LocalJumpError
+            # allow `break' from writer block
+          end
+        }
+      }
+      LOG_on()
+      LOG "wrote #{len} bytes"
+      len
+    end
+
+    private
+
+    def using_each_crlf_line
+      @wbuf = ''
+      yield
+      if not @wbuf.empty?   # unterminated last line
+        write0 @wbuf.chomp + "\r\n"
+      elsif @written_bytes == 0   # empty src
+        write0 "\r\n"
+      end
+      write0 ".\r\n"
+      @wbuf = nil
+    end
+
+    def each_crlf_line(src)
+      buffer_filling(@wbuf, src) do
+        while line = @wbuf.slice!(/\A.*(?:\n|\r\n|\r(?!\z))/n)
+          yield line.chomp("\n") + "\r\n"
+        end
+      end
+    end
+
+    def buffer_filling(buf, src)
+      case src
+      when String    # for speeding up.
+        0.step(src.size - 1, 1024) do |i|
+          buf << src[i, 1024]
+          yield
+        end
+      when File    # for speeding up.
+        while s = src.read(1024)
+          buf << s
+          yield
+        end
+      else    # generic reader
+        src.each do |s|
+          buf << s
+          yield if buf.size > 1024
+        end
+        yield unless buf.empty?
+      end
+    end
+  end
+
+
+  #
+  # The writer adapter class
+  #
+  class WriteAdapter
+    def initialize(socket, method)
+      @socket = socket
+      @method_id = method
+    end
+
+    def inspect
+      "#<#{self.class} socket=#{@socket.inspect}>"
+    end
+
+    def write(str)
+      @socket.__send__(@method_id, str)
+    end
+
+    alias print write
+
+    def <<(str)
+      write str
+      self
+    end
+
+    def puts(str = '')
+      write str.chomp("\n") + "\n"
+    end
+
+    def printf(*args)
+      write sprintf(*args)
+    end
+  end
+
+
+  class ReadAdapter   #:nodoc: internal use only
+    def initialize(block)
+      @block = block
+    end
+
+    def inspect
+      "#<#{self.class}>"
+    end
+
+    def <<(str)
+      call_block(str, &@block) if @block
+    end
+
+    private
+
+    # This method is needed because @block must be called by yield,
+    # not Proc#call.  You can see difference when using `break' in
+    # the block.
+    def call_block(str)
+      yield str
+    end
+  end
+
+
+  module NetPrivate   #:nodoc: obsolete
+    Socket = ::Net::InternetMessageIO
+  end
+
+end   # module Net
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/smtp.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/smtp.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/smtp.rb	(revision 18425)
@@ -0,0 +1,697 @@
+# = net/smtp.rb
+# 
+# Copyright (c) 1999-2003 Yukihiro Matsumoto.
+#
+# Copyright (c) 1999-2003 Minero Aoki.
+# 
+# Written & maintained by Minero Aoki <aamine@loveruby.net>.
+#
+# Documented by William Webber and Minero Aoki.
+# 
+# This program is free software. You can re-distribute and/or
+# modify this program under the same terms as Ruby itself,
+# Ruby Distribute License or GNU General Public License.
+# 
+# NOTE: You can find Japanese version of this document in
+# the doc/net directory of the standard ruby interpreter package.
+# 
+# $Id: smtp.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+# See Net::SMTP for documentation. 
+# 
+
+require 'net/protocol'
+require 'digest/md5'
+
+module Net
+
+  # Module mixed in to all SMTP error classes
+  module SMTPError
+    # This *class* is module for some reason.
+    # In ruby 1.9.x, this module becomes a class.
+  end
+
+  # Represents an SMTP authentication error.
+  class SMTPAuthenticationError < ProtoAuthError
+    include SMTPError
+  end
+
+  # Represents SMTP error code 420 or 450, a temporary error.
+  class SMTPServerBusy < ProtoServerError
+    include SMTPError
+  end
+
+  # Represents an SMTP command syntax error (error code 500)
+  class SMTPSyntaxError < ProtoSyntaxError
+    include SMTPError
+  end
+
+  # Represents a fatal SMTP error (error code 5xx, except for 500)
+  class SMTPFatalError < ProtoFatalError
+    include SMTPError
+  end
+
+  # Unexpected reply code returned from server.
+  class SMTPUnknownError < ProtoUnknownError
+    include SMTPError
+  end
+
+  #
+  # = Net::SMTP
+  #
+  # == What is This Library?
+  # 
+  # This library provides functionality to send internet
+  # mail via SMTP, the Simple Mail Transfer Protocol. For details of
+  # SMTP itself, see [RFC2821] (http://www.ietf.org/rfc/rfc2821.txt).
+  # 
+  # == What is This Library NOT?
+  # 
+  # This library does NOT provide functions to compose internet mails.
+  # You must create them by yourself. If you want better mail support,
+  # try RubyMail or TMail. You can get both libraries from RAA.
+  # (http://www.ruby-lang.org/en/raa.html)
+  # 
+  # FYI: the official documentation on internet mail is: [RFC2822] (http://www.ietf.org/rfc/rfc2822.txt).
+  # 
+  # == Examples
+  # 
+  # === Sending Messages
+  # 
+  # You must open a connection to an SMTP server before sending messages.
+  # The first argument is the address of your SMTP server, and the second 
+  # argument is the port number. Using SMTP.start with a block is the simplest 
+  # way to do this. This way, the SMTP connection is closed automatically 
+  # after the block is executed.
+  # 
+  #     require 'net/smtp'
+  #     Net::SMTP.start('your.smtp.server', 25) do |smtp|
+  #       # Use the SMTP object smtp only in this block.
+  #     end
+  # 
+  # Replace 'your.smtp.server' with your SMTP server. Normally
+  # your system manager or internet provider supplies a server
+  # for you.
+  # 
+  # Then you can send messages.
+  # 
+  #     msgstr = <<END_OF_MESSAGE
+  #     From: Your Name <your@mail.address>
+  #     To: Destination Address <someone@example.com>
+  #     Subject: test message
+  #     Date: Sat, 23 Jun 2001 16:26:43 +0900
+  #     Message-Id: <unique.message.id.string@example.com>
+  # 
+  #     This is a test message.
+  #     END_OF_MESSAGE
+  # 
+  #     require 'net/smtp'
+  #     Net::SMTP.start('your.smtp.server', 25) do |smtp|
+  #       smtp.send_message msgstr,
+  #                         'your@mail.address',
+  #                         'his_addess@example.com'
+  #     end
+  # 
+  # === Closing the Session
+  # 
+  # You MUST close the SMTP session after sending messages, by calling 
+  # the #finish method:
+  # 
+  #     # using SMTP#finish
+  #     smtp = Net::SMTP.start('your.smtp.server', 25)
+  #     smtp.send_message msgstr, 'from@address', 'to@address'
+  #     smtp.finish
+  # 
+  # You can also use the block form of SMTP.start/SMTP#start.  This closes
+  # the SMTP session automatically:
+  # 
+  #     # using block form of SMTP.start
+  #     Net::SMTP.start('your.smtp.server', 25) do |smtp|
+  #       smtp.send_message msgstr, 'from@address', 'to@address'
+  #     end
+  # 
+  # I strongly recommend this scheme.  This form is simpler and more robust.
+  # 
+  # === HELO domain
+  # 
+  # In almost all situations, you must provide a third argument
+  # to SMTP.start/SMTP#start. This is the domain name which you are on
+  # (the host to send mail from). It is called the "HELO domain".
+  # The SMTP server will judge whether it should send or reject
+  # the SMTP session by inspecting the HELO domain.
+  # 
+  #     Net::SMTP.start('your.smtp.server', 25,
+  #                     'mail.from.domain') { |smtp| ... }
+  # 
+  # === SMTP Authentication
+  # 
+  # The Net::SMTP class supports three authentication schemes;
+  # PLAIN, LOGIN and CRAM MD5.  (SMTP Authentication: [RFC2554])
+  # To use SMTP authentication, pass extra arguments to 
+  # SMTP.start/SMTP#start.
+  # 
+  #     # PLAIN
+  #     Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain',
+  #                     'Your Account', 'Your Password', :plain)
+  #     # LOGIN
+  #     Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain',
+  #                     'Your Account', 'Your Password', :login)
+  # 
+  #     # CRAM MD5
+  #     Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain',
+  #                     'Your Account', 'Your Password', :cram_md5)
+  #
+  class SMTP
+
+    Revision = %q$Revision: 11708 $.split[1]
+
+    # The default SMTP port, port 25.
+    def SMTP.default_port
+      25
+    end
+
+    #
+    # Creates a new Net::SMTP object.
+    #
+    # +address+ is the hostname or ip address of your SMTP
+    # server.  +port+ is the port to connect to; it defaults to
+    # port 25.
+    #
+    # This method does not open the TCP connection.  You can use
+    # SMTP.start instead of SMTP.new if you want to do everything
+    # at once.  Otherwise, follow SMTP.new with SMTP#start.
+    #
+    def initialize( address, port = nil )
+      @address = address
+      @port = (port || SMTP.default_port)
+      @esmtp = true
+      @socket = nil
+      @started = false
+      @open_timeout = 30
+      @read_timeout = 60
+      @error_occured = false
+      @debug_output = nil
+    end
+
+    # Provide human-readable stringification of class state.
+    def inspect
+      "#<#{self.class} #{@address}:#{@port} started=#{@started}>"
+    end
+
+    # +true+ if the SMTP object uses ESMTP (which it does by default).
+    def esmtp?
+      @esmtp
+    end
+
+    #
+    # Set whether to use ESMTP or not.  This should be done before 
+    # calling #start.  Note that if #start is called in ESMTP mode,
+    # and the connection fails due to a ProtocolError, the SMTP
+    # object will automatically switch to plain SMTP mode and
+    # retry (but not vice versa).
+    #
+    def esmtp=( bool )
+      @esmtp = bool
+    end
+
+    alias esmtp esmtp?
+
+    # The address of the SMTP server to connect to.
+    attr_reader :address
+
+    # The port number of the SMTP server to connect to.
+    attr_reader :port
+
+    # Seconds to wait while attempting to open a connection.
+    # If the connection cannot be opened within this time, a
+    # TimeoutError is raised.
+    attr_accessor :open_timeout
+
+    # Seconds to wait while reading one block (by one read(2) call).
+    # If the read(2) call does not complete within this time, a
+    # TimeoutError is raised.
+    attr_reader :read_timeout
+
+    # Set the number of seconds to wait until timing-out a read(2)
+    # call.
+    def read_timeout=( sec )
+      @socket.read_timeout = sec if @socket
+      @read_timeout = sec
+    end
+
+    #
+    # WARNING: This method causes serious security holes.
+    # Use this method for only debugging.
+    #
+    # Set an output stream for debug logging.
+    # You must call this before #start.
+    #
+    #   # example
+    #   smtp = Net::SMTP.new(addr, port)
+    #   smtp.set_debug_output $stderr
+    #   smtp.start do |smtp|
+    #     ....
+    #   end
+    #
+    def set_debug_output( arg )
+      @debug_output = arg
+    end
+
+    #
+    # SMTP session control
+    #
+
+    #
+    # Creates a new Net::SMTP object and connects to the server.
+    #
+    # This method is equivalent to:
+    # 
+    #   Net::SMTP.new(address, port).start(helo_domain, account, password, authtype)
+    #
+    # === Example
+    #
+    #     Net::SMTP.start('your.smtp.server') do |smtp|
+    #       smtp.send_message msgstr, 'from@example.com', ['dest@example.com']
+    #     end
+    #
+    # === Block Usage
+    #
+    # If called with a block, the newly-opened Net::SMTP object is yielded
+    # to the block, and automatically closed when the block finishes.  If called
+    # without a block, the newly-opened Net::SMTP object is returned to
+    # the caller, and it is the caller's responsibility to close it when
+    # finished.
+    #
+    # === Parameters
+    #
+    # +address+ is the hostname or ip address of your smtp server.
+    #
+    # +port+ is the port to connect to; it defaults to port 25.
+    #
+    # +helo+ is the _HELO_ _domain_ provided by the client to the
+    # server (see overview comments); it defaults to 'localhost.localdomain'. 
+    #
+    # The remaining arguments are used for SMTP authentication, if required
+    # or desired.  +user+ is the account name; +secret+ is your password
+    # or other authentication token; and +authtype+ is the authentication
+    # type, one of :plain, :login, or :cram_md5.  See the discussion of
+    # SMTP Authentication in the overview notes.
+    #
+    # === Errors
+    #
+    # This method may raise:
+    #
+    # * Net::SMTPAuthenticationError
+    # * Net::SMTPServerBusy
+    # * Net::SMTPSyntaxError
+    # * Net::SMTPFatalError
+    # * Net::SMTPUnknownError
+    # * IOError
+    # * TimeoutError
+    #
+    def SMTP.start( address, port = nil,
+                    helo = 'localhost.localdomain',
+                    user = nil, secret = nil, authtype = nil,
+                    &block) # :yield: smtp
+      new(address, port).start(helo, user, secret, authtype, &block)
+    end
+
+    # +true+ if the SMTP session has been started.
+    def started?
+      @started
+    end
+
+    #
+    # Opens a TCP connection and starts the SMTP session.
+    #
+    # === Parameters
+    #
+    # +helo+ is the _HELO_ _domain_ that you'll dispatch mails from; see
+    # the discussion in the overview notes.
+    #
+    # If both of +user+ and +secret+ are given, SMTP authentication 
+    # will be attempted using the AUTH command.  +authtype+ specifies 
+    # the type of authentication to attempt; it must be one of
+    # :login, :plain, and :cram_md5.  See the notes on SMTP Authentication
+    # in the overview. 
+    #
+    # === Block Usage
+    #
+    # When this methods is called with a block, the newly-started SMTP
+    # object is yielded to the block, and automatically closed after
+    # the block call finishes.  Otherwise, it is the caller's 
+    # responsibility to close the session when finished.
+    #
+    # === Example
+    #
+    # This is very similar to the class method SMTP.start.
+    #
+    #     require 'net/smtp' 
+    #     smtp = Net::SMTP.new('smtp.mail.server', 25)
+    #     smtp.start(helo_domain, account, password, authtype) do |smtp|
+    #       smtp.send_message msgstr, 'from@example.com', ['dest@example.com']
+    #     end 
+    #
+    # The primary use of this method (as opposed to SMTP.start)
+    # is probably to set debugging (#set_debug_output) or ESMTP
+    # (#esmtp=), which must be done before the session is
+    # started.  
+    #
+    # === Errors
+    #
+    # If session has already been started, an IOError will be raised.
+    #
+    # This method may raise:
+    #
+    # * Net::SMTPAuthenticationError
+    # * Net::SMTPServerBusy
+    # * Net::SMTPSyntaxError
+    # * Net::SMTPFatalError
+    # * Net::SMTPUnknownError
+    # * IOError
+    # * TimeoutError
+    #
+    def start( helo = 'localhost.localdomain',
+               user = nil, secret = nil, authtype = nil ) # :yield: smtp
+      if block_given?
+        begin
+          do_start(helo, user, secret, authtype)
+          return yield(self)
+        ensure
+          do_finish
+        end
+      else
+        do_start(helo, user, secret, authtype)
+        return self
+      end
+    end
+
+    def do_start( helodomain, user, secret, authtype )
+      raise IOError, 'SMTP session already started' if @started
+      check_auth_args user, secret, authtype if user or secret
+
+      @socket = InternetMessageIO.old_open(@address, @port,
+                                       @open_timeout, @read_timeout,
+                                       @debug_output)
+      check_response(critical { recv_response() })
+      begin
+        if @esmtp
+          ehlo helodomain
+        else
+          helo helodomain
+        end
+      rescue ProtocolError
+        if @esmtp
+          @esmtp = false
+          @error_occured = false
+          retry
+        end
+        raise
+      end
+      authenticate user, secret, authtype if user
+      @started = true
+    ensure
+      @socket.close if not @started and @socket and not @socket.closed?
+    end
+    private :do_start
+
+    # Finishes the SMTP session and closes TCP connection.
+    # Raises IOError if not started.
+    def finish
+      raise IOError, 'not yet started' unless started?
+      do_finish
+    end
+
+    def do_finish
+      quit if @socket and not @socket.closed? and not @error_occured
+    ensure
+      @started = false
+      @error_occured = false
+      @socket.close if @socket and not @socket.closed?
+      @socket = nil
+    end
+    private :do_finish
+
+    #
+    # message send
+    #
+
+    public
+
+    #
+    # Sends +msgstr+ as a message.  Single CR ("\r") and LF ("\n") found
+    # in the +msgstr+, are converted into the CR LF pair.  You cannot send a
+    # binary message with this method. +msgstr+ should include both 
+    # the message headers and body.
+    #
+    # +from_addr+ is a String representing the source mail address.
+    #
+    # +to_addr+ is a String or Strings or Array of Strings, representing
+    # the destination mail address or addresses.
+    #
+    # === Example
+    #
+    #     Net::SMTP.start('smtp.example.com') do |smtp|
+    #       smtp.send_message msgstr,
+    #                         'from@example.com',
+    #                         ['dest@example.com', 'dest2@example.com']
+    #     end
+    #
+    # === Errors
+    #
+    # This method may raise:
+    #
+    # * Net::SMTPServerBusy
+    # * Net::SMTPSyntaxError
+    # * Net::SMTPFatalError
+    # * Net::SMTPUnknownError
+    # * IOError
+    # * TimeoutError
+    #
+    def send_message( msgstr, from_addr, *to_addrs )
+      send0(from_addr, to_addrs.flatten) {
+        @socket.write_message msgstr
+      }
+    end
+
+    alias send_mail send_message
+    alias sendmail send_message   # obsolete
+
+    #
+    # Opens a message writer stream and gives it to the block.
+    # The stream is valid only in the block, and has these methods:
+    #
+    # puts(str = '')::       outputs STR and CR LF.
+    # print(str)::           outputs STR.
+    # printf(fmt, *args)::   outputs sprintf(fmt,*args).
+    # write(str)::           outputs STR and returns the length of written bytes.
+    # <<(str)::              outputs STR and returns self.
+    #
+    # If a single CR ("\r") or LF ("\n") is found in the message,
+    # it is converted to the CR LF pair.  You cannot send a binary
+    # message with this method.
+    #
+    # === Parameters
+    #
+    # +from_addr+ is a String representing the source mail address.
+    #
+    # +to_addr+ is a String or Strings or Array of Strings, representing
+    # the destination mail address or addresses.
+    #
+    # === Example
+    #
+    #     Net::SMTP.start('smtp.example.com', 25) do |smtp|
+    #       smtp.open_message_stream('from@example.com', ['dest@example.com']) do |f|
+    #         f.puts 'From: from@example.com'
+    #         f.puts 'To: dest@example.com'
+    #         f.puts 'Subject: test message'
+    #         f.puts
+    #         f.puts 'This is a test message.'
+    #       end
+    #     end
+    #
+    # === Errors
+    #
+    # This method may raise:
+    #
+    # * Net::SMTPServerBusy
+    # * Net::SMTPSyntaxError
+    # * Net::SMTPFatalError
+    # * Net::SMTPUnknownError
+    # * IOError
+    # * TimeoutError
+    #
+    def open_message_stream( from_addr, *to_addrs, &block ) # :yield: stream
+      send0(from_addr, to_addrs.flatten) {
+        @socket.write_message_by_block(&block)
+      }
+    end
+
+    alias ready open_message_stream   # obsolete
+
+    private
+
+    def send0( from_addr, to_addrs )
+      raise IOError, 'closed session' unless @socket
+      raise ArgumentError, 'mail destination not given' if to_addrs.empty?
+      if $SAFE > 0
+        raise SecurityError, 'tainted from_addr' if from_addr.tainted?
+        to_addrs.each do |to| 
+          raise SecurityError, 'tainted to_addr' if to.tainted?
+        end
+      end
+
+      mailfrom from_addr
+      to_addrs.each do |to|
+        rcptto to
+      end
+      res = critical {
+        check_response(get_response('DATA'), true)
+        yield
+        recv_response()
+      }
+      check_response(res)
+    end
+
+    #
+    # auth
+    #
+
+    private
+
+    def check_auth_args( user, secret, authtype )
+      raise ArgumentError, 'both user and secret are required'\
+                      unless user and secret
+      auth_method = "auth_#{authtype || 'cram_md5'}"
+      raise ArgumentError, "wrong auth type #{authtype}"\
+                      unless respond_to?(auth_method, true)
+    end
+
+    def authenticate( user, secret, authtype )
+      __send__("auth_#{authtype || 'cram_md5'}", user, secret)
+    end
+
+    def auth_plain( user, secret )
+      res = critical { get_response('AUTH PLAIN %s',
+                                    base64_encode("\0#{user}\0#{secret}")) }
+      raise SMTPAuthenticationError, res unless /\A2../ === res
+    end
+
+    def auth_login( user, secret )
+      res = critical {
+        check_response(get_response('AUTH LOGIN'), true)
+        check_response(get_response(base64_encode(user)), true)
+        get_response(base64_encode(secret))
+      }
+      raise SMTPAuthenticationError, res unless /\A2../ === res
+    end
+
+    def auth_cram_md5( user, secret )
+      # CRAM-MD5: [RFC2195]
+      res = nil
+      critical {
+        res = check_response(get_response('AUTH CRAM-MD5'), true)
+        challenge = res.split(/ /)[1].unpack('m')[0]
+        secret = Digest::MD5.digest(secret) if secret.size > 64
+
+        isecret = secret + "\0" * (64 - secret.size)
+        osecret = isecret.dup
+        0.upto(63) do |i|
+          isecret[i] ^= 0x36
+          osecret[i] ^= 0x5c
+        end
+        tmp = Digest::MD5.digest(isecret + challenge)
+        tmp = Digest::MD5.hexdigest(osecret + tmp)
+
+        res = get_response(base64_encode(user + ' ' + tmp))
+      }
+      raise SMTPAuthenticationError, res unless /\A2../ === res
+    end
+
+    def base64_encode( str )
+      # expects "str" may not become too long
+      [str].pack('m').gsub(/\s+/, '')
+    end
+
+    #
+    # SMTP command dispatcher
+    #
+
+    private
+
+    def helo( domain )
+      getok('HELO %s', domain)
+    end
+
+    def ehlo( domain )
+      getok('EHLO %s', domain)
+    end
+
+    def mailfrom( fromaddr )
+      getok('MAIL FROM:<%s>', fromaddr)
+    end
+
+    def rcptto( to )
+      getok('RCPT TO:<%s>', to)
+    end
+
+    def quit
+      getok('QUIT')
+    end
+
+    #
+    # row level library
+    #
+
+    private
+
+    def getok( fmt, *args )
+      res = critical {
+        @socket.writeline sprintf(fmt, *args)
+        recv_response()
+      }
+      return check_response(res)
+    end
+
+    def get_response( fmt, *args )
+      @socket.writeline sprintf(fmt, *args)
+      recv_response()
+    end
+
+    def recv_response
+      res = ''
+      while true
+        line = @socket.readline
+        res << line << "\n"
+        break unless line[3] == ?-   # "210-PIPELINING"
+      end
+      res
+    end
+
+    def check_response( res, allow_continue = false )
+      return res if /\A2/ === res
+      return res if allow_continue and /\A3/ === res
+      err = case res
+            when /\A4/  then SMTPServerBusy
+            when /\A50/ then SMTPSyntaxError
+            when /\A55/ then SMTPFatalError
+            else SMTPUnknownError
+            end
+      raise err, res
+    end
+
+    def critical( &block )
+      return '200 dummy reply code' if @error_occured
+      begin
+        return yield()
+      rescue Exception
+        @error_occured = true
+        raise
+      end
+    end
+
+  end   # class SMTP
+
+  SMTPSession = SMTP
+
+end   # module Net
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/telnet.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/telnet.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/telnet.rb	(revision 18425)
@@ -0,0 +1,742 @@
+# = net/telnet.rb - Simple Telnet Client Library
+# 
+# Author:: Wakou Aoyama <wakou@ruby-lang.org>
+# Documentation:: William Webber and Wakou Aoyama 
+#
+# This file holds the class Net::Telnet, which provides client-side
+# telnet functionality.
+#
+# For documentation, see Net::Telnet.
+#
+
+require "socket"
+require "delegate"
+require "timeout"
+require "English"
+ 
+module Net
+
+  #
+  # == Net::Telnet
+  #
+  # Provides telnet client functionality.
+  #
+  # This class also has, through delegation, all the methods of a
+  # socket object (by default, a +TCPSocket+, but can be set by the
+  # +Proxy+ option to <tt>new()</tt>).  This provides methods such as
+  # <tt>close()</tt> to end the session and <tt>sysread()</tt> to read
+  # data directly from the host, instead of via the <tt>waitfor()</tt>
+  # mechanism.  Note that if you do use <tt>sysread()</tt> directly
+  # when in telnet mode, you should probably pass the output through
+  # <tt>preprocess()</tt> to extract telnet command sequences.
+  #
+  # == Overview
+  #
+  # The telnet protocol allows a client to login remotely to a user
+  # account on a server and execute commands via a shell.  The equivalent
+  # is done by creating a Net::Telnet class with the +Host+ option
+  # set to your host, calling #login() with your user and password,
+  # issuing one or more #cmd() calls, and then calling #close()
+  # to end the session.  The #waitfor(), #print(), #puts(), and
+  # #write() methods, which #cmd() is implemented on top of, are
+  # only needed if you are doing something more complicated.
+  #
+  # A Net::Telnet object can also be used to connect to non-telnet
+  # services, such as SMTP or HTTP.  In this case, you normally
+  # want to provide the +Port+ option to specify the port to
+  # connect to, and set the +Telnetmode+ option to false to prevent
+  # the client from attempting to interpret telnet command sequences.
+  # Generally, #login() will not work with other protocols, and you
+  # have to handle authentication yourself.
+  #
+  # For some protocols, it will be possible to specify the +Prompt+
+  # option once when you create the Telnet object and use #cmd() calls; 
+  # for others, you will have to specify the response sequence to
+  # look for as the Match option to every #cmd() call, or call
+  # #puts() and #waitfor() directly; for yet others, you will have 
+  # to use #sysread() instead of #waitfor() and parse server 
+  # responses yourself.
+  #
+  # It is worth noting that when you create a new Net::Telnet object,
+  # you can supply a proxy IO channel via the Proxy option.  This
+  # can be used to attach the Telnet object to other Telnet objects,
+  # to already open sockets, or to any read-write IO object.  This
+  # can be useful, for instance, for setting up a test fixture for
+  # unit testing.
+  # 
+  # == Examples
+  # 
+  # === Log in and send a command, echoing all output to stdout
+  # 
+  #   localhost = Net::Telnet::new("Host" => "localhost",
+  #                                "Timeout" => 10,
+  #                                "Prompt" => /[$%#>] \z/n)
+  #   localhost.login("username", "password") { |c| print c }
+  #   localhost.cmd("command") { |c| print c }
+  #   localhost.close
+  # 
+  # 
+  # === Check a POP server to see if you have mail
+  # 
+  #   pop = Net::Telnet::new("Host" => "your_destination_host_here",
+  #                          "Port" => 110,
+  #                          "Telnetmode" => false,
+  #                          "Prompt" => /^\+OK/n)
+  #   pop.cmd("user " + "your_username_here") { |c| print c }
+  #   pop.cmd("pass " + "your_password_here") { |c| print c }
+  #   pop.cmd("list") { |c| print c }
+  #
+  # == References
+  #
+  # There are a large number of RFCs relevant to the Telnet protocol.
+  # RFCs 854-861 define the base protocol.  For a complete listing
+  # of relevant RFCs, see
+  # http://www.omnifarious.org/~hopper/technical/telnet-rfc.html
+  #
+  class Telnet < SimpleDelegator
+
+    # :stopdoc:
+    IAC   = 255.chr # "\377" # "\xff" # interpret as command
+    DONT  = 254.chr # "\376" # "\xfe" # you are not to use option 
+    DO    = 253.chr # "\375" # "\xfd" # please, you use option 
+    WONT  = 252.chr # "\374" # "\xfc" # I won't use option 
+    WILL  = 251.chr # "\373" # "\xfb" # I will use option 
+    SB    = 250.chr # "\372" # "\xfa" # interpret as subnegotiation 
+    GA    = 249.chr # "\371" # "\xf9" # you may reverse the line 
+    EL    = 248.chr # "\370" # "\xf8" # erase the current line 
+    EC    = 247.chr # "\367" # "\xf7" # erase the current character 
+    AYT   = 246.chr # "\366" # "\xf6" # are you there 
+    AO    = 245.chr # "\365" # "\xf5" # abort output--but let prog finish 
+    IP    = 244.chr # "\364" # "\xf4" # interrupt process--permanently 
+    BREAK = 243.chr # "\363" # "\xf3" # break 
+    DM    = 242.chr # "\362" # "\xf2" # data mark--for connect. cleaning 
+    NOP   = 241.chr # "\361" # "\xf1" # nop 
+    SE    = 240.chr # "\360" # "\xf0" # end sub negotiation 
+    EOR   = 239.chr # "\357" # "\xef" # end of record (transparent mode) 
+    ABORT = 238.chr # "\356" # "\xee" # Abort process 
+    SUSP  = 237.chr # "\355" # "\xed" # Suspend process 
+    EOF   = 236.chr # "\354" # "\xec" # End of file 
+    SYNCH = 242.chr # "\362" # "\xf2" # for telfunc calls 
+
+    OPT_BINARY         =   0.chr # "\000" # "\x00" # Binary Transmission 
+    OPT_ECHO           =   1.chr # "\001" # "\x01" # Echo 
+    OPT_RCP            =   2.chr # "\002" # "\x02" # Reconnection 
+    OPT_SGA            =   3.chr # "\003" # "\x03" # Suppress Go Ahead 
+    OPT_NAMS           =   4.chr # "\004" # "\x04" # Approx Message Size Negotiation 
+    OPT_STATUS         =   5.chr # "\005" # "\x05" # Status 
+    OPT_TM             =   6.chr # "\006" # "\x06" # Timing Mark 
+    OPT_RCTE           =   7.chr # "\a"   # "\x07" # Remote Controlled Trans and Echo 
+    OPT_NAOL           =   8.chr # "\010" # "\x08" # Output Line Width 
+    OPT_NAOP           =   9.chr # "\t"   # "\x09" # Output Page Size 
+    OPT_NAOCRD         =  10.chr # "\n"   # "\x0a" # Output Carriage-Return Disposition 
+    OPT_NAOHTS         =  11.chr # "\v"   # "\x0b" # Output Horizontal Tab Stops 
+    OPT_NAOHTD         =  12.chr # "\f"   # "\x0c" # Output Horizontal Tab Disposition 
+    OPT_NAOFFD         =  13.chr # "\r"   # "\x0d" # Output Formfeed Disposition 
+    OPT_NAOVTS         =  14.chr # "\016" # "\x0e" # Output Vertical Tabstops 
+    OPT_NAOVTD         =  15.chr # "\017" # "\x0f" # Output Vertical Tab Disposition 
+    OPT_NAOLFD         =  16.chr # "\020" # "\x10" # Output Linefeed Disposition 
+    OPT_XASCII         =  17.chr # "\021" # "\x11" # Extended ASCII 
+    OPT_LOGOUT         =  18.chr # "\022" # "\x12" # Logout 
+    OPT_BM             =  19.chr # "\023" # "\x13" # Byte Macro 
+    OPT_DET            =  20.chr # "\024" # "\x14" # Data Entry Terminal 
+    OPT_SUPDUP         =  21.chr # "\025" # "\x15" # SUPDUP 
+    OPT_SUPDUPOUTPUT   =  22.chr # "\026" # "\x16" # SUPDUP Output 
+    OPT_SNDLOC         =  23.chr # "\027" # "\x17" # Send Location 
+    OPT_TTYPE          =  24.chr # "\030" # "\x18" # Terminal Type 
+    OPT_EOR            =  25.chr # "\031" # "\x19" # End of Record 
+    OPT_TUID           =  26.chr # "\032" # "\x1a" # TACACS User Identification 
+    OPT_OUTMRK         =  27.chr # "\e"   # "\x1b" # Output Marking 
+    OPT_TTYLOC         =  28.chr # "\034" # "\x1c" # Terminal Location Number 
+    OPT_3270REGIME     =  29.chr # "\035" # "\x1d" # Telnet 3270 Regime 
+    OPT_X3PAD          =  30.chr # "\036" # "\x1e" # X.3 PAD 
+    OPT_NAWS           =  31.chr # "\037" # "\x1f" # Negotiate About Window Size 
+    OPT_TSPEED         =  32.chr # " "    # "\x20" # Terminal Speed 
+    OPT_LFLOW          =  33.chr # "!"    # "\x21" # Remote Flow Control 
+    OPT_LINEMODE       =  34.chr # "\""   # "\x22" # Linemode 
+    OPT_XDISPLOC       =  35.chr # "#"    # "\x23" # X Display Location 
+    OPT_OLD_ENVIRON    =  36.chr # "$"    # "\x24" # Environment Option 
+    OPT_AUTHENTICATION =  37.chr # "%"    # "\x25" # Authentication Option 
+    OPT_ENCRYPT        =  38.chr # "&"    # "\x26" # Encryption Option 
+    OPT_NEW_ENVIRON    =  39.chr # "'"    # "\x27" # New Environment Option 
+    OPT_EXOPL          = 255.chr # "\377" # "\xff" # Extended-Options-List 
+
+    NULL = "\000" 
+    CR   = "\015"   
+    LF   = "\012" 
+    EOL  = CR + LF 
+    REVISION = '$Id: telnet.rb 11708 2007-02-12 23:01:19Z shyouhei $'
+    # :startdoc:
+
+    #
+    # Creates a new Net::Telnet object.
+    #
+    # Attempts to connect to the host (unless the Proxy option is
+    # provided: see below).  If a block is provided, it is yielded
+    # status messages on the attempt to connect to the server, of
+    # the form:
+    # 
+    #   Trying localhost...
+    #   Connected to localhost.
+    #
+    # +options+ is a hash of options.  The following example lists
+    # all options and their default values.
+    # 
+    #   host = Net::Telnet::new(
+    #            "Host"       => "localhost",  # default: "localhost"
+    #            "Port"       => 23,           # default: 23
+    #            "Binmode"    => false,        # default: false
+    #            "Output_log" => "output_log", # default: nil (no output)
+    #            "Dump_log"   => "dump_log",   # default: nil (no output)
+    #            "Prompt"     => /[$%#>] \z/n, # default: /[$%#>] \z/n
+    #            "Telnetmode" => true,         # default: true
+    #            "Timeout"    => 10,           # default: 10
+    #              # if ignore timeout then set "Timeout" to false.
+    #            "Waittime"   => 0,            # default: 0
+    #            "Proxy"      => proxy         # default: nil
+    #                            # proxy is Net::Telnet or IO object
+    #          )
+    #
+    # The options have the following meanings:
+    #
+    # Host:: the hostname or IP address of the host to connect to, as a String. 
+    #        Defaults to "localhost".
+    #
+    # Port:: the port to connect to.  Defaults to 23.
+    #
+    # Binmode:: if false (the default), newline substitution is performed.  
+    #           Outgoing LF is
+    #           converted to CRLF, and incoming CRLF is converted to LF.  If
+    #           true, this substitution is not performed.  This value can
+    #           also be set with the #binmode() method.  The 
+    #           outgoing conversion only applies to the #puts() and #print()
+    #           methods, not the #write() method.  The precise nature of
+    #           the newline conversion is also affected by the telnet options
+    #           SGA and BIN.
+    #
+    # Output_log:: the name of the file to write connection status messages
+    #              and all received traffic to.  In the case of a proper
+    #              Telnet session, this will include the client input as
+    #              echoed by the host; otherwise, it only includes server
+    #              responses.  Output is appended verbatim to this file.  
+    #              By default, no output log is kept.
+    #
+    # Dump_log:: as for Output_log, except that output is written in hexdump
+    #            format (16 bytes per line as hex pairs, followed by their
+    #            printable equivalent), with connection status messages
+    #            preceded by '#', sent traffic preceded by '>', and 
+    #            received traffic preceded by '<'.  By default, not dump log
+    #            is kept.
+    #
+    # Prompt:: a regular expression matching the host's command-line prompt
+    #          sequence.  This is needed by the Telnet class to determine
+    #          when the output from a command has finished and the host is
+    #          ready to receive a new command.  By default, this regular
+    #          expression is /[$%#>] \z/n.
+    #
+    # Telnetmode:: a boolean value, true by default.  In telnet mode, 
+    #              traffic received from the host is parsed for special
+    #              command sequences, and these sequences are escaped
+    #              in outgoing traffic sent using #puts() or #print()
+    #              (but not #write()).  If you are using the Net::Telnet
+    #              object to connect to a non-telnet service (such as
+    #              SMTP or POP), this should be set to "false" to prevent
+    #              undesired data corruption.  This value can also be set
+    #              by the #telnetmode() method.
+    #
+    # Timeout:: the number of seconds to wait before timing out both the
+    #           initial attempt to connect to host (in this constructor),
+    #           and all attempts to read data from the host (in #waitfor(),
+    #           #cmd(), and #login()).  Exceeding this timeout causes a
+    #           TimeoutError to be raised.  The default value is 10 seconds.
+    #           You can disable the timeout by setting this value to false.
+    #           In this case, the connect attempt will eventually timeout
+    #           on the underlying connect(2) socket call with an
+    #           Errno::ETIMEDOUT error (but generally only after a few
+    #           minutes), but other attempts to read data from the host
+    #           will hand indefinitely if no data is forthcoming.
+    #
+    # Waittime:: the amount of time to wait after seeing what looks like a 
+    #            prompt (that is, received data that matches the Prompt
+    #            option regular expression) to see if more data arrives.
+    #            If more data does arrive in this time, Net::Telnet assumes
+    #            that what it saw was not really a prompt.  This is to try to 
+    #            avoid false matches, but it can also lead to missing real
+    #            prompts (if, for instance, a background process writes to
+    #            the terminal soon after the prompt is displayed).  By
+    #            default, set to 0, meaning not to wait for more data.
+    #
+    # Proxy:: a proxy object to used instead of opening a direct connection
+    #         to the host.  Must be either another Net::Telnet object or
+    #         an IO object.  If it is another Net::Telnet object, this 
+    #         instance will use that one's socket for communication.  If an
+    #         IO object, it is used directly for communication.  Any other
+    #         kind of object will cause an error to be raised.
+    #
+    def initialize(options) # :yield: mesg 
+      @options = options
+      @options["Host"]       = "localhost"   unless @options.has_key?("Host")
+      @options["Port"]       = 23            unless @options.has_key?("Port")
+      @options["Prompt"]     = /[$%#>] \z/n  unless @options.has_key?("Prompt")
+      @options["Timeout"]    = 10            unless @options.has_key?("Timeout")
+      @options["Waittime"]   = 0             unless @options.has_key?("Waittime")
+      unless @options.has_key?("Binmode")
+        @options["Binmode"]    = false         
+      else
+        unless (true == @options["Binmode"] or false == @options["Binmode"])
+          raise ArgumentError, "Binmode option must be true or false"
+        end
+      end
+
+      unless @options.has_key?("Telnetmode")
+        @options["Telnetmode"] = true          
+      else
+        unless (true == @options["Telnetmode"] or false == @options["Telnetmode"])
+          raise ArgumentError, "Telnetmode option must be true or false"
+        end
+      end
+
+      @telnet_option = { "SGA" => false, "BINARY" => false }
+
+      if @options.has_key?("Output_log")
+        @log = File.open(@options["Output_log"], 'a+')
+        @log.sync = true
+        @log.binmode
+      end
+
+      if @options.has_key?("Dump_log")
+        @dumplog = File.open(@options["Dump_log"], 'a+')
+        @dumplog.sync = true
+        @dumplog.binmode
+        def @dumplog.log_dump(dir, x)  # :nodoc:
+          len = x.length
+          addr = 0
+          offset = 0
+          while 0 < len
+            if len < 16
+              line = x[offset, len]
+            else
+              line = x[offset, 16]
+            end
+            hexvals = line.unpack('H*')[0]
+            hexvals += ' ' * (32 - hexvals.length)
+            hexvals = format("%s %s %s %s  " * 4, *hexvals.unpack('a2' * 16))
+            line = line.gsub(/[\000-\037\177-\377]/n, '.')
+            printf "%s 0x%5.5x: %s%s\n", dir, addr, hexvals, line
+            addr += 16
+            offset += 16
+            len -= 16
+          end
+          print "\n"
+        end
+      end
+
+      if @options.has_key?("Proxy")
+        if @options["Proxy"].kind_of?(Net::Telnet)
+          @sock = @options["Proxy"].sock
+        elsif @options["Proxy"].kind_of?(IO)
+          @sock = @options["Proxy"]
+        else
+          raise "Error: Proxy must be an instance of Net::Telnet or IO."
+        end
+      else
+        message = "Trying " + @options["Host"] + "...\n"
+        yield(message) if block_given?
+        @log.write(message) if @options.has_key?("Output_log")
+        @dumplog.log_dump('#', message) if @options.has_key?("Dump_log")
+
+        begin
+          if @options["Timeout"] == false
+            @sock = TCPSocket.open(@options["Host"], @options["Port"])
+          else
+            timeout(@options["Timeout"]) do
+              @sock = TCPSocket.open(@options["Host"], @options["Port"])
+            end
+          end
+        rescue TimeoutError
+          raise TimeoutError, "timed out while opening a connection to the host"
+        rescue
+          @log.write($ERROR_INFO.to_s + "\n") if @options.has_key?("Output_log")
+          @dumplog.log_dump('#', $ERROR_INFO.to_s + "\n") if @options.has_key?("Dump_log")
+          raise
+        end
+        @sock.sync = true
+        @sock.binmode
+
+        message = "Connected to " + @options["Host"] + ".\n"
+        yield(message) if block_given?
+        @log.write(message) if @options.has_key?("Output_log")
+        @dumplog.log_dump('#', message) if @options.has_key?("Dump_log")
+      end
+
+      super(@sock)
+    end # initialize
+
+    # The socket the Telnet object is using.  Note that this object becomes
+    # a delegate of the Telnet object, so normally you invoke its methods
+    # directly on the Telnet object.
+    attr :sock 
+
+    # Set telnet command interpretation on (+mode+ == true) or off
+    # (+mode+ == false), or return the current value (+mode+ not
+    # provided).  It should be on for true telnet sessions, off if
+    # using Net::Telnet to connect to a non-telnet service such
+    # as SMTP.
+    def telnetmode(mode = nil)
+      case mode
+      when nil
+        @options["Telnetmode"]
+      when true, false
+        @options["Telnetmode"] = mode
+      else
+        raise ArgumentError, "argument must be true or false, or missing"
+      end
+    end
+
+    # Turn telnet command interpretation on (true) or off (false).  It
+    # should be on for true telnet sessions, off if using Net::Telnet
+    # to connect to a non-telnet service such as SMTP.
+    def telnetmode=(mode)
+      if (true == mode or false == mode)
+        @options["Telnetmode"] = mode
+      else
+        raise ArgumentError, "argument must be true or false"
+      end
+    end
+
+    # Turn newline conversion on (+mode+ == false) or off (+mode+ == true),
+    # or return the current value (+mode+ is not specified).
+    def binmode(mode = nil)
+      case mode
+      when nil
+        @options["Binmode"] 
+      when true, false
+        @options["Binmode"] = mode
+      else
+        raise ArgumentError, "argument must be true or false"
+      end
+    end
+
+    # Turn newline conversion on (false) or off (true).
+    def binmode=(mode)
+      if (true == mode or false == mode)
+        @options["Binmode"] = mode
+      else
+        raise ArgumentError, "argument must be true or false"
+      end
+    end
+
+    # Preprocess received data from the host.
+    #
+    # Performs newline conversion and detects telnet command sequences.
+    # Called automatically by #waitfor().  You should only use this 
+    # method yourself if you have read input directly using sysread()
+    # or similar, and even then only if in telnet mode.
+    def preprocess(string)
+      # combine CR+NULL into CR
+      string = string.gsub(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"]
+
+      # combine EOL into "\n"
+      string = string.gsub(/#{EOL}/no, "\n") unless @options["Binmode"]
+
+      string.gsub(/#{IAC}(
+                   [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]|
+                   [#{DO}#{DONT}#{WILL}#{WONT}]
+                     [#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}]|
+                   #{SB}[^#{IAC}]*#{IAC}#{SE}
+                 )/xno) do
+        if    IAC == $1  # handle escaped IAC characters
+          IAC
+        elsif AYT == $1  # respond to "IAC AYT" (are you there)
+          self.write("nobody here but us pigeons" + EOL)
+          ''
+        elsif DO[0] == $1[0]  # respond to "IAC DO x"
+          if OPT_BINARY[0] == $1[1]
+            @telnet_option["BINARY"] = true
+            self.write(IAC + WILL + OPT_BINARY)
+          else
+            self.write(IAC + WONT + $1[1..1])
+          end
+          ''
+        elsif DONT[0] == $1[0]  # respond to "IAC DON'T x" with "IAC WON'T x"
+          self.write(IAC + WONT + $1[1..1])
+          ''
+        elsif WILL[0] == $1[0]  # respond to "IAC WILL x"
+          if    OPT_BINARY[0] == $1[1]
+            self.write(IAC + DO + OPT_BINARY)
+          elsif OPT_ECHO[0] == $1[1]
+            self.write(IAC + DO + OPT_ECHO)
+          elsif OPT_SGA[0]  == $1[1]
+            @telnet_option["SGA"] = true
+            self.write(IAC + DO + OPT_SGA)
+          else
+            self.write(IAC + DONT + $1[1..1])
+          end
+          ''
+        elsif WONT[0] == $1[0]  # respond to "IAC WON'T x"
+          if    OPT_ECHO[0] == $1[1]
+            self.write(IAC + DONT + OPT_ECHO)
+          elsif OPT_SGA[0]  == $1[1]
+            @telnet_option["SGA"] = false
+            self.write(IAC + DONT + OPT_SGA)
+          else
+            self.write(IAC + DONT + $1[1..1])
+          end
+          ''
+        else
+          ''
+        end
+      end
+    end # preprocess
+
+    # Read data from the host until a certain sequence is matched.
+    #
+    # If a block is given, the received data will be yielded as it
+    # is read in (not necessarily all in one go), or nil if EOF 
+    # occurs before any data is received.  Whether a block is given
+    # or not, all data read will be returned in a single string, or again 
+    # nil if EOF occurs before any data is received.  Note that
+    # received data includes the matched sequence we were looking for.
+    #
+    # +options+ can be either a regular expression or a hash of options.
+    # If a regular expression, this specifies the data to wait for.
+    # If a hash, this can specify the following options:
+    #
+    # Match:: a regular expression, specifying the data to wait for.
+    # Prompt:: as for Match; used only if Match is not specified.
+    # String:: as for Match, except a string that will be converted
+    #          into a regular expression.  Used only if Match and
+    #          Prompt are not specified.
+    # Timeout:: the number of seconds to wait for data from the host
+    #           before raising a TimeoutError.  If set to false, 
+    #           no timeout will occur.  If not specified, the
+    #           Timeout option value specified when this instance
+    #           was created will be used, or, failing that, the
+    #           default value of 10 seconds.
+    # Waittime:: the number of seconds to wait after matching against
+    #            the input data to see if more data arrives.  If more
+    #            data arrives within this time, we will judge ourselves
+    #            not to have matched successfully, and will continue
+    #            trying to match.  If not specified, the Waittime option
+    #            value specified when this instance was created will be
+    #            used, or, failing that, the default value of 0 seconds,
+    #            which means not to wait for more input.
+    #           
+    def waitfor(options) # :yield: recvdata
+      time_out = @options["Timeout"]
+      waittime = @options["Waittime"]
+
+      if options.kind_of?(Hash)
+        prompt   = if options.has_key?("Match")
+                     options["Match"]
+                   elsif options.has_key?("Prompt")
+                     options["Prompt"]
+                   elsif options.has_key?("String")
+                     Regexp.new( Regexp.quote(options["String"]) )
+                   end
+        time_out = options["Timeout"]  if options.has_key?("Timeout")
+        waittime = options["Waittime"] if options.has_key?("Waittime")
+      else
+        prompt = options
+      end
+
+      if time_out == false
+        time_out = nil
+      end
+
+      line = ''
+      buf = ''
+      rest = ''
+      until(prompt === line and not IO::select([@sock], nil, nil, waittime))
+        unless IO::select([@sock], nil, nil, time_out)
+          raise TimeoutError, "timed out while waiting for more data"
+        end
+        begin
+          c = @sock.readpartial(1024 * 1024)
+          @dumplog.log_dump('<', c) if @options.has_key?("Dump_log")
+          if @options["Telnetmode"]
+            c = rest + c
+            if Integer(c.rindex(/#{IAC}#{SE}/no)) <
+               Integer(c.rindex(/#{IAC}#{SB}/no))
+              buf = preprocess(c[0 ... c.rindex(/#{IAC}#{SB}/no)])
+              rest = c[c.rindex(/#{IAC}#{SB}/no) .. -1]
+            elsif pt = c.rindex(/#{IAC}[^#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]?\z/no)
+              buf = preprocess(c[0 ... pt])
+              rest = c[pt .. -1]
+            else
+              buf = preprocess(c)
+              rest = ''
+            end
+         else
+           # Not Telnetmode.
+           #
+           # We cannot use preprocess() on this data, because that
+           # method makes some Telnetmode-specific assumptions.
+           buf = c
+           buf.gsub!(/#{EOL}/no, "\n") unless @options["Binmode"]
+           rest = ''
+          end
+          @log.print(buf) if @options.has_key?("Output_log")
+          line += buf
+          yield buf if block_given?
+        rescue EOFError # End of file reached
+          if line == ''
+            line = nil
+            yield nil if block_given?
+          end
+          break
+        end
+      end
+      line
+    end
+
+    # Write +string+ to the host.
+    #
+    # Does not perform any conversions on +string+.  Will log +string+ to the
+    # dumplog, if the Dump_log option is set.
+    def write(string)
+      length = string.length
+      while 0 < length
+        IO::select(nil, [@sock])
+        @dumplog.log_dump('>', string[-length..-1]) if @options.has_key?("Dump_log")
+        length -= @sock.syswrite(string[-length..-1])
+      end
+    end
+
+    # Sends a string to the host.
+    #
+    # This does _not_ automatically append a newline to the string.  Embedded
+    # newlines may be converted and telnet command sequences escaped 
+    # depending upon the values of telnetmode, binmode, and telnet options
+    # set by the host.
+    def print(string)
+      string = string.gsub(/#{IAC}/no, IAC + IAC) if @options["Telnetmode"]
+
+      if @options["Binmode"]
+        self.write(string)
+      else
+        if @telnet_option["BINARY"] and @telnet_option["SGA"]
+          # IAC WILL SGA IAC DO BIN send EOL --> CR
+          self.write(string.gsub(/\n/n, CR))
+        elsif @telnet_option["SGA"]
+          # IAC WILL SGA send EOL --> CR+NULL
+          self.write(string.gsub(/\n/n, CR + NULL))
+        else
+          # NONE send EOL --> CR+LF
+          self.write(string.gsub(/\n/n, EOL))
+        end
+      end
+    end
+
+    # Sends a string to the host.
+    #
+    # Same as #print(), but appends a newline to the string.
+    def puts(string)
+      self.print(string + "\n")
+    end
+
+    # Send a command to the host.
+    #
+    # More exactly, sends a string to the host, and reads in all received
+    # data until is sees the prompt or other matched sequence.
+    #
+    # If a block is given, the received data will be yielded to it as
+    # it is read in.  Whether a block is given or not, the received data 
+    # will be return as a string.  Note that the received data includes
+    # the prompt and in most cases the host's echo of our command.
+    #
+    # +options+ is either a String, specified the string or command to
+    # send to the host; or it is a hash of options.  If a hash, the
+    # following options can be specified:
+    #
+    # String:: the command or other string to send to the host.
+    # Match:: a regular expression, the sequence to look for in
+    #         the received data before returning.  If not specified,
+    #         the Prompt option value specified when this instance
+    #         was created will be used, or, failing that, the default
+    #         prompt of /[$%#>] \z/n.
+    # Timeout:: the seconds to wait for data from the host before raising
+    #           a Timeout error.  If not specified, the Timeout option
+    #           value specified when this instance was created will be
+    #           used, or, failing that, the default value of 10 seconds.
+    #
+    # The command or other string will have the newline sequence appended
+    # to it.
+    def cmd(options) # :yield: recvdata
+      match    = @options["Prompt"]
+      time_out = @options["Timeout"]
+
+      if options.kind_of?(Hash)
+        string   = options["String"]
+        match    = options["Match"]   if options.has_key?("Match")
+        time_out = options["Timeout"] if options.has_key?("Timeout")
+      else
+        string = options
+      end
+
+      self.puts(string)
+      if block_given?
+        waitfor({"Prompt" => match, "Timeout" => time_out}){|c| yield c }
+      else
+        waitfor({"Prompt" => match, "Timeout" => time_out})
+      end
+    end
+
+    # Login to the host with a given username and password.
+    #
+    # The username and password can either be provided as two string
+    # arguments in that order, or as a hash with keys "Name" and
+    # "Password".    
+    #
+    # This method looks for the strings "login" and "Password" from the
+    # host to determine when to send the username and password.  If the
+    # login sequence does not follow this pattern (for instance, you
+    # are connecting to a service other than telnet), you will need
+    # to handle login yourself.
+    #
+    # The password can be omitted, either by only
+    # provided one String argument, which will be used as the username,
+    # or by providing a has that has no "Password" key.  In this case,
+    # the method will not look for the "Password:" prompt; if it is
+    # sent, it will have to be dealt with by later calls.
+    #
+    # The method returns all data received during the login process from
+    # the host, including the echoed username but not the password (which
+    # the host should not echo).  If a block is passed in, this received
+    # data is also yielded to the block as it is received.
+    def login(options, password = nil) # :yield: recvdata
+      login_prompt = /[Ll]ogin[: ]*\z/n
+      password_prompt = /Password[: ]*\z/n
+      if options.kind_of?(Hash)
+        username = options["Name"]
+        password = options["Password"]
+	login_prompt = options["LoginPrompt"] if options["LoginPrompt"]
+	password_prompt = options["PasswordPrompt"] if options["PasswordPrompt"]
+      else
+        username = options
+      end
+
+      if block_given?
+        line = waitfor(login_prompt){|c| yield c }
+        if password
+          line += cmd({"String" => username,
+                       "Match" => password_prompt}){|c| yield c }
+          line += cmd(password){|c| yield c }
+        else
+          line += cmd(username){|c| yield c }
+        end
+      else
+        line = waitfor(login_prompt)
+        if password
+          line += cmd({"String" => username,
+                       "Match" => password_prompt})
+          line += cmd(password)
+        else
+          line += cmd(username)
+        end
+      end
+      line
+    end
+
+  end  # class Telnet
+end  # module Net
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/telnets.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/telnets.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/telnets.rb	(revision 18425)
@@ -0,0 +1,248 @@
+=begin
+= $RCSfile$ -- SSL/TLS enhancement for Net::Telnet.
+
+= Info
+  'OpenSSL for Ruby 2' project
+  Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
+  All rights reserved.
+
+= Licence
+  This program is licenced under the same licence as Ruby.
+  (See the file 'LICENCE'.)
+
+= Version
+  $Id: telnets.rb 11708 2007-02-12 23:01:19Z shyouhei $
+  
+  2001/11/06: Contiributed to Ruby/OpenSSL project.
+
+== class Net::Telnet
+
+This class will initiate SSL/TLS session automaticaly if the server
+sent OPT_STARTTLS. Some options are added for SSL/TLS.
+
+  host = Net::Telnet::new({
+           "Host"       => "localhost",
+           "Port"       => "telnets",
+           ## follows are new options.
+           'CertFile'   => "user.crt",
+           'KeyFile'    => "user.key",
+           'CAFile'     => "/some/where/certs/casert.pem",
+           'CAPath'     => "/some/where/caserts",
+           'VerifyMode' => SSL::VERIFY_PEER,
+           'VerifyCallback' => verify_proc
+         })
+
+Or, the new options ('Cert', 'Key' and 'CACert') are available from
+Michal Rokos's OpenSSL module.
+
+  cert_data = File.open("user.crt"){|io| io.read }
+  pkey_data = File.open("user.key"){|io| io.read }
+  cacert_data = File.open("your_ca.pem"){|io| io.read }
+  host = Net::Telnet::new({
+           "Host"       => "localhost",
+           "Port"       => "telnets",
+           'Cert'       => OpenSSL::X509::Certificate.new(cert_data)
+           'Key'        => OpenSSL::PKey::RSA.new(pkey_data)
+           'CACert'     => OpenSSL::X509::Certificate.new(cacert_data)
+           'CAFile'     => "/some/where/certs/casert.pem",
+           'CAPath'     => "/some/where/caserts",
+           'VerifyMode' => SSL::VERIFY_PEER,
+           'VerifyCallback' => verify_proc
+         })
+
+This class is expected to be a superset of usual Net::Telnet.
+=end
+
+require "net/telnet"
+require "openssl"
+
+module Net
+  class Telnet
+    attr_reader :ssl
+
+    OPT_STARTTLS       =  46.chr # "\056" # "\x2e" # Start TLS
+    TLS_FOLLOWS        =   1.chr # "\001" # "\x01" # FOLLOWS (for STARTTLS)
+
+    alias preprocess_orig preprocess
+
+    def ssl?; @ssl; end
+
+    def preprocess(string)
+      # combine CR+NULL into CR
+      string = string.gsub(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"]
+
+      # combine EOL into "\n"
+      string = string.gsub(/#{EOL}/no, "\n") unless @options["Binmode"]
+
+      string.gsub(/#{IAC}(
+                   [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]|
+                   [#{DO}#{DONT}#{WILL}#{WONT}][#{OPT_BINARY}-#{OPT_EXOPL}]|
+                   #{SB}[#{OPT_BINARY}-#{OPT_EXOPL}]
+                     (#{IAC}#{IAC}|[^#{IAC}])+#{IAC}#{SE}
+                 )/xno) do
+        if    IAC == $1  # handle escaped IAC characters
+          IAC
+        elsif AYT == $1  # respond to "IAC AYT" (are you there)
+          self.write("nobody here but us pigeons" + EOL)
+          ''
+        elsif DO[0] == $1[0]  # respond to "IAC DO x"
+          if    OPT_BINARY[0] == $1[1]
+            @telnet_option["BINARY"] = true
+            self.write(IAC + WILL + OPT_BINARY)
+          elsif OPT_STARTTLS[0] == $1[1]
+            self.write(IAC + WILL + OPT_STARTTLS)
+            self.write(IAC + SB + OPT_STARTTLS + TLS_FOLLOWS + IAC + SE)
+          else
+            self.write(IAC + WONT + $1[1..1])
+          end
+          ''
+        elsif DONT[0] == $1[0]  # respond to "IAC DON'T x" with "IAC WON'T x"
+          self.write(IAC + WONT + $1[1..1])
+          ''
+        elsif WILL[0] == $1[0]  # respond to "IAC WILL x"
+          if    OPT_BINARY[0] == $1[1]
+            self.write(IAC + DO + OPT_BINARY)
+          elsif OPT_ECHO[0] == $1[1]
+            self.write(IAC + DO + OPT_ECHO)
+          elsif OPT_SGA[0]  == $1[1]
+            @telnet_option["SGA"] = true
+            self.write(IAC + DO + OPT_SGA)
+          else
+            self.write(IAC + DONT + $1[1..1])
+          end
+          ''
+        elsif WONT[0] == $1[0]  # respond to "IAC WON'T x"
+          if    OPT_ECHO[0] == $1[1]
+            self.write(IAC + DONT + OPT_ECHO)
+          elsif OPT_SGA[0]  == $1[1]
+            @telnet_option["SGA"] = false
+            self.write(IAC + DONT + OPT_SGA)
+          else
+            self.write(IAC + DONT + $1[1..1])
+          end
+          ''
+        elsif SB[0] == $1[0]    # respond to "IAC SB xxx IAC SE"
+          if    OPT_STARTTLS[0] == $1[1] && TLS_FOLLOWS[0] == $2[0]
+            @sock = OpenSSL::SSL::SSLSocket.new(@sock)
+            @sock.cert            = @options['Cert'] unless @sock.cert
+            @sock.key             = @options['Key'] unless @sock.key
+            @sock.ca_cert         = @options['CACert']
+            @sock.ca_file         = @options['CAFile']
+            @sock.ca_path         = @options['CAPath']
+            @sock.timeout         = @options['Timeout']
+            @sock.verify_mode     = @options['VerifyMode']
+            @sock.verify_callback = @options['VerifyCallback']
+            @sock.verify_depth    = @options['VerifyDepth']
+            @sock.connect
+            @ssl = true
+          end
+          ''
+        else
+          ''
+        end
+      end
+    end # preprocess
+    
+    alias waitfor_org waitfor
+
+    def waitfor(options)
+      time_out = @options["Timeout"]
+      waittime = @options["Waittime"]
+
+      if options.kind_of?(Hash)
+        prompt   = if options.has_key?("Match")
+                     options["Match"]
+                   elsif options.has_key?("Prompt")
+                     options["Prompt"]
+                   elsif options.has_key?("String")
+                     Regexp.new( Regexp.quote(options["String"]) )
+                   end
+        time_out = options["Timeout"]  if options.has_key?("Timeout")
+        waittime = options["Waittime"] if options.has_key?("Waittime")
+      else
+        prompt = options
+      end
+
+      if time_out == false
+        time_out = nil
+      end
+
+      line = ''
+      buf = ''
+      @rest = '' unless @rest
+
+      until(prompt === line and not IO::select([@sock], nil, nil, waittime))
+        unless IO::select([@sock], nil, nil, time_out)
+          raise TimeoutError, "timed-out; wait for the next data"
+        end
+        begin
+          c = @rest + @sock.sysread(1024 * 1024)
+          @dumplog.log_dump('<', c) if @options.has_key?("Dump_log")
+          if @options["Telnetmode"]   
+            pos = 0
+            catch(:next){
+              while true
+                case c[pos]
+                when IAC[0]
+                  case c[pos+1]
+                  when DO[0], DONT[0], WILL[0], WONT[0]
+                    throw :next unless c[pos+2]
+                    pos += 3
+                  when SB[0]
+                    ret = detect_sub_negotiation(c, pos)
+                    throw :next unless ret
+                    pos = ret
+                  when nil
+                    throw :next
+                  else
+                    pos += 2
+                  end
+                when nil
+                  throw :next
+                else
+                  pos += 1
+                end
+              end
+            }
+
+            buf = preprocess(c[0...pos])
+            @rest = c[pos..-1]
+          end
+          @log.print(buf) if @options.has_key?("Output_log")
+          line.concat(buf)
+          yield buf if block_given?   
+        rescue EOFError # End of file reached
+          if line == ''
+            line = nil
+            yield nil if block_given? 
+          end
+          break
+        end
+      end
+      line
+    end
+
+    private
+
+    def detect_sub_negotiation(data, pos)
+      return nil if data.length < pos+6  # IAC SB x param IAC SE
+      pos += 3
+      while true
+        case data[pos]
+        when IAC[0]
+          if data[pos+1] == SE[0]
+            pos += 2
+            return pos
+          else
+            pos += 2
+          end
+        when nil
+          return nil
+        else
+          pos += 1
+        end
+      end
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/observer.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/observer.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/observer.rb	(revision 18425)
@@ -0,0 +1,192 @@
+#
+# observer.rb implements the _Observer_ object-oriented design pattern.  The
+# following documentation is copied, with modifications, from "Programming
+# Ruby", by Hunt and Thomas; http://www.rubycentral.com/book/lib_patterns.html.
+#
+# == About
+#
+# The Observer pattern, also known as Publish/Subscribe, provides a simple
+# mechanism for one object to inform a set of interested third-party objects
+# when its state changes. 
+#
+# == Mechanism
+#
+# In the Ruby implementation, the notifying class mixes in the +Observable+
+# module, which provides the methods for managing the associated observer
+# objects.
+#
+# The observers must implement the +update+ method to receive notifications.
+#
+# The observable object must:
+# * assert that it has +changed+
+# * call +notify_observers+
+#
+# == Example
+#
+# The following example demonstrates this nicely.  A +Ticker+, when run,
+# continually receives the stock +Price+ for its +@symbol+.  A +Warner+ is a
+# general observer of the price, and two warners are demonstrated, a +WarnLow+
+# and a +WarnHigh+, which print a warning if the price is below or above their
+# set limits, respectively.
+#
+# The +update+ callback allows the warners to run without being explicitly
+# called.  The system is set up with the +Ticker+ and several observers, and the
+# observers do their duty without the top-level code having to interfere.
+#
+# Note that the contract between publisher and subscriber (observable and
+# observer) is not declared or enforced.  The +Ticker+ publishes a time and a
+# price, and the warners receive that.  But if you don't ensure that your
+# contracts are correct, nothing else can warn you.
+#
+#   require "observer"
+#   
+#   class Ticker          ### Periodically fetch a stock price.
+#     include Observable
+#   
+#     def initialize(symbol)
+#       @symbol = symbol
+#     end
+#   
+#     def run
+#       lastPrice = nil
+#       loop do
+#         price = Price.fetch(@symbol)
+#         print "Current price: #{price}\n"
+#         if price != lastPrice
+#           changed                 # notify observers
+#           lastPrice = price
+#           notify_observers(Time.now, price)
+#         end
+#         sleep 1
+#       end
+#     end
+#   end
+#
+#   class Price           ### A mock class to fetch a stock price (60 - 140).
+#     def Price.fetch(symbol)
+#       60 + rand(80)
+#     end
+#   end
+#   
+#   class Warner          ### An abstract observer of Ticker objects.
+#     def initialize(ticker, limit)
+#       @limit = limit
+#       ticker.add_observer(self)
+#     end
+#   end
+#   
+#   class WarnLow < Warner
+#     def update(time, price)       # callback for observer
+#       if price < @limit
+#         print "--- #{time.to_s}: Price below #@limit: #{price}\n"
+#       end
+#     end
+#   end
+#   
+#   class WarnHigh < Warner
+#     def update(time, price)       # callback for observer
+#       if price > @limit
+#         print "+++ #{time.to_s}: Price above #@limit: #{price}\n"
+#       end
+#     end
+#   end
+#
+#   ticker = Ticker.new("MSFT")
+#   WarnLow.new(ticker, 80)
+#   WarnHigh.new(ticker, 120)
+#   ticker.run
+#
+# Produces:
+#
+#   Current price: 83
+#   Current price: 75
+#   --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 75
+#   Current price: 90
+#   Current price: 134
+#   +++ Sun Jun 09 00:10:25 CDT 2002: Price above 120: 134
+#   Current price: 134
+#   Current price: 112
+#   Current price: 79
+#   --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 79
+
+
+#
+# Implements the Observable design pattern as a mixin so that other objects can
+# be notified of changes in state.  See observer.rb for details and an example.
+#
+module Observable
+
+  #
+  # Add +observer+ as an observer on this object. +observer+ will now receive
+  # notifications.
+  #
+  def add_observer(observer)
+    @observer_peers = [] unless defined? @observer_peers
+    unless observer.respond_to? :update
+      raise NoMethodError, "observer needs to respond to `update'" 
+    end
+    @observer_peers.push observer
+  end
+
+  #
+  # Delete +observer+ as an observer on this object. It will no longer receive
+  # notifications.
+  #
+  def delete_observer(observer)
+    @observer_peers.delete observer if defined? @observer_peers
+  end
+
+  #
+  # Delete all observers associated with this object.
+  #
+  def delete_observers
+    @observer_peers.clear if defined? @observer_peers
+  end
+
+  #
+  # Return the number of observers associated with this object.
+  #
+  def count_observers
+    if defined? @observer_peers
+      @observer_peers.size
+    else
+      0
+    end
+  end
+
+  #
+  # Set the changed state of this object.  Notifications will be sent only if
+  # the changed +state+ is +true+.
+  #
+  def changed(state=true)
+    @observer_state = state
+  end
+
+  #
+  # Query the changed state of this object.
+  #
+  def changed?
+    if defined? @observer_state and @observer_state
+      true
+    else
+      false
+    end
+  end
+
+  #
+  # If this object's changed state is +true+, invoke the update method in each
+  # currently associated observer in turn, passing it the given arguments. The
+  # changed state is then set to +false+.
+  #
+  def notify_observers(*arg)
+    if defined? @observer_state and @observer_state
+      if defined? @observer_peers
+	for i in @observer_peers.dup
+	  i.update(*arg)
+	end
+      end
+      @observer_state = false
+    end
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/open-uri.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/open-uri.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/open-uri.rb	(revision 18425)
@@ -0,0 +1,688 @@
+require 'uri'
+require 'stringio'
+require 'time'
+
+module Kernel
+  private
+  alias open_uri_original_open open # :nodoc:
+
+  # makes possible to open various resources including URIs.
+  # If the first argument respond to `open' method,
+  # the method is called with the rest arguments.
+  #
+  # If the first argument is a string which begins with xxx://,
+  # it is parsed by URI.parse.  If the parsed object respond to `open' method,
+  # the method is called with the rest arguments.
+  #
+  # Otherwise original open is called.
+  #
+  # Since open-uri.rb provides URI::HTTP#open, URI::HTTPS#open and
+  # URI::FTP#open,
+  # Kernel[#.]open can accepts such URIs and strings which begins with
+  # http://, https:// and ftp://.
+  # In these case, the opened file object is extended by OpenURI::Meta.
+  def open(name, *rest, &block) # :doc:
+    if name.respond_to?(:open)
+      name.open(*rest, &block)
+    elsif name.respond_to?(:to_str) &&
+          %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ name &&
+          (uri = URI.parse(name)).respond_to?(:open)
+      uri.open(*rest, &block)
+    else
+      open_uri_original_open(name, *rest, &block)
+    end
+  end
+  module_function :open
+end
+
+# OpenURI is an easy-to-use wrapper for net/http, net/https and net/ftp.
+#
+#== Example
+#
+# It is possible to open http/https/ftp URL as usual like opening a file:
+#
+#   open("http://www.ruby-lang.org/") {|f|
+#     f.each_line {|line| p line}
+#   }
+#
+# The opened file has several methods for meta information as follows since
+# it is extended by OpenURI::Meta.
+#
+#   open("http://www.ruby-lang.org/en") {|f|
+#     f.each_line {|line| p line}
+#     p f.base_uri         # <URI::HTTP:0x40e6ef2 URL:http://www.ruby-lang.org/en/>
+#     p f.content_type     # "text/html"
+#     p f.charset          # "iso-8859-1"
+#     p f.content_encoding # []
+#     p f.last_modified    # Thu Dec 05 02:45:02 UTC 2002
+#   }
+#
+# Additional header fields can be specified by an optional hash argument.
+#
+#   open("http://www.ruby-lang.org/en/",
+#     "User-Agent" => "Ruby/#{RUBY_VERSION}",
+#     "From" => "foo@bar.invalid",
+#     "Referer" => "http://www.ruby-lang.org/") {|f|
+#     # ...
+#   }
+#
+# The environment variables such as http_proxy, https_proxy and ftp_proxy
+# are in effect by default.  :proxy => nil disables proxy.
+#
+#   open("http://www.ruby-lang.org/en/raa.html", :proxy => nil) {|f|
+#     # ...
+#   }
+#
+# URI objects can be opened in a similar way.
+#
+#   uri = URI.parse("http://www.ruby-lang.org/en/")
+#   uri.open {|f|
+#     # ...
+#   }
+#
+# URI objects can be read directly. The returned string is also extended by
+# OpenURI::Meta.
+#
+#   str = uri.read
+#   p str.base_uri
+#
+# Author:: Tanaka Akira <akr@m17n.org>
+
+module OpenURI
+  Options = {
+    :proxy => true,
+    :progress_proc => true,
+    :content_length_proc => true,
+    :http_basic_authentication => true,
+  }
+
+  def OpenURI.check_options(options) # :nodoc:
+    options.each {|k, v|
+      next unless Symbol === k
+      unless Options.include? k
+        raise ArgumentError, "unrecognized option: #{k}"
+      end
+    }
+  end
+
+  def OpenURI.scan_open_optional_arguments(*rest) # :nodoc:
+    if !rest.empty? && (String === rest.first || Integer === rest.first)
+      mode = rest.shift
+      if !rest.empty? && Integer === rest.first
+        perm = rest.shift
+      end
+    end
+    return mode, perm, rest
+  end
+
+  def OpenURI.open_uri(name, *rest) # :nodoc:
+    uri = URI::Generic === name ? name : URI.parse(name)
+    mode, perm, rest = OpenURI.scan_open_optional_arguments(*rest)
+    options = rest.shift if !rest.empty? && Hash === rest.first
+    raise ArgumentError.new("extra arguments") if !rest.empty?
+    options ||= {}
+    OpenURI.check_options(options)
+
+    unless mode == nil ||
+           mode == 'r' || mode == 'rb' ||
+           mode == File::RDONLY
+      raise ArgumentError.new("invalid access mode #{mode} (#{uri.class} resource is read only.)")
+    end
+
+    io = open_loop(uri, options)
+    if block_given?
+      begin
+        yield io
+      ensure
+        io.close
+      end
+    else
+      io
+    end
+  end
+
+  def OpenURI.open_loop(uri, options) # :nodoc:
+    case opt_proxy = options.fetch(:proxy, true)
+    when true
+      find_proxy = lambda {|u| u.find_proxy}
+    when nil, false
+      find_proxy = lambda {|u| nil}
+    when String
+      opt_proxy = URI.parse(opt_proxy)
+      find_proxy = lambda {|u| opt_proxy}
+    when URI::Generic
+      find_proxy = lambda {|u| opt_proxy}
+    else
+      raise ArgumentError.new("Invalid proxy option: #{opt_proxy}")
+    end
+
+    uri_set = {}
+    buf = nil
+    while true
+      redirect = catch(:open_uri_redirect) {
+        buf = Buffer.new
+        uri.buffer_open(buf, find_proxy.call(uri), options)
+        nil
+      }
+      if redirect
+        if redirect.relative?
+          # Although it violates RFC2616, Location: field may have relative
+          # URI.  It is converted to absolute URI using uri as a base URI.
+          redirect = uri + redirect
+        end
+        unless OpenURI.redirectable?(uri, redirect)
+          raise "redirection forbidden: #{uri} -> #{redirect}"
+        end
+        if options.include? :http_basic_authentication
+          # send authentication only for the URI directly specified.
+          options = options.dup
+          options.delete :http_basic_authentication
+        end
+        uri = redirect
+        raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s
+        uri_set[uri.to_s] = true
+      else
+        break
+      end
+    end
+    io = buf.io
+    io.base_uri = uri
+    io
+  end
+
+  def OpenURI.redirectable?(uri1, uri2) # :nodoc:
+    # This test is intended to forbid a redirection from http://... to
+    # file:///etc/passwd.
+    # However this is ad hoc.  It should be extensible/configurable.
+    uri1.scheme.downcase == uri2.scheme.downcase ||
+    (/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:http|ftp)\z/i =~ uri2.scheme)
+  end
+
+  def OpenURI.open_http(buf, target, proxy, options) # :nodoc:
+    if proxy
+      raise "Non-HTTP proxy URI: #{proxy}" if proxy.class != URI::HTTP
+    end
+
+    if target.userinfo && "1.9.0" <= RUBY_VERSION
+      # don't raise for 1.8 because compatibility.
+      raise ArgumentError, "userinfo not supported.  [RFC3986]"
+    end
+
+    require 'net/http'
+    klass = Net::HTTP
+    if URI::HTTP === target
+      # HTTP or HTTPS
+      if proxy
+        klass = Net::HTTP::Proxy(proxy.host, proxy.port)
+      end
+      target_host = target.host
+      target_port = target.port
+      request_uri = target.request_uri
+    else
+      # FTP over HTTP proxy
+      target_host = proxy.host
+      target_port = proxy.port
+      request_uri = target.to_s
+    end
+
+    http = klass.new(target_host, target_port)
+    if target.class == URI::HTTPS
+      require 'net/https'
+      http.use_ssl = true
+      http.verify_mode = OpenSSL::SSL::VERIFY_PEER
+      store = OpenSSL::X509::Store.new
+      store.set_default_paths
+      http.cert_store = store
+    end
+
+    header = {}
+    options.each {|k, v| header[k] = v if String === k }
+
+    resp = nil
+    http.start {
+      if target.class == URI::HTTPS
+        # xxx: information hiding violation
+        sock = http.instance_variable_get(:@socket)
+        if sock.respond_to?(:io)
+          sock = sock.io # 1.9
+        else
+          sock = sock.instance_variable_get(:@socket) # 1.8
+        end
+        sock.post_connection_check(target_host)
+      end
+      req = Net::HTTP::Get.new(request_uri, header)
+      if options.include? :http_basic_authentication
+        user, pass = options[:http_basic_authentication]
+        req.basic_auth user, pass
+      end
+      http.request(req) {|response|
+        resp = response
+        if options[:content_length_proc] && Net::HTTPSuccess === resp
+          if resp.key?('Content-Length')
+            options[:content_length_proc].call(resp['Content-Length'].to_i)
+          else
+            options[:content_length_proc].call(nil)
+          end
+        end
+        resp.read_body {|str|
+          buf << str
+          if options[:progress_proc] && Net::HTTPSuccess === resp
+            options[:progress_proc].call(buf.size)
+          end
+        }
+      }
+    }
+    io = buf.io
+    io.rewind
+    io.status = [resp.code, resp.message]
+    resp.each {|name,value| buf.io.meta_add_field name, value }
+    case resp
+    when Net::HTTPSuccess
+    when Net::HTTPMovedPermanently, # 301
+         Net::HTTPFound, # 302
+         Net::HTTPSeeOther, # 303
+         Net::HTTPTemporaryRedirect # 307
+      throw :open_uri_redirect, URI.parse(resp['location'])
+    else
+      raise OpenURI::HTTPError.new(io.status.join(' '), io)
+    end
+  end
+
+  class HTTPError < StandardError
+    def initialize(message, io)
+      super(message)
+      @io = io
+    end
+    attr_reader :io
+  end
+
+  class Buffer # :nodoc:
+    def initialize
+      @io = StringIO.new
+      @size = 0
+    end
+    attr_reader :size
+
+    StringMax = 10240
+    def <<(str)
+      @io << str
+      @size += str.length
+      if StringIO === @io && StringMax < @size
+        require 'tempfile'
+        io = Tempfile.new('open-uri')
+        io.binmode
+        Meta.init io, @io if @io.respond_to? :meta
+        io << @io.string
+        @io = io
+      end
+    end
+
+    def io
+      Meta.init @io unless @io.respond_to? :meta
+      @io
+    end
+  end
+
+  # Mixin for holding meta-information.
+  module Meta
+    def Meta.init(obj, src=nil) # :nodoc:
+      obj.extend Meta
+      obj.instance_eval {
+        @base_uri = nil
+        @meta = {}
+      }
+      if src
+        obj.status = src.status
+        obj.base_uri = src.base_uri
+        src.meta.each {|name, value|
+          obj.meta_add_field(name, value)
+        }
+      end
+    end
+
+    # returns an Array which consists status code and message.
+    attr_accessor :status
+
+    # returns a URI which is base of relative URIs in the data.
+    # It may differ from the URI supplied by a user because redirection.
+    attr_accessor :base_uri
+
+    # returns a Hash which represents header fields.
+    # The Hash keys are downcased for canonicalization.
+    attr_reader :meta
+
+    def meta_add_field(name, value) # :nodoc:
+      @meta[name.downcase] = value
+    end
+
+    # returns a Time which represents Last-Modified field.
+    def last_modified
+      if v = @meta['last-modified']
+        Time.httpdate(v)
+      else
+        nil
+      end
+    end
+
+    RE_LWS = /[\r\n\t ]+/n
+    RE_TOKEN = %r{[^\x00- ()<>@,;:\\"/\[\]?={}\x7f]+}n
+    RE_QUOTED_STRING = %r{"(?:[\r\n\t !#-\[\]-~\x80-\xff]|\\[\x00-\x7f])*"}n
+    RE_PARAMETERS = %r{(?:;#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?=#{RE_LWS}?(?:#{RE_TOKEN}|#{RE_QUOTED_STRING})#{RE_LWS}?)*}n
+
+    def content_type_parse # :nodoc:
+      v = @meta['content-type']
+      # The last (?:;#{RE_LWS}?)? matches extra ";" which violates RFC2045.
+      if v && %r{\A#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?/(#{RE_TOKEN})#{RE_LWS}?(#{RE_PARAMETERS})(?:;#{RE_LWS}?)?\z}no =~ v
+        type = $1.downcase
+        subtype = $2.downcase
+        parameters = []
+        $3.scan(/;#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?=#{RE_LWS}?(?:(#{RE_TOKEN})|(#{RE_QUOTED_STRING}))/no) {|att, val, qval|
+          val = qval.gsub(/[\r\n\t !#-\[\]-~\x80-\xff]+|(\\[\x00-\x7f])/) { $1 ? $1[1,1] : $& } if qval
+          parameters << [att.downcase, val]
+        }
+        ["#{type}/#{subtype}", *parameters]
+      else
+        nil
+      end
+    end
+
+    # returns "type/subtype" which is MIME Content-Type.
+    # It is downcased for canonicalization.
+    # Content-Type parameters are stripped.
+    def content_type
+      type, *parameters = content_type_parse
+      type || 'application/octet-stream'
+    end
+
+    # returns a charset parameter in Content-Type field.
+    # It is downcased for canonicalization.
+    #
+    # If charset parameter is not given but a block is given,
+    # the block is called and its result is returned.
+    # It can be used to guess charset.
+    #
+    # If charset parameter and block is not given,
+    # nil is returned except text type in HTTP.
+    # In that case, "iso-8859-1" is returned as defined by RFC2616 3.7.1.
+    def charset
+      type, *parameters = content_type_parse
+      if pair = parameters.assoc('charset')
+        pair.last.downcase
+      elsif block_given?
+        yield
+      elsif type && %r{\Atext/} =~ type &&
+            @base_uri && /\Ahttp\z/i =~ @base_uri.scheme
+        "iso-8859-1" # RFC2616 3.7.1
+      else
+        nil
+      end
+    end
+
+    # returns a list of encodings in Content-Encoding field
+    # as an Array of String.
+    # The encodings are downcased for canonicalization.
+    def content_encoding
+      v = @meta['content-encoding']
+      if v && %r{\A#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?(?:,#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?)*}o =~ v
+        v.scan(RE_TOKEN).map {|content_coding| content_coding.downcase}
+      else
+        []
+      end
+    end
+  end
+
+  # Mixin for HTTP and FTP URIs.
+  module OpenRead
+    # OpenURI::OpenRead#open provides `open' for URI::HTTP and URI::FTP.
+    #
+    # OpenURI::OpenRead#open takes optional 3 arguments as:
+    # OpenURI::OpenRead#open([mode [, perm]] [, options]) [{|io| ... }]
+    #
+    # `mode', `perm' is same as Kernel#open.
+    #
+    # However, `mode' must be read mode because OpenURI::OpenRead#open doesn't
+    # support write mode (yet).
+    # Also `perm' is just ignored because it is meaningful only for file
+    # creation.
+    #
+    # `options' must be a hash.
+    #
+    # Each pairs which key is a string in the hash specify a extra header
+    # field for HTTP.
+    # I.e. it is ignored for FTP without HTTP proxy.
+    #
+    # The hash may include other options which key is a symbol:
+    #
+    # [:proxy]
+    #  Synopsis:
+    #    :proxy => "http://proxy.foo.com:8000/"
+    #    :proxy => URI.parse("http://proxy.foo.com:8000/")
+    #    :proxy => true
+    #    :proxy => false
+    #    :proxy => nil
+    #   
+    #  If :proxy option is specified, the value should be String, URI,
+    #  boolean or nil.
+    #  When String or URI is given, it is treated as proxy URI.
+    #  When true is given or the option itself is not specified,
+    #  environment variable `scheme_proxy' is examined.
+    #  `scheme' is replaced by `http', `https' or `ftp'.
+    #  When false or nil is given, the environment variables are ignored and
+    #  connection will be made to a server directly.
+    #
+    # [:http_basic_authentication]
+    #  Synopsis:
+    #    :http_basic_authentication=>[user, password]
+    #
+    #  If :http_basic_authentication is specified,
+    #  the value should be an array which contains 2 strings:
+    #  username and password.
+    #  It is used for HTTP Basic authentication defined by RFC 2617.
+    #
+    # [:content_length_proc]
+    #  Synopsis:
+    #    :content_length_proc => lambda {|content_length| ... }
+    # 
+    #  If :content_length_proc option is specified, the option value procedure
+    #  is called before actual transfer is started.
+    #  It takes one argument which is expected content length in bytes.
+    # 
+    #  If two or more transfer is done by HTTP redirection, the procedure
+    #  is called only one for a last transfer.
+    # 
+    #  When expected content length is unknown, the procedure is called with
+    #  nil.
+    #  It is happen when HTTP response has no Content-Length header.
+    #
+    # [:progress_proc]
+    #  Synopsis:
+    #    :progress_proc => lambda {|size| ...}
+    #
+    #  If :progress_proc option is specified, the proc is called with one
+    #  argument each time when `open' gets content fragment from network.
+    #  The argument `size' `size' is a accumulated transfered size in bytes.
+    #
+    #  If two or more transfer is done by HTTP redirection, the procedure
+    #  is called only one for a last transfer.
+    #
+    #  :progress_proc and :content_length_proc are intended to be used for
+    #  progress bar.
+    #  For example, it can be implemented as follows using Ruby/ProgressBar.
+    #
+    #    pbar = nil
+    #    open("http://...",
+    #      :content_length_proc => lambda {|t|
+    #        if t && 0 < t
+    #          pbar = ProgressBar.new("...", t)
+    #          pbar.file_transfer_mode
+    #        end
+    #      },
+    #      :progress_proc => lambda {|s|
+    #        pbar.set s if pbar
+    #      }) {|f| ... }
+    #
+    # OpenURI::OpenRead#open returns an IO like object if block is not given.
+    # Otherwise it yields the IO object and return the value of the block.
+    # The IO object is extended with OpenURI::Meta.
+    def open(*rest, &block)
+      OpenURI.open_uri(self, *rest, &block)
+    end
+
+    # OpenURI::OpenRead#read([options]) reads a content referenced by self and
+    # returns the content as string.
+    # The string is extended with OpenURI::Meta.
+    # The argument `options' is same as OpenURI::OpenRead#open.
+    def read(options={})
+      self.open(options) {|f|
+        str = f.read
+        Meta.init str, f
+        str
+      }
+    end
+  end
+end
+
+module URI
+  class Generic
+    # returns a proxy URI.
+    # The proxy URI is obtained from environment variables such as http_proxy,
+    # ftp_proxy, no_proxy, etc.
+    # If there is no proper proxy, nil is returned.
+    #
+    # Note that capitalized variables (HTTP_PROXY, FTP_PROXY, NO_PROXY, etc.)
+    # are examined too.
+    #
+    # But http_proxy and HTTP_PROXY is treated specially under CGI environment.
+    # It's because HTTP_PROXY may be set by Proxy: header.
+    # So HTTP_PROXY is not used.
+    # http_proxy is not used too if the variable is case insensitive.
+    # CGI_HTTP_PROXY can be used instead.
+    def find_proxy
+      name = self.scheme.downcase + '_proxy'
+      proxy_uri = nil
+      if name == 'http_proxy' && ENV.include?('REQUEST_METHOD') # CGI?
+        # HTTP_PROXY conflicts with *_proxy for proxy settings and
+        # HTTP_* for header information in CGI.
+        # So it should be careful to use it.
+        pairs = ENV.reject {|k, v| /\Ahttp_proxy\z/i !~ k }
+        case pairs.length
+        when 0 # no proxy setting anyway.
+          proxy_uri = nil
+        when 1
+          k, v = pairs.shift
+          if k == 'http_proxy' && ENV[k.upcase] == nil
+            # http_proxy is safe to use because ENV is case sensitive.
+            proxy_uri = ENV[name]
+          else
+            proxy_uri = nil
+          end
+        else # http_proxy is safe to use because ENV is case sensitive.
+          proxy_uri = ENV[name]
+        end
+        if !proxy_uri
+          # Use CGI_HTTP_PROXY.  cf. libwww-perl.
+          proxy_uri = ENV["CGI_#{name.upcase}"]
+        end
+      elsif name == 'http_proxy'
+        unless proxy_uri = ENV[name]
+          if proxy_uri = ENV[name.upcase]
+            warn 'The environment variable HTTP_PROXY is discouraged.  Use http_proxy.'
+          end
+        end
+      else
+        proxy_uri = ENV[name] || ENV[name.upcase]
+      end
+
+      if proxy_uri && self.host
+        require 'socket'
+        begin
+          addr = IPSocket.getaddress(self.host)
+          proxy_uri = nil if /\A127\.|\A::1\z/ =~ addr
+        rescue SocketError
+        end
+      end
+
+      if proxy_uri
+        proxy_uri = URI.parse(proxy_uri)
+        name = 'no_proxy'
+        if no_proxy = ENV[name] || ENV[name.upcase]
+          no_proxy.scan(/([^:,]*)(?::(\d+))?/) {|host, port|
+            if /(\A|\.)#{Regexp.quote host}\z/i =~ self.host &&
+               (!port || self.port == port.to_i)
+              proxy_uri = nil
+              break
+            end
+          }
+        end
+        proxy_uri
+      else
+        nil
+      end
+    end
+  end
+
+  class HTTP
+    def buffer_open(buf, proxy, options) # :nodoc:
+      OpenURI.open_http(buf, self, proxy, options)
+    end
+
+    include OpenURI::OpenRead
+  end
+
+  class FTP
+    def buffer_open(buf, proxy, options) # :nodoc:
+      if proxy
+        OpenURI.open_http(buf, self, proxy, options)
+        return
+      end
+      require 'net/ftp'
+
+      directories = self.path.split(%r{/}, -1)
+      directories.shift if directories[0] == '' # strip a field before leading slash
+      directories.each {|d|
+        d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") }
+      }
+      unless filename = directories.pop
+        raise ArgumentError, "no filename: #{self.inspect}"
+      end
+      directories.each {|d|
+        if /[\r\n]/ =~ d
+          raise ArgumentError, "invalid directory: #{d.inspect}"
+        end
+      }
+      if /[\r\n]/ =~ filename
+        raise ArgumentError, "invalid filename: #{filename.inspect}"
+      end
+      typecode = self.typecode
+      if typecode && /\A[aid]\z/ !~ typecode
+        raise ArgumentError, "invalid typecode: #{typecode.inspect}"
+      end
+
+      # The access sequence is defined by RFC 1738
+      ftp = Net::FTP.open(self.host)
+      # todo: extract user/passwd from .netrc.
+      user = 'anonymous'
+      passwd = nil
+      user, passwd = self.userinfo.split(/:/) if self.userinfo
+      ftp.login(user, passwd)
+      directories.each {|cwd|
+        ftp.voidcmd("CWD #{cwd}")
+      }
+      if typecode
+        # xxx: typecode D is not handled.
+        ftp.voidcmd("TYPE #{typecode.upcase}")
+      end
+      if options[:content_length_proc]
+        options[:content_length_proc].call(ftp.size(filename))
+      end
+      ftp.retrbinary("RETR #{filename}", 4096) { |str|
+        buf << str
+        options[:progress_proc].call(buf.size) if options[:progress_proc]
+      }
+      ftp.close
+      buf.io.rewind
+    end
+
+    include OpenURI::OpenRead
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/open3.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/open3.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/open3.rb	(revision 18425)
@@ -0,0 +1,101 @@
+#
+# = open3.rb: Popen, but with stderr, too
+#
+# Author:: Yukihiro Matsumoto
+# Documentation:: Konrad Meyer
+#
+# Open3 gives you access to stdin, stdout, and stderr when running other
+# programs.
+#
+
+#
+# Open3 grants you access to stdin, stdout, and stderr when running another
+# program. Example:
+#
+#   require "open3"
+#   include Open3
+#   
+#   stdin, stdout, stderr = popen3('nroff -man')
+#
+# Open3.popen3 can also take a block which will receive stdin, stdout and
+# stderr as parameters.  This ensures stdin, stdout and stderr are closed
+# once the block exits. Example:
+#
+#   require "open3"
+#
+#   Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }
+#
+
+module Open3
+  # 
+  # Open stdin, stdout, and stderr streams and start external executable.
+  # Non-block form:
+  #   
+  #   require 'open3'
+  #
+  #   [stdin, stdout, stderr] = Open3.popen3(cmd)
+  #
+  # Block form:
+  #
+  #   require 'open3'
+  #
+  #   Open3.popen3(cmd) { |stdin, stdout, stderr| ... }
+  #
+  # The parameter +cmd+ is passed directly to Kernel#exec.
+  #
+  def popen3(*cmd)
+    pw = IO::pipe   # pipe[0] for read, pipe[1] for write
+    pr = IO::pipe
+    pe = IO::pipe
+
+    pid = fork{
+      # child
+      fork{
+	# grandchild
+	pw[1].close
+	STDIN.reopen(pw[0])
+	pw[0].close
+
+	pr[0].close
+	STDOUT.reopen(pr[1])
+	pr[1].close
+
+	pe[0].close
+	STDERR.reopen(pe[1])
+	pe[1].close
+
+	exec(*cmd)
+      }
+      exit!(0)
+    }
+
+    pw[0].close
+    pr[1].close
+    pe[1].close
+    Process.waitpid(pid)
+    pi = [pw[1], pr[0], pe[0]]
+    pw[1].sync = true
+    if defined? yield
+      begin
+	return yield(*pi)
+      ensure
+	pi.each{|p| p.close unless p.closed?}
+      end
+    end
+    pi
+  end
+  module_function :popen3
+end
+
+if $0 == __FILE__
+  a = Open3.popen3("nroff -man")
+  Thread.start do
+    while line = gets
+      a[0].print line
+    end
+    a[0].close
+  end
+  while line = a[1].gets
+    print ":", line
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl.rb	(revision 18425)
@@ -0,0 +1,24 @@
+=begin
+= $RCSfile$ -- Loader for all OpenSSL C-space and Ruby-space definitions
+
+= Info
+  'OpenSSL for Ruby 2' project
+  Copyright (C) 2002  Michal Rokos <m.rokos@sh.cvut.cz>
+  All rights reserved.
+
+= Licence
+  This program is licenced under the same licence as Ruby.
+  (See the file 'LICENCE'.)
+
+= Version
+  $Id: openssl.rb 11708 2007-02-12 23:01:19Z shyouhei $
+=end
+
+require 'openssl.so'
+
+require 'openssl/bn'
+require 'openssl/cipher'
+require 'openssl/digest'
+require 'openssl/ssl'
+require 'openssl/x509'
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/bn.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/bn.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/bn.rb	(revision 18425)
@@ -0,0 +1,35 @@
+=begin
+= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for BN
+
+= Info
+  'OpenSSL for Ruby 2' project
+  Copyright (C) 2002  Michal Rokos <m.rokos@sh.cvut.cz>
+  All rights reserved.
+
+= Licence
+  This program is licenced under the same licence as Ruby.
+  (See the file 'LICENCE'.)
+
+= Version
+  $Id: bn.rb 11708 2007-02-12 23:01:19Z shyouhei $
+=end
+
+##
+# Should we care what if somebody require this file directly?
+#require 'openssl'
+
+module OpenSSL
+  class BN
+    include Comparable
+  end # BN
+end # OpenSSL
+
+##
+# Add double dispatch to Integer
+#
+class Integer
+  def to_bn
+    OpenSSL::BN::new(self)
+  end
+end # Integer
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/buffering.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/buffering.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/buffering.rb	(revision 18425)
@@ -0,0 +1,239 @@
+=begin
+= $RCSfile$ -- Buffering mix-in module.
+
+= Info
+  'OpenSSL for Ruby 2' project
+  Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
+  All rights reserved.
+
+= Licence
+  This program is licenced under the same licence as Ruby.
+  (See the file 'LICENCE'.)
+
+= Version
+  $Id: buffering.rb 11708 2007-02-12 23:01:19Z shyouhei $
+=end
+
+module Buffering
+  include Enumerable
+  attr_accessor :sync
+  BLOCK_SIZE = 1024*16
+
+  def initialize(*args)
+    @eof = false
+    @rbuffer = ""
+    @sync = @io.sync
+  end
+
+  #
+  # for reading.
+  #
+  private
+
+  def fill_rbuff
+    begin
+      @rbuffer << self.sysread(BLOCK_SIZE)
+    rescue Errno::EAGAIN
+      retry
+    rescue EOFError
+      @eof = true
+    end
+  end
+
+  def consume_rbuff(size=nil)
+    if @rbuffer.empty?
+      nil
+    else
+      size = @rbuffer.size unless size
+      ret = @rbuffer[0, size]
+      @rbuffer[0, size] = ""
+      ret
+    end
+  end
+
+  public
+
+  def read(size=nil, buf=nil)
+    if size == 0
+      if buf
+        buf.clear
+      else
+        buf = ""
+      end
+      return @eof ? nil : buf
+    end
+    until @eof
+      break if size && size <= @rbuffer.size
+      fill_rbuff
+    end
+    ret = consume_rbuff(size) || ""
+    if buf
+      buf.replace(ret)
+      ret = buf
+    end
+    (size && ret.empty?) ? nil : ret
+  end
+
+  def readpartial(maxlen, buf=nil)
+    if maxlen == 0
+      if buf
+        buf.clear
+      else
+        buf = ""
+      end
+      return @eof ? nil : buf
+    end
+    if @rbuffer.empty?
+      begin
+        return sysread(maxlen, buf)
+      rescue Errno::EAGAIN
+        retry
+      end
+    end
+    ret = consume_rbuff(maxlen)
+    if buf
+      buf.replace(ret)
+      ret = buf
+    end
+    raise EOFError if ret.empty?
+    ret
+  end
+
+  def gets(eol=$/)
+    idx = @rbuffer.index(eol)
+    until @eof
+      break if idx
+      fill_rbuff
+      idx = @rbuffer.index(eol)
+    end
+    if eol.is_a?(Regexp)
+      size = idx ? idx+$&.size : nil
+    else
+      size = idx ? idx+eol.size : nil
+    end
+    consume_rbuff(size)
+  end
+
+  def each(eol=$/)
+    while line = self.gets(eol)
+      yield line
+    end
+  end
+  alias each_line each
+
+  def readlines(eol=$/)
+    ary = []
+    while line = self.gets(eol)
+      ary << line
+    end
+    ary
+  end
+
+  def readline(eol=$/)
+    raise EOFError if eof?
+    gets(eol)
+  end
+
+  def getc
+    c = read(1)
+    c ? c[0] : nil
+  end
+
+  def each_byte
+    while c = getc
+      yield(c)
+    end
+  end
+
+  def readchar
+    raise EOFError if eof?
+    getc
+  end
+
+  def ungetc(c)
+    @rbuffer[0,0] = c.chr
+  end
+
+  def eof?
+    fill_rbuff if !@eof && @rbuffer.empty?
+    @eof && @rbuffer.empty?
+  end
+  alias eof eof?
+
+  #
+  # for writing.
+  #
+  private
+
+  def do_write(s)
+    @wbuffer = "" unless defined? @wbuffer
+    @wbuffer << s
+    @sync ||= false
+    if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/)
+      remain = idx ? idx + $/.size : @wbuffer.length
+      nwritten = 0
+      while remain > 0
+        str = @wbuffer[nwritten,remain]
+        begin
+          nwrote = syswrite(str)
+        rescue Errno::EAGAIN
+          retry
+        end
+        remain -= nwrote
+        nwritten += nwrote
+      end
+      @wbuffer[0,nwritten] = ""
+    end
+  end
+
+  public
+
+  def write(s)
+    do_write(s)
+    s.length
+  end
+
+  def << (s)
+    do_write(s)
+    self
+  end
+
+  def puts(*args)
+    s = ""
+    if args.empty?
+      s << "\n"
+    end
+    args.each{|arg|
+      s << arg.to_s
+      if $/ && /\n\z/ !~ s
+        s << "\n"
+      end
+    }
+    do_write(s)
+    nil
+  end
+
+  def print(*args)
+    s = ""
+    args.each{ |arg| s << arg.to_s }
+    do_write(s)
+    nil
+  end
+
+  def printf(s, *args)
+    do_write(s % args)
+    nil
+  end
+
+  def flush
+    osync = @sync
+    @sync = true
+    do_write ""
+    @sync = osync
+  end
+
+  def close
+    flush rescue nil
+    sysclose
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/cipher.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/cipher.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/cipher.rb	(revision 18425)
@@ -0,0 +1,58 @@
+=begin
+= $RCSfile$ -- Ruby-space predefined Cipher subclasses
+
+= Info
+  'OpenSSL for Ruby 2' project
+  Copyright (C) 2002  Michal Rokos <m.rokos@sh.cvut.cz>
+  All rights reserved.
+
+= Licence
+  This program is licenced under the same licence as Ruby.
+  (See the file 'LICENCE'.)
+
+= Version
+  $Id: cipher.rb 11708 2007-02-12 23:01:19Z shyouhei $
+=end
+
+##
+# Should we care what if somebody require this file directly?
+#require 'openssl'
+
+module OpenSSL
+  module Cipher
+    %w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name|
+      klass = Class.new(Cipher){
+        define_method(:initialize){|*args|
+          cipher_name = args.inject(name){|n, arg| "#{n}-#{arg}" }
+          super(cipher_name)
+        }
+      }
+      const_set(name, klass)
+    }
+
+    %w(128 192 256).each{|keylen|
+      klass = Class.new(Cipher){
+        define_method(:initialize){|mode|
+          mode ||= "CBC"
+          cipher_name = "AES-#{keylen}-#{mode}"
+          super(cipher_name)
+        }
+      }
+      const_set("AES#{keylen}", klass)
+    }
+
+    class Cipher
+      def random_key
+        str = OpenSSL::Random.random_bytes(self.key_len)
+        self.key = str
+        return str
+      end
+
+      def random_iv
+        str = OpenSSL::Random.random_bytes(self.iv_len)
+        self.iv = str
+        return str
+      end
+    end
+  end # Cipher
+end # OpenSSL
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/digest.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/digest.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/digest.rb	(revision 18425)
@@ -0,0 +1,49 @@
+=begin
+= $RCSfile$ -- Ruby-space predefined Digest subclasses
+
+= Info
+  'OpenSSL for Ruby 2' project
+  Copyright (C) 2002  Michal Rokos <m.rokos@sh.cvut.cz>
+  All rights reserved.
+
+= Licence
+  This program is licenced under the same licence as Ruby.
+  (See the file 'LICENCE'.)
+
+= Version
+  $Id: digest.rb 11708 2007-02-12 23:01:19Z shyouhei $
+=end
+
+##
+# Should we care what if somebody require this file directly?
+#require 'openssl'
+
+module OpenSSL
+  module Digest
+
+    alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1)
+    if OPENSSL_VERSION_NUMBER > 0x00908000
+      alg += %w(SHA224 SHA256 SHA384 SHA512)
+    end
+
+    alg.each{|name|
+      klass = Class.new(Digest){
+        define_method(:initialize){|*data|
+          if data.length > 1
+            raise ArgumentError,
+              "wrong number of arguments (#{data.length} for 1)"
+          end
+          super(name, data.first)
+        }
+      }
+      singleton = (class <<klass; self; end)
+      singleton.class_eval{
+        define_method(:digest){|data| Digest.digest(name, data) }
+        define_method(:hexdigest){|data| Digest.hexdigest(name, data) }
+      }
+      const_set(name, klass)
+    }
+
+  end # Digest
+end # OpenSSL
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/ssl.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/ssl.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/ssl.rb	(revision 18425)
@@ -0,0 +1,135 @@
+=begin
+= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for SSL
+
+= Info
+  'OpenSSL for Ruby 2' project
+  Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
+  All rights reserved.
+
+= Licence
+  This program is licenced under the same licence as Ruby.
+  (See the file 'LICENCE'.)
+
+= Version
+  $Id: ssl.rb 11708 2007-02-12 23:01:19Z shyouhei $
+=end
+
+require "openssl"
+require "openssl/buffering"
+require "fcntl"
+
+module OpenSSL
+  module SSL
+    module SocketForwarder
+      def addr
+        to_io.addr
+      end
+
+      def peeraddr
+        to_io.peeraddr
+      end
+
+      def setsockopt(level, optname, optval)
+        to_io.setsockopt(level, optname, optval)
+      end
+
+      def getsockopt(level, optname)
+        to_io.getsockopt(level, optname)
+      end
+
+      def fcntl(*args)
+        to_io.fcntl(*args)
+      end
+
+      def closed?
+        to_io.closed?
+      end
+
+      def do_not_reverse_lookup=(flag)
+        to_io.do_not_reverse_lookup = flag
+      end
+    end
+
+    module Nonblock
+      def initialize(*args)
+        flag = File::NONBLOCK
+        flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL)
+        @io.fcntl(Fcntl::F_SETFL, flag)
+        super
+      end
+    end
+
+    class SSLSocket
+      include Buffering
+      include SocketForwarder
+      include Nonblock
+
+      def post_connection_check(hostname)
+        check_common_name = true
+        cert = peer_cert
+        cert.extensions.each{|ext|
+          next if ext.oid != "subjectAltName"
+          ext.value.split(/,\s+/).each{|general_name|
+            if /\ADNS:(.*)/ =~ general_name
+              check_common_name = false
+              reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
+              return true if /\A#{reg}\z/i =~ hostname
+            elsif /\AIP Address:(.*)/ =~ general_name
+              check_common_name = false
+              return true if $1 == hostname
+            end
+          }
+        }
+        if check_common_name
+          cert.subject.to_a.each{|oid, value|
+            if oid == "CN"
+              reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
+              return true if /\A#{reg}\z/i =~ hostname
+            end
+          }
+        end
+        raise SSLError, "hostname not match"
+      end
+    end
+
+    class SSLServer
+      include SocketForwarder
+      attr_accessor :start_immediately
+
+      def initialize(svr, ctx)
+        @svr = svr
+        @ctx = ctx
+        unless ctx.session_id_context
+          session_id = OpenSSL::Digest::MD5.hexdigest($0)
+          @ctx.session_id_context = session_id
+        end
+        @start_immediately = true
+      end
+
+      def to_io
+        @svr
+      end
+
+      def listen(backlog=5)
+        @svr.listen(backlog)
+      end
+
+      def accept
+        sock = @svr.accept
+        begin
+          ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
+          ssl.sync_close = true
+          ssl.accept if @start_immediately
+          ssl
+        rescue SSLError => ex
+          sock.close
+          raise ex
+        end
+      end
+
+      def close
+        @svr.close
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/x509.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/x509.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/openssl/x509.rb	(revision 18425)
@@ -0,0 +1,154 @@
+=begin
+= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for X509 and subclasses
+
+= Info
+  'OpenSSL for Ruby 2' project
+  Copyright (C) 2002  Michal Rokos <m.rokos@sh.cvut.cz>
+  All rights reserved.
+
+= Licence
+  This program is licenced under the same licence as Ruby.
+  (See the file 'LICENCE'.)
+
+= Version
+  $Id: x509.rb 11708 2007-02-12 23:01:19Z shyouhei $
+=end
+
+require "openssl"
+
+module OpenSSL
+  module X509
+    class ExtensionFactory
+      def create_extension(*arg)
+        if arg.size > 1
+          create_ext(*arg)
+        else
+          send("create_ext_from_"+arg[0].class.name.downcase, arg[0])
+        end
+      end
+
+      def create_ext_from_array(ary)
+        raise ExtensionError, "unexpected array form" if ary.size > 3 
+        create_ext(ary[0], ary[1], ary[2])
+      end
+
+      def create_ext_from_string(str) # "oid = critical, value"
+        oid, value = str.split(/=/, 2)
+        oid.strip!
+        value.strip!
+        create_ext(oid, value)
+      end
+      
+      def create_ext_from_hash(hash)
+        create_ext(hash["oid"], hash["value"], hash["critical"])
+      end
+    end
+    
+    class Extension
+      def to_s # "oid = critical, value"
+        str = self.oid
+        str << " = "
+        str << "critical, " if self.critical?
+        str << self.value.gsub(/\n/, ", ")
+      end
+        
+      def to_h # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false}
+        {"oid"=>self.oid,"value"=>self.value,"critical"=>self.critical?}
+      end
+
+      def to_a
+        [ self.oid, self.value, self.critical? ]
+      end
+    end
+
+    class Name
+      module RFC2253DN
+        Special = ',=+<>#;'
+        HexChar = /[0-9a-fA-F]/
+        HexPair = /#{HexChar}#{HexChar}/
+        HexString = /#{HexPair}+/
+        Pair = /\\(?:[#{Special}]|\\|"|#{HexPair})/
+        StringChar = /[^#{Special}\\"]/
+        QuoteChar = /[^\\"]/
+        AttributeType = /[a-zA-Z][0-9a-zA-Z]*|[0-9]+(?:\.[0-9]+)*/
+        AttributeValue = /
+          (?!["#])((?:#{StringChar}|#{Pair})*)|
+          \#(#{HexString})|
+          "((?:#{QuoteChar}|#{Pair})*)"
+        /x
+        TypeAndValue = /\A(#{AttributeType})=#{AttributeValue}/
+
+        module_function
+
+        def expand_pair(str)
+          return nil unless str
+          return str.gsub(Pair){|pair|
+            case pair.size
+            when 2 then pair[1,1]
+            when 3 then Integer("0x#{pair[1,2]}").chr
+            else raise OpenSSL::X509::NameError, "invalid pair: #{str}"
+            end
+          }
+        end
+
+        def expand_hexstring(str)
+          return nil unless str
+          der = str.gsub(HexPair){|hex| Integer("0x#{hex}").chr }
+          a1 = OpenSSL::ASN1.decode(der)
+          return a1.value, a1.tag
+        end
+
+        def expand_value(str1, str2, str3)
+          value = expand_pair(str1)
+          value, tag = expand_hexstring(str2) unless value
+          value = expand_pair(str3) unless value
+          return value, tag
+        end
+
+        def scan(dn)
+          str = dn
+          ary = []
+          while true
+            if md = TypeAndValue.match(str)
+              matched = md.to_s
+              remain = md.post_match
+              type = md[1]
+              value, tag = expand_value(md[2], md[3], md[4]) rescue nil
+              if value
+                type_and_value = [type, value]
+                type_and_value.push(tag) if tag
+                ary.unshift(type_and_value)
+                if remain.length > 2 && remain[0] == ?,
+                  str = remain[1..-1]
+                  next
+                elsif remain.length > 2 && remain[0] == ?+
+                  raise OpenSSL::X509::NameError,
+                    "multi-valued RDN is not supported: #{dn}"
+                elsif remain.empty?
+                  break
+                end
+              end
+            end
+            msg_dn = dn[0, dn.length - str.length] + " =>" + str
+            raise OpenSSL::X509::NameError, "malformed RDN: #{msg_dn}"
+          end
+          return ary
+        end
+      end
+
+      class <<self
+        def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE)
+          ary = OpenSSL::X509::Name::RFC2253DN.scan(str)
+          self.new(ary, template)
+        end
+
+        def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE)
+          ary = str.scan(/\s*([^\/,]+)\s*/).collect{|i| i[0].split("=", 2) }
+          self.new(ary, template)
+        end
+
+        alias parse parse_openssl
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse.rb	(revision 18425)
@@ -0,0 +1,1788 @@
+#
+# optparse.rb - command-line option analysis with the OptionParser class.
+# 
+# Author:: Nobu Nakada
+# Documentation:: Nobu Nakada and Gavin Sinclair.
+#
+# See OptionParser for documentation. 
+#
+
+
+# == Developer Documentation (not for RDoc output) 
+# 
+# === Class tree
+#
+# - OptionParser:: front end
+# - OptionParser::Switch:: each switches
+# - OptionParser::List:: options list
+# - OptionParser::ParseError:: errors on parsing
+#   - OptionParser::AmbiguousOption
+#   - OptionParser::NeedlessArgument
+#   - OptionParser::MissingArgument
+#   - OptionParser::InvalidOption
+#   - OptionParser::InvalidArgument
+#     - OptionParser::AmbiguousArgument
+#
+# === Object relationship diagram
+#
+#   +--------------+
+#   | OptionParser |<>-----+
+#   +--------------+       |                      +--------+
+#                          |                    ,-| Switch |
+#        on_head -------->+---------------+    /  +--------+
+#        accept/reject -->| List          |<|>-
+#                         |               |<|>-  +----------+
+#        on ------------->+---------------+    `-| argument |
+#                           :           :        |  class   |
+#                         +---------------+      |==========|
+#        on_tail -------->|               |      |pattern   |
+#                         +---------------+      |----------|
+#   OptionParser.accept ->| DefaultList   |      |converter |
+#                reject   |(shared between|      +----------+
+#                         | all instances)|
+#                         +---------------+
+#
+# == OptionParser
+#
+# === Introduction
+#
+# OptionParser is a class for command-line option analysis.  It is much more
+# advanced, yet also easier to use, than GetoptLong, and is a more Ruby-oriented
+# solution.
+#
+# === Features
+# 
+# 1. The argument specification and the code to handle it are written in the
+#    same place.
+# 2. It can output an option summary; you don't need to maintain this string
+#    separately.
+# 3. Optional and mandatory arguments are specified very gracefully.
+# 4. Arguments can be automatically converted to a specified class.
+# 5. Arguments can be restricted to a certain set.
+#
+# All of these features are demonstrated in the examples below.
+#
+# === Minimal example
+#
+#   require 'optparse'
+#
+#   options = {}
+#   OptionParser.new do |opts|
+#     opts.banner = "Usage: example.rb [options]"
+#
+#     opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
+#       options[:verbose] = v
+#     end
+#   end.parse!
+#
+#   p options
+#   p ARGV
+#
+# === Complete example
+#
+# The following example is a complete Ruby program.  You can run it and see the
+# effect of specifying various options.  This is probably the best way to learn
+# the features of +optparse+.
+#
+#   require 'optparse'
+#   require 'optparse/time'
+#   require 'ostruct'
+#   require 'pp'
+#   
+#   class OptparseExample
+#   
+#     CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
+#     CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
+#   
+#     #
+#     # Return a structure describing the options.
+#     #
+#     def self.parse(args)
+#       # The options specified on the command line will be collected in *options*.
+#       # We set default values here.
+#       options = OpenStruct.new
+#       options.library = []
+#       options.inplace = false
+#       options.encoding = "utf8"
+#       options.transfer_type = :auto
+#       options.verbose = false
+#       
+#       opts = OptionParser.new do |opts|
+#         opts.banner = "Usage: example.rb [options]"
+#       
+#         opts.separator ""
+#         opts.separator "Specific options:"
+#       
+#         # Mandatory argument.
+#         opts.on("-r", "--require LIBRARY",
+#                 "Require the LIBRARY before executing your script") do |lib|
+#           options.library << lib
+#         end
+#       
+#         # Optional argument; multi-line description.
+#         opts.on("-i", "--inplace [EXTENSION]",
+#                 "Edit ARGV files in place",
+#                 "  (make backup if EXTENSION supplied)") do |ext|
+#           options.inplace = true
+#           options.extension = ext || ''
+#           options.extension.sub!(/\A\.?(?=.)/, ".")  # Ensure extension begins with dot.
+#         end
+#       
+#         # Cast 'delay' argument to a Float.
+#         opts.on("--delay N", Float, "Delay N seconds before executing") do |n|
+#           options.delay = n
+#         end
+#       
+#         # Cast 'time' argument to a Time object.
+#         opts.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
+#           options.time = time
+#         end
+#       
+#         # Cast to octal integer.
+#         opts.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger,
+#                 "Specify record separator (default \\0)") do |rs|
+#           options.record_separator = rs
+#         end
+#       
+#         # List of arguments.
+#         opts.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
+#           options.list = list
+#         end
+#       
+#         # Keyword completion.  We are specifying a specific set of arguments (CODES
+#         # and CODE_ALIASES - notice the latter is a Hash), and the user may provide
+#         # the shortest unambiguous text.
+#         code_list = (CODE_ALIASES.keys + CODES).join(',')
+#         opts.on("--code CODE", CODES, CODE_ALIASES, "Select encoding",
+#                 "  (#{code_list})") do |encoding|
+#           options.encoding = encoding
+#         end
+#       
+#         # Optional argument with keyword completion.
+#         opts.on("--type [TYPE]", [:text, :binary, :auto],
+#                 "Select transfer type (text, binary, auto)") do |t|
+#           options.transfer_type = t
+#         end
+#       
+#         # Boolean switch.
+#         opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
+#           options.verbose = v
+#         end
+#       
+#         opts.separator ""
+#         opts.separator "Common options:"
+#       
+#         # No argument, shows at tail.  This will print an options summary.
+#         # Try it and see!
+#         opts.on_tail("-h", "--help", "Show this message") do
+#           puts opts
+#           exit
+#         end
+#       
+#         # Another typical switch to print the version.
+#         opts.on_tail("--version", "Show version") do
+#           puts OptionParser::Version.join('.')
+#           exit
+#         end
+#       end
+#       
+#       opts.parse!(args)
+#       options
+#     end  # parse()
+#   
+#   end  # class OptparseExample
+#   
+#   options = OptparseExample.parse(ARGV)
+#   pp options
+#
+# === Further documentation
+#
+# The above examples should be enough to learn how to use this class.  If you
+# have any questions, email me (gsinclair@soyabean.com.au) and I will update
+# this document.
+#
+class OptionParser
+  # :stopdoc:
+  RCSID = %w$Id: optparse.rb 11798 2007-02-20 06:53:16Z knu $[1..-1].each {|s| s.freeze}.freeze
+  Version = (RCSID[1].split('.').collect {|s| s.to_i}.extend(Comparable).freeze if RCSID[1])
+  LastModified = (Time.gm(*RCSID[2, 2].join('-').scan(/\d+/).collect {|s| s.to_i}) if RCSID[2])
+  Release = RCSID[2]
+
+  NoArgument = [NO_ARGUMENT = :NONE, nil].freeze
+  RequiredArgument = [REQUIRED_ARGUMENT = :REQUIRED, true].freeze
+  OptionalArgument = [OPTIONAL_ARGUMENT = :OPTIONAL, false].freeze
+  # :startdoc:
+
+  #
+  # Keyword completion module.  This allows partial arguments to be specified
+  # and resolved against a list of acceptable values.
+  #
+  module Completion
+    def complete(key, icase = false, pat = nil)
+      pat ||= Regexp.new('\A' + Regexp.quote(key).gsub(/\w+\b/, '\&\w*'),
+                         icase)
+      canon, sw, k, v, cn = nil
+      candidates = []
+      each do |k, *v|
+        (if Regexp === k
+           kn = nil
+           k === key
+         else
+           kn = defined?(k.id2name) ? k.id2name : k
+           pat === kn
+         end) or next
+        v << k if v.empty?
+        candidates << [k, v, kn]
+      end
+      candidates = candidates.sort_by {|k, v, kn| kn.size}
+      if candidates.size == 1
+        canon, sw, * = candidates[0]
+      elsif candidates.size > 1
+        canon, sw, cn = candidates.shift
+        candidates.each do |k, v, kn|
+          next if sw == v
+          if String === cn and String === kn
+            if cn.rindex(kn, 0)
+              canon, sw, cn = k, v, kn
+              next
+            elsif kn.rindex(cn, 0)
+              next
+            end
+          end
+          throw :ambiguous, key
+        end
+      end
+      if canon
+        block_given? or return key, *sw
+        yield(key, *sw)
+      end
+    end
+
+    def convert(opt = nil, val = nil, *)
+      val
+    end
+  end
+
+
+  #
+  # Map from option/keyword string to object with completion.
+  #
+  class OptionMap < Hash
+    include Completion
+  end
+
+
+  #
+  # Individual switch class.  Not important to the user.
+  #
+  # Defined within Switch are several Switch-derived classes: NoArgument,
+  # RequiredArgument, etc. 
+  #
+  class Switch
+    attr_reader :pattern, :conv, :short, :long, :arg, :desc, :block
+
+    #
+    # Guesses argument style from +arg+.  Returns corresponding
+    # OptionParser::Switch class (OptionalArgument, etc.).
+    #
+    def self.guess(arg)
+      case arg
+      when ""
+        t = self
+      when /\A=?\[/
+        t = Switch::OptionalArgument
+      when /\A\s+\[/
+        t = Switch::PlacedArgument
+      else
+        t = Switch::RequiredArgument
+      end
+      self >= t or incompatible_argument_styles(arg, t)
+      t
+    end
+
+    def self.incompatible_argument_styles(arg, t)
+      raise ArgumentError, "#{arg}: incompatible argument styles\n  #{self}, #{t}"
+    end
+
+    def self.pattern
+      NilClass
+    end
+
+    def initialize(pattern = nil, conv = nil,
+                   short = nil, long = nil, arg = nil,
+                   desc = ([] if short or long), block = Proc.new)
+      raise if Array === pattern
+      @pattern, @conv, @short, @long, @arg, @desc, @block =
+        pattern, conv, short, long, arg, desc, block
+    end
+
+    #
+    # Parses +arg+ and returns rest of +arg+ and matched portion to the
+    # argument pattern. Yields when the pattern doesn't match substring.
+    #
+    def parse_arg(arg)
+      pattern or return nil, arg
+      unless m = pattern.match(arg)
+        yield(InvalidArgument, arg)
+        return arg, nil
+      end
+      if String === m
+        m = [s = m]
+      else
+        m = m.to_a
+        s = m[0]
+        return nil, m unless String === s
+      end
+      raise InvalidArgument, arg unless arg.rindex(s, 0)
+      return nil, m if s.length == arg.length
+      yield(InvalidArgument, arg) # didn't match whole arg
+      return arg[s.length..-1], m
+    end
+    private :parse_arg
+
+    #
+    # Parses argument, converts and returns +arg+, +block+ and result of
+    # conversion. Yields at semi-error condition instead of raising an
+    # exception.
+    #
+    def conv_arg(arg, val = nil)
+      if conv
+        val = conv.call(*val)
+      else
+        val = proc {|val| val}.call(*val)
+      end
+      return arg, block, val
+    end
+    private :conv_arg
+
+    #
+    # Produces the summary text. Each line of the summary is yielded to the
+    # block (without newline).
+    #
+    # +sdone+::  Already summarized short style options keyed hash.
+    # +ldone+::  Already summarized long style options keyed hash.
+    # +width+::  Width of left side (option part). In other words, the right
+    #            side (description part) starts after +width+ columns.
+    # +max+::    Maximum width of left side -> the options are filled within
+    #            +max+ columns.
+    # +indent+:: Prefix string indents all summarized lines.
+    #
+    def summarize(sdone = [], ldone = [], width = 1, max = width - 1, indent = "")
+      sopts, lopts, s = [], [], nil
+      @short.each {|s| sdone.fetch(s) {sopts << s}; sdone[s] = true} if @short
+      @long.each {|s| ldone.fetch(s) {lopts << s}; ldone[s] = true} if @long
+      return if sopts.empty? and lopts.empty? # completely hidden
+
+      left = [sopts.join(', ')]
+      right = desc.dup
+
+      while s = lopts.shift
+        l = left[-1].length + s.length
+        l += arg.length if left.size == 1 && arg
+        l < max or left << ''
+        left[-1] << if left[-1].empty? then ' ' * 4 else ', ' end << s
+      end
+
+      left[0] << arg if arg
+      mlen = left.collect {|s| s.length}.max.to_i
+      while mlen > width and l = left.shift
+        mlen = left.collect {|s| s.length}.max.to_i if l.length == mlen
+        yield(indent + l)
+      end
+
+      while begin l = left.shift; r = right.shift; l or r end
+        l = l.to_s.ljust(width) + ' ' + r if r and !r.empty?
+        yield(indent + l)
+      end
+
+      self
+    end
+
+    def add_banner(to)  # :nodoc:
+      unless @short or @long
+        s = desc.join
+        to << " [" + s + "]..." unless s.empty?
+      end
+      to
+    end
+
+    def match_nonswitch?(str) # :nodoc:
+      @pattern =~ str unless @short or @long
+    end
+
+    #
+    # Main name of the switch.
+    #
+    def switch_name
+      (long.first || short.first).sub(/\A-+(?:\[no-\])?/, '')
+    end
+
+    #
+    # Switch that takes no arguments.
+    #
+    class NoArgument < self
+
+      #
+      # Raises an exception if any arguments given.
+      #
+      def parse(arg, argv)
+        yield(NeedlessArgument, arg) if arg
+        conv_arg(arg)
+      end
+
+      def self.incompatible_argument_styles(*)
+      end
+
+      def self.pattern
+        Object
+      end
+    end
+
+    #
+    # Switch that takes an argument.
+    #
+    class RequiredArgument < self
+
+      #
+      # Raises an exception if argument is not present.
+      #
+      def parse(arg, argv)
+        unless arg
+          raise MissingArgument if argv.empty?
+          arg = argv.shift
+        end
+        conv_arg(*parse_arg(arg) {|*exc| raise(*exc)})
+      end
+    end
+
+    #
+    # Switch that can omit argument.
+    #
+    class OptionalArgument < self
+
+      #
+      # Parses argument if given, or uses default value.
+      #
+      def parse(arg, argv, &error)
+        if arg
+          conv_arg(*parse_arg(arg, &error))
+        else
+          conv_arg(arg)
+        end
+      end
+    end
+
+    #
+    # Switch that takes an argument, which does not begin with '-'.
+    #
+    class PlacedArgument < self
+
+      #
+      # Returns nil if argument is not present or begins with '-'.
+      #
+      def parse(arg, argv, &error)
+        if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
+          return nil, block, nil
+        end
+        opt = (val = parse_arg(val, &error))[1]
+        val = conv_arg(*val)
+        if opt and !arg
+          argv.shift
+        else
+          val[0] = nil
+        end
+        val
+      end
+    end
+  end
+
+  #
+  # Simple option list providing mapping from short and/or long option
+  # string to OptionParser::Switch and mapping from acceptable argument to
+  # matching pattern and converter pair. Also provides summary feature.
+  #
+  class List
+    # Map from acceptable argument types to pattern and converter pairs.
+    attr_reader :atype
+    
+    # Map from short style option switches to actual switch objects.
+    attr_reader :short
+    
+    # Map from long style option switches to actual switch objects.
+    attr_reader :long
+    
+    # List of all switches and summary string.
+    attr_reader :list
+
+    #
+    # Just initializes all instance variables.
+    #
+    def initialize
+      @atype = {}
+      @short = OptionMap.new
+      @long = OptionMap.new
+      @list = []
+    end
+
+    #
+    # See OptionParser.accept.
+    #
+    def accept(t, pat = /.*/nm, &block)
+      if pat
+        pat.respond_to?(:match) or raise TypeError, "has no `match'"
+      else
+        pat = t if t.respond_to?(:match)
+      end
+      unless block
+        block = pat.method(:convert).to_proc if pat.respond_to?(:convert)
+      end
+      @atype[t] = [pat, block]
+    end
+
+    #
+    # See OptionParser.reject.
+    #
+    def reject(t)
+      @atype.delete(t)
+    end
+
+    #
+    # Adds +sw+ according to +sopts+, +lopts+ and +nlopts+.
+    #
+    # +sw+::     OptionParser::Switch instance to be added.
+    # +sopts+::  Short style option list.
+    # +lopts+::  Long style option list.
+    # +nlopts+:: Negated long style options list.
+    #
+    def update(sw, sopts, lopts, nsw = nil, nlopts = nil)
+      o = nil
+      sopts.each {|o| @short[o] = sw} if sopts
+      lopts.each {|o| @long[o] = sw} if lopts
+      nlopts.each {|o| @long[o] = nsw} if nsw and nlopts
+      used = @short.invert.update(@long.invert)
+      @list.delete_if {|o| Switch === o and !used[o]}
+    end
+    private :update
+
+    #
+    # Inserts +switch+ at the head of the list, and associates short, long
+    # and negated long options. Arguments are:
+    # 
+    # +switch+::      OptionParser::Switch instance to be inserted.
+    # +short_opts+::  List of short style options.
+    # +long_opts+::   List of long style options.
+    # +nolong_opts+:: List of long style options with "no-" prefix.
+    #
+    #   prepend(switch, short_opts, long_opts, nolong_opts)
+    #
+    def prepend(*args)
+      update(*args)
+      @list.unshift(args[0])
+    end
+
+    #
+    # Appends +switch+ at the tail of the list, and associates short, long
+    # and negated long options. Arguments are:
+    # 
+    # +switch+::      OptionParser::Switch instance to be inserted.
+    # +short_opts+::  List of short style options.
+    # +long_opts+::   List of long style options.
+    # +nolong_opts+:: List of long style options with "no-" prefix.
+    #
+    #   append(switch, short_opts, long_opts, nolong_opts)
+    #
+    def append(*args)
+      update(*args)
+      @list.push(args[0])
+    end
+
+    #
+    # Searches +key+ in +id+ list. The result is returned or yielded if a
+    # block is given. If it isn't found, nil is returned.
+    #
+    def search(id, key)
+      if list = __send__(id)
+        val = list.fetch(key) {return nil}
+        block_given? ? yield(val) : val
+      end
+    end
+
+    #
+    # Searches list +id+ for +opt+ and the optional patterns for completion
+    # +pat+. If +icase+ is true, the search is case insensitive. The result
+    # is returned or yielded if a block is given. If it isn't found, nil is
+    # returned.
+    #
+    def complete(id, opt, icase = false, *pat, &block)
+      __send__(id).complete(opt, icase, *pat, &block)
+    end
+
+    #
+    # Iterates over each option, passing the option to the +block+.
+    #
+    def each_option(&block)
+      list.each(&block)
+    end
+
+    #
+    # Creates the summary table, passing each line to the +block+ (without
+    # newline). The arguments +args+ are passed along to the summarize
+    # method which is called on every option.
+    #
+    def summarize(*args, &block)
+      list.each do |opt|
+        if opt.respond_to?(:summarize) # perhaps OptionParser::Switch
+          opt.summarize(*args, &block)
+        elsif !opt or opt.empty?
+          yield("")
+        else
+          opt.each(&block)
+        end
+      end
+    end
+
+    def add_banner(to)  # :nodoc:
+      list.each do |opt|
+        if opt.respond_to?(:add_banner)
+          opt.add_banner(to)
+        end
+      end
+      to
+    end
+  end
+
+  #
+  # Hash with completion search feature. See OptionParser::Completion.
+  #
+  class CompletingHash < Hash
+    include Completion
+
+    #
+    # Completion for hash key.
+    #
+    def match(key)
+      return key, *fetch(key) {
+        raise AmbiguousArgument, catch(:ambiguous) {return complete(key)}
+      }
+    end
+  end
+
+  # :stopdoc:
+
+  #
+  # Enumeration of acceptable argument styles. Possible values are:
+  #
+  # NO_ARGUMENT::       The switch takes no arguments. (:NONE)
+  # REQUIRED_ARGUMENT:: The switch requires an argument. (:REQUIRED)
+  # OPTIONAL_ARGUMENT:: The switch requires an optional argument. (:OPTIONAL)
+  #
+  # Use like --switch=argument (long style) or -Xargument (short style). For
+  # short style, only portion matched to argument pattern is dealed as
+  # argument.
+  #
+  ArgumentStyle = {}
+  NoArgument.each {|el| ArgumentStyle[el] = Switch::NoArgument}
+  RequiredArgument.each {|el| ArgumentStyle[el] = Switch::RequiredArgument}
+  OptionalArgument.each {|el| ArgumentStyle[el] = Switch::OptionalArgument}
+  ArgumentStyle.freeze
+
+  #
+  # Switches common used such as '--', and also provides default
+  # argument classes
+  #
+  DefaultList = List.new
+  DefaultList.short['-'] = Switch::NoArgument.new {}
+  DefaultList.long[''] = Switch::NoArgument.new {throw :terminate}
+
+  #
+  # Default options for ARGV, which never appear in option summary.
+  #
+  Officious = {}
+
+  #
+  # --help
+  # Shows option summary.
+  #
+  Officious['help'] = proc do |parser|
+    Switch::NoArgument.new do
+      puts parser.help
+      exit
+    end
+  end
+
+  #
+  # --version
+  # Shows version string if Version is defined.
+  #
+  Officious['version'] = proc do |parser|
+    Switch::OptionalArgument.new do |pkg|
+      if pkg
+        begin
+          require 'optparse/version'
+        rescue LoadError
+        else
+          show_version(*pkg.split(/,/)) or
+            abort("#{parser.program_name}: no version found in package #{pkg}")
+          exit
+        end
+      end
+      v = parser.ver or abort("#{parser.program_name}: version unknown")
+      puts v
+      exit
+    end
+  end
+
+  # :startdoc:
+
+  #
+  # Class methods
+  #
+
+  #
+  # Initializes a new instance and evaluates the optional block in context
+  # of the instance. Arguments +args+ are passed to #new, see there for
+  # description of parameters.
+  # 
+  # This method is *deprecated*, its behavior corresponds to the older #new
+  # method.
+  #
+  def self.with(*args, &block)
+    opts = new(*args)
+    opts.instance_eval(&block)
+    opts
+  end
+
+  #
+  # Returns an incremented value of +default+ according to +arg+.
+  #
+  def self.inc(arg, default = nil)
+    case arg
+    when Integer
+      arg.nonzero?
+    when nil
+      default.to_i + 1
+    end
+  end
+  def inc(*args)
+    self.class.inc(*args)
+  end
+
+  #
+  # Initializes the instance and yields itself if called with a block.
+  #
+  # +banner+:: Banner message.
+  # +width+::  Summary width.
+  # +indent+:: Summary indent.
+  #
+  def initialize(banner = nil, width = 32, indent = ' ' * 4)
+    @stack = [DefaultList, List.new, List.new]
+    @program_name = nil
+    @banner = banner
+    @summary_width = width
+    @summary_indent = indent
+    @default_argv = ARGV
+    add_officious
+    yield self if block_given?
+  end
+
+  def add_officious  # :nodoc:
+    list = base()
+    Officious.each do |opt, block|
+      list.long[opt] ||= block.call(self)
+    end
+  end
+
+  #
+  # Terminates option parsing. Optional parameter +arg+ is a string pushed
+  # back to be the first non-option argument.
+  #
+  def terminate(arg = nil)
+    self.class.terminate(arg)
+  end
+  def self.terminate(arg = nil)
+    throw :terminate, arg
+  end
+
+  @stack = [DefaultList]
+  def self.top() DefaultList end
+
+  #
+  # Directs to accept specified class +t+. The argument string is passed to
+  # the block in which it should be converted to the desired class.
+  #
+  # +t+::   Argument class specifier, any object including Class.
+  # +pat+:: Pattern for argument, defaults to +t+ if it responds to match.
+  #
+  #   accept(t, pat, &block)
+  #
+  def accept(*args, &blk) top.accept(*args, &blk) end
+  #
+  # See #accept.
+  #
+  def self.accept(*args, &blk) top.accept(*args, &blk) end
+
+  #
+  # Directs to reject specified class argument.
+  #
+  # +t+:: Argument class speficier, any object including Class.
+  #
+  #   reject(t)
+  #
+  def reject(*args, &blk) top.reject(*args, &blk) end
+  #
+  # See #reject.
+  #
+  def self.reject(*args, &blk) top.reject(*args, &blk) end
+
+  #
+  # Instance methods
+  #
+
+  # Heading banner preceding summary.
+  attr_writer :banner
+
+  # Program name to be emitted in error message and default banner,
+  # defaults to $0.
+  attr_writer :program_name
+
+  # Width for option list portion of summary. Must be Numeric.
+  attr_accessor :summary_width
+
+  # Indentation for summary. Must be String (or have + String method).
+  attr_accessor :summary_indent
+
+  # Strings to be parsed in default.
+  attr_accessor :default_argv
+
+  #
+  # Heading banner preceding summary.
+  #
+  def banner
+    unless @banner
+      @banner = "Usage: #{program_name} [options]"
+      visit(:add_banner, @banner)
+    end
+    @banner
+  end
+
+  #
+  # Program name to be emitted in error message and default banner, defaults
+  # to $0.
+  #
+  def program_name
+    @program_name || File.basename($0, '.*')
+  end
+
+  # for experimental cascading :-)
+  alias set_banner banner=
+  alias set_program_name program_name=
+  alias set_summary_width summary_width=
+  alias set_summary_indent summary_indent=
+
+  # Version
+  attr_writer :version
+  # Release code
+  attr_writer :release
+
+  #
+  # Version
+  #
+  def version
+    @version || (defined?(::Version) && ::Version)
+  end
+
+  #
+  # Release code
+  #
+  def release
+    @release || (defined?(::Release) && ::Release) || (defined?(::RELEASE) && ::RELEASE)
+  end
+
+  #
+  # Returns version string from program_name, version and release.
+  #
+  def ver
+    if v = version
+      str = "#{program_name} #{[v].join('.')}"
+      str << " (#{v})" if v = release
+      str
+    end
+  end
+
+  def warn(mesg = $!)
+    super("#{program_name}: #{mesg}")
+  end
+
+  def abort(mesg = $!)
+    super("#{program_name}: #{mesg}")
+  end
+
+  #
+  # Subject of #on / #on_head, #accept / #reject
+  #
+  def top
+    @stack[-1]
+  end
+
+  #
+  # Subject of #on_tail.
+  #
+  def base
+    @stack[1]
+  end
+
+  #
+  # Pushes a new List.
+  #
+  def new
+    @stack.push(List.new)
+    if block_given?
+      yield self
+    else
+      self
+    end
+  end
+
+  #
+  # Removes the last List.
+  #
+  def remove
+    @stack.pop
+  end
+
+  #
+  # Puts option summary into +to+ and returns +to+. Yields each line if
+  # a block is given.
+  #
+  # +to+:: Output destination, which must have method <<. Defaults to [].
+  # +width+:: Width of left side, defaults to @summary_width.
+  # +max+:: Maximum length allowed for left side, defaults to +width+ - 1.
+  # +indent+:: Indentation, defaults to @summary_indent.
+  #
+  def summarize(to = [], width = @summary_width, max = width - 1, indent = @summary_indent, &blk)
+    visit(:summarize, {}, {}, width, max, indent, &(blk || proc {|l| to << l + $/}))
+    to
+  end
+
+  #
+  # Returns option summary string.
+  #
+  def help; summarize(banner.to_s.sub(/\n?\z/, "\n")) end
+  alias to_s help
+
+  #
+  # Returns option summary list.
+  #
+  def to_a; summarize(banner.to_a.dup) end
+
+  #
+  # Checks if an argument is given twice, in which case an ArgumentError is
+  # raised. Called from OptionParser#switch only.
+  #
+  # +obj+:: New argument.
+  # +prv+:: Previously specified argument.
+  # +msg+:: Exception message.
+  #
+  def notwice(obj, prv, msg)
+    unless !prv or prv == obj
+      begin
+        raise ArgumentError, "argument #{msg} given twice: #{obj}"
+      rescue
+        $@[0, 2] = nil
+        raise
+      end
+    end
+    obj
+  end
+  private :notwice
+
+  #
+  # Creates an OptionParser::Switch from the parameters. The parsed argument
+  # value is passed to the given block, where it can be processed.
+  #
+  # See at the beginning of OptionParser for some full examples.
+  #
+  # +opts+ can include the following elements:
+  #
+  # [Argument style:]
+  #   One of the following:
+  #     :NONE, :REQUIRED, :OPTIONAL
+  #
+  # [Argument pattern:]
+  #   Acceptable option argument format, must be pre-defined with
+  #   OptionParser.accept or OptionParser#accept, or Regexp. This can appear
+  #   once or assigned as String if not present, otherwise causes an
+  #   ArgumentError. Examples:
+  #     Float, Time, Array
+  #
+  # [Possible argument values:]
+  #   Hash or Array.
+  #     [:text, :binary, :auto]
+  #     %w[iso-2022-jp shift_jis euc-jp utf8 binary]
+  #     { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
+  #
+  # [Long style switch:]
+  #   Specifies a long style switch which takes a mandatory, optional or no
+  #   argument. It's a string of the following form:
+  #     "--switch=MANDATORY" or "--switch MANDATORY"
+  #     "--switch[=OPTIONAL]"
+  #     "--switch"
+  #
+  # [Short style switch:]
+  #   Specifies short style switch which takes a mandatory, optional or no
+  #   argument. It's a string of the following form:
+  #     "-xMANDATORY"
+  #     "-x[OPTIONAL]"
+  #     "-x"
+  #   There is also a special form which matches character range (not full
+  #   set of regural expression):
+  #     "-[a-z]MANDATORY"
+  #     "-[a-z][OPTIONAL]" 
+  #     "-[a-z]"
+  #
+  # [Argument style and description:]
+  #   Instead of specifying mandatory or optional orguments directly in the
+  #   switch parameter, this separate parameter can be used.
+  #     "=MANDATORY"
+  #     "=[OPTIONAL]"
+  #
+  # [Description:]
+  #   Description string for the option.
+  #     "Run verbosely"
+  # 
+  # [Handler:]
+  #   Handler for the parsed argument value. Either give a block or pass a
+  #   Proc or Method as an argument.
+  #
+  def make_switch(opts, block = nil)
+    short, long, nolong, style, pattern, conv, not_pattern, not_conv, not_style = [], [], []
+    ldesc, sdesc, desc, arg = [], [], []
+    default_style = Switch::NoArgument
+    default_pattern = nil
+    klass = nil
+    o = nil
+    n, q, a = nil
+
+    opts.each do |o|
+      # argument class
+      next if search(:atype, o) do |pat, c|
+        klass = notwice(o, klass, 'type')
+        if not_style and not_style != Switch::NoArgument
+          not_pattern, not_conv = pat, c
+        else
+          default_pattern, conv = pat, c
+        end
+      end
+
+      # directly specified pattern(any object possible to match)
+      if !(String === o) and o.respond_to?(:match)
+        pattern = notwice(o, pattern, 'pattern')
+        conv = (pattern.method(:convert).to_proc if pattern.respond_to?(:convert))
+        next
+      end
+
+      # anything others
+      case o
+      when Proc, Method
+        block = notwice(o, block, 'block')
+      when Array, Hash
+        case pattern
+        when CompletingHash
+        when nil
+          pattern = CompletingHash.new
+          conv = (pattern.method(:convert).to_proc if pattern.respond_to?(:convert))
+        else
+          raise ArgumentError, "argument pattern given twice"
+        end
+        o.each {|(o, *v)| pattern[o] = v.fetch(0) {o}}
+      when Module
+        raise ArgumentError, "unsupported argument type: #{o}"
+      when *ArgumentStyle.keys
+        style = notwice(ArgumentStyle[o], style, 'style')
+      when /^--no-([^\[\]=\s]*)(.+)?/
+        q, a = $1, $2
+        o = notwice(a ? Object : TrueClass, klass, 'type')
+        not_pattern, not_conv = search(:atype, o) unless not_style
+        not_style = (not_style || default_style).guess(arg = a) if a
+        default_style = Switch::NoArgument
+        default_pattern, conv = search(:atype, FalseClass) unless default_pattern
+        ldesc << "--no-#{q}"
+        long << 'no-' + (q = q.downcase)
+        nolong << q
+      when /^--\[no-\]([^\[\]=\s]*)(.+)?/
+        q, a = $1, $2
+        o = notwice(a ? Object : TrueClass, klass, 'type')
+        if a
+          default_style = default_style.guess(arg = a)
+          default_pattern, conv = search(:atype, o) unless default_pattern
+        end
+        ldesc << "--[no-]#{q}"
+        long << (o = q.downcase)
+        not_pattern, not_conv = search(:atype, FalseClass) unless not_style
+        not_style = Switch::NoArgument
+        nolong << 'no-' + o
+      when /^--([^\[\]=\s]*)(.+)?/
+        q, a = $1, $2
+        if a
+          o = notwice(NilClass, klass, 'type')
+          default_style = default_style.guess(arg = a)
+          default_pattern, conv = search(:atype, o) unless default_pattern
+        end
+        ldesc << "--#{q}"
+        long << (o = q.downcase)
+      when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/
+        q, a = $1, $2
+        o = notwice(Object, klass, 'type')
+        if a
+          default_style = default_style.guess(arg = a)
+          default_pattern, conv = search(:atype, o) unless default_pattern
+        end
+        sdesc << "-#{q}"
+        short << Regexp.new(q)
+      when /^-(.)(.+)?/
+        q, a = $1, $2
+        if a
+          o = notwice(NilClass, klass, 'type')
+          default_style = default_style.guess(arg = a)
+          default_pattern, conv = search(:atype, o) unless default_pattern
+        end
+        sdesc << "-#{q}"
+        short << q
+      when /^=/
+        style = notwice(default_style.guess(arg = o), style, 'style')
+        default_pattern, conv = search(:atype, Object) unless default_pattern
+      else
+        desc.push(o)
+      end
+    end
+
+    default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern
+    if !(short.empty? and long.empty?)
+      s = (style || default_style).new(pattern || default_pattern,
+                                       conv, sdesc, ldesc, arg, desc, block)
+    elsif !block
+      raise ArgumentError, "no switch given" if style or pattern
+      s = desc
+    else
+      short << pattern
+      s = (style || default_style).new(pattern,
+                                       conv, nil, nil, arg, desc, block)
+    end
+    return s, short, long,
+      (not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style),
+      nolong
+  end
+
+  def define(*opts, &block)
+    top.append(*(sw = make_switch(opts, block)))
+    sw[0]
+  end
+
+  #
+  # Add option switch and handler. See #make_switch for an explanation of
+  # parameters.
+  #
+  def on(*opts, &block)
+    define(*opts, &block)
+    self
+  end
+  alias def_option define
+
+  def define_head(*opts, &block)
+    top.prepend(*(sw = make_switch(opts, block)))
+    sw[0]
+  end
+
+  #
+  # Add option switch like with #on, but at head of summary.
+  #
+  def on_head(*opts, &block)
+    define_head(*opts, &block)
+    self
+  end
+  alias def_head_option define_head
+
+  def define_tail(*opts, &block)
+    base.append(*(sw = make_switch(opts, block)))
+    sw[0]
+  end
+
+  #
+  # Add option switch like with #on, but at tail of summary.
+  #
+  def on_tail(*opts, &block)
+    define_tail(*opts, &block)
+    self
+  end
+  alias def_tail_option define_tail
+
+  #
+  # Add separator in summary.
+  #
+  def separator(string)
+    top.append(string, nil, nil)
+  end
+
+  #
+  # Parses command line arguments +argv+ in order. When a block is given,
+  # each non-option argument is yielded.
+  #
+  # Returns the rest of +argv+ left unparsed.
+  #
+  def order(*argv, &block)
+    argv = argv[0].dup if argv.size == 1 and Array === argv[0]
+    order!(argv, &block)
+  end
+
+  #
+  # Same as #order, but removes switches destructively.
+  #
+  def order!(argv = default_argv, &nonopt)
+    parse_in_order(argv, &nonopt)
+  end
+
+  def parse_in_order(argv = default_argv, setter = nil, &nonopt)  # :nodoc:
+    opt, arg, sw, val, rest = nil
+    nonopt ||= proc {|arg| throw :terminate, arg}
+    argv.unshift(arg) if arg = catch(:terminate) {
+      while arg = argv.shift
+        case arg
+        # long option
+        when /\A--([^=]*)(?:=(.*))?/nm
+          opt, rest = $1, $2
+          begin
+            sw, = complete(:long, opt, true)
+          rescue ParseError
+            raise $!.set_option(arg, true)
+          end
+          begin
+            opt, cb, val = sw.parse(rest, argv) {|*exc| raise(*exc)}
+            val = cb.call(val) if cb
+            setter.call(sw.switch_name, val) if setter
+          rescue ParseError
+            raise $!.set_option(arg, rest)
+          end
+
+        # short option
+        when /\A-(.)((=).*|.+)?/nm
+          opt, has_arg, eq, val, rest = $1, $3, $3, $2, $2
+          begin
+            sw, = search(:short, opt)
+            unless sw
+              begin
+                sw, = complete(:short, opt)
+                # short option matched.
+                val = arg.sub(/\A-/, '')
+                has_arg = true
+              rescue InvalidOption
+                # if no short options match, try completion with long
+                # options.
+                sw, = complete(:long, opt)
+                eq ||= !rest
+              end
+            end
+          rescue ParseError
+            raise $!.set_option(arg, true)
+          end
+          begin
+            opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
+            raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
+            argv.unshift(opt) if opt and (opt = opt.sub(/\A-*/, '-')) != '-'
+            val = cb.call(val) if cb
+            setter.call(sw.switch_name, val) if setter
+          rescue ParseError
+            raise $!.set_option(arg, arg.length > 2)
+          end
+
+        # non-option argument
+        else
+          catch(:prune) do
+            visit(:each_option) do |sw|
+              sw.block.call(arg) if Switch === sw and sw.match_nonswitch?(arg)
+            end
+            nonopt.call(arg)
+          end
+        end
+      end
+
+      nil
+    }
+
+    visit(:search, :short, nil) {|sw| sw.block.call(*argv) if !sw.pattern}
+
+    argv
+  end
+  private :parse_in_order
+
+  #
+  # Parses command line arguments +argv+ in permutation mode and returns
+  # list of non-option arguments.
+  #
+  def permute(*argv)
+    argv = argv[0].dup if argv.size == 1 and Array === argv[0]
+    permute!(argv)
+  end
+
+  #
+  # Same as #permute, but removes switches destructively.
+  #
+  def permute!(argv = default_argv)
+    nonopts = []
+    arg = nil
+    order!(argv) {|arg| nonopts << arg}
+    argv[0, 0] = nonopts
+    argv
+  end
+
+  #
+  # Parses command line arguments +argv+ in order when environment variable
+  # POSIXLY_CORRECT is set, and in permutation mode otherwise.
+  #
+  def parse(*argv)
+    argv = argv[0].dup if argv.size == 1 and Array === argv[0]
+    parse!(argv)
+  end
+
+  #
+  # Same as #parse, but removes switches destructively.
+  #
+  def parse!(argv = default_argv)
+    if ENV.include?('POSIXLY_CORRECT')
+      order!(argv)
+    else
+      permute!(argv)
+    end
+  end
+
+  #
+  # Wrapper method for getopts.rb.
+  #
+  #   params = ARGV.getopts("ab:", "foo", "bar:")
+  #   # params[:a] = true   # -a
+  #   # params[:b] = "1"    # -b1
+  #   # params[:foo] = "1"  # --foo
+  #   # params[:bar] = "x"  # --bar x
+  #
+  def getopts(*args)
+    argv = Array === args.first ? args.shift : default_argv
+    single_options, *long_options = *args
+
+    result = {}
+
+    single_options.scan(/(.)(:)?/) do |opt, val|
+      if val
+        result[opt] = nil
+        define("-#{opt} VAL")
+      else
+        result[opt] = false
+        define("-#{opt}")
+      end
+    end if single_options
+
+    long_options.each do |arg|
+      opt, val = arg.split(':', 2)
+      if val
+        result[opt] = val.empty? ? nil : val
+        define("--#{opt} VAL")
+      else
+        result[opt] = false
+        define("--#{opt}")
+      end
+    end
+
+    parse_in_order(argv, result.method(:[]=))
+    result
+  end
+
+  #
+  # See #getopts.
+  #
+  def self.getopts(*args)
+    new.getopts(*args)
+  end
+
+  #
+  # Traverses @stack, sending each element method +id+ with +args+ and
+  # +block+.
+  #
+  def visit(id, *args, &block)
+    el = nil
+    @stack.reverse_each do |el|
+      el.send(id, *args, &block)
+    end
+    nil
+  end
+  private :visit
+
+  #
+  # Searches +key+ in @stack for +id+ hash and returns or yields the result.
+  #
+  def search(id, key)
+    block_given = block_given?
+    visit(:search, id, key) do |k|
+      return block_given ? yield(k) : k
+    end
+  end
+  private :search
+
+  #
+  # Completes shortened long style option switch and returns pair of
+  # canonical switch and switch descriptor OptionParser::Switch.
+  #
+  # +id+::    Searching table.
+  # +opt+::   Searching key.
+  # +icase+:: Search case insensitive if true.
+  # +pat+::   Optional pattern for completion.
+  #
+  def complete(typ, opt, icase = false, *pat)
+    if pat.empty?
+      search(typ, opt) {|sw| return [sw, opt]} # exact match or...
+    end
+    raise AmbiguousOption, catch(:ambiguous) {
+      visit(:complete, typ, opt, icase, *pat) {|opt, *sw| return sw}
+      raise InvalidOption, opt
+    }
+  end
+  private :complete
+
+  #
+  # Loads options from file names as +filename+. Does nothing when the file
+  # is not present. Returns whether successfully loaded.
+  #
+  # +filename+ defaults to basename of the program without suffix in a
+  # directory ~/.options.
+  #
+  def load(filename = nil)
+    begin
+      filename ||= File.expand_path(File.basename($0, '.*'), '~/.options')
+    rescue
+      return false
+    end
+    begin
+      parse(*IO.readlines(filename).each {|s| s.chomp!})
+      true
+    rescue Errno::ENOENT, Errno::ENOTDIR
+      false
+    end
+  end
+
+  #
+  # Parses environment variable +env+ or its uppercase with splitting like a
+  # shell.
+  #
+  # +env+ defaults to the basename of the program.
+  #
+  def environment(env = File.basename($0, '.*'))
+    env = ENV[env] || ENV[env.upcase] or return
+    parse(*Shellwords.shellwords(env))
+  end
+
+  #
+  # Acceptable argument classes
+  #
+
+  #
+  # Any string and no conversion. This is fall-back.
+  #
+  accept(Object) {|s,|s or s.nil?}
+
+  accept(NilClass) {|s,|s}
+
+  #
+  # Any non-empty string, and no conversion.
+  #
+  accept(String, /.+/nm) {|s,*|s}
+
+  #
+  # Ruby/C-like integer, octal for 0-7 sequence, binary for 0b, hexadecimal
+  # for 0x, and decimal for others; with optional sign prefix. Converts to
+  # Integer.
+  #
+  decimal = '\d+(?:_\d+)*'
+  binary = 'b[01]+(?:_[01]+)*'
+  hex = 'x[\da-f]+(?:_[\da-f]+)*'
+  octal = "0(?:[0-7]*(?:_[0-7]+)*|#{binary}|#{hex})"
+  integer = "#{octal}|#{decimal}"
+  accept(Integer, %r"\A[-+]?(?:#{integer})"io) {|s,| Integer(s) if s}
+
+  #
+  # Float number format, and converts to Float.
+  #
+  float = "(?:#{decimal}(?:\\.(?:#{decimal})?)?|\\.#{decimal})(?:E[-+]?#{decimal})?"
+  floatpat = %r"\A[-+]?#{float}"io
+  accept(Float, floatpat) {|s,| s.to_f if s}
+
+  #
+  # Generic numeric format, converts to Integer for integer format, Float
+  # for float format.
+  #
+  accept(Numeric, %r"\A[-+]?(?:#{octal}|#{float})"io) {|s,| eval(s) if s}
+
+  #
+  # Decimal integer format, to be converted to Integer.
+  #
+  DecimalInteger = /\A[-+]?#{decimal}/io
+  accept(DecimalInteger) {|s,| s.to_i if s}
+
+  #
+  # Ruby/C like octal/hexadecimal/binary integer format, to be converted to
+  # Integer.
+  #
+  OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))/io
+  accept(OctalInteger) {|s,| s.oct if s}
+
+  #
+  # Decimal integer/float number format, to be converted to Integer for
+  # integer format, Float for float format.
+  #
+  DecimalNumeric = floatpat     # decimal integer is allowed as float also.
+  accept(DecimalNumeric) {|s,| eval(s) if s}
+
+  #
+  # Boolean switch, which means whether it is present or not, whether it is
+  # absent or not with prefix no-, or it takes an argument
+  # yes/no/true/false/+/-.
+  #
+  yesno = CompletingHash.new
+  %w[- no false].each {|el| yesno[el] = false}
+  %w[+ yes true].each {|el| yesno[el] = true}
+  yesno['nil'] = false          # shoud be nil?
+  accept(TrueClass, yesno) {|arg, val| val == nil or val}
+  #
+  # Similar to TrueClass, but defaults to false.
+  #
+  accept(FalseClass, yesno) {|arg, val| val != nil and val}
+
+  #
+  # List of strings separated by ",".
+  #
+  accept(Array) do |s,|
+    if s
+      s = s.split(',').collect {|s| s unless s.empty?}
+    end
+    s
+  end
+
+  #
+  # Regular expression with options.
+  #
+  accept(Regexp, %r"\A/((?:\\.|[^\\])*)/([[:alpha:]]+)?\z|.*") do |all, s, o|
+    f = 0
+    if o
+      f |= Regexp::IGNORECASE if /i/ =~ o
+      f |= Regexp::MULTILINE if /m/ =~ o
+      f |= Regexp::EXTENDED if /x/ =~ o
+      k = o.delete("^imx")
+    end
+    Regexp.new(s || all, f, k)
+  end
+
+  #
+  # Exceptions
+  #
+
+  #
+  # Base class of exceptions from OptionParser.
+  #
+  class ParseError < RuntimeError
+    # Reason which caused the error.
+    Reason = 'parse error'.freeze
+
+    def initialize(*args)
+      @args = args
+      @reason = nil
+    end
+
+    attr_reader :args
+    attr_writer :reason
+
+    #
+    # Pushes back erred argument(s) to +argv+.
+    #
+    def recover(argv)
+      argv[0, 0] = @args
+      argv
+    end
+
+    def set_option(opt, eq)
+      if eq
+        @args[0] = opt
+      else
+        @args.unshift(opt)
+      end
+      self
+    end
+
+    #
+    # Returns error reason. Override this for I18N.
+    #
+    def reason
+      @reason || self.class::Reason
+    end
+
+    def inspect
+      "#<#{self.class.to_s}: #{args.join(' ')}>"
+    end
+
+    #
+    # Default stringizing method to emit standard error message.
+    #
+    def message
+      reason + ': ' + args.join(' ')
+    end
+
+    alias to_s message
+  end
+
+  #
+  # Raises when ambiguously completable string is encountered.
+  #
+  class AmbiguousOption < ParseError
+    const_set(:Reason, 'ambiguous option'.freeze)
+  end
+
+  #
+  # Raises when there is an argument for a switch which takes no argument.
+  #
+  class NeedlessArgument < ParseError
+    const_set(:Reason, 'needless argument'.freeze)
+  end
+
+  #
+  # Raises when a switch with mandatory argument has no argument.
+  #
+  class MissingArgument < ParseError
+    const_set(:Reason, 'missing argument'.freeze)
+  end
+
+  #
+  # Raises when switch is undefined.
+  #
+  class InvalidOption < ParseError
+    const_set(:Reason, 'invalid option'.freeze)
+  end
+
+  #
+  # Raises when the given argument does not match required format.
+  #
+  class InvalidArgument < ParseError
+    const_set(:Reason, 'invalid argument'.freeze)
+  end
+
+  #
+  # Raises when the given argument word can't be completed uniquely.
+  #
+  class AmbiguousArgument < InvalidArgument
+    const_set(:Reason, 'ambiguous argument'.freeze)
+  end
+
+  #
+  # Miscellaneous
+  #
+
+  #
+  # Extends command line arguments array (ARGV) to parse itself.
+  #
+  module Arguable
+
+    #
+    # Sets OptionParser object, when +opt+ is +false+ or +nil+, methods
+    # OptionParser::Arguable#options and OptionParser::Arguable#options= are
+    # undefined. Thus, there is no ways to access the OptionParser object
+    # via the receiver object.
+    #
+    def options=(opt)
+      unless @optparse = opt
+        class << self
+          undef_method(:options)
+          undef_method(:options=)
+        end
+      end
+    end
+
+    #
+    # Actual OptionParser object, automatically created if nonexistent.
+    #
+    # If called with a block, yields the OptionParser object and returns the
+    # result of the block. If an OptionParser::ParseError exception occurs
+    # in the block, it is rescued, a error message printed to STDERR and
+    # +nil+ returned.
+    #
+    def options
+      @optparse ||= OptionParser.new
+      @optparse.default_argv = self
+      block_given? or return @optparse
+      begin
+        yield @optparse
+      rescue ParseError
+        @optparse.warn $!
+        nil
+      end
+    end
+
+    #
+    # Parses +self+ destructively in order and returns +self+ containing the
+    # rest arguments left unparsed.
+    #
+    def order!(&blk) options.order!(self, &blk) end
+
+    #
+    # Parses +self+ destructively in permutation mode and returns +self+
+    # containing the rest arguments left unparsed.
+    #
+    def permute!() options.permute!(self) end
+
+    #
+    # Parses +self+ destructively and returns +self+ containing the
+    # rest arguments left unparsed.
+    #
+    def parse!() options.parse!(self) end
+
+    #
+    # Substitution of getopts is possible as follows. Also see
+    # OptionParser#getopts.
+    #
+    #   def getopts(*args)
+    #     ($OPT = ARGV.getopts(*args)).each do |opt, val|
+    #       eval "$OPT_#{opt.gsub(/[^A-Za-z0-9_]/, '_')} = val"
+    #     end
+    #   rescue OptionParser::ParseError
+    #   end
+    #
+    def getopts(*args)
+      options.getopts(self, *args)
+    end
+
+    #
+    # Initializes instance variable.
+    #
+    def self.extend_object(obj)
+      super
+      obj.instance_eval {@optparse = nil}
+    end
+    def initialize(*args)
+      super
+      @optparse = nil
+    end
+  end
+
+  #
+  # Acceptable argument classes. Now contains DecimalInteger, OctalInteger
+  # and DecimalNumeric. See Acceptable argument classes (in source code).
+  #
+  module Acceptables
+    const_set(:DecimalInteger, OptionParser::DecimalInteger)
+    const_set(:OctalInteger, OptionParser::OctalInteger)
+    const_set(:DecimalNumeric, OptionParser::DecimalNumeric)
+  end
+end
+
+# ARGV is arguable by OptionParser
+ARGV.extend(OptionParser::Arguable)
+
+if $0 == __FILE__
+  Version = OptionParser::Version
+  ARGV.options {|q|
+    q.parse!.empty? or puts "what's #{ARGV.join(' ')}?"
+  } or abort(ARGV.options.to_s)
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/date.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/date.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/date.rb	(revision 18425)
@@ -0,0 +1,17 @@
+require 'optparse'
+require 'date'
+
+OptionParser.accept(DateTime) do |s,|
+  begin
+    DateTime.parse(s) if s
+  rescue ArgumentError
+    raise OptionParser::InvalidArgument, s
+  end
+end
+OptionParser.accept(Date) do |s,|
+  begin
+    Date.parse(s) if s
+  rescue ArgumentError
+    raise OptionParser::InvalidArgument, s
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/shellwords.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/shellwords.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/shellwords.rb	(revision 18425)
@@ -0,0 +1,6 @@
+# -*- ruby -*-
+
+require 'shellwords'
+require 'optparse'
+
+OptionParser.accept(Shellwords) {|s,| Shellwords.shellwords(s)}
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/time.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/time.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/time.rb	(revision 18425)
@@ -0,0 +1,10 @@
+require 'optparse'
+require 'time'
+
+OptionParser.accept(Time) do |s,|
+  begin
+    (Time.httpdate(s) rescue Time.parse(s)) if s
+  rescue
+    raise OptionParser::InvalidArgument, s
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/uri.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/uri.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/uri.rb	(revision 18425)
@@ -0,0 +1,6 @@
+# -*- ruby -*-
+
+require 'optparse'
+require 'uri'
+
+OptionParser.accept(URI) {|s,| URI.parse(s) if s}
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/version.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/version.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse/version.rb	(revision 18425)
@@ -0,0 +1,70 @@
+# OptionParser internal utility
+
+class << OptionParser
+  def show_version(*pkg)
+    progname = ARGV.options.program_name
+    result = false
+    show = proc do |klass, cname, version|
+      str = "#{progname}"
+      unless klass == ::Object and cname == :VERSION
+        version = version.join(".") if Array === version
+        str << ": #{klass}" unless klass == Object
+        str << " version #{version}"
+      end
+      [:Release, :RELEASE].find do |rel|
+        if klass.const_defined?(rel)
+          str << " (#{klass.const_get(rel)})"
+        end
+      end
+      puts str
+      result = true
+    end
+    if pkg.size == 1 and pkg[0] == "all"
+      self.search_const(::Object, /\AV(?:ERSION|ersion)\z/) do |klass, cname, version|
+        unless cname[1] == ?e and klass.const_defined?(:Version)
+          show.call(klass, cname.intern, version)
+        end
+      end
+    else
+      pkg.each do |pkg|
+        begin
+          pkg = pkg.split(/::|\//).inject(::Object) {|m, c| m.const_get(c)}
+          v = case
+              when pkg.const_defined?(:Version)
+                pkg.const_get(n = :Version)
+              when pkg.const_defined?(:VERSION)
+                pkg.const_get(n = :VERSION)
+              else
+                n = nil
+                "unknown"
+              end
+          show.call(pkg, n, v)
+        rescue NameError
+        end
+      end
+    end
+    result
+  end
+
+  def each_const(path, klass = ::Object)
+    path.split(/::|\//).inject(klass) do |klass, name|
+      raise NameError, path unless Module === klass
+      klass.constants.grep(/#{name}/i) do |c|
+        klass.const_defined?(c) or next
+        c = klass.const_get(c)
+      end
+    end
+  end
+
+  def search_const(klass, name)
+    klasses = [klass]
+    while klass = klasses.shift
+      klass.constants.each do |cname|
+        klass.const_defined?(cname) or next
+        const = klass.const_get(cname)
+        yield klass, cname, const if name === cname
+        klasses << const if Module === const and const != ::Object
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/ostruct.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/ostruct.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/ostruct.rb	(revision 18425)
@@ -0,0 +1,146 @@
+#
+# = ostruct.rb: OpenStruct implementation
+#
+# Author:: Yukihiro Matsumoto
+# Documentation:: Gavin Sinclair
+#
+# OpenStruct allows the creation of data objects with arbitrary attributes.
+# See OpenStruct for an example.
+#
+
+#
+# OpenStruct allows you to create data objects and set arbitrary attributes.
+# For example:
+#
+#   require 'ostruct' 
+#
+#   record = OpenStruct.new
+#   record.name    = "John Smith"
+#   record.age     = 70
+#   record.pension = 300
+#   
+#   puts record.name     # -> "John Smith"
+#   puts record.address  # -> nil
+#
+# It is like a hash with a different way to access the data.  In fact, it is
+# implemented with a hash, and you can initialize it with one.
+#
+#   hash = { "country" => "Australia", :population => 20_000_000 }
+#   data = OpenStruct.new(hash)
+#
+#   p data        # -> <OpenStruct country="Australia" population=20000000>
+#
+class OpenStruct
+  #
+  # Create a new OpenStruct object.  The optional +hash+, if given, will
+  # generate attributes and values.  For example.
+  #
+  #   require 'ostruct'
+  #   hash = { "country" => "Australia", :population => 20_000_000 }
+  #   data = OpenStruct.new(hash)
+  #
+  #   p data        # -> <OpenStruct country="Australia" population=20000000>
+  #
+  # By default, the resulting OpenStruct object will have no attributes. 
+  #
+  def initialize(hash=nil)
+    @table = {}
+    if hash
+      for k,v in hash
+        @table[k.to_sym] = v
+        new_ostruct_member(k)
+      end
+    end
+  end
+
+  # Duplicate an OpenStruct object members. 
+  def initialize_copy(orig)
+    super
+    @table = @table.dup
+  end
+
+  def marshal_dump
+    @table
+  end
+  def marshal_load(x)
+    @table = x
+    @table.each_key{|key| new_ostruct_member(key)}
+  end
+
+  def new_ostruct_member(name)
+    name = name.to_sym
+    unless self.respond_to?(name)
+      meta = class << self; self; end
+      meta.send(:define_method, name) { @table[name] }
+      meta.send(:define_method, :"#{name}=") { |x| @table[name] = x }
+    end
+  end
+
+  def method_missing(mid, *args) # :nodoc:
+    mname = mid.id2name
+    len = args.length
+    if mname =~ /=$/
+      if len != 1
+        raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
+      end
+      if self.frozen?
+        raise TypeError, "can't modify frozen #{self.class}", caller(1)
+      end
+      mname.chop!
+      self.new_ostruct_member(mname)
+      @table[mname.intern] = args[0]
+    elsif len == 0
+      @table[mid]
+    else
+      raise NoMethodError, "undefined method `#{mname}' for #{self}", caller(1)
+    end
+  end
+
+  #
+  # Remove the named field from the object.
+  #
+  def delete_field(name)
+    @table.delete name.to_sym
+  end
+
+  InspectKey = :__inspect_key__ # :nodoc:
+
+  #
+  # Returns a string containing a detailed summary of the keys and values.
+  #
+  def inspect
+    str = "#<#{self.class}"
+
+    Thread.current[InspectKey] ||= []
+    if Thread.current[InspectKey].include?(self) then
+      str << " ..."
+    else
+      first = true
+      for k,v in @table
+        str << "," unless first
+        first = false
+
+        Thread.current[InspectKey] << v
+        begin
+          str << " #{k}=#{v.inspect}"
+        ensure
+          Thread.current[InspectKey].pop
+        end
+      end
+    end
+
+    str << ">"
+  end
+  alias :to_s :inspect
+
+  attr_reader :table # :nodoc:
+  protected :table
+
+  #
+  # Compare this object and +other+ for equality.
+  #
+  def ==(other)
+    return false unless(other.kind_of?(OpenStruct))
+    return @table == other.table
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/parsearg.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/parsearg.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/parsearg.rb	(revision 18425)
@@ -0,0 +1,87 @@
+#
+#		parsearg.rb - parse arguments
+#			$Release Version: $
+#			$Revision: 11708 $
+#			$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#			by Yasuo OHBA(SHL Japan Inc. Technology Dept.)
+#
+# --
+#
+#	
+#
+
+warn "Warning:#{caller[0].sub(/:in `.*'\z/, '')}: parsearg is deprecated after Ruby 1.8.1; use optparse instead"
+
+$RCS_ID=%q$Header$
+
+require "getopts"
+
+def printUsageAndExit()
+  if $USAGE
+    eval($USAGE)
+  end
+  exit()
+end
+
+def setParenthesis(ex, opt, c)
+  if opt != ""
+    ex = sprintf("%s$OPT_%s%s", ex, opt, c)
+  else
+    ex = sprintf("%s%s", ex, c)
+  end
+  return ex
+end
+
+def setOrAnd(ex, opt, c)
+  if opt != ""
+    ex = sprintf("%s$OPT_%s %s%s ", ex, opt, c, c)
+  else
+    ex = sprintf("%s %s%s ", ex, c, c)
+  end
+  return ex
+end
+
+def setExpression(ex, opt, op)
+  if !op
+    ex = sprintf("%s$OPT_%s", ex, opt)
+    return ex
+  end
+  case op.chr
+  when "(", ")"
+    ex = setParenthesis(ex, opt, op.chr)
+  when "|", "&"
+    ex = setOrAnd(ex, opt, op.chr)
+  else
+    return nil
+  end
+  return ex
+end
+
+# parseArgs is obsolete.  Use OptionParser instead.
+
+def parseArgs(argc, nopt, single_opts, *opts)
+  if (noOptions = getopts(single_opts, *opts)) == nil
+    printUsageAndExit()
+  end
+  if nopt
+    ex = nil
+    pos = 0
+    for o in nopt.split(/[()|&]/)
+      pos += o.length
+      ex = setExpression(ex, o, nopt[pos])
+      pos += 1
+    end
+    begin
+      if !eval(ex)
+	printUsageAndExit()
+      end
+    rescue
+      print "Format Error!! : \"" + nopt + "\"\t[parseArgs]\n"
+      exit!(-1)
+    end
+  end
+  if ARGV.length < argc
+    printUsageAndExit()
+  end
+  return noOptions
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/parsedate.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/parsedate.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/parsedate.rb	(revision 18425)
@@ -0,0 +1,53 @@
+#
+# = parsedate.rb: Parses dates
+#
+# Author:: Tadayoshi Funaba
+# Documentation:: Konrad Meyer
+#
+# ParseDate munches on a date and turns it into an array of values.
+#
+
+#
+# ParseDate converts a date into an array of values.
+# For example:
+#
+#   require 'parsedate'
+#
+#   ParseDate.parsedate "Tuesday, July 6th, 2007, 18:35:20 UTC"
+#   # => [2007, 7, 6, 18, 35, 20, "UTC", 2]
+#
+# The order is of the form [year, month, day of month, hour, minute, second,
+# timezone, day of the week].
+
+require 'date/format'
+
+module ParseDate
+  #
+  # Parse a string representation of a date into values.
+  # For example:
+  #
+  #   require 'parsedate'
+  #
+  #   ParseDate.parsedate "Tuesday, July 5th, 2007, 18:35:20 UTC"
+  #   # => [2007, 7, 5, 18, 35, 20, "UTC", 2]
+  #
+  # The order is of the form [year, month, day of month, hour, minute,
+  # second, timezone, day of week].
+  #
+  # ParseDate.parsedate can also take a second argument, +comp+, which
+  # is a boolean telling the method to compensate for dates with years
+  # expressed as two digits. Example:
+  #
+  #   require 'parsedate'
+  #
+  #   ParseDate.parsedate "Mon Dec 25 00 06:53:24 UTC", true
+  #   # => [2000, 12, 25, 6, 53, 24, "UTC", 1]
+  #
+  def parsedate(str, comp=false)
+    Date._parse(str, comp).
+      values_at(:year, :mon, :mday, :hour, :min, :sec, :zone, :wday)
+  end
+
+  module_function :parsedate
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/pathname.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/pathname.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/pathname.rb	(revision 18425)
@@ -0,0 +1,1062 @@
+#
+# = pathname.rb
+#
+# Object-Oriented Pathname Class
+#
+# Author:: Tanaka Akira <akr@m17n.org>
+# Documentation:: Author and Gavin Sinclair
+#
+# For documentation, see class Pathname.
+#
+# <tt>pathname.rb</tt> is distributed with Ruby since 1.8.0.
+#
+
+#
+# == Pathname
+#
+# Pathname represents a pathname which locates a file in a filesystem.
+# The pathname depends on OS: Unix, Windows, etc.
+# Pathname library works with pathnames of local OS.
+# However non-Unix pathnames are supported experimentally.
+#
+# It does not represent the file itself.
+# A Pathname can be relative or absolute.  It's not until you try to
+# reference the file that it even matters whether the file exists or not.
+#
+# Pathname is immutable.  It has no method for destructive update.
+#
+# The value of this class is to manipulate file path information in a neater
+# way than standard Ruby provides.  The examples below demonstrate the
+# difference.  *All* functionality from File, FileTest, and some from Dir and
+# FileUtils is included, in an unsurprising way.  It is essentially a facade for
+# all of these, and more.
+#
+# == Examples
+#
+# === Example 1: Using Pathname
+#
+#   require 'pathname'
+#   p = Pathname.new("/usr/bin/ruby")
+#   size = p.size              # 27662
+#   isdir = p.directory?       # false
+#   dir  = p.dirname           # Pathname:/usr/bin
+#   base = p.basename          # Pathname:ruby
+#   dir, base = p.split        # [Pathname:/usr/bin, Pathname:ruby]
+#   data = p.read
+#   p.open { |f| _ } 
+#   p.each_line { |line| _ }
+#
+# === Example 2: Using standard Ruby
+#
+#   p = "/usr/bin/ruby"
+#   size = File.size(p)        # 27662
+#   isdir = File.directory?(p) # false
+#   dir  = File.dirname(p)     # "/usr/bin"
+#   base = File.basename(p)    # "ruby"
+#   dir, base = File.split(p)  # ["/usr/bin", "ruby"]
+#   data = File.read(p)
+#   File.open(p) { |f| _ } 
+#   File.foreach(p) { |line| _ }
+#
+# === Example 3: Special features
+#
+#   p1 = Pathname.new("/usr/lib")   # Pathname:/usr/lib
+#   p2 = p1 + "ruby/1.8"            # Pathname:/usr/lib/ruby/1.8
+#   p3 = p1.parent                  # Pathname:/usr
+#   p4 = p2.relative_path_from(p3)  # Pathname:lib/ruby/1.8
+#   pwd = Pathname.pwd              # Pathname:/home/gavin
+#   pwd.absolute?                   # true
+#   p5 = Pathname.new "."           # Pathname:.
+#   p5 = p5 + "music/../articles"   # Pathname:music/../articles
+#   p5.cleanpath                    # Pathname:articles
+#   p5.realpath                     # Pathname:/home/gavin/articles
+#   p5.children                     # [Pathname:/home/gavin/articles/linux, ...]
+# 
+# == Breakdown of functionality
+#
+# === Core methods
+#
+# These methods are effectively manipulating a String, because that's all a path
+# is.  Except for #mountpoint?, #children, and #realpath, they don't access the
+# filesystem.
+#
+# - +
+# - #join
+# - #parent
+# - #root?
+# - #absolute?
+# - #relative?
+# - #relative_path_from
+# - #each_filename
+# - #cleanpath
+# - #realpath
+# - #children
+# - #mountpoint?
+#
+# === File status predicate methods
+#
+# These methods are a facade for FileTest:
+# - #blockdev?
+# - #chardev?
+# - #directory?
+# - #executable?
+# - #executable_real?
+# - #exist?
+# - #file?
+# - #grpowned?
+# - #owned?
+# - #pipe?
+# - #readable?
+# - #world_readable?
+# - #readable_real?
+# - #setgid?
+# - #setuid?
+# - #size
+# - #size?
+# - #socket?
+# - #sticky?
+# - #symlink?
+# - #writable?
+# - #world_writable?
+# - #writable_real?
+# - #zero?
+#
+# === File property and manipulation methods
+#
+# These methods are a facade for File:
+# - #atime
+# - #ctime
+# - #mtime
+# - #chmod(mode)
+# - #lchmod(mode)
+# - #chown(owner, group)
+# - #lchown(owner, group)
+# - #fnmatch(pattern, *args)
+# - #fnmatch?(pattern, *args)
+# - #ftype
+# - #make_link(old)
+# - #open(*args, &block)
+# - #readlink
+# - #rename(to)
+# - #stat
+# - #lstat
+# - #make_symlink(old)
+# - #truncate(length)
+# - #utime(atime, mtime)
+# - #basename(*args)
+# - #dirname
+# - #extname
+# - #expand_path(*args)
+# - #split
+#
+# === Directory methods
+#
+# These methods are a facade for Dir:
+# - Pathname.glob(*args)
+# - Pathname.getwd / Pathname.pwd
+# - #rmdir
+# - #entries
+# - #each_entry(&block)
+# - #mkdir(*args)
+# - #opendir(*args)
+#
+# === IO
+#
+# These methods are a facade for IO:
+# - #each_line(*args, &block)
+# - #read(*args)
+# - #readlines(*args)
+# - #sysopen(*args)
+#
+# === Utilities
+#
+# These methods are a mixture of Find, FileUtils, and others:
+# - #find(&block)
+# - #mkpath
+# - #rmtree
+# - #unlink / #delete
+#
+#
+# == Method documentation
+#
+# As the above section shows, most of the methods in Pathname are facades.  The
+# documentation for these methods generally just says, for instance, "See
+# FileTest.writable?", as you should be familiar with the original method
+# anyway, and its documentation (e.g. through +ri+) will contain more
+# information.  In some cases, a brief description will follow.
+#
+class Pathname
+
+  # :stopdoc:
+  if RUBY_VERSION < "1.9"
+    TO_PATH = :to_str
+  else
+    # to_path is implemented so Pathname objects are usable with File.open, etc.
+    TO_PATH = :to_path
+  end
+  # :startdoc:
+
+  #
+  # Create a Pathname object from the given String (or String-like object).
+  # If +path+ contains a NUL character (<tt>\0</tt>), an ArgumentError is raised.
+  #
+  def initialize(path)
+    path = path.__send__(TO_PATH) if path.respond_to? TO_PATH
+    @path = path.dup
+
+    if /\0/ =~ @path
+      raise ArgumentError, "pathname contains \\0: #{@path.inspect}"
+    end
+
+    self.taint if @path.tainted?
+  end
+
+  def freeze() super; @path.freeze; self end
+  def taint() super; @path.taint; self end
+  def untaint() super; @path.untaint; self end
+
+  #
+  # Compare this pathname with +other+.  The comparison is string-based.
+  # Be aware that two different paths (<tt>foo.txt</tt> and <tt>./foo.txt</tt>)
+  # can refer to the same file.
+  #
+  def ==(other)
+    return false unless Pathname === other
+    other.to_s == @path
+  end
+  alias === ==
+  alias eql? ==
+
+  # Provides for comparing pathnames, case-sensitively.
+  def <=>(other)
+    return nil unless Pathname === other
+    @path.tr('/', "\0") <=> other.to_s.tr('/', "\0")
+  end
+
+  def hash # :nodoc:
+    @path.hash
+  end
+
+  # Return the path as a String.
+  def to_s
+    @path.dup
+  end
+
+  # to_path is implemented so Pathname objects are usable with File.open, etc.
+  alias_method TO_PATH, :to_s
+
+  def inspect # :nodoc:
+    "#<#{self.class}:#{@path}>"
+  end
+
+  # Return a pathname which is substituted by String#sub.
+  def sub(pattern, *rest, &block)
+    self.class.new(@path.sub(pattern, *rest, &block))
+  end
+
+  if File::ALT_SEPARATOR
+    SEPARATOR_PAT = /[#{Regexp.quote File::ALT_SEPARATOR}#{Regexp.quote File::SEPARATOR}]/
+  else
+    SEPARATOR_PAT = /#{Regexp.quote File::SEPARATOR}/
+  end
+
+  # chop_basename(path) -> [pre-basename, basename] or nil
+  def chop_basename(path)
+    base = File.basename(path)
+    if /\A#{SEPARATOR_PAT}?\z/ =~ base
+      return nil
+    else
+      return path[0, path.rindex(base)], base
+    end
+  end
+  private :chop_basename
+
+  # split_names(path) -> prefix, [name, ...]
+  def split_names(path)
+    names = []
+    while r = chop_basename(path)
+      path, basename = r
+      names.unshift basename
+    end
+    return path, names
+  end
+  private :split_names
+
+  def prepend_prefix(prefix, relpath)
+    if relpath.empty?
+      File.dirname(prefix)
+    elsif /#{SEPARATOR_PAT}/ =~ prefix
+      prefix = File.dirname(prefix)
+      prefix = File.join(prefix, "") if File.basename(prefix + 'a') != 'a'
+      prefix + relpath
+    else
+      prefix + relpath
+    end
+  end
+  private :prepend_prefix
+
+  # Returns clean pathname of +self+ with consecutive slashes and useless dots
+  # removed.  The filesystem is not accessed.
+  #
+  # If +consider_symlink+ is +true+, then a more conservative algorithm is used
+  # to avoid breaking symbolic linkages.  This may retain more <tt>..</tt>
+  # entries than absolutely necessary, but without accessing the filesystem,
+  # this can't be avoided.  See #realpath.
+  #
+  def cleanpath(consider_symlink=false)
+    if consider_symlink
+      cleanpath_conservative
+    else
+      cleanpath_aggressive
+    end
+  end
+
+  #
+  # Clean the path simply by resolving and removing excess "." and ".." entries.
+  # Nothing more, nothing less.
+  #
+  def cleanpath_aggressive
+    path = @path
+    names = []
+    pre = path
+    while r = chop_basename(pre)
+      pre, base = r
+      case base
+      when '.'
+      when '..'
+        names.unshift base
+      else
+        if names[0] == '..'
+          names.shift
+        else
+          names.unshift base
+        end
+      end
+    end
+    if /#{SEPARATOR_PAT}/o =~ File.basename(pre)
+      names.shift while names[0] == '..'
+    end
+    self.class.new(prepend_prefix(pre, File.join(*names)))
+  end
+  private :cleanpath_aggressive
+
+  # has_trailing_separator?(path) -> bool
+  def has_trailing_separator?(path)
+    if r = chop_basename(path)
+      pre, basename = r
+      pre.length + basename.length < path.length
+    else
+      false
+    end
+  end
+  private :has_trailing_separator?
+
+  # add_trailing_separator(path) -> path
+  def add_trailing_separator(path)
+    if File.basename(path + 'a') == 'a'
+      path
+    else
+      File.join(path, "") # xxx: Is File.join is appropriate to add separator?
+    end
+  end
+  private :add_trailing_separator
+
+  def del_trailing_separator(path)
+    if r = chop_basename(path)
+      pre, basename = r
+      pre + basename
+    elsif /#{SEPARATOR_PAT}+\z/o =~ path
+      $` + File.dirname(path)[/#{SEPARATOR_PAT}*\z/o]
+    else
+      path
+    end
+  end
+  private :del_trailing_separator
+
+  def cleanpath_conservative
+    path = @path
+    names = []
+    pre = path
+    while r = chop_basename(pre)
+      pre, base = r
+      names.unshift base if base != '.'
+    end
+    if /#{SEPARATOR_PAT}/o =~ File.basename(pre)
+      names.shift while names[0] == '..'
+    end
+    if names.empty?
+      self.class.new(File.dirname(pre))
+    else
+      if names.last != '..' && File.basename(path) == '.'
+        names << '.'
+      end
+      result = prepend_prefix(pre, File.join(*names))
+      if /\A(?:\.|\.\.)\z/ !~ names.last && has_trailing_separator?(path)
+        self.class.new(add_trailing_separator(result))
+      else
+        self.class.new(result)
+      end
+    end
+  end
+  private :cleanpath_conservative
+
+  def realpath_rec(prefix, unresolved, h)
+    resolved = []
+    until unresolved.empty?
+      n = unresolved.shift
+      if n == '.'
+        next
+      elsif n == '..'
+        resolved.pop
+      else
+        path = prepend_prefix(prefix, File.join(*(resolved + [n])))
+        if h.include? path
+          if h[path] == :resolving
+            raise Errno::ELOOP.new(path)
+          else
+            prefix, *resolved = h[path]
+          end
+        else
+          s = File.lstat(path)
+          if s.symlink?
+            h[path] = :resolving
+            link_prefix, link_names = split_names(File.readlink(path))
+            if link_prefix == ''
+              prefix, *resolved = h[path] = realpath_rec(prefix, resolved + link_names, h)
+            else
+              prefix, *resolved = h[path] = realpath_rec(link_prefix, link_names, h)
+            end
+          else
+            resolved << n
+            h[path] = [prefix, *resolved]
+          end
+        end
+      end
+    end
+    return prefix, *resolved
+  end
+  private :realpath_rec
+
+  #
+  # Returns a real (absolute) pathname of +self+ in the actual filesystem.
+  # The real pathname doesn't contain symlinks or useless dots.
+  #
+  # No arguments should be given; the old behaviour is *obsoleted*. 
+  #
+  def realpath
+    path = @path
+    prefix, names = split_names(path)
+    if prefix == ''
+      prefix, names2 = split_names(Dir.pwd)
+      names = names2 + names
+    end
+    prefix, *names = realpath_rec(prefix, names, {})
+    self.class.new(prepend_prefix(prefix, File.join(*names)))
+  end
+
+  # #parent returns the parent directory.
+  #
+  # This is same as <tt>self + '..'</tt>.
+  def parent
+    self + '..'
+  end
+
+  # #mountpoint? returns +true+ if <tt>self</tt> points to a mountpoint.
+  def mountpoint?
+    begin
+      stat1 = self.lstat
+      stat2 = self.parent.lstat
+      stat1.dev == stat2.dev && stat1.ino == stat2.ino ||
+        stat1.dev != stat2.dev
+    rescue Errno::ENOENT
+      false
+    end
+  end
+
+  #
+  # #root? is a predicate for root directories.  I.e. it returns +true+ if the
+  # pathname consists of consecutive slashes.
+  #
+  # It doesn't access actual filesystem.  So it may return +false+ for some
+  # pathnames which points to roots such as <tt>/usr/..</tt>.
+  #
+  def root?
+    !!(chop_basename(@path) == nil && /#{SEPARATOR_PAT}/o =~ @path)
+  end
+
+  # Predicate method for testing whether a path is absolute.
+  # It returns +true+ if the pathname begins with a slash.
+  def absolute?
+    !relative?
+  end
+
+  # The opposite of #absolute?
+  def relative?
+    path = @path
+    while r = chop_basename(path)
+      path, basename = r
+    end
+    path == ''
+  end
+
+  #
+  # Iterates over each component of the path.
+  #
+  #   Pathname.new("/usr/bin/ruby").each_filename {|filename| ... }
+  #     # yields "usr", "bin", and "ruby".
+  #
+  def each_filename # :yield: filename
+    prefix, names = split_names(@path)
+    names.each {|filename| yield filename }
+    nil
+  end
+
+  # Iterates over and yields a new Pathname object
+  # for each element in the given path in descending order.
+  #
+  #  Pathname.new('/path/to/some/file.rb').descend {|v| p v}
+  #     #<Pathname:/>
+  #     #<Pathname:/path>
+  #     #<Pathname:/path/to>
+  #     #<Pathname:/path/to/some>
+  #     #<Pathname:/path/to/some/file.rb>
+  #
+  #  Pathname.new('path/to/some/file.rb').descend {|v| p v}
+  #     #<Pathname:path>
+  #     #<Pathname:path/to>
+  #     #<Pathname:path/to/some>
+  #     #<Pathname:path/to/some/file.rb>
+  #
+  # It doesn't access actual filesystem.
+  #
+  # This method is available since 1.8.5.
+  #
+  def descend
+    vs = []
+    ascend {|v| vs << v }
+    vs.reverse_each {|v| yield v }
+    nil
+  end
+
+  # Iterates over and yields a new Pathname object
+  # for each element in the given path in ascending order.
+  #
+  #  Pathname.new('/path/to/some/file.rb').ascend {|v| p v}
+  #     #<Pathname:/path/to/some/file.rb>
+  #     #<Pathname:/path/to/some>
+  #     #<Pathname:/path/to>
+  #     #<Pathname:/path>
+  #     #<Pathname:/>
+  #
+  #  Pathname.new('path/to/some/file.rb').ascend {|v| p v}
+  #     #<Pathname:path/to/some/file.rb>
+  #     #<Pathname:path/to/some>
+  #     #<Pathname:path/to>
+  #     #<Pathname:path>
+  #
+  # It doesn't access actual filesystem.
+  #
+  # This method is available since 1.8.5.
+  #
+  def ascend
+    path = @path
+    yield self
+    while r = chop_basename(path)
+      path, name = r
+      break if path.empty?
+      yield self.class.new(del_trailing_separator(path))
+    end
+  end
+
+  #
+  # Pathname#+ appends a pathname fragment to this one to produce a new Pathname
+  # object.
+  #
+  #   p1 = Pathname.new("/usr")      # Pathname:/usr
+  #   p2 = p1 + "bin/ruby"           # Pathname:/usr/bin/ruby
+  #   p3 = p1 + "/etc/passwd"        # Pathname:/etc/passwd
+  #
+  # This method doesn't access the file system; it is pure string manipulation. 
+  #
+  def +(other)
+    other = Pathname.new(other) unless Pathname === other
+    Pathname.new(plus(@path, other.to_s))
+  end
+
+  def plus(path1, path2) # -> path
+    prefix2 = path2
+    index_list2 = []
+    basename_list2 = []
+    while r2 = chop_basename(prefix2)
+      prefix2, basename2 = r2
+      index_list2.unshift prefix2.length
+      basename_list2.unshift basename2
+    end
+    return path2 if prefix2 != ''
+    prefix1 = path1
+    while true
+      while !basename_list2.empty? && basename_list2.first == '.'
+        index_list2.shift
+        basename_list2.shift
+      end
+      break unless r1 = chop_basename(prefix1)
+      prefix1, basename1 = r1
+      next if basename1 == '.'
+      if basename1 == '..' || basename_list2.empty? || basename_list2.first != '..'
+        prefix1 = prefix1 + basename1
+        break
+      end
+      index_list2.shift
+      basename_list2.shift
+    end
+    r1 = chop_basename(prefix1)
+    if !r1 && /#{SEPARATOR_PAT}/o =~ File.basename(prefix1)
+      while !basename_list2.empty? && basename_list2.first == '..'
+        index_list2.shift
+        basename_list2.shift
+      end
+    end
+    if !basename_list2.empty?
+      suffix2 = path2[index_list2.first..-1]
+      r1 ? File.join(prefix1, suffix2) : prefix1 + suffix2
+    else
+      r1 ? prefix1 : File.dirname(prefix1)
+    end
+  end
+  private :plus
+
+  #
+  # Pathname#join joins pathnames.
+  #
+  # <tt>path0.join(path1, ..., pathN)</tt> is the same as
+  # <tt>path0 + path1 + ... + pathN</tt>.
+  #
+  def join(*args)
+    args.unshift self
+    result = args.pop
+    result = Pathname.new(result) unless Pathname === result
+    return result if result.absolute?
+    args.reverse_each {|arg|
+      arg = Pathname.new(arg) unless Pathname === arg
+      result = arg + result
+      return result if result.absolute?
+    }
+    result
+  end
+
+  #
+  # Returns the children of the directory (files and subdirectories, not
+  # recursive) as an array of Pathname objects.  By default, the returned
+  # pathnames will have enough information to access the files.  If you set
+  # +with_directory+ to +false+, then the returned pathnames will contain the
+  # filename only.
+  #
+  # For example:
+  #   p = Pathname("/usr/lib/ruby/1.8")
+  #   p.children
+  #       # -> [ Pathname:/usr/lib/ruby/1.8/English.rb,
+  #              Pathname:/usr/lib/ruby/1.8/Env.rb,
+  #              Pathname:/usr/lib/ruby/1.8/abbrev.rb, ... ]
+  #   p.children(false)
+  #       # -> [ Pathname:English.rb, Pathname:Env.rb, Pathname:abbrev.rb, ... ]
+  #
+  # Note that the result never contain the entries <tt>.</tt> and <tt>..</tt> in
+  # the directory because they are not children.
+  #
+  # This method has existed since 1.8.1.
+  #
+  def children(with_directory=true)
+    with_directory = false if @path == '.'
+    result = []
+    Dir.foreach(@path) {|e|
+      next if e == '.' || e == '..'
+      if with_directory
+        result << self.class.new(File.join(@path, e))
+      else
+        result << self.class.new(e)
+      end
+    }
+    result
+  end
+
+  #
+  # #relative_path_from returns a relative path from the argument to the
+  # receiver.  If +self+ is absolute, the argument must be absolute too.  If
+  # +self+ is relative, the argument must be relative too.
+  #
+  # #relative_path_from doesn't access the filesystem.  It assumes no symlinks.
+  #
+  # ArgumentError is raised when it cannot find a relative path.
+  #
+  # This method has existed since 1.8.1.
+  #
+  def relative_path_from(base_directory)
+    dest_directory = self.cleanpath.to_s
+    base_directory = base_directory.cleanpath.to_s
+    dest_prefix = dest_directory
+    dest_names = []
+    while r = chop_basename(dest_prefix)
+      dest_prefix, basename = r
+      dest_names.unshift basename if basename != '.'
+    end
+    base_prefix = base_directory
+    base_names = []
+    while r = chop_basename(base_prefix)
+      base_prefix, basename = r
+      base_names.unshift basename if basename != '.'
+    end
+    if dest_prefix != base_prefix
+      raise ArgumentError, "different prefix: #{dest_prefix.inspect} and #{base_directory.inspect}"
+    end
+    while !dest_names.empty? &&
+          !base_names.empty? &&
+          dest_names.first == base_names.first
+      dest_names.shift
+      base_names.shift
+    end
+    if base_names.include? '..'
+      raise ArgumentError, "base_directory has ..: #{base_directory.inspect}"
+    end
+    base_names.fill('..')
+    relpath_names = base_names + dest_names
+    if relpath_names.empty?
+      Pathname.new('.')
+    else
+      Pathname.new(File.join(*relpath_names))
+    end
+  end
+end
+
+class Pathname    # * IO *
+  #
+  # #each_line iterates over the line in the file.  It yields a String object
+  # for each line.
+  #
+  # This method has existed since 1.8.1.
+  #
+  def each_line(*args, &block) # :yield: line
+    IO.foreach(@path, *args, &block)
+  end
+
+  # Pathname#foreachline is *obsoleted* at 1.8.1.  Use #each_line.
+  def foreachline(*args, &block)
+    warn "Pathname#foreachline is obsoleted.  Use Pathname#each_line."
+    each_line(*args, &block)
+  end
+
+  # See <tt>IO.read</tt>.  Returns all the bytes from the file, or the first +N+
+  # if specified.
+  def read(*args) IO.read(@path, *args) end
+
+  # See <tt>IO.readlines</tt>.  Returns all the lines from the file.
+  def readlines(*args) IO.readlines(@path, *args) end
+
+  # See <tt>IO.sysopen</tt>.
+  def sysopen(*args) IO.sysopen(@path, *args) end
+end
+
+
+class Pathname    # * File *
+
+  # See <tt>File.atime</tt>.  Returns last access time.
+  def atime() File.atime(@path) end
+
+  # See <tt>File.ctime</tt>.  Returns last (directory entry, not file) change time.
+  def ctime() File.ctime(@path) end
+
+  # See <tt>File.mtime</tt>.  Returns last modification time.
+  def mtime() File.mtime(@path) end
+
+  # See <tt>File.chmod</tt>.  Changes permissions.
+  def chmod(mode) File.chmod(mode, @path) end
+
+  # See <tt>File.lchmod</tt>.
+  def lchmod(mode) File.lchmod(mode, @path) end
+
+  # See <tt>File.chown</tt>.  Change owner and group of file.
+  def chown(owner, group) File.chown(owner, group, @path) end
+
+  # See <tt>File.lchown</tt>.
+  def lchown(owner, group) File.lchown(owner, group, @path) end
+
+  # See <tt>File.fnmatch</tt>.  Return +true+ if the receiver matches the given
+  # pattern.
+  def fnmatch(pattern, *args) File.fnmatch(pattern, @path, *args) end
+
+  # See <tt>File.fnmatch?</tt> (same as #fnmatch).
+  def fnmatch?(pattern, *args) File.fnmatch?(pattern, @path, *args) end
+
+  # See <tt>File.ftype</tt>.  Returns "type" of file ("file", "directory",
+  # etc).
+  def ftype() File.ftype(@path) end
+
+  # See <tt>File.link</tt>.  Creates a hard link.
+  def make_link(old) File.link(old, @path) end
+
+  # See <tt>File.open</tt>.  Opens the file for reading or writing.
+  def open(*args, &block) # :yield: file
+    File.open(@path, *args, &block)
+  end
+
+  # See <tt>File.readlink</tt>.  Read symbolic link.
+  def readlink() self.class.new(File.readlink(@path)) end
+
+  # See <tt>File.rename</tt>.  Rename the file.
+  def rename(to) File.rename(@path, to) end
+
+  # See <tt>File.stat</tt>.  Returns a <tt>File::Stat</tt> object.
+  def stat() File.stat(@path) end
+
+  # See <tt>File.lstat</tt>.
+  def lstat() File.lstat(@path) end
+
+  # See <tt>File.symlink</tt>.  Creates a symbolic link.
+  def make_symlink(old) File.symlink(old, @path) end
+
+  # See <tt>File.truncate</tt>.  Truncate the file to +length+ bytes.
+  def truncate(length) File.truncate(@path, length) end
+
+  # See <tt>File.utime</tt>.  Update the access and modification times.
+  def utime(atime, mtime) File.utime(atime, mtime, @path) end
+
+  # See <tt>File.basename</tt>.  Returns the last component of the path.
+  def basename(*args) self.class.new(File.basename(@path, *args)) end
+
+  # See <tt>File.dirname</tt>.  Returns all but the last component of the path.
+  def dirname() self.class.new(File.dirname(@path)) end
+
+  # See <tt>File.extname</tt>.  Returns the file's extension.
+  def extname() File.extname(@path) end
+
+  # See <tt>File.expand_path</tt>.
+  def expand_path(*args) self.class.new(File.expand_path(@path, *args)) end
+
+  # See <tt>File.split</tt>.  Returns the #dirname and the #basename in an
+  # Array.
+  def split() File.split(@path).map {|f| self.class.new(f) } end
+
+  # Pathname#link is confusing and *obsoleted* because the receiver/argument
+  # order is inverted to corresponding system call.
+  def link(old)
+    warn 'Pathname#link is obsoleted.  Use Pathname#make_link.'
+    File.link(old, @path)
+  end
+
+  # Pathname#symlink is confusing and *obsoleted* because the receiver/argument
+  # order is inverted to corresponding system call.
+  def symlink(old)
+    warn 'Pathname#symlink is obsoleted.  Use Pathname#make_symlink.'
+    File.symlink(old, @path)
+  end
+end
+
+
+class Pathname    # * FileTest *
+
+  # See <tt>FileTest.blockdev?</tt>.
+  def blockdev?() FileTest.blockdev?(@path) end
+
+  # See <tt>FileTest.chardev?</tt>.
+  def chardev?() FileTest.chardev?(@path) end
+
+  # See <tt>FileTest.executable?</tt>.
+  def executable?() FileTest.executable?(@path) end
+
+  # See <tt>FileTest.executable_real?</tt>.
+  def executable_real?() FileTest.executable_real?(@path) end
+
+  # See <tt>FileTest.exist?</tt>.
+  def exist?() FileTest.exist?(@path) end
+
+  # See <tt>FileTest.grpowned?</tt>.
+  def grpowned?() FileTest.grpowned?(@path) end
+
+  # See <tt>FileTest.directory?</tt>.
+  def directory?() FileTest.directory?(@path) end
+
+  # See <tt>FileTest.file?</tt>.
+  def file?() FileTest.file?(@path) end
+
+  # See <tt>FileTest.pipe?</tt>.
+  def pipe?() FileTest.pipe?(@path) end
+
+  # See <tt>FileTest.socket?</tt>.
+  def socket?() FileTest.socket?(@path) end
+
+  # See <tt>FileTest.owned?</tt>.
+  def owned?() FileTest.owned?(@path) end
+
+  # See <tt>FileTest.readable?</tt>.
+  def readable?() FileTest.readable?(@path) end
+
+  # See <tt>FileTest.world_readable?</tt>.
+  def world_readable?() FileTest.world_readable?(@path) end
+
+  # See <tt>FileTest.readable_real?</tt>.
+  def readable_real?() FileTest.readable_real?(@path) end
+
+  # See <tt>FileTest.setuid?</tt>.
+  def setuid?() FileTest.setuid?(@path) end
+
+  # See <tt>FileTest.setgid?</tt>.
+  def setgid?() FileTest.setgid?(@path) end
+
+  # See <tt>FileTest.size</tt>.
+  def size() FileTest.size(@path) end
+
+  # See <tt>FileTest.size?</tt>.
+  def size?() FileTest.size?(@path) end
+
+  # See <tt>FileTest.sticky?</tt>.
+  def sticky?() FileTest.sticky?(@path) end
+
+  # See <tt>FileTest.symlink?</tt>.
+  def symlink?() FileTest.symlink?(@path) end
+
+  # See <tt>FileTest.writable?</tt>.
+  def writable?() FileTest.writable?(@path) end
+
+  # See <tt>FileTest.world_writable?</tt>.
+  def world_writable?() FileTest.world_writable?(@path) end
+
+  # See <tt>FileTest.writable_real?</tt>.
+  def writable_real?() FileTest.writable_real?(@path) end
+
+  # See <tt>FileTest.zero?</tt>.
+  def zero?() FileTest.zero?(@path) end
+end
+
+
+class Pathname    # * Dir *
+  # See <tt>Dir.glob</tt>.  Returns or yields Pathname objects.
+  def Pathname.glob(*args) # :yield: p
+    if block_given?
+      Dir.glob(*args) {|f| yield self.new(f) }
+    else
+      Dir.glob(*args).map {|f| self.new(f) }
+    end
+  end
+
+  # See <tt>Dir.getwd</tt>.  Returns the current working directory as a Pathname.
+  def Pathname.getwd() self.new(Dir.getwd) end
+  class << self; alias pwd getwd end
+
+  # Pathname#chdir is *obsoleted* at 1.8.1.
+  def chdir(&block)
+    warn "Pathname#chdir is obsoleted.  Use Dir.chdir."
+    Dir.chdir(@path, &block)
+  end
+
+  # Pathname#chroot is *obsoleted* at 1.8.1.
+  def chroot
+    warn "Pathname#chroot is obsoleted.  Use Dir.chroot."
+    Dir.chroot(@path)
+  end
+
+  # Return the entries (files and subdirectories) in the directory, each as a
+  # Pathname object.
+  def entries() Dir.entries(@path).map {|f| self.class.new(f) } end
+
+  # Iterates over the entries (files and subdirectories) in the directory.  It
+  # yields a Pathname object for each entry.
+  #
+  # This method has existed since 1.8.1.
+  def each_entry(&block) # :yield: p
+    Dir.foreach(@path) {|f| yield self.class.new(f) }
+  end
+
+  # Pathname#dir_foreach is *obsoleted* at 1.8.1.
+  def dir_foreach(*args, &block)
+    warn "Pathname#dir_foreach is obsoleted.  Use Pathname#each_entry."
+    each_entry(*args, &block)
+  end
+
+  # See <tt>Dir.mkdir</tt>.  Create the referenced directory.
+  def mkdir(*args) Dir.mkdir(@path, *args) end
+
+  # See <tt>Dir.rmdir</tt>.  Remove the referenced directory.
+  def rmdir() Dir.rmdir(@path) end
+
+  # See <tt>Dir.open</tt>.
+  def opendir(&block) # :yield: dir
+    Dir.open(@path, &block)
+  end
+end
+
+
+class Pathname    # * Find *
+  #
+  # Pathname#find is an iterator to traverse a directory tree in a depth first
+  # manner.  It yields a Pathname for each file under "this" directory.
+  #
+  # Since it is implemented by <tt>find.rb</tt>, <tt>Find.prune</tt> can be used
+  # to control the traverse.
+  #
+  # If +self+ is <tt>.</tt>, yielded pathnames begin with a filename in the
+  # current directory, not <tt>./</tt>.
+  #
+  def find(&block) # :yield: p
+    require 'find'
+    if @path == '.'
+      Find.find(@path) {|f| yield self.class.new(f.sub(%r{\A\./}, '')) }
+    else
+      Find.find(@path) {|f| yield self.class.new(f) }
+    end
+  end
+end
+
+
+class Pathname    # * FileUtils *
+  # See <tt>FileUtils.mkpath</tt>.  Creates a full path, including any
+  # intermediate directories that don't yet exist.
+  def mkpath
+    require 'fileutils'
+    FileUtils.mkpath(@path)
+    nil
+  end
+
+  # See <tt>FileUtils.rm_r</tt>.  Deletes a directory and all beneath it.
+  def rmtree
+    # The name "rmtree" is borrowed from File::Path of Perl.
+    # File::Path provides "mkpath" and "rmtree".
+    require 'fileutils'
+    FileUtils.rm_r(@path)
+    nil
+  end
+end
+
+
+class Pathname    # * mixed *
+  # Removes a file or directory, using <tt>File.unlink</tt> or
+  # <tt>Dir.unlink</tt> as necessary.
+  def unlink()
+    begin
+      Dir.unlink @path
+    rescue Errno::ENOTDIR
+      File.unlink @path
+    end
+  end
+  alias delete unlink
+
+  # This method is *obsoleted* at 1.8.1.  Use #each_line or #each_entry.
+  def foreach(*args, &block)
+    warn "Pathname#foreach is obsoleted.  Use each_line or each_entry."
+    if FileTest.directory? @path
+      # For polymorphism between Dir.foreach and IO.foreach,
+      # Pathname#foreach doesn't yield Pathname object.
+      Dir.foreach(@path, *args, &block)
+    else
+      IO.foreach(@path, *args, &block)
+    end
+  end
+end
+
+module Kernel
+  # create a pathname object.
+  #
+  # This method is available since 1.8.5.
+  def Pathname(path) # :doc:
+    Pathname.new(path)
+  end
+  private :Pathname
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/ping.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/ping.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/ping.rb	(revision 18425)
@@ -0,0 +1,64 @@
+#
+# = ping.rb: Check a host for upness
+#
+# Author:: Yukihiro Matsumoto
+# Documentation:: Konrad Meyer
+# 
+# Performs the function of the basic network testing tool, ping.
+# See: Ping.
+#
+
+require 'timeout'
+require "socket"
+
+# 
+# Ping contains routines to test for the reachability of remote hosts.
+# Currently the only routine implemented is pingecho().
+#
+# Ping.pingecho uses a TCP echo (not an ICMP echo) to determine if the
+# remote host is reachable. This is usually adequate to tell that a remote
+# host is available to telnet, ftp, or ssh to.
+#
+# Warning: Ping.pingecho may block for a long time if DNS resolution is
+# slow. Requiring 'resolv-replace' allows non-blocking name resolution.
+#
+# Usage:
+# 
+#   require 'ping'
+#
+#   puts "'jimmy' is alive and kicking" if Ping.pingecho('jimmy', 10)
+#
+module Ping
+
+  # 
+  # Return true if we can open a connection to the hostname or IP address
+  # +host+ on port +service+ (which defaults to the "echo" port) waiting up
+  # to +timeout+ seconds.
+  #
+  # Example:
+  #
+  #   require 'ping'
+  #
+  #   Ping.pingecho "google.com", 10, 80
+  #
+  def pingecho(host, timeout=5, service="echo")
+    begin
+      timeout(timeout) do
+	s = TCPSocket.new(host, service)
+	s.close
+      end
+    rescue Errno::ECONNREFUSED
+      return true
+    rescue Timeout::Error, StandardError
+      return false
+    end
+    return true
+  end
+  module_function :pingecho
+end
+
+if $0 == __FILE__
+  host = ARGV[0]
+  host ||= "localhost"
+  printf("%s alive? - %s\n", host,  Ping::pingecho(host, 5))
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/pp.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/pp.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/pp.rb	(revision 18425)
@@ -0,0 +1,647 @@
+# == Pretty-printer for Ruby objects.
+# 
+# = Which seems better?
+# 
+# non-pretty-printed output by #p is:
+#   #<PP:0x81fedf0 @genspace=#<Proc:0x81feda0>, @group_queue=#<PrettyPrint::GroupQueue:0x81fed3c @queue=[[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], []]>, @buffer=[], @newline="\n", @group_stack=[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], @buffer_width=0, @indent=0, @maxwidth=79, @output_width=2, @output=#<IO:0x8114ee4>>
+# 
+# pretty-printed output by #pp is:
+#   #<PP:0x81fedf0
+#    @buffer=[],
+#    @buffer_width=0,
+#    @genspace=#<Proc:0x81feda0>,
+#    @group_queue=
+#     #<PrettyPrint::GroupQueue:0x81fed3c
+#      @queue=
+#       [[#<PrettyPrint::Group:0x81fed78 @break=false, @breakables=[], @depth=0>],
+#        []]>,
+#    @group_stack=
+#     [#<PrettyPrint::Group:0x81fed78 @break=false, @breakables=[], @depth=0>],
+#    @indent=0,
+#    @maxwidth=79,
+#    @newline="\n",
+#    @output=#<IO:0x8114ee4>,
+#    @output_width=2>
+# 
+# I like the latter.  If you do too, this library is for you.
+# 
+# = Usage
+# 
+#   pp(obj)
+#
+# output +obj+ to +$>+ in pretty printed format.
+# 
+# It returns +nil+.
+# 
+# = Output Customization
+# To define your customized pretty printing function for your classes,
+# redefine a method #pretty_print(+pp+) in the class.
+# It takes an argument +pp+ which is an instance of the class PP.
+# The method should use PP#text, PP#breakable, PP#nest, PP#group and
+# PP#pp to print the object.
+#
+# = Author
+# Tanaka Akira <akr@m17n.org>
+
+require 'prettyprint'
+
+module Kernel
+  # returns a pretty printed object as a string.
+  def pretty_inspect
+    PP.pp(self, '')
+  end
+
+  private
+  # prints arguments in pretty form.
+  #
+  # pp returns nil.
+  def pp(*objs) # :doc:
+    objs.each {|obj|
+      PP.pp(obj)
+    }
+    nil
+  end
+  module_function :pp
+end
+
+class PP < PrettyPrint
+  # Outputs +obj+ to +out+ in pretty printed format of
+  # +width+ columns in width.
+  # 
+  # If +out+ is omitted, +$>+ is assumed.
+  # If +width+ is omitted, 79 is assumed.
+  # 
+  # PP.pp returns +out+.
+  def PP.pp(obj, out=$>, width=79)
+    q = PP.new(out, width)
+    q.guard_inspect_key {q.pp obj}
+    q.flush
+    #$pp = q
+    out << "\n"
+  end
+
+  # Outputs +obj+ to +out+ like PP.pp but with no indent and
+  # newline.
+  # 
+  # PP.singleline_pp returns +out+.
+  def PP.singleline_pp(obj, out=$>)
+    q = SingleLine.new(out)
+    q.guard_inspect_key {q.pp obj}
+    q.flush
+    out
+  end
+
+  # :stopdoc:
+  def PP.mcall(obj, mod, meth, *args, &block)
+    mod.instance_method(meth).bind(obj).call(*args, &block)
+  end
+  # :startdoc:
+
+  @sharing_detection = false
+  class << self
+    # Returns the sharing detection flag as a boolean value.
+    # It is false by default.
+    attr_accessor :sharing_detection
+  end
+
+  module PPMethods
+    InspectKey = :__inspect_key__
+
+    def guard_inspect_key
+      if Thread.current[InspectKey] == nil
+        Thread.current[InspectKey] = []
+      end
+
+      save = Thread.current[InspectKey]
+
+      begin
+        Thread.current[InspectKey] = []
+        yield
+      ensure
+        Thread.current[InspectKey] = save
+      end
+    end
+
+    # Adds +obj+ to the pretty printing buffer
+    # using Object#pretty_print or Object#pretty_print_cycle.
+    # 
+    # Object#pretty_print_cycle is used when +obj+ is already
+    # printed, a.k.a the object reference chain has a cycle.
+    def pp(obj)
+      id = obj.__id__
+
+      if Thread.current[InspectKey].include? id
+        group {obj.pretty_print_cycle self}
+        return
+      end
+
+      begin
+        Thread.current[InspectKey] << id
+        group {obj.pretty_print self}
+      ensure
+        Thread.current[InspectKey].pop unless PP.sharing_detection
+      end
+    end
+
+    # A convenience method which is same as follows:
+    # 
+    #   group(1, '#<' + obj.class.name, '>') { ... }
+    def object_group(obj, &block) # :yield:
+      group(1, '#<' + obj.class.name, '>', &block)
+    end
+
+    def object_address_group(obj, &block)
+      id = "%x" % (obj.__id__ * 2)
+      id.sub!(/\Af(?=[[:xdigit:]]{2}+\z)/, '') if id.sub!(/\A\.\./, '')
+      group(1, "\#<#{obj.class}:0x#{id}", '>', &block)
+    end
+
+    # A convenience method which is same as follows:
+    # 
+    #   text ','
+    #   breakable
+    def comma_breakable
+      text ','
+      breakable
+    end
+
+    # Adds a separated list.
+    # The list is separated by comma with breakable space, by default.
+    # 
+    # #seplist iterates the +list+ using +iter_method+.
+    # It yields each object to the block given for #seplist.
+    # The procedure +separator_proc+ is called between each yields.
+    # 
+    # If the iteration is zero times, +separator_proc+ is not called at all.
+    # 
+    # If +separator_proc+ is nil or not given,
+    # +lambda { comma_breakable }+ is used.
+    # If +iter_method+ is not given, :each is used.
+    # 
+    # For example, following 3 code fragments has similar effect.
+    # 
+    #   q.seplist([1,2,3]) {|v| xxx v }
+    # 
+    #   q.seplist([1,2,3], lambda { comma_breakable }, :each) {|v| xxx v }
+    # 
+    #   xxx 1
+    #   q.comma_breakable
+    #   xxx 2
+    #   q.comma_breakable
+    #   xxx 3
+    def seplist(list, sep=nil, iter_method=:each) # :yield: element
+      sep ||= lambda { comma_breakable }
+      first = true
+      list.__send__(iter_method) {|*v|
+        if first
+          first = false
+        else
+          sep.call
+        end
+        yield(*v)
+      }
+    end
+
+    def pp_object(obj)
+      object_address_group(obj) {
+        seplist(obj.pretty_print_instance_variables, lambda { text ',' }) {|v|
+          breakable
+          v = v.to_s if Symbol === v
+          text v
+          text '='
+          group(1) {
+            breakable ''
+            pp(obj.instance_eval(v))
+          }
+        }
+      }
+    end
+
+    def pp_hash(obj)
+      group(1, '{', '}') {
+        seplist(obj, nil, :each_pair) {|k, v|
+          group {
+            pp k
+            text '=>'
+            group(1) {
+              breakable ''
+              pp v
+            }
+          }
+        }
+      }
+    end
+  end
+
+  include PPMethods
+
+  class SingleLine < PrettyPrint::SingleLine
+    include PPMethods
+  end
+
+  module ObjectMixin
+    # 1. specific pretty_print
+    # 2. specific inspect
+    # 3. specific to_s if instance variable is empty
+    # 4. generic pretty_print
+
+    # A default pretty printing method for general objects.
+    # It calls #pretty_print_instance_variables to list instance variables.
+    # 
+    # If +self+ has a customized (redefined) #inspect method,
+    # the result of self.inspect is used but it obviously has no
+    # line break hints.
+    # 
+    # This module provides predefined #pretty_print methods for some of
+    # the most commonly used built-in classes for convenience.
+    def pretty_print(q)
+      if /\(Kernel\)#/ !~ method(:inspect).inspect
+        q.text self.inspect
+      elsif /\(Kernel\)#/ !~ method(:to_s).inspect && instance_variables.empty?
+        q.text self.to_s
+      else
+        q.pp_object(self)
+      end
+    end
+
+    # A default pretty printing method for general objects that are
+    # detected as part of a cycle.
+    def pretty_print_cycle(q)
+      q.object_address_group(self) {
+        q.breakable
+        q.text '...'
+      }
+    end
+
+    # Returns a sorted array of instance variable names.
+    # 
+    # This method should return an array of names of instance variables as symbols or strings as:
+    # +[:@a, :@b]+.
+    def pretty_print_instance_variables
+      instance_variables.sort
+    end
+
+    # Is #inspect implementation using #pretty_print.
+    # If you implement #pretty_print, it can be used as follows.
+    # 
+    #   alias inspect pretty_print_inspect
+    #
+    # However, doing this requires that every class that #inspect is called on
+    # implement #pretty_print, or a RuntimeError will be raised.
+    def pretty_print_inspect
+      if /\(PP::ObjectMixin\)#/ =~ method(:pretty_print).inspect
+        raise "pretty_print is not overridden for #{self.class}"
+      end
+      PP.singleline_pp(self, '')
+    end
+  end
+end
+
+class Array
+  def pretty_print(q)
+    q.group(1, '[', ']') {
+      q.seplist(self) {|v|
+        q.pp v
+      }
+    }
+  end
+
+  def pretty_print_cycle(q)
+    q.text(empty? ? '[]' : '[...]')
+  end
+end
+
+class Hash
+  def pretty_print(q)
+    q.pp_hash self
+  end
+
+  def pretty_print_cycle(q)
+    q.text(empty? ? '{}' : '{...}')
+  end
+end
+
+class << ENV
+  def pretty_print(q)
+    q.pp_hash self
+  end
+end
+
+class Struct
+  def pretty_print(q)
+    q.group(1, '#<struct ' + PP.mcall(self, Kernel, :class).name, '>') {
+      q.seplist(PP.mcall(self, Struct, :members), lambda { q.text "," }) {|member|
+        q.breakable
+        q.text member.to_s
+        q.text '='
+        q.group(1) {
+          q.breakable ''
+          q.pp self[member]
+        }
+      }
+    }
+  end
+
+  def pretty_print_cycle(q)
+    q.text sprintf("#<struct %s:...>", PP.mcall(self, Kernel, :class).name)
+  end
+end
+
+class Range
+  def pretty_print(q)
+    q.pp self.begin
+    q.breakable ''
+    q.text(self.exclude_end? ? '...' : '..')
+    q.breakable ''
+    q.pp self.end
+  end
+end
+
+class File
+  class Stat
+    def pretty_print(q)
+      require 'etc.so'
+      q.object_group(self) {
+        q.breakable
+        q.text sprintf("dev=0x%x", self.dev); q.comma_breakable
+        q.text "ino="; q.pp self.ino; q.comma_breakable
+        q.group {
+          m = self.mode
+          q.text sprintf("mode=0%o", m)
+          q.breakable
+          q.text sprintf("(%s %c%c%c%c%c%c%c%c%c)",
+            self.ftype,
+            (m & 0400 == 0 ? ?- : ?r),
+            (m & 0200 == 0 ? ?- : ?w),
+            (m & 0100 == 0 ? (m & 04000 == 0 ? ?- : ?S) :
+                             (m & 04000 == 0 ? ?x : ?s)),
+            (m & 0040 == 0 ? ?- : ?r),
+            (m & 0020 == 0 ? ?- : ?w),
+            (m & 0010 == 0 ? (m & 02000 == 0 ? ?- : ?S) :
+                             (m & 02000 == 0 ? ?x : ?s)),
+            (m & 0004 == 0 ? ?- : ?r),
+            (m & 0002 == 0 ? ?- : ?w),
+            (m & 0001 == 0 ? (m & 01000 == 0 ? ?- : ?T) :
+                             (m & 01000 == 0 ? ?x : ?t)))
+        }
+        q.comma_breakable
+        q.text "nlink="; q.pp self.nlink; q.comma_breakable
+        q.group {
+          q.text "uid="; q.pp self.uid
+          begin
+            pw = Etc.getpwuid(self.uid)
+          rescue ArgumentError
+          end
+          if pw
+            q.breakable; q.text "(#{pw.name})"
+          end
+        }
+        q.comma_breakable
+        q.group {
+          q.text "gid="; q.pp self.gid
+          begin
+            gr = Etc.getgrgid(self.gid)
+          rescue ArgumentError
+          end
+          if gr
+            q.breakable; q.text "(#{gr.name})"
+          end
+        }
+        q.comma_breakable
+        q.group {
+          q.text sprintf("rdev=0x%x", self.rdev)
+          q.breakable
+          q.text sprintf('(%d, %d)', self.rdev_major, self.rdev_minor)
+        }
+        q.comma_breakable
+        q.text "size="; q.pp self.size; q.comma_breakable
+        q.text "blksize="; q.pp self.blksize; q.comma_breakable
+        q.text "blocks="; q.pp self.blocks; q.comma_breakable
+        q.group {
+          t = self.atime
+          q.text "atime="; q.pp t
+          q.breakable; q.text "(#{t.tv_sec})"
+        }
+        q.comma_breakable
+        q.group {
+          t = self.mtime
+          q.text "mtime="; q.pp t
+          q.breakable; q.text "(#{t.tv_sec})"
+        }
+        q.comma_breakable
+        q.group {
+          t = self.ctime
+          q.text "ctime="; q.pp t
+          q.breakable; q.text "(#{t.tv_sec})"
+        }
+      }
+    end
+  end
+end
+
+class MatchData
+  def pretty_print(q)
+    q.object_group(self) {
+      q.breakable
+      q.seplist(1..self.size, lambda { q.breakable }) {|i|
+        q.pp self[i-1]
+      }
+    }
+  end
+end
+
+class Object
+  include PP::ObjectMixin
+end
+
+[Numeric, Symbol, FalseClass, TrueClass, NilClass, Module].each {|c|
+  c.class_eval {
+    def pretty_print_cycle(q)
+      q.text inspect
+    end
+  }
+}
+
+[Numeric, FalseClass, TrueClass, Module].each {|c|
+  c.class_eval {
+    def pretty_print(q)
+      q.text inspect
+    end
+  }
+}
+
+# :enddoc:
+if __FILE__ == $0
+  require 'test/unit'
+
+  class PPTest < Test::Unit::TestCase
+    def test_list0123_12
+      assert_equal("[0, 1, 2, 3]\n", PP.pp([0,1,2,3], '', 12))
+    end
+
+    def test_list0123_11
+      assert_equal("[0,\n 1,\n 2,\n 3]\n", PP.pp([0,1,2,3], '', 11))
+    end
+
+    OverriddenStruct = Struct.new("OverriddenStruct", :members, :class)
+    def test_struct_override_members # [ruby-core:7865]
+      a = OverriddenStruct.new(1,2)
+      assert_equal("#<struct Struct::OverriddenStruct members=1, class=2>\n", PP.pp(a, ''))
+    end
+  end
+
+  class HasInspect
+    def initialize(a)
+      @a = a
+    end
+
+    def inspect
+      return "<inspect:#{@a.inspect}>"
+    end
+  end
+
+  class HasPrettyPrint
+    def initialize(a)
+      @a = a
+    end
+
+    def pretty_print(q)
+      q.text "<pretty_print:"
+      q.pp @a
+      q.text ">"
+    end
+  end
+
+  class HasBoth
+    def initialize(a)
+      @a = a
+    end
+
+    def inspect
+      return "<inspect:#{@a.inspect}>"
+    end
+
+    def pretty_print(q)
+      q.text "<pretty_print:"
+      q.pp @a
+      q.text ">"
+    end
+  end
+
+  class PrettyPrintInspect < HasPrettyPrint
+    alias inspect pretty_print_inspect
+  end
+
+  class PrettyPrintInspectWithoutPrettyPrint
+    alias inspect pretty_print_inspect
+  end
+
+  class PPInspectTest < Test::Unit::TestCase
+    def test_hasinspect
+      a = HasInspect.new(1)
+      assert_equal("<inspect:1>\n", PP.pp(a, ''))
+    end
+
+    def test_hasprettyprint
+      a = HasPrettyPrint.new(1)
+      assert_equal("<pretty_print:1>\n", PP.pp(a, ''))
+    end
+
+    def test_hasboth
+      a = HasBoth.new(1)
+      assert_equal("<pretty_print:1>\n", PP.pp(a, ''))
+    end
+
+    def test_pretty_print_inspect
+      a = PrettyPrintInspect.new(1)
+      assert_equal("<pretty_print:1>", a.inspect)
+      a = PrettyPrintInspectWithoutPrettyPrint.new
+      assert_raise(RuntimeError) { a.inspect }
+    end
+
+    def test_proc
+      a = proc {1}
+      assert_equal("#{a.inspect}\n", PP.pp(a, ''))
+    end
+
+    def test_to_s_with_iv
+      a = Object.new
+      def a.to_s() "aaa" end
+      a.instance_eval { @a = nil }
+      result = PP.pp(a, '')
+      assert_equal("#{a.inspect}\n", result)
+      assert_match(/\A#<Object.*>\n\z/m, result)
+      a = 1.0
+      a.instance_eval { @a = nil }
+      result = PP.pp(a, '')
+      assert_equal("#{a.inspect}\n", result)
+    end
+    
+    def test_to_s_without_iv
+      a = Object.new
+      def a.to_s() "aaa" end
+      result = PP.pp(a, '')
+      assert_equal("#{a.inspect}\n", result)
+      assert_equal("aaa\n", result)
+    end
+  end
+
+  class PPCycleTest < Test::Unit::TestCase
+    def test_array
+      a = []
+      a << a
+      assert_equal("[[...]]\n", PP.pp(a, ''))
+      assert_equal("#{a.inspect}\n", PP.pp(a, ''))
+    end
+
+    def test_hash
+      a = {}
+      a[0] = a
+      assert_equal("{0=>{...}}\n", PP.pp(a, ''))
+      assert_equal("#{a.inspect}\n", PP.pp(a, ''))
+    end
+
+    S = Struct.new("S", :a, :b)
+    def test_struct
+      a = S.new(1,2)
+      a.b = a
+      assert_equal("#<struct Struct::S a=1, b=#<struct Struct::S:...>>\n", PP.pp(a, ''))
+      assert_equal("#{a.inspect}\n", PP.pp(a, ''))
+    end
+
+    def test_object
+      a = Object.new
+      a.instance_eval {@a = a}
+      assert_equal(a.inspect + "\n", PP.pp(a, ''))
+    end
+
+    def test_anonymous
+      a = Class.new.new
+      assert_equal(a.inspect + "\n", PP.pp(a, ''))
+    end
+
+    def test_withinspect
+      a = []
+      a << HasInspect.new(a)
+      assert_equal("[<inspect:[...]>]\n", PP.pp(a, ''))
+      assert_equal("#{a.inspect}\n", PP.pp(a, ''))
+    end
+
+    def test_share_nil
+      begin
+        PP.sharing_detection = true
+        a = [nil, nil]
+        assert_equal("[nil, nil]\n", PP.pp(a, ''))
+      ensure
+        PP.sharing_detection = false
+      end
+    end
+  end
+
+  class PPSingleLineTest < Test::Unit::TestCase
+    def test_hash
+      assert_equal("{1=>1}", PP.singleline_pp({ 1 => 1}, '')) # [ruby-core:02699]
+      assert_equal("[1#{', 1'*99}]", PP.singleline_pp([1]*100, ''))
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/prettyprint.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/prettyprint.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/prettyprint.rb	(revision 18425)
@@ -0,0 +1,896 @@
+# $Id$
+
+# This class implements a pretty printing algorithm. It finds line breaks and
+# nice indentations for grouped structure.
+# 
+# By default, the class assumes that primitive elements are strings and each
+# byte in the strings have single column in width. But it can be used for
+# other situations by giving suitable arguments for some methods:
+# * newline object and space generation block for PrettyPrint.new
+# * optional width argument for PrettyPrint#text
+# * PrettyPrint#breakable
+#
+# There are several candidate uses:
+# * text formatting using proportional fonts
+# * multibyte characters which has columns different to number of bytes
+# * non-string formatting
+#
+# == Bugs
+# * Box based formatting?
+# * Other (better) model/algorithm?
+# 
+# == References
+# Christian Lindig, Strictly Pretty, March 2000,
+# http://www.st.cs.uni-sb.de/~lindig/papers/#pretty
+# 
+# Philip Wadler, A prettier printer, March 1998,
+# http://homepages.inf.ed.ac.uk/wadler/topics/language-design.html#prettier
+# 
+# == Author
+# Tanaka Akira <akr@m17n.org>
+# 
+class PrettyPrint
+
+  # This is a convenience method which is same as follows:
+  # 
+  #   begin
+  #     q = PrettyPrint.new(output, maxwidth, newline, &genspace)
+  #     ...
+  #     q.flush
+  #     output
+  #   end
+  # 
+  def PrettyPrint.format(output='', maxwidth=79, newline="\n", genspace=lambda {|n| ' ' * n})
+    q = PrettyPrint.new(output, maxwidth, newline, &genspace)
+    yield q
+    q.flush
+    output
+  end
+
+  # This is similar to PrettyPrint::format but the result has no breaks.
+  #
+  # +maxwidth+, +newline+ and +genspace+ are ignored.
+  #
+  # The invocation of +breakable+ in the block doesn't break a line and is
+  # treated as just an invocation of +text+.
+  #
+  def PrettyPrint.singleline_format(output='', maxwidth=nil, newline=nil, genspace=nil)
+    q = SingleLine.new(output)
+    yield q
+    output
+  end
+
+  # Creates a buffer for pretty printing.
+  #
+  # +output+ is an output target. If it is not specified, '' is assumed. It
+  # should have a << method which accepts the first argument +obj+ of
+  # PrettyPrint#text, the first argument +sep+ of PrettyPrint#breakable, the
+  # first argument +newline+ of PrettyPrint.new, and the result of a given
+  # block for PrettyPrint.new.
+  #
+  # +maxwidth+ specifies maximum line length. If it is not specified, 79 is
+  # assumed. However actual outputs may overflow +maxwidth+ if long
+  # non-breakable texts are provided.
+  #
+  # +newline+ is used for line breaks. "\n" is used if it is not specified.
+  #
+  # The block is used to generate spaces. {|width| ' ' * width} is used if it
+  # is not given.
+  #
+  def initialize(output='', maxwidth=79, newline="\n", &genspace)
+    @output = output
+    @maxwidth = maxwidth
+    @newline = newline
+    @genspace = genspace || lambda {|n| ' ' * n}
+
+    @output_width = 0
+    @buffer_width = 0
+    @buffer = []
+
+    root_group = Group.new(0)
+    @group_stack = [root_group]
+    @group_queue = GroupQueue.new(root_group)
+    @indent = 0
+  end
+  attr_reader :output, :maxwidth, :newline, :genspace
+  attr_reader :indent, :group_queue
+
+  def current_group
+    @group_stack.last
+  end
+
+  # first? is a predicate to test the call is a first call to first? with
+  # current group.
+  #
+  # It is useful to format comma separated values as:
+  #
+  #   q.group(1, '[', ']') {
+  #     xxx.each {|yyy|
+  #       unless q.first?
+  #         q.text ','
+  #         q.breakable
+  #       end
+  #       ... pretty printing yyy ...
+  #     }
+  #   }
+  #
+  # first? is obsoleted in 1.8.2.
+  #
+  def first?
+    warn "PrettyPrint#first? is obsoleted at 1.8.2."
+    current_group.first?
+  end
+
+  def break_outmost_groups
+    while @maxwidth < @output_width + @buffer_width
+      return unless group = @group_queue.deq
+      until group.breakables.empty?
+        data = @buffer.shift
+        @output_width = data.output(@output, @output_width)
+        @buffer_width -= data.width
+      end
+      while !@buffer.empty? && Text === @buffer.first
+        text = @buffer.shift
+        @output_width = text.output(@output, @output_width)
+        @buffer_width -= text.width
+      end
+    end
+  end
+
+  # This adds +obj+ as a text of +width+ columns in width.
+  #
+  # If +width+ is not specified, obj.length is used.
+  #
+  def text(obj, width=obj.length)
+    if @buffer.empty?
+      @output << obj
+      @output_width += width
+    else
+      text = @buffer.last
+      unless Text === text
+        text = Text.new
+        @buffer << text
+      end
+      text.add(obj, width)
+      @buffer_width += width
+      break_outmost_groups
+    end
+  end
+
+  def fill_breakable(sep=' ', width=sep.length)
+    group { breakable sep, width }
+  end
+
+  # This tells "you can break a line here if necessary", and a +width+\-column
+  # text +sep+ is inserted if a line is not broken at the point.
+  #
+  # If +sep+ is not specified, " " is used.
+  #
+  # If +width+ is not specified, +sep.length+ is used. You will have to
+  # specify this when +sep+ is a multibyte character, for example.
+  #
+  def breakable(sep=' ', width=sep.length)
+    group = @group_stack.last
+    if group.break?
+      flush
+      @output << @newline
+      @output << @genspace.call(@indent)
+      @output_width = @indent
+      @buffer_width = 0
+    else
+      @buffer << Breakable.new(sep, width, self)
+      @buffer_width += width
+      break_outmost_groups
+    end
+  end
+
+  # Groups line break hints added in the block. The line break hints are all
+  # to be used or not.
+  #
+  # If +indent+ is specified, the method call is regarded as nested by
+  # nest(indent) { ... }.
+  #
+  # If +open_obj+ is specified, <tt>text open_obj, open_width</tt> is called
+  # before grouping. If +close_obj+ is specified, <tt>text close_obj,
+  # close_width</tt> is called after grouping.
+  #
+  def group(indent=0, open_obj='', close_obj='', open_width=open_obj.length, close_width=close_obj.length)
+    text open_obj, open_width
+    group_sub {
+      nest(indent) {
+        yield
+      }
+    }
+    text close_obj, close_width
+  end
+
+  def group_sub
+    group = Group.new(@group_stack.last.depth + 1)
+    @group_stack.push group
+    @group_queue.enq group
+    begin
+      yield
+    ensure
+      @group_stack.pop
+      if group.breakables.empty?
+        @group_queue.delete group
+      end
+    end
+  end
+
+  # Increases left margin after newline with +indent+ for line breaks added in
+  # the block.
+  #
+  def nest(indent)
+    @indent += indent
+    begin
+      yield
+    ensure
+      @indent -= indent
+    end
+  end
+
+  # outputs buffered data.
+  #
+  def flush
+    @buffer.each {|data|
+      @output_width = data.output(@output, @output_width)
+    }
+    @buffer.clear
+    @buffer_width = 0
+  end
+
+  class Text
+    def initialize
+      @objs = []
+      @width = 0
+    end
+    attr_reader :width
+
+    def output(out, output_width)
+      @objs.each {|obj| out << obj}
+      output_width + @width
+    end
+
+    def add(obj, width)
+      @objs << obj
+      @width += width
+    end
+  end
+
+  class Breakable
+    def initialize(sep, width, q)
+      @obj = sep
+      @width = width
+      @pp = q
+      @indent = q.indent
+      @group = q.current_group
+      @group.breakables.push self
+    end
+    attr_reader :obj, :width, :indent
+
+    def output(out, output_width)
+      @group.breakables.shift
+      if @group.break?
+        out << @pp.newline
+        out << @pp.genspace.call(@indent)
+        @indent
+      else
+        @pp.group_queue.delete @group if @group.breakables.empty?
+        out << @obj
+        output_width + @width
+      end
+    end
+  end
+
+  class Group
+    def initialize(depth)
+      @depth = depth
+      @breakables = []
+      @break = false
+    end
+    attr_reader :depth, :breakables
+
+    def break
+      @break = true
+    end
+
+    def break?
+      @break
+    end
+
+    def first?
+      if defined? @first
+        false
+      else
+        @first = false
+        true
+      end
+    end
+  end
+
+  class GroupQueue
+    def initialize(*groups)
+      @queue = []
+      groups.each {|g| enq g}
+    end
+
+    def enq(group)
+      depth = group.depth
+      @queue << [] until depth < @queue.length
+      @queue[depth] << group
+    end
+
+    def deq
+      @queue.each {|gs|
+        (gs.length-1).downto(0) {|i|
+          unless gs[i].breakables.empty?
+            group = gs.slice!(i, 1).first
+            group.break
+            return group
+          end
+        }
+        gs.each {|group| group.break}
+        gs.clear
+      }
+      return nil
+    end
+
+    def delete(group)
+      @queue[group.depth].delete(group)
+    end
+  end
+
+  class SingleLine
+    def initialize(output, maxwidth=nil, newline=nil)
+      @output = output
+      @first = [true]
+    end
+
+    def text(obj, width=nil)
+      @output << obj
+    end
+
+    def breakable(sep=' ', width=nil)
+      @output << sep
+    end
+
+    def nest(indent)
+      yield
+    end
+
+    def group(indent=nil, open_obj='', close_obj='', open_width=nil, close_width=nil)
+      @first.push true
+      @output << open_obj
+      yield
+      @output << close_obj
+      @first.pop
+    end
+
+    def flush
+    end
+
+    def first?
+      result = @first[-1]
+      @first[-1] = false
+      result
+    end
+  end
+end
+
+if __FILE__ == $0
+  require 'test/unit'
+
+  class WadlerExample < Test::Unit::TestCase # :nodoc:
+    def setup
+      @tree = Tree.new("aaaa", Tree.new("bbbbb", Tree.new("ccc"),
+                                                 Tree.new("dd")),
+                               Tree.new("eee"),
+                               Tree.new("ffff", Tree.new("gg"),
+                                                Tree.new("hhh"),
+                                                Tree.new("ii")))
+    end
+
+    def hello(width)
+      PrettyPrint.format('', width) {|hello|
+        hello.group {
+          hello.group {
+            hello.group {
+              hello.group {
+                hello.text 'hello'
+                hello.breakable; hello.text 'a'
+              }
+              hello.breakable; hello.text 'b'
+            }
+            hello.breakable; hello.text 'c'
+          }
+          hello.breakable; hello.text 'd'
+        }
+      }
+    end
+
+    def test_hello_00_06
+      expected = <<'End'.chomp
+hello
+a
+b
+c
+d
+End
+      assert_equal(expected, hello(0))
+      assert_equal(expected, hello(6))
+    end
+
+    def test_hello_07_08
+      expected = <<'End'.chomp
+hello a
+b
+c
+d
+End
+      assert_equal(expected, hello(7))
+      assert_equal(expected, hello(8))
+    end
+
+    def test_hello_09_10
+      expected = <<'End'.chomp
+hello a b
+c
+d
+End
+      out = hello(9); assert_equal(expected, out)
+      out = hello(10); assert_equal(expected, out)
+    end
+
+    def test_hello_11_12
+      expected = <<'End'.chomp
+hello a b c
+d
+End
+      assert_equal(expected, hello(11))
+      assert_equal(expected, hello(12))
+    end
+
+    def test_hello_13
+      expected = <<'End'.chomp
+hello a b c d
+End
+      assert_equal(expected, hello(13))
+    end
+
+    def tree(width)
+      PrettyPrint.format('', width) {|q| @tree.show(q)}
+    end
+
+    def test_tree_00_19
+      expected = <<'End'.chomp
+aaaa[bbbbb[ccc,
+           dd],
+     eee,
+     ffff[gg,
+          hhh,
+          ii]]
+End
+      assert_equal(expected, tree(0))
+      assert_equal(expected, tree(19))
+    end
+
+    def test_tree_20_22
+      expected = <<'End'.chomp
+aaaa[bbbbb[ccc, dd],
+     eee,
+     ffff[gg,
+          hhh,
+          ii]]
+End
+      assert_equal(expected, tree(20))
+      assert_equal(expected, tree(22))
+    end
+
+    def test_tree_23_43
+      expected = <<'End'.chomp
+aaaa[bbbbb[ccc, dd],
+     eee,
+     ffff[gg, hhh, ii]]
+End
+      assert_equal(expected, tree(23))
+      assert_equal(expected, tree(43))
+    end
+
+    def test_tree_44
+      assert_equal(<<'End'.chomp, tree(44))
+aaaa[bbbbb[ccc, dd], eee, ffff[gg, hhh, ii]]
+End
+    end
+
+    def tree_alt(width)
+      PrettyPrint.format('', width) {|q| @tree.altshow(q)}
+    end
+
+    def test_tree_alt_00_18
+      expected = <<'End'.chomp
+aaaa[
+  bbbbb[
+    ccc,
+    dd
+  ],
+  eee,
+  ffff[
+    gg,
+    hhh,
+    ii
+  ]
+]
+End
+      assert_equal(expected, tree_alt(0))
+      assert_equal(expected, tree_alt(18))
+    end
+
+    def test_tree_alt_19_20
+      expected = <<'End'.chomp
+aaaa[
+  bbbbb[ ccc, dd ],
+  eee,
+  ffff[
+    gg,
+    hhh,
+    ii
+  ]
+]
+End
+      assert_equal(expected, tree_alt(19))
+      assert_equal(expected, tree_alt(20))
+    end
+
+    def test_tree_alt_20_49
+      expected = <<'End'.chomp
+aaaa[
+  bbbbb[ ccc, dd ],
+  eee,
+  ffff[ gg, hhh, ii ]
+]
+End
+      assert_equal(expected, tree_alt(21))
+      assert_equal(expected, tree_alt(49))
+    end
+
+    def test_tree_alt_50
+      expected = <<'End'.chomp
+aaaa[ bbbbb[ ccc, dd ], eee, ffff[ gg, hhh, ii ] ]
+End
+      assert_equal(expected, tree_alt(50))
+    end
+
+    class Tree # :nodoc:
+      def initialize(string, *children)
+        @string = string
+        @children = children
+      end
+
+      def show(q)
+        q.group {
+          q.text @string
+          q.nest(@string.length) {
+            unless @children.empty?
+              q.text '['
+              q.nest(1) {
+                first = true
+                @children.each {|t|
+                  if first
+                    first = false
+                  else
+                    q.text ','
+                    q.breakable
+                  end
+                  t.show(q)
+                }
+              }
+              q.text ']'
+            end
+          }
+        }
+      end
+
+      def altshow(q)
+        q.group {
+          q.text @string
+          unless @children.empty?
+            q.text '['
+            q.nest(2) {
+              q.breakable
+              first = true
+              @children.each {|t|
+                if first
+                  first = false
+                else
+                  q.text ','
+                  q.breakable
+                end
+                t.altshow(q)
+              }
+            }
+            q.breakable
+            q.text ']'
+          end
+        }
+      end
+
+    end
+  end
+
+  class StrictPrettyExample < Test::Unit::TestCase # :nodoc:
+    def prog(width)
+      PrettyPrint.format('', width) {|q|
+        q.group {
+          q.group {q.nest(2) {
+                       q.text "if"; q.breakable;
+                       q.group {
+                         q.nest(2) {
+                           q.group {q.text "a"; q.breakable; q.text "=="}
+                           q.breakable; q.text "b"}}}}
+          q.breakable
+          q.group {q.nest(2) {
+                       q.text "then"; q.breakable;
+                       q.group {
+                         q.nest(2) {
+                           q.group {q.text "a"; q.breakable; q.text "<<"}
+                           q.breakable; q.text "2"}}}}
+          q.breakable
+          q.group {q.nest(2) {
+                       q.text "else"; q.breakable;
+                       q.group {
+                         q.nest(2) {
+                           q.group {q.text "a"; q.breakable; q.text "+"}
+                           q.breakable; q.text "b"}}}}}
+      }
+    end
+
+    def test_00_04
+      expected = <<'End'.chomp
+if
+  a
+    ==
+    b
+then
+  a
+    <<
+    2
+else
+  a
+    +
+    b
+End
+      assert_equal(expected, prog(0))
+      assert_equal(expected, prog(4))
+    end
+
+    def test_05
+      expected = <<'End'.chomp
+if
+  a
+    ==
+    b
+then
+  a
+    <<
+    2
+else
+  a +
+    b
+End
+      assert_equal(expected, prog(5))
+    end
+
+    def test_06
+      expected = <<'End'.chomp
+if
+  a ==
+    b
+then
+  a <<
+    2
+else
+  a +
+    b
+End
+      assert_equal(expected, prog(6))
+    end
+
+    def test_07
+      expected = <<'End'.chomp
+if
+  a ==
+    b
+then
+  a <<
+    2
+else
+  a + b
+End
+      assert_equal(expected, prog(7))
+    end
+
+    def test_08
+      expected = <<'End'.chomp
+if
+  a == b
+then
+  a << 2
+else
+  a + b
+End
+      assert_equal(expected, prog(8))
+    end
+
+    def test_09
+      expected = <<'End'.chomp
+if a == b
+then
+  a << 2
+else
+  a + b
+End
+      assert_equal(expected, prog(9))
+    end
+
+    def test_10
+      expected = <<'End'.chomp
+if a == b
+then
+  a << 2
+else a + b
+End
+      assert_equal(expected, prog(10))
+    end
+
+    def test_11_31
+      expected = <<'End'.chomp
+if a == b
+then a << 2
+else a + b
+End
+      assert_equal(expected, prog(11))
+      assert_equal(expected, prog(15))
+      assert_equal(expected, prog(31))
+    end
+
+    def test_32
+      expected = <<'End'.chomp
+if a == b then a << 2 else a + b
+End
+      assert_equal(expected, prog(32))
+    end
+
+  end
+
+  class TailGroup < Test::Unit::TestCase # :nodoc:
+    def test_1
+      out = PrettyPrint.format('', 10) {|q|
+        q.group {
+          q.group {
+            q.text "abc"
+            q.breakable
+            q.text "def"
+          }
+          q.group {
+            q.text "ghi"
+            q.breakable
+            q.text "jkl"
+          }
+        }
+      }
+      assert_equal("abc defghi\njkl", out)
+    end
+  end
+
+  class NonString < Test::Unit::TestCase # :nodoc:
+    def format(width)
+      PrettyPrint.format([], width, 'newline', lambda {|n| "#{n} spaces"}) {|q|
+        q.text(3, 3)
+        q.breakable(1, 1)
+        q.text(3, 3)
+      }
+    end
+
+    def test_6
+      assert_equal([3, "newline", "0 spaces", 3], format(6))
+    end
+
+    def test_7
+      assert_equal([3, 1, 3], format(7))
+    end
+
+  end
+
+  class Fill < Test::Unit::TestCase # :nodoc:
+    def format(width)
+      PrettyPrint.format('', width) {|q|
+        q.group {
+          q.text 'abc'
+          q.fill_breakable
+          q.text 'def'
+          q.fill_breakable
+          q.text 'ghi'
+          q.fill_breakable
+          q.text 'jkl'
+          q.fill_breakable
+          q.text 'mno'
+          q.fill_breakable
+          q.text 'pqr'
+          q.fill_breakable
+          q.text 'stu'
+        }
+      }
+    end
+
+    def test_00_06
+      expected = <<'End'.chomp
+abc
+def
+ghi
+jkl
+mno
+pqr
+stu
+End
+      assert_equal(expected, format(0))
+      assert_equal(expected, format(6))
+    end
+
+    def test_07_10
+      expected = <<'End'.chomp
+abc def
+ghi jkl
+mno pqr
+stu
+End
+      assert_equal(expected, format(7))
+      assert_equal(expected, format(10))
+    end
+
+    def test_11_14
+      expected = <<'End'.chomp
+abc def ghi
+jkl mno pqr
+stu
+End
+      assert_equal(expected, format(11))
+      assert_equal(expected, format(14))
+    end
+
+    def test_15_18
+      expected = <<'End'.chomp
+abc def ghi jkl
+mno pqr stu
+End
+      assert_equal(expected, format(15))
+      assert_equal(expected, format(18))
+    end
+
+    def test_19_22
+      expected = <<'End'.chomp
+abc def ghi jkl mno
+pqr stu
+End
+      assert_equal(expected, format(19))
+      assert_equal(expected, format(22))
+    end
+
+    def test_23_26
+      expected = <<'End'.chomp
+abc def ghi jkl mno pqr
+stu
+End
+      assert_equal(expected, format(23))
+      assert_equal(expected, format(26))
+    end
+
+    def test_27
+      expected = <<'End'.chomp
+abc def ghi jkl mno pqr stu
+End
+      assert_equal(expected, format(27))
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/profile.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/profile.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/profile.rb	(revision 18425)
@@ -0,0 +1,6 @@
+require 'profiler'
+
+END {
+  Profiler__::print_profile(STDERR)
+}
+Profiler__::start_profile
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/profiler.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/profiler.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/profiler.rb	(revision 18425)
@@ -0,0 +1,59 @@
+module Profiler__
+  # internal values
+  @@start = @@stack = @@map = nil
+  PROFILE_PROC = proc{|event, file, line, id, binding, klass|
+    case event
+    when "call", "c-call"
+      now = Process.times[0]
+      @@stack.push [now, 0.0]
+    when "return", "c-return"
+      now = Process.times[0]
+      key = [klass, id]
+      if tick = @@stack.pop
+        data = (@@map[key] ||= [0, 0.0, 0.0, key])
+        data[0] += 1
+        cost = now - tick[0]
+        data[1] += cost
+        data[2] += cost - tick[1]
+        @@stack[-1][1] += cost if @@stack[-1]
+      end
+    end
+  }
+module_function
+  def start_profile
+    @@start = Process.times[0]
+    @@stack = []
+    @@map = {}
+    set_trace_func PROFILE_PROC
+  end
+  def stop_profile
+    set_trace_func nil
+  end
+  def print_profile(f)
+    stop_profile
+    total = Process.times[0] - @@start
+    if total == 0 then total = 0.01 end
+    data = @@map.values
+    data.sort!{|a,b| b[2] <=> a[2]}
+    sum = 0
+    f.printf "  %%   cumulative   self              self     total\n"
+    f.printf " time   seconds   seconds    calls  ms/call  ms/call  name\n"
+    for d in data
+      sum += d[2]
+      f.printf "%6.2f %8.2f  %8.2f %8d ", d[2]/total*100, sum, d[2], d[0]
+      f.printf "%8.2f %8.2f  %s\n", d[2]*1000/d[0], d[1]*1000/d[0], get_name(*d[3])
+    end
+    f.printf "%6.2f %8.2f  %8.2f %8d ", 0.0, total, 0.0, 1     # ???
+    f.printf "%8.2f %8.2f  %s\n", 0.0, total*1000, "#toplevel" # ???
+  end
+  def get_name(klass, id)
+    name = klass.to_s || ""
+    if klass.kind_of? Class
+      name += "#"
+    else
+      name += "."
+    end
+    name + id.id2name
+  end
+  private :get_name
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/pstore.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/pstore.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/pstore.rb	(revision 18425)
@@ -0,0 +1,395 @@
+# = PStore -- Transactional File Storage for Ruby Objects
+#
+# pstore.rb -
+#   originally by matz
+#   documentation by Kev Jackson and James Edward Gray II
+#
+# See PStore for documentation.
+
+
+require "fileutils"
+require "digest/md5"
+
+#
+# PStore implements a file based persistance mechanism based on a Hash.  User
+# code can store hierarchies of Ruby objects (values) into the data store file
+# by name (keys).  An object hierarchy may be just a single object.  User code 
+# may later read values back from the data store or even update data, as needed.
+# 
+# The transactional behavior ensures that any changes succeed or fail together.
+# This can be used to ensure that the data store is not left in a transitory
+# state, where some values were upated but others were not.
+# 
+# Behind the scenes, Ruby objects are stored to the data store file with 
+# Marshal.  That carries the usual limitations.  Proc objects cannot be 
+# marshalled, for example.
+#
+# == Usage example:
+# 
+#  require "pstore"
+#  
+#  # a mock wiki object...
+#  class WikiPage
+#    def initialize( page_name, author, contents )
+#      @page_name = page_name
+#      @revisions = Array.new
+#      
+#      add_revision(author, contents)
+#    end
+#    
+#    attr_reader :page_name
+#    
+#    def add_revision( author, contents )
+#      @revisions << { :created  => Time.now,
+#                      :author   => author,
+#                      :contents => contents }
+#    end
+#    
+#    def wiki_page_references
+#      [@page_name] + @revisions.last[:contents].scan(/\b(?:[A-Z]+[a-z]+){2,}/)
+#    end
+#    
+#    # ...
+#  end
+#  
+#  # create a new page...
+#  home_page = WikiPage.new( "HomePage", "James Edward Gray II",
+#                            "A page about the JoysOfDocumentation..." )
+#  
+#  # then we want to update page data and the index together, or not at all...
+#  wiki = PStore.new("wiki_pages.pstore")
+#  wiki.transaction do  # begin transaction; do all of this or none of it
+#    # store page...
+#    wiki[home_page.page_name] = home_page
+#    # ensure that an index has been created...
+#    wiki[:wiki_index] ||= Array.new
+#    # update wiki index...
+#    wiki[:wiki_index].push(*home_page.wiki_page_references)
+#  end                   # commit changes to wiki data store file
+#  
+#  ### Some time later... ###
+#  
+#  # read wiki data...
+#  wiki.transaction(true) do  # begin read-only transaction, no changes allowed
+#    wiki.roots.each do |data_root_name|
+#      p data_root_name
+#      p wiki[data_root_name]
+#    end
+#  end
+#
+class PStore
+  binmode = defined?(File::BINARY) ? File::BINARY : 0
+  RDWR_ACCESS = File::RDWR | File::CREAT | binmode
+  RD_ACCESS = File::RDONLY | binmode
+  WR_ACCESS = File::WRONLY | File::CREAT | File::TRUNC | binmode
+
+  # The error type thrown by all PStore methods.
+  class Error < StandardError
+  end
+
+  # 
+  # To construct a PStore object, pass in the _file_ path where you would like 
+  # the data to be stored.
+  # 
+  def initialize(file)
+    dir = File::dirname(file)
+    unless File::directory? dir
+      raise PStore::Error, format("directory %s does not exist", dir)
+    end
+    if File::exist? file and not File::readable? file
+      raise PStore::Error, format("file %s not readable", file)
+    end
+    @transaction = false
+    @filename = file
+    @abort = false
+  end
+
+  # Raises PStore::Error if the calling code is not in a PStore#transaction.
+  def in_transaction
+    raise PStore::Error, "not in transaction" unless @transaction
+  end
+  # 
+  # Raises PStore::Error if the calling code is not in a PStore#transaction or
+  # if the code is in a read-only PStore#transaction.
+  # 
+  def in_transaction_wr()
+    in_transaction()
+    raise PStore::Error, "in read-only transaction" if @rdonly
+  end
+  private :in_transaction, :in_transaction_wr
+
+  #
+  # Retrieves a value from the PStore file data, by _name_.  The hierarchy of 
+  # Ruby objects stored under that root _name_ will be returned.
+  # 
+  # *WARNING*:  This method is only valid in a PStore#transaction.  It will
+  # raise PStore::Error if called at any other time.
+  #
+  def [](name)
+    in_transaction
+    @table[name]
+  end
+  #
+  # This method is just like PStore#[], save that you may also provide a 
+  # _default_ value for the object.  In the event the specified _name_ is not 
+  # found in the data store, your _default_ will be returned instead.  If you do 
+  # not specify a default, PStore::Error will be raised if the object is not 
+  # found.
+  # 
+  # *WARNING*:  This method is only valid in a PStore#transaction.  It will
+  # raise PStore::Error if called at any other time.
+  #
+  def fetch(name, default=PStore::Error)
+    in_transaction
+    unless @table.key? name
+      if default==PStore::Error
+	raise PStore::Error, format("undefined root name `%s'", name)
+      else
+	return default
+      end
+    end
+    @table[name]
+  end
+  #
+  # Stores an individual Ruby object or a hierarchy of Ruby objects in the data
+  # store file under the root _name_.  Assigning to a _name_ already in the data
+  # store clobbers the old data.
+  # 
+  # == Example:
+  # 
+  #  require "pstore"
+  #  
+  #  store = PStore.new("data_file.pstore")
+  #  store.transaction do  # begin transaction
+  #    # load some data into the store...
+  #    store[:single_object] = "My data..."
+  #    store[:obj_heirarchy] = { "Kev Jackson" => ["rational.rb", "pstore.rb"],
+  #                              "James Gray"  => ["erb.rb", "pstore.rb"] }
+  #  end                   # commit changes to data store file
+  # 
+  # *WARNING*:  This method is only valid in a PStore#transaction and it cannot
+  # be read-only.  It will raise PStore::Error if called at any other time.
+  #
+  def []=(name, value)
+    in_transaction_wr()
+    @table[name] = value
+  end
+  #
+  # Removes an object hierarchy from the data store, by _name_.
+  # 
+  # *WARNING*:  This method is only valid in a PStore#transaction and it cannot
+  # be read-only.  It will raise PStore::Error if called at any other time.
+  #
+  def delete(name)
+    in_transaction_wr()
+    @table.delete name
+  end
+
+  #
+  # Returns the names of all object hierarchies currently in the store.
+  # 
+  # *WARNING*:  This method is only valid in a PStore#transaction.  It will
+  # raise PStore::Error if called at any other time.
+  #
+  def roots
+    in_transaction
+    @table.keys
+  end
+  #
+  # Returns true if the supplied _name_ is currently in the data store.
+  # 
+  # *WARNING*:  This method is only valid in a PStore#transaction.  It will
+  # raise PStore::Error if called at any other time.
+  #
+  def root?(name)
+    in_transaction
+    @table.key? name
+  end
+  # Returns the path to the data store file.
+  def path
+    @filename
+  end
+
+  #
+  # Ends the current PStore#transaction, committing any changes to the data
+  # store immediately.
+  # 
+  # == Example:
+  # 
+  #  require "pstore"
+  #   
+  #  store = PStore.new("data_file.pstore")
+  #  store.transaction do  # begin transaction
+  #    # load some data into the store...
+  #    store[:one] = 1
+  #    store[:two] = 2
+  #  
+  #    store.commit        # end transaction here, committing changes
+  #  
+  #    store[:three] = 3   # this change is never reached
+  #  end
+  # 
+  # *WARNING*:  This method is only valid in a PStore#transaction.  It will
+  # raise PStore::Error if called at any other time.
+  #
+  def commit
+    in_transaction
+    @abort = false
+    throw :pstore_abort_transaction
+  end
+  #
+  # Ends the current PStore#transaction, discarding any changes to the data
+  # store.
+  # 
+  # == Example:
+  # 
+  #  require "pstore"
+  #   
+  #  store = PStore.new("data_file.pstore")
+  #  store.transaction do  # begin transaction
+  #    store[:one] = 1     # this change is not applied, see below...
+  #    store[:two] = 2     # this change is not applied, see below...
+  #  
+  #    store.abort         # end transaction here, discard all changes
+  #  
+  #    store[:three] = 3   # this change is never reached
+  #  end
+  # 
+  # *WARNING*:  This method is only valid in a PStore#transaction.  It will
+  # raise PStore::Error if called at any other time.
+  #
+  def abort
+    in_transaction
+    @abort = true
+    throw :pstore_abort_transaction
+  end
+
+  #
+  # Opens a new transaction for the data store.  Code executed inside a block
+  # passed to this method may read and write data to and from the data store 
+  # file.
+  # 
+  # At the end of the block, changes are committed to the data store
+  # automatically.  You may exit the transaction early with a call to either 
+  # PStore#commit or PStore#abort.  See those methods for details about how
+  # changes are handled.  Raising an uncaught Exception in the block is 
+  # equivalent to calling PStore#abort.
+  # 
+  # If _read_only_ is set to +true+, you will only be allowed to read from the
+  # data store during the transaction and any attempts to change the data will
+  # raise a PStore::Error.
+  # 
+  # Note that PStore does not support nested transactions.
+  #
+  def transaction(read_only=false)  # :yields:  pstore
+    raise PStore::Error, "nested transaction" if @transaction
+    begin
+      @rdonly = read_only
+      @abort = false
+      @transaction = true
+      value = nil
+      new_file = @filename + ".new"
+
+      content = nil
+      unless read_only
+        file = File.open(@filename, RDWR_ACCESS)
+        file.flock(File::LOCK_EX)
+        commit_new(file) if FileTest.exist?(new_file)
+        content = file.read()
+      else
+        begin
+          file = File.open(@filename, RD_ACCESS)
+          file.flock(File::LOCK_SH)
+          content = (File.open(new_file, RD_ACCESS) {|n| n.read} rescue file.read())
+        rescue Errno::ENOENT
+          content = ""
+        end
+      end
+
+      if content != ""
+	@table = load(content)
+        if !read_only
+          size = content.size
+          md5 = Digest::MD5.digest(content)
+        end
+      else
+	@table = {}
+      end
+      content = nil		# unreference huge data
+
+      begin
+	catch(:pstore_abort_transaction) do
+	  value = yield(self)
+	end
+      rescue Exception
+	@abort = true
+	raise
+      ensure
+	if !read_only and !@abort
+          tmp_file = @filename + ".tmp"
+	  content = dump(@table)
+	  if !md5 || size != content.size || md5 != Digest::MD5.digest(content)
+            File.open(tmp_file, WR_ACCESS) {|t| t.write(content)}
+            File.rename(tmp_file, new_file)
+            commit_new(file)
+          end
+          content = nil		# unreference huge data
+	end
+      end
+    ensure
+      @table = nil
+      @transaction = false
+      file.close if file
+    end
+    value
+  end
+
+  # This method is just a wrapped around Marshal.dump.
+  def dump(table)  # :nodoc:
+    Marshal::dump(table)
+  end
+
+  # This method is just a wrapped around Marshal.load.
+  def load(content)  # :nodoc:
+    Marshal::load(content)
+  end
+
+  # This method is just a wrapped around Marshal.load.
+  def load_file(file)  # :nodoc:
+    Marshal::load(file)
+  end
+
+  private
+  # Commits changes to the data store file.
+  def commit_new(f)
+    f.truncate(0)
+    f.rewind
+    new_file = @filename + ".new"
+    File.open(new_file, RD_ACCESS) do |nf|
+      FileUtils.copy_stream(nf, f)
+    end
+    File.unlink(new_file)
+  end
+end
+
+# :enddoc:
+
+if __FILE__ == $0
+  db = PStore.new("/tmp/foo")
+  db.transaction do
+    p db.roots
+    ary = db["root"] = [1,2,3,4]
+    ary[1] = [1,1.5]
+  end
+
+  1000.times do
+    db.transaction do
+      db["root"][0] += 1
+      p db["root"][0]
+    end
+  end
+
+  db.transaction(true) do
+    p db["root"]
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/racc/parser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/racc/parser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/racc/parser.rb	(revision 18425)
@@ -0,0 +1,442 @@
+#
+# $originalId: parser.rb,v 1.8 2006/07/06 11:42:07 aamine Exp $
+#
+# Copyright (c) 1999-2006 Minero Aoki
+#
+# This program is free software.
+# You can distribute/modify this program under the same terms of ruby.
+#
+# As a special exception, when this code is copied by Racc
+# into a Racc output file, you may use that output file
+# without restriction.
+#
+
+unless defined?(NotImplementedError)
+  NotImplementedError = NotImplementError
+end
+
+module Racc
+  class ParseError < StandardError; end
+end
+unless defined?(::ParseError)
+  ParseError = Racc::ParseError
+end
+
+module Racc
+
+  unless defined?(Racc_No_Extentions)
+    Racc_No_Extentions = false
+  end
+
+  class Parser
+
+    Racc_Runtime_Version = '1.4.5'
+    Racc_Runtime_Revision = '$originalRevision: 1.8 $'.split[1]
+
+    Racc_Runtime_Core_Version_R = '1.4.5'
+    Racc_Runtime_Core_Revision_R = '$originalRevision: 1.8 $'.split[1]
+    begin
+      require 'racc/cparse'
+    # Racc_Runtime_Core_Version_C  = (defined in extention)
+      Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split[2]
+      unless new.respond_to?(:_racc_do_parse_c, true)
+        raise LoadError, 'old cparse.so'
+      end
+      if Racc_No_Extentions
+        raise LoadError, 'selecting ruby version of racc runtime core'
+      end
+
+      Racc_Main_Parsing_Routine    = :_racc_do_parse_c
+      Racc_YY_Parse_Method         = :_racc_yyparse_c
+      Racc_Runtime_Core_Version    = Racc_Runtime_Core_Version_C
+      Racc_Runtime_Core_Revision   = Racc_Runtime_Core_Revision_C
+      Racc_Runtime_Type            = 'c'
+    rescue LoadError
+      Racc_Main_Parsing_Routine    = :_racc_do_parse_rb
+      Racc_YY_Parse_Method         = :_racc_yyparse_rb
+      Racc_Runtime_Core_Version    = Racc_Runtime_Core_Version_R
+      Racc_Runtime_Core_Revision   = Racc_Runtime_Core_Revision_R
+      Racc_Runtime_Type            = 'ruby'
+    end
+
+    def Parser.racc_runtime_type
+      Racc_Runtime_Type
+    end
+
+    private
+
+    def _racc_setup
+      @yydebug = false unless self.class::Racc_debug_parser
+      @yydebug = false unless defined?(@yydebug)
+      if @yydebug
+        @racc_debug_out = $stderr unless defined?(@racc_debug_out)
+        @racc_debug_out ||= $stderr
+      end
+      arg = self.class::Racc_arg
+      arg[13] = true if arg.size < 14
+      arg
+    end
+
+    def _racc_init_sysvars
+      @racc_state  = [0]
+      @racc_tstack = []
+      @racc_vstack = []
+
+      @racc_t = nil
+      @racc_val = nil
+
+      @racc_read_next = true
+
+      @racc_user_yyerror = false
+      @racc_error_status = 0
+    end
+
+    ###
+    ### do_parse
+    ###
+
+    def do_parse
+      __send__(Racc_Main_Parsing_Routine, _racc_setup(), false)
+    end
+
+    def next_token
+      raise NotImplementedError, "#{self.class}\#next_token is not defined"
+    end
+
+    def _racc_do_parse_rb(arg, in_debug)
+      action_table, action_check, action_default, action_pointer,
+      goto_table,   goto_check,   goto_default,   goto_pointer,
+      nt_base,      reduce_table, token_table,    shift_n,
+      reduce_n,     use_result,   * = arg
+
+      _racc_init_sysvars
+      tok = act = i = nil
+      nerr = 0
+
+      catch(:racc_end_parse) {
+        while true
+          if i = action_pointer[@racc_state[-1]]
+            if @racc_read_next
+              if @racc_t != 0   # not EOF
+                tok, @racc_val = next_token()
+                unless tok      # EOF
+                  @racc_t = 0
+                else
+                  @racc_t = (token_table[tok] or 1)   # error token
+                end
+                racc_read_token(@racc_t, tok, @racc_val) if @yydebug
+                @racc_read_next = false
+              end
+            end
+            i += @racc_t
+            unless i >= 0 and
+                   act = action_table[i] and
+                   action_check[i] == @racc_state[-1]
+              act = action_default[@racc_state[-1]]
+            end
+          else
+            act = action_default[@racc_state[-1]]
+          end
+          while act = _racc_evalact(act, arg)
+            ;
+          end
+        end
+      }
+    end
+
+    ###
+    ### yyparse
+    ###
+
+    def yyparse(recv, mid)
+      __send__(Racc_YY_Parse_Method, recv, mid, _racc_setup(), true)
+    end
+
+    def _racc_yyparse_rb(recv, mid, arg, c_debug)
+      action_table, action_check, action_default, action_pointer,
+      goto_table,   goto_check,   goto_default,   goto_pointer,
+      nt_base,      reduce_table, token_table,    shift_n,
+      reduce_n,     use_result,   * = arg
+
+      _racc_init_sysvars
+      tok = nil
+      act = nil
+      i = nil
+      nerr = 0
+
+      catch(:racc_end_parse) {
+        until i = action_pointer[@racc_state[-1]]
+          while act = _racc_evalact(action_default[@racc_state[-1]], arg)
+            ;
+          end
+        end
+        recv.__send__(mid) do |tok, val|
+          unless tok
+            @racc_t = 0
+          else
+            @racc_t = (token_table[tok] or 1)   # error token
+          end
+          @racc_val = val
+          @racc_read_next = false
+
+          i += @racc_t
+          unless i >= 0 and
+                 act = action_table[i] and
+                 action_check[i] == @racc_state[-1]
+            act = action_default[@racc_state[-1]]
+          end
+          while act = _racc_evalact(act, arg)
+            ;
+          end
+
+          while not (i = action_pointer[@racc_state[-1]]) or
+                not @racc_read_next or
+                @racc_t == 0   # $
+            unless i and i += @racc_t and
+                   i >= 0 and
+                   act = action_table[i] and
+                   action_check[i] == @racc_state[-1]
+              act = action_default[@racc_state[-1]]
+            end
+            while act = _racc_evalact(act, arg)
+              ;
+            end
+          end
+        end
+      }
+    end
+
+    ###
+    ### common
+    ###
+
+    def _racc_evalact(act, arg)
+      action_table, action_check, action_default, action_pointer,
+      goto_table,   goto_check,   goto_default,   goto_pointer,
+      nt_base,      reduce_table, token_table,    shift_n,
+      reduce_n,     use_result,   * = arg
+      nerr = 0   # tmp
+
+      if act > 0 and act < shift_n
+        #
+        # shift
+        #
+        if @racc_error_status > 0
+          @racc_error_status -= 1 unless @racc_t == 1   # error token
+        end
+        @racc_vstack.push @racc_val
+        @racc_state.push act
+        @racc_read_next = true
+        if @yydebug
+          @racc_tstack.push @racc_t
+          racc_shift @racc_t, @racc_tstack, @racc_vstack
+        end
+
+      elsif act < 0 and act > -reduce_n
+        #
+        # reduce
+        #
+        code = catch(:racc_jump) {
+          @racc_state.push _racc_do_reduce(arg, act)
+          false
+        }
+        if code
+          case code
+          when 1 # yyerror
+            @racc_user_yyerror = true   # user_yyerror
+            return -reduce_n
+          when 2 # yyaccept
+            return shift_n
+          else
+            raise '[Racc Bug] unknown jump code'
+          end
+        end
+
+      elsif act == shift_n
+        #
+        # accept
+        #
+        racc_accept if @yydebug
+        throw :racc_end_parse, @racc_vstack[0]
+
+      elsif act == -reduce_n
+        #
+        # error
+        #
+        case @racc_error_status
+        when 0
+          unless arg[21]    # user_yyerror
+            nerr += 1
+            on_error @racc_t, @racc_val, @racc_vstack
+          end
+        when 3
+          if @racc_t == 0   # is $
+            throw :racc_end_parse, nil
+          end
+          @racc_read_next = true
+        end
+        @racc_user_yyerror = false
+        @racc_error_status = 3
+        while true
+          if i = action_pointer[@racc_state[-1]]
+            i += 1   # error token
+            if  i >= 0 and
+                (act = action_table[i]) and
+                action_check[i] == @racc_state[-1]
+              break
+            end
+          end
+          throw :racc_end_parse, nil if @racc_state.size <= 1
+          @racc_state.pop
+          @racc_vstack.pop
+          if @yydebug
+            @racc_tstack.pop
+            racc_e_pop @racc_state, @racc_tstack, @racc_vstack
+          end
+        end
+        return act
+
+      else
+        raise "[Racc Bug] unknown action #{act.inspect}"
+      end
+
+      racc_next_state(@racc_state[-1], @racc_state) if @yydebug
+
+      nil
+    end
+
+    def _racc_do_reduce(arg, act)
+      action_table, action_check, action_default, action_pointer,
+      goto_table,   goto_check,   goto_default,   goto_pointer,
+      nt_base,      reduce_table, token_table,    shift_n,
+      reduce_n,     use_result,   * = arg
+      state = @racc_state
+      vstack = @racc_vstack
+      tstack = @racc_tstack
+
+      i = act * -3
+      len       = reduce_table[i]
+      reduce_to = reduce_table[i+1]
+      method_id = reduce_table[i+2]
+      void_array = []
+
+      tmp_t = tstack[-len, len] if @yydebug
+      tmp_v = vstack[-len, len]
+      tstack[-len, len] = void_array if @yydebug
+      vstack[-len, len] = void_array
+      state[-len, len]  = void_array
+
+      # tstack must be updated AFTER method call
+      if use_result
+        vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0])
+      else
+        vstack.push __send__(method_id, tmp_v, vstack)
+      end
+      tstack.push reduce_to
+
+      racc_reduce(tmp_t, reduce_to, tstack, vstack) if @yydebug
+
+      k1 = reduce_to - nt_base
+      if i = goto_pointer[k1]
+        i += state[-1]
+        if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1
+          return curstate
+        end
+      end
+      goto_default[k1]
+    end
+
+    def on_error(t, val, vstack)
+      raise ParseError, sprintf("\nparse error on value %s (%s)",
+                                val.inspect, token_to_str(t) || '?')
+    end
+
+    def yyerror
+      throw :racc_jump, 1
+    end
+
+    def yyaccept
+      throw :racc_jump, 2
+    end
+
+    def yyerrok
+      @racc_error_status = 0
+    end
+
+    #
+    # for debugging output
+    #
+
+    def racc_read_token(t, tok, val)
+      @racc_debug_out.print 'read    '
+      @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') '
+      @racc_debug_out.puts val.inspect
+      @racc_debug_out.puts
+    end
+
+    def racc_shift(tok, tstack, vstack)
+      @racc_debug_out.puts "shift   #{racc_token2str tok}"
+      racc_print_stacks tstack, vstack
+      @racc_debug_out.puts
+    end
+
+    def racc_reduce(toks, sim, tstack, vstack)
+      out = @racc_debug_out
+      out.print 'reduce '
+      if toks.empty?
+        out.print ' <none>'
+      else
+        toks.each {|t| out.print ' ', racc_token2str(t) }
+      end
+      out.puts " --> #{racc_token2str(sim)}"
+          
+      racc_print_stacks tstack, vstack
+      @racc_debug_out.puts
+    end
+
+    def racc_accept
+      @racc_debug_out.puts 'accept'
+      @racc_debug_out.puts
+    end
+
+    def racc_e_pop(state, tstack, vstack)
+      @racc_debug_out.puts 'error recovering mode: pop token'
+      racc_print_states state
+      racc_print_stacks tstack, vstack
+      @racc_debug_out.puts
+    end
+
+    def racc_next_state(curstate, state)
+      @racc_debug_out.puts  "goto    #{curstate}"
+      racc_print_states state
+      @racc_debug_out.puts
+    end
+
+    def racc_print_stacks(t, v)
+      out = @racc_debug_out
+      out.print '        ['
+      t.each_index do |i|
+        out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')'
+      end
+      out.puts ' ]'
+    end
+
+    def racc_print_states(s)
+      out = @racc_debug_out
+      out.print '        ['
+      s.each {|st| out.print ' ', st }
+      out.puts ' ]'
+    end
+
+    def racc_token2str(tok)
+      self.class::Racc_token_to_s_table[tok] or
+          raise "[Racc Bug] can't convert token #{tok} to string"
+    end
+
+    def token_to_str(t)
+      self.class::Racc_token_to_s_table[t]
+    end
+
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rational.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rational.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rational.rb	(revision 18425)
@@ -0,0 +1,530 @@
+#
+#   rational.rb -
+#       $Release Version: 0.5 $
+#       $Revision: 1.7 $
+#       $Date: 1999/08/24 12:49:28 $
+#       by Keiju ISHITSUKA(SHL Japan Inc.)
+#
+# Documentation by Kevin Jackson and Gavin Sinclair.
+# 
+# When you <tt>require 'rational'</tt>, all interactions between numbers
+# potentially return a rational result.  For example:
+#
+#   1.quo(2)              # -> 0.5
+#   require 'rational'
+#   1.quo(2)              # -> Rational(1,2)
+# 
+# See Rational for full documentation.
+#
+
+
+#
+# Creates a Rational number (i.e. a fraction).  +a+ and +b+ should be Integers:
+# 
+#   Rational(1,3)           # -> 1/3
+#
+# Note: trying to construct a Rational with floating point or real values
+# produces errors:
+#
+#   Rational(1.1, 2.3)      # -> NoMethodError
+#
+def Rational(a, b = 1)
+  if a.kind_of?(Rational) && b == 1
+    a
+  else
+    Rational.reduce(a, b)
+  end
+end
+
+#
+# Rational implements a rational class for numbers.
+#
+# <em>A rational number is a number that can be expressed as a fraction p/q
+# where p and q are integers and q != 0.  A rational number p/q is said to have
+# numerator p and denominator q.  Numbers that are not rational are called
+# irrational numbers.</em> (http://mathworld.wolfram.com/RationalNumber.html)
+#
+# To create a Rational Number:
+#   Rational(a,b)             # -> a/b
+#   Rational.new!(a,b)        # -> a/b
+#
+# Examples:
+#   Rational(5,6)             # -> 5/6
+#   Rational(5)               # -> 5/1
+# 
+# Rational numbers are reduced to their lowest terms:
+#   Rational(6,10)            # -> 3/5
+#
+# But not if you use the unusual method "new!":
+#   Rational.new!(6,10)       # -> 6/10
+#
+# Division by zero is obviously not allowed:
+#   Rational(3,0)             # -> ZeroDivisionError
+#
+class Rational < Numeric
+  @RCS_ID='-$Id: rational.rb,v 1.7 1999/08/24 12:49:28 keiju Exp keiju $-'
+
+  #
+  # Reduces the given numerator and denominator to their lowest terms.  Use
+  # Rational() instead.
+  #
+  def Rational.reduce(num, den = 1)
+    raise ZeroDivisionError, "denominator is zero" if den == 0
+
+    if den < 0
+      num = -num
+      den = -den
+    end
+    gcd = num.gcd(den)
+    num = num.div(gcd)
+    den = den.div(gcd)
+    if den == 1 && defined?(Unify)
+      num
+    else
+      new!(num, den)
+    end
+  end
+
+  #
+  # Implements the constructor.  This method does not reduce to lowest terms or
+  # check for division by zero.  Therefore #Rational() should be preferred in
+  # normal use.
+  #
+  def Rational.new!(num, den = 1)
+    new(num, den)
+  end
+
+  private_class_method :new
+
+  #
+  # This method is actually private.
+  #
+  def initialize(num, den)
+    if den < 0
+      num = -num
+      den = -den
+    end
+    if num.kind_of?(Integer) and den.kind_of?(Integer)
+      @numerator = num
+      @denominator = den
+    else
+      @numerator = num.to_i
+      @denominator = den.to_i
+    end
+  end
+
+  #
+  # Returns the addition of this value and +a+.
+  #
+  # Examples:
+  #   r = Rational(3,4)      # -> Rational(3,4)
+  #   r + 1                  # -> Rational(7,4)
+  #   r + 0.5                # -> 1.25
+  #
+  def + (a)
+    if a.kind_of?(Rational)
+      num = @numerator * a.denominator
+      num_a = a.numerator * @denominator
+      Rational(num + num_a, @denominator * a.denominator)
+    elsif a.kind_of?(Integer)
+      self + Rational.new!(a, 1)
+    elsif a.kind_of?(Float)
+      Float(self) + a
+    else
+      x, y = a.coerce(self)
+      x + y
+    end
+  end
+
+  #
+  # Returns the difference of this value and +a+.
+  # subtracted.
+  #
+  # Examples:
+  #   r = Rational(3,4)    # -> Rational(3,4)
+  #   r - 1                # -> Rational(-1,4)
+  #   r - 0.5              # -> 0.25
+  #
+  def - (a)
+    if a.kind_of?(Rational)
+      num = @numerator * a.denominator
+      num_a = a.numerator * @denominator
+      Rational(num - num_a, @denominator*a.denominator)
+    elsif a.kind_of?(Integer)
+      self - Rational.new!(a, 1)
+    elsif a.kind_of?(Float)
+      Float(self) - a
+    else
+      x, y = a.coerce(self)
+      x - y
+    end
+  end
+
+  #
+  # Returns the product of this value and +a+.
+  #
+  # Examples:
+  #   r = Rational(3,4)    # -> Rational(3,4)
+  #   r * 2                # -> Rational(3,2)
+  #   r * 4                # -> Rational(3,1)
+  #   r * 0.5              # -> 0.375
+  #   r * Rational(1,2)    # -> Rational(3,8)
+  #
+  def * (a)
+    if a.kind_of?(Rational)
+      num = @numerator * a.numerator
+      den = @denominator * a.denominator
+      Rational(num, den)
+    elsif a.kind_of?(Integer)
+      self * Rational.new!(a, 1)
+    elsif a.kind_of?(Float)
+      Float(self) * a
+    else
+      x, y = a.coerce(self)
+      x * y
+    end
+  end
+
+  #
+  # Returns the quotient of this value and +a+.
+  #   r = Rational(3,4)    # -> Rational(3,4)
+  #   r / 2                # -> Rational(3,8)
+  #   r / 2.0              # -> 0.375
+  #   r / Rational(1,2)    # -> Rational(3,2)
+  #
+  def / (a)
+    if a.kind_of?(Rational)
+      num = @numerator * a.denominator
+      den = @denominator * a.numerator
+      Rational(num, den)
+    elsif a.kind_of?(Integer)
+      raise ZeroDivisionError, "division by zero" if a == 0
+      self / Rational.new!(a, 1)
+    elsif a.kind_of?(Float)
+      Float(self) / a
+    else
+      x, y = a.coerce(self)
+      x / y
+    end
+  end
+
+  #
+  # Returns this value raised to the given power.
+  #
+  # Examples:
+  #   r = Rational(3,4)    # -> Rational(3,4)
+  #   r ** 2               # -> Rational(9,16)
+  #   r ** 2.0             # -> 0.5625
+  #   r ** Rational(1,2)   # -> 0.866025403784439
+  #
+  def ** (other)
+    if other.kind_of?(Rational)
+      Float(self) ** other
+    elsif other.kind_of?(Integer)
+      if other > 0
+	num = @numerator ** other
+	den = @denominator ** other
+      elsif other < 0
+	num = @denominator ** -other
+	den = @numerator ** -other
+      elsif other == 0
+	num = 1
+	den = 1
+      end
+      Rational.new!(num, den)
+    elsif other.kind_of?(Float)
+      Float(self) ** other
+    else
+      x, y = other.coerce(self)
+      x ** y
+    end
+  end
+
+  #
+  # Returns the remainder when this value is divided by +other+.
+  #
+  # Examples:
+  #   r = Rational(7,4)    # -> Rational(7,4)
+  #   r % Rational(1,2)    # -> Rational(1,4)
+  #   r % 1                # -> Rational(3,4)
+  #   r % Rational(1,7)    # -> Rational(1,28)
+  #   r % 0.26             # -> 0.19
+  #
+  def % (other)
+    value = (self / other).to_i
+    return self - other * value
+  end
+
+  #
+  # Returns the quotient _and_ remainder.
+  #
+  # Examples:
+  #   r = Rational(7,4)        # -> Rational(7,4)
+  #   r.divmod Rational(1,2)   # -> [3, Rational(1,4)]
+  #
+  def divmod(other)
+    value = (self / other).to_i
+    return value, self - other * value
+  end
+
+  #
+  # Returns the absolute value.
+  #
+  def abs
+    if @numerator > 0
+      Rational.new!(@numerator, @denominator)
+    else
+      Rational.new!(-@numerator, @denominator)
+    end
+  end
+
+  #
+  # Returns +true+ iff this value is numerically equal to +other+.
+  #
+  # But beware:
+  #   Rational(1,2) == Rational(4,8)          # -> true
+  #   Rational(1,2) == Rational.new!(4,8)     # -> false
+  #
+  # Don't use Rational.new!
+  #
+  def == (other)
+    if other.kind_of?(Rational)
+      @numerator == other.numerator and @denominator == other.denominator
+    elsif other.kind_of?(Integer)
+      self == Rational.new!(other, 1)
+    elsif other.kind_of?(Float)
+      Float(self) == other
+    else
+      other == self
+    end
+  end
+
+  #
+  # Standard comparison operator.
+  #
+  def <=> (other)
+    if other.kind_of?(Rational)
+      num = @numerator * other.denominator
+      num_a = other.numerator * @denominator
+      v = num - num_a
+      if v > 0
+	return 1
+      elsif v < 0
+	return  -1
+      else
+	return 0
+      end
+    elsif other.kind_of?(Integer)
+      return self <=> Rational.new!(other, 1)
+    elsif other.kind_of?(Float)
+      return Float(self) <=> other
+    elsif defined? other.coerce
+      x, y = other.coerce(self)
+      return x <=> y
+    else
+      return nil
+    end
+  end
+
+  def coerce(other)
+    if other.kind_of?(Float)
+      return other, self.to_f
+    elsif other.kind_of?(Integer)
+      return Rational.new!(other, 1), self
+    else
+      super
+    end
+  end
+
+  #
+  # Converts the rational to an Integer.  Not the _nearest_ integer, the
+  # truncated integer.  Study the following example carefully:
+  #   Rational(+7,4).to_i             # -> 1
+  #   Rational(-7,4).to_i             # -> -2
+  #   (-1.75).to_i                    # -> -1
+  #
+  # In other words:
+  #   Rational(-7,4) == -1.75                 # -> true
+  #   Rational(-7,4).to_i == (-1.75).to_i     # false
+  #
+  def to_i
+    Integer(@numerator.div(@denominator))
+  end
+
+  #
+  # Converts the rational to a Float.
+  #
+  def to_f
+    @numerator.to_f/@denominator.to_f
+  end
+
+  #
+  # Returns a string representation of the rational number.
+  #
+  # Example:
+  #   Rational(3,4).to_s          #  "3/4"
+  #   Rational(8).to_s            #  "8"
+  #
+  def to_s
+    if @denominator == 1
+      @numerator.to_s
+    else
+      @numerator.to_s+"/"+@denominator.to_s
+    end
+  end
+
+  #
+  # Returns +self+.
+  #
+  def to_r
+    self
+  end
+
+  #
+  # Returns a reconstructable string representation:
+  #
+  #   Rational(5,8).inspect     # -> "Rational(5, 8)"
+  #
+  def inspect
+    sprintf("Rational(%s, %s)", @numerator.inspect, @denominator.inspect)
+  end
+
+  #
+  # Returns a hash code for the object.
+  #
+  def hash
+    @numerator.hash ^ @denominator.hash
+  end
+
+  attr :numerator
+  attr :denominator
+
+  private :initialize
+end
+
+class Integer
+  #
+  # In an integer, the value _is_ the numerator of its rational equivalent.
+  # Therefore, this method returns +self+.
+  #
+  def numerator
+    self
+  end
+
+  #
+  # In an integer, the denominator is 1.  Therefore, this method returns 1.
+  #
+  def denominator
+    1
+  end
+
+  #
+  # Returns a Rational representation of this integer.
+  #
+  def to_r
+    Rational(self, 1)
+  end
+
+  #
+  # Returns the <em>greatest common denominator</em> of the two numbers (+self+
+  # and +n+).
+  #
+  # Examples:
+  #   72.gcd 168           # -> 24
+  #   19.gcd 36            # -> 1
+  #
+  # The result is positive, no matter the sign of the arguments.
+  #
+  def gcd(other)
+    min = self.abs
+    max = other.abs
+    while min > 0
+      tmp = min
+      min = max % min
+      max = tmp
+    end
+    max
+  end
+
+  #
+  # Returns the <em>lowest common multiple</em> (LCM) of the two arguments
+  # (+self+ and +other+).
+  #
+  # Examples:
+  #   6.lcm 7        # -> 42
+  #   6.lcm 9        # -> 18
+  #
+  def lcm(other)
+    if self.zero? or other.zero?
+      0
+    else
+      (self.div(self.gcd(other)) * other).abs
+    end
+  end
+
+  #
+  # Returns the GCD _and_ the LCM (see #gcd and #lcm) of the two arguments
+  # (+self+ and +other+).  This is more efficient than calculating them
+  # separately.
+  #
+  # Example:
+  #   6.gcdlcm 9     # -> [3, 18]
+  #
+  def gcdlcm(other)
+    gcd = self.gcd(other)
+    if self.zero? or other.zero?
+      [gcd, 0]
+    else
+      [gcd, (self.div(gcd) * other).abs]
+    end
+  end
+end
+
+class Fixnum
+  undef quo
+  # If Rational is defined, returns a Rational number instead of a Fixnum.
+  def quo(other)
+    Rational.new!(self,1) / other
+  end
+  alias rdiv quo
+
+  # Returns a Rational number if the result is in fact rational (i.e. +other+ < 0).
+  def rpower (other)
+    if other >= 0
+      self.power!(other)
+    else
+      Rational.new!(self,1)**other
+    end
+  end
+
+  unless defined? 1.power!
+    alias power! **
+    alias ** rpower
+  end
+end
+
+class Bignum
+  unless defined? Complex
+    alias power! **
+  end
+
+  undef quo
+  # If Rational is defined, returns a Rational number instead of a Bignum.
+  def quo(other)
+    Rational.new!(self,1) / other
+  end
+  alias rdiv quo
+
+  # Returns a Rational number if the result is in fact rational (i.e. +other+ < 0).
+  def rpower (other)
+    if other >= 0
+      self.power!(other)
+    else
+      Rational.new!(self, 1)**other
+    end
+  end
+
+  unless defined? Complex
+    alias ** rpower
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/code_objects.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/code_objects.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/code_objects.rb	(revision 18425)
@@ -0,0 +1,765 @@
+# We represent the various high-level code constructs that appear
+# in Ruby programs: classes, modules, methods, and so on.
+
+require 'rdoc/tokenstream'
+
+module RDoc
+
+
+  # We contain the common stuff for contexts (which are containers)
+  # and other elements (methods, attributes and so on)
+  #
+  class CodeObject
+
+    attr_accessor :parent
+
+    # We are the model of the code, but we know that at some point
+    # we will be worked on by viewers. By implementing the Viewable
+    # protocol, viewers can associated themselves with these objects.
+
+    attr_accessor :viewer
+
+    # are we done documenting (ie, did we come across a :enddoc:)?
+
+    attr_accessor :done_documenting
+
+    # Which section are we in
+
+    attr_accessor :section
+
+    # do we document ourselves?
+
+    attr_reader :document_self
+
+    def document_self=(val)
+      @document_self = val
+      if !val
+	remove_methods_etc
+      end
+    end
+
+    # set and cleared by :startdoc: and :enddoc:, this is used to toggle
+    # the capturing of documentation
+    def start_doc
+      @document_self = true
+      @document_children = true
+    end
+
+    def stop_doc
+      @document_self = false
+      @document_children = false
+    end
+
+    # do we document ourselves and our children
+
+    attr_reader :document_children
+
+    def document_children=(val)
+      @document_children = val
+      if !val
+	remove_classes_and_modules
+      end
+    end
+
+    # Do we _force_ documentation, even is we wouldn't normally show the entity
+    attr_accessor :force_documentation
+
+    # Default callbacks to nothing, but this is overridden for classes
+    # and modules
+    def remove_classes_and_modules
+    end
+
+    def remove_methods_etc
+    end
+
+    def initialize
+      @document_self = true
+      @document_children = true
+      @force_documentation = false
+      @done_documenting = false
+    end
+
+    # Access the code object's comment
+    attr_reader :comment
+
+    # Update the comment, but don't overwrite a real comment
+    # with an empty one
+    def comment=(comment)
+      @comment = comment unless comment.empty?
+    end
+
+    # There's a wee trick we pull. Comment blocks can have directives that
+    # override the stuff we extract during the parse. So, we have a special
+    # class method, attr_overridable, that lets code objects list
+    # those directives. Wehn a comment is assigned, we then extract
+    # out any matching directives and update our object
+
+    def CodeObject.attr_overridable(name, *aliases)
+      @overridables ||= {}
+
+      attr_accessor name
+
+      aliases.unshift name
+      aliases.each do |directive_name|
+        @overridables[directive_name.to_s] = name
+      end
+    end
+
+  end
+
+  # A Context is something that can hold modules, classes, methods, 
+  # attributes, aliases, requires, and includes. Classes, modules, and
+  # files are all Contexts.
+
+  class Context < CodeObject
+    attr_reader   :name, :method_list, :attributes, :aliases, :constants
+    attr_reader   :requires, :includes, :in_files, :visibility
+
+    attr_reader   :sections
+
+    class Section
+      attr_reader :title, :comment, :sequence
+
+      @@sequence = "SEC00000"
+
+      def initialize(title, comment)
+        @title = title
+        @@sequence.succ!
+        @sequence = @@sequence.dup
+        set_comment(comment)
+      end
+
+      private
+
+      # Set the comment for this section from the original comment block
+      # If the first line contains :section:, strip it and use the rest. Otherwise
+      # remove lines up to the line containing :section:, and look for 
+      # those lines again at the end and remove them. This lets us write
+      #
+      #   # ---------------------
+      #   # :SECTION: The title
+      #   # The body
+      #   # ---------------------
+
+      def set_comment(comment)
+        return unless comment
+
+        if comment =~ /^.*?:section:.*$/
+          start = $`
+          rest = $'
+          if start.empty?
+            @comment = rest
+          else
+            @comment = rest.sub(/#{start.chomp}\Z/, '')
+          end
+        else
+          @comment = comment
+        end
+        @comment = nil if @comment.empty?
+      end
+    end
+
+
+    def initialize
+      super()
+
+      @in_files    = []
+
+      @name    ||= "unknown"
+      @comment ||= ""
+      @parent  = nil
+      @visibility = :public
+
+      @current_section = Section.new(nil, nil)
+      @sections = [ @current_section ]
+
+      initialize_methods_etc
+      initialize_classes_and_modules
+    end
+
+    # map the class hash to an array externally
+    def classes
+      @classes.values
+    end
+
+    # map the module hash to an array externally
+    def modules
+      @modules.values
+    end
+
+    # Change the default visibility for new methods
+    def ongoing_visibility=(vis)
+      @visibility = vis
+    end
+
+    # Given an array +methods+ of method names, set the
+    # visibility of the corresponding AnyMethod object
+
+    def set_visibility_for(methods, vis, singleton=false)
+      count = 0
+      @method_list.each do |m|
+        if methods.include?(m.name) && m.singleton == singleton
+          m.visibility = vis
+          count += 1
+        end
+      end
+
+      return if count == methods.size || singleton
+
+      # perhaps we need to look at attributes
+
+      @attributes.each do |a|
+        if methods.include?(a.name)
+          a.visibility = vis
+          count += 1
+        end
+      end
+    end
+
+    # Record the file that we happen to find it in
+    def record_location(toplevel)
+      @in_files << toplevel unless @in_files.include?(toplevel)
+    end
+
+    # Return true if at least part of this thing was defined in +file+
+    def defined_in?(file)
+      @in_files.include?(file)
+    end
+
+    def add_class(class_type, name, superclass)
+      add_class_or_module(@classes, class_type, name, superclass)
+    end
+
+    def add_module(class_type, name)
+      add_class_or_module(@modules, class_type, name, nil)
+    end
+
+    def add_method(a_method)
+      puts "Adding #@visibility method #{a_method.name} to #@name" if $DEBUG
+      a_method.visibility = @visibility
+      add_to(@method_list, a_method)
+    end
+
+    def add_attribute(an_attribute)
+      add_to(@attributes, an_attribute)
+    end
+
+    def add_alias(an_alias)
+      meth = find_instance_method_named(an_alias.old_name)
+      if meth
+        new_meth = AnyMethod.new(an_alias.text, an_alias.new_name)
+        new_meth.is_alias_for = meth
+        new_meth.singleton    = meth.singleton
+        new_meth.params       = meth.params
+        new_meth.comment = "Alias for \##{meth.name}"
+        meth.add_alias(new_meth)
+        add_method(new_meth)
+      else
+        add_to(@aliases, an_alias)
+      end
+    end
+
+    def add_include(an_include)
+      add_to(@includes, an_include)
+    end
+
+    def add_constant(const)
+      add_to(@constants, const)
+    end
+
+    # Requires always get added to the top-level (file) context
+    def add_require(a_require)
+      if self.kind_of? TopLevel
+        add_to(@requires, a_require)
+      else
+        parent.add_require(a_require)
+      end
+    end
+
+    def add_class_or_module(collection, class_type, name, superclass=nil)
+      cls = collection[name]
+      if cls
+        puts "Reusing class/module #{name}" if $DEBUG
+      else
+        cls = class_type.new(name, superclass)
+        puts "Adding class/module #{name} to #@name" if $DEBUG
+#        collection[name] = cls if @document_self  && !@done_documenting
+        collection[name] = cls if !@done_documenting
+        cls.parent = self
+        cls.section = @current_section
+      end
+      cls
+    end
+
+    def add_to(array, thing)
+      array <<  thing if @document_self  && !@done_documenting
+      thing.parent = self
+      thing.section = @current_section
+    end
+
+    # If a class's documentation is turned off after we've started
+    # collecting methods etc., we need to remove the ones
+    # we have
+
+    def remove_methods_etc
+      initialize_methods_etc
+    end
+
+    def initialize_methods_etc
+      @method_list = []
+      @attributes  = []
+      @aliases     = []
+      @requires    = []
+      @includes    = []
+      @constants   = []
+    end
+
+    # and remove classes and modules when we see a :nodoc: all
+    def remove_classes_and_modules
+      initialize_classes_and_modules
+    end
+
+    def initialize_classes_and_modules
+      @classes     = {}
+      @modules     = {}
+    end
+
+    # Find a named module
+    def find_module_named(name)
+      return self if self.name == name
+      res = @modules[name] || @classes[name]
+      return res if res
+      find_enclosing_module_named(name)
+    end
+
+    # find a module at a higher scope
+    def find_enclosing_module_named(name)
+      parent && parent.find_module_named(name)
+    end
+
+    # Iterate over all the classes and modules in
+    # this object
+
+    def each_classmodule
+      @modules.each_value {|m| yield m}
+      @classes.each_value {|c| yield c}
+    end
+
+    def each_method
+      @method_list.each {|m| yield m}
+    end
+
+    def each_attribute 
+      @attributes.each {|a| yield a}
+    end
+
+    def each_constant
+      @constants.each {|c| yield c}
+    end
+
+    # Return the toplevel that owns us
+
+    def toplevel
+      return @toplevel if defined? @toplevel
+      @toplevel = self
+      @toplevel = @toplevel.parent until TopLevel === @toplevel
+      @toplevel
+    end
+
+    # allow us to sort modules by name
+    def <=>(other)
+      name <=> other.name
+    end
+
+    # Look up the given symbol. If method is non-nil, then
+    # we assume the symbol references a module that
+    # contains that method
+    def find_symbol(symbol, method=nil)
+      result = nil
+      case symbol
+      when /^::(.*)/
+        result = toplevel.find_symbol($1)
+      when /::/
+        modules = symbol.split(/::/)
+        unless modules.empty?
+          module_name = modules.shift
+          result = find_module_named(module_name)
+          if result
+            modules.each do |module_name|
+              result = result.find_module_named(module_name)
+              break unless result
+            end
+          end
+        end
+      else
+        # if a method is specified, then we're definitely looking for
+        # a module, otherwise it could be any symbol
+        if method
+          result = find_module_named(symbol)
+        else
+          result = find_local_symbol(symbol)
+          if result.nil?
+            if symbol =~ /^[A-Z]/
+              result = parent
+              while result && result.name != symbol
+                result = result.parent
+              end
+            end
+          end
+        end
+      end
+      if result && method
+        if !result.respond_to?(:find_local_symbol)
+          p result.name
+          p method
+          fail
+        end
+        result = result.find_local_symbol(method)
+      end
+      result
+    end
+           
+    def find_local_symbol(symbol)
+      res = find_method_named(symbol) ||
+            find_constant_named(symbol) ||
+            find_attribute_named(symbol) ||
+            find_module_named(symbol) 
+    end
+
+    # Handle sections
+
+    def set_current_section(title, comment)
+      @current_section = Section.new(title, comment)
+      @sections << @current_section
+    end
+
+    private
+
+    # Find a named method, or return nil
+    def find_method_named(name)
+      @method_list.find {|meth| meth.name == name}
+    end
+
+    # Find a named instance method, or return nil
+    def find_instance_method_named(name)
+      @method_list.find {|meth| meth.name == name && !meth.singleton}
+    end
+
+    # Find a named constant, or return nil
+    def find_constant_named(name)
+      @constants.find {|m| m.name == name}
+    end
+
+    # Find a named attribute, or return nil
+    def find_attribute_named(name)
+      @attributes.find {|m| m.name == name}
+    end
+    
+  end
+
+
+  # A TopLevel context is a source file
+
+  class TopLevel < Context
+    attr_accessor :file_stat
+    attr_accessor :file_relative_name
+    attr_accessor :file_absolute_name
+    attr_accessor :diagram
+    
+    @@all_classes = {}
+    @@all_modules = {}
+
+    def TopLevel::reset
+      @@all_classes = {}
+      @@all_modules = {}
+    end
+
+    def initialize(file_name)
+      super()
+      @name = "TopLevel"
+      @file_relative_name = file_name
+      @file_absolute_name = file_name
+      @file_stat          = File.stat(file_name)
+      @diagram            = nil
+    end
+
+    def full_name
+      nil
+    end
+
+    # Adding a class or module to a TopLevel is special, as we only
+    # want one copy of a particular top-level class. For example,
+    # if both file A and file B implement class C, we only want one
+    # ClassModule object for C. This code arranges to share
+    # classes and modules between files.
+
+    def add_class_or_module(collection, class_type, name, superclass)
+      cls = collection[name]
+      if cls
+        puts "Reusing class/module #{name}" if $DEBUG
+      else
+        if class_type == NormalModule
+          all = @@all_modules
+        else
+          all = @@all_classes
+        end
+        cls = all[name]
+        if !cls
+          cls = class_type.new(name, superclass)
+          all[name] = cls  unless @done_documenting
+        end
+        puts "Adding class/module #{name} to #@name" if $DEBUG
+        collection[name] = cls unless @done_documenting
+        cls.parent = self
+      end
+      cls
+    end
+
+    def TopLevel.all_classes_and_modules
+      @@all_classes.values + @@all_modules.values
+    end
+
+    def TopLevel.find_class_named(name)
+     @@all_classes.each_value do |c|
+        res = c.find_class_named(name) 
+        return res if res
+      end
+      nil
+    end
+
+    def find_local_symbol(symbol)
+      find_class_or_module_named(symbol) || super
+    end
+
+    def find_class_or_module_named(symbol)
+      @@all_classes.each_value {|c| return c if c.name == symbol}
+      @@all_modules.each_value {|m| return m if m.name == symbol}
+      nil
+    end
+
+    # Find a named module
+    def find_module_named(name)
+      find_class_or_module_named(name) || find_enclosing_module_named(name)
+    end
+
+
+  end
+
+  # ClassModule is the base class for objects representing either a
+  # class or a module.
+
+  class ClassModule < Context
+
+    attr_reader   :superclass
+    attr_accessor :diagram
+
+    def initialize(name, superclass = nil)
+      @name       = name
+      @diagram    = nil
+      @superclass = superclass
+      @comment    = ""
+      super()
+    end
+
+    # Return the fully qualified name of this class or module
+    def full_name
+      if @parent && @parent.full_name
+        @parent.full_name + "::" + @name
+      else
+        @name
+      end
+    end
+
+    def http_url(prefix)
+      path = full_name.split("::")
+      File.join(prefix, *path) + ".html"
+    end
+
+    # Return +true+ if this object represents a module
+    def is_module?
+      false
+    end
+
+    # to_s is simply for debugging
+    def to_s
+      res = self.class.name + ": " + @name 
+      res << @comment.to_s
+      res << super
+      res
+    end
+
+    def find_class_named(name)
+      return self if full_name == name
+      @classes.each_value {|c| return c if c.find_class_named(name) }
+      nil
+    end
+  end
+
+  # Anonymous classes
+  class AnonClass < ClassModule
+  end
+
+  # Normal classes
+  class NormalClass < ClassModule
+  end
+
+  # Singleton classes
+  class SingleClass < ClassModule
+  end
+
+  # Module
+  class NormalModule < ClassModule
+    def is_module?
+      true
+    end
+  end
+
+
+  # AnyMethod is the base class for objects representing methods
+
+  class AnyMethod < CodeObject
+    attr_accessor :name
+    attr_accessor :visibility
+    attr_accessor :block_params
+    attr_accessor :dont_rename_initialize
+    attr_accessor :singleton
+    attr_reader   :aliases           # list of other names for this method
+    attr_accessor :is_alias_for      # or a method we're aliasing
+
+    attr_overridable :params, :param, :parameters, :parameter
+
+    attr_accessor :call_seq
+
+
+    include TokenStream
+
+    def initialize(text, name)
+      super()
+      @text = text
+      @name = name
+      @token_stream  = nil
+      @visibility    = :public
+      @dont_rename_initialize = false
+      @block_params  = nil
+      @aliases       = []
+      @is_alias_for  = nil
+      @comment = ""
+      @call_seq = nil
+    end
+
+    def <=>(other)
+      @name <=> other.name
+    end
+
+    def to_s
+      res = self.class.name + ": " + @name + " (" + @text + ")\n"
+      res << @comment.to_s
+      res
+    end
+
+    def param_seq
+      p = params.gsub(/\s*\#.*/, '')
+      p = p.tr("\n", " ").squeeze(" ")
+      p = "(" + p + ")" unless p[0] == ?(
+
+      if (block = block_params)
+        # If this method has explicit block parameters, remove any
+        # explicit &block
+$stderr.puts p
+        p.sub!(/,?\s*&\w+/)
+$stderr.puts p
+
+        block.gsub!(/\s*\#.*/, '')
+        block = block.tr("\n", " ").squeeze(" ")
+        if block[0] == ?(
+          block.sub!(/^\(/, '').sub!(/\)/, '')
+        end
+        p << " {|#{block}| ...}"
+      end
+      p
+    end
+
+    def add_alias(method)
+      @aliases << method
+    end
+  end
+
+
+  # Represent an alias, which is an old_name/ new_name pair associated
+  # with a particular context
+  class Alias < CodeObject
+    attr_accessor :text, :old_name, :new_name, :comment
+    
+    def initialize(text, old_name, new_name, comment)
+      super()
+      @text = text
+      @old_name = old_name
+      @new_name = new_name
+      self.comment = comment
+    end
+
+    def to_s
+      "alias: #{self.old_name} ->  #{self.new_name}\n#{self.comment}"
+    end
+  end
+
+  # Represent a constant
+  class Constant < CodeObject
+    attr_accessor :name, :value
+
+    def initialize(name, value, comment)
+      super()
+      @name = name
+      @value = value
+      self.comment = comment
+    end
+  end
+
+  # Represent attributes
+  class Attr < CodeObject
+    attr_accessor :text, :name, :rw, :visibility
+
+    def initialize(text, name, rw, comment)
+      super()
+      @text = text
+      @name = name
+      @rw = rw
+      @visibility = :public
+      self.comment = comment
+    end
+
+    def to_s
+      "attr: #{self.name} #{self.rw}\n#{self.comment}"
+    end
+
+    def <=>(other)
+      self.name <=> other.name
+    end
+  end
+
+  # a required file
+
+  class Require < CodeObject
+    attr_accessor :name
+
+    def initialize(name, comment)
+      super()
+      @name = name.gsub(/'|"/, "") #'
+      self.comment = comment
+    end
+
+  end
+
+  # an included module
+  class Include < CodeObject
+    attr_accessor :name
+
+    def initialize(name, comment)
+      super()
+      @name = name
+      self.comment = comment
+    end
+
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/diagram.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/diagram.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/diagram.rb	(revision 18425)
@@ -0,0 +1,335 @@
+# A wonderful hack by to draw package diagrams using the dot package.
+# Originally written by  Jah, team Enticla.
+#
+# You must have the V1.7 or later in your path
+# http://www.research.att.com/sw/tools/graphviz/
+
+require "rdoc/dot/dot"
+require 'rdoc/options'
+
+module RDoc
+
+  # Draw a set of diagrams representing the modules and classes in the
+  # system. We draw one diagram for each file, and one for each toplevel
+  # class or module. This means there will be overlap. However, it also
+  # means that you'll get better context for objects.
+  #
+  # To use, simply
+  #
+  #   d = Diagram.new(info)   # pass in collection of top level infos
+  #   d.draw
+  #
+  # The results will be written to the +dot+ subdirectory. The process
+  # also sets the +diagram+ attribute in each object it graphs to
+  # the name of the file containing the image. This can be used
+  # by output generators to insert images.
+
+  class Diagram
+
+    FONT = "Arial"
+
+    DOT_PATH = "dot"
+
+    # Pass in the set of top level objects. The method also creates
+    # the subdirectory to hold the images
+
+    def initialize(info, options)
+      @info = info
+      @options = options
+      @counter = 0
+      File.makedirs(DOT_PATH)
+      @diagram_cache = {}
+    end
+
+    # Draw the diagrams. We traverse the files, drawing a diagram for
+    # each. We also traverse each top-level class and module in that
+    # file drawing a diagram for these too. 
+
+    def draw
+      unless @options.quiet
+        $stderr.print "Diagrams: "
+        $stderr.flush
+      end
+
+      @info.each_with_index do |i, file_count|
+        @done_modules = {}
+        @local_names = find_names(i)
+        @global_names = []
+        @global_graph = graph = DOT::DOTDigraph.new('name' => 'TopLevel',
+                                    'fontname' => FONT,
+                                    'fontsize' => '8',
+                                    'bgcolor'  => 'lightcyan1',
+                                    'compound' => 'true')
+        
+        # it's a little hack %) i'm too lazy to create a separate class
+        # for default node
+        graph << DOT::DOTNode.new('name' => 'node',
+                                  'fontname' => FONT,
+                                  'color' => 'black',
+                                  'fontsize' => 8)
+        
+        i.modules.each do |mod|
+          draw_module(mod, graph, true, i.file_relative_name)
+        end
+        add_classes(i, graph, i.file_relative_name)
+
+        i.diagram = convert_to_png("f_#{file_count}", graph)
+        
+        # now go through and document each top level class and
+        # module independently
+        i.modules.each_with_index do |mod, count|
+          @done_modules = {}
+          @local_names = find_names(mod)
+          @global_names = []
+
+          @global_graph = graph = DOT::DOTDigraph.new('name' => 'TopLevel',
+                                      'fontname' => FONT,
+                                      'fontsize' => '8',
+                                      'bgcolor'  => 'lightcyan1',
+                                      'compound' => 'true')
+
+          graph << DOT::DOTNode.new('name' => 'node',
+                                    'fontname' => FONT,
+                                    'color' => 'black',
+                                    'fontsize' => 8)
+          draw_module(mod, graph, true)
+          mod.diagram = convert_to_png("m_#{file_count}_#{count}", 
+                                       graph) 
+        end
+      end
+      $stderr.puts unless @options.quiet
+    end
+
+    #######
+    private
+    #######
+
+    def find_names(mod)
+      return [mod.full_name] + mod.classes.collect{|cl| cl.full_name} +
+        mod.modules.collect{|m| find_names(m)}.flatten
+    end
+
+    def find_full_name(name, mod)
+      full_name = name.dup
+      return full_name if @local_names.include?(full_name)
+      mod_path = mod.full_name.split('::')[0..-2]
+      unless mod_path.nil?
+        until mod_path.empty?
+          full_name = mod_path.pop + '::' + full_name
+          return full_name if @local_names.include?(full_name)
+        end
+      end
+      return name
+    end
+
+    def draw_module(mod, graph, toplevel = false, file = nil)
+      return if  @done_modules[mod.full_name] and not toplevel
+
+      @counter += 1
+      url = mod.http_url("classes")
+      m = DOT::DOTSubgraph.new('name' => "cluster_#{mod.full_name.gsub( /:/,'_' )}",
+                               'label' => mod.name,
+                               'fontname' => FONT,
+                               'color' => 'blue', 
+                               'style' => 'filled', 
+                               'URL'   => %{"#{url}"},
+                               'fillcolor' => toplevel ? 'palegreen1' : 'palegreen3')
+      
+      @done_modules[mod.full_name] = m
+      add_classes(mod, m, file)
+      graph << m
+
+      unless mod.includes.empty?
+        mod.includes.each do |m|
+          m_full_name = find_full_name(m.name, mod)
+          if @local_names.include?(m_full_name)
+            @global_graph << DOT::DOTEdge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
+                                      'to' => "#{mod.full_name.gsub( /:/,'_' )}",
+                                      'ltail' => "cluster_#{m_full_name.gsub( /:/,'_' )}",
+                                      'lhead' => "cluster_#{mod.full_name.gsub( /:/,'_' )}")
+          else
+            unless @global_names.include?(m_full_name)
+              path = m_full_name.split("::")
+              url = File.join('classes', *path) + ".html"
+              @global_graph << DOT::DOTNode.new('name' => "#{m_full_name.gsub( /:/,'_' )}",
+                                        'shape' => 'box',
+                                        'label' => "#{m_full_name}",
+                                        'URL'   => %{"#{url}"})
+              @global_names << m_full_name
+            end
+            @global_graph << DOT::DOTEdge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
+                                      'to' => "#{mod.full_name.gsub( /:/,'_' )}",
+                                      'lhead' => "cluster_#{mod.full_name.gsub( /:/,'_' )}")
+          end
+        end
+      end
+    end
+
+    def add_classes(container, graph, file = nil )
+
+      use_fileboxes = Options.instance.fileboxes
+
+      files = {}
+
+      # create dummy node (needed if empty and for module includes)
+      if container.full_name
+        graph << DOT::DOTNode.new('name'     => "#{container.full_name.gsub( /:/,'_' )}",
+                                  'label'    => "",
+                                  'width'  => (container.classes.empty? and 
+                                               container.modules.empty?) ? 
+                                  '0.75' : '0.01',
+                                  'height' => '0.01',
+                                  'shape' => 'plaintext')
+      end
+      container.classes.each_with_index do |cl, cl_index|
+        last_file = cl.in_files[-1].file_relative_name
+
+        if use_fileboxes && !files.include?(last_file)
+          @counter += 1
+          files[last_file] =
+            DOT::DOTSubgraph.new('name'     => "cluster_#{@counter}",
+                                 'label'    => "#{last_file}",
+                                 'fontname' => FONT,
+                                 'color'=>
+                                 last_file == file ? 'red' : 'black')
+        end
+
+        next if cl.name == 'Object' || cl.name[0,2] == "<<"
+
+        url = cl.http_url("classes")
+        
+        label = cl.name.dup
+        if use_fileboxes && cl.in_files.length > 1
+          label <<  '\n[' + 
+                        cl.in_files.collect {|i|
+                             i.file_relative_name 
+                        }.sort.join( '\n' ) +
+                    ']'
+        end 
+                
+        attrs = {
+          'name' => "#{cl.full_name.gsub( /:/, '_' )}",
+          'fontcolor' => 'black',
+          'style'=>'filled',
+          'color'=>'palegoldenrod',
+          'label' => label,
+          'shape' => 'ellipse',
+          'URL'   => %{"#{url}"}
+        }
+
+        c = DOT::DOTNode.new(attrs)
+        
+        if use_fileboxes
+          files[last_file].push c 
+        else
+          graph << c
+        end
+      end
+      
+      if use_fileboxes
+        files.each_value do |val|
+          graph << val
+        end
+      end
+      
+      unless container.classes.empty?
+        container.classes.each_with_index do |cl, cl_index|
+          cl.includes.each do |m|
+            m_full_name = find_full_name(m.name, cl)
+            if @local_names.include?(m_full_name)
+              @global_graph << DOT::DOTEdge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
+                                      'to' => "#{cl.full_name.gsub( /:/,'_' )}",
+                                      'ltail' => "cluster_#{m_full_name.gsub( /:/,'_' )}")
+            else
+              unless @global_names.include?(m_full_name)
+                path = m_full_name.split("::")
+                url = File.join('classes', *path) + ".html"
+                @global_graph << DOT::DOTNode.new('name' => "#{m_full_name.gsub( /:/,'_' )}",
+                                          'shape' => 'box',
+                                          'label' => "#{m_full_name}",
+                                          'URL'   => %{"#{url}"})
+                @global_names << m_full_name
+              end
+              @global_graph << DOT::DOTEdge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
+                                      'to' => "#{cl.full_name.gsub( /:/, '_')}")
+            end
+          end
+
+          sclass = cl.superclass
+          next if sclass.nil? || sclass == 'Object'
+          sclass_full_name = find_full_name(sclass,cl)
+          unless @local_names.include?(sclass_full_name) or @global_names.include?(sclass_full_name)
+            path = sclass_full_name.split("::")
+            url = File.join('classes', *path) + ".html"
+            @global_graph << DOT::DOTNode.new(
+                       'name' => "#{sclass_full_name.gsub( /:/, '_' )}",
+                       'label' => sclass_full_name,
+                       'URL'   => %{"#{url}"})
+            @global_names << sclass_full_name
+          end
+          @global_graph << DOT::DOTEdge.new('from' => "#{sclass_full_name.gsub( /:/,'_' )}",
+                                    'to' => "#{cl.full_name.gsub( /:/, '_')}")
+        end
+      end
+
+      container.modules.each do |submod|
+        draw_module(submod, graph)
+      end
+      
+    end
+
+    def convert_to_png(file_base, graph)
+      str = graph.to_s
+      return @diagram_cache[str] if @diagram_cache[str]
+      op_type = Options.instance.image_format
+      dotfile = File.join(DOT_PATH, file_base)
+      src = dotfile + ".dot"
+      dot = dotfile + "." + op_type
+
+      unless @options.quiet
+        $stderr.print "."
+        $stderr.flush
+      end
+
+      File.open(src, 'w+' ) do |f|
+        f << str << "\n"
+      end
+      
+      system "dot", "-T#{op_type}", src, "-o", dot
+
+      # Now construct the imagemap wrapper around
+      # that png
+
+      ret = wrap_in_image_map(src, dot)
+      @diagram_cache[str] = ret
+      return ret
+    end
+
+    # Extract the client-side image map from dot, and use it
+    # to generate the imagemap proper. Return the whole
+    # <map>..<img> combination, suitable for inclusion on
+    # the page
+
+    def wrap_in_image_map(src, dot)
+      res = %{<map id="map" name="map">\n}
+      dot_map = `dot -Tismap #{src}`
+      dot_map.each do |area|
+        unless area =~ /^rectangle \((\d+),(\d+)\) \((\d+),(\d+)\) ([\/\w.]+)\s*(.*)/
+          $stderr.puts "Unexpected output from dot:\n#{area}"
+          return nil
+        end
+        
+        xs, ys = [$1.to_i, $3.to_i], [$2.to_i, $4.to_i]
+        url, area_name = $5, $6
+
+        res <<  %{  <area shape="rect" coords="#{xs.min},#{ys.min},#{xs.max},#{ys.max}" }
+        res <<  %{     href="#{url}" alt="#{area_name}" />\n}
+      end
+      res << "</map>\n"
+#      map_file = src.sub(/.dot/, '.map')
+#      system("dot -Timap #{src} -o #{map_file}")
+      res << %{<img src="#{dot}" usemap="#map" border="0" alt="#{dot}">}
+      return res
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/dot/dot.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/dot/dot.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/dot/dot.rb	(revision 18425)
@@ -0,0 +1,255 @@
+module DOT
+
+    # these glogal vars are used to make nice graph source
+    $tab = '    '
+    $tab2 = $tab * 2
+
+    # if we don't like 4 spaces, we can change it any time
+    def change_tab( t )
+        $tab = t
+        $tab2 = t * 2
+    end
+
+    # options for node declaration
+    NODE_OPTS = [
+        'bgcolor',
+        'color',
+        'fontcolor',
+        'fontname',
+        'fontsize',
+        'height',
+        'width',
+        'label',
+        'layer',
+        'rank',
+        'shape',
+        'shapefile',
+        'style',
+        'URL',
+    ]
+
+    # options for edge declaration
+    EDGE_OPTS = [
+        'color',
+        'decorate',
+        'dir',
+        'fontcolor',
+        'fontname',
+        'fontsize',
+        'id',
+        'label',
+        'layer',
+        'lhead',
+        'ltail',
+        'minlen',
+        'style',
+        'weight'
+    ]
+
+    # options for graph declaration
+    GRAPH_OPTS = [
+        'bgcolor',
+        'center',
+        'clusterrank',
+        'color',
+        'compound',
+        'concentrate',
+        'fillcolor',
+        'fontcolor',
+        'fontname',
+        'fontsize',
+        'label',
+        'layerseq',
+        'margin',
+        'mclimit',
+        'nodesep',
+        'nslimit',
+        'ordering',
+        'orientation',
+        'page',
+        'rank',
+        'rankdir',
+        'ranksep',
+        'ratio',
+        'size',
+        'style',
+        'URL'
+    ]
+
+    # a root class for any element in dot notation
+    class DOTSimpleElement
+        attr_accessor :name
+
+        def initialize( params = {} )
+            @label = params['name'] ? params['name'] : ''
+        end
+
+        def to_s
+            @name
+        end
+    end
+
+    # an element that has options ( node, edge or graph )
+    class DOTElement < DOTSimpleElement
+        #attr_reader :parent
+        attr_accessor :name, :options
+
+        def initialize( params = {}, option_list = [] )
+            super( params )
+            @name = params['name'] ? params['name'] : nil
+            @parent = params['parent'] ? params['parent'] : nil
+            @options = {}
+            option_list.each{ |i|
+                @options[i] = params[i] if params[i]
+            }
+            @options['label'] ||= @name if @name != 'node'
+        end
+
+        def each_option
+            @options.each{ |i| yield i }
+        end
+
+        def each_option_pair
+            @options.each_pair{ |key, val| yield key, val }
+        end
+
+        #def parent=( thing )
+        #    @parent.delete( self ) if defined?( @parent ) and @parent
+        #    @parent = thing
+        #end
+    end
+
+
+    # this is used when we build nodes that have shape=record
+    # ports don't have options :)
+    class DOTPort < DOTSimpleElement
+        attr_accessor :label
+
+        def initialize( params = {} )
+            super( params )
+            @name = params['label'] ? params['label'] : ''
+        end
+        def to_s
+            ( @name && @name != "" ? "<#{@name}>" : "" ) + "#{@label}"
+        end
+    end
+
+    # node element
+    class DOTNode < DOTElement
+
+        def initialize( params = {}, option_list = NODE_OPTS )
+            super( params, option_list )
+            @ports = params['ports'] ? params['ports'] : []
+        end
+
+        def each_port
+            @ports.each{ |i| yield i }
+        end
+
+        def << ( thing )
+            @ports << thing
+        end
+
+        def push ( thing )
+            @ports.push( thing )
+        end
+
+        def pop
+            @ports.pop
+        end
+
+        def to_s( t = '' )
+
+            label = @options['shape'] != 'record' && @ports.length == 0 ?
+                @options['label'] ?
+                    t + $tab + "label = \"#{@options['label']}\"\n" :
+                    '' :
+                t + $tab + 'label = "' + " \\\n" +
+                t + $tab2 + "#{@options['label']}| \\\n" +
+                @ports.collect{ |i|
+                    t + $tab2 + i.to_s
+                }.join( "| \\\n" ) + " \\\n" +
+                t + $tab + '"' + "\n"
+
+            t + "#{@name} [\n" +
+            @options.to_a.collect{ |i|
+                i[1] && i[0] != 'label' ?
+                    t + $tab + "#{i[0]} = #{i[1]}" : nil
+            }.compact.join( ",\n" ) + ( label != '' ? ",\n" : "\n" ) +
+            label +
+            t + "]\n"
+        end
+    end
+
+    # subgraph element is the same to graph, but has another header in dot
+    # notation
+    class DOTSubgraph < DOTElement
+
+        def initialize( params = {}, option_list = GRAPH_OPTS )
+            super( params, option_list )
+            @nodes = params['nodes'] ? params['nodes'] : []
+            @dot_string = 'subgraph'
+        end
+
+        def each_node
+            @nodes.each{ |i| yield i }
+        end
+
+        def << ( thing )
+            @nodes << thing
+        end
+
+        def push( thing )
+            @nodes.push( thing )
+        end
+
+        def pop
+            @nodes.pop
+        end
+
+        def to_s( t = '' )
+          hdr = t + "#{@dot_string} #{@name} {\n"
+
+          options = @options.to_a.collect{ |name, val|
+            val && name != 'label' ?
+            t + $tab + "#{name} = #{val}" :
+              name ? t + $tab + "#{name} = \"#{val}\"" : nil
+          }.compact.join( "\n" ) + "\n"
+
+          nodes = @nodes.collect{ |i|
+            i.to_s( t + $tab )
+          }.join( "\n" ) + "\n"
+          hdr + options + nodes + t + "}\n"
+        end
+    end
+
+    # this is graph
+    class DOTDigraph < DOTSubgraph
+        def initialize( params = {}, option_list = GRAPH_OPTS )
+            super( params, option_list )
+            @dot_string = 'digraph'
+        end
+    end
+
+    # this is edge
+    class DOTEdge < DOTElement
+        attr_accessor :from, :to
+        def initialize( params = {}, option_list = EDGE_OPTS )
+            super( params, option_list )
+            @from = params['from'] ? params['from'] : nil
+            @to = params['to'] ? params['to'] : nil
+        end
+
+        def to_s( t = '' )
+            t + "#{@from} -> #{to} [\n" +
+            @options.to_a.collect{ |i|
+                i[1] && i[0] != 'label' ?
+                    t + $tab + "#{i[0]} = #{i[1]}" :
+                    i[1] ? t + $tab + "#{i[0]} = \"#{i[1]}\"" : nil
+            }.compact.join( "\n" ) + "\n" + t + "]\n"
+        end
+    end
+end
+
+
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/chm_generator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/chm_generator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/chm_generator.rb	(revision 18425)
@@ -0,0 +1,112 @@
+require 'rdoc/generators/html_generator'
+
+module Generators
+
+  class CHMGenerator < HTMLGenerator
+
+    HHC_PATH = "c:/Program Files/HTML Help Workshop/hhc.exe"
+
+    # Standard generator factory
+    def CHMGenerator.for(options)
+      CHMGenerator.new(options)
+    end
+
+    
+    def initialize(*args)
+      super
+      @op_name = @options.op_name || "rdoc"
+      check_for_html_help_workshop
+    end
+
+    def check_for_html_help_workshop
+      stat = File.stat(HHC_PATH)
+    rescue
+      $stderr <<
+	"\n.chm output generation requires that Microsoft's Html Help\n" <<
+	"Workshop is installed. RDoc looks for it in:\n\n    " <<
+	HHC_PATH <<
+	"\n\nYou can download a copy for free from:\n\n" <<
+	"    http://msdn.microsoft.com/library/default.asp?" <<
+	"url=/library/en-us/htmlhelp/html/hwMicrosoftHTMLHelpDownloads.asp\n\n"
+      
+      exit 99
+    end
+
+    # Generate the html as normal, then wrap it
+    # in a help project
+    def generate(info)
+      super
+      @project_name = @op_name + ".hhp"
+      create_help_project
+    end
+
+    # The project contains the project file, a table of contents
+    # and an index
+    def create_help_project
+      create_project_file
+      create_contents_and_index
+      compile_project
+    end
+
+    # The project file links together all the various
+    # files that go to make up the help.
+
+    def create_project_file
+      template = TemplatePage.new(RDoc::Page::HPP_FILE)
+      values = { "title" => @options.title, "opname" => @op_name }
+      files = []
+      @files.each do |f|
+	files << { "html_file_name" => f.path }
+      end
+
+      values['all_html_files'] = files
+      
+      File.open(@project_name, "w") do |f|
+        template.write_html_on(f, values)
+      end
+    end
+
+    # The contents is a list of all files and modules.
+    # For each we include  as sub-entries the list
+    # of methods they contain. As we build the contents
+    # we also build an index file
+
+    def create_contents_and_index
+      contents = []
+      index    = []
+
+      (@files+@classes).sort.each do |entry|
+	content_entry = { "c_name" => entry.name, "ref" => entry.path }
+	index << { "name" => entry.name, "aref" => entry.path }
+
+	internals = []
+
+	methods = entry.build_method_summary_list(entry.path)
+
+	content_entry["methods"] = methods unless methods.empty?
+        contents << content_entry
+	index.concat methods
+      end
+
+      values = { "contents" => contents }
+      template = TemplatePage.new(RDoc::Page::CONTENTS)
+      File.open("contents.hhc", "w") do |f|
+	template.write_html_on(f, values)
+      end
+
+      values = { "index" => index }
+      template = TemplatePage.new(RDoc::Page::CHM_INDEX)
+      File.open("index.hhk", "w") do |f|
+	template.write_html_on(f, values)
+      end      
+    end
+
+    # Invoke the windows help compiler to compiler the project
+    def compile_project
+      system(HHC_PATH, @project_name)
+    end
+
+  end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/html_generator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/html_generator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/html_generator.rb	(revision 18425)
@@ -0,0 +1,1509 @@
+# We're responsible for generating all the HTML files
+# from the object tree defined in code_objects.rb. We
+# generate:
+#
+# [files]   an html file for each input file given. These
+#           input files appear as objects of class
+#           TopLevel
+#
+# [classes] an html file for each class or module encountered.
+#           These classes are not grouped by file: if a file
+#           contains four classes, we'll generate an html
+#           file for the file itself, and four html files 
+#           for the individual classes. 
+#
+# [indices] we generate three indices for files, classes,
+#           and methods. These are displayed in a browser
+#           like window with three index panes across the
+#           top and the selected description below
+#
+# Method descriptions appear in whatever entity (file, class,
+# or module) that contains them.
+#
+# We generate files in a structure below a specified subdirectory,
+# normally +doc+.
+#
+#  opdir
+#     |
+#     |___ files
+#     |       |__  per file summaries
+#     |
+#     |___ classes
+#             |__ per class/module descriptions
+#
+# HTML is generated using the Template class.
+#
+
+require 'ftools'
+
+require 'rdoc/options'
+require 'rdoc/template'
+require 'rdoc/markup/simple_markup'
+require 'rdoc/markup/simple_markup/to_html'
+require 'cgi'
+
+module Generators
+
+  # Name of sub-direcories that hold file and class/module descriptions
+
+  FILE_DIR  = "files"
+  CLASS_DIR = "classes"
+  CSS_NAME  = "rdoc-style.css"
+  
+
+  ##
+  # Build a hash of all items that can be cross-referenced.
+  # This is used when we output required and included names: 
+  # if the names appear in this hash, we can generate
+  # an html cross reference to the appropriate description.
+  # We also use this when parsing comment blocks: any decorated 
+  # words matching an entry in this list are hyperlinked.
+
+  class AllReferences
+    @@refs = {}
+    
+    def AllReferences::reset
+      @@refs = {}
+    end
+
+    def AllReferences.add(name, html_class)
+      @@refs[name] = html_class
+    end
+
+    def AllReferences.[](name)
+      @@refs[name]
+    end
+
+    def AllReferences.keys
+      @@refs.keys
+    end
+  end
+
+
+  ##
+  # Subclass of the SM::ToHtml class that supports looking
+  # up words in the AllReferences list. Those that are
+  # found (like AllReferences in this comment) will
+  # be hyperlinked
+
+  class HyperlinkHtml < SM::ToHtml
+    # We need to record the html path of our caller so we can generate
+    # correct relative paths for any hyperlinks that we find
+    def initialize(from_path, context)
+      super()
+      @from_path = from_path
+
+      @parent_name = context.parent_name
+      @parent_name += "::" if @parent_name
+      @context = context
+    end
+
+    # We're invoked when any text matches the CROSSREF pattern
+    # (defined in MarkUp). If we fine the corresponding reference,
+    # generate a hyperlink. If the name we're looking for contains
+    # no punctuation, we look for it up the module/class chain. For
+    # example, HyperlinkHtml is found, even without the Generators::
+    # prefix, because we look for it in module Generators first.
+
+    def handle_special_CROSSREF(special)
+      name = special.text
+      if name[0,1] == '#'
+        lookup = name[1..-1]
+        name = lookup unless Options.instance.show_hash
+      else
+        lookup = name
+      end
+
+      # Find class, module, or method in class or module.
+      if /([A-Z]\w*)[.\#](\w+[!?=]?)/ =~ lookup
+        container = $1
+        method = $2
+        ref = @context.find_symbol(container, method)
+      elsif /([A-Za-z]\w*)[.\#](\w+(\([\.\w+\*\/\+\-\=\<\>]+\))?)/ =~ lookup
+        container = $1
+        method = $2
+        ref = @context.find_symbol(container, method)
+      else
+        ref = @context.find_symbol(lookup)
+      end
+
+      if ref and ref.document_self
+        "<a href=\"#{ref.as_href(@from_path)}\">#{name}</a>"
+      else
+        name
+      end
+    end
+
+
+    # Generate a hyperlink for url, labeled with text. Handle the
+    # special cases for img: and link: described under handle_special_HYPEDLINK
+    def gen_url(url, text)
+      if url =~ /([A-Za-z]+):(.*)/
+        type = $1
+        path = $2
+      else
+        type = "http"
+        path = url
+        url  = "http://#{url}"
+      end
+
+      if type == "link"
+        if path[0,1] == '#'     # is this meaningful?
+          url = path
+        else
+          url = HTMLGenerator.gen_url(@from_path, path)
+        end
+      end
+
+      if (type == "http" || type == "link") && 
+          url =~ /\.(gif|png|jpg|jpeg|bmp)$/
+
+        "<img src=\"#{url}\" />"
+      else
+        "<a href=\"#{url}\">#{text.sub(%r{^#{type}:/*}, '')}</a>"
+      end
+    end
+
+    # And we're invoked with a potential external hyperlink mailto:
+    # just gets inserted. http: links are checked to see if they
+    # reference an image. If so, that image gets inserted using an
+    # <img> tag. Otherwise a conventional <a href> is used.  We also
+    # support a special type of hyperlink, link:, which is a reference
+    # to a local file whose path is relative to the --op directory.
+
+    def handle_special_HYPERLINK(special)
+      url = special.text
+      gen_url(url, url)
+    end
+
+    # HEre's a hypedlink where the label is different to the URL
+    #  <label>[url]
+    #
+    
+    def handle_special_TIDYLINK(special)
+      text = special.text
+#      unless text =~ /(\S+)\[(.*?)\]/
+      unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/ 
+        return text
+      end
+      label = $1
+      url   = $2
+      gen_url(url, label)
+    end
+
+  end
+
+
+  
+  #####################################################################
+  #
+  # Handle common markup tasks for the various Html classes
+  #
+
+  module MarkUp
+
+    # Convert a string in markup format into HTML. We keep a cached
+    # SimpleMarkup object lying around after the first time we're
+    # called per object.
+
+    def markup(str, remove_para=false)
+      return '' unless str
+      unless defined? @markup
+        @markup = SM::SimpleMarkup.new
+
+        # class names, variable names, or instance variables
+        @markup.add_special(/(
+                               \w+(::\w+)*[.\#]\w+(\([\.\w+\*\/\+\-\=\<\>]+\))?  # A::B.meth(**) (for operator in Fortran95)
+                             | \#\w+(\([.\w\*\/\+\-\=\<\>]+\))?  #  meth(**) (for operator in Fortran95)
+                             | \b([A-Z]\w*(::\w+)*[.\#]\w+)  #    A::B.meth
+                             | \b([A-Z]\w+(::\w+)*)       #    A::B..
+                             | \#\w+[!?=]?                #    #meth_name 
+                             | \b\w+([_\/\.]+\w+)*[!?=]?  #    meth_name
+                             )/x, 
+                            :CROSSREF)
+
+        # external hyperlinks
+        @markup.add_special(/((link:|https?:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK)
+
+        # and links of the form  <text>[<url>]
+        @markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\.\S+?\])/, :TIDYLINK)
+#        @markup.add_special(/\b(\S+?\[\S+?\.\S+?\])/, :TIDYLINK)
+
+      end
+      unless defined? @html_formatter
+        @html_formatter = HyperlinkHtml.new(self.path, self)
+      end
+
+      # Convert leading comment markers to spaces, but only
+      # if all non-blank lines have them
+
+      if str =~ /^(?>\s*)[^\#]/
+        content = str
+      else
+        content = str.gsub(/^\s*(#+)/)  { $1.tr('#',' ') }
+      end
+
+      res = @markup.convert(content, @html_formatter)
+      if remove_para
+        res.sub!(/^<p>/, '')
+        res.sub!(/<\/p>$/, '')
+      end
+      res
+    end
+
+    # Qualify a stylesheet URL; if if +css_name+ does not begin with '/' or
+    # 'http[s]://', prepend a prefix relative to +path+. Otherwise, return it
+    # unmodified.
+
+    def style_url(path, css_name=nil)
+#      $stderr.puts "style_url( #{path.inspect}, #{css_name.inspect} )"
+      css_name ||= CSS_NAME
+      if %r{^(https?:/)?/} =~ css_name
+        return css_name
+      else
+        return HTMLGenerator.gen_url(path, css_name)
+      end
+    end
+
+    # Build a webcvs URL with the given 'url' argument. URLs with a '%s' in them
+    # get the file's path sprintfed into them; otherwise they're just catenated
+    # together.
+
+    def cvs_url(url, full_path)
+      if /%s/ =~ url
+        return sprintf( url, full_path )
+      else
+        return url + full_path
+      end
+    end
+  end
+
+
+  #####################################################################
+  #
+  # A Context is built by the parser to represent a container: contexts
+  # hold classes, modules, methods, require lists and include lists.
+  # ClassModule and TopLevel are the context objects we process here
+  # 
+  class ContextUser
+
+    include MarkUp
+
+    attr_reader :context
+    
+    def initialize(context, options)
+      @context = context
+      @options = options
+    end
+      
+    # convenience method to build a hyperlink
+    def href(link, cls, name)
+      %{<a href="#{link}" class="#{cls}">#{name}</a>} #"
+    end
+
+    # return a reference to outselves to be used as an href=
+    # the form depends on whether we're all in one file
+    # or in multiple files
+
+    def as_href(from_path)
+      if @options.all_one_file
+        "#" + path
+      else
+        HTMLGenerator.gen_url(from_path, path)
+      end
+    end
+
+    # Create a list of HtmlMethod objects for each method
+    # in the corresponding context object. If the @options.show_all
+    # variable is set (corresponding to the <tt>--all</tt> option,
+    # we include all methods, otherwise just the public ones.
+
+    def collect_methods
+      list = @context.method_list
+      unless @options.show_all
+        list = list.find_all {|m| m.visibility == :public || m.visibility == :protected || m.force_documentation }
+      end
+      @methods = list.collect {|m| HtmlMethod.new(m, self, @options) }
+    end
+
+    # Build a summary list of all the methods in this context
+    def build_method_summary_list(path_prefix="")
+      collect_methods unless @methods
+      meths = @methods.sort
+      res = []
+      meths.each do |meth|
+	res << {
+          "name" => CGI.escapeHTML(meth.name),
+          "aref" => "#{path_prefix}\##{meth.aref}" 
+        }
+      end
+      res
+    end
+
+
+    # Build a list of aliases for which we couldn't find a
+    # corresponding method
+    def build_alias_summary_list(section)
+      values = []
+      @context.aliases.each do |al|
+        next unless al.section == section
+        res = {
+          'old_name' => al.old_name,
+          'new_name' => al.new_name,
+        }
+        if al.comment && !al.comment.empty?
+          res['desc'] = markup(al.comment, true)
+        end
+        values << res
+      end
+      values
+    end
+    
+    # Build a list of constants
+    def build_constants_summary_list(section)
+      values = []
+      @context.constants.each do |co|
+        next unless co.section == section
+        res = {
+          'name'  => co.name,
+          'value' => CGI.escapeHTML(co.value)
+        }
+        res['desc'] = markup(co.comment, true) if co.comment && !co.comment.empty?
+        values << res
+      end
+      values
+    end
+    
+    def build_requires_list(context)
+      potentially_referenced_list(context.requires) {|fn| [fn + ".rb"] }
+    end
+
+    def build_include_list(context)
+      potentially_referenced_list(context.includes)
+    end
+
+    # Build a list from an array of <i>Htmlxxx</i> items. Look up each
+    # in the AllReferences hash: if we find a corresponding entry,
+    # we generate a hyperlink to it, otherwise just output the name.
+    # However, some names potentially need massaging. For example,
+    # you may require a Ruby file without the .rb extension,
+    # but the file names we know about may have it. To deal with
+    # this, we pass in a block which performs the massaging,
+    # returning an array of alternative names to match
+
+    def potentially_referenced_list(array)
+      res = []
+      array.each do |i|
+        ref = AllReferences[i.name] 
+#         if !ref
+#           container = @context.parent
+#           while !ref && container
+#             name = container.name + "::" + i.name
+#             ref = AllReferences[name] 
+#             container = container.parent
+#           end
+#         end
+
+        ref = @context.find_symbol(i.name)
+        ref = ref.viewer if ref
+
+        if !ref && block_given?
+          possibles = yield(i.name)
+          while !ref and !possibles.empty?
+            ref = AllReferences[possibles.shift]
+          end
+        end
+        h_name = CGI.escapeHTML(i.name)
+        if ref and ref.document_self
+          path = url(ref.path)
+          res << { "name" => h_name, "aref" => path }
+        else
+          res << { "name" => h_name }
+        end
+      end
+      res
+    end
+
+    # Build an array of arrays of method details. The outer array has up
+    # to six entries, public, private, and protected for both class
+    # methods, the other for instance methods. The inner arrays contain
+    # a hash for each method
+
+    def build_method_detail_list(section)
+      outer = []
+
+      methods = @methods.sort
+      for singleton in [true, false]
+        for vis in [ :public, :protected, :private ] 
+          res = []
+          methods.each do |m|
+            if m.section == section and
+                m.document_self and 
+                m.visibility == vis and 
+                m.singleton == singleton
+              row = {}
+              if m.call_seq
+                row["callseq"] = m.call_seq.gsub(/->/, '&rarr;')
+              else
+                row["name"]        = CGI.escapeHTML(m.name)
+                row["params"]      = m.params
+              end
+              desc = m.description.strip
+              row["m_desc"]      = desc unless desc.empty?
+              row["aref"]        = m.aref
+              row["visibility"]  = m.visibility.to_s
+
+              alias_names = []
+              m.aliases.each do |other|
+                if other.viewer   # won't be if the alias is private
+                  alias_names << {
+                    'name' => other.name,
+                    'aref'  => other.viewer.as_href(path)
+                  } 
+                end
+              end
+              unless alias_names.empty?
+                row["aka"] = alias_names
+              end
+
+              if @options.inline_source
+                code = m.source_code
+                row["sourcecode"] = code if code
+              else
+                code = m.src_url
+                if code
+                  row["codeurl"] = code
+                  row["imgurl"]  = m.img_url
+                end
+              end
+              res << row
+            end
+          end
+          if res.size > 0 
+            outer << {
+              "type"    => vis.to_s.capitalize,
+              "category"    => singleton ? "Class" : "Instance",
+              "methods" => res
+            }
+          end
+        end
+      end
+      outer
+    end
+
+    # Build the structured list of classes and modules contained
+    # in this context. 
+
+    def build_class_list(level, from, section, infile=nil)
+      res = ""
+      prefix = "&nbsp;&nbsp;::" * level;
+
+      from.modules.sort.each do |mod|
+        next unless mod.section == section
+        next if infile && !mod.defined_in?(infile)
+        if mod.document_self
+          res << 
+            prefix <<
+            "Module " <<
+            href(url(mod.viewer.path), "link", mod.full_name) <<
+            "<br />\n" <<
+            build_class_list(level + 1, mod, section, infile)
+        end
+      end
+
+      from.classes.sort.each do |cls|
+        next unless cls.section == section
+        next if infile && !cls.defined_in?(infile)
+        if cls.document_self
+          res      <<
+            prefix << 
+            "Class " <<
+            href(url(cls.viewer.path), "link", cls.full_name) <<
+            "<br />\n" <<
+            build_class_list(level + 1, cls, section, infile)
+        end
+      end
+
+      res
+    end
+    
+    def url(target)
+      HTMLGenerator.gen_url(path, target)
+    end
+
+    def aref_to(target)
+      if @options.all_one_file
+        "#" + target
+      else
+        url(target)
+      end
+    end
+
+    def document_self
+      @context.document_self
+    end
+
+    def diagram_reference(diagram)
+      res = diagram.gsub(/((?:src|href)=")(.*?)"/) {
+        $1 + url($2) + '"'
+      }
+      res
+    end
+
+
+    # Find a symbol in ourselves or our parent
+    def find_symbol(symbol, method=nil)
+      res = @context.find_symbol(symbol, method)
+      if res
+        res = res.viewer
+      end
+      res
+    end
+
+    # create table of contents if we contain sections
+      
+    def add_table_of_sections
+      toc = []
+      @context.sections.each do |section|
+        if section.title
+          toc << {
+            'secname' => section.title,
+            'href'    => section.sequence
+          }
+        end
+      end
+      
+      @values['toc'] = toc unless toc.empty?
+    end
+
+
+  end
+
+  #####################################################################
+  #
+  # Wrap a ClassModule context
+
+  class HtmlClass < ContextUser
+
+    attr_reader :path
+
+    def initialize(context, html_file, prefix, options)
+      super(context, options)
+
+      @html_file = html_file
+      @is_module = context.is_module?
+      @values    = {}
+
+      context.viewer = self
+
+      if options.all_one_file
+        @path = context.full_name
+      else
+        @path = http_url(context.full_name, prefix)
+      end
+
+      collect_methods
+
+      AllReferences.add(name, self)
+    end
+
+    # return the relative file name to store this class in,
+    # which is also its url
+    def http_url(full_name, prefix)
+      path = full_name.dup
+      if path['<<']
+        path.gsub!(/<<\s*(\w*)/) { "from-#$1" }
+      end
+      File.join(prefix, path.split("::")) + ".html"
+    end
+
+
+    def name
+      @context.full_name
+    end
+
+    def parent_name
+      @context.parent.full_name
+    end
+
+    def index_name
+      name
+    end
+
+    def write_on(f)
+      value_hash
+      template = TemplatePage.new(RDoc::Page::BODY,
+                                      RDoc::Page::CLASS_PAGE,
+                                      RDoc::Page::METHOD_LIST)
+      template.write_html_on(f, @values)
+    end
+
+    def value_hash
+      class_attribute_values
+      add_table_of_sections
+
+      @values["charset"] = @options.charset
+      @values["style_url"] = style_url(path, @options.css)
+
+      d = markup(@context.comment)
+      @values["description"] = d unless d.empty?
+
+      ml = build_method_summary_list
+      @values["methods"] = ml unless ml.empty?
+
+      il = build_include_list(@context)
+      @values["includes"] = il unless il.empty?
+
+      @values["sections"] = @context.sections.map do |section|
+
+        secdata = {
+          "sectitle" => section.title,
+          "secsequence" => section.sequence,
+          "seccomment" => markup(section.comment)
+        }
+
+        al = build_alias_summary_list(section)
+        secdata["aliases"] = al unless al.empty?
+        
+        co = build_constants_summary_list(section)
+        secdata["constants"] = co unless co.empty?
+        
+        al = build_attribute_list(section)
+        secdata["attributes"] = al unless al.empty?
+        
+        cl = build_class_list(0, @context, section)
+        secdata["classlist"] = cl unless cl.empty?
+        
+        mdl = build_method_detail_list(section)
+        secdata["method_list"] = mdl unless mdl.empty?
+
+        secdata
+      end
+
+      @values
+    end
+
+    def build_attribute_list(section)
+      atts = @context.attributes.sort
+      res = []
+      atts.each do |att|
+        next unless att.section == section
+        if att.visibility == :public || att.visibility == :protected || @options.show_all
+          entry = {
+            "name"   => CGI.escapeHTML(att.name), 
+            "rw"     => att.rw, 
+            "a_desc" => markup(att.comment, true)
+          }
+          unless att.visibility == :public || att.visibility == :protected
+            entry["rw"] << "-"
+          end
+          res << entry
+        end
+      end
+      res
+    end
+
+    def class_attribute_values
+      h_name = CGI.escapeHTML(name)
+
+      @values["classmod"]  = @is_module ? "Module" : "Class"
+      @values["title"]     = "#{@values['classmod']}: #{h_name}"
+
+      c = @context
+      c = c.parent while c and !c.diagram
+      if c && c.diagram
+        @values["diagram"] = diagram_reference(c.diagram)
+      end
+
+      @values["full_name"] = h_name
+
+      parent_class = @context.superclass
+
+      if parent_class
+	@values["parent"] = CGI.escapeHTML(parent_class)
+
+	if parent_name
+	  lookup = parent_name + "::" + parent_class
+	else
+	  lookup = parent_class
+	end
+
+	parent_url = AllReferences[lookup] || AllReferences[parent_class]
+
+	if parent_url and parent_url.document_self
+	  @values["par_url"] = aref_to(parent_url.path)
+	end
+      end
+
+      files = []
+      @context.in_files.each do |f|
+        res = {}
+        full_path = CGI.escapeHTML(f.file_absolute_name)
+
+        res["full_path"]     = full_path
+        res["full_path_url"] = aref_to(f.viewer.path) if f.document_self
+
+        if @options.webcvs
+          res["cvsurl"] = cvs_url( @options.webcvs, full_path )
+        end
+
+        files << res
+      end
+
+      @values['infiles'] = files
+    end
+
+    def <=>(other)
+      self.name <=> other.name
+    end
+
+  end
+
+  #####################################################################
+  #
+  # Handles the mapping of a file's information to HTML. In reality,
+  # a file corresponds to a +TopLevel+ object, containing modules,
+  # classes, and top-level methods. In theory it _could_ contain
+  # attributes and aliases, but we ignore these for now.
+
+  class HtmlFile < ContextUser
+
+    attr_reader :path
+    attr_reader :name
+
+    def initialize(context, options, file_dir)
+      super(context, options)
+
+      @values = {}
+
+      if options.all_one_file
+        @path = filename_to_label
+      else
+        @path = http_url(file_dir)
+      end
+
+      @name = @context.file_relative_name
+
+      collect_methods
+      AllReferences.add(name, self)
+      context.viewer = self
+    end
+
+    def http_url(file_dir)
+      File.join(file_dir, @context.file_relative_name.tr('.', '_')) +
+        ".html"
+    end
+
+    def filename_to_label
+      @context.file_relative_name.gsub(/%|\/|\?|\#/) {|s| '%' + ("%x" % s[0]) }
+    end
+
+    def index_name
+      name
+    end
+
+    def parent_name
+      nil
+    end
+
+    def value_hash
+      file_attribute_values
+      add_table_of_sections
+
+      @values["charset"]   = @options.charset
+      @values["href"]      = path
+      @values["style_url"] = style_url(path, @options.css)
+
+      if @context.comment
+        d = markup(@context.comment)
+        @values["description"] = d if d.size > 0
+      end
+
+      ml = build_method_summary_list
+      @values["methods"] = ml unless ml.empty?
+
+      il = build_include_list(@context)
+      @values["includes"] = il unless il.empty?
+
+      rl = build_requires_list(@context)
+      @values["requires"] = rl unless rl.empty?
+
+      if @options.promiscuous
+        file_context = nil
+      else
+        file_context = @context
+      end
+
+
+      @values["sections"] = @context.sections.map do |section|
+
+        secdata = {
+          "sectitle" => section.title,
+          "secsequence" => section.sequence,
+          "seccomment" => markup(section.comment)
+        }
+
+        cl = build_class_list(0, @context, section, file_context)
+        @values["classlist"] = cl unless cl.empty?
+
+        mdl = build_method_detail_list(section)
+        secdata["method_list"] = mdl unless mdl.empty?
+
+        al = build_alias_summary_list(section)
+        secdata["aliases"] = al unless al.empty?
+        
+        co = build_constants_summary_list(section)
+        @values["constants"] = co unless co.empty?
+
+        secdata
+      end
+      
+      @values
+    end
+    
+    def write_on(f)
+      value_hash
+      template = TemplatePage.new(RDoc::Page::BODY,
+                                  RDoc::Page::FILE_PAGE,
+                                  RDoc::Page::METHOD_LIST)
+      template.write_html_on(f, @values)
+    end
+
+    def file_attribute_values
+      full_path = @context.file_absolute_name
+      short_name = File.basename(full_path)
+      
+      @values["title"] = CGI.escapeHTML("File: #{short_name}")
+
+      if @context.diagram
+        @values["diagram"] = diagram_reference(@context.diagram)
+      end
+
+      @values["short_name"]   = CGI.escapeHTML(short_name)
+      @values["full_path"]    = CGI.escapeHTML(full_path)
+      @values["dtm_modified"] = @context.file_stat.mtime.to_s
+
+      if @options.webcvs
+        @values["cvsurl"] = cvs_url( @options.webcvs, @values["full_path"] )
+      end
+    end
+
+    def <=>(other)
+      self.name <=> other.name
+    end
+  end
+
+  #####################################################################
+
+  class HtmlMethod
+    include MarkUp
+
+    attr_reader :context
+    attr_reader :src_url
+    attr_reader :img_url
+    attr_reader :source_code
+
+    @@seq = "M000000"
+
+    @@all_methods = []
+
+    def HtmlMethod::reset
+      @@all_methods = []
+    end
+
+    def initialize(context, html_class, options)
+      @context    = context
+      @html_class = html_class
+      @options    = options
+      @@seq       = @@seq.succ
+      @seq        = @@seq
+      @@all_methods << self
+
+      context.viewer = self
+
+      if (ts = @context.token_stream)
+        @source_code = markup_code(ts)
+        unless @options.inline_source
+          @src_url = create_source_code_file(@source_code)
+          @img_url = HTMLGenerator.gen_url(path, 'source.png')
+        end
+      end
+
+      AllReferences.add(name, self)
+    end
+    
+    # return a reference to outselves to be used as an href=
+    # the form depends on whether we're all in one file
+    # or in multiple files
+
+    def as_href(from_path)
+      if @options.all_one_file
+        "#" + path
+      else
+        HTMLGenerator.gen_url(from_path, path)
+      end
+    end
+
+    def name
+      @context.name
+    end
+
+    def section
+      @context.section
+    end
+
+    def index_name
+      "#{@context.name} (#{@html_class.name})"
+    end
+
+    def parent_name
+      if @context.parent.parent
+        @context.parent.parent.full_name
+      else
+        nil
+      end
+    end
+
+    def aref
+      @seq
+    end
+
+    def path
+      if @options.all_one_file
+	aref
+      else
+	@html_class.path + "#" + aref
+      end
+    end
+
+    def description
+      markup(@context.comment)
+    end
+
+    def visibility
+      @context.visibility
+    end
+
+    def singleton
+      @context.singleton
+    end
+
+    def call_seq
+      cs = @context.call_seq
+      if cs
+        cs.gsub(/\n/, "<br />\n")
+      else
+        nil
+      end
+    end
+
+    def params
+      # params coming from a call-seq in 'C' will start with the
+      # method name
+      p = @context.params
+      if p !~ /^\w/
+        p = @context.params.gsub(/\s*\#.*/, '')
+        p = p.tr("\n", " ").squeeze(" ")
+        p = "(" + p + ")" unless p[0] == ?(
+        
+        if (block = @context.block_params)
+         # If this method has explicit block parameters, remove any
+         # explicit &block
+
+         p.sub!(/,?\s*&\w+/, '')
+
+          block.gsub!(/\s*\#.*/, '')
+          block = block.tr("\n", " ").squeeze(" ")
+          if block[0] == ?(
+            block.sub!(/^\(/, '').sub!(/\)/, '')
+          end
+          p << " {|#{block.strip}| ...}"
+        end
+      end
+      CGI.escapeHTML(p)
+    end
+    
+    def create_source_code_file(code_body)
+      meth_path = @html_class.path.sub(/\.html$/, '.src')
+      File.makedirs(meth_path)
+      file_path = File.join(meth_path, @seq) + ".html"
+
+      template = TemplatePage.new(RDoc::Page::SRC_PAGE)
+      File.open(file_path, "w") do |f|
+        values = {
+          'title'     => CGI.escapeHTML(index_name),
+          'code'      => code_body,
+          'style_url' => style_url(file_path, @options.css),
+          'charset'   => @options.charset
+        }
+        template.write_html_on(f, values)
+      end
+      HTMLGenerator.gen_url(path, file_path)
+    end
+
+    def HtmlMethod.all_methods
+      @@all_methods
+    end
+
+    def <=>(other)
+      @context <=> other.context
+    end
+
+    ##
+    # Given a sequence of source tokens, mark up the source code
+    # to make it look purty.
+
+
+    def markup_code(tokens)
+      src = ""
+      tokens.each do |t|
+        next unless t
+        #    p t.class
+#        style = STYLE_MAP[t.class]
+        style = case t
+                when RubyToken::TkCONSTANT then "ruby-constant"
+                when RubyToken::TkKW       then "ruby-keyword kw"
+                when RubyToken::TkIVAR     then "ruby-ivar"
+                when RubyToken::TkOp       then "ruby-operator"
+                when RubyToken::TkId       then "ruby-identifier"
+                when RubyToken::TkNode     then "ruby-node"
+                when RubyToken::TkCOMMENT  then "ruby-comment cmt"
+                when RubyToken::TkREGEXP   then "ruby-regexp re"
+                when RubyToken::TkSTRING   then "ruby-value str"
+                when RubyToken::TkVal      then "ruby-value"
+                else
+                    nil
+                end
+
+        text = CGI.escapeHTML(t.text)
+
+        if style
+          src << "<span class=\"#{style}\">#{text}</span>"
+        else
+          src << text
+        end
+      end
+
+      add_line_numbers(src) if Options.instance.include_line_numbers
+      src
+    end
+
+    # we rely on the fact that the first line of a source code
+    # listing has 
+    #    # File xxxxx, line dddd
+
+    def add_line_numbers(src)
+      if src =~ /\A.*, line (\d+)/
+        first = $1.to_i - 1
+        last  = first + src.count("\n")
+        size = last.to_s.length
+        real_fmt = "%#{size}d: "
+        fmt = " " * (size+2)
+        src.gsub!(/^/) do
+          res = sprintf(fmt, first) 
+          first += 1
+          fmt = real_fmt
+          res
+        end
+      end
+    end
+
+    def document_self
+      @context.document_self
+    end
+
+    def aliases
+      @context.aliases
+    end
+
+    def find_symbol(symbol, method=nil)
+      res = @context.parent.find_symbol(symbol, method)
+      if res
+        res = res.viewer
+      end
+      res
+    end
+  end
+
+  #####################################################################
+
+  class HTMLGenerator
+
+    include MarkUp
+
+    ##
+    # convert a target url to one that is relative to a given
+    # path
+    
+    def HTMLGenerator.gen_url(path, target)
+      from          = File.dirname(path)
+      to, to_file   = File.split(target)
+      
+      from = from.split("/")
+      to   = to.split("/")
+      
+      while from.size > 0 and to.size > 0 and from[0] == to[0]
+        from.shift
+        to.shift
+      end
+      
+      from.fill("..")
+      from.concat(to)
+      from << to_file
+      File.join(*from)
+    end
+
+    # Generators may need to return specific subclasses depending
+    # on the options they are passed. Because of this
+    # we create them using a factory
+
+    def HTMLGenerator.for(options)
+      AllReferences::reset
+      HtmlMethod::reset
+
+      if options.all_one_file
+        HTMLGeneratorInOne.new(options)
+      else
+        HTMLGenerator.new(options)
+      end
+    end
+
+    class <<self
+      protected :new
+    end
+
+    # Set up a new HTML generator. Basically all we do here is load
+    # up the correct output temlate
+
+    def initialize(options) #:not-new:
+      @options    = options
+      load_html_template
+    end
+
+
+    ##
+    # Build the initial indices and output objects
+    # based on an array of TopLevel objects containing
+    # the extracted information. 
+
+    def generate(toplevels)
+      @toplevels  = toplevels
+      @files      = []
+      @classes    = []
+
+      write_style_sheet
+      gen_sub_directories()
+      build_indices
+      generate_html
+    end
+
+    private
+
+    ##
+    # Load up the HTML template specified in the options.
+    # If the template name contains a slash, use it literally
+    #
+    def load_html_template
+      template = @options.template
+      unless template =~ %r{/|\\}
+        template = File.join("rdoc/generators/template",
+                             @options.generator.key, template)
+      end
+      require template
+      extend RDoc::Page
+    rescue LoadError
+      $stderr.puts "Could not find HTML template '#{template}'"
+      exit 99
+    end
+
+    ##
+    # Write out the style sheet used by the main frames
+    #
+    
+    def write_style_sheet
+      template = TemplatePage.new(RDoc::Page::STYLE)
+      unless @options.css
+        File.open(CSS_NAME, "w") do |f|
+          values = { "fonts" => RDoc::Page::FONTS }
+          template.write_html_on(f, values)
+        end
+      end
+    end
+
+    ##
+    # See the comments at the top for a description of the
+    # directory structure
+
+    def gen_sub_directories
+      File.makedirs(FILE_DIR, CLASS_DIR)
+    rescue 
+      $stderr.puts $!.message
+      exit 1
+    end
+
+    ##
+    # Generate:
+    #
+    # * a list of HtmlFile objects for each TopLevel object.
+    # * a list of HtmlClass objects for each first level
+    #   class or module in the TopLevel objects
+    # * a complete list of all hyperlinkable terms (file,
+    #   class, module, and method names)
+
+    def build_indices
+
+      @toplevels.each do |toplevel|
+        @files << HtmlFile.new(toplevel, @options, FILE_DIR)
+      end
+
+      RDoc::TopLevel.all_classes_and_modules.each do |cls|
+        build_class_list(cls, @files[0], CLASS_DIR)
+      end
+    end
+
+    def build_class_list(from, html_file, class_dir)
+      @classes << HtmlClass.new(from, html_file, class_dir, @options)
+      from.each_classmodule do |mod|
+        build_class_list(mod, html_file, class_dir)
+      end
+    end
+
+    ##
+    # Generate all the HTML
+    #
+    def generate_html
+      # the individual descriptions for files and classes
+      gen_into(@files)
+      gen_into(@classes)
+      # and the index files
+      gen_file_index
+      gen_class_index
+      gen_method_index
+      gen_main_index
+      
+      # this method is defined in the template file
+      write_extra_pages if defined? write_extra_pages
+    end
+
+    def gen_into(list)
+      list.each do |item|
+        if item.document_self
+          op_file = item.path
+          File.makedirs(File.dirname(op_file))
+          File.open(op_file, "w") { |file| item.write_on(file) }
+        end
+      end
+
+    end
+
+    def gen_file_index
+      gen_an_index(@files, 'Files', 
+                   RDoc::Page::FILE_INDEX, 
+                   "fr_file_index.html")
+    end
+
+    def gen_class_index
+      gen_an_index(@classes, 'Classes',
+                   RDoc::Page::CLASS_INDEX,
+                   "fr_class_index.html")
+    end
+
+    def gen_method_index
+      gen_an_index(HtmlMethod.all_methods, 'Methods', 
+                   RDoc::Page::METHOD_INDEX,
+                   "fr_method_index.html")
+    end
+
+    
+    def gen_an_index(collection, title, template, filename)
+      template = TemplatePage.new(RDoc::Page::FR_INDEX_BODY, template)
+      res = []
+      collection.sort.each do |f|
+        if f.document_self
+          res << { "href" => f.path, "name" => f.index_name }
+        end
+      end
+
+      values = {
+        "entries"    => res,
+        'list_title' => CGI.escapeHTML(title),
+        'index_url'  => main_url,
+        'charset'    => @options.charset,
+        'style_url'  => style_url('', @options.css),
+      }
+
+      File.open(filename, "w") do |f|
+        template.write_html_on(f, values)
+      end
+    end
+
+    # The main index page is mostly a template frameset, but includes
+    # the initial page. If the <tt>--main</tt> option was given,
+    # we use this as our main page, otherwise we use the
+    # first file specified on the command line.
+
+    def gen_main_index
+      template = TemplatePage.new(RDoc::Page::INDEX)
+      File.open("index.html", "w") do |f|
+        values = {
+          "initial_page" => main_url,
+          'title'        => CGI.escapeHTML(@options.title),
+          'charset'      => @options.charset
+        }
+        if @options.inline_source
+          values['inline_source'] = true
+        end
+        template.write_html_on(f, values)
+      end
+    end
+
+    # return the url of the main page
+    def main_url
+      main_page = @options.main_page
+      ref = nil
+      if main_page
+        ref = AllReferences[main_page]
+        if ref
+          ref = ref.path
+        else
+          $stderr.puts "Could not find main page #{main_page}"
+        end
+      end
+
+      unless ref
+        for file in @files
+          if file.document_self
+            ref = file.path 
+            break
+          end
+        end
+      end
+
+      unless ref
+        $stderr.puts "Couldn't find anything to document"
+        $stderr.puts "Perhaps you've used :stopdoc: in all classes"
+        exit(1)
+      end
+
+      ref
+    end
+
+
+  end
+
+
+  ######################################################################
+
+
+  class HTMLGeneratorInOne < HTMLGenerator
+
+    def initialize(*args)
+      super
+    end
+
+    ##
+    # Build the initial indices and output objects
+    # based on an array of TopLevel objects containing
+    # the extracted information. 
+
+    def generate(info)
+      @toplevels  = info
+      @files      = []
+      @classes    = []
+      @hyperlinks = {}
+
+      build_indices
+      generate_xml
+    end
+
+
+    ##
+    # Generate:
+    #
+    # * a list of HtmlFile objects for each TopLevel object.
+    # * a list of HtmlClass objects for each first level
+    #   class or module in the TopLevel objects
+    # * a complete list of all hyperlinkable terms (file,
+    #   class, module, and method names)
+
+    def build_indices
+
+      @toplevels.each do |toplevel|
+        @files << HtmlFile.new(toplevel, @options, FILE_DIR)
+      end
+
+      RDoc::TopLevel.all_classes_and_modules.each do |cls|
+        build_class_list(cls, @files[0], CLASS_DIR)
+      end
+    end
+
+    def build_class_list(from, html_file, class_dir)
+      @classes << HtmlClass.new(from, html_file, class_dir, @options)
+      from.each_classmodule do |mod|
+        build_class_list(mod, html_file, class_dir)
+      end
+    end
+
+    ##
+    # Generate all the HTML. For the one-file case, we generate
+    # all the information in to one big hash
+    #
+    def generate_xml
+      values = { 
+        'charset' => @options.charset,
+        'files'   => gen_into(@files),
+        'classes' => gen_into(@classes),
+        'title'        => CGI.escapeHTML(@options.title),
+      }
+      
+      # this method is defined in the template file
+      write_extra_pages if defined? write_extra_pages
+
+      template = TemplatePage.new(RDoc::Page::ONE_PAGE)
+
+      if @options.op_name
+        opfile = File.open(@options.op_name, "w")
+      else
+        opfile = $stdout
+      end
+      template.write_html_on(opfile, values)
+    end
+
+    def gen_into(list)
+      res = []
+      list.each do |item|
+        res << item.value_hash
+      end
+      res
+    end
+
+    def gen_file_index
+      gen_an_index(@files, 'Files')
+    end
+
+    def gen_class_index
+      gen_an_index(@classes, 'Classes')
+    end
+
+    def gen_method_index
+      gen_an_index(HtmlMethod.all_methods, 'Methods')
+    end
+
+    
+    def gen_an_index(collection, title)
+      res = []
+      collection.sort.each do |f|
+        if f.document_self
+          res << { "href" => f.path, "name" => f.index_name }
+        end
+      end
+
+      return {
+        "entries" => res,
+        'list_title' => title,
+        'index_url'  => main_url,
+      }
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/ri_generator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/ri_generator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/ri_generator.rb	(revision 18425)
@@ -0,0 +1,268 @@
+# We're responsible for generating all the HTML files
+# from the object tree defined in code_objects.rb. We
+# generate:
+#
+# [files]   an html file for each input file given. These
+#           input files appear as objects of class
+#           TopLevel
+#
+# [classes] an html file for each class or module encountered.
+#           These classes are not grouped by file: if a file
+#           contains four classes, we'll generate an html
+#           file for the file itself, and four html files 
+#           for the individual classes. 
+#
+# [indices] we generate three indices for files, classes,
+#           and methods. These are displayed in a browser
+#           like window with three index panes across the
+#           top and the selected description below
+#
+# Method descriptions appear in whatever entity (file, class,
+# or module) that contains them.
+#
+# We generate files in a structure below a specified subdirectory,
+# normally +doc+.
+#
+#  opdir
+#     |
+#     |___ files
+#     |       |__  per file summaries
+#     |
+#     |___ classes
+#             |__ per class/module descriptions
+#
+# HTML is generated using the Template class.
+#
+
+require 'ftools'
+
+require 'rdoc/options'
+require 'rdoc/template'
+require 'rdoc/markup/simple_markup'
+require 'rdoc/markup/simple_markup/to_flow'
+require 'cgi'
+
+require 'rdoc/ri/ri_cache'
+require 'rdoc/ri/ri_reader'
+require 'rdoc/ri/ri_writer'
+require 'rdoc/ri/ri_descriptions'
+
+module Generators
+
+
+  class RIGenerator
+
+    # Generators may need to return specific subclasses depending
+    # on the options they are passed. Because of this
+    # we create them using a factory
+
+    def RIGenerator.for(options)
+      new(options)
+    end
+
+    class <<self
+      protected :new
+    end
+
+    # Set up a new HTML generator. Basically all we do here is load
+    # up the correct output temlate
+
+    def initialize(options) #:not-new:
+      @options   = options
+      @ri_writer = RI::RiWriter.new(".")
+      @markup    = SM::SimpleMarkup.new
+      @to_flow   = SM::ToFlow.new
+    end
+
+
+    ##
+    # Build the initial indices and output objects
+    # based on an array of TopLevel objects containing
+    # the extracted information. 
+
+    def generate(toplevels)
+      RDoc::TopLevel.all_classes_and_modules.each do |cls|
+        process_class(cls)
+      end
+    end
+
+    def process_class(from_class)
+      generate_class_info(from_class)
+
+      # now recure into this classes constituent classess
+      from_class.each_classmodule do |mod|
+        process_class(mod)
+      end
+    end
+
+    def generate_class_info(cls)
+      if cls === RDoc::NormalModule
+        cls_desc = RI::ModuleDescription.new
+      else
+        cls_desc = RI::ClassDescription.new
+        cls_desc.superclass  = cls.superclass
+      end
+      cls_desc.name        = cls.name
+      cls_desc.full_name   = cls.full_name
+      cls_desc.comment     = markup(cls.comment)
+
+      cls_desc.attributes =cls.attributes.sort.map do |a|
+        RI::Attribute.new(a.name, a.rw, markup(a.comment))
+      end
+
+      cls_desc.constants = cls.constants.map do |c|
+        RI::Constant.new(c.name, c.value, markup(c.comment))
+      end
+
+      cls_desc.includes = cls.includes.map do |i|
+        RI::IncludedModule.new(i.name)
+      end
+
+      class_methods, instance_methods = method_list(cls)
+
+      cls_desc.class_methods = class_methods.map do |m|
+        RI::MethodSummary.new(m.name)
+      end
+      cls_desc.instance_methods = instance_methods.map do |m|
+        RI::MethodSummary.new(m.name)
+      end
+
+      update_or_replace(cls_desc)
+
+      class_methods.each do |m|
+        generate_method_info(cls_desc, m)
+      end
+
+      instance_methods.each do |m|
+        generate_method_info(cls_desc, m)
+      end
+    end
+
+
+    def generate_method_info(cls_desc, method)
+      meth_desc = RI::MethodDescription.new
+      meth_desc.name = method.name
+      meth_desc.full_name = cls_desc.full_name
+      if method.singleton
+        meth_desc.full_name += "::"
+      else
+        meth_desc.full_name += "#"
+      end
+      meth_desc.full_name << method.name
+
+      meth_desc.comment = markup(method.comment)
+      meth_desc.params = params_of(method)
+      meth_desc.visibility = method.visibility.to_s
+      meth_desc.is_singleton = method.singleton
+      meth_desc.block_params = method.block_params
+
+      meth_desc.aliases = method.aliases.map do |a|
+        RI::AliasName.new(a.name)
+      end
+
+      @ri_writer.add_method(cls_desc, meth_desc)
+    end
+
+    private
+
+    # return a list of class and instance methods that we'll be
+    # documenting
+
+    def method_list(cls)
+      list = cls.method_list
+      unless @options.show_all
+        list = list.find_all do |m|
+          m.visibility == :public || m.visibility == :protected || m.force_documentation
+        end
+      end
+
+      c = []
+      i = []
+      list.sort.each do |m|
+        if m.singleton
+          c << m
+        else
+          i << m
+        end
+      end
+      return c,i
+    end
+    
+    def params_of(method)
+      if method.call_seq
+        method.call_seq
+      else
+        params = method.params || ""
+        
+        p = params.gsub(/\s*\#.*/, '')
+        p = p.tr("\n", " ").squeeze(" ")
+        p = "(" + p + ")" unless p[0] == ?(
+        
+        if (block = method.block_params)
+          block.gsub!(/\s*\#.*/, '')
+          block = block.tr("\n", " ").squeeze(" ")
+          if block[0] == ?(
+            block.sub!(/^\(/, '').sub!(/\)/, '')
+          end
+          p << " {|#{block.strip}| ...}"
+        end
+        p
+      end
+    end
+
+    def markup(comment)
+      return nil if !comment || comment.empty?
+
+      # Convert leading comment markers to spaces, but only
+      # if all non-blank lines have them
+      
+      if comment =~ /^(?>\s*)[^\#]/
+        content = comment
+      else
+        content = comment.gsub(/^\s*(#+)/)  { $1.tr('#',' ') }
+      end
+      @markup.convert(content, @to_flow)
+    end
+
+
+    # By default we replace existing classes with the
+    # same name. If the --merge option was given, we instead
+    # merge this definition into an existing class. We add
+    # our methods, aliases, etc to that class, but do not
+    # change the class's description.
+
+    def update_or_replace(cls_desc)
+      old_cls = nil
+
+      if @options.merge
+        rdr = RI::RiReader.new(RI::RiCache.new(@options.op_dir))
+
+        namespace = rdr.top_level_namespace
+        namespace = rdr.lookup_namespace_in(cls_desc.name, namespace)
+        if namespace.empty?
+          $stderr.puts "You asked me to merge this source into existing "
+          $stderr.puts "documentation. This file references a class or "
+          $stderr.puts "module called #{cls_desc.name} which I don't"
+          $stderr.puts "have existing documentation for."
+          $stderr.puts 
+          $stderr.puts "Perhaps you need to generate its documentation first"
+          exit 1
+        else
+          old_cls = namespace[0]
+        end
+      end
+
+      if old_cls.nil?
+        # no merge: simply overwrite
+        @ri_writer.remove_class(cls_desc)
+        @ri_writer.add_class(cls_desc)
+      else
+        # existing class: merge in
+        old_desc = rdr.get_class(old_cls)
+
+        old_desc.merge_in(cls_desc)
+        @ri_writer.add_class(old_desc)
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/chm/chm.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/chm/chm.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/chm/chm.rb	(revision 18425)
@@ -0,0 +1,87 @@
+module RDoc
+module Page
+
+require "rdoc/generators/template/html/html"
+
+# This is a nasty little hack, but hhc doesn't support the <?xml
+# tag, so...
+
+BODY.sub!(/<\?xml.*\?>/, '')
+SRC_PAGE.sub!(/<\?xml.*\?>/, '')
+
+HPP_FILE = %{
+[OPTIONS]
+Auto Index = Yes
+Compatibility=1.1 or later
+Compiled file=%opname%.chm
+Contents file=contents.hhc
+Full-text search=Yes
+Index file=index.hhk
+Language=0x409 English(United States)
+Title=%title%
+
+[FILES]
+START:all_html_files
+%html_file_name%
+END:all_html_files
+}
+
+CONTENTS = %{
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+<HEAD>
+<meta name="GENERATOR" content="Microsoft&reg; HTML Help Workshop 4.1">
+<!-- Sitemap 1.0 -->
+</HEAD><BODY>
+<OBJECT type="text/site properties">
+	<param name="Foreground" value="0x80">
+	<param name="Window Styles" value="0x800025">
+	<param name="ImageType" value="Folder">
+</OBJECT>
+<UL>
+START:contents
+	<LI> <OBJECT type="text/sitemap">
+		<param name="Name" value="%c_name%">
+		<param name="Local" value="%ref%">
+		</OBJECT>
+IF:methods
+<ul>
+START:methods
+	<LI> <OBJECT type="text/sitemap">
+		<param name="Name" value="%name%">
+		<param name="Local" value="%aref%">
+		</OBJECT>
+END:methods
+</ul>
+ENDIF:methods
+        </LI>
+END:contents
+</UL>
+</BODY></HTML>
+}
+
+
+CHM_INDEX  = %{
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+<HEAD>
+<meta name="GENERATOR" content="Microsoft&reg; HTML Help Workshop 4.1">
+<!-- Sitemap 1.0 -->
+</HEAD><BODY>
+<OBJECT type="text/site properties">
+	<param name="Foreground" value="0x80">
+	<param name="Window Styles" value="0x800025">
+	<param name="ImageType" value="Folder">
+</OBJECT>
+<UL>
+START:index
+	<LI> <OBJECT type="text/sitemap">
+		<param name="Name" value="%name%">
+		<param name="Local" value="%aref%">
+		</OBJECT>
+END:index
+</UL>
+</BODY></HTML>
+}
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/hefss.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/hefss.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/hefss.rb	(revision 18425)
@@ -0,0 +1,418 @@
+module RDoc
+module Page
+
+
+FONTS = "Verdana, Arial, Helvetica, sans-serif"
+
+STYLE = %{
+body,p { font-family: Verdana, Arial, Helvetica, sans-serif; 
+       color: #000040; background: #BBBBBB;
+}
+
+td { font-family: Verdana, Arial, Helvetica, sans-serif; 
+       color: #000040;
+}
+
+.attr-rw { font-size: small; color: #444488 }
+
+.title-row {color:      #eeeeff;
+	    background: #BBBBDD;
+}
+
+.big-title-font { color: white;
+                  font-family: Verdana, Arial, Helvetica, sans-serif;
+                  font-size: large; 
+                  height: 50px}
+
+.small-title-font { color: purple;
+                    font-family: Verdana, Arial, Helvetica, sans-serif;
+                    font-size: small; }
+
+.aqua { color: purple }
+
+.method-name, attr-name {
+      font-family: monospace; font-weight: bold;
+}
+
+.tablesubtitle {
+   width: 100%;
+   margin-top: 1ex;
+   margin-bottom: .5ex;
+   padding: 5px 0px 5px 20px;
+   font-size: large;
+   color: purple;
+   background: #BBBBCC;
+}
+
+.tablesubsubtitle {
+   width: 100%;
+   margin-top: 1ex;
+   margin-bottom: .5ex;
+   padding: 5px 0px 5px 20px;
+   font-size: medium;
+   color: white;
+   background: #BBBBCC;
+}
+
+.name-list {
+  font-family: monospace;
+  margin-left: 40px;
+  margin-bottom: 2ex;
+  line-height: 140%;
+}
+
+.description {
+  margin-left: 40px;
+  margin-bottom: 2ex;
+  line-height: 140%;
+}
+
+.methodtitle {
+  font-size: medium;
+  text_decoration: none;
+  padding: 3px 3px 3px 20px;
+  color: #0000AA;
+}
+
+.column-title {
+  font-size: medium;
+  font-weight: bold;
+  text_decoration: none;
+  padding: 3px 3px 3px 20px;
+  color: #3333CC;
+  }
+
+.variable-name {
+  font-family: monospace;
+  font-size: medium;
+  text_decoration: none;
+  padding: 3px 3px 3px 20px;
+  color: #0000AA;
+}
+
+.row-name {
+  font-size: medium;
+  font-weight: medium;
+  font-family: monospace;
+  text_decoration: none;
+  padding: 3px 3px 3px 20px;
+}
+
+.paramsig {
+   font-size: small;
+}
+
+.srcbut { float: right }
+
+}
+
+
+############################################################################
+
+
+BODY = %{
+<html><head>
+  <title>%title%</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=%charset%">
+  <link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
+  <script type="text/javascript" language="JavaScript">
+  <!--
+  function popCode(url) {
+    parent.frames.source.location = url
+  }
+  //-->
+  </script>
+</head>
+<body bgcolor="#BBBBBB">
+
+!INCLUDE!  <!-- banner header -->
+
+IF:diagram
+<table width="100%"><tr><td align="center">
+%diagram%
+</td></tr></table>
+ENDIF:diagram
+
+IF:description
+<div class="description">%description%</div>
+ENDIF:description
+
+IF:requires
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Required files</td></tr>
+</table><br />
+<div class="name-list">
+START:requires
+HREF:aref:name:
+END:requires
+ENDIF:requires
+</div>
+
+IF:methods
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Subroutines and Functions</td></tr>
+</table><br />
+<div class="name-list">
+START:methods
+HREF:aref:name:,
+END:methods
+</div>
+ENDIF:methods
+
+IF:attributes
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Arguments</td></tr>
+</table><br />
+<table cellspacing="5">
+START:attributes
+     <tr valign="top">
+IF:rw
+       <td align="center" class="attr-rw">&nbsp;[%rw%]&nbsp;</td>
+ENDIF:rw
+IFNOT:rw
+       <td></td>
+ENDIF:rw
+       <td class="attr-name">%name%</td>
+       <td>%a_desc%</td>
+     </tr>
+END:attributes
+</table>
+ENDIF:attributes
+
+IF:classlist
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Modules</td></tr>
+</table><br />
+%classlist%<br />
+ENDIF:classlist
+
+  !INCLUDE!  <!-- method descriptions -->
+
+</body>
+</html>
+}
+
+###############################################################################
+
+FILE_PAGE = <<_FILE_PAGE_
+<table width="100%">
+ <tr class="title-row">
+ <td><table width="100%"><tr>
+   <td class="big-title-font" colspan="2"><font size="-3"><b>File</b><br /></font>%short_name%</td>
+   <td align="right"><table cellspacing="0" cellpadding="2">
+         <tr>
+           <td  class="small-title-font">Path:</td>
+           <td class="small-title-font">%full_path%
+IF:cvsurl
+				&nbsp;(<a href="%cvsurl%"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
+ENDIF:cvsurl
+           </td>
+         </tr>
+         <tr>
+           <td class="small-title-font">Modified:</td>
+           <td class="small-title-font">%dtm_modified%</td>
+         </tr>
+        </table>
+    </td></tr></table></td>
+  </tr>
+</table><br />
+_FILE_PAGE_
+
+###################################################################
+
+CLASS_PAGE = %{
+<table width="100%" border="0" cellspacing="0">
+ <tr class="title-row">
+ <td class="big-title-font">
+   <font size="-3"><b>%classmod%</b><br /></font>%full_name%
+ </td>
+ <td align="right">
+   <table cellspacing="0" cellpadding="2">
+     <tr valign="top">
+      <td class="small-title-font">In:</td>
+      <td class="small-title-font">
+START:infiles
+HREF:full_path_url:full_path:
+IF:cvsurl
+&nbsp;(<a href="%cvsurl%"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
+ENDIF:cvsurl
+END:infiles
+      </td>
+     </tr>
+IF:parent
+     <tr>
+      <td class="small-title-font">Parent:</td>
+      <td class="small-title-font">
+IF:par_url
+        <a href="%par_url%" class="cyan">
+ENDIF:par_url
+%parent%
+IF:par_url
+         </a>
+ENDIF:par_url
+      </td>
+     </tr>
+ENDIF:parent
+   </table>
+  </td>
+  </tr>
+</table><br />
+}
+
+###################################################################
+
+METHOD_LIST = %{
+IF:includes
+<div class="tablesubsubtitle">Uses</div><br />
+<div class="name-list">
+START:includes
+    <span class="method-name">HREF:aref:name:</span>
+END:includes
+</div>
+ENDIF:includes
+
+IF:method_list
+START:method_list
+IF:methods
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">%type% %category% methods</td></tr>
+</table>
+START:methods
+<table width="100%" cellspacing="0" cellpadding="5" border="0">
+<tr><td class="methodtitle">
+<a name="%aref%">
+<b>%name%</b>%params% 
+IF:codeurl
+<a href="%codeurl%" target="source" class="srclink">src</a>
+ENDIF:codeurl
+</a></td></tr>
+</table>
+IF:m_desc
+<div class="description">
+%m_desc%
+</div>
+ENDIF:m_desc
+END:methods
+ENDIF:methods
+END:method_list
+ENDIF:method_list
+}
+
+=begin
+=end
+
+########################## Source code ##########################
+
+SRC_PAGE = %{
+<html>
+<head><title>%title%</title>
+<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
+<style type="text/css">
+  .kw { color: #3333FF; font-weight: bold }
+  .cmt { color: green; font-style: italic }
+  .str { color: #662222; font-style: italic }
+  .re  { color: #662222; }
+.ruby-comment    { color: green; font-style: italic }
+.ruby-constant   { color: #4433aa; font-weight: bold; }
+.ruby-identifier { color: #222222;  }
+.ruby-ivar       { color: #2233dd; }
+.ruby-keyword    { color: #3333FF; font-weight: bold }
+.ruby-node       { color: #777777; }
+.ruby-operator   { color: #111111;  }
+.ruby-regexp     { color: #662222; }
+.ruby-value      { color: #662222; font-style: italic }
+</style>
+</head>
+<body bgcolor="#BBBBBB">
+<pre>%code%</pre>
+</body>
+</html>
+}
+
+########################## Index ################################
+
+FR_INDEX_BODY = %{
+!INCLUDE!
+}
+
+FILE_INDEX = %{
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
+<style type="text/css">
+<!--
+  body {
+background-color: #bbbbbb;
+     font-family: #{FONTS}; 
+       font-size: 11px; 
+      font-style: normal;
+     line-height: 14px; 
+           color: #000040;
+  }
+div.banner {
+  background: #bbbbcc;
+  color:      white;
+  padding: 1;
+  margin: 0;
+  font-size: 90%;
+  font-weight: bold;
+  line-height: 1.1;
+  text-align: center;
+  width: 100%;
+}
+  
+-->
+</style>
+<base target="docwin">
+</head>
+<body>
+<div class="banner">%list_title%</div>
+START:entries
+<a href="%href%">%name%</a><br />
+END:entries
+</body></html>
+}
+
+CLASS_INDEX = FILE_INDEX
+METHOD_INDEX = FILE_INDEX
+
+INDEX = %{
+<html>
+<head>
+  <title>%title%</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=%charset%">
+</head>
+
+<frameset cols="20%,*">
+    <frameset rows="15%,35%,50%">
+        <frame src="fr_file_index.html"   title="Files" name="Files">
+        <frame src="fr_class_index.html"  name="Modules">
+        <frame src="fr_method_index.html" name="Subroutines and Functions">
+    </frameset>
+    <frameset rows="80%,20%">
+      <frame  src="%initial_page%" name="docwin">
+      <frame  src="blank.html" name="source">
+    </frameset>
+    <noframes>
+          <body bgcolor="#BBBBBB">
+            Click <a href="html/index.html">here</a> for a non-frames
+            version of this page.
+          </body>
+    </noframes>
+</frameset>
+
+</html>
+}
+
+# and a blank page to use as a target
+BLANK = %{
+<html><body bgcolor="#BBBBBB"></body></html>
+}
+
+def write_extra_pages
+  template = TemplatePage.new(BLANK)
+  File.open("blank.html", "w") { |f| template.write_html_on(f, {}) }
+end
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/html.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/html.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/html.rb	(revision 18425)
@@ -0,0 +1,711 @@
+#
+# = CSS2 RDoc HTML template
+#
+# This is a template for RDoc that uses XHTML 1.0 Transitional and dictates a
+# bit more of the appearance of the output to cascading stylesheets than the
+# default. It was designed for clean inline code display, and uses DHTMl to
+# toggle the visbility of each method's source with each click on the '[source]'
+# link.
+#
+# == Authors
+#
+# * Michael Granger <ged@FaerieMUD.org>
+#
+# Copyright (c) 2002, 2003 The FaerieMUD Consortium. Some rights reserved.
+#
+# This work is licensed under the Creative Commons Attribution License. To view
+# a copy of this license, visit http://creativecommons.org/licenses/by/1.0/ or
+# send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California
+# 94305, USA.
+#
+
+module RDoc
+  module Page
+
+    FONTS = "Verdana,Arial,Helvetica,sans-serif"
+
+STYLE = %{
+body {
+    font-family: Verdana,Arial,Helvetica,sans-serif;
+    font-size:   90%;
+    margin: 0;
+    margin-left: 40px;
+    padding: 0;
+    background: white;
+}
+
+h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
+h1 { font-size: 150%; }
+h2,h3,h4 { margin-top: 1em; }
+
+a { background: #eef; color: #039; text-decoration: none; }
+a:hover { background: #039; color: #eef; }
+
+/* Override the base stylesheet's Anchor inside a table cell */
+td > a {
+  background: transparent;
+  color: #039;
+  text-decoration: none;
+}
+
+/* and inside a section title */
+.section-title > a {
+  background: transparent;
+  color: #eee;
+  text-decoration: none;
+}
+
+/* === Structural elements =================================== */
+
+div#index {
+    margin: 0;
+    margin-left: -40px;
+    padding: 0;
+    font-size: 90%;
+}
+
+
+div#index a {
+    margin-left: 0.7em;
+}
+
+div#index .section-bar {
+   margin-left: 0px;
+   padding-left: 0.7em;
+   background: #ccc;
+   font-size: small;
+}
+
+
+div#classHeader, div#fileHeader {
+    width: auto;
+    color: white;
+    padding: 0.5em 1.5em 0.5em 1.5em;
+    margin: 0;
+    margin-left: -40px;
+    border-bottom: 3px solid #006;
+}
+
+div#classHeader a, div#fileHeader a {
+    background: inherit;
+    color: white;
+}
+
+div#classHeader td, div#fileHeader td {
+    background: inherit;
+    color: white;
+}
+
+
+div#fileHeader {
+    background: #057;
+}
+
+div#classHeader {
+    background: #048;
+}
+
+
+.class-name-in-header {
+  font-size:  180%;
+  font-weight: bold;
+}
+
+
+div#bodyContent {
+    padding: 0 1.5em 0 1.5em;
+}
+
+div#description {
+    padding: 0.5em 1.5em;
+    background: #efefef;
+    border: 1px dotted #999;
+}
+
+div#description h1,h2,h3,h4,h5,h6 {
+    color: #125;;
+    background: transparent;
+}
+
+div#validator-badges {
+    text-align: center;
+}
+div#validator-badges img { border: 0; }
+
+div#copyright {
+    color: #333;
+    background: #efefef;
+    font: 0.75em sans-serif;
+    margin-top: 5em;
+    margin-bottom: 0;
+    padding: 0.5em 2em;
+}
+
+
+/* === Classes =================================== */
+
+table.header-table {
+    color: white;
+    font-size: small;
+}
+
+.type-note {
+    font-size: small;
+    color: #DEDEDE;
+}
+
+.xxsection-bar {
+    background: #eee;
+    color: #333;
+    padding: 3px;
+}
+
+.section-bar {
+   color: #333;
+   border-bottom: 1px solid #999;
+    margin-left: -20px;
+}
+
+
+.section-title {
+    background: #79a;
+    color: #eee;
+    padding: 3px;
+    margin-top: 2em;
+    margin-left: -30px;
+    border: 1px solid #999;
+}
+
+.top-aligned-row {  vertical-align: top }
+.bottom-aligned-row { vertical-align: bottom }
+
+/* --- Context section classes ----------------------- */
+
+.context-row { }
+.context-item-name { font-family: monospace; font-weight: bold; color: black; }
+.context-item-value { font-size: small; color: #448; }
+.context-item-desc { color: #333; padding-left: 2em; }
+
+/* --- Method classes -------------------------- */
+.method-detail {
+    background: #efefef;
+    padding: 0;
+    margin-top: 0.5em;
+    margin-bottom: 1em;
+    border: 1px dotted #ccc;
+}
+.method-heading {
+  color: black;
+  background: #ccc;
+  border-bottom: 1px solid #666;
+  padding: 0.2em 0.5em 0 0.5em;
+}
+.method-signature { color: black; background: inherit; }
+.method-name { font-weight: bold; }
+.method-args { font-style: italic; }
+.method-description { padding: 0 0.5em 0 0.5em; }
+
+/* --- Source code sections -------------------- */
+
+a.source-toggle { font-size: 90%; }
+div.method-source-code {
+    background: #262626;
+    color: #ffdead;
+    margin: 1em;
+    padding: 0.5em;
+    border: 1px dashed #999;
+    overflow: hidden;
+}
+
+div.method-source-code pre { color: #ffdead; overflow: hidden; }
+
+/* --- Ruby keyword styles --------------------- */
+
+.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
+
+.ruby-constant  { color: #7fffd4; background: transparent; }
+.ruby-keyword { color: #00ffff; background: transparent; }
+.ruby-ivar    { color: #eedd82; background: transparent; }
+.ruby-operator  { color: #00ffee; background: transparent; }
+.ruby-identifier { color: #ffdead; background: transparent; }
+.ruby-node    { color: #ffa07a; background: transparent; }
+.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
+.ruby-regexp  { color: #ffa07a; background: transparent; }
+.ruby-value   { color: #7fffd4; background: transparent; }
+}
+
+
+#####################################################################
+### H E A D E R   T E M P L A T E  
+#####################################################################
+
+XHTML_PREAMBLE = %{<?xml version="1.0" encoding="%charset%"?>
+<!DOCTYPE html 
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+}
+
+HEADER = XHTML_PREAMBLE + %{
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>%title%</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
+  <meta http-equiv="Content-Script-Type" content="text/javascript" />
+  <link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
+  <script type="text/javascript">
+  // <![CDATA[
+
+  function popupCode( url ) {
+    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+
+  function toggleCode( id ) {
+    if ( document.getElementById )
+      elem = document.getElementById( id );
+    else if ( document.all )
+      elem = eval( "document.all." + id );
+    else
+      return false;
+
+    elemStyle = elem.style;
+    
+    if ( elemStyle.display != "block" ) {
+      elemStyle.display = "block"
+    } else {
+      elemStyle.display = "none"
+    }
+
+    return true;
+  }
+  
+  // Make codeblocks hidden by default
+  document.writeln( "<style type=\\"text/css\\">div.method-source-code { display: none }</style>" )
+  
+  // ]]>
+  </script>
+
+</head>
+<body>
+}
+
+
+#####################################################################
+### C O N T E X T   C O N T E N T   T E M P L A T E
+#####################################################################
+
+CONTEXT_CONTENT = %{
+}
+
+
+#####################################################################
+### F O O T E R   T E M P L A T E
+#####################################################################
+FOOTER = %{
+<div id="validator-badges">
+  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+</div>
+
+</body>
+</html>
+}
+
+
+#####################################################################
+### F I L E   P A G E   H E A D E R   T E M P L A T E
+#####################################################################
+
+FILE_PAGE = %{
+  <div id="fileHeader">
+    <h1>%short_name%</h1>
+    <table class="header-table">
+    <tr class="top-aligned-row">
+      <td><strong>Path:</strong></td>
+      <td>%full_path%
+IF:cvsurl
+        &nbsp;(<a href="%cvsurl%"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
+ENDIF:cvsurl
+      </td>
+    </tr>
+    <tr class="top-aligned-row">
+      <td><strong>Last Update:</strong></td>
+      <td>%dtm_modified%</td>
+    </tr>
+    </table>
+  </div>
+}
+
+
+#####################################################################
+### C L A S S   P A G E   H E A D E R   T E M P L A T E
+#####################################################################
+
+CLASS_PAGE = %{
+    <div id="classHeader">
+        <table class="header-table">
+        <tr class="top-aligned-row">
+          <td><strong>%classmod%</strong></td>
+          <td class="class-name-in-header">%full_name%</td>
+        </tr>
+        <tr class="top-aligned-row">
+            <td><strong>In:</strong></td>
+            <td>
+START:infiles
+IF:full_path_url
+                <a href="%full_path_url%">
+ENDIF:full_path_url
+                %full_path%
+IF:full_path_url
+                </a>
+ENDIF:full_path_url
+IF:cvsurl
+        &nbsp;(<a href="%cvsurl%"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
+ENDIF:cvsurl
+        <br />
+END:infiles
+            </td>
+        </tr>
+
+IF:parent
+        <tr class="top-aligned-row">
+            <td><strong>Parent:</strong></td>
+            <td>
+IF:par_url
+                <a href="%par_url%">
+ENDIF:par_url
+                %parent%
+IF:par_url
+               </a>
+ENDIF:par_url
+            </td>
+        </tr>
+ENDIF:parent
+        </table>
+    </div>
+}
+
+
+#####################################################################
+### M E T H O D   L I S T   T E M P L A T E
+#####################################################################
+
+METHOD_LIST = %{
+
+  <div id="contextContent">
+IF:diagram
+    <div id="diagram">
+      %diagram%
+    </div>
+ENDIF:diagram
+
+IF:description
+    <div id="description">
+      %description%
+    </div>
+ENDIF:description
+
+IF:requires
+    <div id="requires-list">
+      <h3 class="section-bar">Required files</h3>
+
+      <div class="name-list">
+START:requires
+      HREF:aref:name:&nbsp;&nbsp;
+END:requires
+      </div>
+    </div>
+ENDIF:requires
+
+IF:toc
+    <div id="contents-list">
+      <h3 class="section-bar">Contents</h3>
+      <ul>
+START:toc
+      <li><a href="#%href%">%secname%</a></li>
+END:toc
+     </ul>
+ENDIF:toc
+   </div>
+
+IF:methods
+    <div id="method-list">
+      <h3 class="section-bar">Methods</h3>
+
+      <div class="name-list">
+START:methods
+      HREF:aref:name:&nbsp;&nbsp;
+END:methods
+      </div>
+    </div>
+ENDIF:methods
+
+  </div>
+
+
+    <!-- if includes -->
+IF:includes
+    <div id="includes">
+      <h3 class="section-bar">Included Modules</h3>
+
+      <div id="includes-list">
+START:includes
+        <span class="include-name">HREF:aref:name:</span>
+END:includes
+      </div>
+    </div>
+ENDIF:includes
+
+START:sections
+    <div id="section">
+IF:sectitle
+      <h2 class="section-title"><a name="%secsequence%">%sectitle%</a></h2>
+IF:seccomment
+      <div class="section-comment">
+        %seccomment%
+      </div>      
+ENDIF:seccomment
+ENDIF:sectitle
+
+IF:classlist
+    <div id="class-list">
+      <h3 class="section-bar">Classes and Modules</h3>
+
+      %classlist%
+    </div>
+ENDIF:classlist
+
+IF:constants
+    <div id="constants-list">
+      <h3 class="section-bar">Constants</h3>
+
+      <div class="name-list">
+        <table summary="Constants">
+START:constants
+        <tr class="top-aligned-row context-row">
+          <td class="context-item-name">%name%</td>
+          <td>=</td>
+          <td class="context-item-value">%value%</td>
+IF:desc
+          <td width="3em">&nbsp;</td>
+          <td class="context-item-desc">%desc%</td>
+ENDIF:desc
+        </tr>
+END:constants
+        </table>
+      </div>
+    </div>
+ENDIF:constants
+
+IF:aliases
+    <div id="aliases-list">
+      <h3 class="section-bar">External Aliases</h3>
+
+      <div class="name-list">
+                        <table summary="aliases">
+START:aliases
+        <tr class="top-aligned-row context-row">
+          <td class="context-item-name">%old_name%</td>
+          <td>-&gt;</td>
+          <td class="context-item-value">%new_name%</td>
+        </tr>
+IF:desc
+      <tr class="top-aligned-row context-row">
+        <td>&nbsp;</td>
+        <td colspan="2" class="context-item-desc">%desc%</td>
+      </tr>
+ENDIF:desc
+END:aliases
+                        </table>
+      </div>
+    </div>
+ENDIF:aliases
+
+
+IF:attributes
+    <div id="attribute-list">
+      <h3 class="section-bar">Attributes</h3>
+
+      <div class="name-list">
+        <table>
+START:attributes
+        <tr class="top-aligned-row context-row">
+          <td class="context-item-name">%name%</td>
+IF:rw
+          <td class="context-item-value">&nbsp;[%rw%]&nbsp;</td>
+ENDIF:rw
+IFNOT:rw
+          <td class="context-item-value">&nbsp;&nbsp;</td>
+ENDIF:rw
+          <td class="context-item-desc">%a_desc%</td>
+        </tr>
+END:attributes
+        </table>
+      </div>
+    </div>
+ENDIF:attributes
+      
+
+
+    <!-- if method_list -->
+IF:method_list
+    <div id="methods">
+START:method_list
+IF:methods
+      <h3 class="section-bar">%type% %category% methods</h3>
+
+START:methods
+      <div id="method-%aref%" class="method-detail">
+        <a name="%aref%"></a>
+
+        <div class="method-heading">
+IF:codeurl
+          <a href="%codeurl%" target="Code" class="method-signature"
+            onclick="popupCode('%codeurl%');return false;">
+ENDIF:codeurl
+IF:sourcecode
+          <a href="#%aref%" class="method-signature">
+ENDIF:sourcecode
+IF:callseq
+          <span class="method-name">%callseq%</span>
+ENDIF:callseq
+IFNOT:callseq
+          <span class="method-name">%name%</span><span class="method-args">%params%</span>
+ENDIF:callseq
+IF:codeurl
+          </a>
+ENDIF:codeurl
+IF:sourcecode
+          </a>
+ENDIF:sourcecode
+        </div>
+      
+        <div class="method-description">
+IF:m_desc
+          %m_desc%
+ENDIF:m_desc
+IF:sourcecode
+          <p><a class="source-toggle" href="#"
+            onclick="toggleCode('%aref%-source');return false;">[Source]</a></p>
+          <div class="method-source-code" id="%aref%-source">
+<pre>
+%sourcecode%
+</pre>
+          </div>
+ENDIF:sourcecode
+        </div>
+      </div>
+
+END:methods
+ENDIF:methods
+END:method_list
+
+    </div>
+ENDIF:method_list
+END:sections
+}
+
+
+#####################################################################
+### B O D Y   T E M P L A T E
+#####################################################################
+
+BODY = HEADER + %{
+
+!INCLUDE!  <!-- banner header -->
+
+  <div id="bodyContent">
+
+} +  METHOD_LIST + %{
+
+  </div>
+
+} + FOOTER
+
+
+
+#####################################################################
+### S O U R C E   C O D E   T E M P L A T E
+#####################################################################
+
+SRC_PAGE = XHTML_PREAMBLE + %{
+<html>
+<head>
+  <title>%title%</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
+  <link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
+</head>
+<body class="standalone-code">
+  <pre>%code%</pre>
+</body>
+</html>
+}
+
+
+#####################################################################
+### I N D E X   F I L E   T E M P L A T E S
+#####################################################################
+
+FR_INDEX_BODY = %{
+!INCLUDE!
+}
+
+FILE_INDEX = XHTML_PREAMBLE + %{
+<!--
+
+    %list_title%
+
+  -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>%list_title%</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
+  <link rel="stylesheet" href="%style_url%" type="text/css" />
+  <base target="docwin" />
+</head>
+<body>
+<div id="index">
+  <h1 class="section-bar">%list_title%</h1>
+  <div id="index-entries">
+START:entries
+    <a href="%href%">%name%</a><br />
+END:entries
+  </div>
+</div>
+</body>
+</html>
+}
+
+CLASS_INDEX = FILE_INDEX
+METHOD_INDEX = FILE_INDEX
+
+INDEX = %{<?xml version="1.0" encoding="%charset%"?>
+<!DOCTYPE html 
+     PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+
+<!--
+
+    %title%
+
+  -->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>%title%</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
+</head>
+<frameset rows="20%, 80%">
+    <frameset cols="25%,35%,45%">
+        <frame src="fr_file_index.html"   title="Files" name="Files" />
+        <frame src="fr_class_index.html"  name="Classes" />
+        <frame src="fr_method_index.html" name="Methods" />
+    </frameset>
+    <frame src="%initial_page%" name="docwin" />
+</frameset>
+</html>
+}
+
+
+
+  end # module Page
+end # class RDoc
+
+require 'rdoc/generators/template/html/one_page_html'
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/kilmer.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/kilmer.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/kilmer.rb	(revision 18425)
@@ -0,0 +1,435 @@
+module RDoc
+module Page
+
+
+FONTS = "Verdana, Arial, Helvetica, sans-serif"
+
+STYLE = %{
+body,td,p { font-family: %fonts%; 
+       color: #000040;
+}
+
+.attr-rw { font-size: xx-small; color: #444488 }
+
+.title-row { background-color: #CCCCFF;
+             color:      #000010;
+}
+
+.big-title-font { 
+  color: black;
+  font-weight: bold;
+  font-family: %fonts%; 
+  font-size: large; 
+  height: 60px;
+  padding: 10px 3px 10px 3px;
+}
+
+.small-title-font { color: black;
+                    font-family: %fonts%;
+                    font-size:10; }
+
+.aqua { color: black }
+
+.method-name, .attr-name {
+      font-family: font-family: %fonts%; 
+      font-weight: bold;
+      font-size: small;
+      margin-left: 20px;
+      color: #000033;
+}
+
+.tablesubtitle, .tablesubsubtitle {
+   width: 100%;
+   margin-top: 1ex;
+   margin-bottom: .5ex;
+   padding: 5px 0px 5px 3px;
+   font-size: large;
+   color: black;
+   background-color: #CCCCFF;
+   border: thin;
+}
+
+.name-list {
+  margin-left: 5px;
+  margin-bottom: 2ex;
+  line-height: 105%;
+}
+
+.description {
+  margin-left: 5px;
+  margin-bottom: 2ex;
+  line-height: 105%;
+  font-size: small;
+}
+
+.methodtitle {
+  font-size: small;
+  font-weight: bold;
+  text-decoration: none;
+  color: #000033;
+  background-color: white; 
+}
+
+.srclink {
+  font-size: small;
+  font-weight: bold;
+  text-decoration: none;
+  color: #0000DD;
+  background-color: white;
+}
+
+.paramsig {
+   font-size: small;
+}
+
+.srcbut { float: right }
+
+}
+
+
+############################################################################
+
+
+BODY = %{
+<html><head>
+  <title>%title%</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=%charset%">
+  <link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
+  <script type="text/javascript" language="JavaScript">
+  <!--
+  function popCode(url) {
+    parent.frames.source.location = url
+  }
+  //-->
+  </script>
+</head>
+<body bgcolor="white">
+
+!INCLUDE!  <!-- banner header -->
+
+IF:diagram
+<table width="100%"><tr><td align="center">
+%diagram%
+</td></tr></table>
+ENDIF:diagram
+
+IF:description
+<div class="description">%description%</div>
+ENDIF:description
+
+IF:requires
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Required files</td></tr>
+</table><br />
+<div class="name-list">
+START:requires
+HREF:aref:name:
+END:requires
+ENDIF:requires
+</div>
+
+IF:methods
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Methods</td></tr>
+</table><br />
+<div class="name-list">
+START:methods
+HREF:aref:name:,
+END:methods
+</div>
+ENDIF:methods
+
+
+START:sections
+    <div id="section">
+IF:sectitle
+      <h2 class="section-title"><a name="%secsequence%">%sectitle%</a></h2>
+IF:seccomment
+      <div class="section-comment">
+        %seccomment%
+      </div>      
+ENDIF:seccomment
+ENDIF:sectitle
+
+IF:attributes
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Attributes</td></tr>
+</table><br />
+<table cellspacing="5">
+START:attributes
+     <tr valign="top">
+IF:rw
+       <td align="center" class="attr-rw">&nbsp;[%rw%]&nbsp;</td>
+ENDIF:rw
+IFNOT:rw
+       <td></td>
+ENDIF:rw
+       <td class="attr-name">%name%</td>
+       <td>%a_desc%</td>
+     </tr>
+END:attributes
+</table>
+ENDIF:attributes
+
+IF:classlist
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Classes and Modules</td></tr>
+</table><br />
+%classlist%<br />
+ENDIF:classlist
+
+  !INCLUDE!  <!-- method descriptions -->
+
+END:sections
+
+</body>
+</html>
+}
+
+###############################################################################
+
+FILE_PAGE = <<_FILE_PAGE_
+<table width="100%">
+ <tr class="title-row">
+ <td><table width="100%"><tr>
+   <td class="big-title-font" colspan="2"><font size="-3"><b>File</b><br /></font>%short_name%</td>
+   <td align="right"><table cellspacing="0" cellpadding="2">
+         <tr>
+           <td  class="small-title-font">Path:</td>
+           <td class="small-title-font">%full_path%
+IF:cvsurl
+				&nbsp;(<a href="%cvsurl%"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
+ENDIF:cvsurl
+           </td>
+         </tr>
+         <tr>
+           <td class="small-title-font">Modified:</td>
+           <td class="small-title-font">%dtm_modified%</td>
+         </tr>
+        </table>
+    </td></tr></table></td>
+  </tr>
+</table><br />
+_FILE_PAGE_
+
+###################################################################
+
+CLASS_PAGE = %{
+<table width="100%" border="0" cellspacing="0">
+ <tr class="title-row">
+ <td class="big-title-font">
+   <font size="-3"><b>%classmod%</b><br /></font>%full_name%
+ </td>
+ <td align="right">
+   <table cellspacing="0" cellpadding="2">
+     <tr valign="top">
+      <td class="small-title-font">In:</td>
+      <td class="small-title-font">
+START:infiles
+HREF:full_path_url:full_path:
+IF:cvsurl
+&nbsp;(<a href="%cvsurl%"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
+ENDIF:cvsurl
+END:infiles
+      </td>
+     </tr>
+IF:parent
+     <tr>
+      <td class="small-title-font">Parent:</td>
+      <td class="small-title-font">
+IF:par_url
+        <a href="%par_url%" class="cyan">
+ENDIF:par_url
+%parent%
+IF:par_url
+         </a>
+ENDIF:par_url
+      </td>
+     </tr>
+ENDIF:parent
+   </table>
+  </td>
+  </tr>
+</table><br />
+}
+
+###################################################################
+
+METHOD_LIST = %{
+IF:includes
+<div class="tablesubsubtitle">Included modules</div><br />
+<div class="name-list">
+START:includes
+    <span class="method-name">HREF:aref:name:</span>
+END:includes
+</div>
+ENDIF:includes
+
+IF:method_list
+START:method_list
+IF:methods
+<table cellpadding=5 width="100%">
+<tr><td class="tablesubtitle">%type% %category% methods</td></tr>
+</table>
+START:methods
+<table width="100%" cellspacing="0" cellpadding="5" border="0">
+<tr><td class="methodtitle">
+<a name="%aref%">
+IF:callseq
+<b>%callseq%</b>
+ENDIF:callseq
+IFNOT:callseq
+ <b>%name%</b>%params%
+ENDIF:callseq
+IF:codeurl
+<a href="%codeurl%" target="source" class="srclink">src</a>
+ENDIF:codeurl
+</a></td></tr>
+</table>
+IF:m_desc
+<div class="description">
+%m_desc%
+</div>
+ENDIF:m_desc
+IF:aka
+<div class="aka">
+This method is also aliased as
+START:aka
+<a href="%aref%">%name%</a>
+END:aka
+</div>
+ENDIF:aka
+IF:sourcecode
+<pre class="source">
+%sourcecode%
+</pre>
+ENDIF:sourcecode
+END:methods
+ENDIF:methods
+END:method_list
+ENDIF:method_list
+}
+
+=begin
+=end
+
+########################## Source code ##########################
+
+SRC_PAGE = %{
+<html>
+<head><title>%title%</title>
+<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
+<style type="text/css">
+.ruby-comment    { color: green; font-style: italic }
+.ruby-constant   { color: #4433aa; font-weight: bold; }
+.ruby-identifier { color: #222222;  }
+.ruby-ivar       { color: #2233dd; }
+.ruby-keyword    { color: #3333FF; font-weight: bold }
+.ruby-node       { color: #777777; }
+.ruby-operator   { color: #111111;  }
+.ruby-regexp     { color: #662222; }
+.ruby-value      { color: #662222; font-style: italic }
+  .kw { color: #3333FF; font-weight: bold }
+  .cmt { color: green; font-style: italic }
+  .str { color: #662222; font-style: italic }
+  .re  { color: #662222; }
+</style>
+</head>
+<body bgcolor="white">
+<pre>%code%</pre>
+</body>
+</html>
+}
+
+########################## Index ################################
+
+FR_INDEX_BODY = %{
+!INCLUDE!
+}
+
+FILE_INDEX = %{
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
+<style>
+<!--
+  body {
+background-color: #ddddff;
+     font-family: #{FONTS}; 
+       font-size: 11px; 
+      font-style: normal;
+     line-height: 14px; 
+           color: #000040;
+  }
+div.banner {
+  background: #0000aa;
+  color:      white;
+  padding: 1;
+  margin: 0;
+  font-size: 90%;
+  font-weight: bold;
+  line-height: 1.1;
+  text-align: center;
+  width: 100%;
+}
+  
+-->
+</style>
+<base target="docwin">
+</head>
+<body>
+<div class="banner">%list_title%</div>
+START:entries
+<a href="%href%">%name%</a><br />
+END:entries
+</body></html>
+}
+
+CLASS_INDEX = FILE_INDEX
+METHOD_INDEX = FILE_INDEX
+
+INDEX = %{
+<html>
+<head>
+  <title>%title%</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=%charset%">
+</head>
+
+<frameset cols="20%,*">
+    <frameset rows="15%,35%,50%">
+        <frame src="fr_file_index.html"   title="Files" name="Files">
+        <frame src="fr_class_index.html"  name="Classes">
+        <frame src="fr_method_index.html" name="Methods">
+    </frameset>
+IF:inline_source
+      <frame  src="%initial_page%" name="docwin">
+ENDIF:inline_source
+IFNOT:inline_source
+    <frameset rows="80%,20%">
+      <frame  src="%initial_page%" name="docwin">
+      <frame  src="blank.html" name="source">
+    </frameset>
+ENDIF:inline_source
+    <noframes>
+          <body bgcolor="white">
+            Click <a href="html/index.html">here</a> for a non-frames
+            version of this page.
+          </body>
+    </noframes>
+</frameset>
+
+</html>
+}
+
+# and a blank page to use as a target
+BLANK = %{
+<html><body bgcolor="white"></body></html>
+}
+
+def write_extra_pages
+  template = TemplatePage.new(BLANK)
+  File.open("blank.html", "w") { |f| template.write_html_on(f, {}) }
+end
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/old_html.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/old_html.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/old_html.rb	(revision 18425)
@@ -0,0 +1,728 @@
+module RDoc
+
+# This is how you define the HTML that RDoc generates. Simply create
+# a file in rdoc/generators/html_templates that creates the
+# module RDoc::Page and populate it as described below. Then invoke
+# rdoc using the --template <name of your file> option, and
+# your template will be used.
+#
+# The constants defining pages use a simple templating system:
+#
+# * The templating system is passed a hash. Keys in the hash correspond
+#   to tags on this page. The tag %abc% is looked up in the hash,
+#   and is replaced by the corresponding hash value.
+#
+# * Some tags are optional. You can detect this using IF/ENDIF
+#
+#      IF: title
+#      The value of title is %title%
+#      ENDIF: title
+#
+# * Some entries in the hash have values that are arrays, where each
+#   entry in the array is itself a hash. These are used to generate
+#   lists using the START: construct. For example, given a hash
+#   containing
+# 
+#      { 'people' => [ { 'name' => 'Fred', 'age' => '12' },
+#                      { 'name' => 'Mary', 'age' => '21' } ]
+#
+#   You could generate a simple table using
+#
+#      <table>
+#      START:people
+#        <tr><td>%name%<td>%age%</tr>
+#      END:people
+#      </table>
+#
+#   These lists can be nested to an arbitrary depth
+#
+# * the construct HREF:url:name: generates <a href="%url%">%name%</a>
+#   if +url+ is defined in the hash, or %name% otherwise.
+#
+#
+# Your file must contain the following constants
+#
+# [*FONTS*]  a list of fonts to be used
+# [*STYLE*]  a CSS section (without the <style> or comments). This is
+#            used to generate a style.css file
+#
+# [*BODY*] 
+#   The main body of all non-index RDoc pages. BODY will contain
+#   two !INCLUDE!s. The first is used to include a document-type
+#   specific header (FILE_PAGE or CLASS_PAGE). The second include
+#   is for the method list (METHOD_LIST). THe body is passed:
+#
+#   %title%::
+#       the page's title
+#
+#   %style_url%::
+#       the url of a style sheet for this page
+#
+#   %diagram%::
+#       the optional URL of a diagram for this page
+#
+#   %description%::
+#       a (potentially multi-paragraph) string containing the
+#       description for th file/class/module.
+#
+#   %requires%::
+#       an optional list of %aref%/%name% pairs, one for each module
+#       required by this file.
+#
+#   %methods%::
+#       an optional list of %aref%/%name%, one for each method
+#       documented on this page. This is intended to be an index.
+#
+#   %attributes%::  
+#       An optional list. For each attribute it contains:
+#       %name%::   the attribute name
+#       %rw%::     r/o, w/o, or r/w
+#       %a_desc%:: description of the attribute
+#
+#   %classlist%:: 
+#       An optional string containing an already-formatted list of
+#       classes and modules documented in this file
+#
+#   For FILE_PAGE entries, the body will be passed
+#
+#   %short_name%::  
+#       The name of the file
+#
+#   %full_path%::
+#       The full path to the file
+#
+#   %dtm_modified%::
+#       The date/time the file was last changed
+#
+#   For class and module pages, the body will be passed
+#
+#   %classmod%::
+#       The name of the class or module
+#
+#   %files%::
+#       A list. For each file this class is defined in, it contains:
+#       %full_path_url%:: an (optional) URL of the RDoc page
+#                         for this file
+#       %full_path%::     the name of the file
+#
+#   %par_url%::
+#       The (optional) URL of the RDoc page documenting this class's
+#       parent class
+#
+#   %parent%::
+#       The name of this class's parent.
+#
+#   For both files and classes, the body is passed the following information
+#   on includes and methods:
+#
+#   %includes%::    
+#       Optional list of included modules. For each, it receives
+#       %aref%:: optional URL to RDoc page for the module
+#       %name%:: the name of the module
+#
+#   %method_list%::
+#       Optional list of methods of a particular class and category.
+#
+#   Each method list entry contains:
+#
+#   %type%::        public/private/protected
+#   %category%::    instance/class
+#   %methods%::     a list of method descriptions
+#
+#   Each method description contains:
+#
+#   %aref%::        a target aref, used when referencing this method
+#                   description. You should code this as <a name="%aref%">
+#   %codeurl%::     the optional URL to the page containing this method's
+#                   source code.
+#   %name%::        the method's name
+#   %params%::      the method's parameters
+#   %callseq%::     a full calling sequence
+#   %m_desc%::      the (potentially multi-paragraph) description of
+#                   this method.
+#
+# [*CLASS_PAGE*]
+#         Header for pages documenting classes and modules. See
+#         BODY above for the available parameters.
+#
+# [*FILE_PAGE*]
+#         Header for pages documenting files. See
+#         BODY above for the available parameters.
+#
+# [*METHOD_LIST*]
+#         Controls the display of the listing of methods. See BODY for
+#         parameters.
+#
+# [*INDEX*]
+#         The top-level index page. For a browser-like environment
+#         define a frame set that includes the file, class, and 
+#         method indices. Passed
+#         %title%:: title of page
+#         %initial_page% :: url of initial page to display
+#
+# [*CLASS_INDEX*]
+#         Individual files for the three indexes. Passed:
+#         %index_url%:: URL of main index page
+#         %entries%::   List of
+#                       %name%:: name of an index entry
+#                       %href%:: url of corresponding page
+# [*METHOD_INDEX*]
+#         Same as CLASS_INDEX for methods
+#
+# [*FILE_INDEX*]
+#         Same as CLASS_INDEX for methods
+#
+# [*FR_INDEX_BODY*]
+#         A wrapper around CLASS_INDEX, METHOD_INDEX, and FILE_INDEX.
+#         If those index strings contain the complete HTML for the
+#         output, then FR_INDEX_BODY can simply be !INCLUDE!
+#
+# [*SRC_PAGE*]
+#         Page used to display source code. Passed %title% and %code%,
+#         the latter being a multi-line string of code.
+
+module Page
+
+FONTS = "Verdana, Arial, Helvetica, sans-serif"
+
+STYLE = %{
+body,td,p { font-family: %fonts%; 
+       color: #000040;
+}
+
+.attr-rw { font-size: x-small; color: #444488 }
+
+.title-row { background: #0000aa;
+             color:      #eeeeff;
+}
+
+.big-title-font { color: white;
+                  font-family: %fonts%;
+                  font-size: large; 
+                  height: 50px}
+
+.small-title-font { color: aqua;
+                    font-family: %fonts%;
+                    font-size: xx-small; }
+
+.aqua { color: aqua }
+
+.method-name, attr-name {
+      font-family: monospace; font-weight: bold;
+}
+
+.tablesubtitle, .tablesubsubtitle {
+   width: 100%;
+   margin-top: 1ex;
+   margin-bottom: .5ex;
+   padding: 5px 0px 5px 20px;
+   font-size: large;
+   color: aqua;
+   background: #3333cc;
+}
+
+.name-list {
+  font-family: monospace;
+  margin-left: 40px;
+  margin-bottom: 2ex;
+  line-height: 140%;
+}
+
+.description {
+  margin-left: 40px;
+  margin-top: -2ex;
+  margin-bottom: 2ex;
+}
+
+.description p {
+  line-height: 140%;
+}
+
+.aka {
+  margin-left: 40px;
+  margin-bottom: 2ex;
+  line-height: 100%;
+  font-size:   small;
+  color:       #808080;
+}
+
+.methodtitle {
+  font-size: medium;
+  text-decoration: none;
+  color: #0000AA;
+  background: white; 
+}
+
+.paramsig {
+   font-size: small;
+}
+
+.srcbut { float: right }
+
+pre { font-size: 1.2em; }
+tt  { font-size: 1.2em; }
+
+pre.source {
+  border-style: groove;
+  background-color: #ddddff;
+  margin-left:  40px;
+  padding: 1em 0em 1em 2em;
+}
+
+.classlist {
+  margin-left: 40px;
+  margin-bottom: 2ex;
+  line-height: 140%;
+}
+
+li {
+  display:    list-item;
+  margin-top: .6em;
+}
+
+.ruby-comment    { color: green; font-style: italic }
+.ruby-constant   { color: #4433aa; font-weight: bold; }
+.ruby-identifier { color: #222222;  }
+.ruby-ivar       { color: #2233dd; }
+.ruby-keyword    { color: #3333FF; font-weight: bold }
+.ruby-node       { color: #777777; }
+.ruby-operator   { color: #111111;  }
+.ruby-regexp     { color: #662222; }
+.ruby-value      { color: #662222; font-style: italic }
+
+}
+
+
+############################################################################
+
+
+HEADER = %{
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>%title%</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
+  <link rel=StyleSheet href="%style_url%" type="text/css" media="screen" />
+  <script type="text/javascript" language="JavaScript">
+  <!--
+  function popCode(url) {
+    window.open(url, "Code", 
+          "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
+  }
+  //-->
+  </script>
+</head>
+}
+
+
+###################################################################
+
+METHOD_LIST = %{
+IF:includes
+<table summary="Included modules" cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Included modules</td></tr>
+</table>
+<div class="name-list">
+START:includes
+    <span class="method-name">HREF:aref:name:</span>
+END:includes
+</div>
+ENDIF:includes
+
+IF:method_list
+START:method_list
+IF:methods
+<table summary="Method list" cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">%type% %category% methods</td></tr>
+</table>
+START:methods
+<table summary="method"  width="100%" cellspacing="0" cellpadding="5" border="0">
+<tr><td class="methodtitle">
+<a name="%aref%"></a>
+IF:codeurl
+<a href="%codeurl%" target="Code" class="methodtitle"
+ onClick="popCode('%codeurl%');return false;">
+ENDIF:codeurl
+IF:callseq
+<b>%callseq%</b>
+ENDIF:callseq
+IFNOT:callseq
+<b>%name%</b>%params%
+ENDIF:callseq
+IF:codeurl
+</a>
+ENDIF:codeurl
+</td></tr>
+</table>
+IF:m_desc
+<div class="description">
+%m_desc%
+</div>
+ENDIF:m_desc
+IF:aka
+<div class="aka">
+This method is also aliased as
+START:aka
+<a href="%aref%">%name%</a>
+END:aka
+</div>
+ENDIF:aka
+IF:sourcecode
+<pre class="source">
+%sourcecode%
+</pre>
+ENDIF:sourcecode
+END:methods
+ENDIF:methods
+END:method_list
+ENDIF:method_list
+}
+
+###################################################################
+
+CONTEXT_CONTENT = %{
+IF:diagram
+<table summary="Diagram of classes and modules" width="100%">
+<tr><td align="center">
+%diagram%
+</td></tr></table>
+ENDIF:diagram
+
+
+IF:description
+<div class="description">%description%</div>
+ENDIF:description
+
+IF:requires
+<table summary="Requires" cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Required files</td></tr>
+</table>
+<div class="name-list">
+START:requires
+HREF:aref:name:&nbsp; &nbsp;
+END:requires
+</div>
+ENDIF:requires
+
+IF:methods
+<table summary="Methods" cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Methods</td></tr>
+</table>
+<div class="name-list">
+START:methods
+HREF:aref:name:&nbsp; &nbsp;
+END:methods
+</div>
+ENDIF:methods
+
+IF:constants
+<table summary="Constants" cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Constants</td></tr>
+</table>
+<table cellpadding="5">
+START:constants
+<tr valign="top"><td>%name%</td><td>=</td><td>%value%</td></tr>
+IF:desc
+<tr><td></td><td></td><td>%desc%</td></tr>
+ENDIF:desc
+END:constants
+</table>
+ENDIF:constants
+
+IF:aliases
+<table summary="Aliases" cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">External Aliases</td></tr>
+</table>
+<div class="name-list">
+START:aliases
+%old_name% -> %new_name%<br />
+END:aliases
+</div>
+ENDIF:aliases
+
+IF:attributes
+<table summary="Attributes" cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Attributes</td></tr>
+</table>
+<table summary="Attribute details" cellspacing="5">
+START:attributes
+     <tr valign="top">
+       <td class="attr-name">%name%</td>
+IF:rw
+       <td align="center" class="attr-rw">&nbsp;[%rw%]&nbsp;</td>
+ENDIF:rw
+IFNOT:rw
+       <td></td>
+ENDIF:rw
+       <td>%a_desc%</td>
+     </tr>
+END:attributes
+</table>
+ENDIF:attributes
+
+IF:classlist
+<table summary="List of classes" cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Classes and Modules</td></tr>
+</table>
+<div class="classlist">
+%classlist%
+</div>
+ENDIF:classlist
+}
+
+###############################################################################
+
+BODY = HEADER + %{
+<body bgcolor="white">
+!INCLUDE!  <!-- banner header -->
+} +
+CONTEXT_CONTENT + METHOD_LIST +
+%{
+</body>
+</html>
+}
+
+
+###############################################################################
+
+FILE_PAGE = <<_FILE_PAGE_
+<table summary="Information on file" width="100%">
+ <tr class="title-row">
+ <td><table summary="layout" width="100%"><tr>
+   <td class="big-title-font" colspan="2">%short_name%</td>
+   <td align="right"><table summary="layout" cellspacing="0" cellpadding="2">
+         <tr>
+           <td  class="small-title-font">Path:</td>
+           <td class="small-title-font">%full_path%
+IF:cvsurl
+				&nbsp;(<a href="%cvsurl%"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
+ENDIF:cvsurl
+           </td>
+         </tr>
+         <tr>
+           <td class="small-title-font">Modified:</td>
+           <td class="small-title-font">%dtm_modified%</td>
+         </tr>
+        </table>
+    </td></tr></table></td>
+  </tr>
+</table>
+_FILE_PAGE_
+
+###################################################################
+
+CLASS_PAGE = %{
+<table summary="Information on class" width="100%" border="0" cellspacing="0">
+ <tr class="title-row">
+ <td class="big-title-font">
+   <sup><font color="aqua">%classmod%</font></sup> %full_name%
+ </td>
+ <td align="right">
+   <table summary="layout" cellspacing="0" cellpadding="2">
+     <tr valign="top">
+      <td class="small-title-font">In:</td>
+      <td class="small-title-font">
+START:infiles
+IF:full_path_url
+        <a href="%full_path_url%" class="aqua">
+ENDIF:full_path_url
+%full_path%
+IF:full_path_url
+         </a>
+ENDIF:full_path_url
+IF:cvsurl
+         &nbsp;(<a href="%cvsurl%"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
+ENDIF:cvsurl
+<br />
+END:infiles
+      </td>
+     </tr>
+IF:parent
+     <tr>
+      <td class="small-title-font">Parent:</td>
+      <td class="small-title-font">
+IF:par_url
+        <a href="%par_url%" class="aqua">
+ENDIF:par_url
+%parent%
+IF:par_url
+         </a>
+ENDIF:par_url
+      </td>
+     </tr>
+ENDIF:parent
+   </table>
+  </td>
+  </tr>
+</table>
+}
+
+=begin
+=end
+
+########################## Source code ##########################
+
+SRC_PAGE = %{
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
+<title>%title%</title>
+<link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
+</head>
+<body bgcolor="white">
+<pre>%code%</pre>
+</body>
+</html>
+}
+
+########################## Index ################################
+
+FR_INDEX_BODY = %{
+!INCLUDE!
+}
+
+FILE_INDEX = %{
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
+<title>%list_title%</title>
+<style type="text/css">
+<!--
+  body {
+background-color: #ddddff;
+     font-family: #{FONTS}; 
+       font-size: 11px; 
+      font-style: normal;
+     line-height: 14px; 
+           color: #000040;
+  }
+div.banner {
+  background: #0000aa;
+  color:      white;
+  padding: 1;
+  margin: 0;
+  font-size: 90%;
+  font-weight: bold;
+  line-height: 1.1;
+  text-align: center;
+  width: 100%;
+}
+
+A.xx { color: white; font-weight: bold; }
+-->
+</style>
+<base target="docwin">
+</head>
+<body>
+<div class="banner"><a href="%index_url%" class="xx">%list_title%</a></div>
+START:entries
+<a href="%href%">%name%</a><br />
+END:entries
+</body></html>
+}
+
+CLASS_INDEX = FILE_INDEX
+METHOD_INDEX = FILE_INDEX
+
+INDEX = %{
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
+<title>%title%</title></head>
+
+<frameset rows="20%, 80%">
+    <frameset cols="25%,35%,45%">
+        <frame src="fr_file_index.html"   title="Files" name="Files">
+        <frame src="fr_class_index.html"  name="Classes">
+        <frame src="fr_method_index.html" name="Methods">
+    </frameset>
+    <frame  src="%initial_page%" name="docwin">
+    <noframes>
+          <body bgcolor="white">
+            Sorry, RDoc currently only generates HTML using frames.
+          </body>
+    </noframes>
+</frameset>
+
+</html>
+}
+
+######################################################################
+#
+# The following is used for the -1 option
+#
+
+CONTENTS_XML = %{
+IF:description
+%description%
+ENDIF:description
+
+IF:requires
+<h4>Requires:</h4>
+<ul>
+START:requires
+IF:aref
+<li><a href="%aref%">%name%</a></li>
+ENDIF:aref
+IFNOT:aref
+<li>%name%</li>
+ENDIF:aref 
+END:requires
+</ul>
+ENDIF:requires
+
+IF:attributes
+<h4>Attributes</h4>
+<table>
+START:attributes
+<tr><td>%name%</td><td>%rw%</td><td>%a_desc%</td></tr>
+END:attributes
+</table>
+ENDIF:attributes
+
+IF:includes
+<h4>Includes</h4>
+<ul>
+START:includes
+IF:aref
+<li><a href="%aref%">%name%</a></li>
+ENDIF:aref
+IFNOT:aref
+<li>%name%</li>
+ENDIF:aref 
+END:includes
+</ul>
+ENDIF:includes
+
+IF:method_list
+<h3>Methods</h3>
+START:method_list
+IF:methods
+START:methods
+<h4>%type% %category% method: <a name="%aref%">%name%%params%</a></h4>
+
+IF:m_desc
+%m_desc%
+ENDIF:m_desc
+
+IF:sourcecode
+<blockquote><pre>
+%sourcecode%
+</pre></blockquote>
+ENDIF:sourcecode
+END:methods
+ENDIF:methods
+END:method_list
+ENDIF:method_list
+}
+
+
+end
+end
+
+require 'rdoc/generators/template/html/one_page_html'
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/one_page_html.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/one_page_html.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/html/one_page_html.rb	(revision 18425)
@@ -0,0 +1,122 @@
+module RDoc
+module Page
+######################################################################
+#
+# The following is used for the -1 option
+#
+
+CONTENTS_XML = %{
+IF:description
+%description%
+ENDIF:description
+
+IF:requires
+<h4>Requires:</h4>
+<ul>
+START:requires
+IF:aref
+<li><a href="%aref%">%name%</a></li>
+ENDIF:aref
+IFNOT:aref
+<li>%name%</li>
+ENDIF:aref 
+END:requires
+</ul>
+ENDIF:requires
+
+IF:attributes
+<h4>Attributes</h4>
+<table>
+START:attributes
+<tr><td>%name%</td><td>%rw%</td><td>%a_desc%</td></tr>
+END:attributes
+</table>
+ENDIF:attributes
+
+IF:includes
+<h4>Includes</h4>
+<ul>
+START:includes
+IF:aref
+<li><a href="%aref%">%name%</a></li>
+ENDIF:aref
+IFNOT:aref
+<li>%name%</li>
+ENDIF:aref 
+END:includes
+</ul>
+ENDIF:includes
+
+IF:method_list
+<h3>Methods</h3>
+START:method_list
+IF:methods
+START:methods
+<h4>%type% %category% method: 
+IF:callseq
+<a name="%aref%">%callseq%</a>
+ENDIF:callseq
+IFNOT:callseq
+<a name="%aref%">%name%%params%</a></h4>
+ENDIF:callseq
+
+IF:m_desc
+%m_desc%
+ENDIF:m_desc
+
+IF:sourcecode
+<blockquote><pre>
+%sourcecode%
+</pre></blockquote>
+ENDIF:sourcecode
+END:methods
+ENDIF:methods
+END:method_list
+ENDIF:method_list
+}
+
+########################################################################
+
+ONE_PAGE = %{
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+  <title>%title%</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
+</head>
+<body>
+START:files
+<h2>File: %short_name%</h2>
+<table>
+  <tr><td>Path:</td><td>%full_path%</td></tr>
+  <tr><td>Modified:</td><td>%dtm_modified%</td></tr>
+</table>
+} + CONTENTS_XML + %{
+END:files
+
+IF:classes
+<h2>Classes</h2>
+START:classes
+IF:parent
+<h3>%classmod% %full_name% &lt; HREF:par_url:parent:</h3>
+ENDIF:parent
+IFNOT:parent
+<h3>%classmod% %full_name%</h3>
+ENDIF:parent
+
+IF:infiles
+(in files
+START:infiles
+HREF:full_path_url:full_path:
+END:infiles
+)
+ENDIF:infiles
+} + CONTENTS_XML + %{
+END:classes
+ENDIF:classes
+</body>
+</html>
+}
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/xml/rdf.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/xml/rdf.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/xml/rdf.rb	(revision 18425)
@@ -0,0 +1,112 @@
+module RDoc
+module Page
+
+
+
+CONTENTS_RDF = %{
+IF:description
+    <description rd:parseType="Literal">
+%description%
+    </description>
+ENDIF:description
+
+IF:requires
+START:requires
+         <rd:required-file rd:name="%name%" />
+END:requires
+ENDIF:requires
+
+IF:attributes
+START:attributes
+        <contents>
+        <Attribute rd:name="%name%">
+IF:rw
+          <attribute-rw>%rw%</attribute-rw>
+ENDIF:rw
+          <description rdf:parseType="Literal">%a_desc%</description>
+        </Attribute>
+        </contents>
+END:attributes
+ENDIF:attributes
+
+IF:includes
+      <IncludedModuleList>
+START:includes
+        <included-module rd:name="%name%"  />
+END:includes
+      </IncludedModuleList>
+ENDIF:includes
+
+IF:method_list
+START:method_list
+IF:methods
+START:methods
+	<contents>
+        <Method rd:name="%name%" rd:visibility="%type%"
+                rd:category="%category%" rd:id="%aref%">
+          <parameters>%params%</parameters>
+IF:m_desc
+          <description rdf:parseType="Literal">
+%m_desc%
+          </description>
+ENDIF:m_desc
+IF:sourcecode
+          <source-code-listing rdf:parseType="Literal">
+%sourcecode%
+          </source-code-listing>
+ENDIF:sourcecode
+        </Method>
+       </contents>
+END:methods
+ENDIF:methods
+END:method_list
+ENDIF:method_list
+     <!-- end method list -->
+}
+
+########################################################################
+
+ONE_PAGE = %{<?xml version="1.0" encoding="utf-8"?>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+        xmlns="http://pragprog.com/rdoc/rdoc.rdf#"
+        xmlns:rd="http://pragprog.com/rdoc/rdoc.rdf#">
+
+<!-- RDoc -->
+START:files
+  <rd:File rd:name="%short_name%" rd:id="%href%">
+      <path>%full_path%</path>
+      <dtm-modified>%dtm_modified%</dtm-modified>
+} + CONTENTS_RDF + %{
+  </rd:File>
+END:files
+START:classes
+  <%classmod% rd:name="%full_name%" rd:id="%full_name%">
+    <classmod-info>
+IF:infiles
+      <InFiles>
+START:infiles
+        <infile>
+          <File rd:name="%full_path%"
+IF:full_path_url
+                rdf:about="%full_path_url%"
+ENDIF:full_path_url
+           />
+         </infile>
+END:infiles
+      </InFiles>
+ENDIF:infiles
+IF:parent
+     <superclass>HREF:par_url:parent:</superclass>
+ENDIF:parent
+    </classmod-info>
+} + CONTENTS_RDF + %{
+  </%classmod%>
+END:classes
+<!-- /RDoc -->
+</rdf:RDF>
+}
+
+
+end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/xml/xml.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/xml/xml.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/template/xml/xml.rb	(revision 18425)
@@ -0,0 +1,112 @@
+module RDoc
+module Page
+
+
+
+CONTENTS_XML = %{
+IF:description
+    <description>
+%description%
+    </description>
+ENDIF:description
+    <contents>
+IF:requires
+      <required-file-list>
+START:requires
+         <required-file name="%name%"
+IF:aref 
+                        href="%aref%"
+ENDIF:aref
+         />
+END:requires
+      </required-file-list>
+ENDIF:requires
+IF:attributes
+      <attribute-list>
+START:attributes
+        <attribute name="%name%">
+IF:rw
+          <attribute-rw>%rw%</attribute-rw>
+ENDIF:rw
+          <description>%a_desc%</description>
+        </attribute>
+END:attributes
+      </attribute-list>
+ENDIF:attributes
+IF:includes
+      <included-module-list>
+START:includes
+        <included-module name="%name%"
+IF:aref
+                         href="%aref%"
+ENDIF:aref
+        />
+END:includes
+      </included-module-list>
+ENDIF:includes
+IF:method_list
+      <method-list>
+START:method_list
+IF:methods
+START:methods
+        <method name="%name%" type="%type%" category="%category%" id="%aref%">
+          <parameters>%params%</parameters>
+IF:m_desc
+          <description>
+%m_desc%
+          </description>
+ENDIF:m_desc
+IF:sourcecode
+          <source-code-listing>
+%sourcecode%
+          </source-code-listing>
+ENDIF:sourcecode
+        </method>
+END:methods
+ENDIF:methods
+END:method_list
+      </method-list>
+ENDIF:method_list
+     </contents>
+}
+
+########################################################################
+
+ONE_PAGE = %{<?xml version="1.0" encoding="utf-8"?>
+<rdoc>
+<file-list>
+START:files
+  <file name="%short_name%" id="%href%">
+    <file-info>
+      <path>%full_path%</path>
+      <dtm-modified>%dtm_modified%</dtm-modified>
+    </file-info>
+} + CONTENTS_XML + %{
+  </file>
+END:files
+</file-list>
+<class-module-list>
+START:classes
+  <%classmod% name="%full_name%" id="%full_name%">
+    <classmod-info>
+IF:infiles
+      <infiles>      
+START:infiles
+        <infile>HREF:full_path_url:full_path:</infile>
+END:infiles
+      </infiles>
+ENDIF:infiles
+IF:parent
+     <superclass>HREF:par_url:parent:</superclass>
+ENDIF:parent
+    </classmod-info>
+} + CONTENTS_XML + %{
+  </%classmod%>
+END:classes
+</class-module-list>
+</rdoc>
+}
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/xml_generator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/xml_generator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/generators/xml_generator.rb	(revision 18425)
@@ -0,0 +1,130 @@
+
+require 'ftools'
+
+require 'rdoc/options'
+require 'rdoc/markup/simple_markup'
+require 'rdoc/markup/simple_markup/to_html'
+require 'rdoc/generators/html_generator'
+
+module Generators
+
+  # Generate XML output as one big file
+
+  class XMLGenerator < HTMLGenerator
+
+    # Standard generator factory
+    def XMLGenerator.for(options)
+      XMLGenerator.new(options)
+    end
+
+    
+    def initialize(*args)
+      super
+    end
+
+    ##
+    # Build the initial indices and output objects
+    # based on an array of TopLevel objects containing
+    # the extracted information. 
+
+    def generate(info)
+      @info       = info
+      @files      = []
+      @classes    = []
+      @hyperlinks = {}
+
+      build_indices
+      generate_xml
+    end
+
+
+    ##
+    # Generate:
+    #
+    # * a list of HtmlFile objects for each TopLevel object.
+    # * a list of HtmlClass objects for each first level
+    #   class or module in the TopLevel objects
+    # * a complete list of all hyperlinkable terms (file,
+    #   class, module, and method names)
+
+    def build_indices
+
+      @info.each do |toplevel|
+        @files << HtmlFile.new(toplevel, @options, FILE_DIR)
+      end
+
+      RDoc::TopLevel.all_classes_and_modules.each do |cls|
+        build_class_list(cls, @files[0], CLASS_DIR)
+      end
+    end
+
+    def build_class_list(from, html_file, class_dir)
+      @classes << HtmlClass.new(from, html_file, class_dir, @options)
+      from.each_classmodule do |mod|
+        build_class_list(mod, html_file, class_dir)
+      end
+    end
+
+    ##
+    # Generate all the HTML. For the one-file case, we generate
+    # all the information in to one big hash
+    #
+    def generate_xml
+      values = { 
+        'charset' => @options.charset,
+        'files'   => gen_into(@files),
+        'classes' => gen_into(@classes)
+      }
+      
+      # this method is defined in the template file
+      write_extra_pages if defined? write_extra_pages
+
+      template = TemplatePage.new(RDoc::Page::ONE_PAGE)
+
+      if @options.op_name
+        opfile = File.open(@options.op_name, "w")
+      else
+        opfile = $stdout
+      end
+      template.write_html_on(opfile, values)
+    end
+
+    def gen_into(list)
+      res = []
+      list.each do |item|
+        res << item.value_hash
+      end
+      res
+    end
+
+    def gen_file_index
+      gen_an_index(@files, 'Files')
+    end
+
+    def gen_class_index
+      gen_an_index(@classes, 'Classes')
+    end
+
+    def gen_method_index
+      gen_an_index(HtmlMethod.all_methods, 'Methods')
+    end
+
+    
+    def gen_an_index(collection, title)
+      res = []
+      collection.sort.each do |f|
+        if f.document_self
+          res << { "href" => f.path, "name" => f.index_name }
+        end
+      end
+
+      return {
+        "entries" => res,
+        'list_title' => title,
+        'index_url'  => main_url,
+      }
+    end
+
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/sample/rdoc2latex.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/sample/rdoc2latex.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/sample/rdoc2latex.rb	(revision 18425)
@@ -0,0 +1,16 @@
+#!/usr/local/bin/ruby
+# Illustration of a script to convert an RDoc-style file to a LaTeX
+# document
+
+require 'rdoc/markup/simple_markup'
+require 'rdoc/markup/simple_markup/to_latex'
+
+p = SM::SimpleMarkup.new
+h = SM::ToLaTeX.new
+
+#puts "\\documentclass{report}"
+#puts "\\usepackage{tabularx}"
+#puts "\\usepackage{parskip}"
+#puts "\\begin{document}"
+puts p.convert(ARGF.read, h)
+#puts "\\end{document}"
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/sample/sample.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/sample/sample.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/sample/sample.rb	(revision 18425)
@@ -0,0 +1,42 @@
+# This program illustrates the basic use of the SimpleMarkup
+# class. It extracts the first comment block from the 
+# simple_markup.rb file and converts it into HTML on
+# standard output. Run it using
+#
+#  % ruby sample.rb
+#
+# You should be in the sample/ directory when you do this,
+# as it hardwires the path to the files it needs to require.
+# This isn't necessary in the code you write once you've 
+# installed the package.
+#
+# For a better way of formatting code comment blocks (and more)
+# see the rdoc package.
+#
+
+$:.unshift "../../.."
+
+require 'rdoc/markup/simple_markup'
+require 'rdoc/markup/simple_markup/to_html'
+
+# Extract the comment block from the source file
+
+input_string = ""
+
+File.foreach("../simple_markup.rb") do |line|
+  break unless line.gsub!(/^\# ?/, '')
+  input_string << line
+end
+
+# Create a markup object
+markup = SM::SimpleMarkup.new
+
+# Attach it to an HTML formatter
+h = SM::ToHtml.new
+
+# And convert out comment block to html. Wrap it a body
+# tag pair to let browsers view it
+
+puts "<html><body>"
+puts markup.convert(input_string, h)
+puts "</body></html>"
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup.rb	(revision 18425)
@@ -0,0 +1,476 @@
+# = Introduction
+#
+# SimpleMarkup parses plain text documents and attempts to decompose
+# them into their constituent parts. Some of these parts are high-level:
+# paragraphs, chunks of verbatim text, list entries and the like. Other
+# parts happen at the character level: a piece of bold text, a word in
+# code font. This markup is similar in spirit to that used on WikiWiki
+# webs, where folks create web pages using a simple set of formatting
+# rules.
+#
+# SimpleMarkup itself does no output formatting: this is left to a
+# different set of classes.
+#
+# SimpleMarkup is extendable at runtime: you can add new markup
+# elements to be recognised in the documents that SimpleMarkup parses.
+#
+# SimpleMarkup is intended to be the basis for a family of tools which
+# share the common requirement that simple, plain-text should be
+# rendered in a variety of different output formats and media. It is
+# envisaged that SimpleMarkup could be the basis for formating RDoc
+# style comment blocks, Wiki entries, and online FAQs.
+#
+# = Basic Formatting
+#
+# * SimpleMarkup looks for a document's natural left margin. This is
+#   used as the initial margin for the document.
+#
+# * Consecutive lines starting at this margin are considered to be a
+#   paragraph.
+#
+# * If a paragraph starts with a "*", "-", or with "<digit>.", then it is
+#   taken to be the start of a list. The margin in increased to be the
+#   first non-space following the list start flag. Subsequent lines
+#   should be indented to this new margin until the list ends. For
+#   example:
+#
+#      * this is a list with three paragraphs in
+#        the first item. This is the first paragraph.
+#
+#        And this is the second paragraph.
+#
+#        1. This is an indented, numbered list.
+#        2. This is the second item in that list
+#
+#        This is the third conventional paragraph in the
+#        first list item.
+#
+#      * This is the second item in the original list
+#
+# * You can also construct labeled lists, sometimes called description
+#   or definition lists. Do this by putting the label in square brackets
+#   and indenting the list body:
+#
+#       [cat]  a small furry mammal
+#              that seems to sleep a lot
+#
+#       [ant]  a little insect that is known
+#              to enjoy picnics
+#
+#   A minor variation on labeled lists uses two colons to separate the
+#   label from the list body:
+#
+#       cat::  a small furry mammal
+#              that seems to sleep a lot
+#
+#       ant::  a little insect that is known
+#              to enjoy picnics
+#     
+#   This latter style guarantees that the list bodies' left margins are
+#   aligned: think of them as a two column table.
+#
+# * Any line that starts to the right of the current margin is treated
+#   as verbatim text. This is useful for code listings. The example of a
+#   list above is also verbatim text.
+#
+# * A line starting with an equals sign (=) is treated as a
+#   heading. Level one headings have one equals sign, level two headings
+#   have two,and so on.
+#
+# * A line starting with three or more hyphens (at the current indent)
+#   generates a horizontal rule. THe more hyphens, the thicker the rule
+#   (within reason, and if supported by the output device)
+#
+# * You can use markup within text (except verbatim) to change the
+#   appearance of parts of that text. Out of the box, SimpleMarkup
+#   supports word-based and general markup.
+#
+#   Word-based markup uses flag characters around individual words:
+#
+#   [\*word*]  displays word in a *bold* font
+#   [\_word_]  displays word in an _emphasized_ font
+#   [\+word+]  displays word in a +code+ font
+#
+#   General markup affects text between a start delimiter and and end
+#   delimiter. Not surprisingly, these delimiters look like HTML markup.
+#
+#   [\<b>text...</b>]    displays word in a *bold* font
+#   [\<em>text...</em>]  displays word in an _emphasized_ font
+#   [\<i>text...</i>]    displays word in an _emphasized_ font
+#   [\<tt>text...</tt>]  displays word in a +code+ font
+#
+#   Unlike conventional Wiki markup, general markup can cross line
+#   boundaries. You can turn off the interpretation of markup by
+#   preceding the first character with a backslash, so \\\<b>bold
+#   text</b> and \\\*bold* produce \<b>bold text</b> and \*bold
+#   respectively.
+#
+# = Using SimpleMarkup
+#
+# For information on using SimpleMarkup programatically, 
+# see SM::SimpleMarkup.
+#
+# Author::   Dave Thomas,  dave@pragmaticprogrammer.com
+# Version::  0.0
+# License::  Ruby license
+
+
+
+require 'rdoc/markup/simple_markup/fragments'
+require 'rdoc/markup/simple_markup/lines.rb'
+
+module SM  #:nodoc:
+
+  # == Synopsis
+  #
+  # This code converts <tt>input_string</tt>, which is in the format
+  # described in markup/simple_markup.rb, to HTML. The conversion
+  # takes place in the +convert+ method, so you can use the same
+  # SimpleMarkup object to convert multiple input strings.
+  #
+  #   require 'rdoc/markup/simple_markup'
+  #   require 'rdoc/markup/simple_markup/to_html'
+  #
+  #   p = SM::SimpleMarkup.new
+  #   h = SM::ToHtml.new
+  #
+  #   puts p.convert(input_string, h)
+  #
+  # You can extend the SimpleMarkup parser to recognise new markup
+  # sequences, and to add special processing for text that matches a
+  # regular epxression. Here we make WikiWords significant to the parser,
+  # and also make the sequences {word} and \<no>text...</no> signify
+  # strike-through text. When then subclass the HTML output class to deal
+  # with these:
+  #
+  #   require 'rdoc/markup/simple_markup'
+  #   require 'rdoc/markup/simple_markup/to_html'
+  #
+  #   class WikiHtml < SM::ToHtml
+  #     def handle_special_WIKIWORD(special)
+  #       "<font color=red>" + special.text + "</font>"
+  #     end
+  #   end
+  #
+  #   p = SM::SimpleMarkup.new
+  #   p.add_word_pair("{", "}", :STRIKE)
+  #   p.add_html("no", :STRIKE)
+  #
+  #   p.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
+  #
+  #   h = WikiHtml.new
+  #   h.add_tag(:STRIKE, "<strike>", "</strike>")
+  #
+  #   puts "<body>" + p.convert(ARGF.read, h) + "</body>"
+  #
+  # == Output Formatters
+  #
+  # _missing_
+  #
+  #
+
+  class SimpleMarkup
+
+    SPACE = ?\s
+
+    # List entries look like:
+    #  *       text
+    #  1.      text
+    #  [label] text
+    #  label:: text
+    #
+    # Flag it as a list entry, and
+    # work out the indent for subsequent lines
+
+    SIMPLE_LIST_RE = /^(
+                  (  \*          (?# bullet)
+                    |-           (?# bullet)
+                    |\d+\.       (?# numbered )
+                    |[A-Za-z]\.  (?# alphabetically numbered )
+                  )
+                  \s+
+                )\S/x
+
+    LABEL_LIST_RE = /^(
+                        (  \[.*?\]    (?# labeled  )
+                          |\S.*::     (?# note     )
+                        )(?:\s+|$)
+                      )/x
+
+
+    ##
+    # take a block of text and use various heuristics to determine
+    # it's structure (paragraphs, lists, and so on). Invoke an
+    # event handler as we identify significant chunks.
+    #
+
+    def initialize
+      @am = AttributeManager.new
+      @output = nil
+    end
+
+    ##
+    # Add to the sequences used to add formatting to an individual word 
+    # (such as *bold*). Matching entries will generate attibutes
+    # that the output formatters can recognize by their +name+
+
+    def add_word_pair(start, stop, name)
+      @am.add_word_pair(start, stop, name)
+    end
+
+    ##
+    # Add to the sequences recognized as general markup
+    #
+
+    def add_html(tag, name)
+      @am.add_html(tag, name)
+    end
+
+    ##
+    # Add to other inline sequences. For example, we could add
+    # WikiWords using something like:
+    #
+    #    parser.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
+    #
+    # Each wiki word will be presented to the output formatter 
+    # via the accept_special method
+    #
+
+    def add_special(pattern, name)
+      @am.add_special(pattern, name)
+    end
+
+
+    # We take a string, split it into lines, work out the type of
+    # each line, and from there deduce groups of lines (for example
+    # all lines in a paragraph). We then invoke the output formatter
+    # using a Visitor to display the result
+
+    def convert(str, op)
+      @lines = Lines.new(str.split(/\r?\n/).collect { |aLine| 
+                           Line.new(aLine) })
+      return "" if @lines.empty?
+      @lines.normalize
+      assign_types_to_lines
+      group = group_lines
+      # call the output formatter to handle the result
+      #      group.to_a.each {|i| p i}
+      group.accept(@am, op)
+    end
+
+
+    #######
+    private
+    #######
+
+
+    ##
+    # Look through the text at line indentation. We flag each line as being
+    # Blank, a paragraph, a list element, or verbatim text
+    #
+
+    def assign_types_to_lines(margin = 0, level = 0)
+
+      while line = @lines.next
+        if line.isBlank?
+          line.stamp(Line::BLANK, level)
+          next
+        end
+        
+        # if a line contains non-blanks before the margin, then it must belong
+        # to an outer level
+
+        text = line.text
+        
+        for i in 0...margin
+          if text[i] != SPACE
+            @lines.unget
+            return
+          end
+        end
+
+        active_line = text[margin..-1]
+
+        # Rules (horizontal lines) look like
+        #
+        #  ---   (three or more hyphens)
+        #
+        # The more hyphens, the thicker the rule
+        #
+
+        if /^(---+)\s*$/ =~ active_line
+          line.stamp(Line::RULE, level, $1.length-2)
+          next
+        end
+
+        # Then look for list entries. First the ones that have to have
+        # text following them (* xxx, - xxx, and dd. xxx)
+
+        if SIMPLE_LIST_RE =~ active_line
+
+          offset = margin + $1.length
+          prefix = $2
+          prefix_length = prefix.length
+
+          flag = case prefix
+                 when "*","-" then ListBase::BULLET
+                 when /^\d/   then ListBase::NUMBER
+                 when /^[A-Z]/ then ListBase::UPPERALPHA
+                 when /^[a-z]/ then ListBase::LOWERALPHA
+                 else raise "Invalid List Type: #{self.inspect}"
+                 end
+
+          line.stamp(Line::LIST, level+1, prefix, flag)
+          text[margin, prefix_length] = " " * prefix_length
+          assign_types_to_lines(offset, level + 1)
+          next
+        end
+
+
+        if LABEL_LIST_RE =~ active_line
+          offset = margin + $1.length
+          prefix = $2
+          prefix_length = prefix.length
+
+          next if handled_labeled_list(line, level, margin, offset, prefix)
+        end
+
+        # Headings look like
+        # = Main heading
+        # == Second level
+        # === Third
+        #
+        # Headings reset the level to 0
+
+        if active_line[0] == ?= and active_line =~ /^(=+)\s*(.*)/
+          prefix_length = $1.length
+          prefix_length = 6 if prefix_length > 6
+          line.stamp(Line::HEADING, 0, prefix_length)
+          line.strip_leading(margin + prefix_length)
+          next
+        end
+        
+        # If the character's a space, then we have verbatim text,
+        # otherwise 
+
+        if active_line[0] == SPACE
+          line.strip_leading(margin) if margin > 0
+          line.stamp(Line::VERBATIM, level)
+        else
+          line.stamp(Line::PARAGRAPH, level)
+        end
+      end
+    end
+
+    # Handle labeled list entries, We have a special case
+    # to deal with. Because the labels can be long, they force
+    # the remaining block of text over the to right:
+    #
+    # this is a long label that I wrote:: and here is the
+    #                                     block of text with
+    #                                     a silly margin
+    #
+    # So we allow the special case. If the label is followed
+    # by nothing, and if the following line is indented, then
+    # we take the indent of that line as the new margin
+    #
+    # this is a long label that I wrote::
+    #     here is a more reasonably indented block which
+    #     will ab attached to the label.
+    #
+    
+    def handled_labeled_list(line, level, margin, offset, prefix)
+      prefix_length = prefix.length
+      text = line.text
+      flag = nil
+      case prefix
+      when /^\[/
+        flag = ListBase::LABELED
+        prefix = prefix[1, prefix.length-2]
+      when /:$/
+        flag = ListBase::NOTE
+        prefix.chop!
+      else raise "Invalid List Type: #{self.inspect}"
+      end
+      
+      # body is on the next line
+      
+      if text.length <= offset
+        original_line = line
+        line = @lines.next
+        return(false) unless line
+        text = line.text
+        
+        for i in 0..margin
+          if text[i] != SPACE
+            @lines.unget
+            return false
+          end
+        end
+        i = margin
+        i += 1 while text[i] == SPACE
+        if i >= text.length
+          @lines.unget
+          return false
+        else
+          offset = i
+          prefix_length = 0
+          @lines.delete(original_line)
+        end
+      end
+      
+      line.stamp(Line::LIST, level+1, prefix, flag)
+      text[margin, prefix_length] = " " * prefix_length
+      assign_types_to_lines(offset, level + 1)
+      return true
+    end
+
+    # Return a block consisting of fragments which are
+    # paragraphs, list entries or verbatim text. We merge consecutive
+    # lines of the same type and level together. We are also slightly
+    # tricky with lists: the lines following a list introduction
+    # look like paragraph lines at the next level, and we remap them
+    # into list entries instead
+
+    def group_lines
+      @lines.rewind
+
+      inList = false
+      wantedType = wantedLevel = nil
+
+      block = LineCollection.new
+      group = nil
+
+      while line = @lines.next
+        if line.level == wantedLevel and line.type == wantedType
+          group.add_text(line.text)
+        else
+          group = block.fragment_for(line)
+          block.add(group)
+          if line.type == Line::LIST
+            wantedType = Line::PARAGRAPH
+          else
+            wantedType = line.type
+          end
+          wantedLevel = line.type == Line::HEADING ? line.param : line.level
+        end
+      end
+
+      block.normalize
+      block
+    end
+
+    ## for debugging, we allow access to our line contents as text
+    def content
+      @lines.as_text
+    end
+    public :content
+
+    ## for debugging, return the list of line types
+    def get_line_types
+      @lines.line_types
+    end
+    public :get_line_types
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/fragments.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/fragments.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/fragments.rb	(revision 18425)
@@ -0,0 +1,328 @@
+require 'rdoc/markup/simple_markup/lines.rb'
+#require 'rdoc/markup/simple_markup/to_flow.rb'
+
+module SM
+
+  ##
+  # A Fragment is a chunk of text, subclassed as a paragraph, a list
+  # entry, or verbatim text
+
+  class Fragment
+    attr_reader   :level, :param, :txt
+    attr_accessor :type
+
+    def initialize(level, param, type, txt)
+      @level = level
+      @param = param
+      @type  = type
+      @txt   = ""
+      add_text(txt) if txt
+    end
+
+    def add_text(txt)
+      @txt << " " if @txt.length > 0
+      @txt << txt.tr_s("\n ", "  ").strip
+    end
+
+    def to_s
+      "L#@level: #{self.class.name.split('::')[-1]}\n#@txt"
+    end
+
+    ######
+    # This is a simple factory system that lets us associate fragement
+    # types (a string) with a subclass of fragment
+
+    TYPE_MAP = {}
+
+    def Fragment.type_name(name)
+      TYPE_MAP[name] = self
+    end
+
+    def Fragment.for(line)
+      klass =  TYPE_MAP[line.type] ||
+        raise("Unknown line type: '#{line.type.inspect}:' '#{line.text}'")
+      return klass.new(line.level, line.param, line.flag, line.text)
+    end
+  end
+
+  ##
+  # A paragraph is a fragment which gets wrapped to fit. We remove all
+  # newlines when we're created, and have them put back on output
+
+  class Paragraph < Fragment
+    type_name Line::PARAGRAPH
+  end
+
+  class BlankLine < Paragraph
+    type_name Line::BLANK
+  end
+
+  class Heading < Paragraph
+    type_name Line::HEADING
+
+    def head_level
+      @param.to_i
+    end
+  end
+
+  ##
+  # A List is a fragment with some kind of label
+  #
+
+  class ListBase < Paragraph
+    # List types
+    BULLET  = :BULLET
+    NUMBER  = :NUMBER
+    UPPERALPHA  = :UPPERALPHA
+    LOWERALPHA  = :LOWERALPHA
+    LABELED = :LABELED
+    NOTE    = :NOTE
+  end
+
+  class ListItem < ListBase
+    type_name Line::LIST
+
+    #  def label
+    #    am = AttributeManager.new(@param)
+    #    am.flow
+    #  end
+  end
+
+  class ListStart < ListBase
+    def initialize(level, param, type)
+      super(level, param, type, nil)
+    end
+  end
+
+  class ListEnd < ListBase
+    def initialize(level, type)
+      super(level, "", type, nil)
+    end
+  end
+
+  ##
+  # Verbatim code contains lines that don't get wrapped.
+
+  class Verbatim < Fragment
+    type_name  Line::VERBATIM
+
+    def add_text(txt)
+      @txt << txt.chomp << "\n"
+    end
+
+  end
+
+  ##
+  # A horizontal rule
+  class Rule < Fragment
+    type_name Line::RULE
+  end
+
+
+  # Collect groups of lines together. Each group
+  # will end up containing a flow of text
+
+  class LineCollection
+    
+    def initialize
+      @fragments = []
+    end
+
+    def add(fragment)
+      @fragments << fragment
+    end
+
+    def each(&b)
+      @fragments.each(&b)
+    end
+
+    # For testing
+    def to_a
+      @fragments.map {|fragment| fragment.to_s}
+    end
+
+    # Factory for different fragment types
+    def fragment_for(*args)
+      Fragment.for(*args)
+    end
+
+    # tidy up at the end
+    def normalize
+      change_verbatim_blank_lines
+      add_list_start_and_ends
+      add_list_breaks
+      tidy_blank_lines
+    end
+
+    def to_s
+      @fragments.join("\n----\n")
+    end
+
+    def accept(am, visitor)
+
+      visitor.start_accepting
+
+      @fragments.each do |fragment|
+        case fragment
+        when Verbatim
+          visitor.accept_verbatim(am, fragment)
+        when Rule
+          visitor.accept_rule(am, fragment)
+        when ListStart
+          visitor.accept_list_start(am, fragment)
+        when ListEnd
+          visitor.accept_list_end(am, fragment)
+        when ListItem
+          visitor.accept_list_item(am, fragment)
+        when BlankLine
+          visitor.accept_blank_line(am, fragment)
+        when Heading
+          visitor.accept_heading(am, fragment)
+        when Paragraph
+          visitor.accept_paragraph(am, fragment)
+        end
+      end
+
+      visitor.end_accepting
+    end
+    #######
+    private
+    #######
+
+    # If you have:
+    #
+    #    normal paragraph text.
+    #
+    #       this is code
+    #   
+    #       and more code
+    #
+    # You'll end up with the fragments Paragraph, BlankLine, 
+    # Verbatim, BlankLine, Verbatim, BlankLine, etc
+    #
+    # The BlankLine in the middle of the verbatim chunk needs to
+    # be changed to a real verbatim newline, and the two
+    # verbatim blocks merged
+    #
+    #    
+    def change_verbatim_blank_lines
+      frag_block = nil
+      blank_count = 0
+      @fragments.each_with_index do |frag, i|
+        if frag_block.nil?
+          frag_block = frag if Verbatim === frag
+        else
+          case frag
+          when Verbatim
+            blank_count.times { frag_block.add_text("\n") }
+            blank_count = 0
+            frag_block.add_text(frag.txt)
+            @fragments[i] = nil    # remove out current fragment
+          when BlankLine
+            if frag_block
+              blank_count += 1
+              @fragments[i] = nil
+            end
+          else
+            frag_block = nil
+            blank_count = 0
+          end
+        end
+      end
+      @fragments.compact!
+    end
+
+    # List nesting is implicit given the level of
+    # Make it explicit, just to make life a tad
+    # easier for the output processors
+
+    def add_list_start_and_ends
+      level = 0
+      res = []
+      type_stack = []
+
+      @fragments.each do |fragment|
+        # $stderr.puts "#{level} : #{fragment.class.name} : #{fragment.level}"
+        new_level = fragment.level
+        while (level < new_level)
+          level += 1
+          type = fragment.type
+          res << ListStart.new(level, fragment.param, type) if type
+          type_stack.push type
+          # $stderr.puts "Start: #{level}"
+        end
+
+        while level > new_level
+          type = type_stack.pop
+          res << ListEnd.new(level, type) if type
+          level -= 1
+          # $stderr.puts "End: #{level}, #{type}"
+        end
+
+        res << fragment
+        level = fragment.level
+      end
+      level.downto(1) do |i|
+        type = type_stack.pop
+        res << ListEnd.new(i, type) if type
+      end
+
+      @fragments = res
+    end
+
+    # now insert start/ends between list entries at the
+    # same level that have different element types
+
+    def add_list_breaks
+      res = @fragments
+
+      @fragments = []
+      list_stack = []
+
+      res.each do |fragment|
+        case fragment
+        when ListStart
+          list_stack.push fragment
+        when ListEnd
+          start = list_stack.pop
+          fragment.type = start.type
+        when ListItem
+          l = list_stack.last
+          if fragment.type != l.type
+            @fragments << ListEnd.new(l.level, l.type)
+            start = ListStart.new(l.level, fragment.param, fragment.type)
+            @fragments << start
+            list_stack.pop
+            list_stack.push start
+          end
+        else
+          ;
+        end
+        @fragments << fragment
+      end
+    end
+
+    # Finally tidy up the blank lines:
+    # * change Blank/ListEnd into ListEnd/Blank
+    # * remove blank lines at the front
+
+    def tidy_blank_lines
+      (@fragments.size - 1).times do |i|
+        if @fragments[i].kind_of?(BlankLine) and 
+            @fragments[i+1].kind_of?(ListEnd)
+          @fragments[i], @fragments[i+1] = @fragments[i+1], @fragments[i] 
+        end
+      end
+
+      # remove leading blanks
+      @fragments.each_with_index do |f, i|
+        break unless f.kind_of? BlankLine
+        @fragments[i] = nil
+      end
+
+      @fragments.compact!
+    end
+
+  end
+  
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/inline.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/inline.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/inline.rb	(revision 18425)
@@ -0,0 +1,340 @@
+module SM
+
+  # We manage a set of attributes. Each attribute has a symbol name
+  # and a bit value
+
+  class Attribute
+    SPECIAL = 1
+
+    @@name_to_bitmap = { :_SPECIAL_ => SPECIAL }
+    @@next_bitmap = 2
+
+    def Attribute.bitmap_for(name)
+      bitmap = @@name_to_bitmap[name]
+      if !bitmap
+        bitmap = @@next_bitmap
+        @@next_bitmap <<= 1
+        @@name_to_bitmap[name] = bitmap
+      end
+      bitmap
+    end
+
+    def Attribute.as_string(bitmap)
+      return "none" if bitmap.zero?
+      res = []
+      @@name_to_bitmap.each do |name, bit|
+        res << name if (bitmap & bit) != 0
+      end
+      res.join(",")
+    end
+
+    def Attribute.each_name_of(bitmap)
+      @@name_to_bitmap.each do |name, bit|
+        next if bit == SPECIAL
+        yield name.to_s if (bitmap & bit) != 0
+      end
+    end
+  end
+
+
+  # An AttrChanger records a change in attributes. It contains
+  # a bitmap of the attributes to turn on, and a bitmap of those to
+  # turn off
+
+  AttrChanger = Struct.new(:turn_on, :turn_off)
+  class AttrChanger
+    def to_s
+      "Attr: +#{Attribute.as_string(@turn_on)}/-#{Attribute.as_string(@turn_on)}"
+    end
+  end
+
+  # An array of attributes which parallels the characters in a string
+  class AttrSpan
+    def initialize(length)
+      @attrs = Array.new(length, 0)
+    end
+
+    def set_attrs(start, length, bits)
+      for i in start ... (start+length)
+        @attrs[i] |= bits
+      end
+    end
+
+    def [](n)
+      @attrs[n]
+    end
+  end
+
+  ##
+  # Hold details of a special sequence
+
+  class Special
+    attr_reader   :type
+    attr_accessor :text
+
+    def initialize(type, text)
+      @type, @text = type, text
+    end
+
+    def ==(o)
+      self.text == o.text && self.type == o.type
+    end
+
+    def to_s
+      "Special: type=#{type}, text=#{text.dump}"
+    end
+  end
+  
+  class AttributeManager
+
+    NULL = "\000".freeze
+
+    ##
+    # We work by substituting non-printing characters in to the
+    # text. For now I'm assuming that I can substitute
+    # a character in the range 0..8 for a 7 bit character
+    # without damaging the encoded string, but this might
+    # be optimistic
+    #
+
+    A_PROTECT  = 004
+    PROTECT_ATTR  = A_PROTECT.chr
+
+    # This maps delimiters that occur around words (such as
+    # *bold* or +tt+) where the start and end delimiters
+    # and the same. This lets us optimize the regexp
+    MATCHING_WORD_PAIRS = {}
+
+    # And this is used when the delimiters aren't the same. In this
+    # case the hash maps a pattern to the attribute character
+    WORD_PAIR_MAP = {}
+
+    # This maps HTML tags to the corresponding attribute char
+    HTML_TAGS = {}
+
+    # And this maps _special_ sequences to a name. A special sequence
+    # is something like a WikiWord
+    SPECIAL = {}
+
+    # Return an attribute object with the given turn_on
+    # and turn_off bits set
+
+    def attribute(turn_on, turn_off)
+      AttrChanger.new(turn_on, turn_off)
+    end
+
+
+    def change_attribute(current, new)
+      diff = current ^ new
+      attribute(new & diff, current & diff)
+    end
+
+    def changed_attribute_by_name(current_set, new_set)
+      current = new = 0
+      current_set.each {|name| current |= Attribute.bitmap_for(name) }
+      new_set.each {|name| new |= Attribute.bitmap_for(name) }
+      change_attribute(current, new)
+    end
+
+    def copy_string(start_pos, end_pos)
+      res = @str[start_pos...end_pos]
+      res.gsub!(/\000/, '')
+      res
+    end
+
+    # Map attributes like <b>text</b>to the sequence \001\002<char>\001\003<char>,
+    # where <char> is a per-attribute specific character
+
+    def convert_attrs(str, attrs)
+      # first do matching ones
+      tags = MATCHING_WORD_PAIRS.keys.join("")
+      re = "(^|\\W)([#{tags}])([A-Za-z_]+?)\\2(\\W|\$)"
+#      re = "(^|\\W)([#{tags}])(\\S+?)\\2(\\W|\$)"
+      1 while str.gsub!(Regexp.new(re)) {
+        attr = MATCHING_WORD_PAIRS[$2];
+        attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr)
+        $1 + NULL*$2.length + $3 + NULL*$2.length + $4
+      }
+
+      # then non-matching
+      unless WORD_PAIR_MAP.empty?
+        WORD_PAIR_MAP.each do |regexp, attr|
+          str.gsub!(regexp) { 
+            attrs.set_attrs($`.length + $1.length, $2.length, attr)
+            NULL*$1.length + $2 + NULL*$3.length
+          }
+        end
+      end
+    end
+
+    def convert_html(str, attrs)
+      tags = HTML_TAGS.keys.join("|")
+      re = "<(#{tags})>(.*?)</\\1>"
+      1 while str.gsub!(Regexp.new(re, Regexp::IGNORECASE)) {
+        attr = HTML_TAGS[$1.downcase]
+        html_length = $1.length + 2
+        seq = NULL * html_length
+        attrs.set_attrs($`.length + html_length, $2.length, attr)
+        seq + $2 + seq + NULL
+      }
+    end
+
+    def convert_specials(str, attrs)
+      unless SPECIAL.empty?
+        SPECIAL.each do |regexp, attr|
+          str.scan(regexp) do
+            attrs.set_attrs($`.length, $&.length, attr | Attribute::SPECIAL)
+          end
+        end
+      end
+    end
+
+    # A \ in front of a character that would normally be
+    # processed turns off processing. We do this by turning
+    # \< into <#{PROTECT}
+    
+    PROTECTABLE = [ "<" << "\\" ]  #"
+
+
+    def mask_protected_sequences
+      protect_pattern = Regexp.new("\\\\([#{Regexp.escape(PROTECTABLE.join(''))}])")
+      @str.gsub!(protect_pattern, "\\1#{PROTECT_ATTR}")
+    end
+
+    def unmask_protected_sequences
+      @str.gsub!(/(.)#{PROTECT_ATTR}/, "\\1\000")
+    end
+
+    def initialize
+      add_word_pair("*", "*", :BOLD)
+      add_word_pair("_", "_", :EM)
+      add_word_pair("+", "+", :TT)
+      
+      add_html("em", :EM)
+      add_html("i",  :EM)
+      add_html("b",  :BOLD)
+      add_html("tt",   :TT)
+      add_html("code", :TT)
+
+      add_special(/<!--(.*?)-->/, :COMMENT)
+    end
+
+    def add_word_pair(start, stop, name)
+      raise "Word flags may not start '<'" if start[0] == ?<
+      bitmap = Attribute.bitmap_for(name)
+      if start == stop
+        MATCHING_WORD_PAIRS[start] = bitmap
+      else
+        pattern = Regexp.new("(" + Regexp.escape(start) + ")" +
+#                             "([A-Za-z]+)" +
+                             "(\\S+)" +
+                             "(" + Regexp.escape(stop) +")")
+        WORD_PAIR_MAP[pattern] = bitmap
+      end
+      PROTECTABLE << start[0,1]
+      PROTECTABLE.uniq!
+    end
+
+    def add_html(tag, name)
+      HTML_TAGS[tag.downcase] = Attribute.bitmap_for(name)
+    end
+
+    def add_special(pattern, name)
+      SPECIAL[pattern] = Attribute.bitmap_for(name)
+    end
+
+    def flow(str)
+      @str = str
+
+      puts("Before flow, str='#{@str.dump}'") if $DEBUG
+      mask_protected_sequences
+ 
+      @attrs = AttrSpan.new(@str.length)
+
+      puts("After protecting, str='#{@str.dump}'") if $DEBUG
+      convert_attrs(@str, @attrs)
+      convert_html(@str, @attrs)
+      convert_specials(str, @attrs)
+      unmask_protected_sequences
+      puts("After flow, str='#{@str.dump}'") if $DEBUG
+      return split_into_flow
+    end
+
+    def display_attributes
+      puts
+      puts @str.tr(NULL, "!")
+      bit = 1
+      16.times do |bno|
+        line = ""
+        @str.length.times do |i|
+          if (@attrs[i] & bit) == 0
+            line << " "
+          else
+            if bno.zero?
+              line << "S"
+            else
+              line << ("%d" % (bno+1))
+            end
+          end
+        end
+        puts(line) unless line =~ /^ *$/
+        bit <<= 1
+      end
+    end
+
+    def split_into_flow
+
+      display_attributes if $DEBUG
+
+      res = []
+      current_attr = 0
+      str = ""
+
+      
+      str_len = @str.length
+
+      # skip leading invisible text
+      i = 0
+      i += 1 while i < str_len and @str[i].zero?
+      start_pos = i
+
+      # then scan the string, chunking it on attribute changes
+      while i < str_len
+        new_attr = @attrs[i]
+        if new_attr != current_attr
+          if i > start_pos
+            res << copy_string(start_pos, i)
+            start_pos = i
+          end
+
+          res << change_attribute(current_attr, new_attr)
+          current_attr = new_attr
+
+          if (current_attr & Attribute::SPECIAL) != 0
+            i += 1 while i < str_len and (@attrs[i] & Attribute::SPECIAL) != 0
+            res << Special.new(current_attr, copy_string(start_pos, i))
+            start_pos = i
+            next
+          end
+        end
+
+        # move on, skipping any invisible characters
+        begin
+          i += 1
+        end while i < str_len and @str[i].zero?
+      end
+      
+      # tidy up trailing text
+      if start_pos < str_len
+        res << copy_string(start_pos, str_len)
+      end
+
+      # and reset to all attributes off
+      res << change_attribute(current_attr, 0) if current_attr != 0
+
+      return res
+    end
+
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/lines.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/lines.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/lines.rb	(revision 18425)
@@ -0,0 +1,151 @@
+##########################################################################
+#
+# We store the lines we're working on as objects of class Line.
+# These contain the text of the line, along with a flag indicating the
+# line type, and an indentation level
+
+module SM
+
+  class Line
+    INFINITY = 9999
+
+    BLANK     = :BLANK
+    HEADING   = :HEADING
+    LIST      = :LIST
+    RULE      = :RULE
+    PARAGRAPH = :PARAGRAPH
+    VERBATIM  = :VERBATIM
+    
+    # line type
+    attr_accessor :type
+
+    # The indentation nesting level
+    attr_accessor :level
+
+    # The contents
+    attr_accessor :text
+
+    # A prefix or parameter. For LIST lines, this is
+    # the text that introduced the list item (the label)
+    attr_accessor  :param
+
+    # A flag. For list lines, this is the type of the list
+    attr_accessor :flag
+
+    # the number of leading spaces
+    attr_accessor :leading_spaces
+
+    # true if this line has been deleted from the list of lines
+    attr_accessor :deleted
+    
+
+    def initialize(text)
+      @text    = text.dup
+      @deleted = false
+
+      # expand tabs
+      1 while @text.gsub!(/\t+/) { ' ' * (8*$&.length - $`.length % 8)}  && $~ #`
+
+      # Strip trailing whitespace
+      @text.sub!(/\s+$/, '')
+
+      # and look for leading whitespace
+      if @text.length > 0
+        @text =~ /^(\s*)/
+        @leading_spaces = $1.length
+      else
+        @leading_spaces = INFINITY
+      end
+    end
+
+    # Return true if this line is blank
+    def isBlank?
+      @text.length.zero?
+    end
+
+    # stamp a line with a type, a level, a prefix, and a flag
+    def stamp(type, level, param="", flag=nil)
+      @type, @level, @param, @flag = type, level, param, flag
+    end
+
+    ##
+    # Strip off the leading margin
+    #
+
+    def strip_leading(size)
+      if @text.size > size
+        @text[0,size] = ""
+      else
+        @text = ""
+      end
+    end
+
+    def to_s
+      "#@type#@level: #@text"
+    end
+  end
+
+  ###############################################################################
+  #
+  # A container for all the lines
+  #
+
+  class Lines
+    include Enumerable
+
+    attr_reader :lines   # for debugging
+
+    def initialize(lines)
+      @lines = lines
+      rewind
+    end
+
+    def empty?
+      @lines.size.zero?
+    end
+
+    def each
+      @lines.each do |line|
+        yield line unless line.deleted
+      end
+    end
+
+#    def [](index)
+#      @lines[index]
+#    end
+
+    def rewind
+      @nextline = 0
+    end
+
+    def next
+      begin
+        res = @lines[@nextline]
+        @nextline += 1 if @nextline < @lines.size
+      end while res and res.deleted and @nextline < @lines.size
+      res
+    end
+
+    def unget
+      @nextline -= 1
+    end
+
+    def delete(a_line)
+      a_line.deleted = true
+    end
+
+    def normalize
+      margin = @lines.collect{|l| l.leading_spaces}.min
+      margin = 0 if margin == Line::INFINITY
+      @lines.each {|line| line.strip_leading(margin) } if margin > 0
+    end
+
+    def as_text
+      @lines.map {|l| l.text}.join("\n")
+    end
+
+    def line_types
+      @lines.map {|l| l.type }
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/preprocess.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/preprocess.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/preprocess.rb	(revision 18425)
@@ -0,0 +1,73 @@
+module SM
+
+  ## 
+  # Handle common directives that can occur in a block of text:
+  #
+  # : include : filename
+  #
+
+  class PreProcess
+
+    def initialize(input_file_name, include_path)
+      @input_file_name = input_file_name
+      @include_path = include_path
+    end
+
+    # Look for common options in a chunk of text. Options that
+    # we don't handle are passed back to our caller
+    # as |directive, param| 
+
+    def handle(text)
+      text.gsub!(/^([ \t#]*):(\w+):\s*(.+)?\n/) do 
+        prefix    = $1
+        directive = $2.downcase
+        param     = $3
+
+        case directive
+        when "include"
+          filename = param.split[0]
+          include_file(filename, prefix)
+
+        else
+          yield(directive, param)
+        end
+      end
+    end
+
+    #######
+    private
+    #######
+
+    # Include a file, indenting it correctly
+
+    def include_file(name, indent)
+      if (full_name = find_include_file(name))
+        content = File.open(full_name) {|f| f.read}
+        # strip leading '#'s, but only if all lines start with them
+        if content =~ /^[^#]/
+          content.gsub(/^/, indent)
+        else
+          content.gsub(/^#?/, indent)
+        end
+      else
+        $stderr.puts "Couldn't find file to include: '#{name}'"
+        ''
+      end
+    end
+
+    # Look for the given file in the directory containing the current
+    # file, and then in each of the directories specified in the
+    # RDOC_INCLUDE path
+
+    def find_include_file(name)
+      to_search = [ File.dirname(@input_file_name) ].concat @include_path
+      to_search.each do |dir|
+        full_name = File.join(dir, name)
+        stat = File.stat(full_name) rescue next
+        return full_name if stat.readable?
+      end
+      nil
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/to_flow.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/to_flow.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/to_flow.rb	(revision 18425)
@@ -0,0 +1,188 @@
+require 'rdoc/markup/simple_markup/fragments'
+require 'rdoc/markup/simple_markup/inline'
+require 'cgi'
+
+module SM
+
+  module Flow
+    P = Struct.new(:body)
+    VERB = Struct.new(:body)
+    RULE = Struct.new(:width)
+    class LIST
+      attr_reader :type, :contents
+      def initialize(type)
+        @type = type
+        @contents = []
+      end
+      def <<(stuff)
+        @contents << stuff
+      end
+    end
+    LI = Struct.new(:label, :body)
+    H = Struct.new(:level, :text)
+  end
+
+  class ToFlow
+    LIST_TYPE_TO_HTML = {
+      SM::ListBase::BULLET     =>  [ "<ul>", "</ul>" ],
+      SM::ListBase::NUMBER     =>  [ "<ol>", "</ol>" ],
+      SM::ListBase::UPPERALPHA =>  [ "<ol>", "</ol>" ],
+      SM::ListBase::LOWERALPHA =>  [ "<ol>", "</ol>" ],
+      SM::ListBase::LABELED    =>  [ "<dl>", "</dl>" ],
+      SM::ListBase::NOTE       =>  [ "<table>", "</table>" ],
+    }
+
+    InlineTag = Struct.new(:bit, :on, :off)
+
+    def initialize
+      init_tags
+    end
+
+    ##
+    # Set up the standard mapping of attributes to HTML tags
+    #
+    def init_tags
+      @attr_tags = [
+        InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
+        InlineTag.new(SM::Attribute.bitmap_for(:TT),   "<tt>", "</tt>"),
+        InlineTag.new(SM::Attribute.bitmap_for(:EM),   "<em>", "</em>"),
+      ]
+    end
+
+    ##
+    # Add a new set of HTML tags for an attribute. We allow
+    # separate start and end tags for flexibility
+    #
+    def add_tag(name, start, stop)
+      @attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop)
+    end
+
+    ##
+    # Given an HTML tag, decorate it with class information
+    # and the like if required. This is a no-op in the base
+    # class, but is overridden in HTML output classes that
+    # implement style sheets
+
+    def annotate(tag)
+      tag
+    end
+
+    ## 
+    # Here's the client side of the visitor pattern
+
+    def start_accepting
+      @res = []
+      @list_stack = []
+    end
+
+    def end_accepting
+      @res
+    end
+
+    def accept_paragraph(am, fragment)
+      @res << Flow::P.new((convert_flow(am.flow(fragment.txt))))
+    end
+
+    def accept_verbatim(am, fragment)
+      @res << Flow::VERB.new((convert_flow(am.flow(fragment.txt))))
+    end
+
+    def accept_rule(am, fragment)
+      size = fragment.param
+      size = 10 if size > 10
+      @res << Flow::RULE.new(size)
+    end
+
+    def accept_list_start(am, fragment)
+      @list_stack.push(@res)
+      list = Flow::LIST.new(fragment.type)
+      @res << list
+      @res = list
+    end
+
+    def accept_list_end(am, fragment)
+      @res = @list_stack.pop
+    end
+
+    def accept_list_item(am, fragment)
+      @res << Flow::LI.new(fragment.param, convert_flow(am.flow(fragment.txt)))
+    end
+
+    def accept_blank_line(am, fragment)
+      # @res << annotate("<p />") << "\n"
+    end
+
+    def accept_heading(am, fragment)
+      @res << Flow::H.new(fragment.head_level, convert_flow(am.flow(fragment.txt)))
+    end
+
+
+    #######################################################################
+
+    private
+
+    #######################################################################
+
+    def on_tags(res, item)
+      attr_mask = item.turn_on
+      return if attr_mask.zero?
+
+      @attr_tags.each do |tag|
+        if attr_mask & tag.bit != 0
+          res << annotate(tag.on)
+        end
+      end
+    end
+
+    def off_tags(res, item)
+      attr_mask = item.turn_off
+      return if attr_mask.zero?
+
+      @attr_tags.reverse_each do |tag|
+        if attr_mask & tag.bit != 0
+          res << annotate(tag.off)
+        end
+      end
+    end
+
+    def convert_flow(flow)
+      res = ""
+      flow.each do |item|
+        case item
+        when String
+          res << convert_string(item)
+        when AttrChanger
+          off_tags(res, item)
+          on_tags(res,  item)
+        when Special
+          res << convert_special(item)
+        else
+          raise "Unknown flow element: #{item.inspect}"
+        end
+      end
+      res
+    end
+
+    # some of these patterns are taken from SmartyPants...
+
+    def convert_string(item)
+      CGI.escapeHTML(item)
+    end
+
+    def convert_special(special)
+      handled = false
+      Attribute.each_name_of(special.type) do |name|
+        method_name = "handle_special_#{name}"
+        if self.respond_to? method_name
+          special.text = send(method_name, special)
+          handled = true
+        end
+      end
+      raise "Unhandled special: #{special}" unless handled
+      special.text
+    end
+
+
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/to_html.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/to_html.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/to_html.rb	(revision 18425)
@@ -0,0 +1,289 @@
+require 'rdoc/markup/simple_markup/fragments'
+require 'rdoc/markup/simple_markup/inline'
+
+require 'cgi'
+
+module SM
+
+  class ToHtml
+
+    LIST_TYPE_TO_HTML = {
+      ListBase::BULLET =>  [ "<ul>", "</ul>" ],
+      ListBase::NUMBER =>  [ "<ol>", "</ol>" ],
+      ListBase::UPPERALPHA =>  [ "<ol>", "</ol>" ],
+      ListBase::LOWERALPHA =>  [ "<ol>", "</ol>" ],
+      ListBase::LABELED => [ "<dl>", "</dl>" ],
+      ListBase::NOTE    => [ "<table>", "</table>" ],
+    }
+
+    InlineTag = Struct.new(:bit, :on, :off)
+
+    def initialize
+      init_tags
+    end
+
+    ##
+    # Set up the standard mapping of attributes to HTML tags
+    #
+    def init_tags
+      @attr_tags = [
+        InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
+        InlineTag.new(SM::Attribute.bitmap_for(:TT),   "<tt>", "</tt>"),
+        InlineTag.new(SM::Attribute.bitmap_for(:EM),   "<em>", "</em>"),
+      ]
+    end
+
+    ##
+    # Add a new set of HTML tags for an attribute. We allow
+    # separate start and end tags for flexibility
+    #
+    def add_tag(name, start, stop)
+      @attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop)
+    end
+
+    ##
+    # Given an HTML tag, decorate it with class information
+    # and the like if required. This is a no-op in the base
+    # class, but is overridden in HTML output classes that
+    # implement style sheets
+
+    def annotate(tag)
+      tag
+    end
+
+    ## 
+    # Here's the client side of the visitor pattern
+
+    def start_accepting
+      @res = ""
+      @in_list_entry = []
+    end
+
+    def end_accepting
+      @res
+    end
+
+    def accept_paragraph(am, fragment)
+      @res << annotate("<p>") + "\n"
+      @res << wrap(convert_flow(am.flow(fragment.txt)))
+      @res << annotate("</p>") + "\n"
+    end
+
+    def accept_verbatim(am, fragment)
+      @res << annotate("<pre>") + "\n"
+      @res << CGI.escapeHTML(fragment.txt)
+      @res << annotate("</pre>") << "\n"
+    end
+
+    def accept_rule(am, fragment)
+      size = fragment.param
+      size = 10 if size > 10
+      @res << "<hr size=\"#{size}\"></hr>"
+    end
+
+    def accept_list_start(am, fragment)
+      @res << html_list_name(fragment.type, true) <<"\n"
+      @in_list_entry.push false
+    end
+
+    def accept_list_end(am, fragment)
+      if tag = @in_list_entry.pop
+        @res << annotate(tag) << "\n"
+      end
+      @res << html_list_name(fragment.type, false) <<"\n"
+    end
+
+    def accept_list_item(am, fragment)
+      if tag = @in_list_entry.last
+        @res << annotate(tag) << "\n"
+      end
+      @res << list_item_start(am, fragment)
+      @res << wrap(convert_flow(am.flow(fragment.txt))) << "\n"
+      @in_list_entry[-1] = list_end_for(fragment.type)
+    end
+
+    def accept_blank_line(am, fragment)
+      # @res << annotate("<p />") << "\n"
+    end
+
+    def accept_heading(am, fragment)
+      @res << convert_heading(fragment.head_level, am.flow(fragment.txt))
+    end
+
+    # This is a higher speed (if messier) version of wrap
+
+    def wrap(txt, line_len = 76)
+      res = ""
+      sp = 0
+      ep = txt.length
+      while sp < ep
+        # scan back for a space
+        p = sp + line_len - 1
+        if p >= ep
+          p = ep
+        else
+          while p > sp and txt[p] != ?\s
+            p -= 1
+          end
+          if p <= sp
+            p = sp + line_len
+            while p < ep and txt[p] != ?\s
+              p += 1
+            end
+          end
+        end
+        res << txt[sp...p] << "\n"
+        sp = p
+        sp += 1 while sp < ep and txt[sp] == ?\s
+      end
+      res
+    end
+
+    #######################################################################
+
+    private
+
+    #######################################################################
+
+    def on_tags(res, item)
+      attr_mask = item.turn_on
+      return if attr_mask.zero?
+
+      @attr_tags.each do |tag|
+        if attr_mask & tag.bit != 0
+          res << annotate(tag.on)
+        end
+      end
+    end
+
+    def off_tags(res, item)
+      attr_mask = item.turn_off
+      return if attr_mask.zero?
+
+      @attr_tags.reverse_each do |tag|
+        if attr_mask & tag.bit != 0
+          res << annotate(tag.off)
+        end
+      end
+    end
+
+    def convert_flow(flow)
+      res = ""
+      flow.each do |item|
+        case item
+        when String
+          res << convert_string(item)
+        when AttrChanger
+          off_tags(res, item)
+          on_tags(res,  item)
+        when Special
+          res << convert_special(item)
+        else
+          raise "Unknown flow element: #{item.inspect}"
+        end
+      end
+      res
+    end
+
+    # some of these patterns are taken from SmartyPants...
+
+    def convert_string(item)
+      CGI.escapeHTML(item).
+      
+      
+      # convert -- to em-dash, (-- to en-dash)
+        gsub(/---?/, '&#8212;'). #gsub(/--/, '&#8211;').
+
+      # convert ... to elipsis (and make sure .... becomes .<elipsis>)
+        gsub(/\.\.\.\./, '.&#8230;').gsub(/\.\.\./, '&#8230;').
+
+      # convert single closing quote
+        gsub(%r{([^ \t\r\n\[\{\(])\'}) { "#$1&#8217;" }.
+        gsub(%r{\'(?=\W|s\b)}) { "&#8217;" }.
+
+      # convert single opening quote
+        gsub(/'/, '&#8216;').
+
+      # convert double closing quote
+        gsub(%r{([^ \t\r\n\[\{\(])\'(?=\W)}) { "#$1&#8221;" }.
+
+      # convert double opening quote
+        gsub(/'/, '&#8220;').
+
+      # convert copyright
+        gsub(/\(c\)/, '&#169;').
+
+      # convert and registered trademark
+        gsub(/\(r\)/, '&#174;')
+
+    end
+
+    def convert_special(special)
+      handled = false
+      Attribute.each_name_of(special.type) do |name|
+        method_name = "handle_special_#{name}"
+        if self.respond_to? method_name
+          special.text = send(method_name, special)
+          handled = true
+        end
+      end
+      raise "Unhandled special: #{special}" unless handled
+      special.text
+    end
+
+    def convert_heading(level, flow)
+      res =
+        annotate("<h#{level}>") + 
+        convert_flow(flow) + 
+        annotate("</h#{level}>\n")
+    end
+
+    def html_list_name(list_type, is_open_tag)
+      tags = LIST_TYPE_TO_HTML[list_type] || raise("Invalid list type: #{list_type.inspect}")
+      annotate(tags[ is_open_tag ? 0 : 1])
+    end
+
+    def list_item_start(am, fragment)
+      case fragment.type
+      when ListBase::BULLET, ListBase::NUMBER
+        annotate("<li>")
+
+      when ListBase::UPPERALPHA
+	annotate("<li type=\"A\">")
+
+      when ListBase::LOWERALPHA
+	annotate("<li type=\"a\">")
+
+      when ListBase::LABELED
+        annotate("<dt>") +
+          convert_flow(am.flow(fragment.param)) + 
+          annotate("</dt>") +
+          annotate("<dd>")
+
+      when ListBase::NOTE
+        annotate("<tr>") +
+          annotate("<td valign=\"top\">") +
+          convert_flow(am.flow(fragment.param)) + 
+          annotate("</td>") +
+          annotate("<td>")
+      else
+        raise "Invalid list type"
+      end
+    end
+
+    def list_end_for(fragment_type)
+      case fragment_type
+      when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA
+        "</li>"
+      when ListBase::LABELED
+        "</dd>"
+      when ListBase::NOTE
+        "</td></tr>"
+      else
+        raise "Invalid list type"
+      end
+    end
+
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/to_latex.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/to_latex.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/simple_markup/to_latex.rb	(revision 18425)
@@ -0,0 +1,333 @@
+require 'rdoc/markup/simple_markup/fragments'
+require 'rdoc/markup/simple_markup/inline'
+
+require 'cgi'
+
+module SM
+
+  # Convert SimpleMarkup to basic LaTeX report format
+
+  class ToLaTeX
+
+    BS = "\020"   # \
+    OB = "\021"   # {
+    CB = "\022"   # }
+    DL = "\023"   # Dollar
+
+    BACKSLASH   = "#{BS}symbol#{OB}92#{CB}"
+    HAT         = "#{BS}symbol#{OB}94#{CB}"
+    BACKQUOTE   = "#{BS}symbol#{OB}0#{CB}"
+    TILDE       = "#{DL}#{BS}sim#{DL}"
+    LESSTHAN    = "#{DL}<#{DL}"
+    GREATERTHAN = "#{DL}>#{DL}"
+
+    def self.l(str)
+      str.tr('\\', BS).tr('{', OB).tr('}', CB).tr('$', DL)
+    end
+
+    def l(arg)
+      SM::ToLaTeX.l(arg)
+    end
+
+    LIST_TYPE_TO_LATEX = {
+      ListBase::BULLET =>  [ l("\\begin{itemize}"), l("\\end{itemize}") ],
+      ListBase::NUMBER =>  [ l("\\begin{enumerate}"), l("\\end{enumerate}"), "\\arabic" ],
+      ListBase::UPPERALPHA =>  [ l("\\begin{enumerate}"), l("\\end{enumerate}"), "\\Alph" ],
+      ListBase::LOWERALPHA =>  [ l("\\begin{enumerate}"), l("\\end{enumerate}"), "\\alph" ],
+      ListBase::LABELED => [ l("\\begin{description}"), l("\\end{description}") ],
+      ListBase::NOTE    => [
+        l("\\begin{tabularx}{\\linewidth}{@{} l X @{}}"), 
+        l("\\end{tabularx}") ],
+    }
+
+    InlineTag = Struct.new(:bit, :on, :off)
+
+    def initialize
+      init_tags
+      @list_depth = 0
+      @prev_list_types = []
+    end
+
+    ##
+    # Set up the standard mapping of attributes to LaTeX
+    #
+    def init_tags
+      @attr_tags = [
+        InlineTag.new(SM::Attribute.bitmap_for(:BOLD), l("\\textbf{"), l("}")),
+        InlineTag.new(SM::Attribute.bitmap_for(:TT),   l("\\texttt{"), l("}")),
+        InlineTag.new(SM::Attribute.bitmap_for(:EM),   l("\\emph{"), l("}")),
+      ]
+    end
+
+    ##
+    # Escape a LaTeX string
+    def escape(str)
+# $stderr.print "FE: ", str
+      s = str.
+#        sub(/\s+$/, '').
+        gsub(/([_\${}&%#])/, "#{BS}\\1").
+        gsub(/\\/, BACKSLASH).
+        gsub(/\^/, HAT).
+        gsub(/~/,  TILDE).
+        gsub(/</,  LESSTHAN).
+        gsub(/>/,  GREATERTHAN).
+        gsub(/,,/, ",{},").
+        gsub(/\`/,  BACKQUOTE)
+# $stderr.print "-> ", s, "\n"
+      s
+    end
+
+    ##
+    # Add a new set of LaTeX tags for an attribute. We allow
+    # separate start and end tags for flexibility
+    #
+    def add_tag(name, start, stop)
+      @attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop)
+    end
+
+
+    ## 
+    # Here's the client side of the visitor pattern
+
+    def start_accepting
+      @res = ""
+      @in_list_entry = []
+    end
+
+    def end_accepting
+      @res.tr(BS, '\\').tr(OB, '{').tr(CB, '}').tr(DL, '$')
+    end
+
+    def accept_paragraph(am, fragment)
+      @res << wrap(convert_flow(am.flow(fragment.txt)))
+      @res << "\n"
+    end
+
+    def accept_verbatim(am, fragment)
+      @res << "\n\\begin{code}\n"
+      @res << fragment.txt.sub(/[\n\s]+\Z/, '')
+      @res << "\n\\end{code}\n\n"
+    end
+
+    def accept_rule(am, fragment)
+      size = fragment.param
+      size = 10 if size > 10
+      @res << "\n\n\\rule{\\linewidth}{#{size}pt}\n\n"
+    end
+
+    def accept_list_start(am, fragment)
+      @res << list_name(fragment.type, true) <<"\n"
+      @in_list_entry.push false
+    end
+
+    def accept_list_end(am, fragment)
+      if tag = @in_list_entry.pop
+        @res << tag << "\n"
+      end
+      @res << list_name(fragment.type, false) <<"\n"
+    end
+
+    def accept_list_item(am, fragment)
+      if tag = @in_list_entry.last
+        @res << tag << "\n"
+      end
+      @res << list_item_start(am, fragment)
+      @res << wrap(convert_flow(am.flow(fragment.txt))) << "\n"
+      @in_list_entry[-1] = list_end_for(fragment.type)
+    end
+
+    def accept_blank_line(am, fragment)
+      # @res << "\n"
+    end
+
+    def accept_heading(am, fragment)
+      @res << convert_heading(fragment.head_level, am.flow(fragment.txt))
+    end
+
+    # This is a higher speed (if messier) version of wrap
+
+    def wrap(txt, line_len = 76)
+      res = ""
+      sp = 0
+      ep = txt.length
+      while sp < ep
+        # scan back for a space
+        p = sp + line_len - 1
+        if p >= ep
+          p = ep
+        else
+          while p > sp and txt[p] != ?\s
+            p -= 1
+          end
+          if p <= sp
+            p = sp + line_len
+            while p < ep and txt[p] != ?\s
+              p += 1
+            end
+          end
+        end
+        res << txt[sp...p] << "\n"
+        sp = p
+        sp += 1 while sp < ep and txt[sp] == ?\s
+      end
+      res
+    end
+
+    #######################################################################
+
+    private
+
+    #######################################################################
+
+    def on_tags(res, item)
+      attr_mask = item.turn_on
+      return if attr_mask.zero?
+
+      @attr_tags.each do |tag|
+        if attr_mask & tag.bit != 0
+          res << tag.on
+        end
+      end
+    end
+
+    def off_tags(res, item)
+      attr_mask = item.turn_off
+      return if attr_mask.zero?
+
+      @attr_tags.reverse_each do |tag|
+        if attr_mask & tag.bit != 0
+          res << tag.off
+        end
+      end
+    end
+
+    def convert_flow(flow)
+      res = ""
+      flow.each do |item|
+        case item
+        when String
+#          $stderr.puts "Converting '#{item}'"
+          res << convert_string(item)
+        when AttrChanger
+          off_tags(res, item)
+          on_tags(res,  item)
+        when Special
+          res << convert_special(item)
+        else
+          raise "Unknown flow element: #{item.inspect}"
+        end
+      end
+      res
+    end
+
+    # some of these patterns are taken from SmartyPants...
+
+    def convert_string(item)
+
+      escape(item).
+      
+      
+      # convert ... to elipsis (and make sure .... becomes .<elipsis>)
+        gsub(/\.\.\.\./, '.\ldots{}').gsub(/\.\.\./, '\ldots{}').
+
+      # convert single closing quote
+        gsub(%r{([^ \t\r\n\[\{\(])\'}) { "#$1'" }.
+        gsub(%r{\'(?=\W|s\b)}) { "'" }.
+
+      # convert single opening quote
+        gsub(/'/, '`').
+
+      # convert double closing quote
+        gsub(%r{([^ \t\r\n\[\{\(])\"(?=\W)}) { "#$1''" }.
+
+      # convert double opening quote
+        gsub(/"/, "``").
+
+      # convert copyright
+        gsub(/\(c\)/, '\copyright{}')
+
+    end
+
+    def convert_special(special)
+      handled = false
+      Attribute.each_name_of(special.type) do |name|
+        method_name = "handle_special_#{name}"
+        if self.respond_to? method_name
+          special.text = send(method_name, special)
+          handled = true
+        end
+      end
+      raise "Unhandled special: #{special}" unless handled
+      special.text
+    end
+
+    def convert_heading(level, flow)
+      res =
+        case level
+        when 1 then "\\chapter{"
+        when 2 then "\\section{"
+        when 3 then "\\subsection{"
+        when 4 then "\\subsubsection{"
+        else  "\\paragraph{"
+        end +
+        convert_flow(flow) + 
+        "}\n"
+    end
+
+    def list_name(list_type, is_open_tag)
+      tags = LIST_TYPE_TO_LATEX[list_type] || raise("Invalid list type: #{list_type.inspect}")
+      if tags[2] # enumerate
+        if is_open_tag
+          @list_depth += 1
+          if @prev_list_types[@list_depth] != tags[2]
+            case @list_depth
+            when 1
+              roman = "i"
+            when 2
+              roman = "ii"
+            when 3
+              roman = "iii"
+            when 4
+              roman = "iv"
+            else
+              raise("Too deep list: level #{@list_depth}")
+            end
+            @prev_list_types[@list_depth] = tags[2]
+            return l("\\renewcommand{\\labelenum#{roman}}{#{tags[2]}{enum#{roman}}}") + "\n" + tags[0]
+          end
+        else
+          @list_depth -= 1
+        end
+      end
+      tags[ is_open_tag ? 0 : 1]
+    end
+
+    def list_item_start(am, fragment)
+      case fragment.type
+      when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA
+        "\\item "
+
+      when ListBase::LABELED
+        "\\item[" + convert_flow(am.flow(fragment.param)) + "] "
+
+      when ListBase::NOTE
+          convert_flow(am.flow(fragment.param)) + " & "
+      else
+        raise "Invalid list type"
+      end
+    end
+
+    def list_end_for(fragment_type)
+      case fragment_type
+      when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA, ListBase::LABELED
+        ""
+      when ListBase::NOTE
+        "\\\\\n"
+      else
+        raise "Invalid list type"
+      end
+    end
+
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/test/AllTests.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/test/AllTests.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/test/AllTests.rb	(revision 18425)
@@ -0,0 +1,2 @@
+require 'TestParse.rb'
+require 'TestInline.rb'
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/test/TestInline.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/test/TestInline.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/test/TestInline.rb	(revision 18425)
@@ -0,0 +1,154 @@
+require "test/unit"
+
+$:.unshift "../../.."
+
+require "rdoc/markup/simple_markup/inline"
+
+class TestInline < Test::Unit::TestCase
+
+
+  def setup
+    @am = SM::AttributeManager.new
+
+    @bold_on  = @am.changed_attribute_by_name([], [:BOLD])
+    @bold_off = @am.changed_attribute_by_name([:BOLD], [])
+    
+    @tt_on    = @am.changed_attribute_by_name([], [:TT])
+    @tt_off   = @am.changed_attribute_by_name([:TT], [])
+    
+    @em_on    = @am.changed_attribute_by_name([], [:EM])
+    @em_off   = @am.changed_attribute_by_name([:EM], [])
+    
+    @bold_em_on   = @am.changed_attribute_by_name([], [:BOLD] | [:EM])
+    @bold_em_off  = @am.changed_attribute_by_name([:BOLD] | [:EM], [])
+    
+    @em_then_bold = @am.changed_attribute_by_name([:EM], [:EM] | [:BOLD])
+    
+    @em_to_bold   = @am.changed_attribute_by_name([:EM], [:BOLD])
+    
+    @am.add_word_pair("{", "}", :WOMBAT)
+    @wombat_on    = @am.changed_attribute_by_name([], [:WOMBAT])
+    @wombat_off   = @am.changed_attribute_by_name([:WOMBAT], [])
+  end
+
+  def crossref(text)
+    [ @am.changed_attribute_by_name([], [:CROSSREF] | [:_SPECIAL_]),
+      SM::Special.new(33, text),
+      @am.changed_attribute_by_name([:CROSSREF] | [:_SPECIAL_], [])
+    ]
+  end
+
+  def test_special
+    # class names, variable names, file names, or instance variables
+    @am.add_special(/(
+                       \b([A-Z]\w+(::\w+)*)
+                       | \#\w+[!?=]?
+                       | \b\w+([_\/\.]+\w+)+[!?=]?
+                      )/x, 
+                    :CROSSREF)
+    
+    assert_equal(["cat"], @am.flow("cat"))
+
+    assert_equal(["cat ", crossref("#fred"), " dog"].flatten,
+                  @am.flow("cat #fred dog"))
+
+    assert_equal([crossref("#fred"), " dog"].flatten,
+                  @am.flow("#fred dog"))
+
+    assert_equal(["cat ", crossref("#fred")].flatten, @am.flow("cat #fred"))
+  end
+
+  def test_basic
+    assert_equal(["cat"], @am.flow("cat"))
+
+    assert_equal(["cat ", @bold_on, "and", @bold_off, " dog"],
+                  @am.flow("cat *and* dog"))
+
+    assert_equal(["cat ", @bold_on, "AND", @bold_off, " dog"],
+                  @am.flow("cat *AND* dog"))
+
+    assert_equal(["cat ", @em_on, "And", @em_off, " dog"],
+                  @am.flow("cat _And_ dog"))
+
+    assert_equal(["cat *and dog*"], @am.flow("cat *and dog*"))
+
+    assert_equal(["*cat and* dog"], @am.flow("*cat and* dog"))
+
+    assert_equal(["cat *and ", @bold_on, "dog", @bold_off],
+                  @am.flow("cat *and *dog*"))
+
+    assert_equal(["cat ", @em_on, "and", @em_off, " dog"],
+                  @am.flow("cat _and_ dog"))
+
+    assert_equal(["cat_and_dog"],
+                  @am.flow("cat_and_dog"))
+
+    assert_equal(["cat ", @tt_on, "and", @tt_off, " dog"],
+                  @am.flow("cat +and+ dog"))
+
+    assert_equal(["cat ", @bold_on, "a_b_c", @bold_off, " dog"],
+                  @am.flow("cat *a_b_c* dog"))
+
+    assert_equal(["cat __ dog"],
+                  @am.flow("cat __ dog"))
+
+    assert_equal(["cat ", @em_on, "_", @em_off, " dog"],
+                  @am.flow("cat ___ dog"))
+
+  end
+
+  def test_combined
+    assert_equal(["cat ", @em_on, "and", @em_off, " ", @bold_on, "dog", @bold_off],
+                  @am.flow("cat _and_ *dog*"))
+
+    assert_equal(["cat ", @em_on, "a__nd", @em_off, " ", @bold_on, "dog", @bold_off], 
+                  @am.flow("cat _a__nd_ *dog*"))
+  end
+
+  def test_html_like
+    assert_equal(["cat ", @tt_on, "dog", @tt_off], @am.flow("cat <tt>dog</Tt>"))
+
+    assert_equal(["cat ", @em_on, "and", @em_off, " ", @bold_on, "dog", @bold_off], 
+                  @am.flow("cat <i>and</i> <B>dog</b>"))
+    
+    assert_equal(["cat ", @em_on, "and ", @em_then_bold, "dog", @bold_em_off], 
+                  @am.flow("cat <i>and <B>dog</B></I>"))
+    
+    assert_equal(["cat ", @em_on, "and ", @em_to_bold, "dog", @bold_off], 
+                  @am.flow("cat <i>and </i><b>dog</b>"))
+    
+    assert_equal(["cat ", @em_on, "and ", @em_to_bold, "dog", @bold_off], 
+                  @am.flow("cat <i>and <b></i>dog</b>"))
+    
+    assert_equal([@tt_on, "cat", @tt_off, " ", @em_on, "and ", @em_to_bold, "dog", @bold_off], 
+                  @am.flow("<tt>cat</tt> <i>and <b></i>dog</b>"))
+
+    assert_equal(["cat ", @em_on, "and ", @em_then_bold, "dog", @bold_em_off], 
+                  @am.flow("cat <i>and <b>dog</b></i>"))
+    
+    assert_equal(["cat ", @bold_em_on, "and", @bold_em_off, " dog"], 
+                  @am.flow("cat <i><b>and</b></i> dog"))
+    
+    
+  end
+
+  def test_protect
+    assert_equal(['cat \\ dog'], @am.flow('cat \\ dog'))
+
+    assert_equal(["cat <tt>dog</Tt>"], @am.flow("cat \\<tt>dog</Tt>"))
+
+    assert_equal(["cat ", @em_on, "and", @em_off, " <B>dog</b>"], 
+                  @am.flow("cat <i>and</i> \\<B>dog</b>"))
+    
+    assert_equal(["*word* or <b>text</b>"], @am.flow("\\*word* or \\<b>text</b>"))
+
+    assert_equal(["_cat_", @em_on, "dog", @em_off], 
+                  @am.flow("\\_cat_<i>dog</i>"))
+  end
+
+  def test_adding
+    assert_equal(["cat ", @wombat_on, "and", @wombat_off, " dog" ],
+                  @am.flow("cat {and} dog"))
+#    assert_equal(["cat {and} dog" ], @am.flow("cat \\{and} dog"))
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/test/TestParse.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/test/TestParse.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/markup/test/TestParse.rb	(revision 18425)
@@ -0,0 +1,503 @@
+require 'test/unit'
+
+$:.unshift "../../.."
+
+require 'rdoc/markup/simple_markup'
+
+include SM
+
+class TestParse < Test::Unit::TestCase
+
+  class MockOutput
+    def start_accepting
+      @res = []
+      end
+    
+    def end_accepting
+      @res
+    end
+
+    def accept_paragraph(am, fragment)
+      @res << fragment.to_s
+    end
+
+    def accept_verbatim(am, fragment)
+      @res << fragment.to_s
+    end
+
+    def accept_list_start(am, fragment)
+      @res << fragment.to_s
+    end
+
+    def accept_list_end(am, fragment)
+      @res << fragment.to_s
+    end
+
+    def accept_list_item(am, fragment)
+      @res << fragment.to_s
+    end
+
+    def accept_blank_line(am, fragment)
+      @res << fragment.to_s
+    end
+
+    def accept_heading(am, fragment)
+      @res << fragment.to_s
+    end
+
+    def accept_rule(am, fragment)
+      @res << fragment.to_s
+    end
+
+  end
+
+  def basic_conv(str)
+    sm = SimpleMarkup.new
+    mock = MockOutput.new
+    sm.convert(str, mock)
+    sm.content
+  end
+
+  def line_types(str, expected)
+    p = SimpleMarkup.new
+    mock = MockOutput.new
+    p.convert(str, mock)
+    assert_equal(expected, p.get_line_types.map{|type| type.to_s[0,1]}.join(''))
+  end
+
+  def line_groups(str, expected)
+    p = SimpleMarkup.new
+    mock = MockOutput.new
+
+    block = p.convert(str, mock)
+
+    if block != expected
+      rows = (0...([expected.size, block.size].max)).collect{|i|
+        [expected[i]||"nil", block[i]||"nil"] 
+      }
+      printf "\n\n%35s %35s\n", "Expected", "Got"
+      rows.each {|e,g| printf "%35s %35s\n", e.dump, g.dump }
+    end
+
+    assert_equal(expected, block)
+  end
+
+  def test_tabs
+    str = "hello\n  dave"
+    assert_equal(str, basic_conv(str))
+    str = "hello\n\tdave"
+    assert_equal("hello\n        dave", basic_conv(str))
+    str = "hello\n \tdave"
+    assert_equal("hello\n        dave", basic_conv(str))
+    str = "hello\n  \tdave"
+    assert_equal("hello\n        dave", basic_conv(str))
+    str = "hello\n   \tdave"
+    assert_equal("hello\n        dave", basic_conv(str))
+    str = "hello\n    \tdave"
+    assert_equal("hello\n        dave", basic_conv(str))
+    str = "hello\n     \tdave"
+    assert_equal("hello\n        dave", basic_conv(str))
+    str = "hello\n      \tdave"
+    assert_equal("hello\n        dave", basic_conv(str))
+    str = "hello\n       \tdave"
+    assert_equal("hello\n        dave", basic_conv(str))
+    str = "hello\n        \tdave"
+    assert_equal("hello\n                dave", basic_conv(str))
+    str = ".\t\t."
+    assert_equal(".               .", basic_conv(str))
+  end
+
+  def test_whitespace
+    assert_equal("hello", basic_conv("hello"))
+    assert_equal("hello", basic_conv(" hello "))
+    assert_equal("hello", basic_conv(" \t \t hello\t\t"))
+
+    assert_equal("1\n 2\n  3", basic_conv("1\n 2\n  3"))
+    assert_equal("1\n 2\n  3", basic_conv("  1\n   2\n    3"))
+
+    assert_equal("1\n 2\n  3\n1\n 2", basic_conv("1\n 2\n  3\n1\n 2"))
+    assert_equal("1\n 2\n  3\n1\n 2", basic_conv("  1\n   2\n    3\n  1\n   2"))
+
+    assert_equal("1\n 2\n\n  3", basic_conv("  1\n   2\n\n    3"))
+  end
+
+  def test_types
+    str = "now is the time"
+    line_types(str, 'P')
+
+    str = "now is the time\nfor all good men"
+    line_types(str, 'PP')
+
+    str = "now is the time\n  code\nfor all good men"
+    line_types(str, 'PVP')
+
+    str = "now is the time\n  code\n more code\nfor all good men"
+    line_types(str, 'PVVP')
+
+    str = "now is\n---\nthe time"
+    line_types(str, 'PRP')
+
+    str = %{\
+       now is
+       * l1
+       * l2
+       the time}
+    line_types(str, 'PLLP')
+
+    str = %{\
+       now is
+       * l1
+         l1+
+       * l2
+       the time}
+    line_types(str, 'PLPLP')
+
+    str = %{\
+       now is
+       * l1
+         * l1.1
+       * l2
+       the time}
+    line_types(str, 'PLLLP')
+
+    str = %{\
+       now is
+       * l1
+         * l1.1
+           text
+             code
+             code
+
+           text
+       * l2
+       the time}
+    line_types(str, 'PLLPVVBPLP')
+
+    str = %{\
+       now is
+       1. l1
+          * l1.1
+       2. l2
+       the time}
+    line_types(str, 'PLLLP')
+
+    str = %{\
+       now is
+       [cat] l1
+             * l1.1
+       [dog] l2
+       the time}
+    line_types(str, 'PLLLP')
+
+    str = %{\
+       now is
+       [cat] l1
+             continuation
+       [dog] l2
+       the time}
+    line_types(str, 'PLPLP')
+  end
+
+  def test_groups
+    str = "now is the time"
+    line_groups(str, ["L0: Paragraph\nnow is the time"] )
+
+    str = "now is the time\nfor all good men"
+    line_groups(str, ["L0: Paragraph\nnow is the time for all good men"] )
+
+    str = %{\
+      now is the time
+        code _line_ here
+      for all good men}
+
+    line_groups(str,
+                [ "L0: Paragraph\nnow is the time",
+                  "L0: Verbatim\n  code _line_ here\n",
+                  "L0: Paragraph\nfor all good men"
+                ] )
+
+    str = "now is the time\n  code\n more code\nfor all good men"
+    line_groups(str,
+                [ "L0: Paragraph\nnow is the time",
+                  "L0: Verbatim\n  code\n more code\n",
+                  "L0: Paragraph\nfor all good men"
+                ] )
+
+    str = %{\
+       now is
+       * l1
+       * l2
+       the time}
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L1: ListStart\n",
+                  "L1: ListItem\nl1",
+                  "L1: ListItem\nl2",
+                  "L1: ListEnd\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+    str = %{\
+       now is
+       * l1
+         l1+
+       * l2
+       the time}
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L1: ListStart\n",
+                  "L1: ListItem\nl1 l1+",
+                  "L1: ListItem\nl2",
+                  "L1: ListEnd\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+    str = %{\
+       now is
+       * l1
+         * l1.1
+       * l2
+       the time}
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L1: ListStart\n",
+                  "L1: ListItem\nl1",
+                  "L2: ListStart\n",
+                  "L2: ListItem\nl1.1",
+                  "L2: ListEnd\n",
+                  "L1: ListItem\nl2",
+                  "L1: ListEnd\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+
+    str = %{\
+       now is
+       * l1
+         * l1.1
+           text
+             code
+               code
+
+           text
+       * l2
+       the time}
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L1: ListStart\n",
+                  "L1: ListItem\nl1",
+                  "L2: ListStart\n",
+                  "L2: ListItem\nl1.1 text",
+                  "L2: Verbatim\n  code\n    code\n",
+                  "L2: Paragraph\ntext",
+                  "L2: ListEnd\n",
+                  "L1: ListItem\nl2",
+                  "L1: ListEnd\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+
+    str = %{\
+       now is
+       1. l1
+          * l1.1
+       2. l2
+       the time}
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L1: ListStart\n",
+                  "L1: ListItem\nl1",
+                  "L2: ListStart\n",
+                  "L2: ListItem\nl1.1",
+                  "L2: ListEnd\n",
+                  "L1: ListItem\nl2",
+                  "L1: ListEnd\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+    str = %{\
+       now is
+       [cat] l1
+             * l1.1
+       [dog] l2
+       the time}
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L1: ListStart\n",
+                  "L1: ListItem\nl1",
+                  "L2: ListStart\n",
+                  "L2: ListItem\nl1.1",
+                  "L2: ListEnd\n",
+                  "L1: ListItem\nl2",
+                  "L1: ListEnd\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+    str = %{\
+       now is
+       [cat] l1
+             continuation
+       [dog] l2
+       the time}
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L1: ListStart\n",
+                  "L1: ListItem\nl1 continuation",
+                  "L1: ListItem\nl2",
+                  "L1: ListEnd\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+    
+  end
+
+  def test_verbatim_merge
+    str = %{\
+       now is
+          code
+       the time}
+
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L0: Verbatim\n   code\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+
+    str = %{\
+       now is
+          code
+          code1
+       the time}
+
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L0: Verbatim\n   code\n   code1\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+
+    str = %{\
+       now is
+          code
+
+          code1
+       the time}
+
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L0: Verbatim\n   code\n\n   code1\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+
+    str = %{\
+       now is
+          code
+
+          code1
+
+       the time}
+
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L0: Verbatim\n   code\n\n   code1\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+
+    str = %{\
+       now is
+          code
+
+          code1
+
+          code2
+       the time}
+
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L0: Verbatim\n   code\n\n   code1\n\n   code2\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+
+    # Folds multiple blank lines
+    str = %{\
+       now is
+          code
+
+
+          code1
+
+       the time}
+
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L0: Verbatim\n   code\n\n   code1\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+
+  end
+ 
+  def test_list_split
+    str = %{\
+       now is
+       * l1
+       1. n1
+       2. n2
+       * l2
+       the time}
+    line_groups(str,
+                [ "L0: Paragraph\nnow is",
+                  "L1: ListStart\n",
+                  "L1: ListItem\nl1",
+                  "L1: ListEnd\n",
+                  "L1: ListStart\n",
+                  "L1: ListItem\nn1",
+                  "L1: ListItem\nn2",
+                  "L1: ListEnd\n",
+                  "L1: ListStart\n",
+                  "L1: ListItem\nl2",
+                  "L1: ListEnd\n",
+                  "L0: Paragraph\nthe time"
+                ])
+
+  end
+
+
+  def test_headings
+    str = "= heading one"
+    line_groups(str, 
+                [ "L0: Heading\nheading one"
+                ])
+
+    str = "=== heading three"
+    line_groups(str, 
+                [ "L0: Heading\nheading three"
+                ])
+
+    str = "text\n   === heading three"
+    line_groups(str, 
+                [ "L0: Paragraph\ntext",
+                  "L0: Verbatim\n   === heading three\n"
+                ])
+
+    str = "text\n   code\n   === heading three"
+    line_groups(str, 
+                [ "L0: Paragraph\ntext",
+                  "L0: Verbatim\n   code\n   === heading three\n"
+                ])
+
+    str = "text\n   code\n=== heading three"
+    line_groups(str, 
+                [ "L0: Paragraph\ntext",
+                  "L0: Verbatim\n   code\n",
+                  "L0: Heading\nheading three"
+                ])
+
+  end
+
+  
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/options.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/options.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/options.rb	(revision 18425)
@@ -0,0 +1,586 @@
+# We handle the parsing of options, and subsequently as a singleton
+# object to be queried for option values
+
+require "rdoc/ri/ri_paths"
+
+class Options
+
+  require 'singleton'
+  require 'getoptlong'
+
+  include Singleton
+
+  # files matching this pattern will be excluded
+  attr_accessor :exclude
+
+  # the name of the output directory
+  attr_accessor :op_dir
+  
+  # the name to use for the output
+  attr_reader :op_name
+
+  # include private and protected methods in the
+  # output
+  attr_accessor :show_all
+  
+  # name of the file, class or module to display in
+  # the initial index page (if not specified
+  # the first file we encounter is used)
+  attr_accessor :main_page
+
+  # merge into classes of the name name when generating ri
+  attr_reader :merge
+
+  # Don't display progress as we process the files
+  attr_reader :quiet
+
+  # description of the output generator (set with the <tt>-fmt</tt>
+  # option
+  attr_accessor :generator
+
+  # and the list of files to be processed
+  attr_reader :files
+
+  # array of directories to search for files to satisfy an :include:
+  attr_reader :rdoc_include
+
+  # title to be used out the output
+  #attr_writer :title
+
+  # template to be used when generating output
+  attr_reader :template
+
+  # should diagrams be drawn
+  attr_reader :diagram
+
+  # should we draw fileboxes in diagrams
+  attr_reader :fileboxes
+
+  # include the '#' at the front of hyperlinked instance method names
+  attr_reader :show_hash
+
+  # image format for diagrams
+  attr_reader :image_format
+
+  # character-set
+  attr_reader :charset
+
+  # should source code be included inline, or displayed in a popup
+  attr_reader :inline_source
+
+  # should the output be placed into a single file
+  attr_reader :all_one_file
+
+  # the number of columns in a tab
+  attr_reader :tab_width
+
+  # include line numbers in the source listings
+  attr_reader :include_line_numbers
+
+  # pattern for additional attr_... style methods
+  attr_reader :extra_accessors
+  attr_reader :extra_accessor_flags
+
+  # URL of stylesheet
+  attr_reader :css
+
+  # URL of web cvs frontend
+  attr_reader :webcvs
+
+  # Are we promiscuous about showing module contents across
+  # multiple files
+  attr_reader :promiscuous
+
+  # scan newer sources than the flag file if true.
+  attr_reader :force_update
+
+  module OptionList
+
+    OPTION_LIST = [
+      [ "--accessor",      "-A",   "accessorname[,..]",
+        "comma separated list of additional class methods\n" +
+        "that should be treated like 'attr_reader' and\n" +
+        "friends. Option may be repeated. Each accessorname\n" +
+        "may have '=text' appended, in which case that text\n" +
+        "appears where the r/w/rw appears for normal accessors."],
+                                                                   
+      [ "--all",           "-a",   nil,
+        "include all methods (not just public)\nin the output" ],
+
+      [ "--charset",       "-c",   "charset",
+        "specifies HTML character-set" ],
+
+      [ "--debug",         "-D",   nil,
+        "displays lots on internal stuff" ],
+
+      [ "--diagram",       "-d",   nil,
+        "Generate diagrams showing modules and classes.\n" +
+        "You need dot V1.8.6 or later to use the --diagram\n" +
+        "option correctly. Dot is available from\n"+
+        "http://www.research.att.com/sw/tools/graphviz/" ],
+
+      [ "--exclude",       "-x",   "pattern",
+        "do not process files or directories matching\n" +
+        "pattern. Files given explicitly on the command\n" +
+        "line will never be excluded." ],
+
+      [ "--extension",     "-E",   "new=old",
+        "Treat files ending with .new as if they ended with\n" +
+        ".old. Using '-E cgi=rb' will cause xxx.cgi to be\n" +
+        "parsed as a Ruby file"],
+
+      [ "--fileboxes",     "-F",   nil,
+        "classes are put in boxes which represents\n" +
+        "files, where these classes reside. Classes\n" +
+        "shared between more than one file are\n" +
+        "shown with list of files that sharing them.\n" +
+        "Silently discarded if --diagram is not given\n" +
+        "Experimental." ],
+
+      [ "--force-update",  "-U",   nil,
+        "forces to scan all sources even if newer than\n" +
+        "the flag file." ],
+
+      [ "--fmt",           "-f",   "format name",
+        "set the output formatter (see below)" ],
+
+      [ "--help",          "-h",   nil,
+        "you're looking at it" ],
+
+      [ "--help-output",   "-O",   nil,
+        "explain the various output options" ],
+
+      [ "--image-format",  "-I",   "gif/png/jpg/jpeg",
+        "Sets output image format for diagrams. Can\n" +
+        "be png, gif, jpeg, jpg. If this option is\n" +
+        "omitted, png is used. Requires --diagram." ],
+
+      [ "--include",       "-i",   "dir[,dir...]",
+        "set (or add to) the list of directories\n" +
+        "to be searched when satisfying :include:\n" +
+        "requests. Can be used more than once." ],
+
+      [ "--inline-source", "-S",   nil,
+        "Show method source code inline, rather\n" +
+        "than via a popup link" ],
+
+      [ "--line-numbers", "-N", nil,
+        "Include line numbers in the source code" ],
+
+      [ "--main",          "-m",   "name",
+        "'name' will be the initial page displayed" ],
+
+      [ "--merge",         "-M",   nil,
+        "when creating ri output, merge processed classes\n" +
+        "into previously documented classes of the name name"],
+
+      [ "--one-file",      "-1",   nil,
+        "put all the output into a single file" ],
+
+      [ "--op",            "-o",   "dir",
+        "set the output directory" ],
+
+      [ "--opname",       "-n",    "name",
+        "Set the 'name' of the output. Has no\n" +
+        "effect for HTML." ],
+
+      [ "--promiscuous",   "-p",   nil,
+        "When documenting a file that contains a module\n" +
+        "or class also defined in other files, show\n" +
+        "all stuff for that module/class in each files\n" +
+        "page. By default, only show stuff defined in\n" +
+        "that particular file." ],
+
+      [ "--quiet",         "-q",   nil,
+        "don't show progress as we parse" ],
+
+      [ "--ri",            "-r",   nil,
+       "generate output for use by 'ri.' The files are\n" +
+       "stored in the '.rdoc' directory under your home\n"+
+       "directory unless overridden by a subsequent\n" +
+       "--op parameter, so no special privileges are needed." ],
+
+      [ "--ri-site",       "-R",   nil,
+       "generate output for use by 'ri.' The files are\n" +
+       "stored in a site-wide directory, making them accessible\n"+
+       "to others, so special privileges are needed." ],
+
+      [ "--ri-system",     "-Y",   nil,
+       "generate output for use by 'ri.' The files are\n" +
+       "stored in a system-level directory, making them accessible\n"+
+       "to others, so special privileges are needed. This option\n"+
+       "is intended to be used during Ruby installations" ],
+
+      [ "--show-hash",     "-H",   nil,
+        "A name of the form #name in a comment\n" +
+        "is a possible hyperlink to an instance\n" +
+        "method name. When displayed, the '#' is\n" +
+        "removed unless this option is specified" ],
+
+      [ "--style",         "-s",   "stylesheet url",
+        "specifies the URL of a separate stylesheet." ],
+
+      [ "--tab-width",     "-w",   "n",
+        "Set the width of tab characters (default 8)"],
+
+      [ "--template",      "-T",   "template name",
+        "Set the template used when generating output" ],
+
+      [ "--title",         "-t",   "text",
+        "Set 'txt' as the title for the output" ],
+
+      [ "--version",       "-v",   nil,
+        "display  RDoc's version" ],
+
+      [ "--webcvs",        "-W",   "url",
+        "Specify a URL for linking to a web frontend\n" +
+        "to CVS. If the URL contains a '\%s', the\n" +
+        "name of the current file will be substituted;\n" +
+        "if the URL doesn't contain a '\%s', the\n" +
+        "filename will be appended to it." ],
+    ]
+
+    def OptionList.options
+      OPTION_LIST.map do |long, short, arg,|
+        [ long, 
+          short, 
+          arg ? GetoptLong::REQUIRED_ARGUMENT : GetoptLong::NO_ARGUMENT 
+        ]
+      end
+    end
+
+
+    def OptionList.strip_output(text)
+      text =~ /^\s+/
+      leading_spaces = $&
+      text.gsub!(/^#{leading_spaces}/, '')
+      $stdout.puts text
+    end
+
+
+    # Show an error and exit
+
+    def OptionList.error(msg)
+      $stderr.puts
+      $stderr.puts msg
+      $stderr.puts "\nFor help on options, try 'rdoc --help'\n\n"
+      exit 1
+    end
+
+    # Show usage and exit
+    
+    def OptionList.usage(generator_names)
+      
+      puts
+      puts(VERSION_STRING)
+      puts
+
+      name = File.basename($0)
+      OptionList.strip_output(<<-EOT)
+          Usage:
+
+            #{name} [options]  [names...]
+
+          Files are parsed, and the information they contain
+          collected, before any output is produced. This allows cross
+          references between all files to be resolved. If a name is a
+          directory, it is traversed. If no names are specified, all
+          Ruby files in the current directory (and subdirectories) are
+          processed.
+
+          Options:
+
+      EOT
+
+      OPTION_LIST.each do |long, short, arg, desc|
+        opt = sprintf("%20s", "#{long}, #{short}")
+        oparg = sprintf("%-7s", arg)
+        print "#{opt} #{oparg}"
+        desc = desc.split("\n")
+        if arg.nil? || arg.length < 7
+          puts desc.shift
+        else
+          puts
+        end
+        desc.each do |line|
+          puts(" "*28 + line)
+        end
+        puts
+      end
+
+      puts "\nAvailable output formatters: " +
+        generator_names.sort.join(', ') + "\n\n"
+
+      puts "For information on where the output goes, use\n\n"
+      puts "   rdoc --help-output\n\n"
+
+      exit 0
+    end
+
+    def OptionList.help_output
+      OptionList.strip_output(<<-EOT)
+      How RDoc generates output depends on the output formatter being
+      used, and on the options you give.
+
+      - HTML output is normally produced into a number of separate files
+        (one per class, module, and file, along with various indices). 
+        These files will appear in the directory given by the --op
+        option (doc/ by default).
+
+      - XML output by default is written to standard output. If a
+        --opname option is given, the output will instead be written
+        to a file with that name in the output directory.
+
+      - .chm files (Windows help files) are written in the --op directory.
+        If an --opname parameter is present, that name is used, otherwise
+        the file will be called rdoc.chm.
+
+      For information on other RDoc options, use "rdoc --help".
+      EOT
+      exit 0
+    end
+  end
+
+  # Parse command line options. We're passed a hash containing
+  # output generators, keyed by the generator name
+
+  def parse(argv, generators)
+    old_argv = ARGV.dup
+    begin
+      ARGV.replace(argv)
+      @op_dir = "doc"
+      @op_name = nil
+      @show_all = false
+      @main_page = nil
+      @marge     = false
+      @exclude   = []
+      @quiet = false
+      @generator_name = 'html'
+      @generator = generators[@generator_name]
+      @rdoc_include = []
+      @title = nil
+      @template = nil
+      @diagram = false
+      @fileboxes = false
+      @show_hash = false
+      @image_format = 'png'
+      @inline_source = false
+      @all_one_file  = false
+      @tab_width = 8
+      @include_line_numbers = false
+      @extra_accessor_flags = {}
+      @promiscuous = false
+      @force_update = false
+
+      @css = nil
+      @webcvs = nil
+
+      @charset = case $KCODE
+                 when /^S/i
+                   'Shift_JIS'
+                 when /^E/i
+                   'EUC-JP'
+                 else
+                   'iso-8859-1'
+                 end
+
+      accessors = []
+
+      go = GetoptLong.new(*OptionList.options)
+      go.quiet = true
+
+      go.each do |opt, arg|
+	case opt
+        when "--all"           then @show_all      = true
+        when "--charset"       then @charset       = arg
+        when "--debug"         then $DEBUG         = true
+        when "--exclude"       then @exclude       << Regexp.new(arg)
+        when "--inline-source" then @inline_source = true
+        when "--line-numbers"  then @include_line_numbers = true
+        when "--main"          then @main_page     = arg
+        when "--merge"         then @merge         = true
+        when "--one-file"      then @all_one_file  = @inline_source = true
+        when "--op"            then @op_dir        = arg
+        when "--opname"        then @op_name       = arg
+        when "--promiscuous"   then @promiscuous   = true
+        when "--quiet"         then @quiet         = true
+        when "--show-hash"     then @show_hash     = true
+        when "--style"         then @css           = arg
+        when "--template"      then @template      = arg
+        when "--title"         then @title         = arg
+        when "--webcvs"        then @webcvs        = arg
+
+        when "--accessor" 
+          arg.split(/,/).each do |accessor|
+            if accessor =~ /^(\w+)(=(.*))?$/
+              accessors << $1
+              @extra_accessor_flags[$1] = $3
+            end
+          end
+
+        when "--diagram"
+          check_diagram
+          @diagram = true
+
+        when "--fileboxes"
+          @fileboxes = true if @diagram
+
+	when "--fmt"
+          @generator_name = arg.downcase
+          setup_generator(generators)
+
+        when "--help"      
+          OptionList.usage(generators.keys)
+
+        when "--help-output"      
+          OptionList.help_output
+
+        when "--image-format"
+          if ['gif', 'png', 'jpeg', 'jpg'].include?(arg)
+            @image_format = arg
+          else
+            raise GetoptLong::InvalidOption.new("unknown image format: #{arg}")
+          end
+
+        when "--include"   
+          @rdoc_include.concat arg.split(/\s*,\s*/)
+
+        when "--ri", "--ri-site", "--ri-system"
+          @generator_name = "ri"
+          @op_dir = case opt
+                    when "--ri" then RI::Paths::HOMEDIR 
+                    when "--ri-site" then RI::Paths::SITEDIR
+                    when "--ri-system" then RI::Paths::SYSDIR
+                    else fail opt
+                    end
+          setup_generator(generators)
+
+        when "--tab-width"
+          begin
+            @tab_width     = Integer(arg)
+          rescue 
+            $stderr.puts "Invalid tab width: '#{arg}'"
+            exit 1
+          end
+
+        when "--extension"
+          new, old = arg.split(/=/, 2)
+          OptionList.error("Invalid parameter to '-E'") unless new && old
+          unless RDoc::ParserFactory.alias_extension(old, new)
+            OptionList.error("Unknown extension .#{old} to -E")
+          end
+
+        when "--force-update"
+          @force_update = true
+
+	when "--version"
+	  puts VERSION_STRING
+	  exit
+	end
+
+      end
+
+      @files = ARGV.dup
+
+      @rdoc_include << "." if @rdoc_include.empty?
+
+      if @exclude.empty?
+        @exclude = nil
+      else
+        @exclude = Regexp.new(@exclude.join("|"))
+      end
+
+      check_files
+
+      # If no template was specified, use the default
+      # template for the output formatter
+
+      @template ||= @generator_name
+
+      # Generate a regexp from the accessors
+      unless accessors.empty?
+        re = '^(' + accessors.map{|a| Regexp.quote(a)}.join('|') + ')$' 
+        @extra_accessors = Regexp.new(re)
+      end
+
+    rescue GetoptLong::InvalidOption, GetoptLong::MissingArgument => error
+      OptionList.error(error.message)
+
+    ensure
+      ARGV.replace(old_argv)
+    end
+  end
+
+
+  def title
+    @title ||= "RDoc Documentation"
+  end
+  
+  # Set the title, but only if not already set. This means that a title set from 
+  # the command line trumps one set in a source file
+
+  def title=(string)
+    @title ||= string
+  end
+
+
+  private
+
+  # Set up an output generator for the format in @generator_name
+  def setup_generator(generators)
+    @generator = generators[@generator_name]
+    if !@generator
+      OptionList.error("Invalid output formatter")
+    end
+    
+    if @generator_name == "xml"
+      @all_one_file = true
+      @inline_source = true
+    end
+  end
+
+  # Check that the right version of 'dot' is available.
+  # Unfortuately this doesn't work correctly under Windows NT, 
+  # so we'll bypass the test under Windows
+
+  def check_diagram
+    return if RUBY_PLATFORM =~ /win/
+
+    ok = false
+    ver = nil
+    IO.popen("dot -V 2>&1") do |io|
+      ver = io.read
+      if ver =~ /dot\s+version(?:\s+gviz)?\s+(\d+)\.(\d+)/
+        ok = ($1.to_i > 1) || ($1.to_i == 1 && $2.to_i >= 8)
+      end
+    end
+    unless ok
+      if ver =~ /^dot version/
+        $stderr.puts "Warning: You may need dot V1.8.6 or later to use\n",
+          "the --diagram option correctly. You have:\n\n   ",
+          ver,
+          "\nDiagrams might have strange background colors.\n\n"
+      else
+        $stderr.puts "You need the 'dot' program to produce diagrams.",
+          "(see http://www.research.att.com/sw/tools/graphviz/)\n\n"
+        exit
+      end
+#      exit
+    end
+  end
+  
+  # Check that the files on the command line exist
+  
+  def check_files
+    @files.each do |f|
+      stat = File.stat f rescue error("File not found: #{f}")
+      error("File '#{f}' not readable") unless stat.readable?
+    end
+  end
+
+  def error(str)
+    $stderr.puts str
+    exit(1)
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parse_c.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parse_c.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parse_c.rb	(revision 18425)
@@ -0,0 +1,773 @@
+# Classes and modules built in to the interpreter. We need
+# these to define superclasses of user objects
+
+require "rdoc/code_objects"
+require "rdoc/parsers/parserfactory"
+require "rdoc/options"
+require "rdoc/rdoc"
+
+module RDoc
+
+  ##
+  # Ruby's built-in classes.
+
+  KNOWN_CLASSES = {
+    "rb_cObject"           => "Object",
+    "rb_cArray"            => "Array",
+    "rb_cBignum"           => "Bignum",
+    "rb_cClass"            => "Class",
+    "rb_cDir"              => "Dir",
+    "rb_cData"             => "Data",
+    "rb_cFalseClass"       => "FalseClass",
+    "rb_cFile"             => "File",
+    "rb_cFixnum"           => "Fixnum",
+    "rb_cFloat"            => "Float",
+    "rb_cHash"             => "Hash",
+    "rb_cInteger"          => "Integer",
+    "rb_cIO"               => "IO",
+    "rb_cModule"           => "Module",
+    "rb_cNilClass"         => "NilClass",
+    "rb_cNumeric"          => "Numeric",
+    "rb_cProc"             => "Proc",
+    "rb_cRange"            => "Range",
+    "rb_cRegexp"           => "Regexp",
+    "rb_cString"           => "String",
+    "rb_cSymbol"           => "Symbol",
+    "rb_cThread"           => "Thread",
+    "rb_cTime"             => "Time",
+    "rb_cTrueClass"        => "TrueClass",
+    "rb_cStruct"           => "Struct",
+    "rb_eException"        => "Exception",
+    "rb_eStandardError"    => "StandardError",
+    "rb_eSystemExit"       => "SystemExit",
+    "rb_eInterrupt"        => "Interrupt",
+    "rb_eSignal"           => "Signal",
+    "rb_eFatal"            => "Fatal",
+    "rb_eArgError"         => "ArgError",
+    "rb_eEOFError"         => "EOFError",
+    "rb_eIndexError"       => "IndexError",
+    "rb_eRangeError"       => "RangeError",
+    "rb_eIOError"          => "IOError",
+    "rb_eRuntimeError"     => "RuntimeError",
+    "rb_eSecurityError"    => "SecurityError",
+    "rb_eSystemCallError"  => "SystemCallError",
+    "rb_eTypeError"        => "TypeError",
+    "rb_eZeroDivError"     => "ZeroDivError",
+    "rb_eNotImpError"      => "NotImpError",
+    "rb_eNoMemError"       => "NoMemError",
+    "rb_eFloatDomainError" => "FloatDomainError",
+    "rb_eScriptError"      => "ScriptError",
+    "rb_eNameError"        => "NameError",
+    "rb_eSyntaxError"      => "SyntaxError",
+    "rb_eLoadError"        => "LoadError",
+
+    "rb_mKernel"           => "Kernel",
+    "rb_mComparable"       => "Comparable",
+    "rb_mEnumerable"       => "Enumerable",
+    "rb_mPrecision"        => "Precision",
+    "rb_mErrno"            => "Errno",
+    "rb_mFileTest"         => "FileTest",
+    "rb_mGC"               => "GC",
+    "rb_mMath"             => "Math",
+    "rb_mProcess"          => "Process"
+  }
+
+  ##
+  # We attempt to parse C extension files. Basically we look for
+  # the standard patterns that you find in extensions: <tt>rb_define_class,
+  # rb_define_method</tt> and so on. We also try to find the corresponding
+  # C source for the methods and extract comments, but if we fail
+  # we don't worry too much.
+  #
+  # The comments associated with a Ruby method are extracted from the C
+  # comment block associated with the routine that _implements_ that
+  # method, that is to say the method whose name is given in the
+  # <tt>rb_define_method</tt> call. For example, you might write:
+  #
+  #  /*
+  #   * Returns a new array that is a one-dimensional flattening of this
+  #   * array (recursively). That is, for every element that is an array,
+  #   * extract its elements into the new array.
+  #   *
+  #   *    s = [ 1, 2, 3 ]           #=> [1, 2, 3]
+  #   *    t = [ 4, 5, 6, [7, 8] ]   #=> [4, 5, 6, [7, 8]]
+  #   *    a = [ s, t, 9, 10 ]       #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
+  #   *    a.flatten                 #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+  #   */
+  #   static VALUE
+  #   rb_ary_flatten(ary)
+  #       VALUE ary;
+  #   {
+  #       ary = rb_obj_dup(ary);
+  #       rb_ary_flatten_bang(ary);
+  #       return ary;
+  #   }
+  #
+  #   ...
+  #
+  #   void
+  #   Init_Array()
+  #   {
+  #     ...
+  #     rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);
+  #
+  # Here RDoc will determine from the rb_define_method line that there's a
+  # method called "flatten" in class Array, and will look for the implementation
+  # in the method rb_ary_flatten. It will then use the comment from that
+  # method in the HTML output. This method must be in the same source file
+  # as the rb_define_method.
+  #
+  # C classes can be diagramed (see /tc/dl/ruby/ruby/error.c), and RDoc
+  # integrates C and Ruby source into one tree
+  #
+  # The comment blocks may include special direcives:
+  #
+  # [Document-class: <i>name</i>]
+  #   This comment block is documentation for the given class. Use this
+  #   when the <tt>Init_xxx</tt> method is not named after the class.
+  #
+  # [Document-method: <i>name</i>]
+  #   This comment documents the named method. Use when RDoc cannot
+  #   automatically find the method from it's declaration
+  #
+  # [call-seq:  <i>text up to an empty line</i>]
+  #   Because C source doesn't give descripive names to Ruby-level parameters,
+  #   you need to document the calling sequence explicitly
+  #
+  # In additon, RDoc assumes by default that the C method implementing a 
+  # Ruby function is in the same source file as the rb_define_method call.
+  # If this isn't the case, add the comment 
+  #
+  #    rb_define_method(....);  // in: filename
+  #
+  # As an example, we might have an extension that defines multiple classes
+  # in its Init_xxx method. We could document them using
+  #
+  #  
+  #  /*
+  #   * Document-class:  MyClass
+  #   *
+  #   * Encapsulate the writing and reading of the configuration
+  #   * file. ...
+  #   */
+  #  
+  #  /*
+  #   * Document-method: read_value
+  #   *
+  #   * call-seq:
+  #   *   cfg.read_value(key)            -> value
+  #   *   cfg.read_value(key} { |key| }  -> value
+  #   *
+  #   * Return the value corresponding to +key+ from the configuration.
+  #   * In the second form, if the key isn't found, invoke the
+  #   * block and return its value.
+  #   */
+  #
+
+  class C_Parser
+
+    attr_accessor :progress
+
+    extend ParserFactory
+    parse_files_matching(/\.(c|cc|cpp|CC)$/)
+
+    @@known_bodies = {}
+
+    # prepare to parse a C file
+    def initialize(top_level, file_name, body, options, stats)
+      @known_classes = KNOWN_CLASSES.dup
+      @body = handle_tab_width(handle_ifdefs_in(body))
+      @options = options
+      @stats   = stats
+      @top_level = top_level
+      @classes = Hash.new
+      @file_dir = File.dirname(file_name)
+      @progress = $stderr unless options.quiet
+    end
+
+    # Extract the classes/modules and methods from a C file
+    # and return the corresponding top-level object
+    def scan
+      remove_commented_out_lines
+      do_classes
+      do_constants
+      do_methods
+      do_includes
+      do_aliases
+      @top_level
+    end
+
+    #######
+    private
+    #######
+
+    def progress(char)
+      unless @options.quiet
+        @progress.print(char)
+        @progress.flush
+      end
+    end
+
+    def warn(msg)
+      $stderr.puts
+      $stderr.puts msg
+      $stderr.flush
+    end
+
+    def remove_private_comments(comment)
+       comment.gsub!(/\/?\*--(.*?)\/?\*\+\+/m, '')
+       comment.sub!(/\/?\*--.*/m, '')
+    end
+
+    ##
+    # removes lines that are commented out that might otherwise get picked up
+    # when scanning for classes and methods
+
+    def remove_commented_out_lines
+      @body.gsub!(%r{//.*rb_define_}, '//')
+    end
+    
+    def handle_class_module(var_name, class_mod, class_name, parent, in_module)
+      progress(class_mod[0, 1])
+
+      parent_name = @known_classes[parent] || parent
+
+      if in_module
+        enclosure = @classes[in_module]
+        unless enclosure
+          if enclosure = @known_classes[in_module]
+            handle_class_module(in_module, (/^rb_m/ =~ in_module ? "module" : "class"),
+                                enclosure, nil, nil)
+            enclosure = @classes[in_module]
+          end
+        end
+        unless enclosure
+          warn("Enclosing class/module '#{in_module}' for " +
+                "#{class_mod} #{class_name} not known")
+          return
+        end
+      else
+        enclosure = @top_level
+      end
+
+      if class_mod == "class" 
+        cm = enclosure.add_class(NormalClass, class_name, parent_name)
+        @stats.num_classes += 1
+      else
+        cm = enclosure.add_module(NormalModule, class_name)
+        @stats.num_modules += 1
+      end
+      cm.record_location(enclosure.toplevel)
+
+      find_class_comment(cm.full_name, cm)
+      @classes[var_name] = cm
+      @known_classes[var_name] = cm.full_name
+    end
+
+    ##
+    # Look for class or module documentation above Init_+class_name+(void),
+    # in a Document-class +class_name+ (or module) comment or above an
+    # rb_define_class (or module).  If a comment is supplied above a matching
+    # Init_ and a rb_define_class the Init_ comment is used.
+    #
+    #   /*
+    #    * This is a comment for Foo
+    #    */
+    #   Init_Foo(void) {
+    #       VALUE cFoo = rb_define_class("Foo", rb_cObject);
+    #   }
+    #
+    #   /*
+    #    * Document-class: Foo
+    #    * This is a comment for Foo
+    #    */
+    #   Init_foo(void) {
+    #       VALUE cFoo = rb_define_class("Foo", rb_cObject);
+    #   }
+    #
+    #   /*
+    #    * This is a comment for Foo
+    #    */
+    #   VALUE cFoo = rb_define_class("Foo", rb_cObject);
+
+    def find_class_comment(class_name, class_meth)
+      comment = nil
+      if @body =~ %r{((?>/\*.*?\*/\s+))
+                     (static\s+)?void\s+Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)}xmi
+        comment = $1
+      elsif @body =~ %r{Document-(class|module):\s#{class_name}\s*?\n((?>.*?\*/))}m
+        comment = $2
+      else
+        if @body =~ /rb_define_(class|module)/m then
+          class_name = class_name.split("::").last
+          comments = []
+          @body.split(/(\/\*.*?\*\/)\s*?\n/m).each_with_index do |chunk, index|
+            comments[index] = chunk
+            if chunk =~ /rb_define_(class|module).*?"(#{class_name})"/m then
+              comment = comments[index-1]
+              break
+            end
+          end
+        end
+      end
+      class_meth.comment = mangle_comment(comment) if comment
+    end
+    
+    ############################################################
+
+    def do_classes
+      @body.scan(/(\w+)\s* = \s*rb_define_module\s*\(\s*"(\w+)"\s*\)/mx) do 
+        |var_name, class_name|
+        handle_class_module(var_name, "module", class_name, nil, nil)
+      end
+      
+      # The '.' lets us handle SWIG-generated files
+      @body.scan(/([\w\.]+)\s* = \s*rb_define_class\s*
+                \( 
+                   \s*"(\w+)",
+                   \s*(\w+)\s*
+                \)/mx) do 
+        
+        |var_name, class_name, parent|
+        handle_class_module(var_name, "class", class_name, parent, nil)
+      end
+      
+      @body.scan(/(\w+)\s*=\s*boot_defclass\s*\(\s*"(\w+?)",\s*(\w+?)\s*\)/) do
+        |var_name, class_name, parent|
+        parent = nil if parent == "0"
+        handle_class_module(var_name, "class", class_name, parent, nil)
+      end
+
+      @body.scan(/(\w+)\s* = \s*rb_define_module_under\s*
+                \( 
+                   \s*(\w+),
+                   \s*"(\w+)"
+                \s*\)/mx) do 
+        
+        |var_name, in_module, class_name|
+        handle_class_module(var_name, "module", class_name, nil, in_module)
+      end
+      
+      @body.scan(/([\w\.]+)\s* = \s*rb_define_class_under\s*
+                \( 
+                   \s*(\w+),
+                   \s*"(\w+)",
+                   \s*(\w+)\s*
+                \s*\)/mx) do 
+        
+        |var_name, in_module, class_name, parent|
+        handle_class_module(var_name, "class", class_name, parent, in_module)
+      end
+      
+    end
+
+		###########################################################
+
+    def do_constants
+      @body.scan(%r{\Wrb_define_
+                     (
+                        variable |
+                        readonly_variable |
+                        const |
+                        global_const |
+                      )
+                 \s*\( 
+                   (?:\s*(\w+),)?
+                   \s*"(\w+)",
+                   \s*(.*?)\s*\)\s*;
+                   }xm) do
+        
+        |type, var_name, const_name, definition|
+        var_name = "rb_cObject" if !var_name or var_name == "rb_mKernel"
+				handle_constants(type, var_name, const_name, definition)
+      end
+    end
+    
+    ############################################################
+    
+    def do_methods
+
+      @body.scan(%r{rb_define_
+                     (
+                        singleton_method |
+                        method           |
+                        module_function  |
+                        private_method
+                     )
+                     \s*\(\s*([\w\.]+),
+                       \s*"([^"]+)",
+                       \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
+                       \s*(-?\w+)\s*\)
+                     (?:;\s*/[*/]\s+in\s+(\w+?\.[cy]))?
+                   }xm) do
+        |type, var_name, meth_name, meth_body, param_count, source_file|
+       #" 
+
+        # Ignore top-object and weird struct.c dynamic stuff
+        next if var_name == "ruby_top_self" 
+        next if var_name == "nstr"
+        next if var_name == "envtbl"
+        next if var_name == "argf"   # it'd be nice to handle this one
+
+        var_name = "rb_cObject" if var_name == "rb_mKernel"
+        handle_method(type, var_name, meth_name, 
+                      meth_body, param_count, source_file)
+      end
+
+      @body.scan(%r{rb_define_attr\(
+                               \s*([\w\.]+),
+                               \s*"([^"]+)",
+                               \s*(\d+),
+                               \s*(\d+)\s*\);
+                  }xm) do  #"
+        |var_name, attr_name, attr_reader, attr_writer|
+        
+        #var_name = "rb_cObject" if var_name == "rb_mKernel"
+        handle_attr(var_name, attr_name,
+                    attr_reader.to_i != 0,
+                    attr_writer.to_i != 0)
+      end
+
+      @body.scan(%r{rb_define_global_function\s*\(
+                               \s*"([^"]+)",
+                               \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
+                               \s*(-?\w+)\s*\)
+                  (?:;\s*/[*/]\s+in\s+(\w+?\.[cy]))?
+                  }xm) do  #"
+        |meth_name, meth_body, param_count, source_file|
+        handle_method("method", "rb_mKernel", meth_name, 
+                      meth_body, param_count, source_file)
+      end
+  
+      @body.scan(/define_filetest_function\s*\(
+                               \s*"([^"]+)",
+                               \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
+                               \s*(-?\w+)\s*\)/xm) do  #"
+        |meth_name, meth_body, param_count|
+        
+        handle_method("method", "rb_mFileTest", meth_name, meth_body, param_count)
+        handle_method("singleton_method", "rb_cFile", meth_name, meth_body, param_count)
+      end
+   end
+
+    ############################################################
+    
+    def do_aliases
+      @body.scan(%r{rb_define_alias\s*\(\s*(\w+),\s*"([^"]+)",\s*"([^"]+)"\s*\)}m) do
+        |var_name, new_name, old_name|
+        @stats.num_methods += 1
+        class_name = @known_classes[var_name] || var_name
+        class_obj  = find_class(var_name, class_name)
+
+        class_obj.add_alias(Alias.new("", old_name, new_name, ""))
+      end
+   end
+
+    ##
+    # Adds constant comments.  By providing some_value: at the start ofthe
+    # comment you can override the C value of the comment to give a friendly
+    # definition.
+    #
+    #   /* 300: The perfect score in bowling */
+    #   rb_define_const(cFoo, "PERFECT", INT2FIX(300);
+    #
+    # Will override +INT2FIX(300)+ with the value +300+ in the output RDoc.
+    # Values may include quotes and escaped colons (\:).
+
+    def handle_constants(type, var_name, const_name, definition)
+      #@stats.num_constants += 1
+      class_name = @known_classes[var_name]
+      
+      return unless class_name
+
+      class_obj  = find_class(var_name, class_name)
+
+      unless class_obj
+        warn("Enclosing class/module '#{const_name}' for not known")
+        return
+      end
+      
+      comment = find_const_comment(type, const_name)
+
+      # In the case of rb_define_const, the definition and comment are in
+      # "/* definition: comment */" form.  The literal ':' and '\' characters
+      # can be escaped with a backslash.
+      if type.downcase == 'const' then
+         elements = mangle_comment(comment).split(':')
+         if elements.nil? or elements.empty? then
+            con = Constant.new(const_name, definition, mangle_comment(comment))
+         else
+            new_definition = elements[0..-2].join(':')
+            if new_definition.empty? then # Default to literal C definition
+               new_definition = definition
+            else
+               new_definition.gsub!("\:", ":")
+               new_definition.gsub!("\\", '\\')
+            end
+            new_definition.sub!(/\A(\s+)/, '')
+            new_comment = $1.nil? ? elements.last : "#{$1}#{elements.last.lstrip}"
+            con = Constant.new(const_name, new_definition,
+                               mangle_comment(new_comment))
+         end
+      else
+         con = Constant.new(const_name, definition, mangle_comment(comment))
+      end
+
+      class_obj.add_constant(con)
+    end
+
+    ##
+    # Finds a comment matching +type+ and +const_name+ either above the
+    # comment or in the matching Document- section.
+
+    def find_const_comment(type, const_name)
+      if @body =~ %r{((?>^\s*/\*.*?\*/\s+))
+                     rb_define_#{type}\((?:\s*(\w+),)?\s*"#{const_name}"\s*,.*?\)\s*;}xmi
+        $1
+      elsif @body =~ %r{Document-(?:const|global|variable):\s#{const_name}\s*?\n((?>.*?\*/))}m
+        $1
+      else
+        ''
+      end
+    end
+
+    ###########################################################
+
+    def handle_attr(var_name, attr_name, reader, writer)
+      rw = ''
+      if reader 
+        #@stats.num_methods += 1
+        rw << 'R'
+      end
+      if writer
+        #@stats.num_methods += 1
+        rw << 'W'
+      end
+
+      class_name = @known_classes[var_name]
+
+      return unless class_name
+      
+      class_obj  = find_class(var_name, class_name)
+
+      if class_obj
+        comment = find_attr_comment(attr_name)
+        unless comment.empty?
+          comment = mangle_comment(comment)
+        end
+        att = Attr.new('', attr_name, rw, comment)
+        class_obj.add_attribute(att)
+      end
+
+    end
+
+    ###########################################################
+
+    def find_attr_comment(attr_name)
+      if @body =~ %r{((?>/\*.*?\*/\s+))
+                     rb_define_attr\((?:\s*(\w+),)?\s*"#{attr_name}"\s*,.*?\)\s*;}xmi
+        $1
+      elsif @body =~ %r{Document-attr:\s#{attr_name}\s*?\n((?>.*?\*/))}m
+        $1
+      else
+        ''
+      end
+    end
+
+    ###########################################################
+
+    def handle_method(type, var_name, meth_name, 
+                      meth_body, param_count, source_file = nil)
+      progress(".")
+
+      @stats.num_methods += 1
+      class_name = @known_classes[var_name]
+
+      return unless class_name
+
+      class_obj  = find_class(var_name, class_name)
+      
+      if class_obj
+        if meth_name == "initialize"
+          meth_name = "new"
+          type = "singleton_method"
+        end
+        meth_obj = AnyMethod.new("", meth_name)
+        meth_obj.singleton =
+	  %w{singleton_method module_function}.include?(type) 
+        
+        p_count = (Integer(param_count) rescue -1)
+        
+        if p_count < 0
+          meth_obj.params = "(...)"
+        elsif p_count == 0
+          meth_obj.params = "()"
+        else
+          meth_obj.params = "(" +
+                            (1..p_count).map{|i| "p#{i}"}.join(", ") + 
+                                                ")"
+        end
+
+        if source_file
+          file_name = File.join(@file_dir, source_file)
+          body = (@@known_bodies[source_file] ||= File.read(file_name))
+        else
+          body = @body
+        end
+        if find_body(meth_body, meth_obj, body) and meth_obj.document_self
+          class_obj.add_method(meth_obj)
+        end
+      end
+    end
+    
+    ############################################################
+
+    # Find the C code corresponding to a Ruby method
+    def find_body(meth_name, meth_obj, body, quiet = false)
+      case body
+      when %r{((?>/\*.*?\*/\s*))(?:static\s+)?VALUE\s+#{meth_name}
+              \s*(\(.*?\)).*?^}xm
+        comment, params = $1, $2
+        body_text = $&
+
+        remove_private_comments(comment) if comment
+
+        # see if we can find the whole body
+        
+        re = Regexp.escape(body_text) + '[^(]*^\{.*?^\}'
+        if Regexp.new(re, Regexp::MULTILINE).match(body)
+          body_text = $&
+        end
+
+        # The comment block may have been overridden with a
+        # 'Document-method' block. This happens in the interpreter
+        # when multiple methods are vectored through to the same
+        # C method but those methods are logically distinct (for
+        # example Kernel.hash and Kernel.object_id share the same
+        # implementation
+
+        override_comment = find_override_comment(meth_obj.name)
+        comment = override_comment if override_comment
+
+        find_modifiers(comment, meth_obj) if comment
+        
+#        meth_obj.params = params
+        meth_obj.start_collecting_tokens
+        meth_obj.add_token(RubyToken::Token.new(1,1).set_text(body_text))
+        meth_obj.comment = mangle_comment(comment)
+      when %r{((?>/\*.*?\*/\s*))^\s*\#\s*define\s+#{meth_name}\s+(\w+)}m
+        comment = $1
+        find_body($2, meth_obj, body, true)
+        find_modifiers(comment, meth_obj)
+        meth_obj.comment = mangle_comment(comment) + meth_obj.comment
+      when %r{^\s*\#\s*define\s+#{meth_name}\s+(\w+)}m
+        unless find_body($1, meth_obj, body, true)
+          warn "No definition for #{meth_name}" unless quiet
+          return false
+        end
+      else
+
+        # No body, but might still have an override comment
+        comment = find_override_comment(meth_obj.name)
+
+        if comment
+          find_modifiers(comment, meth_obj)
+          meth_obj.comment = mangle_comment(comment)
+        else
+          warn "No definition for #{meth_name}" unless quiet
+          return false
+        end
+      end
+      true
+    end
+
+
+    ##
+    # If the comment block contains a section that looks like:
+    #
+    #    call-seq:
+    #        Array.new
+    #        Array.new(10)
+    #
+    # use it for the parameters.
+
+    def find_modifiers(comment, meth_obj)
+      if comment.sub!(/:nodoc:\s*^\s*\*?\s*$/m, '') or
+         comment.sub!(/\A\/\*\s*:nodoc:\s*\*\/\Z/, '')
+        meth_obj.document_self = false
+      end
+      if comment.sub!(/call-seq:(.*?)^\s*\*?\s*$/m, '') or
+         comment.sub!(/\A\/\*\s*call-seq:(.*?)\*\/\Z/, '')
+        seq = $1
+        seq.gsub!(/^\s*\*\s*/, '')
+        meth_obj.call_seq = seq
+      end
+    end
+
+    ############################################################
+
+    def find_override_comment(meth_name)
+      name = Regexp.escape(meth_name)
+      if @body =~ %r{Document-method:\s#{name}\s*?\n((?>.*?\*/))}m
+        $1
+      end
+    end
+
+    ##
+    # Look for includes of the form:
+    #
+    #     rb_include_module(rb_cArray, rb_mEnumerable);
+
+    def do_includes
+      @body.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c,m|
+        if cls = @classes[c]
+          m = @known_classes[m] || m
+          cls.add_include(Include.new(m, ""))
+        end
+      end
+    end
+
+    ##
+    # Remove the /*'s and leading asterisks from C comments
+    
+    def mangle_comment(comment)
+      comment.sub!(%r{/\*+}) { " " * $&.length }
+      comment.sub!(%r{\*+/}) { " " * $&.length }
+      comment.gsub!(/^[ \t]*\*/m) { " " * $&.length }
+      comment
+    end
+
+    def find_class(raw_name, name)
+      unless @classes[raw_name]
+        if raw_name =~ /^rb_m/ 
+          @classes[raw_name] = @top_level.add_module(NormalModule, name)
+        else
+          @classes[raw_name] = @top_level.add_class(NormalClass, name, nil)
+        end
+      end
+      @classes[raw_name]
+    end
+
+    def handle_tab_width(body)
+      if /\t/ =~ body
+        tab_width = Options.instance.tab_width
+        body.split(/\n/).map do |line|
+          1 while line.gsub!(/\t+/) { ' ' * (tab_width*$&.length - $`.length % tab_width)}  && $~ #`
+          line
+        end .join("\n")
+      else
+        body
+      end
+    end
+
+    ##
+    # Removes #ifdefs that would otherwise confuse us
+    
+    def handle_ifdefs_in(body)
+      body.gsub(/^#ifdef HAVE_PROTOTYPES.*?#else.*?\n(.*?)#endif.*?\n/m) { $1 }
+    end
+    
+  end
+
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parse_f95.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parse_f95.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parse_f95.rb	(revision 18425)
@@ -0,0 +1,1841 @@
+#= parse_f95.rb - Fortran95 Parser
+#
+#== Overview
+#
+#"parse_f95.rb" parses Fortran95 files with suffixes "f90", "F90", "f95"
+#and "F95". Fortran95 files are expected to be conformed to Fortran95
+#standards.
+#
+#== Rules
+#
+#Fundamental rules are same as that of the Ruby parser.
+#But comment markers are '!' not '#'.
+#
+#=== Correspondence between RDoc documentation and Fortran95 programs
+#
+#"parse_f95.rb" parses main programs, modules, subroutines, functions,
+#derived-types, public variables, public constants,
+#defined operators and defined assignments.
+#These components are described in items of RDoc documentation, as follows.
+#
+#Files :: Files (same as Ruby)
+#Classes :: Modules
+#Methods :: Subroutines, functions, variables, constants, derived-types, defined operators, defined assignments
+#Required files :: Files in which imported modules, external subroutines and external functions are defined.
+#Included Modules :: List of imported modules
+#Attributes :: List of derived-types, List of imported modules all of whose components are published again
+#
+#Components listed in 'Methods' (subroutines, functions, ...)
+#defined in modules are described in the item of 'Classes'.
+#On the other hand, components defined in main programs or
+#as external procedures are described in the item of 'Files'.
+#
+#=== Components parsed by default
+#
+#By default, documentation on public components (subroutines, functions, 
+#variables, constants, derived-types, defined operators, 
+#defined assignments) are generated. 
+#With "--all" option, documentation on all components
+#are generated (almost same as the Ruby parser).
+#
+#=== Information parsed automatically
+#
+#The following information is automatically parsed.
+#
+#* Types of arguments
+#* Types of variables and constants
+#* Types of variables in the derived types, and initial values
+#* NAMELISTs and types of variables in them, and initial values
+#
+#Aliases by interface statement are described in the item of 'Methods'.
+#
+#Components which are imported from other modules and published again 
+#are described in the item of 'Methods'.
+#
+#=== Format of comment blocks
+#
+#Comment blocks should be written as follows.
+#Comment blocks are considered to be ended when the line without '!'
+#appears.
+#The indentation is not necessary.
+#
+#     ! (Top of file)
+#     !
+#     ! Comment blocks for the files.
+#     !
+#     !--
+#     ! The comment described in the part enclosed by
+#     ! "!--" and "!++" is ignored.
+#     !++
+#     !
+#     module hogehoge
+#       !
+#       ! Comment blocks for the modules (or the programs).
+#       !
+#
+#       private
+#
+#       logical            :: a     ! a private variable
+#       real, public       :: b     ! a public variable
+#       integer, parameter :: c = 0 ! a public constant
+#
+#       public :: c
+#       public :: MULTI_ARRAY
+#       public :: hoge, foo
+#
+#       type MULTI_ARRAY
+#         !
+#         ! Comment blocks for the derived-types.
+#         !
+#         real, pointer :: var(:) =>null() ! Comments block for the variables.
+#         integer       :: num = 0
+#       end type MULTI_ARRAY
+#
+#     contains
+#
+#       subroutine hoge( in,   &   ! Comment blocks between continuation lines are ignored.
+#           &            out )
+#         !
+#         ! Comment blocks for the subroutines or functions
+#         !
+#         character(*),intent(in):: in ! Comment blocks for the arguments.
+#         character(*),intent(out),allocatable,target  :: in
+#                                      ! Comment blocks can be
+#                                      ! written under Fortran statements.
+#
+#         character(32) :: file ! This comment parsed as a variable in below NAMELIST.
+#         integer       :: id
+#
+#         namelist /varinfo_nml/ file, id
+#                 !
+#                 ! Comment blocks for the NAMELISTs.
+#                 ! Information about variables are described above.
+#                 !
+#
+#       ....
+#
+#       end subroutine hoge
+#
+#       integer function foo( in )
+#         !
+#         ! This part is considered as comment block.
+#
+#         ! Comment blocks under blank lines are ignored.
+#         !
+#         integer, intent(in):: inA ! This part is considered as comment block.
+#
+#                                   ! This part is ignored.
+#
+#       end function foo
+#
+#       subroutine hide( in,   &
+#         &              out )      !:nodoc:
+#         !
+#         ! If "!:nodoc:" is described at end-of-line in subroutine
+#         ! statement as above, the subroutine is ignored.
+#         ! This assignment can be used to modules, subroutines,
+#         ! functions, variables, constants, derived-types,
+#         ! defined operators, defined assignments,
+#         ! list of imported modules ("use" statement).
+#         !
+#
+#       ....
+#
+#       end subroutine hide
+#
+#     end module hogehoge
+#
+
+
+require "rdoc/code_objects"
+
+module RDoc
+
+  class Token
+
+    NO_TEXT = "??".freeze
+
+    def initialize(line_no, char_no)
+      @line_no = line_no
+      @char_no = char_no
+      @text    = NO_TEXT
+    end
+    # Because we're used in contexts that expect to return a token,
+    # we set the text string and then return ourselves
+    def set_text(text)
+      @text = text
+      self
+    end
+
+    attr_reader :line_no, :char_no, :text
+
+  end
+
+  # See rdoc/parsers/parse_f95.rb
+
+  class Fortran95parser
+
+    extend ParserFactory
+    parse_files_matching(/\.((f|F)9(0|5)|F)$/)
+
+    @@external_aliases = []
+    @@public_methods   = []
+
+    # "false":: Comments are below source code
+    # "true" :: Comments are upper source code
+    COMMENTS_ARE_UPPER  = false
+
+    # Internal alias message
+    INTERNAL_ALIAS_MES = "Alias for"
+
+    # External alias message
+    EXTERNAL_ALIAS_MES = "The entity is"
+
+    # prepare to parse a Fortran 95 file
+    def initialize(top_level, file_name, body, options, stats)
+      @body = body
+      @stats = stats
+      @file_name  = file_name
+      @options = options
+      @top_level = top_level
+      @progress = $stderr unless options.quiet
+    end
+
+    # devine code constructs
+    def scan
+
+      # remove private comment
+      remaining_code = remove_private_comments(@body)
+
+      # continuation lines are united to one line
+      remaining_code = united_to_one_line(remaining_code)
+
+      # semicolons are replaced to line feed
+      remaining_code = semicolon_to_linefeed(remaining_code)
+
+      # collect comment for file entity
+      whole_comment, remaining_code = collect_first_comment(remaining_code)
+      @top_level.comment = whole_comment
+
+      # String "remaining_code" is converted to Array "remaining_lines"
+      remaining_lines = remaining_code.split("\n")
+
+      # "module" or "program" parts are parsed (new)
+      #
+      level_depth = 0
+      block_searching_flag = nil
+      block_searching_lines = []
+      pre_comment = []
+      module_program_trailing = ""
+      module_program_name = ""
+      other_block_level_depth = 0
+      other_block_searching_flag = nil
+      remaining_lines.collect!{|line|
+        if !block_searching_flag && !other_block_searching_flag
+          if line =~ /^\s*?module\s+(\w+)\s*?(!.*?)?$/i
+            block_searching_flag = :module
+            block_searching_lines << line
+            module_program_name = $1
+            module_program_trailing = find_comments($2)
+            next false
+          elsif line =~ /^\s*?program\s+(\w+)\s*?(!.*?)?$/i ||
+                 line =~ /^\s*?\w/ && !block_start?(line)
+            block_searching_flag = :program
+            block_searching_lines << line
+            module_program_name = $1 || ""
+            module_program_trailing = find_comments($2)
+            next false
+
+          elsif block_start?(line)
+            other_block_searching_flag = true
+            next line
+
+          elsif line =~ /^\s*?!\s?(.*)/
+            pre_comment << line
+            next line
+          else
+            pre_comment = []
+            next line
+          end
+        elsif other_block_searching_flag
+          other_block_level_depth += 1 if block_start?(line)
+          other_block_level_depth -= 1 if block_end?(line)
+          if other_block_level_depth < 0
+            other_block_level_depth = 0
+            other_block_searching_flag = nil
+          end
+          next line
+        end
+
+        block_searching_lines << line
+        level_depth += 1 if block_start?(line)
+        level_depth -= 1 if block_end?(line)
+        if level_depth >= 0
+          next false
+        end
+
+        # "module_program_code" is formatted.
+        # ":nodoc:" flag is checked.
+        #
+        module_program_code = block_searching_lines.join("\n")
+        module_program_code = remove_empty_head_lines(module_program_code)
+        if module_program_trailing =~ /^:nodoc:/
+          # next loop to search next block
+          level_depth = 0
+          block_searching_flag = false
+          block_searching_lines = []
+          pre_comment = []
+          next false
+        end
+
+        # NormalClass is created, and added to @top_level
+        #
+        if block_searching_flag == :module
+          module_name = module_program_name
+          module_code = module_program_code
+          module_trailing = module_program_trailing
+          progress "m"
+          @stats.num_modules += 1
+          f9x_module = @top_level.add_module NormalClass, module_name
+          f9x_module.record_location @top_level
+
+          f9x_comment = COMMENTS_ARE_UPPER ? 
+            find_comments(pre_comment.join("\n"))  + "\n" + module_trailing :
+              module_trailing + "\n" + find_comments(module_code.sub(/^.*$\n/i, ''))
+          f9x_module.comment = f9x_comment
+          parse_program_or_module(f9x_module, module_code)
+
+          TopLevel.all_files.each do |name, toplevel|
+            if toplevel.include_includes?(module_name, @options.ignore_case)
+              if !toplevel.include_requires?(@file_name, @options.ignore_case)
+                toplevel.add_require(Require.new(@file_name, ""))
+              end
+            end
+            toplevel.each_classmodule{|m|
+              if m.include_includes?(module_name, @options.ignore_case)
+                if !m.include_requires?(@file_name, @options.ignore_case)
+                  m.add_require(Require.new(@file_name, ""))
+                end
+              end
+            }
+          end
+        elsif block_searching_flag == :program
+          program_name = module_program_name
+          program_code = module_program_code
+          program_trailing = module_program_trailing
+          progress "p"
+          program_comment = COMMENTS_ARE_UPPER ? 
+            find_comments(pre_comment.join("\n")) + "\n" + program_trailing : 
+              program_trailing + "\n" + find_comments(program_code.sub(/^.*$\n/i, ''))
+          program_comment = "\n\n= <i>Program</i> <tt>#{program_name}</tt>\n\n" \
+                            + program_comment
+          @top_level.comment << program_comment
+          parse_program_or_module(@top_level, program_code, :private)
+        end
+
+        # next loop to search next block
+        level_depth = 0
+        block_searching_flag = false
+        block_searching_lines = []
+        pre_comment = []
+        next false
+      }
+
+      remaining_lines.delete_if{ |line|
+        line == false
+      }
+
+      # External subprograms and functions are parsed
+      #
+      parse_program_or_module(@top_level, remaining_lines.join("\n"),
+                              :public, true)
+
+      @top_level
+    end  # End of scan
+
+    private
+
+    def parse_program_or_module(container, code,
+                                visibility=:public, external=nil)
+      return unless container
+      return unless code
+      remaining_lines = code.split("\n")
+      remaining_code = "#{code}"
+
+      #
+      # Parse variables before "contains" in module
+      #
+      level_depth = 0
+      before_contains_lines = []
+      before_contains_code = nil
+      before_contains_flag = nil
+      remaining_lines.each{ |line|
+        if !before_contains_flag
+          if line =~ /^\s*?module\s+\w+\s*?(!.*?)?$/i
+            before_contains_flag = true
+          end
+        else
+          break if line =~ /^\s*?contains\s*?(!.*?)?$/i
+          level_depth += 1 if block_start?(line)
+          level_depth -= 1 if block_end?(line)
+          break if level_depth < 0
+          before_contains_lines << line
+        end
+      }
+      before_contains_code = before_contains_lines.join("\n")
+      if before_contains_code
+        before_contains_code.gsub!(/^\s*?interface\s+.*?\s+end\s+interface.*?$/im, "")
+        before_contains_code.gsub!(/^\s*?type[\s\,]+.*?\s+end\s+type.*?$/im, "")
+      end
+
+      #
+      # Parse global "use"
+      #
+      use_check_code = "#{before_contains_code}"
+      cascaded_modules_list = []
+      while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i
+        use_check_code = $~.pre_match
+        use_check_code << $~.post_match
+        used_mod_name = $1.strip.chomp
+        used_list = $2 || ""
+        used_trailing = $3 || ""
+        next if used_trailing =~ /!:nodoc:/
+        if !container.include_includes?(used_mod_name, @options.ignore_case)
+          progress "."
+          container.add_include Include.new(used_mod_name, "")
+        end
+        if ! (used_list =~ /\,\s*?only\s*?:/i )
+          cascaded_modules_list << "\#" + used_mod_name
+        end
+      end
+
+      #
+      # Parse public and private, and store information.
+      # This information is used when "add_method" and
+      # "set_visibility_for" are called.
+      #
+      visibility_default, visibility_info = 
+                parse_visibility(remaining_lines.join("\n"), visibility, container)
+      @@public_methods.concat visibility_info
+      if visibility_default == :public
+        if !cascaded_modules_list.empty?
+          cascaded_modules = 
+            Attr.new("Cascaded Modules",
+                     "Imported modules all of whose components are published again",
+                     "",
+                     cascaded_modules_list.join(", "))
+          container.add_attribute(cascaded_modules)
+        end
+      end
+
+      #
+      # Check rename elements
+      #
+      use_check_code = "#{before_contains_code}"
+      while use_check_code =~ /^\s*?use\s+(\w+)\s*?\,(.+)$/i
+        use_check_code = $~.pre_match
+        use_check_code << $~.post_match
+        used_mod_name = $1.strip.chomp
+        used_elements = $2.sub(/\s*?only\s*?:\s*?/i, '')
+        used_elements.split(",").each{ |used|
+          if /\s*?(\w+)\s*?=>\s*?(\w+)\s*?/ =~ used
+            local = $1
+            org = $2
+            @@public_methods.collect!{ |pub_meth|
+              if local == pub_meth["name"] ||
+                  local.upcase == pub_meth["name"].upcase &&
+                  @options.ignore_case
+                pub_meth["name"] = org
+                pub_meth["local_name"] = local
+              end
+              pub_meth
+            }
+          end
+        }
+      end
+
+      #
+      # Parse private "use"
+      #
+      use_check_code = remaining_lines.join("\n")
+      while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i
+        use_check_code = $~.pre_match
+        use_check_code << $~.post_match
+        used_mod_name = $1.strip.chomp
+        used_trailing = $3 || ""
+        next if used_trailing =~ /!:nodoc:/
+        if !container.include_includes?(used_mod_name, @options.ignore_case)
+          progress "."
+          container.add_include Include.new(used_mod_name, "")
+        end
+      end
+
+      container.each_includes{ |inc|
+        TopLevel.all_files.each do |name, toplevel|
+          indicated_mod = toplevel.find_symbol(inc.name,
+                                               nil, @options.ignore_case)
+          if indicated_mod
+            indicated_name = indicated_mod.parent.file_relative_name
+            if !container.include_requires?(indicated_name, @options.ignore_case)
+              container.add_require(Require.new(indicated_name, ""))
+            end
+            break
+          end
+        end
+      }
+
+      #
+      # Parse derived-types definitions
+      #
+      derived_types_comment = ""
+      remaining_code = remaining_lines.join("\n")
+      while remaining_code =~ /^\s*?
+                                    type[\s\,]+(public|private)?\s*?(::)?\s*?
+                                    (\w+)\s*?(!.*?)?$
+                                    (.*?)
+                                    ^\s*?end\s+type.*?$
+                              /imx
+        remaining_code = $~.pre_match
+        remaining_code << $~.post_match
+        typename = $3.chomp.strip
+        type_elements = $5 || ""
+        type_code = remove_empty_head_lines($&)
+        type_trailing = find_comments($4)
+        next if type_trailing =~ /^:nodoc:/
+        type_visibility = $1
+        type_comment = COMMENTS_ARE_UPPER ? 
+          find_comments($~.pre_match) + "\n" + type_trailing :
+            type_trailing + "\n" + find_comments(type_code.sub(/^.*$\n/i, ''))
+        type_element_visibility_public = true
+        type_code.split("\n").each{ |line|
+          if /^\s*?private\s*?$/ =~ line
+            type_element_visibility_public = nil
+            break
+          end
+        } if type_code
+
+        args_comment = ""
+        type_args_info = nil
+
+        if @options.show_all
+          args_comment = find_arguments(nil, type_code, true)
+        else
+          type_public_args_list = []
+          type_args_info = definition_info(type_code)
+          type_args_info.each{ |arg|
+            arg_is_public = type_element_visibility_public
+            arg_is_public = true if arg.include_attr?("public")
+            arg_is_public = nil if arg.include_attr?("private")
+            type_public_args_list << arg.varname if arg_is_public
+          }
+          args_comment = find_arguments(type_public_args_list, type_code)
+        end
+
+        type = AnyMethod.new("type #{typename}", typename)
+        type.singleton = false
+        type.params = ""
+        type.comment = "<b><em> Derived Type </em></b> :: <tt></tt>\n"
+        type.comment << args_comment if args_comment
+        type.comment << type_comment if type_comment
+        progress "t"
+        @stats.num_methods += 1
+        container.add_method type
+
+        set_visibility(container, typename, visibility_default, @@public_methods)
+
+        if type_visibility
+          type_visibility.gsub!(/\s/,'')
+          type_visibility.gsub!(/\,/,'')
+          type_visibility.gsub!(/:/,'')
+          type_visibility.downcase!
+          if type_visibility == "public"
+            container.set_visibility_for([typename], :public)
+          elsif type_visibility == "private"
+            container.set_visibility_for([typename], :private)
+          end
+        end
+
+        check_public_methods(type, container.name)
+
+        if @options.show_all
+          derived_types_comment << ", " unless derived_types_comment.empty?
+          derived_types_comment << typename
+        else
+          if type.visibility == :public
+          derived_types_comment << ", " unless derived_types_comment.empty?
+          derived_types_comment << typename
+          end
+        end
+
+      end
+
+      if !derived_types_comment.empty?
+        derived_types_table = 
+          Attr.new("Derived Types", "Derived_Types", "", 
+                   derived_types_comment)
+        container.add_attribute(derived_types_table)
+      end
+
+      #
+      # move interface scope
+      #
+      interface_code = ""
+      while remaining_code =~ /^\s*?
+                                   interface(
+                                              \s+\w+                      |
+                                              \s+operator\s*?\(.*?\)       |
+                                              \s+assignment\s*?\(\s*?=\s*?\)
+                                            )?\s*?$
+                                   (.*?)
+                                   ^\s*?end\s+interface.*?$
+                              /imx
+        interface_code << remove_empty_head_lines($&) + "\n"
+        remaining_code = $~.pre_match
+        remaining_code << $~.post_match
+      end
+
+      #
+      # Parse global constants or variables in modules
+      #
+      const_var_defs = definition_info(before_contains_code)
+      const_var_defs.each{|defitem|
+        next if defitem.nodoc
+        const_or_var_type = "Variable"
+        const_or_var_progress = "v"
+        if defitem.include_attr?("parameter")
+          const_or_var_type = "Constant"
+          const_or_var_progress = "c"
+        end
+        const_or_var = AnyMethod.new(const_or_var_type, defitem.varname)
+        const_or_var.singleton = false
+        const_or_var.params = ""
+        self_comment = find_arguments([defitem.varname], before_contains_code)
+        const_or_var.comment = "<b><em>" + const_or_var_type + "</em></b> :: <tt></tt>\n"
+        const_or_var.comment << self_comment if self_comment
+        progress const_or_var_progress
+        @stats.num_methods += 1
+        container.add_method const_or_var
+
+        set_visibility(container, defitem.varname, visibility_default, @@public_methods)
+
+        if defitem.include_attr?("public")
+          container.set_visibility_for([defitem.varname], :public)
+        elsif defitem.include_attr?("private")
+          container.set_visibility_for([defitem.varname], :private)
+        end
+
+        check_public_methods(const_or_var, container.name)
+
+      } if const_var_defs
+
+      remaining_lines = remaining_code.split("\n")
+
+      # "subroutine" or "function" parts are parsed (new)
+      #
+      level_depth = 0
+      block_searching_flag = nil
+      block_searching_lines = []
+      pre_comment = []
+      procedure_trailing = ""
+      procedure_name = ""
+      procedure_params = ""
+      procedure_prefix = ""
+      procedure_result_arg = ""
+      procedure_type = ""
+      contains_lines = []
+      contains_flag = nil
+      remaining_lines.collect!{|line|
+        if !block_searching_flag
+          # subroutine
+          if line =~ /^\s*?
+                           (recursive|pure|elemental)?\s*?
+                           subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
+                     /ix
+            block_searching_flag = :subroutine
+            block_searching_lines << line
+
+            procedure_name = $2.chomp.strip
+            procedure_params = $3 || ""
+            procedure_prefix = $1 || ""
+            procedure_trailing = $4 || "!"
+            next false
+
+          # function
+          elsif line =~ /^\s*?
+                         (recursive|pure|elemental)?\s*?
+                         (
+                             character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                           | type\s*?\([\w\s]+?\)\s+
+                           | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                           | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                           | double\s+precision\s+
+                           | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                           | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                         )?
+                         function\s+(\w+)\s*?
+                         (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
+                        /ix
+            block_searching_flag = :function
+            block_searching_lines << line
+
+            procedure_prefix = $1 || ""
+            procedure_type = $2 ? $2.chomp.strip : nil
+            procedure_name = $8.chomp.strip
+            procedure_params = $9 || ""
+            procedure_result_arg = $11 ? $11.chomp.strip : procedure_name
+            procedure_trailing = $12 || "!"
+            next false
+          elsif line =~ /^\s*?!\s?(.*)/
+            pre_comment << line
+            next line
+          else
+            pre_comment = []
+            next line
+          end
+        end
+        contains_flag = true if line =~ /^\s*?contains\s*?(!.*?)?$/
+        block_searching_lines << line
+        contains_lines << line if contains_flag
+
+        level_depth += 1 if block_start?(line)
+        level_depth -= 1 if block_end?(line)
+        if level_depth >= 0
+          next false
+        end
+
+        # "procedure_code" is formatted.
+        # ":nodoc:" flag is checked.
+        #
+        procedure_code = block_searching_lines.join("\n")
+        procedure_code = remove_empty_head_lines(procedure_code)
+        if procedure_trailing =~ /^!:nodoc:/
+          # next loop to search next block
+          level_depth = 0
+          block_searching_flag = nil
+          block_searching_lines = []
+          pre_comment = []
+          procedure_trailing = ""
+          procedure_name = ""
+          procedure_params = ""
+          procedure_prefix = ""
+          procedure_result_arg = ""
+          procedure_type = ""
+          contains_lines = []
+          contains_flag = nil
+          next false
+        end
+
+        # AnyMethod is created, and added to container
+        #
+        subroutine_function = nil
+        if block_searching_flag == :subroutine
+          subroutine_prefix   = procedure_prefix
+          subroutine_name     = procedure_name
+          subroutine_params   = procedure_params
+          subroutine_trailing = procedure_trailing
+          subroutine_code     = procedure_code
+
+          subroutine_comment = COMMENTS_ARE_UPPER ? 
+            pre_comment.join("\n") + "\n" + subroutine_trailing : 
+              subroutine_trailing + "\n" + subroutine_code.sub(/^.*$\n/i, '')
+          subroutine = AnyMethod.new("subroutine", subroutine_name)
+          parse_subprogram(subroutine, subroutine_params,
+                           subroutine_comment, subroutine_code,
+                           before_contains_code, nil, subroutine_prefix)
+          progress "s"
+          @stats.num_methods += 1
+          container.add_method subroutine
+          subroutine_function = subroutine
+
+        elsif block_searching_flag == :function
+          function_prefix     = procedure_prefix
+          function_type       = procedure_type
+          function_name       = procedure_name
+          function_params_org = procedure_params
+          function_result_arg = procedure_result_arg
+          function_trailing   = procedure_trailing
+          function_code_org   = procedure_code
+
+          function_comment = COMMENTS_ARE_UPPER ?
+            pre_comment.join("\n") + "\n" + function_trailing :
+              function_trailing + "\n " + function_code_org.sub(/^.*$\n/i, '')
+
+          function_code = "#{function_code_org}"
+          if function_type
+            function_code << "\n" + function_type + " :: " + function_result_arg
+          end
+
+          function_params =
+            function_params_org.sub(/^\(/, "\(#{function_result_arg}, ")
+
+          function = AnyMethod.new("function", function_name)
+          parse_subprogram(function, function_params,
+                           function_comment, function_code,
+                           before_contains_code, true, function_prefix)
+
+          # Specific modification due to function
+          function.params.sub!(/\(\s*?#{function_result_arg}\s*?,\s*?/, "\( ")
+          function.params << " result(" + function_result_arg + ")"
+          function.start_collecting_tokens
+          function.add_token Token.new(1,1).set_text(function_code_org)
+
+          progress "f"
+          @stats.num_methods += 1
+          container.add_method function
+          subroutine_function = function
+
+        end
+
+        # The visibility of procedure is specified
+        #
+        set_visibility(container, procedure_name, 
+                       visibility_default, @@public_methods)
+
+        # The alias for this procedure from external modules
+        #
+        check_external_aliases(procedure_name,
+                               subroutine_function.params,
+                               subroutine_function.comment, subroutine_function) if external
+        check_public_methods(subroutine_function, container.name)
+
+
+        # contains_lines are parsed as private procedures
+        if contains_flag
+          parse_program_or_module(container,
+                                  contains_lines.join("\n"), :private)
+        end
+
+        # next loop to search next block
+        level_depth = 0
+        block_searching_flag = nil
+        block_searching_lines = []
+        pre_comment = []
+        procedure_trailing = ""
+        procedure_name = ""
+        procedure_params = ""
+        procedure_prefix = ""
+        procedure_result_arg = ""
+        contains_lines = []
+        contains_flag = nil
+        next false
+      } # End of remaining_lines.collect!{|line|
+
+      # Array remains_lines is converted to String remains_code again
+      #
+      remaining_code = remaining_lines.join("\n")
+
+      #
+      # Parse interface
+      #
+      interface_scope = false
+      generic_name = ""
+      interface_code.split("\n").each{ |line|
+        if /^\s*?
+                 interface(
+                            \s+\w+|
+                            \s+operator\s*?\(.*?\)|
+                            \s+assignment\s*?\(\s*?=\s*?\)
+                          )?
+                 \s*?(!.*?)?$
+           /ix =~ line
+          generic_name = $1 ? $1.strip.chomp : nil
+          interface_trailing = $2 || "!"
+          interface_scope = true
+          interface_scope = false if interface_trailing =~ /!:nodoc:/
+#          if generic_name =~ /operator\s*?\((.*?)\)/i
+#            operator_name = $1
+#            if operator_name && !operator_name.empty?
+#              generic_name = "#{operator_name}"
+#            end
+#          end
+#          if generic_name =~ /assignment\s*?\((.*?)\)/i
+#            assignment_name = $1
+#            if assignment_name && !assignment_name.empty?
+#              generic_name = "#{assignment_name}"
+#            end
+#          end
+        end
+        if /^\s*?end\s+interface/i =~ line
+          interface_scope = false
+          generic_name = nil
+        end
+        # internal alias
+        if interface_scope && /^\s*?module\s+procedure\s+(.*?)(!.*?)?$/i =~ line
+          procedures = $1.strip.chomp
+          procedures_trailing = $2 || "!"
+          next if procedures_trailing =~ /!:nodoc:/
+          procedures.split(",").each{ |proc|
+            proc.strip!
+            proc.chomp!
+            next if generic_name == proc || !generic_name
+            old_meth = container.find_symbol(proc, nil, @options.ignore_case)
+            next if !old_meth
+            nolink = old_meth.visibility == :private ? true : nil
+            nolink = nil if @options.show_all
+            new_meth = 
+               initialize_external_method(generic_name, proc, 
+                                          old_meth.params, nil, 
+                                          old_meth.comment, 
+                                          old_meth.clone.token_stream[0].text, 
+                                          true, nolink)
+            new_meth.singleton = old_meth.singleton
+
+            progress "i"
+            @stats.num_methods += 1
+            container.add_method new_meth
+
+            set_visibility(container, generic_name, visibility_default, @@public_methods)
+
+            check_public_methods(new_meth, container.name)
+
+          }
+        end
+
+        # external aliases
+        if interface_scope
+          # subroutine
+          proc = nil
+          params = nil
+          procedures_trailing = nil
+          if line =~ /^\s*?
+                           (recursive|pure|elemental)?\s*?
+                           subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
+                     /ix
+            proc = $2.chomp.strip
+            generic_name = proc unless generic_name
+            params = $3 || ""
+            procedures_trailing = $4 || "!"
+
+          # function
+          elsif line =~ /^\s*?
+                         (recursive|pure|elemental)?\s*?
+                         (
+                             character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                           | type\s*?\([\w\s]+?\)\s+
+                           | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                           | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                           | double\s+precision\s+
+                           | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                           | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                         )?
+                         function\s+(\w+)\s*?
+                         (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
+                        /ix
+            proc = $8.chomp.strip
+            generic_name = proc unless generic_name
+            params = $9 || ""
+            procedures_trailing = $12 || "!"
+          else
+            next
+          end
+          next if procedures_trailing =~ /!:nodoc:/
+          indicated_method = nil
+          indicated_file   = nil
+          TopLevel.all_files.each do |name, toplevel|
+            indicated_method = toplevel.find_local_symbol(proc, @options.ignore_case)
+            indicated_file = name
+            break if indicated_method
+          end
+
+          if indicated_method
+            external_method = 
+              initialize_external_method(generic_name, proc, 
+                                         indicated_method.params, 
+                                         indicated_file, 
+                                         indicated_method.comment)
+
+            progress "e"
+            @stats.num_methods += 1
+            container.add_method external_method
+            set_visibility(container, generic_name, visibility_default, @@public_methods)
+            if !container.include_requires?(indicated_file, @options.ignore_case)
+              container.add_require(Require.new(indicated_file, ""))
+            end
+            check_public_methods(external_method, container.name)
+
+          else
+            @@external_aliases << {
+              "new_name"  => generic_name,
+              "old_name"  => proc,
+              "file_or_module" => container,
+              "visibility" => find_visibility(container, generic_name, @@public_methods) || visibility_default
+            }
+          end
+        end
+
+      } if interface_code # End of interface_code.split("\n").each ...
+
+      #
+      # Already imported methods are removed from @@public_methods.
+      # Remainders are assumed to be imported from other modules.
+      #
+      @@public_methods.delete_if{ |method| method["entity_is_discovered"]}
+
+      @@public_methods.each{ |pub_meth|
+        next unless pub_meth["file_or_module"].name == container.name
+        pub_meth["used_modules"].each{ |used_mod|
+          TopLevel.all_classes_and_modules.each{ |modules|
+            if modules.name == used_mod ||
+                modules.name.upcase == used_mod.upcase &&
+                @options.ignore_case
+              modules.method_list.each{ |meth|
+                if meth.name == pub_meth["name"] ||
+                    meth.name.upcase == pub_meth["name"].upcase &&
+                    @options.ignore_case
+                  new_meth = initialize_public_method(meth,
+                                                      modules.name)
+                  if pub_meth["local_name"]
+                    new_meth.name = pub_meth["local_name"]
+                  end
+                  progress "e"
+                  @stats.num_methods += 1
+                  container.add_method new_meth
+                end
+              }
+            end
+          }
+        }
+      }
+
+      container
+    end  # End of parse_program_or_module
+
+    #
+    # Parse arguments, comment, code of subroutine and function.
+    # Return AnyMethod object.
+    #
+    def parse_subprogram(subprogram, params, comment, code, 
+                         before_contains=nil, function=nil, prefix=nil)
+      subprogram.singleton = false
+      prefix = "" if !prefix
+      arguments = params.sub(/\(/, "").sub(/\)/, "").split(",") if params
+      args_comment, params_opt = 
+        find_arguments(arguments, code.sub(/^s*?contains\s*?(!.*?)?$.*/im, ""),
+                       nil, nil, true)
+      params_opt = "( " + params_opt + " ) " if params_opt
+      subprogram.params = params_opt || ""
+      namelist_comment = find_namelists(code, before_contains)
+
+      block_comment = find_comments comment
+      if function
+        subprogram.comment = "<b><em> Function </em></b> :: <em>#{prefix}</em>\n"
+      else
+        subprogram.comment = "<b><em> Subroutine </em></b> :: <em>#{prefix}</em>\n"
+      end
+      subprogram.comment << args_comment if args_comment
+      subprogram.comment << block_comment if block_comment
+      subprogram.comment << namelist_comment if namelist_comment
+
+      # For output source code
+      subprogram.start_collecting_tokens
+      subprogram.add_token Token.new(1,1).set_text(code)
+
+      subprogram
+    end
+
+    #
+    # Collect comment for file entity
+    #
+    def collect_first_comment(body)
+      comment = ""
+      not_comment = ""
+      comment_start = false
+      comment_end   = false
+      body.split("\n").each{ |line|
+        if comment_end
+          not_comment << line
+          not_comment << "\n"
+        elsif /^\s*?!\s?(.*)$/i =~ line
+          comment_start = true
+          comment << $1
+          comment << "\n"
+        elsif /^\s*?$/i =~ line
+          comment_end = true if comment_start && COMMENTS_ARE_UPPER
+        else
+          comment_end = true
+          not_comment << line
+          not_comment << "\n"
+        end
+      }
+      return comment, not_comment
+    end
+
+
+    # Return comments of definitions of arguments
+    #
+    # If "all" argument is true, information of all arguments are returned.
+    # If "modified_params" is true, list of arguments are decorated,
+    # for exameple, optional arguments are parenthetic as "[arg]".
+    #
+    def find_arguments(args, text, all=nil, indent=nil, modified_params=nil)
+      return unless args || all
+      indent = "" unless indent
+      args = ["all"] if all
+      params = "" if modified_params
+      comma = ""
+      return unless text
+      args_rdocforms = "\n"
+      remaining_lines = "#{text}"
+      definitions = definition_info(remaining_lines)
+      args.each{ |arg|
+        arg.strip!
+        arg.chomp!
+        definitions.each { |defitem|
+          if arg == defitem.varname.strip.chomp || all
+            args_rdocforms << <<-"EOF"
+
+#{indent}<tt><b>#{defitem.varname.chomp.strip}#{defitem.arraysuffix}</b> #{defitem.inivalue}</tt> :: 
+#{indent}   <tt>#{defitem.types.chomp.strip}</tt>
+EOF
+            if !defitem.comment.chomp.strip.empty?
+              comment = ""
+              defitem.comment.split("\n").each{ |line|
+                comment << "       " + line + "\n"
+              }
+              args_rdocforms << <<-"EOF"
+
+#{indent}   <tt></tt> :: 
+#{indent}       <tt></tt>
+#{indent}       #{comment.chomp.strip}
+EOF
+            end
+
+            if modified_params
+              if defitem.include_attr?("optional")
+                params << "#{comma}[#{arg}]"
+              else
+                params << "#{comma}#{arg}"
+              end
+              comma = ", "
+            end
+          end
+        }
+      }
+      if modified_params
+        return args_rdocforms, params
+      else
+        return args_rdocforms
+      end
+    end
+
+    # Return comments of definitions of namelists
+    #
+    def find_namelists(text, before_contains=nil)
+      return nil if !text
+      result = ""
+      lines = "#{text}"
+      before_contains = "" if !before_contains
+      while lines =~ /^\s*?namelist\s+\/\s*?(\w+)\s*?\/([\s\w\,]+)$/i
+        lines = $~.post_match
+        nml_comment = COMMENTS_ARE_UPPER ? 
+            find_comments($~.pre_match) : find_comments($~.post_match)
+        nml_name = $1
+        nml_args = $2.split(",")
+        result << "\n\n=== NAMELIST <tt><b>" + nml_name + "</tt></b>\n\n"
+        result << nml_comment + "\n" if nml_comment
+        if lines.split("\n")[0] =~ /^\//i
+          lines = "namelist " + lines
+        end
+        result << find_arguments(nml_args, "#{text}" + "\n" + before_contains)
+      end
+      return result
+    end
+
+    #
+    # Comments just after module or subprogram, or arguments are
+    # returnd. If "COMMENTS_ARE_UPPER" is true, comments just before
+    # modules or subprograms are returnd
+    #
+    def find_comments text
+      return "" unless text
+      lines = text.split("\n")
+      lines.reverse! if COMMENTS_ARE_UPPER
+      comment_block = Array.new
+      lines.each do |line|
+        break if line =~ /^\s*?\w/ || line =~ /^\s*?$/
+        if COMMENTS_ARE_UPPER
+          comment_block.unshift line.sub(/^\s*?!\s?/,"")
+        else
+          comment_block.push line.sub(/^\s*?!\s?/,"")
+        end
+      end
+      nice_lines = comment_block.join("\n").split "\n\s*?\n"
+      nice_lines[0] ||= ""
+      nice_lines.shift
+    end
+
+    def progress(char)
+      unless @options.quiet
+        @progress.print(char)
+        @progress.flush
+      end
+    end
+
+    #
+    # Create method for internal alias
+    #
+    def initialize_public_method(method, parent)
+      return if !method || !parent
+
+      new_meth = AnyMethod.new("External Alias for module", method.name)
+      new_meth.singleton    = method.singleton
+      new_meth.params       = method.params.clone
+      new_meth.comment      = remove_trailing_alias(method.comment.clone)
+      new_meth.comment      << "\n\n#{EXTERNAL_ALIAS_MES} #{parent.strip.chomp}\##{method.name}"
+
+      return new_meth
+    end
+
+    #
+    # Create method for external alias
+    #
+    # If argument "internal" is true, file is ignored.
+    #
+    def initialize_external_method(new, old, params, file, comment, token=nil,
+                                   internal=nil, nolink=nil)
+      return nil unless new || old
+
+      if internal
+        external_alias_header = "#{INTERNAL_ALIAS_MES} "
+        external_alias_text   = external_alias_header + old 
+      elsif file
+        external_alias_header = "#{EXTERNAL_ALIAS_MES} "
+        external_alias_text   = external_alias_header + file + "#" + old
+      else
+        return nil
+      end
+      external_meth = AnyMethod.new(external_alias_text, new)
+      external_meth.singleton    = false
+      external_meth.params       = params
+      external_comment = remove_trailing_alias(comment) + "\n\n" if comment
+      external_meth.comment = external_comment || ""
+      if nolink && token
+        external_meth.start_collecting_tokens
+        external_meth.add_token Token.new(1,1).set_text(token)
+      else
+        external_meth.comment << external_alias_text
+      end
+
+      return external_meth
+    end
+
+
+
+    #
+    # Parse visibility
+    #
+    def parse_visibility(code, default, container)
+      result = []
+      visibility_default = default || :public
+
+      used_modules = []
+      container.includes.each{|i| used_modules << i.name} if container
+
+      remaining_code = code.gsub(/^\s*?type[\s\,]+.*?\s+end\s+type.*?$/im, "")
+      remaining_code.split("\n").each{ |line|
+        if /^\s*?private\s*?$/ =~ line
+          visibility_default = :private
+          break
+        end
+      } if remaining_code
+
+      remaining_code.split("\n").each{ |line|
+        if /^\s*?private\s*?(::)?\s+(.*)\s*?(!.*?)?/i =~ line
+          methods = $2.sub(/!.*$/, '')
+          methods.split(",").each{ |meth|
+            meth.sub!(/!.*$/, '')
+            meth.gsub!(/:/, '')
+            result << {
+              "name" => meth.chomp.strip,
+              "visibility" => :private,
+              "used_modules" => used_modules.clone,
+              "file_or_module" => container,
+              "entity_is_discovered" => nil,
+              "local_name" => nil
+            }
+          }
+        elsif /^\s*?public\s*?(::)?\s+(.*)\s*?(!.*?)?/i =~ line
+          methods = $2.sub(/!.*$/, '')
+          methods.split(",").each{ |meth|
+            meth.sub!(/!.*$/, '')
+            meth.gsub!(/:/, '')
+            result << {
+              "name" => meth.chomp.strip,
+              "visibility" => :public,
+              "used_modules" => used_modules.clone,
+              "file_or_module" => container,
+              "entity_is_discovered" => nil,
+              "local_name" => nil
+            }
+          }
+        end
+      } if remaining_code
+
+      if container
+        result.each{ |vis_info|
+          vis_info["parent"] = container.name
+        }
+      end
+
+      return visibility_default, result
+    end
+
+    #
+    # Set visibility
+    #
+    # "subname" element of "visibility_info" is deleted.
+    #
+    def set_visibility(container, subname, visibility_default, visibility_info)
+      return unless container || subname || visibility_default || visibility_info
+      not_found = true
+      visibility_info.collect!{ |info|
+        if info["name"] == subname ||
+            @options.ignore_case && info["name"].upcase == subname.upcase
+          if info["file_or_module"].name == container.name
+            container.set_visibility_for([subname], info["visibility"])
+            info["entity_is_discovered"] = true
+            not_found = false
+          end
+        end
+        info
+      }
+      if not_found
+        return container.set_visibility_for([subname], visibility_default)
+      else
+        return container
+      end
+    end
+
+    #
+    # Find visibility
+    #
+    def find_visibility(container, subname, visibility_info)
+      return nil if !subname || !visibility_info
+      visibility_info.each{ |info|
+        if info["name"] == subname ||
+            @options.ignore_case && info["name"].upcase == subname.upcase
+          if info["parent"] == container.name
+            return info["visibility"]
+          end
+        end
+      }
+      return nil
+    end
+
+    #
+    # Check external aliases
+    #
+    def check_external_aliases(subname, params, comment, test=nil)
+      @@external_aliases.each{ |alias_item|
+        if subname == alias_item["old_name"] ||
+                    subname.upcase == alias_item["old_name"].upcase &&
+                            @options.ignore_case
+
+          new_meth = initialize_external_method(alias_item["new_name"], 
+                                                subname, params, @file_name, 
+                                                comment)
+          new_meth.visibility = alias_item["visibility"]
+
+          progress "e"
+          @stats.num_methods += 1
+          alias_item["file_or_module"].add_method(new_meth)
+
+          if !alias_item["file_or_module"].include_requires?(@file_name, @options.ignore_case)
+            alias_item["file_or_module"].add_require(Require.new(@file_name, ""))
+          end
+        end
+      }
+    end
+
+    #
+    # Check public_methods
+    #
+    def check_public_methods(method, parent)
+      return if !method || !parent
+      @@public_methods.each{ |alias_item|
+        parent_is_used_module = nil
+        alias_item["used_modules"].each{ |used_module|
+          if used_module == parent ||
+              used_module.upcase == parent.upcase &&
+              @options.ignore_case
+            parent_is_used_module = true
+          end
+        }
+        next if !parent_is_used_module
+
+        if method.name == alias_item["name"] ||
+            method.name.upcase == alias_item["name"].upcase &&
+            @options.ignore_case
+
+          new_meth = initialize_public_method(method, parent)
+          if alias_item["local_name"]
+            new_meth.name = alias_item["local_name"]
+          end
+
+          progress "e"
+          @stats.num_methods += 1
+          alias_item["file_or_module"].add_method new_meth
+        end
+      }
+    end
+
+    #
+    # Continuous lines are united.
+    #
+    # Comments in continuous lines are removed.
+    #
+    def united_to_one_line(f90src)
+      return "" unless f90src
+      lines = f90src.split("\n")
+      previous_continuing = false
+      now_continuing = false
+      body = ""
+      lines.each{ |line|
+        words = line.split("")
+        next if words.empty? && previous_continuing
+        commentout = false
+        brank_flag = true ; brank_char = ""
+        squote = false    ; dquote = false
+        ignore = false
+        words.collect! { |char|
+          if previous_continuing && brank_flag
+            now_continuing = true
+            ignore         = true
+            case char
+            when "!"                       ; break
+            when " " ; brank_char << char  ; next ""
+            when "&"
+              brank_flag = false
+              now_continuing = false
+              next ""
+            else 
+              brank_flag     = false
+              now_continuing = false
+              ignore         = false
+              next brank_char + char
+            end
+          end
+          ignore = false
+
+          if now_continuing
+            next ""
+          elsif !(squote) && !(dquote) && !(commentout)
+            case char
+            when "!" ; commentout = true     ; next char
+            when "\""; dquote = true         ; next char
+            when "\'"; squote = true         ; next char
+            when "&" ; now_continuing = true ; next ""
+            else next char
+            end
+          elsif commentout
+            next char
+          elsif squote
+            case char
+            when "\'"; squote = false ; next char
+            else next char
+            end
+          elsif dquote
+            case char
+            when "\""; dquote = false ; next char
+            else next char
+            end
+          end
+        }
+        if !ignore && !previous_continuing || !brank_flag
+          if previous_continuing
+            body << words.join("")
+          else
+            body << "\n" + words.join("")
+          end
+        end
+        previous_continuing = now_continuing ? true : nil
+        now_continuing = nil
+      }
+      return body
+    end
+
+
+    #
+    # Continuous line checker
+    #
+    def continuous_line?(line)
+      continuous = false
+      if /&\s*?(!.*)?$/ =~ line
+        continuous = true
+        if comment_out?($~.pre_match)
+          continuous = false
+        end
+      end
+      return continuous
+    end
+
+    #
+    # Comment out checker
+    #
+    def comment_out?(line)
+      return nil unless line
+      commentout = false
+      squote = false ; dquote = false
+      line.split("").each { |char|
+        if !(squote) && !(dquote)
+          case char
+          when "!" ; commentout = true ; break
+          when "\""; dquote = true
+          when "\'"; squote = true
+          else next
+          end
+        elsif squote
+          case char
+          when "\'"; squote = false
+          else next
+          end
+        elsif dquote
+          case char
+          when "\""; dquote = false
+          else next
+          end
+        end
+      }
+      return commentout
+    end
+
+    #
+    # Semicolons are replaced to line feed.
+    #
+    def semicolon_to_linefeed(text)
+      return "" unless text
+      lines = text.split("\n")
+      lines.collect!{ |line|
+        words = line.split("")
+        commentout = false
+        squote = false ; dquote = false
+        words.collect! { |char|
+          if !(squote) && !(dquote) && !(commentout)
+            case char
+            when "!" ; commentout = true ; next char
+            when "\""; dquote = true     ; next char
+            when "\'"; squote = true     ; next char
+            when ";" ;                     "\n"
+            else next char
+            end
+          elsif commentout
+            next char
+          elsif squote
+            case char
+            when "\'"; squote = false ; next char
+            else next char
+            end
+          elsif dquote
+            case char
+            when "\""; dquote = false ; next char
+            else next char
+            end
+          end
+        }
+        words.join("")
+      }
+      return lines.join("\n")
+    end
+
+    #
+    # Which "line" is start of block (module, program, block data,
+    # subroutine, function) statement ?
+    #
+    def block_start?(line)
+      return nil if !line
+
+      if line =~ /^\s*?module\s+(\w+)\s*?(!.*?)?$/i    ||
+          line =~ /^\s*?program\s+(\w+)\s*?(!.*?)?$/i  ||
+          line =~ /^\s*?block\s+data(\s+\w+)?\s*?(!.*?)?$/i     ||
+          line =~ \
+                  /^\s*?
+                   (recursive|pure|elemental)?\s*?
+                   subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
+                  /ix ||
+          line =~ \
+                  /^\s*?
+                   (recursive|pure|elemental)?\s*?
+                   (
+                       character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                     | type\s*?\([\w\s]+?\)\s+
+                     | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                     | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                     | double\s+precision\s+
+                     | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                     | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+                   )?
+                   function\s+(\w+)\s*?
+                   (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
+                  /ix
+        return true
+      end
+
+      return nil
+    end
+
+    #
+    # Which "line" is end of block (module, program, block data,
+    # subroutine, function) statement ?
+    #
+    def block_end?(line)
+      return nil if !line
+
+      if line =~ /^\s*?end\s*?(!.*?)?$/i                 ||
+          line =~ /^\s*?end\s+module(\s+\w+)?\s*?(!.*?)?$/i       ||
+          line =~ /^\s*?end\s+program(\s+\w+)?\s*?(!.*?)?$/i      ||
+          line =~ /^\s*?end\s+block\s+data(\s+\w+)?\s*?(!.*?)?$/i  ||
+          line =~ /^\s*?end\s+subroutine(\s+\w+)?\s*?(!.*?)?$/i   ||
+          line =~ /^\s*?end\s+function(\s+\w+)?\s*?(!.*?)?$/i
+        return true
+      end
+
+      return nil
+    end
+
+    #
+    # Remove "Alias for" in end of comments
+    #
+    def remove_trailing_alias(text)
+      return "" if !text
+      lines = text.split("\n").reverse
+      comment_block = Array.new
+      checked = false
+      lines.each do |line|
+        if !checked 
+          if /^\s?#{INTERNAL_ALIAS_MES}/ =~ line ||
+              /^\s?#{EXTERNAL_ALIAS_MES}/ =~ line
+            checked = true
+            next
+          end
+        end
+        comment_block.unshift line
+      end
+      nice_lines = comment_block.join("\n")
+      nice_lines ||= ""
+      return nice_lines
+    end
+
+    # Empty lines in header are removed
+    def remove_empty_head_lines(text)
+      return "" unless text
+      lines = text.split("\n")
+      header = true
+      lines.delete_if{ |line|
+        header = false if /\S/ =~ line
+        header && /^\s*?$/ =~ line
+      }
+      lines.join("\n")
+    end
+
+
+    # header marker "=", "==", ... are removed
+    def remove_header_marker(text)
+      return text.gsub(/^\s?(=+)/, '<tt></tt>\1')
+    end
+
+    def remove_private_comments(body)
+      body.gsub!(/^\s*!--\s*?$.*?^\s*!\+\+\s*?$/m, '')
+      return body
+    end
+
+
+    #
+    # Information of arguments of subroutines and functions in Fortran95
+    #
+    class Fortran95Definition
+
+      # Name of variable
+      #
+      attr_reader   :varname
+
+      # Types of variable
+      #
+      attr_reader   :types
+
+      # Initial Value
+      #
+      attr_reader   :inivalue
+
+      # Suffix of array
+      #
+      attr_reader   :arraysuffix
+
+      # Comments
+      #
+      attr_accessor   :comment
+
+      # Flag of non documentation
+      #
+      attr_accessor   :nodoc
+
+      def initialize(varname, types, inivalue, arraysuffix, comment,
+                     nodoc=false)
+        @varname = varname
+        @types = types
+        @inivalue = inivalue
+        @arraysuffix = arraysuffix
+        @comment = comment
+        @nodoc = nodoc
+      end
+
+      def to_s
+        return <<-EOF
+<Fortran95Definition: 
+  varname=#{@varname}, types=#{types},
+  inivalue=#{@inivalue}, arraysuffix=#{@arraysuffix}, nodoc=#{@nodoc}, 
+  comment=
+#{@comment}
+>
+EOF
+      end
+
+      #
+      # If attr is included, true is returned
+      #
+      def include_attr?(attr)
+        return if !attr
+        @types.split(",").each{ |type|
+          return true if type.strip.chomp.upcase == attr.strip.chomp.upcase
+        }
+        return nil
+      end
+
+    end # End of Fortran95Definition
+
+    #
+    # Parse string argument "text", and Return Array of
+    # Fortran95Definition object
+    #
+    def definition_info(text)
+      return nil unless text
+      lines = "#{text}"
+      defs = Array.new
+      comment = ""
+      trailing_comment = ""
+      under_comment_valid = false
+      lines.split("\n").each{ |line|
+        if /^\s*?!\s?(.*)/ =~ line
+          if COMMENTS_ARE_UPPER
+            comment << remove_header_marker($1)
+            comment << "\n"
+          elsif defs[-1] && under_comment_valid
+            defs[-1].comment << "\n"
+            defs[-1].comment << remove_header_marker($1)
+          end
+          next
+        elsif /^\s*?$/ =~ line
+          comment = ""
+          under_comment_valid = false
+          next
+        end
+        type = ""
+        characters = ""
+        if line =~ /^\s*?
+                    (
+                        character\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
+                      | type\s*?\([\w\s]+?\)[\s\,]*
+                      | integer\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
+                      | real\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
+                      | double\s+precision[\s\,]*
+                      | logical\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
+                      | complex\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
+                    )
+                    (.*?::)?
+                    (.+)$
+                   /ix
+          characters = $8
+          type = $1
+          type << $7.gsub(/::/, '').gsub(/^\s*?\,/, '') if $7
+        else
+          under_comment_valid = false
+          next
+        end
+        squote = false ; dquote = false ; bracket = 0
+        iniflag = false; commentflag = false
+        varname = "" ; arraysuffix = "" ; inivalue = ""
+        start_pos = defs.size
+        characters.split("").each { |char|
+          if !(squote) && !(dquote) && bracket <= 0 && !(iniflag) && !(commentflag)
+            case char
+            when "!" ; commentflag = true
+            when "(" ; bracket += 1       ; arraysuffix = char
+            when "\""; dquote = true
+            when "\'"; squote = true
+            when "=" ; iniflag = true     ; inivalue << char
+            when ","
+              defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
+              varname = "" ; arraysuffix = "" ; inivalue = ""
+              under_comment_valid = true
+            when " " ; next
+            else     ; varname << char
+            end
+          elsif commentflag
+            comment << remove_header_marker(char)
+            trailing_comment << remove_header_marker(char)
+          elsif iniflag
+            if dquote
+              case char
+              when "\"" ; dquote = false ; inivalue << char
+              else      ; inivalue << char
+              end
+            elsif squote
+              case char
+              when "\'" ; squote = false ; inivalue << char
+              else      ; inivalue << char
+              end
+            elsif bracket > 0
+              case char
+              when "(" ; bracket += 1 ; inivalue << char
+              when ")" ; bracket -= 1 ; inivalue << char
+              else     ; inivalue << char
+              end
+            else
+              case char
+              when ","
+                defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
+                varname = "" ; arraysuffix = "" ; inivalue = ""
+                iniflag = false
+                under_comment_valid = true
+              when "(" ; bracket += 1 ; inivalue << char
+              when "\""; dquote = true  ; inivalue << char
+              when "\'"; squote = true  ; inivalue << char
+              when "!" ; commentflag = true
+              else     ; inivalue << char
+              end
+            end
+          elsif !(squote) && !(dquote) && bracket > 0
+            case char
+            when "(" ; bracket += 1 ; arraysuffix << char
+            when ")" ; bracket -= 1 ; arraysuffix << char
+            else     ; arraysuffix << char
+            end
+          elsif squote
+            case char
+            when "\'"; squote = false ; inivalue << char
+            else     ; inivalue << char
+            end
+          elsif dquote
+            case char
+            when "\""; dquote = false ; inivalue << char
+            else     ; inivalue << char
+            end
+          end
+        }
+        defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
+        if trailing_comment =~ /^:nodoc:/
+          defs[start_pos..-1].collect!{ |defitem|
+            defitem.nodoc = true
+          }
+        end
+        varname = "" ; arraysuffix = "" ; inivalue = ""
+        comment = ""
+        under_comment_valid = true
+        trailing_comment = ""
+      }
+      return defs
+    end
+
+
+  end # class Fortran95parser
+
+end # module RDoc
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parse_rb.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parse_rb.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parse_rb.rb	(revision 18425)
@@ -0,0 +1,2605 @@
+#!/usr/local/bin/ruby
+
+# Parse a Ruby source file, building a set of objects
+# representing the modules, classes, methods,
+# requires, and includes we find (these classes
+# are defined in code_objects.rb).
+
+# This file contains stuff stolen outright from:
+#
+#   rtags.rb - 
+#   ruby-lex.rb - ruby lexcal analizer
+#   ruby-token.rb - ruby tokens 
+#   	by Keiju ISHITSUKA (Nippon Rational Inc.)
+#
+
+require "e2mmap"
+require "irb/slex"
+
+require "rdoc/code_objects"
+require "rdoc/tokenstream"
+
+require "rdoc/markup/simple_markup/preprocess"
+
+require "rdoc/parsers/parserfactory"
+
+$TOKEN_DEBUG = $DEBUG
+
+# Definitions of all tokens involved in the lexical analysis
+
+module RubyToken
+  EXPR_BEG   = :EXPR_BEG
+  EXPR_MID   = :EXPR_MID
+  EXPR_END   = :EXPR_END
+  EXPR_ARG   = :EXPR_ARG
+  EXPR_FNAME = :EXPR_FNAME
+  EXPR_DOT   = :EXPR_DOT
+  EXPR_CLASS = :EXPR_CLASS
+  
+  class Token
+    NO_TEXT = "??".freeze
+    attr :text
+
+    def initialize(line_no, char_no)
+      @line_no = line_no
+      @char_no = char_no
+      @text    = NO_TEXT
+    end
+
+    # Because we're used in contexts that expect to return a token,
+    # we set the text string and then return ourselves
+    def set_text(text)
+      @text = text
+      self
+    end
+
+    attr_reader :line_no, :char_no, :text
+  end
+
+  class TkNode < Token
+    attr :node
+  end
+
+  class TkId < Token
+    def initialize(line_no, char_no, name)
+      super(line_no, char_no)
+      @name = name
+    end
+    attr :name
+  end
+
+  class TkKW < TkId
+  end
+
+  class TkVal < Token
+    def initialize(line_no, char_no, value = nil)
+      super(line_no, char_no)
+      set_text(value)
+    end
+  end
+
+  class TkOp < Token
+    def name
+      self.class.op_name
+    end
+  end
+
+  class TkOPASGN < TkOp
+    def initialize(line_no, char_no, op)
+      super(line_no, char_no)
+      op = TkReading2Token[op] unless op.kind_of?(Symbol)
+      @op = op
+    end
+    attr :op
+  end
+
+  class TkUnknownChar < Token
+    def initialize(line_no, char_no, id)
+      super(line_no, char_no)
+      @name = char_no.chr
+    end
+    attr :name
+  end
+
+  class TkError < Token
+  end
+
+  def set_token_position(line, char)
+    @prev_line_no = line
+    @prev_char_no = char
+  end
+
+  def Token(token, value = nil)
+    tk = nil
+    case token
+    when String, Symbol
+      source = token.kind_of?(String) ? TkReading2Token : TkSymbol2Token
+      if (tk = source[token]).nil?
+	IRB.fail TkReading2TokenNoKey, token
+      end
+      tk = Token(tk[0], value) 
+    else 
+      tk = if (token.ancestors & [TkId, TkVal, TkOPASGN, TkUnknownChar]).empty?
+             token.new(@prev_line_no, @prev_char_no)
+           else
+             token.new(@prev_line_no, @prev_char_no, value)
+           end
+    end
+    tk
+  end
+
+  TokenDefinitions = [
+    [:TkCLASS,      TkKW,  "class",  EXPR_CLASS],
+    [:TkMODULE,     TkKW,  "module", EXPR_BEG],
+    [:TkDEF,	    TkKW,  "def",    EXPR_FNAME],
+    [:TkUNDEF,      TkKW,  "undef",  EXPR_FNAME],
+    [:TkBEGIN,      TkKW,  "begin",  EXPR_BEG],
+    [:TkRESCUE,     TkKW,  "rescue", EXPR_MID],
+    [:TkENSURE,     TkKW,  "ensure", EXPR_BEG],
+    [:TkEND,	    TkKW,  "end",    EXPR_END],
+    [:TkIF,         TkKW,  "if",     EXPR_BEG, :TkIF_MOD],
+    [:TkUNLESS,     TkKW,  "unless", EXPR_BEG, :TkUNLESS_MOD],
+    [:TkTHEN,	    TkKW,  "then",   EXPR_BEG],
+    [:TkELSIF,      TkKW,  "elsif",  EXPR_BEG],
+    [:TkELSE,	    TkKW,  "else",   EXPR_BEG],
+    [:TkCASE,	    TkKW,  "case",   EXPR_BEG],
+    [:TkWHEN,	    TkKW,  "when",   EXPR_BEG],
+    [:TkWHILE,      TkKW,  "while",  EXPR_BEG, :TkWHILE_MOD],
+    [:TkUNTIL,      TkKW,  "until",  EXPR_BEG, :TkUNTIL_MOD],
+    [:TkFOR,	    TkKW,  "for",    EXPR_BEG],
+    [:TkBREAK,      TkKW,  "break",  EXPR_END],
+    [:TkNEXT,	    TkKW,  "next",   EXPR_END],
+    [:TkREDO,	    TkKW,  "redo",   EXPR_END],
+    [:TkRETRY,      TkKW,  "retry",  EXPR_END],
+    [:TkIN,	    TkKW,  "in",     EXPR_BEG],
+    [:TkDO,	    TkKW,  "do",     EXPR_BEG],
+    [:TkRETURN,     TkKW,  "return", EXPR_MID],
+    [:TkYIELD,      TkKW,  "yield",  EXPR_END],
+    [:TkSUPER,      TkKW,  "super",  EXPR_END],
+    [:TkSELF,	    TkKW,  "self",   EXPR_END],
+    [:TkNIL, 	    TkKW,  "nil",    EXPR_END],
+    [:TkTRUE,	    TkKW,  "true",   EXPR_END],
+    [:TkFALSE,      TkKW,  "false",  EXPR_END],
+    [:TkAND,	    TkKW,  "and",    EXPR_BEG],
+    [:TkOR, 	    TkKW,  "or",     EXPR_BEG],
+    [:TkNOT,	    TkKW,  "not",    EXPR_BEG],
+    [:TkIF_MOD,     TkKW],
+    [:TkUNLESS_MOD, TkKW],
+    [:TkWHILE_MOD,  TkKW],
+    [:TkUNTIL_MOD,  TkKW],
+    [:TkALIAS,      TkKW,  "alias",    EXPR_FNAME],
+    [:TkDEFINED,    TkKW,  "defined?", EXPR_END],
+    [:TklBEGIN,     TkKW,  "BEGIN",    EXPR_END],
+    [:TklEND,	    TkKW,  "END",      EXPR_END],
+    [:Tk__LINE__,   TkKW,  "__LINE__", EXPR_END],
+    [:Tk__FILE__,   TkKW,  "__FILE__", EXPR_END],
+
+    [:TkIDENTIFIER, TkId],
+    [:TkFID,	    TkId],
+    [:TkGVAR,	    TkId],
+    [:TkIVAR,	    TkId],
+    [:TkCONSTANT,   TkId],
+
+    [:TkINTEGER,    TkVal],
+    [:TkFLOAT,      TkVal],
+    [:TkSTRING,     TkVal],
+    [:TkXSTRING,    TkVal],
+    [:TkREGEXP,     TkVal],
+    [:TkCOMMENT,    TkVal],
+
+    [:TkDSTRING,    TkNode],
+    [:TkDXSTRING,   TkNode],
+    [:TkDREGEXP,    TkNode],
+    [:TkNTH_REF,    TkId],
+    [:TkBACK_REF,   TkId],
+
+    [:TkUPLUS,      TkOp,   "+@"],
+    [:TkUMINUS,     TkOp,   "-@"],
+    [:TkPOW,	    TkOp,   "**"],
+    [:TkCMP,	    TkOp,   "<=>"],
+    [:TkEQ,	    TkOp,   "=="],
+    [:TkEQQ,	    TkOp,   "==="],
+    [:TkNEQ,	    TkOp,   "!="],
+    [:TkGEQ,	    TkOp,   ">="],
+    [:TkLEQ,	    TkOp,   "<="],
+    [:TkANDOP,      TkOp,   "&&"],
+    [:TkOROP,	    TkOp,   "||"],
+    [:TkMATCH,      TkOp,   "=~"],
+    [:TkNMATCH,     TkOp,   "!~"],
+    [:TkDOT2,	    TkOp,   ".."],
+    [:TkDOT3,	    TkOp,   "..."],
+    [:TkAREF,	    TkOp,   "[]"],
+    [:TkASET,	    TkOp,   "[]="],
+    [:TkLSHFT,      TkOp,   "<<"],
+    [:TkRSHFT,      TkOp,   ">>"],
+    [:TkCOLON2,     TkOp],
+    [:TkCOLON3,     TkOp],
+#   [:OPASGN,	    TkOp],               # +=, -=  etc. #
+    [:TkASSOC,      TkOp,   "=>"],
+    [:TkQUESTION,   TkOp,   "?"],	 #?
+    [:TkCOLON,      TkOp,   ":"],        #:
+    
+    [:TkfLPAREN],         # func( #
+    [:TkfLBRACK],         # func[ #
+    [:TkfLBRACE],         # func{ #
+    [:TkSTAR],            # *arg
+    [:TkAMPER],           # &arg #
+    [:TkSYMBOL,     TkId],          # :SYMBOL
+    [:TkSYMBEG,     TkId], 
+    [:TkGT,	    TkOp,   ">"],
+    [:TkLT,	    TkOp,   "<"],
+    [:TkPLUS,	    TkOp,   "+"],
+    [:TkMINUS,      TkOp,   "-"],
+    [:TkMULT,	    TkOp,   "*"],
+    [:TkDIV,	    TkOp,   "/"],
+    [:TkMOD,	    TkOp,   "%"],
+    [:TkBITOR,      TkOp,   "|"],
+    [:TkBITXOR,     TkOp,   "^"],
+    [:TkBITAND,     TkOp,   "&"],
+    [:TkBITNOT,     TkOp,   "~"],
+    [:TkNOTOP,      TkOp,   "!"],
+
+    [:TkBACKQUOTE,  TkOp,   "`"],
+
+    [:TkASSIGN,     Token,  "="],
+    [:TkDOT,	    Token,  "."],
+    [:TkLPAREN,     Token,  "("],  #(exp)
+    [:TkLBRACK,     Token,  "["],  #[arry]
+    [:TkLBRACE,     Token,  "{"],  #{hash}
+    [:TkRPAREN,     Token,  ")"],
+    [:TkRBRACK,     Token,  "]"],
+    [:TkRBRACE,     Token,  "}"],
+    [:TkCOMMA,      Token,  ","],
+    [:TkSEMICOLON,  Token,  ";"],
+
+    [:TkRD_COMMENT],
+    [:TkSPACE],
+    [:TkNL],
+    [:TkEND_OF_SCRIPT],
+
+    [:TkBACKSLASH,  TkUnknownChar,  "\\"],
+    [:TkAT,	    TkUnknownChar,  "@"],
+    [:TkDOLLAR,     TkUnknownChar,  "\$"], #"
+  ]
+
+  # {reading => token_class}
+  # {reading => [token_class, *opt]}
+  TkReading2Token = {}
+  TkSymbol2Token = {}
+
+  def RubyToken.def_token(token_n, super_token = Token, reading = nil, *opts)
+    token_n = token_n.id2name unless token_n.kind_of?(String)
+    if RubyToken.const_defined?(token_n)
+      IRB.fail AlreadyDefinedToken, token_n
+    end
+
+    token_c =  Class.new super_token
+    RubyToken.const_set token_n, token_c
+#    token_c.inspect
+ 
+    if reading
+      if TkReading2Token[reading]
+	IRB.fail TkReading2TokenDuplicateError, token_n, reading
+      end
+      if opts.empty?
+	TkReading2Token[reading] = [token_c]
+      else
+	TkReading2Token[reading] = [token_c].concat(opts)
+      end
+    end
+    TkSymbol2Token[token_n.intern] = token_c
+
+    if token_c <= TkOp
+      token_c.class_eval %{
+        def self.op_name; "#{reading}"; end
+      }
+    end
+  end
+
+  for defs in TokenDefinitions
+    def_token(*defs)
+  end
+
+  NEWLINE_TOKEN = TkNL.new(0,0)
+  NEWLINE_TOKEN.set_text("\n")
+
+end
+
+
+
+# Lexical analyzer for Ruby source
+
+class RubyLex
+
+  ######################################################################
+  #
+  # Read an input stream character by character. We allow for unlimited
+  # ungetting of characters just read.
+  #
+  # We simplify the implementation greatly by reading the entire input
+  # into a buffer initially, and then simply traversing it using
+  # pointers.
+  #
+  # We also have to allow for the <i>here document diversion</i>. This
+  # little gem comes about when the lexer encounters a here
+  # document. At this point we effectively need to split the input
+  # stream into two parts: one to read the body of the here document,
+  # the other to read the rest of the input line where the here
+  # document was initially encountered. For example, we might have
+  #
+  #   do_something(<<-A, <<-B)
+  #     stuff
+  #     for
+  #   A
+  #     stuff
+  #     for
+  #   B
+  #
+  # When the lexer encounters the <<A, it reads until the end of the
+  # line, and keeps it around for later. It then reads the body of the
+  # here document.  Once complete, it needs to read the rest of the
+  # original line, but then skip the here document body.
+  #
+  
+  class BufferedReader
+    
+    attr_reader :line_num
+    
+    def initialize(content)
+      if /\t/ =~ content
+        tab_width = Options.instance.tab_width
+        content = content.split(/\n/).map do |line|
+          1 while line.gsub!(/\t+/) { ' ' * (tab_width*$&.length - $`.length % tab_width)}  && $~ #`
+          line
+        end .join("\n")
+      end
+      @content   = content
+      @content << "\n" unless @content[-1,1] == "\n"
+      @size      = @content.size
+      @offset    = 0
+      @hwm       = 0
+      @line_num  = 1
+      @read_back_offset = 0
+      @last_newline = 0
+      @newline_pending = false
+    end
+    
+    def column
+      @offset - @last_newline
+    end
+    
+    def getc
+      return nil if @offset >= @size
+      ch = @content[@offset, 1]
+      
+      @offset += 1
+      @hwm = @offset if @hwm < @offset
+      
+      if @newline_pending
+        @line_num += 1
+        @last_newline = @offset - 1
+        @newline_pending = false
+      end
+      
+      if ch == "\n"
+        @newline_pending = true
+      end
+      ch
+    end
+    
+    def getc_already_read
+      getc
+    end
+    
+    def ungetc(ch)
+      raise "unget past beginning of file" if @offset <= 0
+      @offset -= 1
+      if @content[@offset] == ?\n
+        @newline_pending = false
+      end
+    end
+    
+    def get_read
+      res = @content[@read_back_offset...@offset]
+      @read_back_offset = @offset
+      res
+    end
+    
+    def peek(at)
+      pos = @offset + at
+      if pos >= @size
+        nil
+      else
+        @content[pos, 1]
+      end
+    end
+    
+    def peek_equal(str)
+      @content[@offset, str.length] == str
+    end
+    
+    def divert_read_from(reserve)
+      @content[@offset, 0] = reserve
+      @size      = @content.size
+    end
+  end
+
+  # end of nested class BufferedReader
+
+  extend Exception2MessageMapper
+  def_exception(:AlreadyDefinedToken, "Already defined token(%s)")
+  def_exception(:TkReading2TokenNoKey, "key nothing(key='%s')")
+  def_exception(:TkSymbol2TokenNoKey, "key nothing(key='%s')")
+  def_exception(:TkReading2TokenDuplicateError, 
+		"key duplicate(token_n='%s', key='%s')")
+  def_exception(:SyntaxError, "%s")
+  
+  include RubyToken
+  include IRB
+
+  attr_reader :continue
+  attr_reader :lex_state
+
+  def RubyLex.debug?
+    false
+  end
+
+  def initialize(content)
+    lex_init
+
+    @reader = BufferedReader.new(content)
+
+    @exp_line_no = @line_no = 1
+    @base_char_no = 0
+    @indent = 0
+
+    @ltype = nil
+    @quoted = nil
+    @lex_state = EXPR_BEG
+    @space_seen = false
+    
+    @continue = false
+    @line = ""
+
+    @skip_space = false
+    @read_auto_clean_up = false
+    @exception_on_syntax_error = true
+  end
+
+  attr :skip_space, true
+  attr :read_auto_clean_up, true
+  attr :exception_on_syntax_error, true
+
+  attr :indent
+
+  # io functions
+  def line_no
+    @reader.line_num
+  end
+
+  def char_no
+    @reader.column
+  end
+
+  def get_read
+    @reader.get_read
+  end
+
+  def getc
+    @reader.getc
+  end
+
+  def getc_of_rests
+    @reader.getc_already_read
+  end
+
+  def gets
+    c = getc or return
+    l = ""
+    begin
+      l.concat c unless c == "\r"
+      break if c == "\n"
+    end while c = getc
+    l
+  end
+
+
+  def ungetc(c = nil)
+    @reader.ungetc(c)
+  end
+
+  def peek_equal?(str)
+    @reader.peek_equal(str)
+  end
+
+  def peek(i = 0)
+    @reader.peek(i)
+  end
+
+  def lex
+    until (((tk = token).kind_of?(TkNL) || tk.kind_of?(TkEND_OF_SCRIPT)) &&
+	     !@continue or
+	     tk.nil?)
+    end
+    line = get_read
+
+    if line == "" and tk.kind_of?(TkEND_OF_SCRIPT) || tk.nil?
+      nil
+    else
+      line
+    end
+  end
+
+  def token
+    set_token_position(line_no, char_no)
+    begin
+      begin
+	tk = @OP.match(self)
+	@space_seen = tk.kind_of?(TkSPACE)
+      rescue SyntaxError
+	abort if @exception_on_syntax_error
+	tk = TkError.new(line_no, char_no)
+      end
+    end while @skip_space and tk.kind_of?(TkSPACE)
+    if @read_auto_clean_up
+      get_read
+    end
+#   throw :eof unless tk
+    p tk if $DEBUG
+    tk
+  end
+  
+  ENINDENT_CLAUSE = [
+    "case", "class", "def", "do", "for", "if",
+    "module", "unless", "until", "while", "begin" #, "when"
+  ]
+  DEINDENT_CLAUSE = ["end" #, "when"
+  ]
+
+  PERCENT_LTYPE = {
+    "q" => "\'",
+    "Q" => "\"",
+    "x" => "\`",
+    "r" => "/",
+    "w" => "]"
+  }
+  
+  PERCENT_PAREN = {
+    "{" => "}",
+    "[" => "]",
+    "<" => ">",
+    "(" => ")"
+  }
+
+  Ltype2Token = {
+    "\'" => TkSTRING,
+    "\"" => TkSTRING,
+    "\`" => TkXSTRING,
+    "/" => TkREGEXP,
+    "]" => TkDSTRING
+  }
+  Ltype2Token.default = TkSTRING
+
+  DLtype2Token = {
+    "\"" => TkDSTRING,
+    "\`" => TkDXSTRING,
+    "/" => TkDREGEXP,
+  }
+
+  def lex_init()
+    @OP = SLex.new
+    @OP.def_rules("\0", "\004", "\032") do |chars, io|
+      Token(TkEND_OF_SCRIPT).set_text(chars)
+    end
+
+    @OP.def_rules(" ", "\t", "\f", "\r", "\13") do |chars, io|
+      @space_seen = TRUE
+      while (ch = getc) =~ /[ \t\f\r\13]/
+        chars << ch
+      end
+      ungetc
+      Token(TkSPACE).set_text(chars)
+    end
+
+    @OP.def_rule("#") do
+      |op, io|
+      identify_comment
+    end
+
+    @OP.def_rule("=begin", proc{@prev_char_no == 0 && peek(0) =~ /\s/}) do
+      |op, io|
+      str = op
+      @ltype = "="
+
+
+      begin
+        line = ""
+        begin
+          ch = getc
+          line << ch
+        end until ch == "\n"
+        str << line
+      end until line =~ /^=end/
+
+      ungetc
+
+      @ltype = nil
+
+      if str =~ /\A=begin\s+rdoc/i
+        str.sub!(/\A=begin.*\n/, '')
+        str.sub!(/^=end.*/m, '')
+        Token(TkCOMMENT).set_text(str)
+      else
+        Token(TkRD_COMMENT)#.set_text(str)
+      end
+    end
+
+    @OP.def_rule("\n") do
+      print "\\n\n" if RubyLex.debug?
+      case @lex_state
+      when EXPR_BEG, EXPR_FNAME, EXPR_DOT
+	@continue = TRUE
+      else
+	@continue = FALSE
+	@lex_state = EXPR_BEG
+      end
+      Token(TkNL).set_text("\n")
+    end
+
+    @OP.def_rules("*", "**",	
+		  "!", "!=", "!~",
+		  "=", "==", "===", 
+		  "=~", "<=>",	
+		  "<", "<=",
+		  ">", ">=", ">>") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      Token(op).set_text(op)
+    end
+
+    @OP.def_rules("<<") do
+      |op, io|
+      tk = nil
+      if @lex_state != EXPR_END && @lex_state != EXPR_CLASS &&
+	  (@lex_state != EXPR_ARG || @space_seen)
+	c = peek(0)
+	if /[-\w_\"\'\`]/ =~ c
+	  tk = identify_here_document
+	end
+      end
+      if !tk
+        @lex_state = EXPR_BEG
+        tk = Token(op).set_text(op)
+      end
+      tk
+    end
+
+    @OP.def_rules("'", '"') do
+      |op, io|
+      identify_string(op)
+    end
+
+    @OP.def_rules("`") do
+      |op, io|
+      if @lex_state == EXPR_FNAME
+	Token(op).set_text(op)
+      else
+	identify_string(op)
+      end
+    end
+
+    @OP.def_rules('?') do
+      |op, io|
+      if @lex_state == EXPR_END
+	@lex_state = EXPR_BEG
+	Token(TkQUESTION).set_text(op)
+      else
+	ch = getc
+	if @lex_state == EXPR_ARG && ch !~ /\s/
+	  ungetc
+	  @lex_state = EXPR_BEG;
+	  Token(TkQUESTION).set_text(op)
+	else
+          str = op
+          str << ch
+	  if (ch == '\\') #'
+	    str << read_escape
+	  end
+	  @lex_state = EXPR_END
+	  Token(TkINTEGER).set_text(str)
+	end
+      end
+    end
+
+    @OP.def_rules("&", "&&", "|", "||") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      Token(op).set_text(op)
+    end
+    
+    @OP.def_rules("+=", "-=", "*=", "**=", 
+		  "&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      op =~ /^(.*)=$/
+      Token(TkOPASGN, $1).set_text(op)
+    end
+
+    @OP.def_rule("+@", proc{@lex_state == EXPR_FNAME}) do |op, io|
+      Token(TkUPLUS).set_text(op)
+    end
+
+    @OP.def_rule("-@", proc{@lex_state == EXPR_FNAME}) do |op, io|
+      Token(TkUMINUS).set_text(op)
+    end
+
+    @OP.def_rules("+", "-") do
+      |op, io|
+      catch(:RET) do
+	if @lex_state == EXPR_ARG
+	  if @space_seen and peek(0) =~ /[0-9]/
+	    throw :RET, identify_number(op)
+	  else
+	    @lex_state = EXPR_BEG
+	  end
+	elsif @lex_state != EXPR_END and peek(0) =~ /[0-9]/
+	  throw :RET, identify_number(op)
+	else
+	  @lex_state = EXPR_BEG
+	end
+	Token(op).set_text(op)
+      end
+    end
+
+    @OP.def_rule(".") do
+      @lex_state = EXPR_BEG
+      if peek(0) =~ /[0-9]/
+	ungetc
+	identify_number("")
+      else
+	# for obj.if
+	@lex_state = EXPR_DOT
+	Token(TkDOT).set_text(".")
+      end
+    end
+
+    @OP.def_rules("..", "...") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      Token(op).set_text(op)
+    end
+
+    lex_int2
+  end
+  
+  def lex_int2
+    @OP.def_rules("]", "}", ")") do
+      |op, io|
+      @lex_state = EXPR_END
+      @indent -= 1
+      Token(op).set_text(op)
+    end
+
+    @OP.def_rule(":") do
+      if @lex_state == EXPR_END || peek(0) =~ /\s/
+	@lex_state = EXPR_BEG
+	tk = Token(TkCOLON)
+      else
+	@lex_state = EXPR_FNAME;
+	tk = Token(TkSYMBEG)
+      end
+      tk.set_text(":")
+    end
+
+    @OP.def_rule("::") do
+#      p @lex_state.id2name, @space_seen
+      if @lex_state == EXPR_BEG or @lex_state == EXPR_ARG && @space_seen
+	@lex_state = EXPR_BEG
+	tk = Token(TkCOLON3)
+      else
+	@lex_state = EXPR_DOT
+	tk = Token(TkCOLON2)
+      end
+      tk.set_text("::")
+    end
+
+    @OP.def_rule("/") do
+      |op, io|
+      if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+	identify_string(op)
+      elsif peek(0) == '='
+	getc
+	@lex_state = EXPR_BEG
+	Token(TkOPASGN, :/).set_text("/=") #")
+      elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
+	identify_string(op)
+      else 
+	@lex_state = EXPR_BEG
+        Token("/").set_text(op)
+      end
+    end
+
+    @OP.def_rules("^") do
+      @lex_state = EXPR_BEG
+      Token("^").set_text("^")
+    end
+
+    #       @OP.def_rules("^=") do
+    # 	@lex_state = EXPR_BEG
+    # 	Token(TkOPASGN, :^)
+    #       end
+    
+    @OP.def_rules(",", ";") do
+      |op, io|
+      @lex_state = EXPR_BEG
+      Token(op).set_text(op)
+    end
+
+    @OP.def_rule("~") do
+      @lex_state = EXPR_BEG
+      Token("~").set_text("~")
+    end
+
+    @OP.def_rule("~@", proc{@lex_state = EXPR_FNAME}) do
+      @lex_state = EXPR_BEG
+      Token("~").set_text("~@")
+    end
+    
+    @OP.def_rule("(") do
+      @indent += 1
+      if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+	@lex_state = EXPR_BEG
+	tk = Token(TkfLPAREN)
+      else
+	@lex_state = EXPR_BEG
+	tk = Token(TkLPAREN)
+      end
+      tk.set_text("(")
+    end
+
+    @OP.def_rule("[]", proc{@lex_state == EXPR_FNAME}) do
+      Token("[]").set_text("[]")
+    end
+
+    @OP.def_rule("[]=", proc{@lex_state == EXPR_FNAME}) do
+      Token("[]=").set_text("[]=")
+    end
+
+    @OP.def_rule("[") do
+      @indent += 1
+      if @lex_state == EXPR_FNAME
+	t = Token(TkfLBRACK)
+      else
+	if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+	  t = Token(TkLBRACK)
+	elsif @lex_state == EXPR_ARG && @space_seen
+	  t = Token(TkLBRACK)
+	else
+	  t = Token(TkfLBRACK)
+	end
+	@lex_state = EXPR_BEG
+      end
+      t.set_text("[")
+    end
+
+    @OP.def_rule("{") do
+      @indent += 1
+      if @lex_state != EXPR_END && @lex_state != EXPR_ARG
+	t = Token(TkLBRACE)
+      else
+	t = Token(TkfLBRACE)
+      end
+      @lex_state = EXPR_BEG
+      t.set_text("{")
+    end
+
+    @OP.def_rule('\\') do   #'
+      if getc == "\n" 
+	@space_seen = true
+	@continue = true
+	Token(TkSPACE).set_text("\\\n")
+      else 
+	ungetc
+	Token("\\").set_text("\\")  #"
+      end 
+    end 
+
+    @OP.def_rule('%') do
+      |op, io|
+      if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+	identify_quotation('%')
+      elsif peek(0) == '='
+	getc
+	Token(TkOPASGN, "%").set_text("%=")
+      elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
+	identify_quotation('%')
+      else
+	@lex_state = EXPR_BEG
+	Token("%").set_text("%")
+      end
+    end
+
+    @OP.def_rule('$') do  #'
+      identify_gvar
+    end
+
+    @OP.def_rule('@') do
+      if peek(0) =~ /[@\w_]/
+	ungetc
+	identify_identifier
+      else
+	Token("@").set_text("@")
+      end
+    end
+
+    #       @OP.def_rule("def", proc{|op, io| /\s/ =~ io.peek(0)}) do 
+    # 	|op, io|
+    # 	@indent += 1
+    # 	@lex_state = EXPR_FNAME
+    # #	@lex_state = EXPR_END
+    # #	until @rests[0] == "\n" or @rests[0] == ";"
+    # #	  rests.shift
+    # #	end
+    #       end
+
+    @OP.def_rule("__END__", proc{@prev_char_no == 0 && peek(0) =~ /[\r\n]/}) do
+      throw :eof
+    end
+
+    @OP.def_rule("") do
+      |op, io|
+      printf "MATCH: start %s: %s\n", op, io.inspect if RubyLex.debug?
+      if peek(0) =~ /[0-9]/
+	t = identify_number("")
+      elsif peek(0) =~ /[\w_]/
+	t = identify_identifier
+      end
+      printf "MATCH: end %s: %s\n", op, io.inspect if RubyLex.debug?
+      t
+    end
+    
+    p @OP if RubyLex.debug?
+  end
+  
+  def identify_gvar
+    @lex_state = EXPR_END
+    str = "$"
+
+    tk = case ch = getc
+         when /[~_*$?!@\/\\;,=:<>".]/   #"
+           str << ch
+           Token(TkGVAR, str)
+           
+         when "-"
+           str << "-" << getc
+           Token(TkGVAR, str)
+           
+         when "&", "`", "'", "+"
+           str << ch
+           Token(TkBACK_REF, str)
+           
+         when /[1-9]/
+           str << ch
+           while (ch = getc) =~ /[0-9]/
+             str << ch
+           end
+           ungetc
+           Token(TkNTH_REF)
+         when /\w/
+           ungetc
+           ungetc
+           return identify_identifier
+         else 
+           ungetc
+           Token("$")     
+         end
+    tk.set_text(str)
+  end
+  
+  def identify_identifier
+    token = ""
+    token.concat getc if peek(0) =~ /[$@]/
+    token.concat getc if peek(0) == "@"
+
+    while (ch = getc) =~ /\w|_/
+      print ":", ch, ":" if RubyLex.debug?
+      token.concat ch
+    end
+    ungetc
+    
+    if ch == "!" or ch == "?"
+      token.concat getc
+    end
+    # fix token
+
+    # $stderr.puts "identifier - #{token}, state = #@lex_state"
+
+    case token
+    when /^\$/
+      return Token(TkGVAR, token).set_text(token)
+    when /^\@/
+      @lex_state = EXPR_END
+      return Token(TkIVAR, token).set_text(token)
+    end
+    
+    if @lex_state != EXPR_DOT
+      print token, "\n" if RubyLex.debug?
+
+      token_c, *trans = TkReading2Token[token]
+      if token_c
+	# reserved word?
+
+	if (@lex_state != EXPR_BEG &&
+	    @lex_state != EXPR_FNAME &&
+	    trans[1])
+	  # modifiers
+	  token_c = TkSymbol2Token[trans[1]]
+	  @lex_state = trans[0]
+	else
+	  if @lex_state != EXPR_FNAME
+	    if ENINDENT_CLAUSE.include?(token)
+	      @indent += 1
+	    elsif DEINDENT_CLAUSE.include?(token)
+	      @indent -= 1
+	    end
+	    @lex_state = trans[0]
+	  else
+	    @lex_state = EXPR_END
+	  end
+	end
+	return Token(token_c, token).set_text(token)
+      end
+    end
+
+    if @lex_state == EXPR_FNAME
+      @lex_state = EXPR_END
+      if peek(0) == '='
+	token.concat getc
+      end
+    elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT
+      @lex_state = EXPR_ARG
+    else
+      @lex_state = EXPR_END
+    end
+
+    if token[0, 1] =~ /[A-Z]/
+      return Token(TkCONSTANT, token).set_text(token)
+    elsif token[token.size - 1, 1] =~ /[!?]/
+      return Token(TkFID, token).set_text(token)
+    else
+      return Token(TkIDENTIFIER, token).set_text(token)
+    end
+  end
+
+  def identify_here_document
+    ch = getc
+    if ch == "-"
+      ch = getc
+      indent = true
+    end
+    if /['"`]/ =~ ch            # '
+      lt = ch
+      quoted = ""
+      while (c = getc) && c != lt
+	quoted.concat c
+      end
+    else
+      lt = '"'
+      quoted = ch.dup
+      while (c = getc) && c =~ /\w/
+	quoted.concat c
+      end
+      ungetc
+    end
+
+    ltback, @ltype = @ltype, lt
+    reserve = ""
+
+    while ch = getc
+      reserve << ch
+      if ch == "\\"    #"
+        ch = getc
+	reserve << ch
+      elsif ch == "\n"
+	break
+      end
+    end
+
+    str = ""
+    while (l = gets)
+      l.chomp!
+      l.strip! if indent
+      break if l == quoted
+      str << l.chomp << "\n"
+    end
+
+    @reader.divert_read_from(reserve)
+
+    @ltype = ltback
+    @lex_state = EXPR_END
+    Token(Ltype2Token[lt], str).set_text(str.dump)
+  end
+  
+  def identify_quotation(initial_char)
+    ch = getc
+    if lt = PERCENT_LTYPE[ch]
+      initial_char += ch
+      ch = getc
+    elsif ch =~ /\W/
+      lt = "\""
+    else
+      RubyLex.fail SyntaxError, "unknown type of %string ('#{ch}')"
+    end
+#     if ch !~ /\W/
+#       ungetc
+#       next
+#     end
+    #@ltype = lt
+    @quoted = ch unless @quoted = PERCENT_PAREN[ch]
+    identify_string(lt, @quoted, ch, initial_char)
+  end
+
+  def identify_number(start)
+    str = start.dup
+
+    if start == "+" or start == "-" or start == ""
+      start = getc
+      str << start
+    end
+
+    @lex_state = EXPR_END
+
+    if start == "0"
+      if peek(0) == "x"
+        ch = getc
+        str << ch
+        match = /[0-9a-f_]/
+      else
+        match = /[0-7_]/
+      end
+      while ch = getc
+        if ch !~ match
+          ungetc
+          break
+        else
+          str << ch
+        end
+      end
+      return Token(TkINTEGER).set_text(str)
+    end
+
+    type = TkINTEGER
+    allow_point = TRUE
+    allow_e = TRUE
+    while ch = getc
+      case ch
+      when /[0-9_]/
+        str << ch
+
+      when allow_point && "."
+	type = TkFLOAT
+	if peek(0) !~ /[0-9]/
+	  ungetc
+	  break
+	end
+        str << ch
+	allow_point = false
+
+      when allow_e && "e", allow_e && "E"
+        str << ch
+	type = TkFLOAT
+	if peek(0) =~ /[+-]/
+	  str << getc
+	end
+	allow_e = false
+	allow_point = false
+      else
+	ungetc
+	break
+      end
+    end
+    Token(type).set_text(str)
+  end
+  
+  def identify_string(ltype, quoted = ltype, opener=nil, initial_char = nil)
+    @ltype = ltype
+    @quoted = quoted
+    subtype = nil
+
+    str = ""
+    str << initial_char if initial_char
+    str << (opener||quoted)
+
+    nest = 0
+    begin
+      while ch = getc 
+	str << ch
+	if @quoted == ch 
+          if nest == 0
+            break
+          else
+            nest -= 1
+          end
+        elsif opener == ch
+          nest += 1
+	elsif @ltype != "'" && @ltype != "]" and ch == "#"
+          ch = getc
+          if ch == "{"
+            subtype = true
+            str << ch << skip_inner_expression
+          else
+            ungetc(ch)
+          end
+	elsif ch == '\\' #'
+	  str << read_escape
+	end
+      end
+      if @ltype == "/"
+	if peek(0) =~ /i|o|n|e|s/
+	  str << getc
+	end
+      end
+      if subtype
+	Token(DLtype2Token[ltype], str)
+      else
+	Token(Ltype2Token[ltype], str)
+      end.set_text(str)
+    ensure
+      @ltype = nil
+      @quoted = nil
+      @lex_state = EXPR_END
+    end
+  end
+
+  def skip_inner_expression
+    res = ""
+    nest = 0
+    while (ch = getc)
+      res << ch
+      if ch == '}'
+        break if nest.zero?
+        nest -= 1
+      elsif ch == '{'
+        nest += 1
+      end
+    end
+    res
+  end
+
+  def identify_comment
+    @ltype = "#"
+    comment = "#"
+    while ch = getc
+      if ch == "\\"
+        ch = getc
+        if ch == "\n"
+          ch = " "
+        else
+          comment << "\\" 
+        end
+      else
+        if ch == "\n"
+          @ltype = nil
+          ungetc
+          break
+        end
+      end
+      comment << ch
+    end
+    return Token(TkCOMMENT).set_text(comment)
+  end
+  
+  def read_escape
+    res = ""
+    case ch = getc
+    when /[0-7]/
+      ungetc ch
+      3.times do
+	case ch = getc
+	when /[0-7]/
+	when nil
+	  break
+	else
+	  ungetc
+	  break
+	end
+        res << ch
+      end
+      
+    when "x"
+      res << ch
+      2.times do
+	case ch = getc
+	when /[0-9a-fA-F]/
+	when nil
+	  break
+	else
+	  ungetc
+	  break
+	end
+        res << ch
+      end
+
+    when "M"
+      res << ch
+      if (ch = getc) != '-'
+	ungetc
+      else
+        res << ch
+	if (ch = getc) == "\\" #"
+          res << ch
+	  res << read_escape
+        else
+          res << ch
+	end
+      end
+
+    when "C", "c" #, "^"
+      res << ch
+      if ch == "C" and (ch = getc) != "-"
+	ungetc
+      else
+        res << ch
+        if (ch = getc) == "\\" #"
+          res << ch
+          res << read_escape
+        else
+          res << ch
+        end
+      end
+    else
+      res << ch
+    end
+    res
+  end
+end
+
+
+
+# Extract code elements from a source file, returning a TopLevel
+# object containing the constituent file elements.
+#
+# This file is based on rtags
+
+module RDoc
+
+  GENERAL_MODIFIERS = [ 'nodoc' ].freeze
+
+  CLASS_MODIFIERS = GENERAL_MODIFIERS
+
+  ATTR_MODIFIERS  = GENERAL_MODIFIERS
+
+  CONSTANT_MODIFIERS = GENERAL_MODIFIERS
+
+  METHOD_MODIFIERS = GENERAL_MODIFIERS + 
+    [ 'arg', 'args', 'yield', 'yields', 'notnew', 'not-new', 'not_new', 'doc' ]
+
+
+  class RubyParser
+    include RubyToken
+    include TokenStream
+
+    extend ParserFactory
+
+    parse_files_matching(/\.rbw?$/)
+
+
+    def initialize(top_level, file_name, content, options, stats)
+      @options = options
+      @stats   = stats
+      @size = 0
+      @token_listeners = nil
+      @input_file_name = file_name
+      @scanner = RubyLex.new(content)
+      @scanner.exception_on_syntax_error = false
+      @top_level = top_level
+      @progress = $stderr unless options.quiet
+    end
+
+    def scan
+      @tokens = []
+      @unget_read = []
+      @read = []
+      catch(:eof) do
+        catch(:enddoc) do
+          begin
+            parse_toplevel_statements(@top_level)
+          rescue Exception => e
+            $stderr.puts "\n\n"
+            $stderr.puts "RDoc failure in #@input_file_name at or around " +
+                         "line #{@scanner.line_no} column #{@scanner.char_no}"
+            $stderr.puts 
+            $stderr.puts "Before reporting this, could you check that the file"
+            $stderr.puts "you're documenting compiles cleanly--RDoc is not a"
+            $stderr.puts "full Ruby parser, and gets confused easily if fed"
+            $stderr.puts "invalid programs."
+            $stderr.puts
+            $stderr.puts "The internal error was:\n\n"
+            
+            e.set_backtrace(e.backtrace[0,4])
+            raise
+          end
+        end
+      end
+      @top_level
+    end
+
+    private 
+
+    def make_message(msg)
+      prefix = "\n" + @input_file_name + ":"
+      if @scanner
+        prefix << "#{@scanner.line_no}:#{@scanner.char_no}: "
+      end
+      return prefix + msg
+    end
+
+    def warn(msg)
+      return if @options.quiet
+      msg = make_message msg
+      $stderr.puts msg
+    end
+
+    def error(msg)
+      msg = make_message msg
+      $stderr.puts msg
+      exit(1)
+    end
+
+    def progress(char)
+      unless @options.quiet
+        @progress.print(char)
+	@progress.flush
+      end
+    end
+
+    def add_token_listener(obj)
+      @token_listeners ||= []
+      @token_listeners << obj
+    end
+
+    def remove_token_listener(obj)
+      @token_listeners.delete(obj)
+    end
+
+    def get_tk
+      tk = nil
+      if @tokens.empty?
+	tk = @scanner.token
+	@read.push @scanner.get_read
+	puts "get_tk1 => #{tk.inspect}" if $TOKEN_DEBUG
+      else
+	@read.push @unget_read.shift
+	tk = @tokens.shift
+	puts "get_tk2 => #{tk.inspect}" if $TOKEN_DEBUG
+      end
+
+      if tk.kind_of?(TkSYMBEG)
+        set_token_position(tk.line_no, tk.char_no)
+        tk1 = get_tk
+        if tk1.kind_of?(TkId) || tk1.kind_of?(TkOp)
+          tk = Token(TkSYMBOL).set_text(":" + tk1.name)
+          # remove the identifier we just read (we're about to
+          # replace it with a symbol)
+          @token_listeners.each do |obj|
+            obj.pop_token
+          end if @token_listeners
+        else
+          warn("':' not followed by identifier or operator")
+          tk = tk1
+        end
+      end
+
+      # inform any listeners of our shiny new token
+      @token_listeners.each do |obj|
+        obj.add_token(tk)
+      end if @token_listeners
+
+      tk
+    end
+
+    def peek_tk
+      unget_tk(tk = get_tk)
+      tk
+    end
+
+    def unget_tk(tk)
+      @tokens.unshift tk
+      @unget_read.unshift @read.pop
+
+      # Remove this token from any listeners
+      @token_listeners.each do |obj|
+        obj.pop_token
+      end if @token_listeners
+    end
+
+    def skip_tkspace(skip_nl = true)
+      tokens = []
+      while ((tk = get_tk).kind_of?(TkSPACE) ||
+	     (skip_nl && tk.kind_of?(TkNL)))
+	tokens.push tk
+      end
+      unget_tk(tk)
+      tokens
+    end
+
+    def get_tkread
+      read = @read.join("")
+      @read = []
+      read
+    end
+
+    def peek_read
+      @read.join('')
+    end
+
+    NORMAL = "::"
+    SINGLE = "<<"
+
+    # Look for the first comment in a file that isn't
+    # a shebang line.
+
+    def collect_first_comment
+      skip_tkspace
+      res = ''
+      first_line = true
+
+      tk = get_tk
+      while tk.kind_of?(TkCOMMENT)
+        if first_line && tk.text[0,2] == "#!"
+          skip_tkspace
+          tk = get_tk
+        else
+          res << tk.text << "\n"
+          tk = get_tk
+          if tk.kind_of? TkNL
+            skip_tkspace(false)
+            tk = get_tk
+          end
+        end
+        first_line = false
+      end
+      unget_tk(tk)
+      res
+    end
+
+    def parse_toplevel_statements(container)
+      comment = collect_first_comment
+      look_for_directives_in(container, comment)
+      container.comment = comment unless comment.empty?
+      parse_statements(container, NORMAL, nil, comment)
+    end
+    
+    def parse_statements(container, single=NORMAL, current_method=nil, comment='')
+      nest = 1
+      save_visibility = container.visibility
+      
+#      if container.kind_of?(TopLevel)
+#      else
+#        comment = ''
+#      end
+
+      non_comment_seen = true
+      
+      while tk = get_tk
+        
+        keep_comment = false
+        
+        non_comment_seen = true unless tk.kind_of?(TkCOMMENT)
+        
+	case tk
+
+        when TkNL
+          skip_tkspace(true)   # Skip blanks and newlines
+          tk = get_tk
+          if tk.kind_of?(TkCOMMENT)
+            if non_comment_seen
+              comment = ''
+              non_comment_seen = false
+            end
+            while tk.kind_of?(TkCOMMENT)
+              comment << tk.text << "\n"
+              tk = get_tk          # this is the newline 
+              skip_tkspace(false)  # leading spaces
+              tk = get_tk
+            end
+            unless comment.empty?
+              look_for_directives_in(container, comment) 
+              if container.done_documenting
+                container.ongoing_visibility = save_visibility
+#                return
+              end
+            end
+            keep_comment = true
+          else
+            non_comment_seen = true
+          end
+          unget_tk(tk)
+          keep_comment = true
+
+
+	when TkCLASS
+	  if container.document_children
+            parse_class(container, single, tk, comment)
+	  else
+	    nest += 1
+          end
+
+	when TkMODULE
+	  if container.document_children
+            parse_module(container, single, tk, comment)
+	  else
+	    nest += 1
+          end
+
+	when TkDEF
+	  if container.document_self
+	    parse_method(container, single, tk, comment)
+	  else
+	    nest += 1
+          end
+
+        when TkCONSTANT
+          if container.document_self
+            parse_constant(container, single, tk, comment)
+          end
+
+	when TkALIAS
+ 	  if container.document_self
+	    parse_alias(container, single, tk, comment)
+	  end
+
+        when TkYIELD
+          if current_method.nil?
+            warn("Warning: yield outside of method") if container.document_self
+          else
+            parse_yield(container, single, tk, current_method)
+          end
+
+          # Until and While can have a 'do', which shouldn't increas
+          # the nesting. We can't solve the general case, but we can
+          # handle most occurrences by ignoring a do at the end of a line
+
+        when  TkUNTIL, TkWHILE
+          nest += 1
+          puts "FOUND #{tk.class} in #{container.name}, nest = #{nest}, " +
+            "line #{tk.line_no}" if $DEBUG
+          skip_optional_do_after_expression
+
+          # 'for' is trickier
+        when TkFOR
+          nest += 1
+          puts "FOUND #{tk.class} in #{container.name}, nest = #{nest}, " +
+            "line #{tk.line_no}" if $DEBUG
+          skip_for_variable
+          skip_optional_do_after_expression
+
+	when TkCASE, TkDO, TkIF, TkUNLESS, TkBEGIN
+	  nest += 1
+          puts "Found #{tk.class} in #{container.name}, nest = #{nest}, " +
+            "line #{tk.line_no}" if $DEBUG
+
+	when TkIDENTIFIER
+          if nest == 1 and current_method.nil?
+            case tk.name
+            when "private", "protected", "public",
+                 "private_class_method", "public_class_method"
+              parse_visibility(container, single, tk)
+              keep_comment = true
+            when "attr"
+              parse_attr(container, single, tk, comment)
+            when /^attr_(reader|writer|accessor)$/, @options.extra_accessors
+              parse_attr_accessor(container, single, tk, comment)
+            when "alias_method"
+              if container.document_self
+	        parse_alias(container, single, tk, comment)
+	      end
+            end
+	  end
+	  
+	  case tk.name
+	  when "require"
+	    parse_require(container, comment)
+	  when "include"
+	    parse_include(container, comment)
+	  end
+
+
+	when TkEND
+          nest -= 1
+          puts "Found 'end' in #{container.name}, nest = #{nest}, line #{tk.line_no}" if $DEBUG
+          puts "Method = #{current_method.name}" if $DEBUG and current_method
+	  if nest == 0
+            read_documentation_modifiers(container, CLASS_MODIFIERS)
+            container.ongoing_visibility = save_visibility
+            return
+          end
+
+	end
+
+        comment = '' unless keep_comment
+	begin
+	  get_tkread
+	  skip_tkspace(false)
+	end while peek_tk == TkNL
+
+      end
+    end
+    
+    def parse_class(container, single, tk, comment, &block)
+      progress("c")
+
+      @stats.num_classes += 1
+
+      container, name_t = get_class_or_module(container)
+
+      case name_t
+      when TkCONSTANT
+	name = name_t.name
+        superclass = "Object"
+
+        if peek_tk.kind_of?(TkLT)
+          get_tk
+          skip_tkspace(true)
+          superclass = get_class_specification
+          superclass = "<unknown>" if superclass.empty?
+        end
+
+	if single == SINGLE
+	  cls_type = SingleClass
+	else
+	  cls_type = NormalClass
+	end
+
+        cls = container.add_class(cls_type, name, superclass)
+        read_documentation_modifiers(cls, CLASS_MODIFIERS)
+        cls.record_location(@top_level)
+	parse_statements(cls)
+        cls.comment = comment
+
+      when TkLSHFT
+	case name = get_class_specification
+	when "self", container.name
+	  parse_statements(container, SINGLE, &block)
+	else
+          other = TopLevel.find_class_named(name)
+          unless other
+#            other = @top_level.add_class(NormalClass, name, nil)
+#            other.record_location(@top_level)
+#            other.comment = comment
+            other = NormalClass.new("Dummy", nil)
+          end
+          read_documentation_modifiers(other, CLASS_MODIFIERS)
+          parse_statements(other, SINGLE, &block)
+	end
+
+      else
+	warn("Expected class name or '<<'. Got #{name_t.class}: #{name_t.text.inspect}")
+      end
+    end
+
+    def parse_module(container, single, tk, comment)
+      progress("m")
+      @stats.num_modules += 1
+      container, name_t  = get_class_or_module(container)
+#      skip_tkspace
+      name = name_t.name
+      mod = container.add_module(NormalModule, name)
+      mod.record_location(@top_level)
+      read_documentation_modifiers(mod, CLASS_MODIFIERS)
+      parse_statements(mod)
+      mod.comment = comment
+    end
+
+    # Look for the name of a class of module (optionally with a leading :: or
+    # with :: separated named) and return the ultimate name and container
+
+    def get_class_or_module(container)
+      skip_tkspace
+      name_t = get_tk
+
+      # class ::A -> A is in the top level
+      if name_t.kind_of?(TkCOLON2)
+        name_t = get_tk
+        container = @top_level
+      end
+
+      skip_tkspace(false)
+
+      while peek_tk.kind_of?(TkCOLON2)
+        prev_container = container
+        container = container.find_module_named(name_t.name)
+        if !container
+#          warn("Couldn't find module #{name_t.name}")
+          container = prev_container.add_module(NormalModule, name_t.name)
+        end
+        get_tk
+        name_t = get_tk
+      end
+      skip_tkspace(false)
+      return [container, name_t]
+    end
+
+    def parse_constant(container, single, tk, comment)
+      name = tk.name
+      skip_tkspace(false)
+      eq_tk = get_tk
+
+      unless eq_tk.kind_of?(TkASSIGN)
+        unget_tk(eq_tk)
+        return
+      end
+
+
+      nest = 0
+      get_tkread
+
+      tk = get_tk
+      if tk.kind_of? TkGT
+        unget_tk(tk)
+        unget_tk(eq_tk)
+        return
+      end
+
+      loop do
+        puts("Param: #{tk}, #{@scanner.continue} " +
+          "#{@scanner.lex_state} #{nest}")  if $DEBUG
+
+        case tk
+        when TkSEMICOLON
+          break
+        when TkLPAREN, TkfLPAREN
+          nest += 1
+        when TkRPAREN
+          nest -= 1
+        when TkCOMMENT
+          if nest <= 0 && @scanner.lex_state == EXPR_END
+            unget_tk(tk)
+            break
+          end
+        when TkNL
+          if (@scanner.lex_state == EXPR_END and nest <= 0) || !@scanner.continue
+            unget_tk(tk)
+            break
+          end
+        end
+        tk = get_tk
+      end
+
+      res = get_tkread.tr("\n", " ").strip
+      res = "" if res == ";"
+      con = Constant.new(name, res, comment)
+      read_documentation_modifiers(con, CONSTANT_MODIFIERS)
+      if con.document_self
+	container.add_constant(con)
+      end
+    end
+
+    def parse_method(container, single, tk, comment)
+      progress(".")
+      @stats.num_methods += 1
+      line_no = tk.line_no
+      column  = tk.char_no
+      
+      start_collecting_tokens
+      add_token(tk)
+      add_token_listener(self)
+      
+      @scanner.instance_eval{@lex_state = EXPR_FNAME}
+      skip_tkspace(false)
+      name_t = get_tk
+      back_tk = skip_tkspace
+      meth = nil
+      added_container = false
+
+      dot = get_tk
+      if dot.kind_of?(TkDOT) or dot.kind_of?(TkCOLON2)
+	@scanner.instance_eval{@lex_state = EXPR_FNAME}
+	skip_tkspace
+	name_t2 = get_tk
+	case name_t
+	when TkSELF
+	  name = name_t2.name
+	when TkCONSTANT
+          name = name_t2.name
+          prev_container = container
+          container = container.find_module_named(name_t.name)
+          if !container
+            added_container = true
+            obj = name_t.name.split("::").inject(Object) do |state, item|
+              state.const_get(item)
+            end rescue nil
+
+            type = obj.class == Class ? NormalClass : NormalModule
+            if not [Class, Module].include?(obj.class)
+              warn("Couldn't find #{name_t.name}. Assuming it's a module")
+            end
+
+            if type == NormalClass then
+              container = prev_container.add_class(type, name_t.name, obj.superclass.name)
+            else
+              container = prev_container.add_module(type, name_t.name)
+            end
+          end
+	else
+	  # warn("Unexpected token '#{name_t2.inspect}'")
+	  # break
+          skip_method(container)
+          return
+	end
+	meth =  AnyMethod.new(get_tkread, name)
+        meth.singleton = true
+      else
+	unget_tk dot
+	back_tk.reverse_each do
+	  |tk|
+	  unget_tk tk
+	end
+	name = name_t.name
+
+        meth =  AnyMethod.new(get_tkread, name)
+        meth.singleton = (single == SINGLE)
+      end
+
+      remove_token_listener(self)
+
+      meth.start_collecting_tokens
+      indent = TkSPACE.new(1,1)
+      indent.set_text(" " * column)
+
+      meth.add_tokens([TkCOMMENT.new(line_no,
+                                     1,
+                                     "# File #{@top_level.file_absolute_name}, line #{line_no}"),
+                        NEWLINE_TOKEN,
+                        indent])
+
+      meth.add_tokens(@token_stream)
+
+      add_token_listener(meth)
+
+      @scanner.instance_eval{@continue = false}
+      parse_method_parameters(meth)
+
+      if meth.document_self
+        container.add_method(meth)
+      elsif added_container
+        container.document_self = false
+      end
+
+      # Having now read the method parameters and documentation modifiers, we
+      # now know whether we have to rename #initialize to ::new
+
+      if name == "initialize" && !meth.singleton
+        if meth.dont_rename_initialize
+          meth.visibility = :protected
+        else
+          meth.singleton = true
+          meth.name = "new"
+          meth.visibility = :public
+        end
+      end
+      
+      parse_statements(container, single, meth)
+      
+      remove_token_listener(meth)
+
+      # Look for a 'call-seq' in the comment, and override the
+      # normal parameter stuff
+
+      if comment.sub!(/:?call-seq:(.*?)^\s*\#?\s*$/m, '')
+        seq = $1
+        seq.gsub!(/^\s*\#\s*/, '')
+        meth.call_seq = seq
+      end
+      
+      meth.comment = comment
+
+    end
+    
+    def skip_method(container)
+      meth =  AnyMethod.new("", "anon")
+      parse_method_parameters(meth)
+      parse_statements(container, false, meth)
+    end
+    
+    # Capture the method's parameters. Along the way,
+    # look for a comment containing 
+    #
+    #    # yields: ....
+    #
+    # and add this as the block_params for the method
+
+    def parse_method_parameters(method)
+      res = parse_method_or_yield_parameters(method)
+      res = "(" + res + ")" unless res[0] == ?(
+      method.params = res unless method.params
+      if method.block_params.nil?
+          skip_tkspace(false)
+	  read_documentation_modifiers(method, METHOD_MODIFIERS)
+      end
+    end
+
+    def parse_method_or_yield_parameters(method=nil, modifiers=METHOD_MODIFIERS)
+      skip_tkspace(false)
+      tk = get_tk
+
+      # Little hack going on here. In the statement
+      #  f = 2*(1+yield)
+      # We see the RPAREN as the next token, so we need
+      # to exit early. This still won't catch all cases
+      # (such as "a = yield + 1"
+      end_token = case tk
+                  when TkLPAREN, TkfLPAREN
+                    TkRPAREN
+                  when TkRPAREN
+                    return ""
+                  else
+                    TkNL
+                  end
+      nest = 0
+
+      loop do
+        puts("Param: #{tk.inspect}, #{@scanner.continue} " +
+          "#{@scanner.lex_state} #{nest}")  if $DEBUG
+        case tk
+        when TkSEMICOLON
+          break
+        when TkLBRACE
+          nest += 1
+        when TkRBRACE
+          # we might have a.each {|i| yield i }
+          unget_tk(tk) if nest.zero?
+          nest -= 1
+          break if nest <= 0
+        when TkLPAREN, TkfLPAREN
+          nest += 1
+        when end_token
+          if end_token == TkRPAREN
+            nest -= 1
+            break if @scanner.lex_state == EXPR_END and nest <= 0
+          else
+            break unless @scanner.continue
+          end
+        when method && method.block_params.nil? && TkCOMMENT
+	  unget_tk(tk)
+	  read_documentation_modifiers(method, modifiers)
+        end
+        tk = get_tk
+      end
+      res = get_tkread.tr("\n", " ").strip
+      res = "" if res == ";"
+      res
+    end
+
+    # skip the var [in] part of a 'for' statement
+    def skip_for_variable
+      skip_tkspace(false)
+      tk = get_tk
+      skip_tkspace(false)
+      tk = get_tk
+      unget_tk(tk) unless tk.kind_of?(TkIN)
+    end
+
+    # while, until, and for have an optional 
+    def skip_optional_do_after_expression
+      skip_tkspace(false)
+      tk = get_tk
+      case tk
+      when TkLPAREN, TkfLPAREN
+        end_token = TkRPAREN
+      else
+        end_token = TkNL
+      end
+
+      nest = 0
+      @scanner.instance_eval{@continue = false}
+
+      loop do
+        puts("\nWhile: #{tk}, #{@scanner.continue} " +
+          "#{@scanner.lex_state} #{nest}") if $DEBUG
+        case tk
+        when TkSEMICOLON
+          break
+        when TkLPAREN, TkfLPAREN
+          nest += 1
+        when TkDO
+          break if nest.zero?
+        when end_token
+          if end_token == TkRPAREN
+            nest -= 1
+            break if @scanner.lex_state == EXPR_END and nest.zero?
+          else
+            break unless @scanner.continue
+          end
+        end
+        tk = get_tk
+      end
+      skip_tkspace(false)
+      if peek_tk.kind_of? TkDO
+        get_tk
+      end
+    end
+    
+    # Return a superclass, which can be either a constant
+    # of an expression
+
+    def get_class_specification
+      tk = get_tk
+      return "self" if tk.kind_of?(TkSELF)
+        
+      res = ""
+      while tk.kind_of?(TkCOLON2) ||
+          tk.kind_of?(TkCOLON3)   ||
+          tk.kind_of?(TkCONSTANT)   
+        
+        res += tk.text
+        tk = get_tk
+      end
+
+      unget_tk(tk)
+      skip_tkspace(false)
+
+      get_tkread # empty out read buffer
+
+      tk = get_tk
+
+      case tk
+      when TkNL, TkCOMMENT, TkSEMICOLON
+        unget_tk(tk)
+        return res
+      end
+
+      res += parse_call_parameters(tk)
+      res
+    end
+
+    def parse_call_parameters(tk)
+
+      end_token = case tk
+                  when TkLPAREN, TkfLPAREN
+                    TkRPAREN
+                  when TkRPAREN
+                    return ""
+                  else
+                    TkNL
+                  end
+      nest = 0
+
+      loop do
+        puts("Call param: #{tk}, #{@scanner.continue} " +
+          "#{@scanner.lex_state} #{nest}") if $DEBUG
+        case tk
+        when TkSEMICOLON
+          break
+        when TkLPAREN, TkfLPAREN
+          nest += 1
+        when end_token
+          if end_token == TkRPAREN
+            nest -= 1
+            break if @scanner.lex_state == EXPR_END and nest <= 0
+          else
+            break unless @scanner.continue
+          end
+        when TkCOMMENT
+	  unget_tk(tk)
+	  break
+        end
+        tk = get_tk
+      end
+      res = get_tkread.tr("\n", " ").strip
+      res = "" if res == ";"
+      res
+    end
+
+
+    # Parse a constant, which might be qualified by
+    # one or more class or module names
+
+    def get_constant
+      res = ""
+      skip_tkspace(false)
+      tk = get_tk
+
+      while tk.kind_of?(TkCOLON2) ||
+          tk.kind_of?(TkCOLON3)   ||
+          tk.kind_of?(TkCONSTANT)          
+        
+        res += tk.text
+        tk = get_tk
+      end
+
+#      if res.empty?
+#        warn("Unexpected token #{tk} in constant")
+#      end 
+      unget_tk(tk)
+      res
+    end
+
+    # Get a constant that may be surrounded by parens
+    
+    def get_constant_with_optional_parens
+      skip_tkspace(false)
+      nest = 0
+      while (tk = peek_tk).kind_of?(TkLPAREN)  || tk.kind_of?(TkfLPAREN)
+        get_tk
+        skip_tkspace(true)
+        nest += 1
+      end
+
+      name = get_constant
+
+      while nest > 0
+        skip_tkspace(true)
+        tk = get_tk
+        nest -= 1 if tk.kind_of?(TkRPAREN)
+      end
+      name
+    end
+
+    # Directives are modifier comments that can appear after class, module,
+    # or method names. For example
+    #
+    #   def fred    # :yields:  a, b
+    #
+    # or
+    #
+    #   class SM  # :nodoc:
+    #
+    # we return the directive name and any parameters as a two element array
+    
+    def read_directive(allowed)
+      tk = get_tk
+      puts "directive: #{tk.inspect}" if $DEBUG
+      result = nil
+      if tk.kind_of?(TkCOMMENT) 
+        if tk.text =~ /\s*:?(\w+):\s*(.*)/
+          directive = $1.downcase
+          if allowed.include?(directive)
+            result = [directive, $2]
+          end
+        end
+      else
+        unget_tk(tk)
+      end
+      result
+    end
+
+    
+    def read_documentation_modifiers(context, allow)
+      dir = read_directive(allow)
+
+      case dir[0]
+
+      when "notnew", "not_new", "not-new"
+        context.dont_rename_initialize = true
+
+      when "nodoc"
+        context.document_self = false
+	if dir[1].downcase == "all"
+	  context.document_children = false
+	end
+
+      when "doc"
+        context.document_self = true
+        context.force_documentation = true
+
+      when "yield", "yields"
+        unless context.params.nil?
+          context.params.sub!(/(,|)\s*&\w+/,'') # remove parameter &proc
+        end
+	context.block_params = dir[1]
+
+      when "arg", "args"
+        context.params = dir[1]
+      end if dir
+    end
+
+    
+    # Look for directives in a normal comment block:
+    #
+    #   #--       - don't display comment from this point forward
+    #  
+    #
+    # This routine modifies it's parameter
+
+    def look_for_directives_in(context, comment)
+
+      preprocess = SM::PreProcess.new(@input_file_name,
+                                      @options.rdoc_include)
+
+      preprocess.handle(comment) do |directive, param|
+        case directive
+        when "stopdoc"
+          context.stop_doc
+          ""
+        when "startdoc"
+          context.start_doc
+          context.force_documentation = true
+          ""
+
+        when "enddoc"
+          #context.done_documenting = true
+          #""
+          throw :enddoc
+
+        when "main"
+          options = Options.instance
+          options.main_page = param
+	  ""
+
+        when "title"
+          options = Options.instance
+          options.title = param
+          ""
+
+        when "section"
+          context.set_current_section(param, comment)
+          comment.replace("") # 1.8 doesn't support #clear
+          break 
+        else
+          warn "Unrecognized directive '#{directive}'"
+          break
+        end
+      end
+
+      remove_private_comments(comment)
+    end
+
+    def remove_private_comments(comment)
+      comment.gsub!(/^#--.*?^#\+\+/m, '')
+      comment.sub!(/^#--.*/m, '')
+    end
+
+
+
+    def get_symbol_or_name
+      tk = get_tk
+      case tk
+      when  TkSYMBOL
+        tk.text.sub(/^:/, '')
+      when TkId, TkOp
+        tk.name
+      when TkSTRING
+        tk.text
+      else
+        raise "Name or symbol expected (got #{tk})"
+      end
+    end
+    
+    def parse_alias(context, single, tk, comment)
+      skip_tkspace
+      if (peek_tk.kind_of? TkLPAREN)
+        get_tk
+        skip_tkspace
+      end
+      new_name = get_symbol_or_name
+      @scanner.instance_eval{@lex_state = EXPR_FNAME}
+      skip_tkspace
+      if (peek_tk.kind_of? TkCOMMA)
+        get_tk
+        skip_tkspace
+      end
+      old_name = get_symbol_or_name
+
+      al = Alias.new(get_tkread, old_name, new_name, comment)
+      read_documentation_modifiers(al, ATTR_MODIFIERS)
+      if al.document_self
+	context.add_alias(al)
+      end
+    end
+
+    def parse_yield_parameters
+      parse_method_or_yield_parameters
+    end
+
+  def parse_yield(context, single, tk, method)
+    if method.block_params.nil?
+      get_tkread
+      @scanner.instance_eval{@continue = false}
+      method.block_params = parse_yield_parameters
+    end
+  end
+
+  def parse_require(context, comment)
+    skip_tkspace_comment
+    tk = get_tk
+    if tk.kind_of? TkLPAREN
+      skip_tkspace_comment
+      tk = get_tk
+    end
+
+    name = nil
+    case tk
+    when TkSTRING
+      name = tk.text
+#    when TkCONSTANT, TkIDENTIFIER, TkIVAR, TkGVAR
+#      name = tk.name
+    when TkDSTRING
+      warn "Skipping require of dynamic string: #{tk.text}"
+ #   else
+ #     warn "'require' used as variable"
+    end
+    if name
+      context.add_require(Require.new(name, comment))
+    else
+      unget_tk(tk)
+    end
+  end
+
+  def parse_include(context, comment)
+    loop do
+      skip_tkspace_comment
+      name = get_constant_with_optional_parens
+      unless name.empty?
+        context.add_include(Include.new(name, comment))
+      end
+      return unless peek_tk.kind_of?(TkCOMMA)
+      get_tk
+    end
+  end
+
+    def get_bool
+      skip_tkspace
+      tk = get_tk
+      case tk
+      when TkTRUE
+        true
+      when TkFALSE, TkNIL
+        false
+      else
+        unget_tk tk
+        true
+      end
+    end
+
+    def parse_attr(context, single, tk, comment)
+      args = parse_symbol_arg(1)
+      if args.size > 0
+	name = args[0]
+        rw = "R"
+        skip_tkspace(false)
+        tk = get_tk
+        if tk.kind_of? TkCOMMA
+          rw = "RW" if get_bool
+        else
+          unget_tk tk
+        end
+	att = Attr.new(get_tkread, name, rw, comment)
+	read_documentation_modifiers(att, ATTR_MODIFIERS)
+	if att.document_self
+	  context.add_attribute(att)
+	end
+      else
+	warn("'attr' ignored - looks like a variable")
+      end    
+
+    end
+
+    def parse_visibility(container, single, tk)
+      singleton = (single == SINGLE)
+      vis = case tk.name
+            when "private"   then :private
+            when "protected" then :protected
+            when "public"    then :public
+            when "private_class_method"
+              singleton = true
+              :private
+            when "public_class_method"
+              singleton = true
+              :public
+            else raise "Invalid visibility: #{tk.name}"
+            end
+            
+      skip_tkspace_comment(false)
+      case peek_tk
+        # Ryan Davis suggested the extension to ignore modifiers, because he
+        # often writes
+        #
+        #   protected unless $TESTING
+        #
+      when TkNL, TkUNLESS_MOD, TkIF_MOD
+#        error("Missing argument") if singleton        
+        container.ongoing_visibility = vis
+      else
+        args = parse_symbol_arg
+        container.set_visibility_for(args, vis, singleton)
+      end
+    end
+
+    def parse_attr_accessor(context, single, tk, comment)
+      args = parse_symbol_arg
+      read = get_tkread
+      rw = "?"
+
+      # If nodoc is given, don't document any of them
+
+      tmp = CodeObject.new
+      read_documentation_modifiers(tmp, ATTR_MODIFIERS)
+      return unless tmp.document_self
+
+      case tk.name
+      when "attr_reader"   then rw = "R"
+      when "attr_writer"   then rw = "W"
+      when "attr_accessor" then rw = "RW"
+      else
+        rw = @options.extra_accessor_flags[tk.name]
+      end
+      
+      for name in args
+	att = Attr.new(get_tkread, name, rw, comment)
+        context.add_attribute(att)
+      end    
+    end
+
+    def skip_tkspace_comment(skip_nl = true)
+      loop do
+        skip_tkspace(skip_nl)
+        return unless peek_tk.kind_of? TkCOMMENT
+        get_tk
+      end
+    end
+
+    def parse_symbol_arg(no = nil)
+
+      args = []
+      skip_tkspace_comment
+      case tk = get_tk
+      when TkLPAREN
+	loop do
+	  skip_tkspace_comment
+	  if tk1 = parse_symbol_in_arg
+	    args.push tk1
+	    break if no and args.size >= no
+	  end
+	  
+	  skip_tkspace_comment
+	  case tk2 = get_tk
+	  when TkRPAREN
+	    break
+	  when TkCOMMA
+	  else
+           warn("unexpected token: '#{tk2.inspect}'") if $DEBUG
+	    break
+	  end
+	end
+      else
+	unget_tk tk
+	if tk = parse_symbol_in_arg
+	  args.push tk
+	  return args if no and args.size >= no
+	end
+
+	loop do
+#	  skip_tkspace_comment(false)
+	  skip_tkspace(false)
+
+	  tk1 = get_tk
+	  unless tk1.kind_of?(TkCOMMA) 
+	    unget_tk tk1
+	    break
+	  end
+	  
+	  skip_tkspace_comment
+	  if tk = parse_symbol_in_arg
+	    args.push tk
+	    break if no and args.size >= no
+	  end
+	end
+      end
+      args
+    end
+
+    def parse_symbol_in_arg
+      case tk = get_tk
+      when TkSYMBOL
+        tk.text.sub(/^:/, '')
+      when TkSTRING
+	eval @read[-1]
+      else
+	warn("Expected symbol or string, got #{tk.inspect}") if $DEBUG
+	nil
+      end
+    end
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parse_simple.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parse_simple.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parse_simple.rb	(revision 18425)
@@ -0,0 +1,41 @@
+# Parse a non-source file. We basically take the whole thing 
+# as one big comment. If the first character in the file
+# is '#', we strip leading pound signs.
+
+
+require "rdoc/code_objects"
+require "rdoc/markup/simple_markup/preprocess"
+
+module RDoc
+  # See rdoc/parsers/parse_c.rb
+
+  class SimpleParser
+    
+    # prepare to parse a plain file
+    def initialize(top_level, file_name, body, options, stats)
+      
+      preprocess = SM::PreProcess.new(file_name, options.rdoc_include)
+      
+      preprocess.handle(body) do |directive, param|
+        $stderr.puts "Unrecognized directive '#{directive}' in #{file_name}"
+      end
+      
+      @body = body
+      @options = options
+      @top_level = top_level
+    end
+    
+    # Extract the file contents and attach them to the toplevel as a
+    # comment
+    
+    def scan
+      #    @body.gsub(/^(\s\n)+/, '')
+      @top_level.comment = remove_private_comments(@body)
+      @top_level
+    end
+
+    def remove_private_comments(comment)
+      comment.gsub(/^--.*?^\+\+/m, '').sub(/^--.*/m, '')
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parserfactory.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parserfactory.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/parsers/parserfactory.rb	(revision 18425)
@@ -0,0 +1,99 @@
+require "rdoc/parsers/parse_simple"
+
+module RDoc
+
+  # A parser is simple a class that implements
+  #
+  #   #initialize(file_name, body, options)
+  #
+  # and
+  #
+  #   #scan
+  #
+  # The initialize method takes a file name to be used, the body of the
+  # file, and an RDoc::Options object. The scan method is then called
+  # to return an appropriately parsed TopLevel code object.
+  #
+  # The ParseFactory is used to redirect to the correct parser given a filename
+  # extension. This magic works because individual parsers have to register 
+  # themselves with us as they are loaded in. The do this using the following
+  # incantation
+  #
+  #
+  #    require "rdoc/parsers/parsefactory"
+  #    
+  #    module RDoc
+  #    
+  #      class XyzParser
+  #        extend ParseFactory                  <<<<
+  #        parse_files_matching /\.xyz$/        <<<<
+  #    
+  #        def initialize(file_name, body, options)
+  #          ...
+  #        end
+  #    
+  #        def scan
+  #          ...
+  #        end
+  #      end
+  #    end
+  #
+  # Just to make life interesting, if we suspect a plain text file, we
+  # also look for a shebang line just in case it's a potential
+  # shell script
+
+
+
+  module ParserFactory
+
+    @@parsers = []
+
+    Parsers = Struct.new(:regexp, :parser)
+
+    # Record the fact that a particular class parses files that
+    # match a given extension
+
+    def parse_files_matching(regexp)
+      @@parsers.unshift Parsers.new(regexp, self)
+    end
+
+    # Return a parser that can handle a particular extension
+
+    def ParserFactory.can_parse(file_name)
+      @@parsers.find {|p| p.regexp.match(file_name) }
+    end
+
+    # Alias an extension to another extension. After this call,
+    # files ending "new_ext" will be parsed using the same parser
+    # as "old_ext"
+
+    def ParserFactory.alias_extension(old_ext, new_ext)
+      parser = ParserFactory.can_parse("xxx.#{old_ext}")
+      return false unless parser
+      @@parsers.unshift Parsers.new(Regexp.new("\\.#{new_ext}$"), parser.parser)
+      true
+    end
+
+    # Find the correct parser for a particular file name. Return a 
+    # SimpleParser for ones that we don't know
+
+    def ParserFactory.parser_for(top_level, file_name, body, options, stats)
+      # If no extension, look for shebang
+      if file_name !~ /\.\w+$/ && body =~ %r{\A#!(.+)}
+        shebang = $1
+        case shebang
+        when %r{env\s+ruby}, %r{/ruby}
+          file_name = "dummy.rb"
+        end
+      end
+      parser_description = can_parse(file_name)
+      if parser_description
+        parser = parser_description.parser 
+      else
+        parser = SimpleParser
+      end
+
+      parser.new(top_level, file_name, body, options, stats)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/rdoc.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/rdoc.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/rdoc.rb	(revision 18425)
@@ -0,0 +1,298 @@
+# See README.
+#
+ 
+
+VERSION_STRING = %{RDoc V1.0.1 - 20041108}
+
+
+require 'rdoc/parsers/parse_rb.rb'
+require 'rdoc/parsers/parse_c.rb'
+require 'rdoc/parsers/parse_f95.rb'
+
+require 'rdoc/parsers/parse_simple.rb'
+require 'rdoc/options'
+
+require 'rdoc/diagram'
+
+require 'find'
+require 'ftools'
+require 'time'
+
+# We put rdoc stuff in the RDoc module to avoid namespace
+# clutter.
+#
+# ToDo: This isn't universally true.
+#
+# :include: README
+
+module RDoc
+
+  # Name of the dotfile that contains the description of files to be
+  # processed in the current directory
+  DOT_DOC_FILENAME = ".document"
+
+  # Simple stats collector
+  class Stats
+    attr_accessor :num_files, :num_classes, :num_modules, :num_methods
+    def initialize
+      @num_files = @num_classes = @num_modules = @num_methods = 0
+      @start = Time.now
+    end
+    def print
+      puts "Files:   #@num_files"
+      puts "Classes: #@num_classes"
+      puts "Modules: #@num_modules"
+      puts "Methods: #@num_methods"
+      puts "Elapsed: " + sprintf("%0.3fs", Time.now - @start)
+    end
+  end
+
+
+  # Exception thrown by any rdoc error. Only the #message part is
+  # of use externally.
+
+  class RDocError < Exception
+  end
+
+  # Encapsulate the production of rdoc documentation. Basically
+  # you can use this as you would invoke rdoc from the command
+  # line:
+  #
+  #    rdoc = RDoc::RDoc.new
+  #    rdoc.document(args)
+  #
+  # where _args_ is an array of strings, each corresponding to
+  # an argument you'd give rdoc on the command line. See rdoc/rdoc.rb 
+  # for details.
+  
+  class RDoc
+
+    ##
+    # This is the list of output generators that we
+    # support
+    
+    Generator = Struct.new(:file_name, :class_name, :key)
+    
+    GENERATORS = {}
+    $:.collect {|d|
+      File::expand_path(d)
+    }.find_all {|d|
+      File::directory?("#{d}/rdoc/generators")
+    }.each {|dir|
+      Dir::entries("#{dir}/rdoc/generators").each {|gen|
+        next unless /(\w+)_generator.rb$/ =~ gen
+        type = $1
+        unless GENERATORS.has_key? type
+          GENERATORS[type] = Generator.new("rdoc/generators/#{gen}",
+                                           "#{type.upcase}Generator".intern,
+                                           type)
+        end
+      }
+    }                                                    
+
+    #######
+    private
+    #######
+
+    ##
+    # Report an error message and exit
+    
+    def error(msg)
+      raise RDocError.new(msg)
+    end
+    
+    ##
+    # Create an output dir if it doesn't exist. If it does
+    # exist, but doesn't contain the flag file <tt>created.rid</tt>
+    # then we refuse to use it, as we may clobber some
+    # manually generated documentation
+    
+    def setup_output_dir(op_dir, force)
+      flag_file = output_flag_file(op_dir)
+      if File.exist?(op_dir)
+        unless File.directory?(op_dir)
+          error "'#{op_dir}' exists, and is not a directory" 
+        end
+        begin
+          created = File.read(flag_file)
+        rescue SystemCallError
+          error "\nDirectory #{op_dir} already exists, but it looks like it\n" +
+            "isn't an RDoc directory. Because RDoc doesn't want to risk\n" +
+            "destroying any of your existing files, you'll need to\n" +
+            "specify a different output directory name (using the\n" +
+            "--op <dir> option).\n\n"
+        else
+          last = (Time.parse(created) unless force rescue nil)
+        end
+      else
+        File.makedirs(op_dir)
+      end
+      last
+    end
+
+    # Update the flag file in an output directory.
+    def update_output_dir(op_dir, time)
+      File.open(output_flag_file(op_dir), "w") {|f| f.puts time.rfc2822 }
+    end
+
+    # Return the path name of the flag file in an output directory.
+    def output_flag_file(op_dir)
+      File.join(op_dir, "created.rid")
+    end
+
+    # The .document file contains a list of file and directory name
+    # patterns, representing candidates for documentation. It may
+    # also contain comments (starting with '#')
+    def parse_dot_doc_file(in_dir, filename, options)
+      # read and strip comments
+      patterns = File.read(filename).gsub(/#.*/, '')
+
+      result = []
+
+      patterns.split.each do |patt|
+        candidates = Dir.glob(File.join(in_dir, patt))
+        result.concat(normalized_file_list(options,  candidates))
+      end
+      result
+    end
+
+
+    # Given a list of files and directories, create a list
+    # of all the Ruby files they contain. 
+    #
+    # If +force_doc+ is true, we always add the given files.
+    # If false, only add files that we guarantee we can parse
+    # It is true when looking at files given on the command line,
+    # false when recursing through subdirectories. 
+    #
+    # The effect of this is that if you want a file with a non-
+    # standard extension parsed, you must name it explicity.
+    #
+
+    def normalized_file_list(options, relative_files, force_doc = false, exclude_pattern=nil)
+      file_list = []
+
+      relative_files.each do |rel_file_name|
+        next if exclude_pattern && exclude_pattern =~ rel_file_name
+        stat = File.stat(rel_file_name)
+        case type = stat.ftype
+        when "file"
+          next if @last_created and stat.mtime < @last_created
+          file_list << rel_file_name.sub(/^\.\//, '') if force_doc || ParserFactory.can_parse(rel_file_name)
+        when "directory"
+          next if rel_file_name == "CVS" || rel_file_name == ".svn"
+          dot_doc = File.join(rel_file_name, DOT_DOC_FILENAME)
+          if File.file?(dot_doc)
+            file_list.concat(parse_dot_doc_file(rel_file_name, dot_doc, options))
+          else
+            file_list.concat(list_files_in_directory(rel_file_name, options))
+          end
+        else
+          raise RDocError.new("I can't deal with a #{type} #{rel_file_name}")
+        end
+      end
+      file_list
+    end
+
+    # Return a list of the files to be processed in
+    # a directory. We know that this directory doesn't have
+    # a .document file, so we're looking for real files. However
+    # we may well contain subdirectories which must
+    # be tested for .document files
+    def list_files_in_directory(dir, options)
+      normalized_file_list(options, Dir.glob(File.join(dir, "*")), false, options.exclude)
+    end
+
+
+    # Parse each file on the command line, recursively entering
+    # directories
+
+    def parse_files(options)
+ 
+      file_info = []
+
+      files = options.files
+      files = ["."] if files.empty?
+
+      file_list = normalized_file_list(options, files, true)
+
+      file_list.each do |fn|
+        $stderr.printf("\n%35s: ", File.basename(fn)) unless options.quiet
+        
+        content = File.open(fn, "r") {|f| f.read}
+
+        top_level = TopLevel.new(fn)
+        parser = ParserFactory.parser_for(top_level, fn, content, options, @stats)
+        file_info << parser.scan
+        @stats.num_files += 1
+      end
+
+      file_info
+    end
+
+
+    public
+
+    ###################################################################
+    #
+    # Format up one or more files according to the given arguments.
+    # For simplicity, _argv_ is an array of strings, equivalent to the
+    # strings that would be passed on the command line. (This isn't a
+    # coincidence, as we _do_ pass in ARGV when running
+    # interactively). For a list of options, see rdoc/rdoc.rb. By
+    # default, output will be stored in a directory called +doc+ below
+    # the current directory, so make sure you're somewhere writable
+    # before invoking.
+    #
+    # Throws: RDocError on error
+
+    def document(argv)
+
+      TopLevel::reset
+
+      @stats = Stats.new
+
+      options = Options.instance
+      options.parse(argv, GENERATORS)
+
+      @last_created = nil
+      unless options.all_one_file
+        @last_created = setup_output_dir(options.op_dir, options.force_update)
+      end
+      start_time = Time.now
+
+      file_info = parse_files(options)
+
+      if file_info.empty?
+        $stderr.puts "\nNo newer files." unless options.quiet
+      else
+        gen = options.generator
+
+        $stderr.puts "\nGenerating #{gen.key.upcase}..." unless options.quiet
+
+        require gen.file_name
+
+        gen_class = Generators.const_get(gen.class_name)
+        gen = gen_class.for(options)
+
+        pwd = Dir.pwd
+
+        Dir.chdir(options.op_dir)  unless options.all_one_file
+
+        begin
+          Diagram.new(file_info, options).draw if options.diagram
+          gen.generate(file_info)
+          update_output_dir(".", start_time)
+        ensure
+          Dir.chdir(pwd)
+        end
+      end
+
+      unless options.quiet
+        puts
+        @stats.print
+      end
+    end
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_cache.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_cache.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_cache.rb	(revision 18425)
@@ -0,0 +1,187 @@
+module RI
+
+  class ClassEntry
+
+    attr_reader :name
+    attr_reader :path_names
+    
+    def initialize(path_name, name, in_class)
+      @path_names = [ path_name ]
+      @name = name
+      @in_class = in_class
+      @class_methods    = []
+      @instance_methods = []
+      @inferior_classes = []
+    end
+
+    # We found this class in more tha one place, so add
+    # in the name from there.
+    def add_path(path)
+      @path_names << path
+    end
+
+    # read in our methods and any classes
+    # and modules in our namespace. Methods are
+    # stored in files called name-c|i.yaml,
+    # where the 'name' portion is the external
+    # form of the method name and the c|i is a class|instance
+    # flag
+
+    def load_from(dir)
+      Dir.foreach(dir) do |name|
+        next if name =~ /^\./
+
+        # convert from external to internal form, and
+        # extract the instance/class flag
+
+        if name =~ /^(.*?)-(c|i).yaml$/
+          external_name = $1
+          is_class_method = $2 == "c"
+          internal_name = RiWriter.external_to_internal(external_name)
+          list = is_class_method ? @class_methods : @instance_methods
+          path = File.join(dir, name)
+          list << MethodEntry.new(path, internal_name, is_class_method, self)
+        else
+          full_name = File.join(dir, name)
+          if File.directory?(full_name)
+            inf_class = @inferior_classes.find {|c| c.name == name }
+            if inf_class
+              inf_class.add_path(full_name)
+            else
+              inf_class = ClassEntry.new(full_name, name, self)
+              @inferior_classes << inf_class
+            end
+            inf_class.load_from(full_name)
+          end
+        end
+      end
+    end
+
+    # Return a list of any classes or modules that we contain
+    # that match a given string
+
+    def contained_modules_matching(name)
+      @inferior_classes.find_all {|c| c.name[name]}
+    end
+
+    def classes_and_modules
+      @inferior_classes
+    end
+
+    # Return an exact match to a particular name
+    def contained_class_named(name)
+      @inferior_classes.find {|c| c.name == name}
+    end
+
+    # return the list of local methods matching name
+    # We're split into two because we need distinct behavior
+    # when called from the _toplevel_
+    def methods_matching(name, is_class_method)
+      local_methods_matching(name, is_class_method)
+    end
+
+    # Find methods matching 'name' in ourselves and in
+    # any classes we contain
+    def recursively_find_methods_matching(name, is_class_method)
+      res = local_methods_matching(name, is_class_method)
+      @inferior_classes.each do |c|
+        res.concat(c.recursively_find_methods_matching(name, is_class_method))
+      end
+      res
+    end
+
+
+    # Return our full name
+    def full_name
+      res = @in_class.full_name
+      res << "::" unless res.empty?
+      res << @name
+    end
+
+    # Return a list of all out method names
+    def all_method_names
+      res = @class_methods.map {|m| m.full_name }
+      @instance_methods.each {|m| res << m.full_name}
+      res
+    end
+
+    private
+
+    # Return a list of all our methods matching a given string.
+    # Is +is_class_methods+ if 'nil', we don't care if the method
+    # is a class method or not, otherwise we only return
+    # those methods that match
+    def local_methods_matching(name, is_class_method)
+
+      list = case is_class_method
+             when nil then  @class_methods + @instance_methods
+             when true then @class_methods
+             when false then @instance_methods
+             else fail "Unknown is_class_method: #{is_class_method.inspect}"
+             end
+
+      list.find_all {|m| m.name;  m.name[name]}
+    end
+  end
+
+  # A TopLevelEntry is like a class entry, but when asked to search
+  # for methods searches all classes, not just itself
+
+  class TopLevelEntry < ClassEntry
+    def methods_matching(name, is_class_method)
+      res = recursively_find_methods_matching(name, is_class_method)
+    end
+
+    def full_name
+      ""
+    end
+
+    def module_named(name)
+      
+    end
+
+  end
+
+  class MethodEntry
+    attr_reader :name
+    attr_reader :path_name
+
+    def initialize(path_name, name, is_class_method, in_class)
+      @path_name = path_name
+      @name = name
+      @is_class_method = is_class_method
+      @in_class = in_class
+    end
+
+    def full_name
+      res = @in_class.full_name
+      unless res.empty?
+        if @is_class_method
+          res << "::"
+        else
+          res << "#"
+        end
+      end
+      res << @name
+    end
+  end
+
+  # We represent everything know about all 'ri' files
+  # accessible to this program
+
+  class RiCache
+
+    attr_reader :toplevel
+
+    def initialize(dirs)
+      # At the top level we have a dummy module holding the
+      # overall namespace
+      @toplevel = TopLevelEntry.new('', '::', nil)
+
+      dirs.each do |dir|
+        @toplevel.load_from(dir)
+      end
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_descriptions.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_descriptions.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_descriptions.rb	(revision 18425)
@@ -0,0 +1,154 @@
+require 'yaml'
+require 'rdoc/markup/simple_markup/fragments'
+
+# Descriptions are created by RDoc (in ri_generator) and
+# written out in serialized form into the documentation
+# tree. ri then reads these to generate the documentation
+
+module RI
+  class NamedThing
+    attr_reader :name
+    def initialize(name)
+      @name = name
+    end
+    def <=>(other)
+      @name <=> other.name
+    end
+
+    def hash
+      @name.hash
+    end
+
+    def eql?(other)
+      @name.eql?(other)
+    end
+  end
+
+#  Alias          = Struct.new(:old_name, :new_name)
+
+  class AliasName < NamedThing
+  end
+
+  class Attribute < NamedThing
+    attr_reader :rw, :comment
+    def initialize(name, rw, comment)
+      super(name)
+      @rw = rw
+      @comment = comment
+    end
+  end
+
+  class Constant < NamedThing
+    attr_reader :value, :comment
+    def initialize(name, value, comment)
+      super(name)
+      @value = value
+      @comment = comment
+    end
+  end
+
+  class IncludedModule < NamedThing
+  end
+
+
+  class MethodSummary < NamedThing
+    def initialize(name="")
+      super
+    end
+  end
+
+
+
+  class Description
+    attr_accessor :name
+    attr_accessor :full_name
+    attr_accessor :comment
+
+    def serialize
+      self.to_yaml
+    end
+
+    def Description.deserialize(from)
+      YAML.load(from)
+    end
+
+    def <=>(other)
+      @name <=> other.name
+    end
+  end
+  
+  class ModuleDescription < Description
+    
+    attr_accessor :class_methods
+    attr_accessor :instance_methods
+    attr_accessor :attributes
+    attr_accessor :constants
+    attr_accessor :includes
+
+    # merge in another class desscription into this one
+    def merge_in(old)
+      merge(@class_methods, old.class_methods)
+      merge(@instance_methods, old.instance_methods)
+      merge(@attributes, old.attributes)
+      merge(@constants, old.constants)
+      merge(@includes, old.includes)
+      if @comment.nil? || @comment.empty?
+        @comment = old.comment
+      else
+        unless old.comment.nil? or old.comment.empty? then
+          @comment << SM::Flow::RULE.new
+          @comment.concat old.comment
+        end
+      end
+    end
+
+    def display_name
+      "Module"
+    end
+
+    # the 'ClassDescription' subclass overrides this
+    # to format up the name of a parent
+    def superclass_string
+      nil
+    end
+
+    private
+
+    def merge(into, from)
+      names = {}
+      into.each {|i| names[i.name] = i }
+      from.each {|i| names[i.name] = i }
+      into.replace(names.keys.sort.map {|n| names[n]})
+    end
+  end
+  
+  class ClassDescription < ModuleDescription
+    attr_accessor :superclass
+
+    def display_name
+      "Class"
+    end
+
+    def superclass_string
+      if @superclass && @superclass != "Object"
+        @superclass
+      else
+        nil
+      end
+    end
+  end
+
+
+  class MethodDescription < Description
+    
+    attr_accessor :is_class_method
+    attr_accessor :visibility
+    attr_accessor :block_params
+    attr_accessor :is_singleton
+    attr_accessor :aliases
+    attr_accessor :is_alias_for
+    attr_accessor :params
+
+  end
+  
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_display.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_display.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_display.rb	(revision 18425)
@@ -0,0 +1,255 @@
+require 'rdoc/ri/ri_util'
+require 'rdoc/ri/ri_formatter'
+require 'rdoc/ri/ri_options'
+
+
+# This is a kind of 'flag' module. If you want to write your
+# own 'ri' display module (perhaps because you'r writing
+# an IDE or somesuch beast), you simply write a class
+# which implements the various 'display' methods in 'DefaultDisplay',
+# and include the 'RiDisplay' module in that class. 
+#
+# To access your class from the command line, you can do
+#
+#    ruby -r <your source file>  ../ri ....
+#
+# If folks _really_ want to do this from the command line,
+# I'll build an option in
+
+module RiDisplay
+  @@display_class = nil
+
+  def RiDisplay.append_features(display_class)
+    @@display_class = display_class
+  end
+
+  def RiDisplay.new(*args)
+    @@display_class.new(*args)
+  end
+end
+
+######################################################################
+#
+# A paging display module. Uses the ri_formatter class to do the
+# actual presentation
+#
+
+class  DefaultDisplay
+
+  include RiDisplay
+
+  def initialize(options)
+    @options = options
+    @formatter = @options.formatter.new(@options, "     ")
+  end    
+  
+  
+  ######################################################################
+  
+  def display_usage
+    page do
+      RI::Options::OptionList.usage(short_form=true)
+    end
+  end
+
+
+  ######################################################################
+  
+  def display_method_info(method)
+    page do
+      @formatter.draw_line(method.full_name)
+      display_params(method)
+      @formatter.draw_line
+      display_flow(method.comment)
+      if method.aliases && !method.aliases.empty?
+        @formatter.blankline
+        aka = "(also known as "
+        aka << method.aliases.map {|a| a.name }.join(", ") 
+        aka << ")"
+        @formatter.wrap(aka)
+      end
+    end
+  end
+  
+  ######################################################################
+  
+  def display_class_info(klass, ri_reader)
+    page do 
+      superclass = klass.superclass_string
+      
+      if superclass
+        superclass = " < " + superclass
+      else
+        superclass = ""
+      end
+      
+      @formatter.draw_line(klass.display_name + ": " +
+                           klass.full_name + superclass)
+      
+      display_flow(klass.comment)
+      @formatter.draw_line 
+    
+      unless klass.includes.empty?
+        @formatter.blankline
+        @formatter.display_heading("Includes:", 2, "")
+        incs = []
+        klass.includes.each do |inc|
+          inc_desc = ri_reader.find_class_by_name(inc.name)
+          if inc_desc
+            str = inc.name + "("
+            str << inc_desc.instance_methods.map{|m| m.name}.join(", ")
+            str << ")"
+            incs << str
+          else
+            incs << inc.name
+          end
+      end
+        @formatter.wrap(incs.sort.join(', '))
+      end
+      
+      unless klass.constants.empty?
+        @formatter.blankline
+        @formatter.display_heading("Constants:", 2, "")
+        len = 0
+        klass.constants.each { |c| len = c.name.length if c.name.length > len }
+        len += 2
+        klass.constants.each do |c|
+          @formatter.wrap(c.value, 
+                          @formatter.indent+((c.name+":").ljust(len)))
+        end 
+      end
+      
+      unless klass.class_methods.empty?
+        @formatter.blankline
+        @formatter.display_heading("Class methods:", 2, "")
+        @formatter.wrap(klass.class_methods.map{|m| m.name}.sort.join(', '))
+      end
+      
+      unless klass.instance_methods.empty?
+        @formatter.blankline
+        @formatter.display_heading("Instance methods:", 2, "")
+        @formatter.wrap(klass.instance_methods.map{|m| m.name}.sort.join(', '))
+      end
+      
+      unless klass.attributes.empty?
+        @formatter.blankline
+        @formatter.wrap("Attributes:", "")
+        @formatter.wrap(klass.attributes.map{|a| a.name}.sort.join(', '))
+      end
+    end
+  end
+  
+  ######################################################################
+  
+  # Display a list of method names
+  
+  def display_method_list(methods)
+    page do
+      puts "More than one method matched your request. You can refine"
+      puts "your search by asking for information on one of:\n\n"
+      @formatter.wrap(methods.map {|m| m.full_name} .join(", "))
+    end
+  end
+  
+  ######################################################################
+  
+  def display_class_list(namespaces)
+    page do
+      puts "More than one class or module matched your request. You can refine"
+      puts "your search by asking for information on one of:\n\n"
+      @formatter.wrap(namespaces.map {|m| m.full_name}.join(", "))
+    end
+  end
+  
+  ######################################################################
+
+  def list_known_classes(classes)
+    if classes.empty?
+      warn_no_database
+    else
+      page do 
+        @formatter.draw_line("Known classes and modules")
+        @formatter.blankline
+        @formatter.wrap(classes.sort.join(", "))
+      end
+    end
+  end
+
+  ######################################################################
+
+  def list_known_names(names)
+    if names.empty?
+      warn_no_database
+    else
+      page do 
+        names.each {|n| @formatter.raw_print_line(n)}
+      end
+    end
+  end
+
+  ######################################################################
+
+  private
+
+  ######################################################################
+
+  def page
+    return yield unless pager = setup_pager
+    begin
+      save_stdout = STDOUT.clone
+      STDOUT.reopen(pager)
+      yield
+    ensure
+      STDOUT.reopen(save_stdout)
+      save_stdout.close
+      pager.close
+    end
+  end
+
+  ######################################################################
+
+  def setup_pager
+    unless @options.use_stdout
+      for pager in [ ENV['PAGER'], "less", "more", 'pager' ].compact.uniq
+        return IO.popen(pager, "w") rescue nil
+      end
+      @options.use_stdout = true
+      nil
+    end
+  end
+
+  ######################################################################
+  
+  def display_params(method)
+
+    params = method.params
+
+    if params[0,1] == "("
+      if method.is_singleton
+        params = method.full_name + params
+      else
+        params = method.name + params
+      end
+    end
+    params.split(/\n/).each do |p|
+      @formatter.wrap(p) 
+      @formatter.break_to_newline
+    end
+  end
+  ######################################################################
+  
+  def display_flow(flow)
+    if !flow || flow.empty?
+      @formatter.wrap("(no description...)")
+    else
+      @formatter.display_flow(flow)
+    end
+  end
+
+  ######################################################################
+  
+  def warn_no_database
+    puts "Before using ri, you need to generate documentation"
+    puts "using 'rdoc' with the --ri option"
+  end
+end  # class RiDisplay
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_driver.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_driver.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_driver.rb	(revision 18425)
@@ -0,0 +1,143 @@
+require 'rdoc/ri/ri_paths'
+require 'rdoc/usage'
+require 'rdoc/ri/ri_cache'
+require 'rdoc/ri/ri_util'
+require 'rdoc/ri/ri_reader'
+require 'rdoc/ri/ri_formatter'
+require 'rdoc/ri/ri_options'
+
+
+######################################################################
+
+class  RiDriver
+
+  def initialize
+    @options = RI::Options.instance
+
+    args = ARGV
+    if ENV["RI"]
+      args = ENV["RI"].split.concat(ARGV)
+    end
+
+    @options.parse(args)
+
+    path = @options.path
+    report_missing_documentation @options.raw_path if path.empty?
+
+    @ri_reader = RI::RiReader.new(RI::RiCache.new(path))
+    @display   = @options.displayer
+  end
+  
+  # Couldn't find documentation in +path+, so tell the user what to do
+
+  def report_missing_documentation(path)
+    STDERR.puts "No ri documentation found in:"
+    path.each do |d|
+      STDERR.puts "     #{d}"
+    end
+    STDERR.puts "\nWas rdoc run to create documentation?\n\n"
+    RDoc::usage("Installing Documentation")
+  end
+  
+  ######################################################################
+  
+  # If the list of matching methods contains exactly one entry, or
+  # if it contains an entry that exactly matches the requested method,
+  # then display that entry, otherwise display the list of
+  # matching method names
+  
+  def report_method_stuff(requested_method_name, methods)
+    if methods.size == 1
+      method = @ri_reader.get_method(methods[0])
+      @display.display_method_info(method)
+    else
+      entries = methods.find_all {|m| m.name == requested_method_name}
+      if entries.size == 1
+        method = @ri_reader.get_method(entries[0])
+        @display.display_method_info(method)
+      else
+        @display.display_method_list(methods)
+      end
+    end
+  end
+  
+  ######################################################################
+  
+  def report_class_stuff(namespaces)
+    if namespaces.size == 1
+      klass = @ri_reader.get_class(namespaces[0])
+      @display.display_class_info(klass, @ri_reader)
+    else 
+#      entries = namespaces.find_all {|m| m.full_name == requested_class_name}
+#      if entries.size == 1
+#        klass = @ri_reader.get_class(entries[0])
+#        @display.display_class_info(klass, @ri_reader)
+#      else
+        @display.display_class_list(namespaces)
+#      end
+    end
+  end
+  
+  ######################################################################
+  
+  
+  def get_info_for(arg)
+    desc = NameDescriptor.new(arg)
+
+    namespaces = @ri_reader.top_level_namespace
+    
+    for class_name in desc.class_names
+      namespaces = @ri_reader.lookup_namespace_in(class_name, namespaces)
+      if namespaces.empty?
+        raise RiError.new("Nothing known about #{arg}")
+      end
+    end
+
+    # at this point, if we have multiple possible namespaces, but one
+    # is an exact match for our requested class, prune down to just it
+
+    full_class_name = desc.full_class_name
+    entries = namespaces.find_all {|m| m.full_name == full_class_name}
+    namespaces = entries if entries.size == 1
+
+    if desc.method_name.nil?
+      report_class_stuff(namespaces)
+    else
+      methods = @ri_reader.find_methods(desc.method_name, 
+                                        desc.is_class_method,
+                                        namespaces)
+
+      if methods.empty?
+        raise RiError.new("Nothing known about #{arg}")
+      else
+        report_method_stuff(desc.method_name, methods)
+      end
+    end
+  end
+
+  ######################################################################
+
+  def process_args
+    if @options.list_classes
+      classes = @ri_reader.full_class_names
+      @display.list_known_classes(classes)
+    elsif @options.list_names
+      names = @ri_reader.all_names
+      @display.list_known_names(names)
+    else
+      if ARGV.size.zero?
+        @display.display_usage
+      else
+        begin
+          ARGV.each do |arg|
+            get_info_for(arg)
+          end
+        rescue RiError => e
+          STDERR.puts(e.message)
+          exit(1)
+        end
+      end
+    end
+  end
+
+end  # class RiDriver
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_formatter.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_formatter.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_formatter.rb	(revision 18425)
@@ -0,0 +1,672 @@
+module RI
+  class TextFormatter
+
+    attr_reader :indent
+    
+    def initialize(options, indent)
+      @options = options
+      @width   = options.width
+      @indent  = indent
+    end
+    
+    
+    ######################################################################
+    
+    def draw_line(label=nil)
+      len = @width
+      len -= (label.size+1) if label
+      print "-"*len
+      if label
+        print(" ")
+        bold_print(label) 
+      end
+      puts
+    end
+    
+    ######################################################################
+    
+    def wrap(txt,  prefix=@indent, linelen=@width)
+      return unless txt && !txt.empty?
+      work = conv_markup(txt)
+      textLen = linelen - prefix.length
+      patt = Regexp.new("^(.{0,#{textLen}})[ \n]")
+      next_prefix = prefix.tr("^ ", " ")
+
+      res = []
+
+      while work.length > textLen
+        if work =~ patt
+          res << $1
+          work.slice!(0, $&.length)
+        else
+          res << work.slice!(0, textLen)
+        end
+      end
+      res << work if work.length.nonzero?
+      puts(prefix + res.join("\n" + next_prefix))
+    end
+
+    ######################################################################
+
+    def blankline
+      puts
+    end
+    
+    ######################################################################
+
+    # called when we want to ensure a nbew 'wrap' starts on a newline
+    # Only needed for HtmlFormatter, because the rest do their
+    # own line breaking
+
+    def break_to_newline
+    end
+    
+    ######################################################################
+
+    def bold_print(txt)
+      print txt
+    end
+
+    ######################################################################
+
+    def raw_print_line(txt)
+      puts txt
+    end
+
+    ######################################################################
+
+    # convert HTML entities back to ASCII
+    def conv_html(txt)
+      txt.
+          gsub(/&gt;/, '>').
+          gsub(/&lt;/, '<').
+          gsub(/&quot;/, '"').
+          gsub(/&amp;/, '&')
+          
+    end
+
+    # convert markup into display form
+    def conv_markup(txt)
+      txt.
+          gsub(%r{<tt>(.*?)</tt>}) { "+#$1+" } .
+          gsub(%r{<code>(.*?)</code>}) { "+#$1+" } .
+          gsub(%r{<b>(.*?)</b>}) { "*#$1*" } .
+          gsub(%r{<em>(.*?)</em>}) { "_#$1_" }
+    end
+
+    ######################################################################
+
+    def display_list(list)
+      case list.type
+
+      when SM::ListBase::BULLET 
+        prefixer = proc { |ignored| @indent + "*   " }
+
+      when SM::ListBase::NUMBER,
+      SM::ListBase::UPPERALPHA,
+      SM::ListBase::LOWERALPHA
+
+        start = case list.type
+                when SM::ListBase::NUMBER      then 1
+                when  SM::ListBase::UPPERALPHA then 'A'
+                when SM::ListBase::LOWERALPHA  then 'a'
+                end
+        prefixer = proc do |ignored|
+          res = @indent + "#{start}.".ljust(4)
+          start = start.succ
+          res
+        end
+        
+      when SM::ListBase::LABELED
+        prefixer = proc do |li|
+          li.label
+        end
+
+      when SM::ListBase::NOTE
+        longest = 0
+        list.contents.each do |item|
+          if item.kind_of?(SM::Flow::LI) && item.label.length > longest
+            longest = item.label.length
+          end
+        end
+
+        prefixer = proc do |li|
+          @indent + li.label.ljust(longest+1)
+        end
+
+      else
+        fail "unknown list type"
+
+      end
+
+      list.contents.each do |item|
+        if item.kind_of? SM::Flow::LI
+          prefix = prefixer.call(item)
+          display_flow_item(item, prefix)
+        else
+          display_flow_item(item)
+        end
+       end
+    end
+
+    ######################################################################
+
+    def display_flow_item(item, prefix=@indent)
+      case item
+      when SM::Flow::P, SM::Flow::LI
+        wrap(conv_html(item.body), prefix)
+        blankline
+        
+      when SM::Flow::LIST
+        display_list(item)
+
+      when SM::Flow::VERB
+        display_verbatim_flow_item(item, @indent)
+
+      when SM::Flow::H
+        display_heading(conv_html(item.text), item.level, @indent)
+
+      when SM::Flow::RULE
+        draw_line
+
+      else
+        fail "Unknown flow element: #{item.class}"
+      end
+    end
+
+    ######################################################################
+
+    def display_verbatim_flow_item(item, prefix=@indent)
+        item.body.split(/\n/).each do |line|
+          print @indent, conv_html(line), "\n"
+        end
+        blankline
+    end
+
+    ######################################################################
+
+    def display_heading(text, level, indent)
+      text = strip_attributes(text)
+      case level
+      when 1
+        ul = "=" * text.length
+        puts
+        puts text.upcase
+        puts ul
+#        puts
+        
+      when 2
+        ul = "-" * text.length
+        puts
+        puts text
+        puts ul
+#        puts
+      else
+        print indent, text, "\n"
+      end
+    end
+
+
+    def display_flow(flow)
+      flow.each do |f|
+        display_flow_item(f)
+      end
+    end
+
+    def strip_attributes(txt)
+      tokens = txt.split(%r{(</?(?:b|code|em|i|tt)>)})
+      text = [] 
+      attributes = 0
+      tokens.each do |tok|
+        case tok
+        when %r{^</(\w+)>$}, %r{^<(\w+)>$}
+          ;
+        else
+          text << tok
+        end
+      end
+      text.join
+    end
+
+
+  end
+  
+  
+  ######################################################################
+  # Handle text with attributes. We're a base class: there are
+  # different presentation classes (one, for example, uses overstrikes
+  # to handle bold and underlining, while another using ANSI escape
+  # sequences
+  
+  class AttributeFormatter < TextFormatter
+    
+    BOLD      = 1
+    ITALIC    = 2
+    CODE      = 4
+
+    ATTR_MAP = {
+      "b"    => BOLD,
+      "code" => CODE,
+      "em"   => ITALIC,
+      "i"    => ITALIC,
+      "tt"   => CODE
+    }
+
+    # TODO: struct?
+    class AttrChar
+      attr_reader :char
+      attr_reader :attr
+
+      def initialize(char, attr)
+        @char = char
+        @attr = attr
+      end
+    end
+
+    
+    class AttributeString
+      attr_reader :txt
+
+      def initialize
+        @txt = []
+        @optr = 0
+      end
+
+      def <<(char)
+        @txt << char
+      end
+
+      def empty?
+        @optr >= @txt.length
+      end
+
+      # accept non space, then all following spaces
+      def next_word
+        start = @optr
+        len = @txt.length
+
+        while @optr < len && @txt[@optr].char != " "
+          @optr += 1
+        end
+
+        while @optr < len && @txt[@optr].char == " "
+          @optr += 1
+        end
+
+        @txt[start...@optr]
+      end
+    end
+
+    ######################################################################
+    # overrides base class. Looks for <tt>...</tt> etc sequences
+    # and generates an array of AttrChars. This array is then used
+    # as the basis for the split
+
+    def wrap(txt,  prefix=@indent, linelen=@width)
+      return unless txt && !txt.empty?
+
+      txt = add_attributes_to(txt)
+      next_prefix = prefix.tr("^ ", " ")
+      linelen -= prefix.size
+
+      line = []
+
+      until txt.empty?
+        word = txt.next_word
+        if word.size + line.size > linelen
+          write_attribute_text(prefix, line)
+          prefix = next_prefix
+          line = []
+        end
+        line.concat(word)
+      end
+
+      write_attribute_text(prefix, line) if line.length > 0
+    end
+
+    protected
+
+    # overridden in specific formatters
+
+    def write_attribute_text(prefix, line)
+      print prefix
+      line.each do |achar|
+        print achar.char
+      end
+      puts
+    end
+
+    # again, overridden
+
+    def bold_print(txt)
+      print txt
+    end
+
+    private
+
+    def add_attributes_to(txt)
+      tokens = txt.split(%r{(</?(?:b|code|em|i|tt)>)})
+      text = AttributeString.new
+      attributes = 0
+      tokens.each do |tok|
+        case tok
+        when %r{^</(\w+)>$} then attributes &= ~(ATTR_MAP[$1]||0)
+        when %r{^<(\w+)>$}  then attributes  |= (ATTR_MAP[$1]||0)
+        else
+          tok.split(//).each {|ch| text << AttrChar.new(ch, attributes)}
+        end
+      end
+      text
+    end
+
+  end
+
+
+  ##################################################
+  
+  # This formatter generates overstrike-style formatting, which
+  # works with pagers such as man and less.
+
+  class OverstrikeFormatter < AttributeFormatter
+
+    BS = "\C-h"
+
+    def write_attribute_text(prefix, line)
+      print prefix
+      line.each do |achar|
+        attr = achar.attr
+        if (attr & (ITALIC+CODE)) != 0
+          print "_", BS
+        end
+        if (attr & BOLD) != 0
+          print achar.char, BS
+        end
+        print achar.char
+      end
+      puts
+    end
+
+    # draw a string in bold
+    def bold_print(text)
+      text.split(//).each do |ch|
+        print ch, BS, ch
+      end
+    end
+  end
+
+  ##################################################
+  
+  # This formatter uses ANSI escape sequences
+  # to colorize stuff
+  # works with pages such as man and less.
+
+  class AnsiFormatter < AttributeFormatter
+
+    def initialize(*args)
+      print "\033[0m"
+      super
+    end
+
+    def write_attribute_text(prefix, line)
+      print prefix
+      curr_attr = 0
+      line.each do |achar|
+        attr = achar.attr
+        if achar.attr != curr_attr
+          update_attributes(achar.attr)
+          curr_attr = achar.attr
+        end
+        print achar.char
+      end
+      update_attributes(0) unless curr_attr.zero?
+      puts
+    end
+
+
+    def bold_print(txt)
+      print "\033[1m#{txt}\033[m"
+    end
+
+    HEADINGS = {
+      1 => [ "\033[1;32m", "\033[m" ] ,
+      2 => ["\033[4;32m", "\033[m" ],
+      3 => ["\033[32m", "\033[m" ]
+    }
+
+    def display_heading(text, level, indent)
+      level = 3 if level > 3
+      heading = HEADINGS[level]
+      print indent
+      print heading[0]
+      print strip_attributes(text)
+      puts heading[1]
+    end
+    
+    private
+
+    ATTR_MAP = {
+      BOLD   => "1",
+      ITALIC => "33",
+      CODE   => "36"
+    }
+
+    def update_attributes(attr)
+      str = "\033["
+      for quality in [ BOLD, ITALIC, CODE]
+        unless (attr & quality).zero?
+          str << ATTR_MAP[quality]
+        end
+      end
+      print str, "m"
+    end
+  end
+
+  ##################################################
+  
+  # This formatter uses HTML.
+
+  class HtmlFormatter < AttributeFormatter
+
+    def initialize(*args)
+      super
+    end
+
+    def write_attribute_text(prefix, line)
+      curr_attr = 0
+      line.each do |achar|
+        attr = achar.attr
+        if achar.attr != curr_attr
+          update_attributes(curr_attr, achar.attr)
+          curr_attr = achar.attr
+        end
+        print(escape(achar.char))
+      end
+      update_attributes(curr_attr, 0) unless curr_attr.zero?
+    end
+
+    def draw_line(label=nil)
+      if label != nil
+        bold_print(label)
+      end
+      puts("<hr>")
+    end
+
+    def bold_print(txt)
+      tag("b") { txt }
+    end
+
+    def blankline()
+      puts("<p>")
+    end
+
+    def break_to_newline
+      puts("<br>")
+    end
+
+    def display_heading(text, level, indent)
+      level = 4 if level > 4
+      tag("h#{level}") { text }
+      puts
+    end
+    
+    ######################################################################
+
+    def display_list(list)
+
+      case list.type
+      when SM::ListBase::BULLET 
+        list_type = "ul"
+        prefixer = proc { |ignored| "<li>" }
+
+      when SM::ListBase::NUMBER,
+      SM::ListBase::UPPERALPHA,
+      SM::ListBase::LOWERALPHA
+        list_type = "ol"
+        prefixer = proc { |ignored| "<li>" }
+        
+      when SM::ListBase::LABELED
+        list_type = "dl"
+        prefixer = proc do |li|
+          "<dt><b>" + escape(li.label) + "</b><dd>"
+        end
+
+      when SM::ListBase::NOTE
+        list_type = "table"
+        prefixer = proc do |li|
+          %{<tr valign="top"><td>#{li.label.gsub(/ /, '&nbsp;')}</td><td>}
+        end
+      else
+        fail "unknown list type"
+      end
+
+      print "<#{list_type}>"
+      list.contents.each do |item|
+        if item.kind_of? SM::Flow::LI
+          prefix = prefixer.call(item)
+          print prefix
+          display_flow_item(item, prefix)
+        else
+          display_flow_item(item)
+        end
+      end
+      print "</#{list_type}>"
+    end
+
+    def display_verbatim_flow_item(item, prefix=@indent)
+        print("<pre>")
+        puts item.body
+        puts("</pre>")
+    end
+
+    private
+
+    ATTR_MAP = {
+      BOLD   => "b>",
+      ITALIC => "i>",
+      CODE   => "tt>"
+    }
+
+    def update_attributes(current, wanted)
+      str = ""
+      # first turn off unwanted ones
+      off = current & ~wanted
+      for quality in [ BOLD, ITALIC, CODE]
+        if (off & quality) > 0
+          str << "</" + ATTR_MAP[quality]
+        end
+      end
+
+      # now turn on wanted
+      for quality in [ BOLD, ITALIC, CODE]
+        unless (wanted & quality).zero?
+          str << "<" << ATTR_MAP[quality]
+        end
+      end
+      print str
+    end
+
+    def tag(code)
+        print("<#{code}>")
+        print(yield)
+        print("</#{code}>")
+    end
+
+    def escape(str)
+      str.
+          gsub(/&/n, '&amp;').
+          gsub(/\"/n, '&quot;').
+          gsub(/>/n, '&gt;').
+          gsub(/</n, '&lt;')
+    end
+
+  end
+
+  ##################################################
+  
+  # This formatter reduces extra lines for a simpler output.
+  # It improves way output looks for tools like IRC bots.
+
+  class SimpleFormatter < TextFormatter
+
+    ######################################################################
+
+    # No extra blank lines
+
+    def blankline
+    end
+
+    ######################################################################
+
+    # Display labels only, no lines
+
+    def draw_line(label=nil)
+      unless label.nil? then
+        bold_print(label) 
+        puts
+      end
+    end
+
+    ######################################################################
+
+    # Place heading level indicators inline with heading.
+
+    def display_heading(text, level, indent)
+      text = strip_attributes(text)
+      case level
+      when 1
+        puts "= " + text.upcase
+      when 2
+        puts "-- " + text
+      else
+        print indent, text, "\n"
+      end
+    end
+
+  end
+
+
+  # Finally, fill in the list of known formatters
+
+  class TextFormatter
+
+    FORMATTERS = {
+      "ansi"   => AnsiFormatter,
+      "bs"     => OverstrikeFormatter,
+      "html"   => HtmlFormatter,
+      "plain"  => TextFormatter,
+      "simple" => SimpleFormatter,
+    }
+      
+    def TextFormatter.list
+      FORMATTERS.keys.sort.join(", ")
+    end
+
+    def TextFormatter.for(name)
+      FORMATTERS[name.downcase]
+    end
+
+  end
+
+end
+
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_options.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_options.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_options.rb	(revision 18425)
@@ -0,0 +1,313 @@
+# We handle the parsing of options, and subsequently as a singleton
+# object to be queried for option values
+
+module RI
+
+  require 'rdoc/ri/ri_paths'
+  require 'rdoc/ri/ri_display'
+
+  VERSION_STRING = "ri v1.0.1 - 20041108"
+
+  class Options
+    
+    require 'singleton'
+    require 'getoptlong'
+    
+    include Singleton
+
+    # No not use a pager. Writable, because ri sets it if it
+    # can't find a pager
+    attr_accessor :use_stdout
+
+    # should we just display a class list and exit
+    attr_reader :list_classes
+
+    # should we display a list of all names
+    attr_reader :list_names
+
+    # The width of the output line
+    attr_reader :width
+
+    # the formatting we apply to the output
+    attr_reader :formatter
+
+    # the directory we search for original documentation
+    attr_reader :doc_dir
+
+    module OptionList
+      
+      OPTION_LIST = [
+        [ "--help",          "-h",   nil,
+          "you're looking at it" ],
+
+        [ "--classes",      "-c",   nil,
+          "Display the names of classes and modules we\n" +
+          "know about"],
+
+        [ "--doc-dir",      "-d",   "<dirname>",
+          "A directory to search for documentation. If not\n" +
+          "specified, we search the standard rdoc/ri directories.\n" +
+          "May be repeated."],
+
+        [ "--system",       nil,    nil,
+          "Include documentation from Ruby's standard library:\n  " +
+          RI::Paths::SYSDIR ],
+
+        [ "--site",         nil,    nil,
+          "Include documentation from libraries installed in site_lib:\n  " +
+          RI::Paths::SITEDIR ],
+
+        [ "--home",         nil,    nil,
+          "Include documentation stored in ~/.rdoc:\n  " +
+          (RI::Paths::HOMEDIR || "No ~/.rdoc found") ],
+
+        [ "--gems",         nil,    nil,
+          "Include documentation from Rubygems:\n  " +
+          (RI::Paths::GEMDIRS ? "#{Gem.path}/doc/*/ri" :
+                                "No Rubygems ri found.") ],
+                                                           
+        [ "--format",       "-f",   "<name>",
+          "Format to use when displaying output:\n" +
+          "   " + RI::TextFormatter.list + "\n" +
+          "Use 'bs' (backspace) with most pager programs.\n" +
+          "To use ANSI, either also use the -T option, or\n" +
+          "tell your pager to allow control characters\n" +
+          "(for example using the -R option to less)"],
+
+        [ "--list-names",    "-l",   nil,
+          "List all the names known to RDoc, one per line"
+        ],
+
+        [ "--no-pager",      "-T",   nil,
+          "Send output directly to stdout." 
+        ],
+
+        [ "--width",         "-w",   "output width",
+        "Set the width of the output" ],
+
+        [ "--version",       "-v",   nil,
+         "Display the version of ri"
+        ],
+
+      ]
+
+      def OptionList.options
+        OPTION_LIST.map do |long, short, arg,|
+          option = []
+          option << long
+          option << short unless short.nil?
+          option << (arg ? GetoptLong::REQUIRED_ARGUMENT :
+                           GetoptLong::NO_ARGUMENT)
+          option
+        end
+      end
+
+
+      def OptionList.strip_output(text)
+        text =~ /^\s+/
+        leading_spaces = $&
+        text.gsub!(/^#{leading_spaces}/, '')
+        $stdout.puts text
+      end
+      
+      
+      # Show an error and exit
+      
+      def OptionList.error(msg)
+        $stderr.puts
+        $stderr.puts msg
+        $stderr.puts "\nFor help on options, try 'ri --help'\n\n"
+        exit 1
+      end
+      
+      # Show usage and exit
+      
+      def OptionList.usage(short_form=false)
+        
+        puts
+        puts(RI::VERSION_STRING)
+        puts
+        
+        name = File.basename($0)
+
+        directories = [
+          RI::Paths::SYSDIR,
+          RI::Paths::SITEDIR,
+          RI::Paths::HOMEDIR
+        ]
+
+        directories << "#{Gem.path}/doc/*/ri" if RI::Paths::GEMDIRS
+
+        directories = directories.join("\n    ")
+
+        OptionList.strip_output(<<-EOT)
+          Usage:
+
+            #{name} [options]  [names...]
+
+          Display information on Ruby classes, modules, and methods.
+          Give the names of classes or methods to see their documentation.
+          Partial names may be given: if the names match more than
+          one entity, a list will be shown, otherwise details on
+          that entity will be displayed.
+
+          Nested classes and modules can be specified using the normal
+          Name::Name notation, and instance methods can be distinguished
+          from class methods using "." (or "#") instead of "::".
+
+          For example:
+
+              ri  File
+              ri  File.new
+              ri  F.n
+              ri  zip
+
+          Note that shell quoting may be required for method names
+          containing punctuation:
+
+              ri 'Array.[]'
+              ri compact\\!
+
+          By default ri searches for documentation in the following
+          directories:
+
+              #{directories}
+
+          Specifying the --system, --site, --home, --gems or --doc-dir
+          options will limit ri to searching only the specified
+          directories.
+
+        EOT
+
+        if short_form
+          puts "For help on options, type 'ri -h'"
+          puts "For a list of classes I know about, type 'ri -c'"
+        else
+          puts "Options:\n\n"
+          OPTION_LIST.each do|long, short, arg, desc|
+            opt = ''
+            opt << (short ? sprintf("%15s", "#{long}, #{short}") :
+                            sprintf("%15s", long))
+            if arg
+              opt << " " << arg
+            end
+            print opt
+            desc = desc.split("\n")
+            if opt.size < 17
+              print " "*(18-opt.size)
+              puts desc.shift
+            else
+              puts
+            end
+            desc.each do |line|
+              puts(" "*18 + line)
+            end
+            puts
+          end
+          puts "Options may also be passed in the 'RI' environment variable"
+          exit 0
+        end
+      end
+    end
+
+    # Show the version and exit
+    def show_version
+      puts VERSION_STRING
+      exit(0)
+    end
+
+    def initialize
+      @use_stdout   = !STDOUT.tty?
+      @width        = 72
+      @formatter    = RI::TextFormatter.for("plain") 
+      @list_classes = false
+      @list_names   = false
+
+      # By default all paths are used.  If any of these are true, only those
+      # directories are used.
+      @use_system = false
+      @use_site = false
+      @use_home = false
+      @use_gems = false
+      @doc_dirs = []
+    end
+
+    # Parse command line options.
+
+    def parse(args)
+    
+      old_argv = ARGV.dup
+
+      ARGV.replace(args)
+
+      begin
+
+        go = GetoptLong.new(*OptionList.options)
+        go.quiet = true
+
+        go.each do |opt, arg|
+          case opt
+          when "--help"       then OptionList.usage
+          when "--version"    then show_version
+          when "--list-names" then @list_names = true
+          when "--no-pager"   then @use_stdout = true
+          when "--classes"    then @list_classes = true
+
+          when "--system"     then @use_system = true
+          when "--site"       then @use_site = true
+          when "--home"       then @use_home = true
+          when "--gems"       then @use_gems = true
+
+          when "--doc-dir"
+            if File.directory?(arg)
+              @doc_dirs << arg
+            else
+              $stderr.puts "Invalid directory: #{arg}"
+              exit 1
+            end
+
+          when "--format"
+            @formatter = RI::TextFormatter.for(arg)
+            unless @formatter
+              $stderr.print "Invalid formatter (should be one of "
+              $stderr.puts RI::TextFormatter.list + ")"
+              exit 1
+            end
+          when "--width"
+            begin
+              @width = Integer(arg)
+            rescue 
+              $stderr.puts "Invalid width: '#{arg}'"
+              exit 1
+            end
+          end
+        end
+
+      rescue GetoptLong::InvalidOption, GetoptLong::MissingArgument => error
+        OptionList.error(error.message)
+
+      end
+    end
+
+    # Return the selected documentation directories.
+
+    def path
+      RI::Paths.path(@use_system, @use_site, @use_home, @use_gems, *@doc_dirs)
+    end
+
+    def raw_path
+      RI::Paths.raw_path(@use_system, @use_site, @use_home, @use_gems,
+                         *@doc_dirs)
+    end
+
+    # Return an instance of the displayer (the thing that actually writes
+    # the information). This allows us to load in new displayer classes
+    # at runtime (for example to help with IDE integration)
+    
+    def displayer
+      ::RiDisplay.new(self)
+    end
+  end
+
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_paths.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_paths.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_paths.rb	(revision 18425)
@@ -0,0 +1,80 @@
+module RI
+
+  # Encapsulate all the strangeness to do with finding out
+  # where to find RDoc files
+  #
+  # We basically deal with three directories:
+  #
+  # 1. The 'system' documentation directory, which holds
+  #    the documentation distributed with Ruby, and which
+  #    is managed by the Ruby install process
+  # 2. The 'site' directory, which contains site-wide
+  #    documentation added locally.
+  # 3. The 'user' documentation directory, stored under the
+  #    user's own home directory.
+  #
+  # There's contention about all this, but for now:
+  #
+  # system:: $datadir/ri/<ver>/system/...
+  # site::   $datadir/ri/<ver>/site/...
+  # user::   ~/.rdoc
+
+  module Paths
+
+    #:stopdoc:
+    require 'rbconfig'
+    
+    DOC_DIR  = "doc/rdoc"
+
+    version = Config::CONFIG['ruby_version']
+
+    base    = File.join(Config::CONFIG['datadir'], "ri", version)
+    SYSDIR  = File.join(base, "system")
+    SITEDIR = File.join(base, "site")
+    homedir = ENV['HOME'] || ENV['USERPROFILE'] || ENV['HOMEPATH']
+
+    if homedir
+      HOMEDIR = File.join(homedir, ".rdoc")
+    else
+      HOMEDIR = nil
+    end
+
+    # This is the search path for 'ri'
+    PATH = [ SYSDIR, SITEDIR, HOMEDIR ].find_all {|p| p && File.directory?(p)}
+
+    begin
+      require 'rubygems'
+      GEMDIRS = Dir["#{Gem.path}/doc/*/ri"]
+      GEMDIRS.each { |path| RI::Paths::PATH << path }
+    rescue LoadError
+      GEMDIRS = nil
+    end
+
+    # Returns the selected documentation directories as an Array, or PATH if no
+    # overriding directories were given.
+
+    def self.path(use_system, use_site, use_home, use_gems, *extra_dirs)
+      path = raw_path(use_system, use_site, use_home, use_gems, *extra_dirs)
+      return path.select { |path| File.directory? path }
+    end
+
+    # Returns the selected documentation directories including nonexistent
+    # directories.  Used to print out what paths were searched if no ri was
+    # found.
+
+    def self.raw_path(use_system, use_site, use_home, use_gems, *extra_dirs)
+      return PATH unless use_system or use_site or use_home or use_gems or
+                         not extra_dirs.empty?
+
+      path = []
+      path << extra_dirs unless extra_dirs.empty?
+      path << RI::Paths::SYSDIR if use_system
+      path << RI::Paths::SITEDIR if use_site
+      path << RI::Paths::HOMEDIR if use_home
+      path << RI::Paths::GEMDIRS if use_gems
+
+      return path.flatten.compact
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_reader.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_reader.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_reader.rb	(revision 18425)
@@ -0,0 +1,100 @@
+require 'rdoc/ri/ri_descriptions'
+require 'rdoc/ri/ri_writer'
+require 'rdoc/markup/simple_markup/to_flow'
+
+module RI
+  class RiReader
+
+    def initialize(ri_cache)
+      @cache = ri_cache
+    end
+
+    def top_level_namespace
+      [ @cache.toplevel ]
+    end
+
+    def lookup_namespace_in(target, namespaces)
+      result = []
+      for n in namespaces
+        result.concat(n.contained_modules_matching(target))
+      end
+      result
+    end
+
+    def find_class_by_name(full_name)
+      names = full_name.split(/::/)
+      ns = @cache.toplevel
+      for name in names
+        ns = ns.contained_class_named(name)
+        return nil if ns.nil?
+      end
+      get_class(ns)
+    end
+
+    def find_methods(name, is_class_method, namespaces)
+      result = []
+      namespaces.each do |ns|
+        result.concat ns.methods_matching(name, is_class_method)
+      end
+      result
+    end
+
+    # return the MethodDescription for a given MethodEntry
+    # by deserializing the YAML
+    def get_method(method_entry)
+      path = method_entry.path_name
+      File.open(path) { |f| RI::Description.deserialize(f) }
+    end
+
+    # Return a class description
+    def get_class(class_entry)
+      result = nil
+      for path in class_entry.path_names
+        path = RiWriter.class_desc_path(path, class_entry)
+        desc = File.open(path) {|f| RI::Description.deserialize(f) }
+        if result
+          result.merge_in(desc)
+        else
+          result = desc
+        end
+      end
+      result
+    end
+
+    # return the names of all classes and modules
+    def full_class_names
+      res = []
+      find_classes_in(res, @cache.toplevel)
+    end
+
+    # return a list of all classes, modules, and methods
+    def all_names
+      res = []
+      find_names_in(res, @cache.toplevel)
+    end
+
+    # ----
+    private
+    # ----
+
+    def find_classes_in(res, klass)
+      classes = klass.classes_and_modules
+      for c in classes
+        res << c.full_name
+        find_classes_in(res, c)
+      end
+      res
+    end
+
+    def find_names_in(res, klass)
+      classes = klass.classes_and_modules
+      for c in classes
+        res << c.full_name
+        res.concat c.all_method_names
+        find_names_in(res, c)
+      end
+      res
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_util.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_util.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_util.rb	(revision 18425)
@@ -0,0 +1,75 @@
+######################################################################
+
+class RiError < Exception; end
+#
+# Break argument into its constituent class or module names, an
+# optional method type, and a method name
+
+class NameDescriptor
+
+  attr_reader :class_names
+  attr_reader :method_name
+
+  # true and false have the obvious meaning. nil means we don't care
+  attr_reader :is_class_method
+
+  # arg may be
+  # 1. a class or module name (optionally qualified with other class
+  #    or module names (Kernel, File::Stat etc)
+  # 2. a method name
+  # 3. a method name qualified by a optionally fully qualified class
+  #    or module name
+  #
+  # We're fairly casual about delimiters: folks can say Kernel::puts,
+  # Kernel.puts, or Kernel\#puts for example. There's one exception:
+  # if you say IO::read, we look for a class method, but if you
+  # say IO.read, we look for an instance method
+
+  def initialize(arg)
+    @class_names = []
+    separator = nil
+
+    tokens = arg.split(/(\.|::|#)/)
+
+    # Skip leading '::', '#' or '.', but remember it might
+    # be a method name qualifier
+    separator = tokens.shift if tokens[0] =~ /^(\.|::|#)/
+
+    # Skip leading '::', but remember we potentially have an inst
+
+    # leading stuff must be class names
+    
+    while tokens[0] =~ /^[A-Z]/
+      @class_names << tokens.shift
+      unless tokens.empty?
+        separator = tokens.shift
+        break unless separator == "::"
+      end
+    end
+    
+    # Now must have a single token, the method name, or an empty
+    # array
+    unless tokens.empty?
+      @method_name = tokens.shift
+      # We may now have a trailing !, ?, or = to roll into
+      # the method name
+      if !tokens.empty? && tokens[0] =~ /^[!?=]$/
+        @method_name << tokens.shift
+      end
+
+      if @method_name =~ /::|\.|#/ or !tokens.empty?
+        raise RiError.new("Bad argument: #{arg}") 
+      end
+      if separator && separator != '.'
+        @is_class_method = separator == "::"
+      end
+    end
+  end
+
+  # Return the full class name (with '::' between the components)
+  # or "" if there's no class name
+
+  def full_class_name
+    @class_names.join("::")
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_writer.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_writer.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/ri/ri_writer.rb	(revision 18425)
@@ -0,0 +1,62 @@
+require 'fileutils'
+
+module RI
+  class RiWriter
+
+    def RiWriter.class_desc_path(dir, class_desc)
+      File.join(dir, "cdesc-" + class_desc.name + ".yaml")
+    end
+
+    
+    # Convert a name from internal form (containing punctuation)
+    # to an external form (where punctuation is replaced
+    # by %xx)
+
+    def RiWriter.internal_to_external(name)
+      name.gsub(/\W/) { sprintf("%%%02x", $&[0]) }
+    end
+
+    # And the reverse operation
+    def RiWriter.external_to_internal(name)
+      name.gsub(/%([0-9a-f]{2,2})/) { $1.to_i(16).chr }
+    end
+
+    def initialize(base_dir)
+      @base_dir = base_dir
+    end
+
+    def remove_class(class_desc)
+      FileUtils.rm_rf(path_to_dir(class_desc.full_name))
+    end
+
+    def add_class(class_desc)
+      dir = path_to_dir(class_desc.full_name)
+      FileUtils.mkdir_p(dir)
+      class_file_name = RiWriter.class_desc_path(dir, class_desc)
+      File.open(class_file_name, "w") do |f|
+        f.write(class_desc.serialize)
+      end
+    end
+
+    def add_method(class_desc, method_desc)
+      dir = path_to_dir(class_desc.full_name)
+      file_name = RiWriter.internal_to_external(method_desc.name)
+      meth_file_name = File.join(dir, file_name)
+      if method_desc.is_singleton
+        meth_file_name += "-c.yaml"
+      else
+        meth_file_name += "-i.yaml"
+      end
+
+      File.open(meth_file_name, "w") do |f|
+        f.write(method_desc.serialize)
+      end
+    end
+
+    private
+
+    def path_to_dir(class_name)
+      File.join(@base_dir, *class_name.split('::'))
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/template.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/template.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/template.rb	(revision 18425)
@@ -0,0 +1,234 @@
+# Cheap-n-cheerful HTML page template system. You create a 
+# template containing:
+#
+# * variable names between percent signs (<tt>%fred%</tt>)
+# * blocks of repeating stuff:
+#
+#     START:key
+#       ... stuff
+#     END:key
+#
+# You feed the code a hash. For simple variables, the values
+# are resolved directly from the hash. For blocks, the hash entry
+# corresponding to +key+ will be an array of hashes. The block will
+# be generated once for each entry. Blocks can be nested arbitrarily
+# deeply.
+#
+# The template may also contain
+#
+#   IF:key
+#     ... stuff
+#   ENDIF:key
+#
+# _stuff_ will only be included in the output if the corresponding
+# key is set in the value hash.
+#
+# Usage:  Given a set of templates <tt>T1, T2,</tt> etc
+#
+#            values = { "name" => "Dave", state => "TX" }
+#
+#            t = TemplatePage.new(T1, T2, T3)
+#            File.open(name, "w") {|f| t.write_html_on(f, values)}
+#         or
+#            res = ''
+#            t.write_html_on(res, values)
+#
+#
+
+class TemplatePage
+
+  ##########
+  # A context holds a stack of key/value pairs (like a symbol
+  # table). When asked to resolve a key, it first searches the top of
+  # the stack, then the next level, and so on until it finds a match
+  # (or runs out of entries)
+
+  class Context
+    def initialize
+      @stack = []
+    end
+
+    def push(hash)
+      @stack.push(hash)
+    end
+
+    def pop
+      @stack.pop
+    end
+
+    # Find a scalar value, throwing an exception if not found. This
+    # method is used when substituting the %xxx% constructs
+
+    def find_scalar(key)
+      @stack.reverse_each do |level|
+        if val = level[key]
+          return val unless val.kind_of? Array
+        end
+      end
+      raise "Template error: can't find variable '#{key}'"
+    end
+
+    # Lookup any key in the stack of hashes
+
+    def lookup(key)
+      @stack.reverse_each do |level|
+        val = level[key]
+        return val if val
+      end
+      nil
+    end
+  end
+
+  #########
+  # Simple class to read lines out of a string
+
+  class LineReader
+    # we're initialized with an array of lines
+    def initialize(lines)
+      @lines = lines
+    end
+
+    # read the next line 
+    def read
+      @lines.shift
+    end
+
+    # Return a list of lines up to the line that matches
+    # a pattern. That last line is discarded.
+    def read_up_to(pattern)
+      res = []
+      while line = read
+        if pattern.match(line)
+          return LineReader.new(res) 
+        else
+          res << line
+        end
+      end
+      raise "Missing end tag in template: #{pattern.source}"
+    end
+
+    # Return a copy of ourselves that can be modified without
+    # affecting us
+    def dup
+      LineReader.new(@lines.dup)
+    end
+  end
+
+
+
+  # +templates+ is an array of strings containing the templates.
+  # We start at the first, and substitute in subsequent ones
+  # where the string <tt>!INCLUDE!</tt> occurs. For example,
+  # we could have the overall page template containing
+  #
+  #   <html><body>
+  #     <h1>Master</h1>
+  #     !INCLUDE!
+  #   </bost></html>
+  #
+  # and substitute subpages in to it by passing [master, sub_page].
+  # This gives us a cheap way of framing pages
+
+  def initialize(*templates)
+    result = "!INCLUDE!"
+    templates.each do |content|
+      result.sub!(/!INCLUDE!/, content)
+    end
+    @lines = LineReader.new(result.split($/))
+  end
+
+  # Render the templates into HTML, storing the result on +op+ 
+  # using the method <tt><<</tt>. The <tt>value_hash</tt> contains
+  # key/value pairs used to drive the substitution (as described above)
+
+  def write_html_on(op, value_hash)
+    @context = Context.new
+    op << substitute_into(@lines, value_hash).tr("\000", '\\')
+  end
+
+
+  # Substitute a set of key/value pairs into the given template. 
+  # Keys with scalar values have them substituted directly into
+  # the page. Those with array values invoke <tt>substitute_array</tt>
+  # (below), which examples a block of the template once for each 
+  # row in the array.
+  #
+  # This routine also copes with the <tt>IF:</tt>_key_ directive,
+  # removing chunks of the template if the corresponding key
+  # does not appear in the hash, and the START: directive, which
+  # loops its contents for each value in an array
+
+  def substitute_into(lines, values)
+    @context.push(values)
+    skip_to = nil
+    result = []
+
+    while line = lines.read
+
+      case line
+
+      when /^IF:(\w+)/
+        lines.read_up_to(/^ENDIF:#$1/) unless @context.lookup($1)
+
+    when /^IFNOT:(\w+)/
+        lines.read_up_to(/^ENDIF:#$1/) if @context.lookup($1)
+
+      when /^ENDIF:/
+        ;
+
+      when /^START:(\w+)/
+        tag = $1
+        body = lines.read_up_to(/^END:#{tag}/)
+        inner_values = @context.lookup(tag)
+        raise "unknown tag: #{tag}" unless inner_values
+        raise "not array: #{tag}"   unless inner_values.kind_of?(Array)
+        inner_values.each do |vals|
+          result << substitute_into(body.dup, vals)
+        end
+      else
+        result << expand_line(line.dup)
+      end
+    end
+
+    @context.pop
+
+    result.join("\n")
+  end
+
+  # Given an individual line, we look for %xxx% constructs and 
+  # HREF:ref:name: constructs, substituting for each.
+
+  def expand_line(line)
+    # Generate a cross reference if a reference is given,
+    # otherwise just fill in the name part
+
+    line.gsub!(/HREF:(\w+?):(\w+?):/) {
+      ref = @context.lookup($1)
+      name = @context.find_scalar($2)
+
+      if ref and !ref.kind_of?(Array)
+	"<a href=\"#{ref}\">#{name}</a>"
+      else
+	name
+      end
+    }
+
+    # Substitute in values for %xxx% constructs.  This is made complex
+    # because the replacement string may contain characters that are
+    # meaningful to the regexp (like \1)
+
+    line = line.gsub(/%([a-zA-Z]\w*)%/) {
+      val = @context.find_scalar($1) 
+      val.tr('\\', "\000")
+    }
+
+
+    line
+  rescue Exception => e
+    $stderr.puts "Error in template: #{e}"
+    $stderr.puts "Original line: #{line}"
+    exit
+  end
+
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/tokenstream.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/tokenstream.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/tokenstream.rb	(revision 18425)
@@ -0,0 +1,25 @@
+# A TokenStream is a list of tokens, gathered during the parse
+# of some entity (say a method). Entities populate these streams
+# by being registered with the lexer. Any class can collect tokens
+# by including TokenStream. From the outside, you use such an object
+# by calling the start_collecting_tokens method, followed by calls
+# to add_token and pop_token
+
+module TokenStream
+  def token_stream
+    @token_stream
+  end
+
+  def start_collecting_tokens
+    @token_stream = []
+  end
+  def add_token(tk)
+    @token_stream << tk
+  end
+  def add_tokens(tks)
+    tks.each  {|tk| add_token(tk)}
+  end
+  def pop_token
+    @token_stream.pop
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/usage.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/usage.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rdoc/usage.rb	(revision 18425)
@@ -0,0 +1,210 @@
+# = Synopsis
+#
+# This library allows command-line tools to encapsulate their usage
+# as a comment at the top of the main file. Calling <tt>RDoc::usage</tt>
+# then displays some or all of that comment, and optionally exits
+# the program with an exit status. We always look for the comment
+# in the main program file, so it is safe to call this method
+# from anywhere in the executing program.
+#
+# = Usage
+#
+#   RDoc::usage( [ exit_status ], [ section, ...])
+#   RDoc::usage_no_exit( [ section, ...])
+#
+# where:
+#
+# exit_status::
+#     the integer exit code (default zero). RDoc::usage will exit
+#     the calling program with this status.
+#
+# section::
+#     an optional list of section names. If specified, only the
+#     sections with the given names as headings will be output.
+#     For example, this section is named 'Usage', and the next
+#     section is named 'Examples'. The section names are case
+#     insensitive.
+#
+# = Examples
+#
+#    # Comment block describing usage
+#    # with (optional) section headings
+#    # . . .
+#
+#    require 'rdoc/usage'
+#
+#    # Display all usage and exit with a status of 0
+#
+#    RDoc::usage
+#
+#    # Display all usage and exit with a status of 99
+#
+#    RDoc::usage(99)
+#
+#    # Display usage in the 'Summary' section only, then
+#    # exit with a status of 99
+#
+#    RDoc::usage(99, 'Summary')
+#
+#    # Display information in the Author and Copyright
+#    # sections, then exit 0.
+#    
+#    RDoc::usage('Author', 'Copyright')
+#
+#    # Display information in the Author and Copyright
+#    # sections, but don't exit
+#  
+#    RDoc::usage_no_exit('Author', 'Copyright')
+#
+# = Author
+#
+# Dave Thomas, The Pragmatic Programmers, LLC
+#
+# = Copyright
+#
+# Copyright (c) 2004 Dave Thomas.
+# Licensed under the same terms as Ruby
+#
+
+require 'rdoc/markup/simple_markup'
+require 'rdoc/markup/simple_markup/to_flow'
+require 'rdoc/ri/ri_formatter'
+require 'rdoc/ri/ri_options'
+
+module RDoc
+
+  # Display usage information from the comment at the top of
+  # the file. String arguments identify specific sections of the
+  # comment to display. An optional integer first argument
+  # specifies the exit status  (defaults to 0)
+
+  def RDoc.usage(*args)
+    exit_code = 0
+
+    if args.size > 0
+      status = args[0]
+      if status.respond_to?(:to_int)
+        exit_code = status.to_int
+        args.shift
+      end
+    end
+
+    # display the usage and exit with the given code
+    usage_no_exit(*args)
+    exit(exit_code)
+  end
+
+  # Display usage
+  def RDoc.usage_no_exit(*args)
+    main_program_file = caller[-1].sub(/:\d+$/, '')
+    comment = File.open(main_program_file) do |file|
+      find_comment(file)
+    end
+
+    comment = comment.gsub(/^\s*#/, '')
+
+    markup = SM::SimpleMarkup.new
+    flow_convertor = SM::ToFlow.new
+    
+    flow = markup.convert(comment, flow_convertor)
+
+    format = "plain"
+
+    unless args.empty?
+      flow = extract_sections(flow, args)
+    end
+
+    options = RI::Options.instance
+    if args = ENV["RI"]
+      options.parse(args.split)
+    end
+    formatter = options.formatter.new(options, "")
+    formatter.display_flow(flow)
+  end
+
+  ######################################################################
+
+  private
+
+  # Find the first comment in the file (that isn't a shebang line)
+  # If the file doesn't start with a comment, report the fact
+  # and return empty string
+
+  def RDoc.gets(file)
+    if (line = file.gets) && (line =~ /^#!/) # shebang
+      throw :exit, find_comment(file)
+    else
+      line
+    end
+  end
+
+  def RDoc.find_comment(file)
+    catch(:exit) do
+      # skip leading blank lines
+      0 while (line = gets(file)) && (line =~ /^\s*$/)
+
+      comment = []
+      while line && line =~ /^\s*#/
+        comment << line
+        line = gets(file)
+      end
+
+      0 while line && (line = gets(file))
+      return no_comment if comment.empty?
+      return comment.join
+    end
+  end
+
+
+  #####
+  # Given an array of flow items and an array of section names, extract those
+  # sections from the flow which have headings corresponding to
+  # a section name in the list. Return them in the order
+  # of names in the +sections+ array.
+
+  def RDoc.extract_sections(flow, sections)
+    result = []
+    sections.each do |name|
+      name = name.downcase
+      copy_upto_level = nil
+
+      flow.each do |item|
+        case item
+        when SM::Flow::H
+          if copy_upto_level && item.level >= copy_upto_level
+            copy_upto_level = nil
+          else
+            if item.text.downcase == name
+              result << item
+              copy_upto_level = item.level
+            end
+          end
+        else
+          if copy_upto_level
+            result << item
+          end
+        end
+      end
+    end
+    if result.empty?
+      puts "Note to developer: requested section(s) [#{sections.join(', ')}] " +
+           "not found"
+      result = flow
+    end
+    result
+  end
+
+  #####
+  # Report the fact that no doc comment count be found
+  def RDoc.no_comment
+    $stderr.puts "No usage information available for this program"
+    ""
+  end
+end
+
+
+if $0 == __FILE__
+
+  RDoc::usage(*ARGV)
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/readbytes.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/readbytes.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/readbytes.rb	(revision 18425)
@@ -0,0 +1,41 @@
+# TruncatedDataError is raised when IO#readbytes fails to read enough data.
+
+class TruncatedDataError<IOError
+  def initialize(mesg, data) # :nodoc:
+    @data = data
+    super(mesg)
+  end
+
+  # The read portion of an IO#readbytes attempt.
+  attr_reader :data
+end
+
+class IO
+  # Reads exactly +n+ bytes.
+  #
+  # If the data read is nil an EOFError is raised.
+  #
+  # If the data read is too short a TruncatedDataError is raised and the read
+  # data is obtainable via its #data method.
+  def readbytes(n)
+    str = read(n)
+    if str == nil
+      raise EOFError, "End of file reached"
+    end
+    if str.size < n
+      raise TruncatedDataError.new("data truncated", str) 
+    end
+    str
+  end
+end
+
+if __FILE__ == $0
+  begin
+    loop do
+      print STDIN.readbytes(6)
+    end
+  rescue TruncatedDataError
+    p $!.data
+    raise
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/resolv-replace.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/resolv-replace.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/resolv-replace.rb	(revision 18425)
@@ -0,0 +1,62 @@
+require 'socket'
+require 'resolv'
+
+class << IPSocket
+  alias original_resolv_getaddress getaddress
+  def getaddress(host)
+    begin
+      return Resolv.getaddress(host).to_s
+    rescue Resolv::ResolvError
+      raise SocketError, "Hostname not known: #{host}"
+    end
+  end
+end
+
+class TCPSocket
+  alias original_resolv_initialize initialize
+  def initialize(host, serv, *rest)
+    rest[0] = IPSocket.getaddress(rest[0]) unless rest.empty?
+    original_resolv_initialize(IPSocket.getaddress(host), serv, *rest)
+  end
+end
+
+class UDPSocket
+  alias original_resolv_bind bind
+  def bind(host, port)
+    original_resolv_bind(IPSocket.getaddress(host), port)
+  end
+
+  alias original_resolv_connect connect
+  def connect(host, port)
+    original_resolv_connect(IPSocket.getaddress(host), port)
+  end
+
+  alias original_resolv_send send
+  def send(mesg, flags, *rest)
+    if rest.length == 2
+      host, port = rest
+      begin
+        addrs = Resolv.getaddresses(host)
+      rescue Resolv::ResolvError
+        raise SocketError, "Hostname not known: #{host}"
+      end
+      err = nil
+      addrs[0...-1].each {|addr|
+        begin
+          return original_resolv_send(mesg, flags, addr, port)
+        rescue SystemCallError
+        end
+      }
+      original_resolv_send(mesg, flags, addrs[-1], port)
+    else
+      original_resolv_send(mesg, flags, *rest)
+    end
+  end
+end
+
+class SOCKSSocket
+  alias original_resolv_initialize initialize
+  def initialize(host, serv)
+    original_resolv_initialize(IPSocket.getaddress(host), port)
+  end
+end if defined? SOCKSSocket
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/resolv.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/resolv.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/resolv.rb	(revision 18425)
@@ -0,0 +1,1884 @@
+=begin
+= resolv library
+resolv.rb is a resolver library written in Ruby.
+Since it is written in Ruby, it is thread-aware.
+I.e. it can resolv many hostnames concurrently.
+
+It is possible to lookup various resources of DNS using DNS module directly.
+
+== example
+  p Resolv.getaddress("www.ruby-lang.org")
+  p Resolv.getname("210.251.121.214")
+
+  Resolv::DNS.open {|dns|
+    p dns.getresources("www.ruby-lang.org", Resolv::DNS::Resource::IN::A).collect {|r| r.address}
+    p dns.getresources("ruby-lang.org", Resolv::DNS::Resource::IN::MX).collect {|r| [r.exchange.to_s, r.preference]}
+  }
+
+== Resolv class
+
+=== class methods
+--- Resolv.getaddress(name)
+--- Resolv.getaddresses(name)
+--- Resolv.each_address(name) {|address| ...}
+    They lookups IP addresses of ((|name|)) which represents a hostname
+    as a string by default resolver.
+
+    getaddress returns first entry of lookupped addresses.
+    getaddresses returns lookupped addresses as an array.
+    each_address iterates over lookupped addresses.
+
+--- Resolv.getname(address)
+--- Resolv.getnames(address)
+--- Resolv.each_name(address) {|name| ...}
+    lookups hostnames of ((|address|)) which represents IP address as a string.
+
+    getname returns first entry of lookupped names.
+    getnames returns lookupped names as an array.
+    each_names iterates over lookupped names.
+
+== Resolv::Hosts class
+hostname resolver using /etc/hosts format.
+
+=== class methods
+--- Resolv::Hosts.new(hosts='/etc/hosts')
+
+=== methods
+--- Resolv::Hosts#getaddress(name)
+--- Resolv::Hosts#getaddresses(name)
+--- Resolv::Hosts#each_address(name) {|address| ...}
+    address lookup methods.
+
+--- Resolv::Hosts#getname(address)
+--- Resolv::Hosts#getnames(address)
+--- Resolv::Hosts#each_name(address) {|name| ...}
+    hostnames lookup methods.
+
+== Resolv::DNS class
+DNS stub resolver.
+
+=== class methods
+--- Resolv::DNS.new(config_info=nil)
+
+    ((|config_info|)) should be nil, a string or a hash.
+    If nil is given, /etc/resolv.conf and platform specific information is used.
+    If a string is given, it should be a filename which format is same as /etc/resolv.conf.
+    If a hash is given, it may contains information for nameserver, search and ndots as follows.
+
+      Resolv::DNS.new({:nameserver=>["210.251.121.21"], :search=>["ruby-lang.org"], :ndots=>1})
+
+--- Resolv::DNS.open(config_info=nil)
+--- Resolv::DNS.open(config_info=nil) {|dns| ...}
+
+=== methods
+--- Resolv::DNS#close
+
+--- Resolv::DNS#getaddress(name)
+--- Resolv::DNS#getaddresses(name)
+--- Resolv::DNS#each_address(name) {|address| ...}
+    address lookup methods.
+
+    ((|name|)) must be a instance of Resolv::DNS::Name or String.  Lookupped
+    address is represented as an instance of Resolv::IPv4 or Resolv::IPv6.
+
+--- Resolv::DNS#getname(address)
+--- Resolv::DNS#getnames(address)
+--- Resolv::DNS#each_name(address) {|name| ...}
+    hostnames lookup methods.
+
+    ((|address|)) must be a instance of Resolv::IPv4, Resolv::IPv6 or String.
+    Lookupped name is represented as an instance of Resolv::DNS::Name.
+
+--- Resolv::DNS#getresource(name, typeclass)
+--- Resolv::DNS#getresources(name, typeclass)
+--- Resolv::DNS#each_resource(name, typeclass) {|resource| ...}
+    They lookup DNS resources of ((|name|)).
+    ((|name|)) must be a instance of Resolv::Name or String.
+
+    ((|typeclass|)) should be one of follows:
+    * Resolv::DNS::Resource::IN::ANY
+    * Resolv::DNS::Resource::IN::NS
+    * Resolv::DNS::Resource::IN::CNAME
+    * Resolv::DNS::Resource::IN::SOA
+    * Resolv::DNS::Resource::IN::HINFO
+    * Resolv::DNS::Resource::IN::MINFO
+    * Resolv::DNS::Resource::IN::MX
+    * Resolv::DNS::Resource::IN::TXT
+    * Resolv::DNS::Resource::IN::ANY
+    * Resolv::DNS::Resource::IN::A
+    * Resolv::DNS::Resource::IN::WKS
+    * Resolv::DNS::Resource::IN::PTR
+    * Resolv::DNS::Resource::IN::AAAA
+
+    Lookupped resource is represented as an instance of (a subclass of)
+    Resolv::DNS::Resource. 
+    (Resolv::DNS::Resource::IN::A, etc.)
+
+== Resolv::DNS::Resource::IN::NS class
+--- name
+== Resolv::DNS::Resource::IN::CNAME class
+--- name
+== Resolv::DNS::Resource::IN::SOA class
+--- mname
+--- rname
+--- serial
+--- refresh
+--- retry
+--- expire
+--- minimum
+== Resolv::DNS::Resource::IN::HINFO class
+--- cpu
+--- os
+== Resolv::DNS::Resource::IN::MINFO class
+--- rmailbx
+--- emailbx
+== Resolv::DNS::Resource::IN::MX class
+--- preference
+--- exchange
+== Resolv::DNS::Resource::IN::TXT class
+--- data
+== Resolv::DNS::Resource::IN::A class
+--- address
+== Resolv::DNS::Resource::IN::WKS class
+--- address
+--- protocol
+--- bitmap
+== Resolv::DNS::Resource::IN::PTR class
+--- name
+== Resolv::DNS::Resource::IN::AAAA class
+--- address
+
+== Resolv::DNS::Name class
+
+=== class methods
+--- Resolv::DNS::Name.create(name)
+
+=== methods
+--- Resolv::DNS::Name#to_s
+
+== Resolv::DNS::Resource class
+
+== Resolv::IPv4 class
+=== class methods
+--- Resolv::IPv4.create(address)
+
+=== methods
+--- Resolv::IPv4#to_s
+--- Resolv::IPv4#to_name
+
+=== constants
+--- Resolv::IPv4::Regex
+    regular expression for IPv4 address.
+
+== Resolv::IPv6 class
+=== class methods
+--- Resolv::IPv6.create(address)
+
+=== methods
+--- Resolv::IPv6#to_s
+--- Resolv::IPv6#to_name
+
+=== constants
+--- Resolv::IPv6::Regex
+    regular expression for IPv6 address.
+
+== Bugs
+* NIS is not supported.
+* /etc/nsswitch.conf is not supported.
+* IPv6 is not supported.
+
+=end
+
+require 'socket'
+require 'fcntl'
+require 'timeout'
+require 'thread'
+
+class Resolv
+  def self.getaddress(name)
+    DefaultResolver.getaddress(name)
+  end
+
+  def self.getaddresses(name)
+    DefaultResolver.getaddresses(name)
+  end
+
+  def self.each_address(name, &block)
+    DefaultResolver.each_address(name, &block)
+  end
+
+  def self.getname(address)
+    DefaultResolver.getname(address)
+  end
+
+  def self.getnames(address)
+    DefaultResolver.getnames(address)
+  end
+
+  def self.each_name(address, &proc)
+    DefaultResolver.each_name(address, &proc)
+  end
+
+  def initialize(resolvers=[Hosts.new, DNS.new])
+    @resolvers = resolvers
+  end
+
+  def getaddress(name)
+    each_address(name) {|address| return address}
+    raise ResolvError.new("no address for #{name}")
+  end
+
+  def getaddresses(name)
+    ret = []
+    each_address(name) {|address| ret << address}
+    return ret
+  end
+
+  def each_address(name)
+    if AddressRegex =~ name
+      yield name
+      return
+    end
+    yielded = false
+    @resolvers.each {|r|
+      r.each_address(name) {|address|
+        yield address.to_s
+        yielded = true
+      }
+      return if yielded
+    }
+  end
+
+  def getname(address)
+    each_name(address) {|name| return name}
+    raise ResolvError.new("no name for #{address}")
+  end
+
+  def getnames(address)
+    ret = []
+    each_name(address) {|name| ret << name}
+    return ret
+  end
+
+  def each_name(address)
+    yielded = false
+    @resolvers.each {|r|
+      r.each_name(address) {|name|
+        yield name.to_s
+        yielded = true
+      }
+      return if yielded
+    }
+  end
+
+  class ResolvError < StandardError
+  end
+
+  class ResolvTimeout < TimeoutError
+  end
+
+  class Hosts
+    if /mswin32|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM
+      require 'win32/resolv'
+      DefaultFileName = Win32::Resolv.get_hosts_path
+    else
+      DefaultFileName = '/etc/hosts'
+    end
+
+    def initialize(filename = DefaultFileName)
+      @filename = filename
+      @mutex = Mutex.new
+      @initialized = nil
+    end
+
+    def lazy_initialize
+      @mutex.synchronize {
+        unless @initialized
+          @name2addr = {}
+          @addr2name = {}
+          open(@filename) {|f|
+            f.each {|line|
+              line.sub!(/#.*/, '')
+              addr, hostname, *aliases = line.split(/\s+/)
+              next unless addr
+              addr.untaint
+              hostname.untaint
+              @addr2name[addr] = [] unless @addr2name.include? addr
+              @addr2name[addr] << hostname
+              @addr2name[addr] += aliases
+              @name2addr[hostname] = [] unless @name2addr.include? hostname
+              @name2addr[hostname] << addr
+              aliases.each {|n|
+                n.untaint
+                @name2addr[n] = [] unless @name2addr.include? n
+                @name2addr[n] << addr
+              }
+            }
+          }
+          @name2addr.each {|name, arr| arr.reverse!}
+          @initialized = true
+        end
+      }
+      self
+    end
+
+    def getaddress(name)
+      each_address(name) {|address| return address}
+      raise ResolvError.new("#{@filename} has no name: #{name}")
+    end
+
+    def getaddresses(name)
+      ret = []
+      each_address(name) {|address| ret << address}
+      return ret
+    end
+
+    def each_address(name, &proc)
+      lazy_initialize
+      if @name2addr.include?(name)
+        @name2addr[name].each(&proc)
+      end
+    end
+
+    def getname(address)
+      each_name(address) {|name| return name}
+      raise ResolvError.new("#{@filename} has no address: #{address}")
+    end
+
+    def getnames(address)
+      ret = []
+      each_name(address) {|name| ret << name}
+      return ret
+    end
+
+    def each_name(address, &proc)
+      lazy_initialize
+      if @addr2name.include?(address)
+        @addr2name[address].each(&proc)
+      end
+    end
+  end
+
+  class DNS
+    # STD0013 (RFC 1035, etc.)
+    # ftp://ftp.isi.edu/in-notes/iana/assignments/dns-parameters
+
+    Port = 53
+    UDPSize = 512
+
+    DNSThreadGroup = ThreadGroup.new
+
+    def self.open(*args)
+      dns = new(*args)
+      return dns unless block_given?
+      begin
+        yield dns
+      ensure
+        dns.close
+      end
+    end
+
+    def initialize(config_info=nil)
+      @mutex = Mutex.new
+      @config = Config.new(config_info)
+      @initialized = nil
+    end
+
+    def lazy_initialize
+      @mutex.synchronize {
+        unless @initialized
+          @config.lazy_initialize
+
+          if nameserver = @config.single?
+            @requester = Requester::ConnectedUDP.new(nameserver)
+          else
+            @requester = Requester::UnconnectedUDP.new
+          end
+
+          @initialized = true
+        end
+      }
+      self
+    end
+
+    def close
+      @mutex.synchronize {
+        if @initialized
+          @requester.close if @requester
+          @requester = nil
+          @initialized = false
+        end
+      }
+    end
+
+    def getaddress(name)
+      each_address(name) {|address| return address}
+      raise ResolvError.new("DNS result has no information for #{name}")
+    end
+
+    def getaddresses(name)
+      ret = []
+      each_address(name) {|address| ret << address}
+      return ret
+    end
+
+    def each_address(name)
+      each_resource(name, Resource::IN::A) {|resource| yield resource.address}
+    end
+
+    def getname(address)
+      each_name(address) {|name| return name}
+      raise ResolvError.new("DNS result has no information for #{address}")
+    end
+
+    def getnames(address)
+      ret = []
+      each_name(address) {|name| ret << name}
+      return ret
+    end
+
+    def each_name(address)
+      case address
+      when Name
+        ptr = address
+      when IPv4::Regex
+        ptr = IPv4.create(address).to_name
+      when IPv6::Regex
+        ptr = IPv6.create(address).to_name
+      else
+        raise ResolvError.new("cannot interpret as address: #{address}")
+      end
+      each_resource(ptr, Resource::IN::PTR) {|resource| yield resource.name}
+    end
+
+    def getresource(name, typeclass)
+      each_resource(name, typeclass) {|resource| return resource}
+      raise ResolvError.new("DNS result has no information for #{name}")
+    end
+
+    def getresources(name, typeclass)
+      ret = []
+      each_resource(name, typeclass) {|resource| ret << resource}
+      return ret
+    end
+
+    def each_resource(name, typeclass, &proc)
+      lazy_initialize
+      q = Queue.new
+      senders = {}
+      begin
+        @config.resolv(name) {|candidate, tout, nameserver|
+          msg = Message.new
+          msg.rd = 1
+          msg.add_question(candidate, typeclass)
+          unless sender = senders[[candidate, nameserver]]
+            sender = senders[[candidate, nameserver]] =
+              @requester.sender(msg, candidate, q, nameserver)
+          end
+          sender.send
+          reply = reply_name = nil
+          timeout(tout, ResolvTimeout) { reply, reply_name = q.pop }
+          case reply.rcode
+          when RCode::NoError
+            extract_resources(reply, reply_name, typeclass, &proc)
+            return
+          when RCode::NXDomain
+            raise Config::NXDomain.new(reply_name.to_s)
+          else
+            raise Config::OtherResolvError.new(reply_name.to_s)
+          end
+        }
+      ensure
+        @requester.delete(q)
+      end
+    end
+
+    def extract_resources(msg, name, typeclass)
+      if typeclass < Resource::ANY
+        n0 = Name.create(name)
+        msg.each_answer {|n, ttl, data|
+          yield data if n0 == n
+        }
+      end
+      yielded = false
+      n0 = Name.create(name)
+      msg.each_answer {|n, ttl, data|
+        if n0 == n
+          case data
+          when typeclass
+            yield data
+            yielded = true
+          when Resource::CNAME
+            n0 = data.name
+          end
+        end
+      }
+      return if yielded
+      msg.each_answer {|n, ttl, data|
+        if n0 == n
+          case data
+          when typeclass
+            yield data
+          end
+        end
+      }
+    end
+
+    class Requester
+      def initialize
+        @senders = {}
+      end
+
+      def close
+        thread, sock, @thread, @sock = @thread, @sock
+        begin
+          if thread
+            thread.kill
+            thread.join
+          end
+        ensure
+          sock.close if sock
+        end
+      end
+
+      def delete(arg)
+        case arg
+        when Sender
+          @senders.delete_if {|k, s| s == arg }
+        when Queue
+          @senders.delete_if {|k, s| s.queue == arg }
+        else
+          raise ArgumentError.new("neither Sender or Queue: #{arg}")
+        end
+      end
+
+      class Sender
+        def initialize(msg, data, sock, queue)
+          @msg = msg
+          @data = data
+          @sock = sock
+          @queue = queue
+        end
+        attr_reader :queue
+
+        def recv(msg)
+          @queue.push([msg, @data])
+        end
+      end
+
+      class UnconnectedUDP < Requester
+        def initialize
+          super()
+          @sock = UDPSocket.new
+          @sock.fcntl(Fcntl::F_SETFD, 1) if defined? Fcntl::F_SETFD
+          @id = {}
+          @id.default = -1
+          @thread = Thread.new {
+            DNSThreadGroup.add Thread.current
+            loop {
+              reply, from = @sock.recvfrom(UDPSize)
+              msg = begin
+                Message.decode(reply)
+              rescue DecodeError
+                STDERR.print("DNS message decoding error: #{reply.inspect}\n")
+                next
+              end
+              if s = @senders[[[from[3],from[1]],msg.id]]
+                s.recv msg
+              else
+                #STDERR.print("non-handled DNS message: #{msg.inspect} from #{from.inspect}\n")
+              end
+            }
+          }
+        end
+
+        def sender(msg, data, queue, host, port=Port)
+          service = [host, port]
+          id = Thread.exclusive {
+            @id[service] = (@id[service] + 1) & 0xffff
+          }
+          request = msg.encode
+          request[0,2] = [id].pack('n')
+          return @senders[[service, id]] =
+            Sender.new(request, data, @sock, host, port, queue)
+        end
+
+        class Sender < Requester::Sender
+          def initialize(msg, data, sock, host, port, queue)
+            super(msg, data, sock, queue)
+            @host = host
+            @port = port
+          end
+
+          def send
+            @sock.send(@msg, 0, @host, @port)
+          end
+        end
+      end
+
+      class ConnectedUDP < Requester
+        def initialize(host, port=Port)
+          super()
+          @host = host
+          @port = port
+          @sock = UDPSocket.new(host.index(':') ? Socket::AF_INET6 : Socket::AF_INET)
+          @sock.connect(host, port)
+          @sock.fcntl(Fcntl::F_SETFD, 1) if defined? Fcntl::F_SETFD
+          @id = -1
+          @thread = Thread.new {
+            DNSThreadGroup.add Thread.current
+            loop {
+              reply = @sock.recv(UDPSize)
+              msg = begin
+                Message.decode(reply)
+              rescue DecodeError
+                STDERR.print("DNS message decoding error: #{reply.inspect}")
+                next
+              end
+              if s = @senders[msg.id]
+                s.recv msg
+              else
+                #STDERR.print("non-handled DNS message: #{msg.inspect}")
+              end
+            }
+          }
+        end
+
+        def sender(msg, data, queue, host=@host, port=@port)
+          unless host == @host && port == @port
+            raise RequestError.new("host/port don't match: #{host}:#{port}")
+          end
+          id = Thread.exclusive { @id = (@id + 1) & 0xffff }
+          request = msg.encode
+          request[0,2] = [id].pack('n')
+          return @senders[id] = Sender.new(request, data, @sock, queue)
+        end
+
+        class Sender < Requester::Sender
+          def send
+            @sock.send(@msg, 0)
+          end
+        end
+      end
+
+      class TCP < Requester
+        def initialize(host, port=Port)
+          super()
+          @host = host
+          @port = port
+          @sock = TCPSocket.new
+          @sock.connect(host, port)
+          @sock.fcntl(Fcntl::F_SETFD, 1) if defined? Fcntl::F_SETFD
+          @id = -1
+          @senders = {}
+          @thread = Thread.new {
+            DNSThreadGroup.add Thread.current
+            loop {
+              len = @sock.read(2).unpack('n')
+              reply = @sock.read(len)
+              msg = begin
+                Message.decode(reply)
+              rescue DecodeError
+                STDERR.print("DNS message decoding error: #{reply.inspect}")
+                next
+              end
+              if s = @senders[msg.id]
+                s.push msg
+              else
+                #STDERR.print("non-handled DNS message: #{msg.inspect}")
+              end
+            }
+          }
+        end
+
+        def sender(msg, data, queue, host=@host, port=@port)
+          unless host == @host && port == @port
+            raise RequestError.new("host/port don't match: #{host}:#{port}")
+          end
+          id = Thread.exclusive { @id = (@id + 1) & 0xffff }
+          request = msg.encode
+          request[0,2] = [request.length, id].pack('nn')
+          return @senders[id] = Sender.new(request, data, @sock, queue)
+        end
+
+        class Sender < Requester::Sender
+          def send
+            @sock.print(@msg)
+            @sock.flush
+          end
+        end
+      end
+
+      class RequestError < StandardError
+      end
+    end
+
+    class Config
+      def initialize(config_info=nil)
+        @mutex = Mutex.new
+        @config_info = config_info
+        @initialized = nil
+      end
+
+      def Config.parse_resolv_conf(filename)
+        nameserver = []
+        search = nil
+        ndots = 1
+        open(filename) {|f|
+          f.each {|line|
+            line.sub!(/[#;].*/, '')
+            keyword, *args = line.split(/\s+/)
+            args.each { |arg|
+              arg.untaint
+            }
+            next unless keyword
+            case keyword
+            when 'nameserver'
+              nameserver += args
+            when 'domain'
+              next if args.empty?
+              search = [args[0]]
+            when 'search'
+              next if args.empty?
+              search = args
+            when 'options'
+              args.each {|arg|
+                case arg
+                when /\Andots:(\d+)\z/
+                  ndots = $1.to_i
+                end
+              }
+            end
+          }
+        }
+        return { :nameserver => nameserver, :search => search, :ndots => ndots }
+      end
+
+      def Config.default_config_hash(filename="/etc/resolv.conf")
+        if File.exist? filename
+          config_hash = Config.parse_resolv_conf(filename)
+        else
+          if /mswin32|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM
+            search, nameserver = Win32::Resolv.get_resolv_info
+            config_hash = {}
+            config_hash[:nameserver] = nameserver if nameserver
+            config_hash[:search] = [search].flatten if search
+          end
+        end
+        config_hash
+      end
+
+      def lazy_initialize
+        @mutex.synchronize {
+          unless @initialized
+            @nameserver = []
+            @search = nil
+            @ndots = 1
+            case @config_info
+            when nil
+              config_hash = Config.default_config_hash
+            when String
+              config_hash = Config.parse_resolv_conf(@config_info)
+            when Hash
+              config_hash = @config_info.dup
+              if String === config_hash[:nameserver]
+                config_hash[:nameserver] = [config_hash[:nameserver]]
+              end
+              if String === config_hash[:search]
+                config_hash[:search] = [config_hash[:search]]
+              end
+            else
+              raise ArgumentError.new("invalid resolv configuration: #{@config_info.inspect}")
+            end
+            @nameserver = config_hash[:nameserver] if config_hash.include? :nameserver
+            @search = config_hash[:search] if config_hash.include? :search
+            @ndots = config_hash[:ndots] if config_hash.include? :ndots
+
+            @nameserver = ['0.0.0.0'] if @nameserver.empty?
+            if @search
+              @search = @search.map {|arg| Label.split(arg) }
+            else
+              hostname = Socket.gethostname
+              if /\./ =~ hostname
+                @search = [Label.split($')]
+              else
+                @search = [[]]
+              end
+            end
+
+            if !@nameserver.kind_of?(Array) ||
+               !@nameserver.all? {|ns| String === ns }
+              raise ArgumentError.new("invalid nameserver config: #{@nameserver.inspect}")
+            end
+
+            if !@search.kind_of?(Array) ||
+               !@search.all? {|ls| ls.all? {|l| Label::Str === l } }
+              raise ArgumentError.new("invalid search config: #{@search.inspect}")
+            end
+
+            if !@ndots.kind_of?(Integer)
+              raise ArgumentError.new("invalid ndots config: #{@ndots.inspect}")
+            end
+
+            @initialized = true
+          end
+        }
+        self
+      end
+
+      def single?
+        lazy_initialize
+        if @nameserver.length == 1
+          return @nameserver[0]
+        else
+          return nil
+        end
+      end
+
+      def generate_candidates(name)
+        candidates = nil
+        name = Name.create(name)
+        if name.absolute?
+          candidates = [name]
+        else
+          if @ndots <= name.length - 1
+            candidates = [Name.new(name.to_a)]
+          else
+            candidates = []
+          end
+          candidates.concat(@search.map {|domain| Name.new(name.to_a + domain)})
+        end
+        return candidates
+      end
+
+      InitialTimeout = 5
+
+      def generate_timeouts
+        ts = [InitialTimeout]
+        ts << ts[-1] * 2 / @nameserver.length
+        ts << ts[-1] * 2
+        ts << ts[-1] * 2
+        return ts
+      end
+
+      def resolv(name)
+        candidates = generate_candidates(name)
+        timeouts = generate_timeouts
+        begin
+          candidates.each {|candidate|
+            begin
+              timeouts.each {|tout|
+                @nameserver.each {|nameserver|
+                  begin
+                    yield candidate, tout, nameserver
+                  rescue ResolvTimeout
+                  end
+                }
+              }
+              raise ResolvError.new("DNS resolv timeout: #{name}")
+            rescue NXDomain
+            end
+          }
+        rescue ResolvError
+        end
+      end
+
+      class NXDomain < ResolvError
+      end
+
+      class OtherResolvError < ResolvError
+      end
+    end
+
+    module OpCode
+      Query = 0
+      IQuery = 1
+      Status = 2
+      Notify = 4
+      Update = 5
+    end
+
+    module RCode
+      NoError = 0
+      FormErr = 1
+      ServFail = 2
+      NXDomain = 3
+      NotImp = 4
+      Refused = 5
+      YXDomain = 6
+      YXRRSet = 7
+      NXRRSet = 8
+      NotAuth = 9
+      NotZone = 10
+      BADVERS = 16
+      BADSIG = 16
+      BADKEY = 17
+      BADTIME = 18
+      BADMODE = 19
+      BADNAME = 20
+      BADALG = 21
+    end
+
+    class DecodeError < StandardError
+    end
+
+    class EncodeError < StandardError
+    end
+
+    module Label
+      def self.split(arg)
+        labels = []
+        arg.scan(/[^\.]+/) {labels << Str.new($&)}
+        return labels
+      end
+
+      class Str
+        def initialize(string)
+          @string = string
+          @downcase = string.downcase
+        end
+        attr_reader :string, :downcase
+
+        def to_s
+          return @string
+        end
+
+        def inspect
+          return "#<#{self.class} #{self.to_s}>"
+        end
+
+        def ==(other)
+          return @downcase == other.downcase
+        end
+
+        def eql?(other)
+          return self == other
+        end
+
+        def hash
+          return @downcase.hash
+        end
+      end
+    end
+
+    class Name
+      def self.create(arg)
+        case arg
+        when Name
+          return arg
+        when String
+          return Name.new(Label.split(arg), /\.\z/ =~ arg ? true : false)
+        else
+          raise ArgumentError.new("cannot interpret as DNS name: #{arg.inspect}")
+        end
+      end
+
+      def initialize(labels, absolute=true)
+        @labels = labels
+        @absolute = absolute
+      end
+
+      def inspect
+        "#<#{self.class}: #{self.to_s}#{@absolute ? '.' : ''}>"
+      end
+
+      def absolute?
+        return @absolute
+      end
+
+      def ==(other)
+        return false unless Name === other
+        return @labels == other.to_a && @absolute == other.absolute?
+      end
+      alias eql? ==
+
+      # tests subdomain-of relation.
+      #
+      #   domain = Resolv::DNS::Name.create("y.z")
+      #   p Resolv::DNS::Name.create("w.x.y.z").subdomain_of?(domain) #=> true
+      #   p Resolv::DNS::Name.create("x.y.z").subdomain_of?(domain) #=> true
+      #   p Resolv::DNS::Name.create("y.z").subdomain_of?(domain) #=> false
+      #   p Resolv::DNS::Name.create("z").subdomain_of?(domain) #=> false
+      #   p Resolv::DNS::Name.create("x.y.z.").subdomain_of?(domain) #=> false
+      #   p Resolv::DNS::Name.create("w.z").subdomain_of?(domain) #=> false
+      #
+      def subdomain_of?(other)
+        raise ArgumentError, "not a domain name: #{other.inspect}" unless Name === other
+        return false if @absolute != other.absolute?
+        other_len = other.length
+        return false if @labels.length <= other_len
+        return @labels[-other_len, other_len] == other.to_a
+      end
+
+      def hash
+        return @labels.hash ^ @absolute.hash
+      end
+
+      def to_a
+        return @labels
+      end
+
+      def length
+        return @labels.length
+      end
+
+      def [](i)
+        return @labels[i]
+      end
+
+      # returns the domain name as a string.
+      #
+      # The domain name doesn't have a trailing dot even if the name object is
+      # absolute.
+      #
+      #   p Resolv::DNS::Name.create("x.y.z.").to_s #=> "x.y.z"
+      #   p Resolv::DNS::Name.create("x.y.z").to_s #=> "x.y.z"
+      #
+      def to_s
+        return @labels.join('.')
+      end
+    end
+
+    class Message
+      @@identifier = -1
+
+      def initialize(id = (@@identifier += 1) & 0xffff)
+        @id = id
+        @qr = 0
+        @opcode = 0
+        @aa = 0
+        @tc = 0
+        @rd = 0 # recursion desired
+        @ra = 0 # recursion available
+        @rcode = 0
+        @question = []
+        @answer = []
+        @authority = []
+        @additional = []
+      end
+
+      attr_accessor :id, :qr, :opcode, :aa, :tc, :rd, :ra, :rcode
+      attr_reader :question, :answer, :authority, :additional
+
+      def ==(other)
+        return @id == other.id &&
+               @qr == other.qr &&
+               @opcode == other.opcode &&
+               @aa == other.aa &&
+               @tc == other.tc &&
+               @rd == other.rd &&
+               @ra == other.ra &&
+               @rcode == other.rcode &&
+               @question == other.question &&
+               @answer == other.answer &&
+               @authority == other.authority &&
+               @additional == other.additional
+      end
+
+      def add_question(name, typeclass)
+        @question << [Name.create(name), typeclass]
+      end
+
+      def each_question
+        @question.each {|name, typeclass|
+          yield name, typeclass
+        }
+      end
+
+      def add_answer(name, ttl, data)
+        @answer << [Name.create(name), ttl, data]
+      end
+
+      def each_answer
+        @answer.each {|name, ttl, data|
+          yield name, ttl, data
+        }
+      end
+
+      def add_authority(name, ttl, data)
+        @authority << [Name.create(name), ttl, data]
+      end
+
+      def each_authority
+        @authority.each {|name, ttl, data|
+          yield name, ttl, data
+        }
+      end
+
+      def add_additional(name, ttl, data)
+        @additional << [Name.create(name), ttl, data]
+      end
+
+      def each_additional
+        @additional.each {|name, ttl, data|
+          yield name, ttl, data
+        }
+      end
+
+      def each_resource
+        each_answer {|name, ttl, data| yield name, ttl, data}
+        each_authority {|name, ttl, data| yield name, ttl, data}
+        each_additional {|name, ttl, data| yield name, ttl, data}
+      end
+
+      def encode
+        return MessageEncoder.new {|msg|
+          msg.put_pack('nnnnnn',
+            @id,
+            (@qr & 1) << 15 |
+            (@opcode & 15) << 11 |
+            (@aa & 1) << 10 |
+            (@tc & 1) << 9 |
+            (@rd & 1) << 8 |
+            (@ra & 1) << 7 |
+            (@rcode & 15),
+            @question.length,
+            @answer.length,
+            @authority.length,
+            @additional.length)
+          @question.each {|q|
+            name, typeclass = q
+            msg.put_name(name)
+            msg.put_pack('nn', typeclass::TypeValue, typeclass::ClassValue)
+          }
+          [@answer, @authority, @additional].each {|rr|
+            rr.each {|r|
+              name, ttl, data = r
+              msg.put_name(name)
+              msg.put_pack('nnN', data.class::TypeValue, data.class::ClassValue, ttl)
+              msg.put_length16 {data.encode_rdata(msg)}
+            }
+          }
+        }.to_s
+      end
+
+      class MessageEncoder
+        def initialize
+          @data = ''
+          @names = {}
+          yield self
+        end
+
+        def to_s
+          return @data
+        end
+
+        def put_bytes(d)
+          @data << d
+        end
+
+        def put_pack(template, *d)
+          @data << d.pack(template)
+        end
+
+        def put_length16
+          length_index = @data.length
+          @data << "\0\0"
+          data_start = @data.length
+          yield
+          data_end = @data.length
+          @data[length_index, 2] = [data_end - data_start].pack("n")
+        end
+
+        def put_string(d)
+          self.put_pack("C", d.length)
+          @data << d
+        end
+
+        def put_string_list(ds)
+          ds.each {|d|
+            self.put_string(d)
+          }
+        end
+
+        def put_name(d)
+          put_labels(d.to_a)
+        end
+
+        def put_labels(d)
+          d.each_index {|i|
+            domain = d[i..-1]
+            if idx = @names[domain]
+              self.put_pack("n", 0xc000 | idx)
+              return
+            else
+              @names[domain] = @data.length
+              self.put_label(d[i])
+            end
+          }
+          @data << "\0"
+        end
+
+        def put_label(d)
+          self.put_string(d.string)
+        end
+      end
+
+      def Message.decode(m)
+        o = Message.new(0)
+        MessageDecoder.new(m) {|msg|
+          id, flag, qdcount, ancount, nscount, arcount =
+            msg.get_unpack('nnnnnn')
+          o.id = id
+          o.qr = (flag >> 15) & 1
+          o.opcode = (flag >> 11) & 15
+          o.aa = (flag >> 10) & 1
+          o.tc = (flag >> 9) & 1
+          o.rd = (flag >> 8) & 1
+          o.ra = (flag >> 7) & 1
+          o.rcode = flag & 15
+          (1..qdcount).each {
+            name, typeclass = msg.get_question
+            o.add_question(name, typeclass)
+          }
+          (1..ancount).each {
+            name, ttl, data = msg.get_rr
+            o.add_answer(name, ttl, data)
+          }
+          (1..nscount).each {
+            name, ttl, data = msg.get_rr
+            o.add_authority(name, ttl, data)
+          }
+          (1..arcount).each {
+            name, ttl, data = msg.get_rr
+            o.add_additional(name, ttl, data)
+          }
+        }
+        return o
+      end
+
+      class MessageDecoder
+        def initialize(data)
+          @data = data
+          @index = 0
+          @limit = data.length
+          yield self
+        end
+
+        def get_length16
+          len, = self.get_unpack('n')
+          save_limit = @limit
+          @limit = @index + len
+          d = yield(len)
+          if @index < @limit
+            raise DecodeError.new("junk exists")
+          elsif @limit < @index
+            raise DecodeError.new("limit exceeded")
+          end
+          @limit = save_limit
+          return d
+        end
+
+        def get_bytes(len = @limit - @index)
+          d = @data[@index, len]
+          @index += len
+          return d
+        end
+
+        def get_unpack(template)
+          len = 0
+          template.each_byte {|byte|
+            case byte
+            when ?c, ?C
+              len += 1
+            when ?n
+              len += 2
+            when ?N
+              len += 4
+            else
+              raise StandardError.new("unsupported template: '#{byte.chr}' in '#{template}'")
+            end
+          }
+          raise DecodeError.new("limit exceeded") if @limit < @index + len
+          arr = @data.unpack("@#{@index}#{template}")
+          @index += len
+          return arr
+        end
+
+        def get_string
+          len = @data[@index]
+          raise DecodeError.new("limit exceeded") if @limit < @index + 1 + len
+          d = @data[@index + 1, len]
+          @index += 1 + len
+          return d
+        end
+
+        def get_string_list
+          strings = []
+          while @index < @limit
+            strings << self.get_string
+          end
+          strings
+        end
+
+        def get_name
+          return Name.new(self.get_labels)
+        end
+
+        def get_labels(limit=nil)
+          limit = @index if !limit || @index < limit
+          d = []
+          while true
+            case @data[@index]
+            when 0
+              @index += 1
+              return d
+            when 192..255
+              idx = self.get_unpack('n')[0] & 0x3fff
+              if limit <= idx
+                raise DecodeError.new("non-backward name pointer")
+              end
+              save_index = @index
+              @index = idx
+              d += self.get_labels(limit)
+              @index = save_index
+              return d
+            else
+              d << self.get_label
+            end
+          end
+          return d
+        end
+
+        def get_label
+          return Label::Str.new(self.get_string)
+        end
+
+        def get_question
+          name = self.get_name
+          type, klass = self.get_unpack("nn")
+          return name, Resource.get_class(type, klass)
+        end
+
+        def get_rr
+          name = self.get_name
+          type, klass, ttl = self.get_unpack('nnN')
+          typeclass = Resource.get_class(type, klass)
+          return name, ttl, self.get_length16 {typeclass.decode_rdata(self)}
+        end
+      end
+    end
+
+    class Query
+      def encode_rdata(msg)
+        raise EncodeError.new("#{self.class} is query.") 
+      end
+
+      def self.decode_rdata(msg)
+        raise DecodeError.new("#{self.class} is query.") 
+      end
+    end
+
+    class Resource < Query
+      ClassHash = {}
+
+      def encode_rdata(msg)
+        raise NotImplementedError.new
+      end
+
+      def self.decode_rdata(msg)
+        raise NotImplementedError.new
+      end
+
+      def ==(other)
+        return self.class == other.class &&
+          self.instance_variables == other.instance_variables &&
+          self.instance_variables.collect {|name| self.instance_eval name} ==
+            other.instance_variables.collect {|name| other.instance_eval name}
+      end
+
+      def eql?(other)
+        return self == other
+      end
+
+      def hash
+        h = 0
+        self.instance_variables.each {|name|
+          h ^= self.instance_eval("#{name}.hash")
+        }
+        return h
+      end
+
+      def self.get_class(type_value, class_value)
+        return ClassHash[[type_value, class_value]] ||
+               Generic.create(type_value, class_value)
+      end
+
+      class Generic < Resource
+        def initialize(data)
+          @data = data
+        end
+        attr_reader :data
+
+        def encode_rdata(msg)
+          msg.put_bytes(data)
+        end
+
+        def self.decode_rdata(msg)
+          return self.new(msg.get_bytes)
+        end
+
+        def self.create(type_value, class_value)
+          c = Class.new(Generic)
+          c.const_set(:TypeValue, type_value)
+          c.const_set(:ClassValue, class_value)
+          Generic.const_set("Type#{type_value}_Class#{class_value}", c)
+          ClassHash[[type_value, class_value]] = c
+          return c
+        end
+      end
+
+      class DomainName < Resource
+        def initialize(name)
+          @name = name
+        end
+        attr_reader :name
+
+        def encode_rdata(msg)
+          msg.put_name(@name)
+        end
+
+        def self.decode_rdata(msg)
+          return self.new(msg.get_name)
+        end
+      end
+
+      # Standard (class generic) RRs
+      ClassValue = nil
+
+      class NS < DomainName
+        TypeValue = 2
+      end
+
+      class CNAME < DomainName
+        TypeValue = 5
+      end
+
+      class SOA < Resource
+        TypeValue = 6
+
+        def initialize(mname, rname, serial, refresh, retry_, expire, minimum)
+          @mname = mname
+          @rname = rname
+          @serial = serial
+          @refresh = refresh
+          @retry = retry_
+          @expire = expire
+          @minimum = minimum
+        end
+        attr_reader :mname, :rname, :serial, :refresh, :retry, :expire, :minimum
+
+        def encode_rdata(msg)
+          msg.put_name(@mname)
+          msg.put_name(@rname)
+          msg.put_pack('NNNNN', @serial, @refresh, @retry, @expire, @minimum)
+        end
+
+        def self.decode_rdata(msg)
+          mname = msg.get_name
+          rname = msg.get_name
+          serial, refresh, retry_, expire, minimum = msg.get_unpack('NNNNN')
+          return self.new(
+            mname, rname, serial, refresh, retry_, expire, minimum)
+        end
+      end
+
+      class PTR < DomainName
+        TypeValue = 12
+      end
+
+      class HINFO < Resource
+        TypeValue = 13
+
+        def initialize(cpu, os)
+          @cpu = cpu
+          @os = os
+        end
+        attr_reader :cpu, :os
+
+        def encode_rdata(msg)
+          msg.put_string(@cpu)
+          msg.put_string(@os)
+        end
+
+        def self.decode_rdata(msg)
+          cpu = msg.get_string
+          os = msg.get_string
+          return self.new(cpu, os)
+        end
+      end
+
+      class MINFO < Resource
+        TypeValue = 14
+
+        def initialize(rmailbx, emailbx)
+          @rmailbx = rmailbx
+          @emailbx = emailbx
+        end
+        attr_reader :rmailbx, :emailbx
+
+        def encode_rdata(msg)
+          msg.put_name(@rmailbx)
+          msg.put_name(@emailbx)
+        end
+
+        def self.decode_rdata(msg)
+          rmailbx = msg.get_string
+          emailbx = msg.get_string
+          return self.new(rmailbx, emailbx)
+        end
+      end
+
+      class MX < Resource
+        TypeValue= 15
+
+        def initialize(preference, exchange)
+          @preference = preference
+          @exchange = exchange
+        end
+        attr_reader :preference, :exchange
+
+        def encode_rdata(msg)
+          msg.put_pack('n', @preference)
+          msg.put_name(@exchange)
+        end
+
+        def self.decode_rdata(msg)
+          preference, = msg.get_unpack('n')
+          exchange = msg.get_name
+          return self.new(preference, exchange)
+        end
+      end
+
+      class TXT < Resource
+        TypeValue = 16
+
+        def initialize(first_string, *rest_strings)
+          @strings = [first_string, *rest_strings]
+        end
+        attr_reader :strings
+
+        def data
+          @strings[0]
+        end
+
+        def encode_rdata(msg)
+          msg.put_string_list(@strings)
+        end
+
+        def self.decode_rdata(msg)
+          strings = msg.get_string_list
+          return self.new(*strings)
+        end
+      end
+
+      class ANY < Query
+        TypeValue = 255
+      end
+
+      ClassInsensitiveTypes = [
+        NS, CNAME, SOA, PTR, HINFO, MINFO, MX, TXT, ANY
+      ]
+
+      # ARPA Internet specific RRs
+      module IN
+        ClassValue = 1
+
+        ClassInsensitiveTypes.each {|s|
+          c = Class.new(s)
+          c.const_set(:TypeValue, s::TypeValue)
+          c.const_set(:ClassValue, ClassValue)
+          ClassHash[[s::TypeValue, ClassValue]] = c
+          self.const_set(s.name.sub(/.*::/, ''), c)
+        }
+
+        class A < Resource
+          ClassHash[[TypeValue = 1, ClassValue = ClassValue]] = self
+
+          def initialize(address)
+            @address = IPv4.create(address)
+          end
+          attr_reader :address
+
+          def encode_rdata(msg)
+            msg.put_bytes(@address.address)
+          end
+
+          def self.decode_rdata(msg)
+            return self.new(IPv4.new(msg.get_bytes(4)))
+          end
+        end
+
+        class WKS < Resource
+          ClassHash[[TypeValue = 11, ClassValue = ClassValue]] = self
+
+          def initialize(address, protocol, bitmap)
+            @address = IPv4.create(address)
+            @protocol = protocol
+            @bitmap = bitmap
+          end
+          attr_reader :address, :protocol, :bitmap
+
+          def encode_rdata(msg)
+            msg.put_bytes(@address.address)
+            msg.put_pack("n", @protocol)
+            msg.put_bytes(@bitmap)
+          end
+
+          def self.decode_rdata(msg)
+            address = IPv4.new(msg.get_bytes(4))
+            protocol, = msg.get_unpack("n")
+            bitmap = msg.get_bytes
+            return self.new(address, protocol, bitmap)
+          end
+        end
+
+        class AAAA < Resource
+          ClassHash[[TypeValue = 28, ClassValue = ClassValue]] = self
+
+          def initialize(address)
+            @address = IPv6.create(address)
+          end
+          attr_reader :address
+
+          def encode_rdata(msg)
+            msg.put_bytes(@address.address)
+          end
+
+          def self.decode_rdata(msg)
+            return self.new(IPv6.new(msg.get_bytes(16)))
+          end
+        end
+
+        # SRV resource record defined in RFC 2782
+        # 
+        # These records identify the hostname and port that a service is
+        # available at.
+        # 
+        # The format is:
+        #   _Service._Proto.Name TTL Class SRV Priority Weight Port Target
+        #
+        # The fields specific to SRV are defined in RFC 2782 as meaning:
+        # - +priority+ The priority of this target host.  A client MUST attempt
+        #   to contact the target host with the lowest-numbered priority it can
+        #   reach; target hosts with the same priority SHOULD be tried in an
+        #   order defined by the weight field.  The range is 0-65535.  Note that
+        #   it is not widely implemented and should be set to zero.
+        # 
+        # - +weight+ A server selection mechanism.  The weight field specifies
+        #   a relative weight for entries with the same priority. Larger weights
+        #   SHOULD be given a proportionately higher probability of being
+        #   selected. The range of this number is 0-65535.  Domain administrators
+        #   SHOULD use Weight 0 when there isn't any server selection to do, to
+        #   make the RR easier to read for humans (less noisy). Note that it is
+        #   not widely implemented and should be set to zero.
+        #
+        # - +port+  The port on this target host of this service.  The range is 0-
+        #   65535.
+        # 
+        # - +target+ The domain name of the target host. A target of "." means
+        #   that the service is decidedly not available at this domain.
+        class SRV < Resource
+          ClassHash[[TypeValue = 33, ClassValue = ClassValue]] = self
+
+          # Create a SRV resource record.
+          def initialize(priority, weight, port, target)
+            @priority = priority.to_int
+            @weight = weight.to_int
+            @port = port.to_int
+            @target = Name.create(target)
+          end
+
+          attr_reader :priority, :weight, :port, :target
+
+          def encode_rdata(msg)
+            msg.put_pack("n", @priority)
+            msg.put_pack("n", @weight)
+            msg.put_pack("n", @port)
+            msg.put_name(@target)
+          end
+
+          def self.decode_rdata(msg)
+            priority, = msg.get_unpack("n")
+            weight,   = msg.get_unpack("n")
+            port,     = msg.get_unpack("n")
+            target    = msg.get_name
+            return self.new(priority, weight, port, target)
+          end
+        end
+
+      end
+    end
+  end
+
+  class IPv4
+    Regex = /\A(\d+)\.(\d+)\.(\d+)\.(\d+)\z/
+
+    def self.create(arg)
+      case arg
+      when IPv4
+        return arg
+      when Regex
+        if (0..255) === (a = $1.to_i) &&
+           (0..255) === (b = $2.to_i) &&
+           (0..255) === (c = $3.to_i) &&
+           (0..255) === (d = $4.to_i)
+          return self.new([a, b, c, d].pack("CCCC"))
+        else
+          raise ArgumentError.new("IPv4 address with invalid value: " + arg)
+        end
+      else
+        raise ArgumentError.new("cannot interpret as IPv4 address: #{arg.inspect}")
+      end
+    end
+
+    def initialize(address)
+      unless address.kind_of?(String) && address.length == 4
+        raise ArgumentError.new('IPv4 address must be 4 bytes')
+      end
+      @address = address
+    end
+    attr_reader :address
+
+    def to_s
+      return sprintf("%d.%d.%d.%d", *@address.unpack("CCCC"))
+    end
+
+    def inspect
+      return "#<#{self.class} #{self.to_s}>"
+    end
+
+    def to_name
+      return DNS::Name.create(
+        '%d.%d.%d.%d.in-addr.arpa.' % @address.unpack('CCCC').reverse)
+    end
+
+    def ==(other)
+      return @address == other.address
+    end
+
+    def eql?(other)
+      return self == other
+    end
+
+    def hash
+      return @address.hash
+    end
+  end
+
+  class IPv6
+    Regex_8Hex = /\A
+      (?:[0-9A-Fa-f]{1,4}:){7}
+         [0-9A-Fa-f]{1,4}
+      \z/x
+
+    Regex_CompressedHex = /\A
+      ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::
+      ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
+      \z/x
+
+    Regex_6Hex4Dec = /\A
+      ((?:[0-9A-Fa-f]{1,4}:){6,6})
+      (\d+)\.(\d+)\.(\d+)\.(\d+)
+      \z/x
+
+    Regex_CompressedHex4Dec = /\A
+      ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::
+      ((?:[0-9A-Fa-f]{1,4}:)*)
+      (\d+)\.(\d+)\.(\d+)\.(\d+)
+      \z/x
+
+    Regex = /
+      (?:#{Regex_8Hex}) |
+      (?:#{Regex_CompressedHex}) |
+      (?:#{Regex_6Hex4Dec}) |
+      (?:#{Regex_CompressedHex4Dec})/x
+
+    def self.create(arg)
+      case arg
+      when IPv6
+        return arg
+      when String
+        address = ''
+        if Regex_8Hex =~ arg
+          arg.scan(/[0-9A-Fa-f]+/) {|hex| address << [hex.hex].pack('n')}
+        elsif Regex_CompressedHex =~ arg
+          prefix = $1
+          suffix = $2
+          a1 = ''
+          a2 = ''
+          prefix.scan(/[0-9A-Fa-f]+/) {|hex| a1 << [hex.hex].pack('n')}
+          suffix.scan(/[0-9A-Fa-f]+/) {|hex| a2 << [hex.hex].pack('n')}
+          omitlen = 16 - a1.length - a2.length
+          address << a1 << "\0" * omitlen << a2
+        elsif Regex_6Hex4Dec =~ arg
+          prefix, a, b, c, d = $1, $2.to_i, $3.to_i, $4.to_i, $5.to_i
+          if (0..255) === a && (0..255) === b && (0..255) === c && (0..255) === d
+            prefix.scan(/[0-9A-Fa-f]+/) {|hex| address << [hex.hex].pack('n')}
+            address << [a, b, c, d].pack('CCCC')
+          else
+            raise ArgumentError.new("not numeric IPv6 address: " + arg)
+          end
+        elsif Regex_CompressedHex4Dec =~ arg
+          prefix, suffix, a, b, c, d = $1, $2, $3.to_i, $4.to_i, $5.to_i, $6.to_i
+          if (0..255) === a && (0..255) === b && (0..255) === c && (0..255) === d
+            a1 = ''
+            a2 = ''
+            prefix.scan(/[0-9A-Fa-f]+/) {|hex| a1 << [hex.hex].pack('n')}
+            suffix.scan(/[0-9A-Fa-f]+/) {|hex| a2 << [hex.hex].pack('n')}
+            omitlen = 12 - a1.length - a2.length
+            address << a1 << "\0" * omitlen << a2 << [a, b, c, d].pack('CCCC')
+          else
+            raise ArgumentError.new("not numeric IPv6 address: " + arg)
+          end
+        else
+          raise ArgumentError.new("not numeric IPv6 address: " + arg)
+        end
+        return IPv6.new(address)
+      else
+        raise ArgumentError.new("cannot interpret as IPv6 address: #{arg.inspect}")
+      end
+    end
+
+    def initialize(address)
+      unless address.kind_of?(String) && address.length == 16
+        raise ArgumentError.new('IPv6 address must be 16 bytes')
+      end
+      @address = address
+    end
+    attr_reader :address
+
+    def to_s
+      address = sprintf("%X:%X:%X:%X:%X:%X:%X:%X", *@address.unpack("nnnnnnnn"))
+      unless address.sub!(/(^|:)0(:0)+(:|$)/, '::')
+        address.sub!(/(^|:)0(:|$)/, '::')
+      end
+      return address
+    end
+
+    def inspect
+      return "#<#{self.class} #{self.to_s}>"
+    end
+
+    def to_name
+      # ip6.arpa should be searched too. [RFC3152]
+      return DNS::Name.new(
+        @address.unpack("H32")[0].split(//).reverse + ['ip6', 'int'])
+    end
+
+    def ==(other)
+      return @address == other.address
+    end
+
+    def eql?(other)
+      return self == other
+    end
+
+    def hash
+      return @address.hash
+    end
+  end
+
+  DefaultResolver = self.new
+  AddressRegex = /(?:#{IPv4::Regex})|(?:#{IPv6::Regex})/
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/attlistdecl.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/attlistdecl.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/attlistdecl.rb	(revision 18425)
@@ -0,0 +1,62 @@
+#vim:ts=2 sw=2 noexpandtab:
+require 'rexml/child'
+require 'rexml/source'
+
+module REXML
+	# This class needs:
+	# * Documentation
+	# * Work!  Not all types of attlists are intelligently parsed, so we just
+	# spew back out what we get in.  This works, but it would be better if
+	# we formatted the output ourselves.
+	#
+	# AttlistDecls provide *just* enough support to allow namespace
+	# declarations.  If you need some sort of generalized support, or have an
+	# interesting idea about how to map the hideous, terrible design of DTD
+	# AttlistDecls onto an intuitive Ruby interface, let me know.  I'm desperate
+	# for anything to make DTDs more palateable.
+	class AttlistDecl < Child
+		include Enumerable
+
+		# What is this?  Got me.
+		attr_reader :element_name
+
+		# Create an AttlistDecl, pulling the information from a Source.  Notice
+		# that this isn't very convenient; to create an AttlistDecl, you basically
+		# have to format it yourself, and then have the initializer parse it.
+		# Sorry, but for the forseeable future, DTD support in REXML is pretty
+		# weak on convenience.  Have I mentioned how much I hate DTDs?
+		def initialize(source)
+			super()
+			if (source.kind_of? Array)
+				@element_name, @pairs, @contents = *source
+			end
+		end
+	
+		# Access the attlist attribute/value pairs.
+		#  value = attlist_decl[ attribute_name ]
+		def [](key)
+			@pairs[key]
+		end
+
+		# Whether an attlist declaration includes the given attribute definition
+		#  if attlist_decl.include? "xmlns:foobar"
+		def include?(key)
+			@pairs.keys.include? key
+		end
+
+		# Itterate over the key/value pairs:
+		#  attlist_decl.each { |attribute_name, attribute_value| ... }
+		def each(&block)
+			@pairs.each(&block)
+		end
+
+		# Write out exactly what we got in.
+		def write out, indent=-1
+			out << @contents
+		end
+
+		def node_type
+			:attlistdecl
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/attribute.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/attribute.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/attribute.rb	(revision 18425)
@@ -0,0 +1,163 @@
+require "rexml/namespace"
+require 'rexml/text'
+
+module REXML
+	# Defines an Element Attribute; IE, a attribute=value pair, as in:
+	# <element attribute="value"/>.  Attributes can be in their own
+	# namespaces.  General users of REXML will not interact with the
+	# Attribute class much.
+	class Attribute
+		include Node
+		include Namespace
+
+		# The element to which this attribute belongs
+		attr_reader :element
+		# The normalized value of this attribute.  That is, the attribute with
+		# entities intact.
+		attr_writer :normalized	
+		PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um
+
+		# Constructor.
+		#
+		#  Attribute.new( attribute_to_clone )
+		#  Attribute.new( source )
+		#  Attribute.new( "attr", "attr_value" )
+		#  Attribute.new( "attr", "attr_value", parent_element )
+		def initialize( first, second=nil, parent=nil )
+			@normalized = @unnormalized = @element = nil
+			if first.kind_of? Attribute
+				self.name = first.expanded_name
+				@value = first.value
+				if second.kind_of? Element
+					@element = second
+				else
+					@element = first.element
+				end
+			elsif first.kind_of? String
+				@element = parent if parent.kind_of? Element
+				self.name = first
+				@value = second.to_s
+			else
+				raise "illegal argument #{first.class.name} to Attribute constructor"
+			end
+		end
+
+		# Returns the namespace of the attribute.
+		# 
+		#  e = Element.new( "elns:myelement" )
+		#  e.add_attribute( "nsa:a", "aval" )
+		#  e.add_attribute( "b", "bval" )
+		#  e.attributes.get_attribute( "a" ).prefix   # -> "nsa"
+		#  e.attributes.get_attribute( "b" ).prefix   # -> "elns"
+		#  a = Attribute.new( "x", "y" )
+		#  a.prefix                                   # -> ""
+		def prefix
+			pf = super
+			if pf == ""
+				pf = @element.prefix if @element
+			end
+			pf
+		end
+
+		# Returns the namespace URL, if defined, or nil otherwise
+		# 
+		#  e = Element.new("el")
+		#  e.add_attributes({"xmlns:ns", "http://url"})
+		#  e.namespace( "ns" )              # -> "http://url"
+		def namespace arg=nil
+			arg = prefix if arg.nil?
+			@element.namespace arg
+		end
+
+		# Returns true if other is an Attribute and has the same name and value,
+		# false otherwise.
+		def ==( other )
+			other.kind_of?(Attribute) and other.name==name and other.value==@value
+		end
+
+		# Creates (and returns) a hash from both the name and value
+		def hash
+			name.hash + value.hash
+		end
+
+		# Returns this attribute out as XML source, expanding the name
+		#
+		#  a = Attribute.new( "x", "y" )
+		#  a.to_string     # -> "x='y'"
+		#  b = Attribute.new( "ns:x", "y" )
+		#  b.to_string     # -> "ns:x='y'"
+		def to_string
+			"#@expanded_name='#{to_s().gsub(/'/, '&apos;')}'"
+		end
+
+		# Returns the attribute value, with entities replaced
+		def to_s
+			return @normalized if @normalized
+
+			doctype = nil
+			if @element
+				doc = @element.document
+				doctype = doc.doctype if doc
+			end
+
+			@unnormalized = nil
+			@normalized = Text::normalize( @value, doctype )
+		end
+
+		# Returns the UNNORMALIZED value of this attribute.  That is, entities
+		# have been expanded to their values
+		def value
+			return @unnormalized if @unnormalized
+			doctype = nil
+			if @element
+				doc = @element.document
+				doctype = doc.doctype if doc
+			end
+			@normalized = nil
+			@unnormalized = Text::unnormalize( @value, doctype )
+		end
+
+		# Returns a copy of this attribute
+		def clone
+			Attribute.new self
+		end
+
+		# Sets the element of which this object is an attribute.  Normally, this
+		# is not directly called.
+		#
+		# Returns this attribute
+		def element=( element )
+			@element = element
+			self
+		end
+
+		# Removes this Attribute from the tree, and returns true if successfull
+		# 
+		# This method is usually not called directly.
+		def remove
+			@element.attributes.delete self.name unless @element.nil?
+		end
+
+		# Writes this attribute (EG, puts 'key="value"' to the output)
+		def write( output, indent=-1 )
+			output << to_string
+		end
+
+    def node_type
+      :attribute
+    end
+
+    def inspect
+      rv = ""
+      write( rv )
+      rv
+    end
+
+    def xpath
+      path = @element.xpath
+      path += "/@#{self.expanded_name}"
+      return path
+    end
+	end
+end
+#vim:ts=2 sw=2 noexpandtab:
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/cdata.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/cdata.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/cdata.rb	(revision 18425)
@@ -0,0 +1,72 @@
+require "rexml/text"
+
+module REXML
+	class CData < Text
+		START = '<![CDATA['
+		STOP = ']]>'
+		ILLEGAL = /(\]\]>)/
+
+		#	Constructor.  CData is data between <![CDATA[ ... ]]>
+		#
+		# _Examples_
+		#  CData.new( source )
+		#  CData.new( "Here is some CDATA" )
+		#  CData.new( "Some unprocessed data", respect_whitespace_TF, parent_element )
+		def initialize( first, whitespace=true, parent=nil )
+			super( first, whitespace, parent, true, true, ILLEGAL )
+		end
+
+		# Make a copy of this object
+		# 
+		# _Examples_
+		#  c = CData.new( "Some text" )
+		#  d = c.clone
+		#  d.to_s        # -> "Some text"
+		def clone
+			CData.new self
+		end
+
+		# Returns the content of this CData object
+		#
+		# _Examples_
+		#  c = CData.new( "Some text" )
+		#  c.to_s        # -> "Some text"
+		def to_s
+			@string
+		end
+
+    def value
+      @string
+    end
+
+		# Generates XML output of this object
+		#
+		# output::
+		#   Where to write the string.  Defaults to $stdout
+		# indent::
+		#   An integer.  If -1, no indenting will be used; otherwise, the
+		#   indentation will be this number of spaces, and children will be
+		#   indented an additional amount.  Defaults to -1.
+		# transitive::
+		#   If transitive is true and indent is >= 0, then the output will be
+		#   pretty-printed in such a way that the added whitespace does not affect
+		#   the absolute *value* of the document -- that is, it leaves the value
+		#   and number of Text nodes in the document unchanged.
+		# ie_hack::
+		#   Internet Explorer is the worst piece of crap to have ever been
+		#   written, with the possible exception of Windows itself.  Since IE is
+		#   unable to parse proper XML, we have to provide a hack to generate XML
+		#   that IE's limited abilities can handle.  This hack inserts a space 
+		#   before the /> on empty tags.
+		#
+		# _Examples_
+		#  c = CData.new( " Some text " )
+		#  c.write( $stdout )     #->  <![CDATA[ Some text ]]>
+		def write( output=$stdout, indent=-1, transitive=false, ie_hack=false )
+      #indent( output, indent ) unless transitive
+			output << START
+			output << @string
+			output << STOP
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/child.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/child.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/child.rb	(revision 18425)
@@ -0,0 +1,96 @@
+require "rexml/node"
+
+module REXML
+	##
+	# A Child object is something contained by a parent, and this class
+	# contains methods to support that.  Most user code will not use this
+	# class directly.
+	class Child
+		include Node
+		attr_reader :parent		# The Parent of this object
+
+		# Constructor.  Any inheritors of this class should call super to make
+		# sure this method is called.
+		# parent::
+		#   if supplied, the parent of this child will be set to the
+		#   supplied value, and self will be added to the parent
+		def initialize( parent = nil )
+			@parent = nil  
+			# Declare @parent, but don't define it.  The next line sets the 
+			# parent.
+			parent.add( self ) if parent
+		end
+
+		# Replaces this object with another object.  Basically, calls
+		# Parent.replace_child
+		#
+		# Returns:: self
+		def replace_with( child )
+			@parent.replace_child( self, child )
+			self
+		end
+
+		# Removes this child from the parent.
+		#
+		# Returns:: self
+		def remove
+			unless @parent.nil?
+				@parent.delete self
+			end
+			self
+		end
+
+		# Sets the parent of this child to the supplied argument.
+		#
+		# other::
+		#   Must be a Parent object.  If this object is the same object as the
+		#   existing parent of this child, no action is taken. Otherwise, this
+		#   child is removed from the current parent (if one exists), and is added
+		#   to the new parent.
+		# Returns:: The parent added
+		def parent=( other )
+			return @parent if @parent == other
+			@parent.delete self if defined? @parent and @parent
+			@parent = other
+		end
+
+		alias :next_sibling :next_sibling_node
+		alias :previous_sibling :previous_sibling_node
+
+		# Sets the next sibling of this child.  This can be used to insert a child
+		# after some other child.
+		#  a = Element.new("a")
+		#  b = a.add_element("b")
+		#  c = Element.new("c")
+		#  b.next_sibling = c
+		#  # => <a><b/><c/></a>
+		def next_sibling=( other )
+		  parent.insert_after self, other
+		end
+
+		# Sets the previous sibling of this child.  This can be used to insert a 
+		# child before some other child.
+		#  a = Element.new("a")
+		#  b = a.add_element("b")
+		#  c = Element.new("c")
+		#  b.previous_sibling = c
+		#  # => <a><b/><c/></a>
+		def previous_sibling=(other)
+		  parent.insert_before self, other
+		end
+
+		# Returns:: the document this child belongs to, or nil if this child
+		# belongs to no document
+		def document
+			return parent.document unless parent.nil?
+			nil
+		end
+
+		# This doesn't yet handle encodings
+		def bytes
+			encoding = document.encoding
+
+			to_s
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/comment.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/comment.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/comment.rb	(revision 18425)
@@ -0,0 +1,76 @@
+require "rexml/child"
+
+module REXML
+	##
+	# Represents an XML comment; that is, text between \<!-- ... -->
+	class Comment < Child
+		include Comparable
+		START = "<!--"
+		STOP = "-->"
+
+		# The content text
+
+		attr_accessor :string
+
+		##
+		# Constructor.  The first argument can be one of three types:
+		# @param first If String, the contents of this comment are set to the 
+		# argument.  If Comment, the argument is duplicated.  If
+		# Source, the argument is scanned for a comment.
+		# @param second If the first argument is a Source, this argument 
+		# should be nil, not supplied, or a Parent to be set as the parent 
+		# of this object
+		def initialize( first, second = nil )
+			#puts "IN COMMENT CONSTRUCTOR; SECOND IS #{second.type}"
+			super(second)
+			if first.kind_of? String
+				@string = first
+			elsif first.kind_of? Comment
+				@string = first.string
+			end
+		end
+
+		def clone
+			Comment.new self
+		end
+
+		# output::
+		#	 Where to write the string
+		# indent::
+		#	 An integer.	If -1, no indenting will be used; otherwise, the
+		#	 indentation will be this number of spaces, and children will be
+		#	 indented an additional amount.
+		# transitive::
+		#	 Ignored by this class.	The contents of comments are never modified.
+		# ie_hack::
+		#	 Needed for conformity to the child API, but not used by this class.
+		def write( output, indent=-1, transitive=false, ie_hack=false )
+			indent( output, indent )
+			output << START
+			output << @string
+			output << STOP
+		end
+
+		alias :to_s :string
+
+		##
+		# Compares this Comment to another; the contents of the comment are used
+		# in the comparison.
+		def <=>(other)
+			other.to_s <=> @string
+		end
+
+		##
+		# Compares this Comment to another; the contents of the comment are used
+		# in the comparison.
+		def ==( other )
+			other.kind_of? Comment and
+			(other <=> self) == 0
+		end
+
+    def node_type
+      :comment
+    end
+	end
+end
+#vim:ts=2 sw=2 noexpandtab:
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/doctype.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/doctype.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/doctype.rb	(revision 18425)
@@ -0,0 +1,278 @@
+require "rexml/parent"
+require "rexml/parseexception"
+require "rexml/namespace"
+require 'rexml/entity'
+require 'rexml/attlistdecl'
+require 'rexml/xmltokens'
+
+module REXML
+  # Represents an XML DOCTYPE declaration; that is, the contents of <!DOCTYPE
+  # ... >.  DOCTYPES can be used to declare the DTD of a document, as well as
+  # being used to declare entities used in the document.
+  class DocType < Parent
+    include XMLTokens
+    START = "<!DOCTYPE"
+    STOP = ">"
+    SYSTEM = "SYSTEM"
+    PUBLIC = "PUBLIC"
+    DEFAULT_ENTITIES = { 
+      'gt'=>EntityConst::GT, 
+      'lt'=>EntityConst::LT, 
+      'quot'=>EntityConst::QUOT, 
+      "apos"=>EntityConst::APOS 
+    }
+
+    # name is the name of the doctype
+    # external_id is the referenced DTD, if given
+    attr_reader :name, :external_id, :entities, :namespaces
+
+    # Constructor
+    #
+    #   dt = DocType.new( 'foo', '-//I/Hate/External/IDs' )
+    #   # <!DOCTYPE foo '-//I/Hate/External/IDs'>
+    #   dt = DocType.new( doctype_to_clone )
+    #   # Incomplete.  Shallow clone of doctype
+    #
+    # +Note+ that the constructor: 
+    #
+    #  Doctype.new( Source.new( "<!DOCTYPE foo 'bar'>" ) )
+    #
+    # is _deprecated_.  Do not use it.  It will probably disappear.
+    def initialize( first, parent=nil )
+      @entities = DEFAULT_ENTITIES
+      @long_name = @uri = nil
+      if first.kind_of? String
+        super()
+        @name = first
+        @external_id = parent
+      elsif first.kind_of? DocType
+        super( parent )
+        @name = first.name
+        @external_id = first.external_id
+      elsif first.kind_of? Array
+        super( parent )
+        @name = first[0]
+        @external_id = first[1]
+        @long_name = first[2]
+        @uri = first[3]
+      elsif first.kind_of? Source
+        super( parent )
+        parser = Parsers::BaseParser.new( first )
+        event = parser.pull
+        if event[0] == :start_doctype
+          @name, @external_id, @long_name, @uri, = event[1..-1]
+        end
+      else
+        super()
+      end
+    end
+
+    def node_type
+      :doctype
+    end
+
+    def attributes_of element
+      rv = []
+      each do |child|
+        child.each do |key,val|
+          rv << Attribute.new(key,val)
+        end if child.kind_of? AttlistDecl and child.element_name == element
+      end
+      rv
+    end
+
+    def attribute_of element, attribute
+      att_decl = find do |child|
+        child.kind_of? AttlistDecl and
+        child.element_name == element and
+        child.include? attribute
+      end
+      return nil unless att_decl
+      att_decl[attribute]
+    end
+
+    def clone
+      DocType.new self
+    end
+
+    # output::
+    #   Where to write the string
+    # indent::
+    #   An integer.  If -1, no indenting will be used; otherwise, the
+    #   indentation will be this number of spaces, and children will be
+    #   indented an additional amount.
+    # transitive::
+    #   If transitive is true and indent is >= 0, then the output will be
+    #   pretty-printed in such a way that the added whitespace does not affect
+    #   the absolute *value* of the document -- that is, it leaves the value
+    #   and number of Text nodes in the document unchanged.
+    # ie_hack::
+    #   Internet Explorer is the worst piece of crap to have ever been
+    #   written, with the possible exception of Windows itself.  Since IE is
+    #   unable to parse proper XML, we have to provide a hack to generate XML
+    #   that IE's limited abilities can handle.  This hack inserts a space 
+    #   before the /> on empty tags.
+    #
+    def write( output, indent=0, transitive=false, ie_hack=false )
+      indent( output, indent )
+      output << START
+      output << ' '
+      output << @name
+      output << " #@external_id" if @external_id
+      output << " #@long_name" if @long_name
+      output << " #@uri" if @uri
+      unless @children.empty?
+        next_indent = indent + 1
+        output << ' ['
+        child = nil    # speed
+        @children.each { |child|
+          output << "\n"
+          child.write( output, next_indent )
+        }
+        #output << '   '*next_indent
+        output << "\n]"
+      end
+      output << STOP
+    end
+
+    def context
+      @parent.context
+    end
+
+    def entity( name )
+      @entities[name].unnormalized if @entities[name]
+    end
+
+    def add child
+      super(child)
+      @entities = DEFAULT_ENTITIES.clone if @entities == DEFAULT_ENTITIES
+      @entities[ child.name ] = child if child.kind_of? Entity
+    end
+    
+    # This method retrieves the public identifier identifying the document's 
+    # DTD.
+    #
+    # Method contributed by Henrik Martensson
+    def public
+      case @external_id
+      when "SYSTEM"
+        nil
+      when "PUBLIC"
+        strip_quotes(@long_name)
+      end
+    end
+    
+    # This method retrieves the system identifier identifying the document's DTD
+    #
+    # Method contributed by Henrik Martensson
+    def system
+      case @external_id
+      when "SYSTEM"
+        strip_quotes(@long_name)
+      when "PUBLIC"
+        @uri.kind_of?(String) ? strip_quotes(@uri) : nil
+      end
+    end
+    
+    # This method returns a list of notations that have been declared in the
+    # _internal_ DTD subset. Notations in the external DTD subset are not 
+    # listed.
+    #
+    # Method contributed by Henrik Martensson
+    def notations
+      children().select {|node| node.kind_of?(REXML::NotationDecl)}
+    end
+    
+    # Retrieves a named notation. Only notations declared in the internal
+    # DTD subset can be retrieved.
+    #
+    # Method contributed by Henrik Martensson
+    def notation(name)
+      notations.find { |notation_decl|
+        notation_decl.name == name
+      }
+    end
+    
+    private
+    
+    # Method contributed by Henrik Martensson
+    def strip_quotes(quoted_string)
+      quoted_string =~ /^[\'\"].*[\ÂŽ\"]$/ ?
+        quoted_string[1, quoted_string.length-2] :
+        quoted_string
+    end
+  end
+
+  # We don't really handle any of these since we're not a validating
+  # parser, so we can be pretty dumb about them.  All we need to be able
+  # to do is spew them back out on a write()
+
+  # This is an abstract class.  You never use this directly; it serves as a
+  # parent class for the specific declarations.
+  class Declaration < Child
+    def initialize src
+      super()
+      @string = src
+    end
+
+    def to_s
+      @string+'>'
+    end
+
+    def write( output, indent )
+      output << ('   '*indent) if indent > 0
+      output << to_s
+    end
+  end
+  
+  public
+  class ElementDecl < Declaration
+    def initialize( src )
+      super
+    end
+  end
+
+  class ExternalEntity < Child
+    def initialize( src )
+      super()
+      @entity = src
+    end
+    def to_s
+      @entity
+    end
+    def write( output, indent )
+      output << @entity
+    end
+  end
+
+  class NotationDecl < Child
+    attr_accessor :public, :system
+    def initialize name, middle, pub, sys
+      super(nil)
+      @name = name
+      @middle = middle
+      @public = pub
+      @system = sys
+    end
+
+    def to_s
+      "<!NOTATION #@name #@middle#{
+        @public ? ' ' + public.inspect : '' 
+      }#{
+        @system ? ' ' +@system.inspect : ''
+      }>"
+    end
+
+    def write( output, indent=-1 )
+      output << ('   '*indent) if indent > 0
+      output << to_s
+    end
+    
+    # This method retrieves the name of the notation.
+    #
+    # Method contributed by Henrik Martensson
+    def name
+      @name
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/document.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/document.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/document.rb	(revision 18425)
@@ -0,0 +1,193 @@
+require "rexml/element"
+require "rexml/xmldecl"
+require "rexml/source"
+require "rexml/comment"
+require "rexml/doctype"
+require "rexml/instruction"
+require "rexml/rexml"
+require "rexml/parseexception"
+require "rexml/output"
+require "rexml/parsers/baseparser"
+require "rexml/parsers/streamparser"
+require "rexml/parsers/treeparser"
+
+module REXML
+  # Represents a full XML document, including PIs, a doctype, etc.  A
+  # Document has a single child that can be accessed by root().
+  # Note that if you want to have an XML declaration written for a document
+  # you create, you must add one; REXML documents do not write a default
+	# declaration for you.  See |DECLARATION| and |write|.
+	class Document < Element
+		# A convenient default XML declaration.  If you want an XML declaration,
+		# the easiest way to add one is mydoc << Document::DECLARATION
+    # +DEPRECATED+
+    # Use: mydoc << XMLDecl.default
+		DECLARATION = XMLDecl.default
+
+		# Constructor
+		# @param source if supplied, must be a Document, String, or IO. 
+		# Documents have their context and Element attributes cloned.
+	  # Strings are expected to be valid XML documents.  IOs are expected
+	  # to be sources of valid XML documents.
+	  # @param context if supplied, contains the context of the document;
+	  # this should be a Hash.
+	  # NOTE that I'm not sure what the context is for; I cloned it out of
+	  # the Electric XML API (in which it also seems to do nothing), and it
+	  # is now legacy.  It may do something, someday... it may disappear.
+		def initialize( source = nil, context = {} )
+			super()
+			@context = context
+			return if source.nil?
+			if source.kind_of? Document
+				@context = source.context
+				super source
+			else
+				build(  source )
+			end
+		end
+
+    def node_type
+      :document
+    end
+
+		# Should be obvious
+		def clone
+			Document.new self
+		end
+
+		# According to the XML spec, a root node has no expanded name
+		def expanded_name
+			''
+			#d = doc_type
+			#d ? d.name : "UNDEFINED"
+		end
+
+		alias :name :expanded_name
+
+		# We override this, because XMLDecls and DocTypes must go at the start
+		# of the document
+		def add( child )
+			if child.kind_of? XMLDecl
+				@children.unshift child
+			elsif child.kind_of? DocType
+        # Find first Element or DocType node and insert the decl right 
+        # before it.  If there is no such node, just insert the child at the
+        # end.  If there is a child and it is an DocType, then replace it.
+        insert_before_index = 0
+        @children.find { |x| 
+          insert_before_index += 1
+          x.kind_of?(Element) || x.kind_of?(DocType)
+        }
+        if @children[ insert_before_index ] # Not null = not end of list
+          if @children[ insert_before_index ].kind_of DocType
+            @children[ insert_before_index ] = child
+          else
+            @children[ index_before_index-1, 0 ] = child
+          end
+        else  # Insert at end of list
+          @children[insert_before_index] = child
+        end
+				child.parent = self
+			else
+				rv = super
+				raise "attempted adding second root element to document" if @elements.size > 1
+				rv
+			end
+		end
+		alias :<< :add
+
+		def add_element(arg=nil, arg2=nil)
+			rv = super
+			raise "attempted adding second root element to document" if @elements.size > 1
+			rv
+		end
+
+		# @return the root Element of the document, or nil if this document
+		# has no children.
+		def root
+      elements[1]
+      #self
+      #@children.find { |item| item.kind_of? Element }
+		end
+
+		# @return the DocType child of the document, if one exists,
+		# and nil otherwise.
+		def doctype
+			@children.find { |item| item.kind_of? DocType }
+		end
+
+		# @return the XMLDecl of this document; if no XMLDecl has been
+		# set, the default declaration is returned.
+		def xml_decl
+			rv = @children[0]
+      return rv if rv.kind_of? XMLDecl
+      rv = @children.unshift(XMLDecl.default)[0]
+		end
+
+		# @return the XMLDecl version of this document as a String.
+		# If no XMLDecl has been set, returns the default version.
+		def version
+			xml_decl().version
+		end
+
+		# @return the XMLDecl encoding of this document as a String.
+		# If no XMLDecl has been set, returns the default encoding.
+		def encoding
+			xml_decl().encoding
+		end
+
+		# @return the XMLDecl standalone value of this document as a String.
+		# If no XMLDecl has been set, returns the default setting.
+		def stand_alone?
+			xml_decl().stand_alone?
+		end
+
+		# Write the XML tree out, optionally with indent.  This writes out the
+		# entire XML document, including XML declarations, doctype declarations,
+		# and processing instructions (if any are given).
+		# A controversial point is whether Document should always write the XML
+		# declaration (<?xml version='1.0'?>) whether or not one is given by the
+		# user (or source document).  REXML does not write one if one was not
+		# specified, because it adds unneccessary bandwidth to applications such
+		# as XML-RPC.
+		#
+		#
+		# output::
+		#	  output an object which supports '<< string'; this is where the
+		#   document will be written.
+		# indent::
+		#   An integer.  If -1, no indenting will be used; otherwise, the
+		#   indentation will be this number of spaces, and children will be
+		#   indented an additional amount.  Defaults to -1
+		# transitive::
+		#   If transitive is true and indent is >= 0, then the output will be
+		#   pretty-printed in such a way that the added whitespace does not affect
+		#   the absolute *value* of the document -- that is, it leaves the value
+		#   and number of Text nodes in the document unchanged.
+		# ie_hack::
+		#   Internet Explorer is the worst piece of crap to have ever been
+		#   written, with the possible exception of Windows itself.  Since IE is
+		#   unable to parse proper XML, we have to provide a hack to generate XML
+		#   that IE's limited abilities can handle.  This hack inserts a space 
+		#   before the /> on empty tags.  Defaults to false
+		def write( output=$stdout, indent=-1, transitive=false, ie_hack=false )
+			output = Output.new( output, xml_decl.encoding ) if xml_decl.encoding != "UTF-8" && !output.kind_of?(Output)
+			@children.each { |node|
+				indent( output, indent ) if node.node_type == :element
+				if node.write( output, indent, transitive, ie_hack )
+          output << "\n" unless indent<0 or node == @children[-1]
+        end
+			}
+		end
+
+		
+		def Document::parse_stream( source, listener )
+			Parsers::StreamParser.new( source, listener ).parse
+		end
+
+		private
+		def build( source )
+      Parsers::TreeParser.new( source, self ).parse
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/attlistdecl.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/attlistdecl.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/attlistdecl.rb	(revision 18425)
@@ -0,0 +1,10 @@
+require "rexml/child"
+module REXML
+	module DTD
+		class AttlistDecl < Child
+			START = "<!ATTLIST"
+			START_RE = /^\s*#{START}/um
+			PATTERN_RE = /\s*(#{START}.*?>)/um
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/dtd.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/dtd.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/dtd.rb	(revision 18425)
@@ -0,0 +1,51 @@
+require "rexml/dtd/elementdecl"
+require "rexml/dtd/entitydecl"
+require "rexml/comment"
+require "rexml/dtd/notationdecl"
+require "rexml/dtd/attlistdecl"
+require "rexml/parent"
+
+module REXML
+	module DTD
+		class Parser
+			def Parser.parse( input )
+				case input
+				when String
+					parse_helper input
+				when File
+					parse_helper input.read
+				end
+			end
+
+			# Takes a String and parses it out
+			def Parser.parse_helper( input )
+				contents = Parent.new
+				while input.size > 0
+					case input
+					when ElementDecl.PATTERN_RE
+						match = $&
+						source = $'
+						contents << EleemntDecl.new( match )
+					when AttlistDecl.PATTERN_RE
+						matchdata = $~
+						source = $'
+						contents << AttlistDecl.new( matchdata )
+					when EntityDecl.PATTERN_RE
+						matchdata = $~
+						source = $'
+						contents << EntityDecl.new( matchdata )
+					when Comment.PATTERN_RE
+						matchdata = $~
+						source = $'
+						contents << Comment.new( matchdata )
+					when NotationDecl.PATTERN_RE
+						matchdata = $~
+						source = $'
+						contents << NotationDecl.new( matchdata )
+					end
+				end
+				contents
+			end
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/elementdecl.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/elementdecl.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/elementdecl.rb	(revision 18425)
@@ -0,0 +1,17 @@
+require "rexml/child"
+module REXML
+	module DTD
+		class ElementDecl < Child
+			START = "<!ELEMENT"
+			START_RE = /^\s*#{START}/um
+			PATTERN_RE = /^\s*(#{START}.*?)>/um
+			PATTERN_RE = /^\s*#{START}\s+((?:[:\w_][-\.\w_]*:)?[-!\*\.\w_]*)(.*?)>/
+			#\s*((((["']).*?\5)|[^\/'">]*)*?)(\/)?>/um, true)
+
+			def initialize match
+				@name = match[1]
+				@rest = match[2]
+			end
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/entitydecl.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/entitydecl.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/entitydecl.rb	(revision 18425)
@@ -0,0 +1,56 @@
+require "rexml/child"
+module REXML
+	module DTD
+		class EntityDecl < Child
+			START = "<!ENTITY"
+			START_RE = /^\s*#{START}/um
+			PUBLIC = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+PUBLIC\s+((["']).*?\3)\s+((["']).*?\5)\s*>/um
+			SYSTEM = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+SYSTEM\s+((["']).*?\3)(?:\s+NDATA\s+\w+)?\s*>/um
+			PLAIN = /^\s*#{START}\s+(\w+)\s+((["']).*?\3)\s*>/um
+			PERCENT = /^\s*#{START}\s+%\s+(\w+)\s+((["']).*?\3)\s*>/um
+			# <!ENTITY name SYSTEM "...">
+			# <!ENTITY name "...">
+			def initialize src
+				super()
+				md = nil
+				if src.match( PUBLIC )
+					md = src.match( PUBLIC, true )
+					@middle = "PUBLIC"
+					@content = "#{md[2]} #{md[4]}"
+				elsif src.match( SYSTEM )
+					md = src.match( SYSTEM, true )
+					@middle = "SYSTEM"
+					@content = md[2]
+				elsif src.match( PLAIN )
+					md = src.match( PLAIN, true )
+					@middle = ""
+					@content = md[2]
+				elsif src.match( PERCENT )
+					md = src.match( PERCENT, true )
+					@middle = ""
+					@content = md[2]
+				end
+				raise ParseException.new("failed Entity match", src) if md.nil?
+				@name = md[1]
+			end
+
+			def to_s
+				rv = "<!ENTITY #@name "
+				rv << "#@middle " if @middle.size > 0
+				rv << @content
+				rv
+			end
+
+			def write( output, indent )
+        indent( output, indent )
+				output << to_s
+			end
+
+			def EntityDecl.parse_source source, listener
+				md = source.match( PATTERN_RE, true )
+				thing = md[0].squeeze(" \t\n\r")
+				listener.send inspect.downcase, thing 
+			end
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/notationdecl.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/notationdecl.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/dtd/notationdecl.rb	(revision 18425)
@@ -0,0 +1,39 @@
+require "rexml/child"
+module REXML
+	module DTD
+		class NotationDecl < Child
+			START = "<!NOTATION"
+			START_RE = /^\s*#{START}/um
+			PUBLIC = /^\s*#{START}\s+(\w[\w-]*)\s+(PUBLIC)\s+((["']).*?\4)\s*>/um
+			SYSTEM = /^\s*#{START}\s+(\w[\w-]*)\s+(SYSTEM)\s+((["']).*?\4)\s*>/um
+			def initialize src
+				super()
+				if src.match( PUBLIC )
+					md = src.match( PUBLIC, true )
+				elsif src.match( SYSTEM )
+					md = src.match( SYSTEM, true )
+				else
+					raise ParseException.new( "error parsing notation: no matching pattern", src )
+				end
+				@name = md[1]
+				@middle = md[2]
+				@rest = md[3]
+			end
+
+			def to_s
+				"<!NOTATION #@name #@middle #@rest>"
+			end
+
+			def write( output, indent )
+        indent( output, indent )
+				output << to_s
+			end
+
+			def NotationDecl.parse_source source, listener
+				md = source.match( PATTERN_RE, true )
+				thing = md[0].squeeze(" \t\n\r")
+				listener.send inspect.downcase, thing 
+			end
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/element.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/element.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/element.rb	(revision 18425)
@@ -0,0 +1,1261 @@
+require "rexml/parent"
+require "rexml/namespace"
+require "rexml/attribute"
+require "rexml/cdata"
+require "rexml/xpath"
+require "rexml/parseexception"
+
+module REXML
+  # An implementation note about namespaces:
+  # As we parse, when we find namespaces we put them in a hash and assign
+  # them a unique ID.  We then convert the namespace prefix for the node
+  # to the unique ID.  This makes namespace lookup much faster for the
+  # cost of extra memory use.  We save the namespace prefix for the
+  # context node and convert it back when we write it.
+  @@namespaces = {}
+
+	# Represents a tagged XML element.  Elements are characterized by
+	# having children, attributes, and names, and can themselves be
+	# children.
+	class Element < Parent
+		include Namespace
+
+		UNDEFINED = "UNDEFINED";		# The default name
+
+		# Mechanisms for accessing attributes and child elements of this
+		# element.
+		attr_reader :attributes, :elements
+		# The context holds information about the processing environment, such as
+		# whitespace handling.
+		attr_accessor :context
+
+		# Constructor
+		# arg:: 
+		# 	if not supplied, will be set to the default value.
+		# 	If a String, the name of this object will be set to the argument.
+		# 	If an Element, the object will be shallowly cloned; name, 
+		# 	attributes, and namespaces will be copied.  Children will +not+ be
+		# 	copied.
+		# parent:: 
+		# 	if supplied, must be a Parent, and will be used as
+		# 	the parent of this object.
+		# context::
+		# 	If supplied, must be a hash containing context items.  Context items
+		# 	include:
+		# * <tt>:respect_whitespace</tt> the value of this is :+all+ or an array of
+		#   strings being the names of the elements to respect
+		#   whitespace for.  Defaults to :+all+.
+		# * <tt>:compress_whitespace</tt> the value can be :+all+ or an array of
+		#   strings being the names of the elements to ignore whitespace on.
+		#   Overrides :+respect_whitespace+.
+		# * <tt>:ignore_whitespace_nodes</tt> the value can be :+all+ or an array
+		#   of strings being the names of the elements in which to ignore
+		#   whitespace-only nodes.  If this is set, Text nodes which contain only
+		#   whitespace will not be added to the document tree.
+		# * <tt>:raw</tt> can be :+all+, or an array of strings being the names of
+		#   the elements to process in raw mode.  In raw mode, special
+		#   characters in text is not converted to or from entities.
+		def initialize( arg = UNDEFINED, parent=nil, context=nil )
+			super(parent)
+
+			@elements = Elements.new(self)
+			@attributes = Attributes.new(self)
+			@context = context
+
+			if arg.kind_of? String
+				self.name = arg
+			elsif arg.kind_of? Element
+				self.name = arg.expanded_name
+				arg.attributes.each_attribute{ |attribute|
+					@attributes << Attribute.new( attribute )
+				}
+				@context = arg.context
+			end
+		end
+
+    def inspect
+      rv = "<#@expanded_name"
+
+      @attributes.each_attribute do |attr|
+        rv << " "
+        attr.write( rv, 0 )
+      end
+
+      if children.size > 0
+        rv << "> ... </>"
+      else
+        rv << "/>"
+      end
+    end
+
+
+		# Creates a shallow copy of self.
+		#   d = Document.new "<a><b/><b/><c><d/></c></a>"
+		#   new_a = d.root.clone
+		#   puts new_a  # => "<a/>"
+		def clone
+			self.class.new self
+		end
+
+		# Evaluates to the root node of the document that this element 
+		# belongs to. If this element doesn't belong to a document, but does
+		# belong to another Element, the parent's root will be returned, until the
+		# earliest ancestor is found.
+    #
+    # Note that this is not the same as the document element.
+    # In the following example, <a> is the document element, and the root
+    # node is the parent node of the document element.  You may ask yourself
+    # why the root node is useful: consider the doctype and XML declaration,
+    # and any processing instructions before the document element... they
+    # are children of the root node, or siblings of the document element.
+    # The only time this isn't true is when an Element is created that is
+    # not part of any Document.  In this case, the ancestor that has no
+    # parent acts as the root node.
+		#  d = Document.new '<a><b><c/></b></a>'
+		#  a = d[1] ; c = a[1][1]
+		#  d.root_node == d   # TRUE
+		#  a.root_node        # namely, d
+		#  c.root_node        # again, d
+		def root_node
+			parent.nil? ? self : parent.root_node
+		end
+
+    def root
+      return elements[1] if self.kind_of? Document
+      return self if parent.kind_of? Document or parent.nil?
+      return parent.root
+    end
+
+		# Evaluates to the document to which this element belongs, or nil if this
+		# element doesn't belong to a document.
+		def document
+      rt = root
+			rt.parent if rt
+		end
+
+		# Evaluates to +true+ if whitespace is respected for this element.  This
+		# is the case if:
+		# 1. Neither :+respect_whitespace+ nor :+compress_whitespace+ has any value
+		# 2. The context has :+respect_whitespace+ set to :+all+ or
+		#    an array containing the name of this element, and 
+    #    :+compress_whitespace+ isn't set to :+all+ or an array containing the 
+    #    name of this element.
+		# The evaluation is tested against +expanded_name+, and so is namespace
+		# sensitive.
+		def whitespace
+			@whitespace = nil
+			if @context
+				if @context[:respect_whitespace]
+					@whitespace = (@context[:respect_whitespace] == :all or
+												 @context[:respect_whitespace].include? expanded_name)
+				end
+				@whitespace = false if (@context[:compress_whitespace] and
+					(@context[:compress_whitespace] == :all or
+					 @context[:compress_whitespace].include? expanded_name)
+				)
+			end
+			@whitespace = true unless @whitespace == false
+			@whitespace
+		end
+
+		def ignore_whitespace_nodes
+			@ignore_whitespace_nodes = false
+			if @context
+				if @context[:ignore_whitespace_nodes]
+					@ignore_whitespace_nodes = 
+						(@context[:ignore_whitespace_nodes] == :all or
+						 @context[:ignore_whitespace_nodes].include? expanded_name)
+				end
+			end
+		end
+
+		# Evaluates to +true+ if raw mode is set for this element.  This
+		# is the case if the context has :+raw+ set to :+all+ or
+		# an array containing the name of this element.
+		#
+		# The evaluation is tested against +expanded_name+, and so is namespace
+		# sensitive.
+		def raw
+			@raw = (@context and @context[:raw] and
+			(@context[:raw] == :all or
+			@context[:raw].include? expanded_name))
+			@raw
+		end
+
+		#once :whitespace, :raw, :ignore_whitespace_nodes
+
+		#################################################
+		# Namespaces                                    #
+		#################################################
+
+		# Evaluates to an +Array+ containing the prefixes (names) of all defined
+		# namespaces at this context node.
+		#  doc = Document.new("<a xmlns:x='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
+		#  doc.elements['//b'].prefixes # -> ['x', 'y']
+		def prefixes
+			prefixes = []
+			prefixes = parent.prefixes if parent
+			prefixes |= attributes.prefixes
+			return prefixes
+		end
+
+		def namespaces
+			namespaces = {}
+			namespaces = parent.namespaces if parent
+			namespaces = namespaces.merge( attributes.namespaces )
+			return namespaces
+		end
+
+		# Evalutas to the URI for a prefix, or the empty string if no such 
+		# namespace is declared for this element. Evaluates recursively for
+		# ancestors.  Returns the default namespace, if there is one.
+		# prefix:: 
+		#   the prefix to search for.  If not supplied, returns the default
+		#   namespace if one exists
+		# Returns:: 
+		#   the namespace URI as a String, or nil if no such namespace
+		#   exists.  If the namespace is undefined, returns an empty string
+		#  doc = Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
+		#  b = doc.elements['//b']
+		#  b.namespace           # -> '1'
+		#  b.namespace("y")      # -> '2'
+		def namespace(prefix=nil)
+			if prefix.nil?
+				prefix = prefix()
+			end
+			if prefix == ''
+				prefix = "xmlns"
+			else
+				prefix = "xmlns:#{prefix}" unless prefix[0,5] == 'xmlns'
+			end
+			ns = attributes[ prefix ]
+			ns = parent.namespace(prefix) if ns.nil? and parent
+			ns = '' if ns.nil? and prefix == 'xmlns'
+			return ns
+		end
+
+		# Adds a namespace to this element.
+		# prefix:: 
+		#   the prefix string, or the namespace URI if +uri+ is not
+		#   supplied
+		# uri::    
+		#   the namespace URI.  May be nil, in which +prefix+ is used as
+		#   the URI
+		# Evaluates to: this Element
+		#  a = Element.new("a")
+		#  a.add_namespace("xmlns:foo", "bar" )
+		#  a.add_namespace("foo", "bar")  # shorthand for previous line
+		#  a.add_namespace("twiddle")
+		#  puts a   #-> <a xmlns:foo='bar' xmlns='twiddle'/>
+		def add_namespace( prefix, uri=nil )
+			unless uri
+				@attributes["xmlns"] = prefix
+			else
+				prefix = "xmlns:#{prefix}" unless prefix =~ /^xmlns:/
+				@attributes[ prefix ] = uri
+			end
+			self
+		end
+
+		# Removes a namespace from this node.  This only works if the namespace is
+		# actually declared in this node.  If no argument is passed, deletes the
+		# default namespace.
+		#
+		# Evaluates to: this element
+		#  doc = Document.new "<a xmlns:foo='bar' xmlns='twiddle'/>"
+		#  doc.root.delete_namespace
+		#  puts doc     # -> <a xmlns:foo='bar'/>
+		#  doc.root.delete_namespace 'foo'
+		#  puts doc     # -> <a/>
+		def delete_namespace namespace="xmlns"
+			namespace = "xmlns:#{namespace}" unless namespace == 'xmlns'
+			attribute = attributes.get_attribute(namespace)
+			attribute.remove unless attribute.nil?
+			self
+		end
+
+		#################################################
+		# Elements                                      #
+		#################################################
+
+		# Adds a child to this element, optionally setting attributes in
+		# the element.
+		# element:: 
+		#   optional.  If Element, the element is added.
+		#   Otherwise, a new Element is constructed with the argument (see
+		#   Element.initialize).
+		# attrs:: 
+		#   If supplied, must be a Hash containing String name,value 
+		#   pairs, which will be used to set the attributes of the new Element.
+		# Returns:: the Element that was added
+		#  el = doc.add_element 'my-tag'
+		#  el = doc.add_element 'my-tag', {'attr1'=>'val1', 'attr2'=>'val2'}
+		#  el = Element.new 'my-tag'
+		#  doc.add_element el
+		def add_element element, attrs=nil
+      raise "First argument must be either an element name, or an Element object" if element.nil?
+			el = @elements.add(element)
+			if attrs.kind_of? Hash
+				attrs.each do |key, value|
+					el.attributes[key]=value if key =~ /^xmlns:/
+				end
+				attrs.each do |key, value|
+					el.attributes[key]=value if key !~ /^xmlns:/
+				end
+			end
+			el
+		end
+
+		# Deletes a child element.
+		# element:: 
+		#   Must be an +Element+, +String+, or +Integer+.  If Element, 
+		#   the element is removed.  If String, the element is found (via XPath) 
+		#   and removed.  <em>This means that any parent can remove any
+		#   descendant.<em>  If Integer, the Element indexed by that number will be
+		#   removed.
+		# Returns:: the element that was removed.
+		#  doc.delete_element "/a/b/c[@id='4']"
+		#  doc.delete_element doc.elements["//k"]
+		#  doc.delete_element 1
+		def delete_element element
+			@elements.delete element
+		end
+
+		# Evaluates to +true+ if this element has at least one child Element
+		#  doc = Document.new "<a><b/><c>Text</c></a>"
+		#  doc.root.has_elements               # -> true
+		#  doc.elements["/a/b"].has_elements   # -> false
+		#  doc.elements["/a/c"].has_elements   # -> false
+		def has_elements?
+			!@elements.empty?
+		end
+
+		# Iterates through the child elements, yielding for each Element that
+		# has a particular attribute set.
+		# key:: 
+		#   the name of the attribute to search for
+		# value:: 
+		#   the value of the attribute
+		# max:: 
+		#   (optional) causes this method to return after yielding 
+		#   for this number of matching children
+		# name:: 
+		#   (optional) if supplied, this is an XPath that filters
+		#   the children to check.
+		#
+		#  doc = Document.new "<a><b @id='1'/><c @id='2'/><d @id='1'/><e/></a>"
+		#  # Yields b, c, d
+		#  doc.root.each_element_with_attribute( 'id' ) {|e| p e}
+		#  # Yields b, d
+		#  doc.root.each_element_with_attribute( 'id', '1' ) {|e| p e}
+		#  # Yields b
+		#  doc.root.each_element_with_attribute( 'id', '1', 1 ) {|e| p e}
+		#  # Yields d
+		#  doc.root.each_element_with_attribute( 'id', '1', 0, 'd' ) {|e| p e}
+		def each_element_with_attribute( key, value=nil, max=0, name=nil, &block ) # :yields: Element
+			each_with_something( proc {|child| 
+				if value.nil?
+					child.attributes[key] != nil
+				else
+					child.attributes[key]==value
+				end
+			}, max, name, &block )
+		end
+
+		# Iterates through the children, yielding for each Element that
+		# has a particular text set.
+		# text:: 
+		#   the text to search for.  If nil, or not supplied, will itterate
+		#   over all +Element+ children that contain at least one +Text+ node.
+		# max:: 
+		#   (optional) causes this method to return after yielding
+		#   for this number of matching children
+		# name:: 
+		#   (optional) if supplied, this is an XPath that filters
+		#   the children to check.
+		#
+		#  doc = Document.new '<a><b>b</b><c>b</c><d>d</d><e/></a>'
+		#  # Yields b, c, d
+		#  doc.each_element_with_text {|e|p e}
+		#  # Yields b, c
+		#  doc.each_element_with_text('b'){|e|p e}
+		#  # Yields b
+		#  doc.each_element_with_text('b', 1){|e|p e}
+		#  # Yields d
+		#  doc.each_element_with_text(nil, 0, 'd'){|e|p e}
+		def each_element_with_text( text=nil, max=0, name=nil, &block ) # :yields: Element
+			each_with_something( proc {|child| 
+				if text.nil?
+					child.has_text?
+				else
+					child.text == text
+				end
+			}, max, name, &block )
+		end
+
+		# Synonym for Element.elements.each
+		def each_element( xpath=nil, &block ) # :yields: Element
+			@elements.each( xpath, &block )
+		end
+
+		# Synonym for Element.to_a
+		# This is a little slower than calling elements.each directly.
+		# xpath:: any XPath by which to search for elements in the tree
+		# Returns:: an array of Elements that match the supplied path
+		def get_elements( xpath )
+			@elements.to_a( xpath )
+		end
+
+		# Returns the next sibling that is an element, or nil if there is
+		# no Element sibling after this one
+		#  doc = Document.new '<a><b/>text<c/></a>'
+		#  doc.root.elements['b'].next_element          #-> <c/>
+		#  doc.root.elements['c'].next_element          #-> nil
+		def next_element
+			element = next_sibling
+			element = element.next_sibling until element.nil? or element.kind_of? Element 
+			return element
+		end
+
+		# Returns the previous sibling that is an element, or nil if there is
+		# no Element sibling prior to this one
+		#  doc = Document.new '<a><b/>text<c/></a>'
+		#  doc.root.elements['c'].previous_element          #-> <b/>
+		#  doc.root.elements['b'].previous_element          #-> nil
+		def previous_element
+			element = previous_sibling
+			element = element.previous_sibling until element.nil? or element.kind_of? Element
+			return element
+		end
+
+
+		#################################################
+		# Text                                          #
+		#################################################
+
+		# Evaluates to +true+ if this element has at least one Text child
+		def has_text?
+			not text().nil?
+		end
+
+		# A convenience method which returns the String value of the _first_
+		# child text element, if one exists, and +nil+ otherwise.
+		#
+		# <em>Note that an element may have multiple Text elements, perhaps
+		# separated by other children</em>.  Be aware that this method only returns
+		# the first Text node.
+		#
+		# This method returns the +value+ of the first text child node, which
+		# ignores the +raw+ setting, so always returns normalized text. See
+		# the Text::value documentation.
+		#
+		#  doc = Document.new "<p>some text <b>this is bold!</b> more text</p>"
+		#  # The element 'p' has two text elements, "some text " and " more text".
+		#  doc.root.text              #-> "some text "
+		def text( path = nil )
+			rv = get_text(path)
+			return rv.value unless rv.nil?
+			nil
+		end
+
+		# Returns the first child Text node, if any, or +nil+ otherwise.
+		# This method returns the actual +Text+ node, rather than the String content.
+		#  doc = Document.new "<p>some text <b>this is bold!</b> more text</p>"
+		#  # The element 'p' has two text elements, "some text " and " more text".
+		#  doc.root.get_text.value            #-> "some text "
+		def get_text path = nil
+			rv = nil
+			if path
+				element = @elements[ path ]
+				rv = element.get_text unless element.nil?
+			else
+				rv = @children.find { |node| node.kind_of? Text }
+			end
+			return rv
+		end
+
+		# Sets the first Text child of this object.  See text() for a
+		# discussion about Text children.
+		#
+		# If a Text child already exists, the child is replaced by this
+		# content.  This means that Text content can be deleted by calling
+		# this method with a nil argument.  In this case, the next Text
+		# child becomes the first Text child.  In no case is the order of
+		# any siblings disturbed.
+		# text:: 
+		#   If a String, a new Text child is created and added to
+		#   this Element as the first Text child.  If Text, the text is set
+		#   as the first Child element.  If nil, then any existing first Text
+		#   child is removed.
+		# Returns:: this Element.
+		#  doc = Document.new '<a><b/></a>'
+		#  doc.root.text = 'Sean'      #-> '<a><b/>Sean</a>'
+		#  doc.root.text = 'Elliott'   #-> '<a><b/>Elliott</a>'
+		#  doc.root.add_element 'c'    #-> '<a><b/>Elliott<c/></a>'
+		#  doc.root.text = 'Russell'   #-> '<a><b/>Russell<c/></a>'
+		#  doc.root.text = nil         #-> '<a><b/><c/></a>'
+    def text=( text )
+      if text.kind_of? String
+        text = Text.new( text, whitespace(), nil, raw() )
+      elsif text and !text.kind_of? Text
+        text = Text.new( text.to_s, whitespace(), nil, raw() )
+      end
+			old_text = get_text
+			if text.nil?
+				old_text.remove unless old_text.nil?
+			else
+				if old_text.nil?
+					self << text
+				else
+					old_text.replace_with( text )
+				end
+			end
+			return self
+		end
+
+		# A helper method to add a Text child.  Actual Text instances can
+		# be added with regular Parent methods, such as add() and <<()
+		# text::
+		#   if a String, a new Text instance is created and added
+		#   to the parent.  If Text, the object is added directly.
+		# Returns:: this Element
+		#  e = Element.new('a')          #-> <e/>
+		#  e.add_text 'foo'              #-> <e>foo</e>
+		#  e.add_text Text.new(' bar')    #-> <e>foo bar</e>
+		# Note that at the end of this example, the branch has <b>3</b> nodes; the 'e'
+		# element and <b>2</b> Text node children.
+		def add_text( text )
+			if text.kind_of? String 
+				if @children[-1].kind_of? Text
+					@children[-1] << text
+					return
+				end
+				text = Text.new( text, whitespace(), nil, raw() )
+			end
+			self << text unless text.nil?
+			return self
+		end
+
+    def node_type
+      :element
+    end
+
+    def xpath
+      path_elements = []
+      cur = self
+      path_elements << __to_xpath_helper( self )
+      while cur.parent
+        cur = cur.parent
+        path_elements << __to_xpath_helper( cur )
+      end
+      return path_elements.reverse.join( "/" )
+    end
+
+		#################################################
+		# Attributes                                    #
+		#################################################
+
+		def attribute( name, namespace=nil )
+			prefix = nil
+      prefix = namespaces.index(namespace) if namespace
+			attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" )
+		end
+
+		# Evaluates to +true+ if this element has any attributes set, false
+		# otherwise.
+		def has_attributes?
+			return !@attributes.empty?
+		end
+
+		# Adds an attribute to this element, overwriting any existing attribute
+		# by the same name.
+		# key::
+		#   can be either an Attribute or a String.  If an Attribute,
+		#   the attribute is added to the list of Element attributes.  If String,
+		#   the argument is used as the name of the new attribute, and the value
+		#   parameter must be supplied.
+		# value:: 
+		#   Required if +key+ is a String, and ignored if the first argument is
+		#   an Attribute.  This is a String, and is used as the value
+		#   of the new Attribute.
+		# Returns:: the Attribute added
+		#  e = Element.new 'e'
+		#  e.add_attribute( 'a', 'b' )               #-> <e a='b'/>
+		#  e.add_attribute( 'x:a', 'c' )             #-> <e a='b' x:a='c'/>
+		#  e.add_attribute Attribute.new('b', 'd')   #-> <e a='b' x:a='c' b='d'/>
+		def add_attribute( key, value=nil )
+			if key.kind_of? Attribute
+				@attributes << key
+			else
+				@attributes[key] = value
+			end
+		end
+
+		# Add multiple attributes to this element.
+		# hash:: is either a hash, or array of arrays
+		#  el.add_attributes( {"name1"=>"value1", "name2"=>"value2"} )
+		#  el.add_attributes( [ ["name1","value1"], ["name2"=>"value2"] ] )
+		def add_attributes hash
+			if hash.kind_of? Hash
+				hash.each_pair {|key, value| @attributes[key] = value }
+			elsif hash.kind_of? Array
+				hash.each { |value| @attributes[ value[0] ] = value[1] }
+			end
+		end
+
+		# Removes an attribute
+		# key::
+		#   either an Attribute or a String.  In either case, the
+		#   attribute is found by matching the attribute name to the argument,
+		#   and then removed.  If no attribute is found, no action is taken.
+		# Returns:: 
+		#   the attribute removed, or nil if this Element did not contain
+		#   a matching attribute
+		#  e = Element.new('E')
+		#  e.add_attribute( 'name', 'Sean' )             #-> <E name='Sean'/>
+		#  r = e.add_attribute( 'sur:name', 'Russell' )  #-> <E name='Sean' sur:name='Russell'/>
+		#  e.delete_attribute( 'name' )                  #-> <E sur:name='Russell'/>
+		#  e.delete_attribute( r )                       #-> <E/>
+		def delete_attribute(key)
+			attr = @attributes.get_attribute(key)
+			attr.remove unless attr.nil?
+		end
+
+		#################################################
+		# Other Utilities                               #
+		#################################################
+
+		# Get an array of all CData children.  
+		# IMMUTABLE
+		def cdatas
+			find_all { |child| child.kind_of? CData }.freeze
+		end
+
+		# Get an array of all Comment children.
+		# IMMUTABLE
+		def comments
+			find_all { |child| child.kind_of? Comment }.freeze
+		end
+
+		# Get an array of all Instruction children.
+		# IMMUTABLE
+		def instructions
+			find_all { |child| child.kind_of? Instruction }.freeze
+		end
+
+		# Get an array of all Text children.
+		# IMMUTABLE
+		def texts
+			find_all { |child| child.kind_of? Text }.freeze
+		end
+
+		# Writes out this element, and recursively, all children.
+		# output::
+		#	  output an object which supports '<< string'; this is where the
+		#   document will be written.
+		# indent::
+		#   An integer.  If -1, no indenting will be used; otherwise, the
+		#   indentation will be this number of spaces, and children will be
+		#   indented an additional amount.  Defaults to -1
+		# transitive::
+		#   If transitive is true and indent is >= 0, then the output will be
+		#   pretty-printed in such a way that the added whitespace does not affect
+		#   the parse tree of the document
+		# ie_hack::
+		#   Internet Explorer is the worst piece of crap to have ever been
+		#   written, with the possible exception of Windows itself.  Since IE is
+		#   unable to parse proper XML, we have to provide a hack to generate XML
+		#   that IE's limited abilities can handle.  This hack inserts a space 
+		#   before the /> on empty tags.  Defaults to false
+		#
+		#  out = ''
+		#  doc.write( out )     #-> doc is written to the string 'out'
+		#  doc.write( $stdout ) #-> doc written to the console
+		def write(writer=$stdout, indent=-1, transitive=false, ie_hack=false)
+			#print "ID:#{indent}"
+			writer << "<#@expanded_name"
+
+			@attributes.each_attribute do |attr|
+				writer << " "
+				attr.write( writer, indent )
+			end unless @attributes.empty?
+
+			if @children.empty?
+        if transitive and indent>-1
+          writer << "\n"
+          indent( writer, indent )
+        elsif ie_hack
+          writer << " " 
+        end
+				writer << "/" 
+			else
+				if transitive and indent>-1 and !@children[0].kind_of? Text
+					writer << "\n"
+					indent writer, indent+1
+				end
+				writer << ">"
+				write_children( writer, indent, transitive, ie_hack )
+				writer << "</#{expanded_name}"
+			end
+			if transitive and indent>-1 and !@children.empty?
+				writer << "\n"
+				indent -= 1 if next_sibling.nil?
+				indent(writer, indent)
+			end
+			writer << ">"
+		end
+
+
+		private
+    def __to_xpath_helper node
+      rv = node.expanded_name.clone
+      if node.parent
+        results = node.parent.find_all {|n| 
+          n.kind_of?(REXML::Element) and n.expanded_name == node.expanded_name 
+        }
+        if results.length > 1
+          idx = results.index( node )
+          rv << "[#{idx+1}]"
+        end
+      end
+      rv
+    end
+
+		# A private helper method
+		def each_with_something( test, max=0, name=nil )
+			num = 0
+			child=nil
+			@elements.each( name ){ |child|
+				yield child if test.call(child) and num += 1
+				return if max>0 and num == max
+			}
+		end
+
+		# A private helper method
+		def write_children( writer, indent, transitive, ie_hack )
+			cr = (indent < 0) ? '' : "\n"
+			if indent == -1
+				each { |child| child.write( writer, indent, transitive, ie_hack ) }
+			else
+				next_indent = indent+1
+				last_child=nil
+				each { |child|
+					unless child.kind_of? Text or last_child.kind_of? Text or transitive
+						writer << cr
+						indent(writer, next_indent)
+					end
+					child.write( writer, next_indent, transitive, ie_hack )
+					last_child = child
+				}
+				unless last_child.kind_of? Text or transitive
+					writer << cr
+					indent( writer, indent )
+				end
+			end
+		end
+	end
+
+	########################################################################
+	# ELEMENTS                                                             #
+	########################################################################
+
+	# A class which provides filtering of children for Elements, and
+	# XPath search support.  You are expected to only encounter this class as
+	# the <tt>element.elements</tt> object.  Therefore, you are 
+	# _not_ expected to instantiate this yourself.
+	class Elements
+		include Enumerable
+		# Constructor
+		# parent:: the parent Element
+		def initialize parent
+			@element = parent
+		end
+
+		# Fetches a child element.  Filters only Element children, regardless of
+		# the XPath match.
+		# index:: 
+		#   the search parameter.  This is either an Integer, which
+		#   will be used to find the index'th child Element, or an XPath,
+		#   which will be used to search for the Element.  <em>Because
+		#   of the nature of XPath searches, any element in the connected XML
+		#   document can be fetched through any other element.</em>  <b>The
+		#   Integer index is 1-based, not 0-based.</b>  This means that the first
+		#   child element is at index 1, not 0, and the +n+th element is at index
+		#   +n+, not <tt>n-1</tt>.  This is because XPath indexes element children
+		#   starting from 1, not 0, and the indexes should be the same.
+		# name:: 
+		#   optional, and only used in the first argument is an
+		#   Integer.  In that case, the index'th child Element that has the
+		#   supplied name will be returned.  Note again that the indexes start at 1.
+		# Returns:: the first matching Element, or nil if no child matched
+		#  doc = Document.new '<a><b/><c id="1"/><c id="2"/><d/></a>'
+		#  doc.root.elements[1]       #-> <b/>
+		#  doc.root.elements['c']     #-> <c id="1"/>
+		#  doc.root.elements[2,'c']   #-> <c id="2"/>
+		def []( index, name=nil)
+			if index.kind_of? Integer
+				raise "index (#{index}) must be >= 1" if index < 1
+				name = literalize(name) if name
+				num = 0
+				child = nil
+				@element.find { |child|
+					child.kind_of? Element and
+					(name.nil? ? true : child.has_name?( name )) and 
+					(num += 1) == index
+				}
+			else
+				return XPath::first( @element, index )
+				#{ |element| 
+				#	return element if element.kind_of? Element
+				#}
+				#return nil
+			end
+		end
+
+		# Sets an element, replacing any previous matching element.  If no
+		# existing element is found ,the element is added.
+		# index:: Used to find a matching element to replace.  See []().
+		# element:: 
+		#   The element to replace the existing element with
+		#   the previous element
+		# Returns:: nil if no previous element was found.
+		#
+		#  doc = Document.new '<a/>'
+		#  doc.root.elements[10] = Element.new('b')    #-> <a><b/></a>
+		#  doc.root.elements[1]                        #-> <b/>
+		#  doc.root.elements[1] = Element.new('c')     #-> <a><c/></a>
+		#  doc.root.elements['c'] = Element.new('d')   #-> <a><d/></a>
+		def []=( index, element )
+			previous = self[index]
+			if previous.nil?
+				@element.add element
+			else
+				previous.replace_with element
+			end
+			return previous
+		end
+
+		# Returns +true+ if there are no +Element+ children, +false+ otherwise
+		def empty?
+			@element.find{ |child| child.kind_of? Element}.nil?
+		end
+
+		# Returns the index of the supplied child (starting at 1), or -1 if 
+		# the element is not a child
+		# element:: an +Element+ child
+		def index element
+			rv = 0
+			found = @element.find do |child| 
+				child.kind_of? Element and
+				(rv += 1) and
+				child == element
+			end
+			return rv if found == element
+			return -1
+		end
+
+		# Deletes a child Element
+		# element:: 
+		#   Either an Element, which is removed directly; an
+		#   xpath, where the first matching child is removed; or an Integer,
+		#   where the n'th Element is removed.
+		# Returns:: the removed child
+		#  doc = Document.new '<a><b/><c/><c id="1"/></a>'
+		#  b = doc.root.elements[1]
+		#  doc.root.elements.delete b           #-> <a><c/><c id="1"/></a>
+		#  doc.elements.delete("a/c[@id='1']")  #-> <a><c/></a>
+		#  doc.root.elements.delete 1           #-> <a/>
+		def delete element
+			if element.kind_of? Element
+				@element.delete element
+			else
+				el = self[element]
+				el.remove if el
+			end
+		end
+
+		# Removes multiple elements.  Filters for Element children, regardless of
+		# XPath matching.
+		# xpath:: all elements matching this String path are removed.
+		# Returns:: an Array of Elements that have been removed
+		#  doc = Document.new '<a><c/><c/><c/><c/></a>'
+		#  deleted = doc.elements.delete_all 'a/c' #-> [<c/>, <c/>, <c/>, <c/>]
+		def delete_all( xpath )
+			rv = []
+			XPath::each( @element, xpath) {|element| 
+				rv << element if element.kind_of? Element
+			}
+			rv.each do |element|
+				@element.delete element
+				element.remove
+			end
+			return rv
+		end
+
+		# Adds an element
+		# element:: 
+		#   if supplied, is either an Element, String, or
+		#   Source (see Element.initialize).  If not supplied or nil, a
+		#   new, default Element will be constructed
+		# Returns:: the added Element
+		#  a = Element.new 'a'
+		#  a.elements.add Element.new 'b'  #-> <a><b/></a>
+		#  a.elements.add 'c'              #-> <a><b/><c/></a>
+		def add element=nil
+			rv = nil
+			if element.nil?
+				Element.new "", self, @element.context
+			elsif not element.kind_of?(Element)
+				Element.new element, self, @element.context
+			else
+				@element << element
+				element.context = @element.context
+				element
+			end
+		end
+
+		alias :<< :add
+
+		# Iterates through all of the child Elements, optionally filtering
+		# them by a given XPath
+		# xpath:: 
+		#   optional.  If supplied, this is a String XPath, and is used to 
+		#   filter the children, so that only matching children are yielded.  Note
+		#   that XPaths are automatically filtered for Elements, so that
+		#   non-Element children will not be yielded
+		#  doc = Document.new '<a><b/><c/><d/>sean<b/><c/><d/></a>'
+		#  doc.root.each {|e|p e}       #-> Yields b, c, d, b, c, d elements
+		#  doc.root.each('b') {|e|p e}  #-> Yields b, b elements
+		#  doc.root.each('child::node()')  {|e|p e}
+		#  #-> Yields <b/>, <c/>, <d/>, <b/>, <c/>, <d/>
+		#  XPath.each(doc.root, 'child::node()', &block)
+		#  #-> Yields <b/>, <c/>, <d/>, sean, <b/>, <c/>, <d/>
+		def each( xpath=nil, &block)
+			XPath::each( @element, xpath ) {|e| yield e if e.kind_of? Element }
+		end
+		
+		def collect( xpath=nil, &block )
+			collection = []
+			XPath::each( @element, xpath ) {|e| 
+				collection << yield(e)  if e.kind_of?(Element) 
+			}
+			collection
+		end
+			
+		def inject( xpath=nil, initial=nil, &block )
+			first = true
+			XPath::each( @element, xpath ) {|e|
+				if (e.kind_of? Element)
+					if (first and initial == nil)
+						initial = e
+						first = false
+					else
+						initial = yield( initial, e ) if e.kind_of? Element
+					end
+				end
+			}
+			initial
+		end
+
+		# Returns the number of +Element+ children of the parent object.
+		#  doc = Document.new '<a>sean<b/>elliott<b/>russell<b/></a>'
+		#  doc.root.size            #-> 6, 3 element and 3 text nodes
+		#  doc.root.elements.size   #-> 3
+		def size
+			count = 0
+			@element.each {|child| count+=1 if child.kind_of? Element }
+			count
+		end
+
+		# Returns an Array of Element children.  An XPath may be supplied to
+		# filter the children.  Only Element children are returned, even if the
+		# supplied XPath matches non-Element children.
+		#  doc = Document.new '<a>sean<b/>elliott<c/></a>'
+		#  doc.root.elements.to_a                  #-> [ <b/>, <c/> ]
+		#  doc.root.elements.to_a("child::node()") #-> [ <b/>, <c/> ] 
+		#  XPath.match(doc.root, "child::node()")  #-> [ sean, <b/>, elliott, <c/> ]
+		def to_a( xpath=nil )
+			rv = XPath.match( @element, xpath )
+			return rv.find_all{|e| e.kind_of? Element} if xpath
+			rv
+		end
+
+		private
+		# Private helper class.  Removes quotes from quoted strings
+		def literalize name
+			name = name[1..-2] if name[0] == ?' or name[0] == ?"               #'
+			name
+		end
+	end
+
+	########################################################################
+	# ATTRIBUTES                                                           #
+	########################################################################
+
+	# A class that defines the set of Attributes of an Element and provides 
+	# operations for accessing elements in that set.
+	class Attributes < Hash
+		# Constructor
+		# element:: the Element of which this is an Attribute
+		def initialize element
+			@element = element
+		end
+
+		# Fetches an attribute value.  If you want to get the Attribute itself,
+		# use get_attribute()
+		# name:: an XPath attribute name.  Namespaces are relevant here.
+		# Returns:: 
+		#   the String value of the matching attribute, or +nil+ if no
+		#   matching attribute was found.
+		# 
+		#  doc = Document.new "<a foo:att='1' bar:att='2' att='3'/>"
+		#  doc.root.attributes['att']         #-> '3'
+		#  doc.root.attributes['bar:att']     #-> '2'
+		def [](name)
+			attr = get_attribute(name)
+			return attr.value unless attr.nil?
+			return nil
+		end
+
+		def to_a
+			values.flatten
+		end
+
+		# Returns the number of attributes the owning Element contains.
+		#  doc = Document "<a x='1' y='2' foo:x='3'/>"
+		#  doc.root.attributes.length        #-> 3
+		def length
+			c = 0
+			each_attribute { c+=1 }
+			c
+		end
+		alias :size :length
+
+		# Itterates over the attributes of an Element.  Yields actual Attribute
+		# nodes, not String values.
+		# 
+		#  doc = Document.new '<a x="1" y="2"/>'
+		#  doc.root.attributes.each_attribute {|attr|
+		#    p attr.expanded_name+" => "+attr.value
+		#  }
+		def each_attribute # :yields: attribute
+			each_value do |val|
+				if val.kind_of? Attribute
+					yield val
+				else
+					val.each_value { |atr| yield atr }
+				end
+			end
+		end
+
+		# Itterates over each attribute of an Element, yielding the expanded name
+		# and value as a pair of Strings.
+		#
+		#  doc = Document.new '<a x="1" y="2"/>'
+		#  doc.root.attributes.each {|name, value| p name+" => "+value }
+		def each
+			each_attribute do |attr|
+				yield attr.expanded_name, attr.value
+			end
+		end
+
+		# Fetches an attribute
+		# name:: 
+		#   the name by which to search for the attribute.  Can be a
+		#   <tt>prefix:name</tt> namespace name.
+		# Returns:: The first matching attribute, or nil if there was none.  This
+		# value is an Attribute node, not the String value of the attribute.
+		#  doc = Document.new '<a x:foo="1" foo="2" bar="3"/>'
+		#  doc.root.attributes.get_attribute("foo").value    #-> "2"
+		#  doc.root.attributes.get_attribute("x:foo").value  #-> "1"
+		def get_attribute( name )
+			attr = fetch( name, nil )
+			if attr.nil?
+				return nil if name.nil?
+				# Look for prefix
+				name =~ Namespace::NAMESPLIT
+				prefix, n = $1, $2
+				if prefix
+					attr = fetch( n, nil )
+					# check prefix
+					if attr == nil
+					elsif attr.kind_of? Attribute
+						return attr if prefix == attr.prefix
+					else
+						attr = attr[ prefix ]
+						return attr
+					end
+				end
+        element_document = @element.document
+				if element_document and element_document.doctype
+					expn = @element.expanded_name
+					expn = element_document.doctype.name if expn.size == 0
+					attr_val = element_document.doctype.attribute_of(expn, name)
+					return Attribute.new( name, attr_val ) if attr_val
+				end
+				return nil
+			end
+			if attr.kind_of? Hash
+				attr = attr[ @element.prefix ]
+			end
+			return attr
+		end
+
+		# Sets an attribute, overwriting any existing attribute value by the
+		# same name.  Namespace is significant.
+		# name:: the name of the attribute
+		# value:: 
+		#   (optional) If supplied, the value of the attribute.  If
+		#   nil, any existing matching attribute is deleted.
+		# Returns:: 
+		#   Owning element
+		#  doc = Document.new "<a x:foo='1' foo='3'/>"
+		#  doc.root.attributes['y:foo'] = '2'
+		#  doc.root.attributes['foo'] = '4'
+		#  doc.root.attributes['x:foo'] = nil
+		def []=( name, value )
+			if value.nil?		# Delete the named attribute
+				attr = get_attribute(name)
+				delete attr
+				return
+			end
+			value = Attribute.new(name, value) unless value.kind_of? Attribute
+			value.element = @element
+			old_attr = fetch(value.name, nil)
+			if old_attr.nil?
+				store(value.name, value)
+			elsif old_attr.kind_of? Hash
+				old_attr[value.prefix] = value
+			elsif old_attr.prefix != value.prefix
+				# Check for conflicting namespaces
+				raise ParseException.new( 
+					"Namespace conflict in adding attribute \"#{value.name}\": "+
+					"Prefix \"#{old_attr.prefix}\" = "+
+					"\"#{@element.namespace(old_attr.prefix)}\" and prefix "+
+					"\"#{value.prefix}\" = \"#{@element.namespace(value.prefix)}\"") if 
+					value.prefix != "xmlns" and old_attr.prefix != "xmlns" and
+					@element.namespace( old_attr.prefix ) == 
+					@element.namespace( value.prefix )
+				store value.name, { old_attr.prefix	=> old_attr,
+														value.prefix		=> value }
+			else
+				store value.name, value
+			end
+			return @element
+		end
+
+		# Returns an array of Strings containing all of the prefixes declared 
+		# by this set of # attributes.  The array does not include the default
+		# namespace declaration, if one exists.
+		#  doc = Document.new("<a xmlns='foo' xmlns:x='bar' xmlns:y='twee' "+
+		#        "z='glorp' p:k='gru'/>")
+		#  prefixes = doc.root.attributes.prefixes    #-> ['x', 'y']
+		def prefixes
+			ns = []
+			each_attribute do |attribute|
+				ns << attribute.name if attribute.prefix == 'xmlns'
+			end
+			if @element.document and @element.document.doctype
+				expn = @element.expanded_name
+				expn = @element.document.doctype.name if expn.size == 0
+				@element.document.doctype.attributes_of(expn).each {
+					|attribute|
+					ns << attribute.name if attribute.prefix == 'xmlns'
+				}
+			end
+			ns
+		end
+
+		def namespaces
+			namespaces = {}
+			each_attribute do |attribute|
+				namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns'
+			end
+			if @element.document and @element.document.doctype
+				expn = @element.expanded_name
+				expn = @element.document.doctype.name if expn.size == 0
+				@element.document.doctype.attributes_of(expn).each {
+					|attribute|
+					namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns'
+				}
+			end
+			namespaces
+		end
+
+		# Removes an attribute
+		# attribute:: 
+		#   either a String, which is the name of the attribute to remove --
+		#   namespaces are significant here -- or the attribute to remove.
+		# Returns:: the owning element
+		#  doc = Document.new "<a y:foo='0' x:foo='1' foo='3' z:foo='4'/>"
+		#  doc.root.attributes.delete 'foo'   #-> <a y:foo='0' x:foo='1' z:foo='4'/>"
+		#  doc.root.attributes.delete 'x:foo' #-> <a y:foo='0' z:foo='4'/>"
+		#  attr = doc.root.attributes.get_attribute('y:foo')
+		#  doc.root.attributes.delete attr    #-> <a z:foo='4'/>"
+		def delete( attribute )
+			name = nil
+			prefix = nil
+			if attribute.kind_of? Attribute
+				name = attribute.name
+				prefix = attribute.prefix
+			else
+				attribute =~ Namespace::NAMESPLIT
+				prefix, name = $1, $2
+				prefix = '' unless prefix
+			end
+			old = fetch(name, nil)
+			attr = nil
+			if old.kind_of? Hash # the supplied attribute is one of many
+				attr = old.delete(prefix)
+				if old.size == 1
+					repl = nil
+					old.each_value{|v| repl = v}
+					store name, repl
+				end
+			elsif old.nil?
+				return @element
+			else # the supplied attribute is a top-level one
+				attr = old
+				res = super(name)
+			end
+			@element
+		end
+
+		# Adds an attribute, overriding any existing attribute by the
+		# same name.  Namespaces are significant.
+		# attribute:: An Attribute
+		def add( attribute )
+			self[attribute.name] = attribute
+		end
+
+		alias :<< :add
+
+		# Deletes all attributes matching a name.  Namespaces are significant.
+		# name:: 
+		#   A String; all attributes that match this path will be removed
+		# Returns:: an Array of the Attributes that were removed
+		def delete_all( name )
+			rv = []
+			each_attribute { |attribute| 
+				rv << attribute if attribute.expanded_name == name
+			}
+			rv.each{ |attr| attr.remove }
+			return rv
+		end
+    
+    # The +get_attribute_ns+ method retrieves a method by its namespace
+    # and name. Thus it is possible to reliably identify an attribute
+    # even if an XML processor has changed the prefix.
+    # 
+    # Method contributed by Henrik Martensson
+    def get_attribute_ns(namespace, name)
+      each_attribute() { |attribute|
+        if name == attribute.name &&
+           namespace == attribute.namespace()
+          return attribute
+        end
+      }
+      nil
+    end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encoding.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encoding.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encoding.rb	(revision 18425)
@@ -0,0 +1,66 @@
+# -*- mode: ruby; ruby-indent-level: 2; indent-tabs-mode: t; tab-width: 2 -*- vim: sw=2 ts=2
+module REXML
+  module Encoding
+    @encoding_methods = {}
+    def self.register(enc, &block)
+      @encoding_methods[enc] = block
+    end
+    def self.apply(obj, enc)
+      @encoding_methods[enc][obj]
+    end
+    def self.encoding_method(enc)
+      @encoding_methods[enc]
+    end
+
+    # Native, default format is UTF-8, so it is declared here rather than in
+    # an encodings/ definition.
+    UTF_8 = 'UTF-8'
+    UTF_16 = 'UTF-16'
+    UNILE = 'UNILE'
+
+    # ID ---> Encoding name
+    attr_reader :encoding
+    def encoding=( enc )
+      old_verbosity = $VERBOSE
+      begin
+        $VERBOSE = false
+        enc = enc.nil? ? nil : enc.upcase
+        return false if defined? @encoding and enc == @encoding
+        if enc and enc != UTF_8
+          @encoding = enc
+          raise ArgumentError, "Bad encoding name #@encoding" unless @encoding =~ /^[\w-]+$/
+          @encoding.untaint 
+          begin
+            require 'rexml/encodings/ICONV.rb'
+            Encoding.apply(self, "ICONV")
+          rescue LoadError, Exception
+            begin
+              enc_file = File.join( "rexml", "encodings", "#@encoding.rb" )
+              require enc_file
+              Encoding.apply(self, @encoding)
+            rescue LoadError => err
+              puts err.message
+              raise ArgumentError, "No decoder found for encoding #@encoding.  Please install iconv."
+            end
+          end
+        else
+          @encoding = UTF_8
+          require 'rexml/encodings/UTF-8.rb'
+          Encoding.apply(self, @encoding)
+        end
+      ensure
+        $VERBOSE = old_verbosity
+      end
+      true
+    end
+
+    def check_encoding str
+      # We have to recognize UTF-16, LSB UTF-16, and UTF-8
+      return UTF_16 if /\A\xfe\xff/n =~ str
+      return UNILE if /\A\xff\xfe/n =~ str
+      str =~ /^\s*<?xml\s*version\s*=\s*(['"]).*?\2\s*encoding\s*=\s*(["'])(.*?)\2/um
+      return $1.upcase if $1
+      return UTF_8
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/CP-1252.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/CP-1252.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/CP-1252.rb	(revision 18425)
@@ -0,0 +1,98 @@
+#
+# This class was contributed by Mikko Tiihonen mikko DOT tiihonen AT hut DOT fi
+#
+module REXML
+  module Encoding
+    @@__REXML_encoding_methods = %q~
+    # Convert from UTF-8
+    def encode content
+      array_utf8 = content.unpack('U*')
+      array_enc = []
+      array_utf8.each do |num|
+        case num
+          # shortcut first bunch basic characters
+        when 0..0xFF: array_enc << num
+          # characters added compared to iso-8859-1
+        when 0x20AC: array_enc << 0x80 # 0xe2 0x82 0xac
+        when 0x201A: array_enc << 0x82 # 0xe2 0x82 0x9a
+        when 0x0192: array_enc << 0x83 # 0xc6 0x92
+        when 0x201E: array_enc << 0x84 # 0xe2 0x82 0x9e
+        when 0x2026: array_enc << 0x85 # 0xe2 0x80 0xa6
+        when 0x2020: array_enc << 0x86 # 0xe2 0x80 0xa0
+        when 0x2021: array_enc << 0x87 # 0xe2 0x80 0xa1
+        when 0x02C6: array_enc << 0x88 # 0xcb 0x86
+        when 0x2030: array_enc << 0x89 # 0xe2 0x80 0xb0
+        when 0x0160: array_enc << 0x8A # 0xc5 0xa0
+        when 0x2039: array_enc << 0x8B # 0xe2 0x80 0xb9
+        when 0x0152: array_enc << 0x8C # 0xc5 0x92
+        when 0x017D: array_enc << 0x8E # 0xc5 0xbd
+        when 0x2018: array_enc << 0x91 # 0xe2 0x80 0x98
+        when 0x2019: array_enc << 0x92 # 0xe2 0x80 0x99
+        when 0x201C: array_enc << 0x93 # 0xe2 0x80 0x9c
+        when 0x201D: array_enc << 0x94 # 0xe2 0x80 0x9d
+        when 0x2022: array_enc << 0x95 # 0xe2 0x80 0xa2
+        when 0x2013: array_enc << 0x96 # 0xe2 0x80 0x93
+        when 0x2014: array_enc << 0x97 # 0xe2 0x80 0x94
+        when 0x02DC: array_enc << 0x98 # 0xcb 0x9c
+        when 0x2122: array_enc << 0x99 # 0xe2 0x84 0xa2
+        when 0x0161: array_enc << 0x9A # 0xc5 0xa1
+        when 0x203A: array_enc << 0x9B # 0xe2 0x80 0xba
+        when 0x0152: array_enc << 0x9C # 0xc5 0x93
+        when 0x017E: array_enc << 0x9E # 0xc5 0xbe
+        when 0x0178: array_enc << 0x9F # 0xc5 0xb8
+        else
+          # all remaining basic characters can be used directly
+          if num <= 0xFF
+            array_enc << num
+          else
+            # Numeric entity (&#nnnn;); shard by  Stefan Scholl
+            array_enc.concat "&\##{num};".unpack('C*')
+          end
+        end
+      end
+      array_enc.pack('C*')
+    end
+    
+    # Convert to UTF-8
+    def decode(str)
+      array_latin9 = str.unpack('C*')
+      array_enc = []
+      array_latin9.each do |num|
+        case num
+          # characters that added compared to iso-8859-1
+        when 0x80: array_enc << 0x20AC # 0xe2 0x82 0xac
+        when 0x82: array_enc << 0x201A # 0xe2 0x82 0x9a
+        when 0x83: array_enc << 0x0192 # 0xc6 0x92
+        when 0x84: array_enc << 0x201E # 0xe2 0x82 0x9e
+        when 0x85: array_enc << 0x2026 # 0xe2 0x80 0xa6
+        when 0x86: array_enc << 0x2020 # 0xe2 0x80 0xa0
+        when 0x87: array_enc << 0x2021 # 0xe2 0x80 0xa1
+        when 0x88: array_enc << 0x02C6 # 0xcb 0x86
+        when 0x89: array_enc << 0x2030 # 0xe2 0x80 0xb0
+        when 0x8A: array_enc << 0x0160 # 0xc5 0xa0
+        when 0x8B: array_enc << 0x2039 # 0xe2 0x80 0xb9
+        when 0x8C: array_enc << 0x0152 # 0xc5 0x92
+        when 0x8E: array_enc << 0x017D # 0xc5 0xbd
+        when 0x91: array_enc << 0x2018 # 0xe2 0x80 0x98
+        when 0x92: array_enc << 0x2019 # 0xe2 0x80 0x99
+        when 0x93: array_enc << 0x201C # 0xe2 0x80 0x9c
+        when 0x94: array_enc << 0x201D # 0xe2 0x80 0x9d
+        when 0x95: array_enc << 0x2022 # 0xe2 0x80 0xa2
+        when 0x96: array_enc << 0x2013 # 0xe2 0x80 0x93
+        when 0x97: array_enc << 0x2014 # 0xe2 0x80 0x94
+        when 0x98: array_enc << 0x02DC # 0xcb 0x9c
+        when 0x99: array_enc << 0x2122 # 0xe2 0x84 0xa2
+        when 0x9A: array_enc << 0x0161 # 0xc5 0xa1
+        when 0x9B: array_enc << 0x203A # 0xe2 0x80 0xba
+        when 0x9C: array_enc << 0x0152 # 0xc5 0x93
+        when 0x9E: array_enc << 0x017E # 0xc5 0xbe
+        when 0x9F: array_enc << 0x0178 # 0xc5 0xb8
+        else
+          array_enc << num
+        end
+      end
+      array_enc.pack('U*')
+    end
+    ~
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/EUC-JP.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/EUC-JP.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/EUC-JP.rb	(revision 18425)
@@ -0,0 +1,35 @@
+module REXML
+  module Encoding
+    begin
+      require 'uconv'
+
+      def decode_eucjp(str)
+        Uconv::euctou8(str)
+      end
+
+      def encode_eucjp content
+        Uconv::u8toeuc(content)
+      end
+    rescue LoadError
+      require 'nkf'
+
+      EUCTOU8 = '-Ewm0'
+      U8TOEUC = '-Wem0'
+
+      def decode_eucjp(str)
+        NKF.nkf(EUCTOU8, str)
+      end
+
+      def encode_eucjp content
+        NKF.nkf(U8TOEUC, content)
+      end
+    end
+
+    register("EUC-JP") do |obj|
+      class << obj
+        alias decode decode_eucjp
+        alias encode encode_eucjp
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/ICONV.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/ICONV.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/ICONV.rb	(revision 18425)
@@ -0,0 +1,22 @@
+require "iconv"
+raise LoadError unless defined? Iconv
+
+module REXML
+  module Encoding
+    def decode_iconv(str)
+      Iconv.conv(UTF_8, @encoding, str)
+    end
+
+    def encode_iconv(content)
+      Iconv.conv(@encoding, UTF_8, content)
+    end
+
+    register("ICONV") do |obj|
+      Iconv.conv(UTF_8, obj.encoding, nil)
+      class << obj
+        alias decode decode_iconv
+        alias encode encode_iconv
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/ISO-8859-1.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/ISO-8859-1.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/ISO-8859-1.rb	(revision 18425)
@@ -0,0 +1,7 @@
+require 'rexml/encodings/US-ASCII'
+
+module REXML
+  module Encoding
+    register("ISO-8859-1", &encoding_method("US-ASCII"))
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/ISO-8859-15.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/ISO-8859-15.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/ISO-8859-15.rb	(revision 18425)
@@ -0,0 +1,69 @@
+#
+# This class was contributed by Mikko Tiihonen mikko DOT tiihonen AT hut DOT fi
+#
+module REXML
+  module Encoding
+    @@__REXML_encoding_methods = %q~
+    # Convert from UTF-8
+    def to_iso_8859_15 content
+      array_utf8 = content.unpack('U*')
+      array_enc = []
+      array_utf8.each do |num|
+        case num
+          # shortcut first bunch basic characters
+        when 0..0xA3: array_enc << num
+          # characters removed compared to iso-8859-1
+        when 0xA4: array_enc << '&#164;'
+        when 0xA6: array_enc << '&#166;'
+        when 0xA8: array_enc << '&#168;'
+        when 0xB4: array_enc << '&#180;'
+        when 0xB8: array_enc << '&#184;'
+        when 0xBC: array_enc << '&#188;'
+        when 0xBD: array_enc << '&#189;'
+        when 0xBE: array_enc << '&#190;'
+          # characters added compared to iso-8859-1
+        when 0x20AC: array_enc << 0xA4 # 0xe2 0x82 0xac
+        when 0x0160: array_enc << 0xA6 # 0xc5 0xa0
+        when 0x0161: array_enc << 0xA8 # 0xc5 0xa1
+        when 0x017D: array_enc << 0xB4 # 0xc5 0xbd
+        when 0x017E: array_enc << 0xB8 # 0xc5 0xbe
+        when 0x0152: array_enc << 0xBC # 0xc5 0x92
+        when 0x0153: array_enc << 0xBD # 0xc5 0x93
+        when 0x0178: array_enc << 0xBE # 0xc5 0xb8
+        else
+          # all remaining basic characters can be used directly
+          if num <= 0xFF
+            array_enc << num
+          else
+            # Numeric entity (&#nnnn;); shard by  Stefan Scholl
+            array_enc.concat "&\##{num};".unpack('C*')
+          end
+        end
+      end
+      array_enc.pack('C*')
+    end
+    
+    # Convert to UTF-8
+    def from_iso_8859_15(str)
+      array_latin9 = str.unpack('C*')
+      array_enc = []
+      array_latin9.each do |num|
+        case num
+          # characters that differ compared to iso-8859-1
+        when 0xA4: array_enc << 0x20AC
+        when 0xA6: array_enc << 0x0160
+        when 0xA8: array_enc << 0x0161
+        when 0xB4: array_enc << 0x017D
+        when 0xB8: array_enc << 0x017E
+        when 0xBC: array_enc << 0x0152
+        when 0xBD: array_enc << 0x0153
+        when 0xBE: array_enc << 0x0178
+        else
+          array_enc << num
+        end
+      end
+      array_enc.pack('U*')
+    end
+    ~
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/SHIFT-JIS.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/SHIFT-JIS.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/SHIFT-JIS.rb	(revision 18425)
@@ -0,0 +1,37 @@
+module REXML
+  module Encoding
+    begin
+      require 'uconv'
+
+      def decode_sjis content
+        Uconv::sjistou8(content)
+      end
+
+      def encode_sjis(str)
+        Uconv::u8tosjis(str)
+      end
+    rescue LoadError
+      require 'nkf'
+
+      SJISTOU8 = '-Swm0'
+      U8TOSJIS = '-Wsm0'
+
+      def decode_sjis(str)
+        NKF.nkf(SJISTOU8, str)
+      end
+
+      def encode_sjis content
+        NKF.nkf(U8TOSJIS, content)
+      end
+    end
+
+    b = proc do |obj|
+      class << obj
+        alias decode decode_sjis
+        alias encode encode_sjis
+      end
+    end
+    register("SHIFT-JIS", &b)
+    register("SHIFT_JIS", &b)
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/SHIFT_JIS.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/SHIFT_JIS.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/SHIFT_JIS.rb	(revision 18425)
@@ -0,0 +1,1 @@
+require 'rexml/encodings/SHIFT-JIS'
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/UNILE.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/UNILE.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/UNILE.rb	(revision 18425)
@@ -0,0 +1,34 @@
+module REXML
+  module Encoding
+    def encode_unile content
+      array_utf8 = content.unpack("U*")
+      array_enc = []
+      array_utf8.each do |num|
+        if ((num>>16) > 0)
+          array_enc << ??
+          array_enc << 0
+        else
+          array_enc << (num & 0xFF)
+          array_enc << (num >> 8)
+        end
+      end
+      array_enc.pack('C*')
+    end
+
+    def decode_unile(str)
+      array_enc=str.unpack('C*')
+      array_utf8 = []
+      0.step(array_enc.size-1, 2){|i| 
+        array_utf8 << (array_enc.at(i) + array_enc.at(i+1)*0x100)
+      }
+      array_utf8.pack('U*')
+    end
+
+    register(UNILE) do |obj|
+      class << obj
+        alias decode decode_unile
+        alias encode encode_unile
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/US-ASCII.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/US-ASCII.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/US-ASCII.rb	(revision 18425)
@@ -0,0 +1,30 @@
+module REXML
+  module Encoding
+    # Convert from UTF-8
+    def encode_ascii content
+      array_utf8 = content.unpack('U*')
+      array_enc = []
+      array_utf8.each do |num|
+        if num <= 0x7F
+          array_enc << num
+        else
+          # Numeric entity (&#nnnn;); shard by  Stefan Scholl
+          array_enc.concat "&\##{num};".unpack('C*')
+        end
+      end
+      array_enc.pack('C*')
+    end
+
+    # Convert to UTF-8
+    def decode_ascii(str)
+      str.unpack('C*').pack('U*')
+    end
+
+    register("US-ASCII") do |obj|
+      class << obj
+        alias decode decode_ascii
+        alias encode encode_ascii
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/UTF-16.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/UTF-16.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/UTF-16.rb	(revision 18425)
@@ -0,0 +1,35 @@
+module REXML
+  module Encoding
+    def encode_utf16 content
+      array_utf8 = content.unpack("U*")
+      array_enc = []
+      array_utf8.each do |num|
+        if ((num>>16) > 0)
+          array_enc << 0
+          array_enc << ??
+        else
+          array_enc << (num >> 8)
+          array_enc << (num & 0xFF)
+        end
+      end
+      array_enc.pack('C*')
+    end
+
+    def decode_utf16(str)
+      str = str[2..-1] if /^\376\377/ =~ str
+      array_enc=str.unpack('C*')
+      array_utf8 = []
+      0.step(array_enc.size-1, 2){|i| 
+        array_utf8 << (array_enc.at(i+1) + array_enc.at(i)*0x100)
+      }
+      array_utf8.pack('U*')
+    end
+
+    register(UTF_16) do |obj|
+      class << obj
+        alias decode decode_utf16
+        alias encode encode_utf16
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/UTF-8.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/UTF-8.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/encodings/UTF-8.rb	(revision 18425)
@@ -0,0 +1,18 @@
+module REXML
+  module Encoding
+    def encode_utf8 content
+      content
+    end
+
+    def decode_utf8(str)
+      str
+    end
+
+    register(UTF_8) do |obj|
+      class << obj
+        alias decode decode_utf8
+        alias encode encode_utf8
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/entity.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/entity.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/entity.rb	(revision 18425)
@@ -0,0 +1,159 @@
+require 'rexml/child'
+require 'rexml/source'
+require 'rexml/xmltokens'
+
+module REXML
+	# God, I hate DTDs.  I really do.  Why this idiot standard still
+	# plagues us is beyond me.
+	class Entity < Child
+		include XMLTokens
+		PUBIDCHAR = "\x20\x0D\x0Aa-zA-Z0-9\\-()+,./:=?;!*@$_%#"
+		SYSTEMLITERAL = %Q{((?:"[^"]*")|(?:'[^']*'))}
+		PUBIDLITERAL = %Q{("[#{PUBIDCHAR}']*"|'[#{PUBIDCHAR}]*')}
+		EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))"
+		NDATADECL = "\\s+NDATA\\s+#{NAME}"
+		PEREFERENCE = "%#{NAME};"
+		ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))}
+		PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})"
+		ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))"
+		PEDECL = "<!ENTITY\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>"
+		GEDECL = "<!ENTITY\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>"
+		ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um
+
+		attr_reader :name, :external, :ref, :ndata, :pubid
+
+		# Create a new entity.  Simple entities can be constructed by passing a
+		# name, value to the constructor; this creates a generic, plain entity
+		# reference. For anything more complicated, you have to pass a Source to
+		# the constructor with the entity definiton, or use the accessor methods.
+		# +WARNING+: There is no validation of entity state except when the entity
+		# is read from a stream.  If you start poking around with the accessors,
+		# you can easily create a non-conformant Entity.  The best thing to do is
+		# dump the stupid DTDs and use XMLSchema instead.
+		# 
+		#  e = Entity.new( 'amp', '&' )
+		def initialize stream, value=nil, parent=nil, reference=false
+			super(parent)
+			@ndata = @pubid = @value = @external = nil
+			if stream.kind_of? Array
+				@name = stream[1]
+				if stream[-1] == '%'
+					@reference = true 
+					stream.pop
+				else
+					@reference = false
+				end
+				if stream[2] =~ /SYSTEM|PUBLIC/
+					@external = stream[2]
+					if @external == 'SYSTEM'
+						@ref = stream[3]
+						@ndata = stream[4] if stream.size == 5
+					else
+						@pubid = stream[3]
+						@ref = stream[4]
+					end
+				else
+					@value = stream[2]
+				end
+			else
+				@reference = reference
+				@external = nil
+				@name = stream
+				@value = value
+			end
+		end
+
+		# Evaluates whether the given string matchs an entity definition,
+		# returning true if so, and false otherwise.
+		def Entity::matches? string
+			(ENTITYDECL =~ string) == 0
+		end
+
+		# Evaluates to the unnormalized value of this entity; that is, replacing
+		# all entities -- both %ent; and &ent; entities.  This differs from
+		# +value()+ in that +value+ only replaces %ent; entities.
+		def unnormalized
+			v = value()
+			return nil if v.nil?
+			@unnormalized = Text::unnormalize(v, parent)
+			@unnormalized
+		end
+
+		#once :unnormalized
+
+		# Returns the value of this entity unprocessed -- raw.  This is the
+		# normalized value; that is, with all %ent; and &ent; entities intact
+		def normalized
+			@value
+		end
+
+		# Write out a fully formed, correct entity definition (assuming the Entity
+		# object itself is valid.)
+		def write out, indent=-1
+			out << '<!ENTITY '
+			out << '% ' if @reference
+			out << @name
+			out << ' '
+			if @external
+				out << @external << ' '
+				if @pubid
+					q = @pubid.include?('"')?"'":'"'
+					out << q << @pubid << q << ' '
+				end
+				q = @ref.include?('"')?"'":'"'
+				out << q << @ref << q
+				out << ' NDATA ' << @ndata if @ndata
+			else
+				q = @value.include?('"')?"'":'"'
+				out << q << @value << q
+			end
+			out << '>'
+		end
+
+		# Returns this entity as a string.  See write().
+		def to_s
+			rv = ''
+			write rv
+			rv
+		end
+
+		PEREFERENCE_RE = /#{PEREFERENCE}/um
+		# Returns the value of this entity.  At the moment, only internal entities
+		# are processed.  If the value contains internal references (IE,
+		# %blah;), those are replaced with their values.  IE, if the doctype
+		# contains:
+		#  <!ENTITY % foo "bar">
+		#  <!ENTITY yada "nanoo %foo; nanoo>
+		# then:
+		#  doctype.entity('yada').value   #-> "nanoo bar nanoo"
+		def value
+			if @value
+				matches = @value.scan(PEREFERENCE_RE)
+				rv = @value.clone
+				if @parent
+					matches.each do |entity_reference|
+						entity_value = @parent.entity( entity_reference[0] )
+						rv.gsub!( /%#{entity_reference};/um, entity_value )
+					end
+				end
+				return rv
+			end
+			nil
+		end
+	end
+
+	# This is a set of entity constants -- the ones defined in the XML
+	# specification.  These are +gt+, +lt+, +amp+, +quot+ and +apos+.
+	module EntityConst
+		# +>+
+		GT = Entity.new( 'gt', '>' )
+		# +<+
+		LT = Entity.new( 'lt', '<' )
+		# +&+
+		AMP = Entity.new( 'amp', '&' )
+		# +"+
+		QUOT = Entity.new( 'quot', '"' )
+		# +'+
+		APOS = Entity.new( 'apos', "'" )
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/functions.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/functions.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/functions.rb	(revision 18425)
@@ -0,0 +1,383 @@
+module REXML
+  # If you add a method, keep in mind two things:
+  # (1) the first argument will always be a list of nodes from which to
+  # filter.  In the case of context methods (such as position), the function
+  # should return an array with a value for each child in the array.
+  # (2) all method calls from XML will have "-" replaced with "_".
+  # Therefore, in XML, "local-name()" is identical (and actually becomes)
+  # "local_name()"
+  module Functions
+    @@context = nil
+    @@namespace_context = {}
+    @@variables = {}
+
+    def Functions::namespace_context=(x) ; @@namespace_context=x ; end
+    def Functions::variables=(x) ; @@variables=x ; end
+    def Functions::namespace_context ; @@namespace_context ; end
+    def Functions::variables ; @@variables ; end
+
+    def Functions::context=(value); @@context = value; end
+
+    def Functions::text( )
+      if @@context[:node].node_type == :element
+        return @@context[:node].find_all{|n| n.node_type == :text}.collect{|n| n.value}
+      elsif @@context[:node].node_type == :text
+        return @@context[:node].value
+      else
+        return false
+      end
+    end
+
+    def Functions::last( )
+      @@context[:size]
+    end
+
+    def Functions::position( )
+      @@context[:index]
+    end
+
+    def Functions::count( node_set )
+      node_set.size
+    end
+
+    # Since REXML is non-validating, this method is not implemented as it
+    # requires a DTD
+    def Functions::id( object )
+    end
+
+    # UNTESTED
+    def Functions::local_name( node_set=nil )
+      get_namespace( node_set ) do |node|
+        return node.local_name 
+      end
+    end
+
+    def Functions::namespace_uri( node_set=nil )
+      get_namespace( node_set ) {|node| node.namespace}
+    end
+
+    def Functions::name( node_set=nil )
+      get_namespace( node_set ) do |node| 
+        node.expanded_name
+      end
+    end
+
+    # Helper method.
+    def Functions::get_namespace( node_set = nil )
+      if node_set == nil
+        yield @@context[:node] if defined? @@context[:node].namespace
+      else  
+        if node_set.respond_to? :each
+          node_set.each { |node| yield node if defined? node.namespace }
+        elsif node_set.respond_to? :namespace
+          yield node_set
+        end
+      end
+    end
+
+    # A node-set is converted to a string by returning the string-value of the
+    # node in the node-set that is first in document order. If the node-set is
+    # empty, an empty string is returned.
+    #
+    # A number is converted to a string as follows
+    #
+    # NaN is converted to the string NaN 
+    #
+    # positive zero is converted to the string 0 
+    #
+    # negative zero is converted to the string 0 
+    #
+    # positive infinity is converted to the string Infinity 
+    #
+    # negative infinity is converted to the string -Infinity 
+    #
+    # if the number is an integer, the number is represented in decimal form
+    # as a Number with no decimal point and no leading zeros, preceded by a
+    # minus sign (-) if the number is negative
+    #
+    # otherwise, the number is represented in decimal form as a Number
+    # including a decimal point with at least one digit before the decimal
+    # point and at least one digit after the decimal point, preceded by a
+    # minus sign (-) if the number is negative; there must be no leading zeros
+    # before the decimal point apart possibly from the one required digit
+    # immediately before the decimal point; beyond the one required digit
+    # after the decimal point there must be as many, but only as many, more
+    # digits as are needed to uniquely distinguish the number from all other
+    # IEEE 754 numeric values.
+    #
+    # The boolean false value is converted to the string false. The boolean
+    # true value is converted to the string true.
+    #
+    # An object of a type other than the four basic types is converted to a
+    # string in a way that is dependent on that type.
+    def Functions::string( object=nil )
+      #object = @context unless object
+      if object.instance_of? Array
+        string( object[0] )
+      elsif defined? object.node_type
+        if object.node_type == :attribute
+          object.value
+        elsif object.node_type == :element || object.node_type == :document
+          string_value(object)
+        else
+          object.to_s
+        end
+      elsif object.nil?
+        return ""
+      else
+        object.to_s
+      end
+    end
+
+    def Functions::string_value( o )
+      rv = ""
+      o.children.each { |e|
+        if e.node_type == :text
+          rv << e.to_s
+        elsif e.node_type == :element
+          rv << string_value( e )
+        end
+      }
+      rv
+    end
+
+    # UNTESTED
+    def Functions::concat( *objects )
+      objects.join
+    end
+
+    # Fixed by Mike Stok
+    def Functions::starts_with( string, test )
+      string(string).index(string(test)) == 0
+    end
+
+    # Fixed by Mike Stok
+    def Functions::contains( string, test )
+      string(string).include?(string(test))
+    end
+
+    # Kouhei fixed this 
+    def Functions::substring_before( string, test )
+      ruby_string = string(string)
+      ruby_index = ruby_string.index(string(test))
+      if ruby_index.nil?
+        ""
+      else
+        ruby_string[ 0...ruby_index ]
+      end
+    end
+ 
+    # Kouhei fixed this too
+    def Functions::substring_after( string, test )
+      ruby_string = string(string)
+      test_string = string(test)
+      return $1 if ruby_string =~ /#{test}(.*)/
+      ""
+    end
+
+    # Take equal portions of Mike Stok and Sean Russell; mix 
+    # vigorously, and pour into a tall, chilled glass.  Serves 10,000.
+    def Functions::substring( string, start, length=nil )
+      ruby_string = string(string)
+      ruby_length = if length.nil? 
+                      ruby_string.length.to_f
+                    else
+                      number(length)
+                    end
+      ruby_start = number(start)
+
+      # Handle the special cases
+      return '' if (
+        ruby_length.nan? or 
+        ruby_start.nan? or
+        ruby_start.infinite?
+      )
+
+      infinite_length = ruby_length.infinite? == 1
+      ruby_length = ruby_string.length if infinite_length
+        
+      # Now, get the bounds.  The XPath bounds are 1..length; the ruby bounds 
+      # are 0..length.  Therefore, we have to offset the bounds by one.
+      ruby_start = ruby_start.round - 1
+      ruby_length = ruby_length.round
+
+      if ruby_start < 0
+       ruby_length += ruby_start unless infinite_length
+       ruby_start = 0
+      end
+      return '' if ruby_length <= 0
+      ruby_string[ruby_start,ruby_length]
+    end
+
+    # UNTESTED
+    def Functions::string_length( string )
+      string(string).length
+    end
+
+    # UNTESTED
+    def Functions::normalize_space( string=nil )
+      string = string(@@context[:node]) if string.nil?
+      if string.kind_of? Array
+        string.collect{|x| string.to_s.strip.gsub(/\s+/um, ' ') if string}
+      else
+        string.to_s.strip.gsub(/\s+/um, ' ')
+      end
+    end
+
+    # This is entirely Mike Stok's beast
+    def Functions::translate( string, tr1, tr2 )
+      from = string(tr1)
+      to = string(tr2)
+
+      # the map is our translation table.
+      #
+      # if a character occurs more than once in the
+      # from string then we ignore the second &
+      # subsequent mappings
+      #
+      # if a charactcer maps to nil then we delete it
+      # in the output.  This happens if the from
+      # string is longer than the to string
+      #
+      # there's nothing about - or ^ being special in
+      # http://www.w3.org/TR/xpath#function-translate
+      # so we don't build ranges or negated classes
+
+      map = Hash.new
+      0.upto(from.length - 1) { |pos|
+        from_char = from[pos]
+        unless map.has_key? from_char
+          map[from_char] = 
+          if pos < to.length
+            to[pos]
+          else
+            nil
+          end
+        end
+      }
+
+      string(string).unpack('U*').collect { |c|
+        if map.has_key? c then map[c] else c end
+      }.compact.pack('U*')
+    end
+
+    # UNTESTED
+    def Functions::boolean( object=nil )
+      if object.kind_of? String
+        if object =~ /\d+/u
+          return object.to_f != 0
+        else
+          return object.size > 0
+        end
+      elsif object.kind_of? Array
+        object = object.find{|x| x and true}
+      end
+      return object ? true : false
+    end
+
+    # UNTESTED
+    def Functions::not( object )
+      not boolean( object )
+    end
+
+    # UNTESTED
+    def Functions::true( )
+      true
+    end
+
+    # UNTESTED
+    def Functions::false(  )
+      false
+    end
+
+    # UNTESTED
+    def Functions::lang( language )
+      lang = false
+      node = @@context[:node]
+      attr = nil
+      until node.nil?
+        if node.node_type == :element
+          attr = node.attributes["xml:lang"]
+          unless attr.nil?
+            lang = compare_language(string(language), attr)
+            break
+          else
+          end
+        end
+        node = node.parent
+      end
+      lang
+    end
+
+    def Functions::compare_language lang1, lang2
+      lang2.downcase.index(lang1.downcase) == 0
+    end
+
+    # a string that consists of optional whitespace followed by an optional
+    # minus sign followed by a Number followed by whitespace is converted to
+    # the IEEE 754 number that is nearest (according to the IEEE 754
+    # round-to-nearest rule) to the mathematical value represented by the
+    # string; any other string is converted to NaN
+    #
+    # boolean true is converted to 1; boolean false is converted to 0
+    #
+    # a node-set is first converted to a string as if by a call to the string
+    # function and then converted in the same way as a string argument
+    #
+    # an object of a type other than the four basic types is converted to a
+    # number in a way that is dependent on that type
+    def Functions::number( object=nil )
+      object = @@context[:node] unless object
+      case object
+      when true
+        Float(1)
+      when false
+        Float(0)
+      when Array
+        number(string( object ))
+      when Numeric
+        object.to_f
+      else
+        str = string( object )
+        #puts "STRING OF #{object.inspect} = #{str}"
+        # If XPath ever gets scientific notation...
+        #if str =~ /^\s*-?(\d*\.?\d+|\d+\.)([Ee]\d*)?\s*$/
+        if str =~ /^\s*-?(\d*\.?\d+|\d+\.)\s*$/
+          str.to_f
+        else
+          (0.0 / 0.0)
+        end
+      end
+    end
+
+    def Functions::sum( nodes )
+      nodes = [nodes] unless nodes.kind_of? Array
+      nodes.inject(0) { |r,n| r += number(string(n)) }
+    end
+    
+    def Functions::floor( number )
+      number(number).floor
+    end
+
+    def Functions::ceiling( number )
+      number(number).ceil
+    end
+
+    def Functions::round( number )
+      begin
+        number(number).round
+      rescue FloatDomainError
+        number(number)
+      end
+    end
+
+    def Functions::processing_instruction( node )
+      node.node_type == :processing_instruction
+    end
+
+    def Functions::method_missing( id )
+      puts "METHOD MISSING #{id.id2name}"
+      XPath.match( @@context[:node], id.id2name )
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/instruction.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/instruction.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/instruction.rb	(revision 18425)
@@ -0,0 +1,66 @@
+require "rexml/child"
+require "rexml/source"
+
+module REXML
+	# Represents an XML Instruction; IE, <? ... ?>
+	# TODO: Add parent arg (3rd arg) to constructor
+	class Instruction < Child
+		START = '<\?'
+		STOP = '\?>'
+
+		# target is the "name" of the Instruction; IE, the "tag" in <?tag ...?>
+		# content is everything else.
+		attr_accessor :target, :content
+
+		# Constructs a new Instruction
+		# @param target can be one of a number of things.  If String, then 
+		# the target of this instruction is set to this.  If an Instruction,
+		# then the Instruction is shallowly cloned (target and content are
+		# copied).  If a Source, then the source is scanned and parsed for
+		# an Instruction declaration.
+		# @param content Must be either a String, or a Parent.  Can only
+		# be a Parent if the target argument is a Source.  Otherwise, this
+		# String is set as the content of this instruction.
+		def initialize(target, content=nil)
+			if target.kind_of? String
+				super()
+				@target = target
+				@content = content
+			elsif target.kind_of? Instruction
+				super(content)
+				@target = target.target
+				@content = target.content
+			end
+			@content.strip! if @content
+		end
+
+		def clone
+			Instruction.new self
+		end
+		
+		def write writer, indent=-1, transitive=false, ie_hack=false
+			indent(writer, indent)
+			writer << START.sub(/\\/u, '')
+			writer << @target
+			writer << ' '
+			writer << @content
+			writer << STOP.sub(/\\/u, '')
+		end
+
+		# @return true if other is an Instruction, and the content and target
+		# of the other matches the target and content of this object.
+		def ==( other )
+			other.kind_of? Instruction and
+			other.target == @target and
+			other.content == @content
+		end
+
+    def node_type
+      :processing_instruction
+    end
+
+    def inspect
+      "<?p-i #{target} ...?>"
+    end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/light/node.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/light/node.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/light/node.rb	(revision 18425)
@@ -0,0 +1,196 @@
+require 'rexml/xmltokens'
+require 'rexml/light/node'
+
+# [ :element, parent, name, attributes, children* ]
+	# a = Node.new
+	# a << "B"		# => <a>B</a>
+	# a.b			# => <a>B<b/></a>
+	# a.b[1]			# => <a>B<b/><b/><a>
+	# a.b[1]["x"] = "y"	# => <a>B<b/><b x="y"/></a>
+	# a.b[0].c		# => <a>B<b><c/></b><b x="y"/></a>
+	# a.b.c << "D"		# => <a>B<b><c>D</c></b><b x="y"/></a>
+module REXML
+	module Light
+		# Represents a tagged XML element.  Elements are characterized by
+		# having children, attributes, and names, and can themselves be
+		# children.
+		class Node
+			NAMESPLIT = /^(?:(#{XMLTokens::NCNAME_STR}):)?(#{XMLTokens::NCNAME_STR})/u
+			PARENTS = [ :element, :document, :doctype ]
+			# Create a new element.
+			def initialize node=nil
+				@node = node
+				if node.kind_of? String
+					node = [ :text, node ]
+				elsif node.nil?
+					node = [ :document, nil, nil ]
+				elsif node[0] == :start_element
+					node[0] = :element
+				elsif node[0] == :start_doctype
+					node[0] = :doctype
+				elsif node[0] == :start_document
+					node[0] = :document
+				end
+			end
+
+			def size
+				if PARENTS.include? @node[0]
+					@node[-1].size
+				else
+					0
+				end
+			end
+
+			def each( &block )
+				size.times { |x| yield( at(x+4) ) }
+			end
+
+			def name
+				at(2)
+			end
+
+			def name=( name_str, ns=nil )
+				pfx = ''
+				pfx = "#{prefix(ns)}:" if ns
+				_old_put(2, "#{pfx}#{name_str}")
+			end
+
+			def parent=( node )
+				_old_put(1,node)
+			end
+
+			def local_name
+				namesplit
+				@name
+			end
+
+			def local_name=( name_str )
+				_old_put( 1, "#@prefix:#{name_str}" )
+			end
+
+			def prefix( namespace=nil )
+				prefix_of( self, namespace )
+			end
+
+			def namespace( prefix=prefix() )
+				namespace_of( self, prefix )
+			end
+
+			def namespace=( namespace )
+				@prefix = prefix( namespace )
+				pfx = ''
+				pfx = "#@prefix:" if @prefix.size > 0
+				_old_put(1, "#{pfx}#@name")
+			end
+
+			def []( reference, ns=nil )
+				if reference.kind_of? String
+					pfx = ''
+					pfx = "#{prefix(ns)}:" if ns
+					at(3)["#{pfx}#{reference}"]
+				elsif reference.kind_of? Range
+					_old_get( Range.new(4+reference.begin, reference.end, reference.exclude_end?) )
+				else
+					_old_get( 4+reference )
+				end
+			end
+
+			def =~( path )
+				XPath.match( self, path )
+			end
+
+			# Doesn't handle namespaces yet
+			def []=( reference, ns, value=nil )
+				if reference.kind_of? String
+					value = ns unless value
+					at( 3 )[reference] = value
+				elsif reference.kind_of? Range
+					_old_put( Range.new(3+reference.begin, reference.end, reference.exclude_end?), ns )
+				else
+					if value
+						_old_put( 4+reference, ns, value )
+					else
+						_old_put( 4+reference, ns )
+					end
+				end
+			end
+
+			# Append a child to this element, optionally under a provided namespace.
+			# The namespace argument is ignored if the element argument is an Element
+			# object.  Otherwise, the element argument is a string, the namespace (if
+			# provided) is the namespace the element is created in.
+			def << element
+				if node_type() == :text
+					at(-1) << element
+				else
+					newnode = Node.new( element )
+					newnode.parent = self
+					self.push( newnode )
+				end
+				at(-1)
+			end
+
+			def node_type
+				_old_get(0)
+			end
+
+			def text=( foo )
+				replace = at(4).kind_of?(String)? 1 : 0
+				self._old_put(4,replace, normalizefoo)
+			end
+
+			def root
+				context = self
+				context = context.at(1) while context.at(1)
+			end
+
+			def has_name?( name, namespace = '' )
+				at(3) == name and namespace() == namespace
+			end
+
+			def children
+				self
+			end
+
+			def parent
+				at(1)
+			end
+
+			def to_s
+
+			end
+
+			private
+
+			def namesplit
+				return if @name.defined?
+				at(2) =~ NAMESPLIT
+				@prefix = '' || $1
+				@name = $2
+			end
+
+			def namespace_of( node, prefix=nil )
+				if not prefix
+					name = at(2)
+					name =~ NAMESPLIT
+					prefix = $1
+				end
+				to_find = 'xmlns'
+				to_find = "xmlns:#{prefix}" if not prefix.nil?
+				ns = at(3)[ to_find ]
+				ns ? ns : namespace_of( @node[0], prefix )
+			end
+
+			def prefix_of( node, namespace=nil )
+				if not namespace
+					name = node.name
+					name =~ NAMESPLIT
+					$1
+				else
+					ns = at(3).find { |k,v| v == namespace }
+					ns ? ns : prefix_of( node.parent, namespace )
+				end
+			end
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/namespace.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/namespace.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/namespace.rb	(revision 18425)
@@ -0,0 +1,47 @@
+require 'rexml/xmltokens'
+
+module REXML
+	# Adds named attributes to an object.
+	module Namespace
+		# The name of the object, valid if set
+		attr_reader :name, :expanded_name
+		# The expanded name of the object, valid if name is set
+		attr_accessor :prefix
+		include XMLTokens
+		NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u
+
+		# Sets the name and the expanded name
+		def name=( name )
+			@expanded_name = name
+			name =~ NAMESPLIT
+			if $1
+				@prefix = $1
+			else
+				@prefix = ""
+				@namespace = ""
+			end
+			@name = $2
+		end
+
+		# Compares names optionally WITH namespaces
+		def has_name?( other, ns=nil )
+			if ns
+				return (namespace() == ns and name() == other)
+			elsif other.include? ":"
+				return fully_expanded_name == other
+			else
+				return name == other
+			end
+		end
+
+		alias :local_name :name
+
+		# Fully expand the name, even if the prefix wasn't specified in the
+		# source file.
+		def fully_expanded_name
+			ns = prefix
+			return "#{ns}:#@name" if ns.size > 0 
+			return @name
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/node.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/node.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/node.rb	(revision 18425)
@@ -0,0 +1,64 @@
+require "rexml/parseexception"
+
+module REXML
+	# Represents a node in the tree.  Nodes are never encountered except as
+	# superclasses of other objects.  Nodes have siblings.
+	module Node
+		# @return the next sibling (nil if unset)
+		def next_sibling_node
+			return nil if @parent.nil?
+			@parent[ @parent.index(self) + 1 ]
+		end
+
+		# @return the previous sibling (nil if unset)
+		def previous_sibling_node
+			return nil if @parent.nil?
+			ind = @parent.index(self)
+			return nil if ind == 0
+			@parent[ ind - 1 ]
+		end
+
+		def to_s indent=-1
+			rv = ""
+			write rv,indent
+			rv
+		end
+
+		def indent to, ind
+ 			if @parent and @parent.context and not @parent.context[:indentstyle].nil? then
+ 				indentstyle = @parent.context[:indentstyle]
+ 			else
+ 				indentstyle = '  '
+ 			end
+ 			to << indentstyle*ind unless ind<1
+		end
+
+		def parent?
+			false;
+		end
+
+
+		# Visit all subnodes of +self+ recursively
+		def each_recursive(&block) # :yields: node
+			self.elements.each {|node|
+				block.call(node)
+				node.each_recursive(&block)
+			}
+		end
+
+		# Find (and return) first subnode (recursively) for which the block 
+    # evaluates to true. Returns +nil+ if none was found.
+		def find_first_recursive(&block) # :yields: node
+      each_recursive {|node|
+        return node if block.call(node)
+      }
+      return nil
+    end
+
+    # Returns the position that +self+ holds in its parent's array, indexed
+    # from 1.
+    def index_in_parent
+      parent.index(self)+1
+    end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/output.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/output.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/output.rb	(revision 18425)
@@ -0,0 +1,24 @@
+require 'rexml/encoding'
+
+module REXML
+	class Output
+		include Encoding
+    
+    attr_reader :encoding
+
+		def initialize real_IO, encd="iso-8859-1"
+			@output = real_IO
+			self.encoding = encd
+
+			@to_utf = encd == UTF_8 ? false : true
+		end
+
+		def <<( content )
+			@output << (@to_utf ? self.encode(content) : content)
+		end
+
+    def to_s
+      "Output[#{encoding}]"
+    end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parent.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parent.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parent.rb	(revision 18425)
@@ -0,0 +1,166 @@
+require "rexml/child"
+
+module REXML
+  # A parent has children, and has methods for accessing them.  The Parent
+  # class is never encountered except as the superclass for some other
+  # object.
+  class Parent < Child
+    include Enumerable
+    
+    # Constructor
+    # @param parent if supplied, will be set as the parent of this object
+    def initialize parent=nil
+      super(parent)
+      @children = []
+    end
+    
+    def add( object )
+      #puts "PARENT GOTS #{size} CHILDREN"
+      object.parent = self
+      @children << object
+      #puts "PARENT NOW GOTS #{size} CHILDREN"
+      object
+    end
+    
+    alias :push :add
+    alias :<< :push
+    
+    def unshift( object )
+      object.parent = self
+      @children.unshift object
+    end
+    
+    def delete( object )
+      found = false
+      @children.delete_if {|c| c.equal?(object) and found = true }
+      object.parent = nil if found
+    end
+    
+    def each(&block)
+      @children.each(&block)
+    end
+    
+    def delete_if( &block )
+      @children.delete_if(&block)
+    end
+    
+    def delete_at( index )
+      @children.delete_at index
+    end
+    
+    def each_index( &block )
+      @children.each_index(&block)
+    end
+    
+    # Fetches a child at a given index
+    # @param index the Integer index of the child to fetch
+    def []( index )
+      @children[index]
+    end
+    
+    alias :each_child :each
+    
+    
+    
+    # Set an index entry.  See Array.[]=
+    # @param index the index of the element to set
+    # @param opt either the object to set, or an Integer length
+    # @param child if opt is an Integer, this is the child to set
+    # @return the parent (self)
+    def []=( *args )
+      args[-1].parent = self
+      @children[*args[0..-2]] = args[-1]
+    end
+    
+    # Inserts an child before another child
+    # @param child1 this is either an xpath or an Element.  If an Element,
+    # child2 will be inserted before child1 in the child list of the parent.
+    # If an xpath, child2 will be inserted before the first child to match
+    # the xpath.
+    # @param child2 the child to insert
+    # @return the parent (self)
+    def insert_before( child1, child2 )
+      if child1.kind_of? String
+        child1 = XPath.first( self, child1 )
+        child1.parent.insert_before child1, child2
+      else
+        ind = index(child1)
+        child2.parent.delete(child2) if child2.parent
+        @children[ind,0] = child2
+        child2.parent = self
+      end
+      self
+    end
+    
+    # Inserts an child after another child
+    # @param child1 this is either an xpath or an Element.  If an Element,
+    # child2 will be inserted after child1 in the child list of the parent.
+    # If an xpath, child2 will be inserted after the first child to match
+    # the xpath.
+    # @param child2 the child to insert
+    # @return the parent (self)
+    def insert_after( child1, child2 )
+      if child1.kind_of? String
+        child1 = XPath.first( self, child1 )
+        child1.parent.insert_after child1, child2
+      else
+        ind = index(child1)+1
+        child2.parent.delete(child2) if child2.parent
+        @children[ind,0] = child2
+        child2.parent = self
+      end
+      self
+    end
+    
+    def to_a
+      @children.dup
+    end
+    
+    # Fetches the index of a given child
+    # @param child the child to get the index of
+    # @return the index of the child, or nil if the object is not a child
+    # of this parent.
+    def index( child )
+      count = -1
+      @children.find { |i| count += 1 ; i.hash == child.hash }
+      count
+    end
+    
+    # @return the number of children of this parent
+    def size
+      @children.size
+    end
+    
+    alias :length :size
+    
+    # Replaces one child with another, making sure the nodelist is correct
+    # @param to_replace the child to replace (must be a Child)
+    # @param replacement the child to insert into the nodelist (must be a 
+    # Child)
+    def replace_child( to_replace, replacement )
+      @children.map! {|c| c.equal?( to_replace ) ? replacement : c }
+      to_replace.parent = nil
+      replacement.parent = self
+    end
+    
+    # Deeply clones this object.  This creates a complete duplicate of this
+    # Parent, including all descendants.
+    def deep_clone
+      cl = clone()
+      each do |child|
+        if child.kind_of? Parent
+          cl << child.deep_clone
+        else
+          cl << child.clone
+        end
+      end
+      cl
+    end
+    
+    alias :children :to_a
+    
+    def parent?
+      true
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parseexception.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parseexception.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parseexception.rb	(revision 18425)
@@ -0,0 +1,51 @@
+module REXML
+  class ParseException < RuntimeError
+    attr_accessor :source, :parser, :continued_exception
+
+    def initialize( message, source=nil, parser=nil, exception=nil )
+      super(message)
+      @source = source
+      @parser = parser
+      @continued_exception = exception
+    end
+
+    def to_s
+      # Quote the original exception, if there was one
+      if @continued_exception
+        err = @continued_exception.inspect
+        err << "\n"
+        err << @continued_exception.backtrace.join("\n")
+        err << "\n...\n"
+      else
+        err = ""
+      end
+
+      # Get the stack trace and error message
+      err << super
+
+      # Add contextual information
+      if @source
+        err << "\nLine: #{line}\n"
+        err << "Position: #{position}\n"
+        err << "Last 80 unconsumed characters:\n"
+        err << @source.buffer[0..80].gsub(/\n/, ' ')
+      end
+      
+      err
+    end
+
+    def position
+      @source.current_line[0] if @source and defined? @source.current_line and
+      @source.current_line
+    end
+
+    def line
+      @source.current_line[2] if @source and defined? @source.current_line and 
+      @source.current_line
+    end
+
+    def context
+      @source.current_line
+    end
+  end  
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/baseparser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/baseparser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/baseparser.rb	(revision 18425)
@@ -0,0 +1,463 @@
+require 'rexml/parseexception'
+require 'rexml/source'
+
+module REXML
+  module Parsers
+    # = Using the Pull Parser
+    # <em>This API is experimental, and subject to change.</em>
+    #  parser = PullParser.new( "<a>text<b att='val'/>txet</a>" )
+    #  while parser.has_next?
+    #    res = parser.next
+    #    puts res[1]['att'] if res.start_tag? and res[0] == 'b'
+    #  end
+    # See the PullEvent class for information on the content of the results.
+    # The data is identical to the arguments passed for the various events to
+    # the StreamListener API.
+    #
+    # Notice that:
+    #  parser = PullParser.new( "<a>BAD DOCUMENT" )
+    #  while parser.has_next?
+    #    res = parser.next
+    #    raise res[1] if res.error?
+    #  end
+    #
+    # Nat Price gave me some good ideas for the API.
+    class BaseParser
+      NCNAME_STR= '[\w:][\-\w\d.]*'
+      NAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
+
+      NAMECHAR = '[\-\w\d\.:]'
+      NAME = "([\\w:]#{NAMECHAR}*)"
+      NMTOKEN = "(?:#{NAMECHAR})+"
+      NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*"
+      REFERENCE = "(?:&#{NAME};|&#\\d+;|&#x[0-9a-fA-F]+;)"
+      REFERENCE_RE = /#{REFERENCE}/
+
+      DOCTYPE_START = /\A\s*<!DOCTYPE\s/um
+      DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um
+      ATTRIBUTE_PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um
+      COMMENT_START = /\A<!--/u
+      COMMENT_PATTERN = /<!--(.*?)-->/um
+      CDATA_START = /\A<!\[CDATA\[/u
+      CDATA_END = /^\s*\]\s*>/um
+      CDATA_PATTERN = /<!\[CDATA\[(.*?)\]\]>/um
+      XMLDECL_START = /\A<\?xml\s/u;
+      XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>/um
+      INSTRUCTION_START = /\A<\?/u
+      INSTRUCTION_PATTERN = /<\?(.*?)(\s+.*?)?\?>/um
+      TAG_MATCH = /^<((?>#{NAME_STR}))\s*((?>\s+#{NAME_STR}\s*=\s*(["']).*?\3)*)\s*(\/)?>/um
+      CLOSE_MATCH = /^\s*<\/(#{NAME_STR})\s*>/um
+
+      VERSION = /\bversion\s*=\s*["'](.*?)['"]/um
+      ENCODING = /\bencoding\s*=\s*["'](.*?)['"]/um
+      STANDALONE = /\bstandalone\s*=\s["'](.*?)['"]/um
+
+      ENTITY_START = /^\s*<!ENTITY/
+      IDENTITY = /^([!\*\w\-]+)(\s+#{NCNAME_STR})?(\s+["'].*?['"])?(\s+['"].*?["'])?/u
+      ELEMENTDECL_START = /^\s*<!ELEMENT/um
+      ELEMENTDECL_PATTERN = /^\s*(<!ELEMENT.*?)>/um
+      SYSTEMENTITY = /^\s*(%.*?;)\s*$/um
+      ENUMERATION = "\\(\\s*#{NMTOKEN}(?:\\s*\\|\\s*#{NMTOKEN})*\\s*\\)"
+      NOTATIONTYPE = "NOTATION\\s+\\(\\s*#{NAME}(?:\\s*\\|\\s*#{NAME})*\\s*\\)"
+      ENUMERATEDTYPE = "(?:(?:#{NOTATIONTYPE})|(?:#{ENUMERATION}))"
+      ATTTYPE = "(CDATA|ID|IDREF|IDREFS|ENTITY|ENTITIES|NMTOKEN|NMTOKENS|#{ENUMERATEDTYPE})"
+      ATTVALUE = "(?:\"((?:[^<&\"]|#{REFERENCE})*)\")|(?:'((?:[^<&']|#{REFERENCE})*)')"
+      DEFAULTDECL = "(#REQUIRED|#IMPLIED|(?:(#FIXED\\s+)?#{ATTVALUE}))"
+      ATTDEF = "\\s+#{NAME}\\s+#{ATTTYPE}\\s+#{DEFAULTDECL}"
+      ATTDEF_RE = /#{ATTDEF}/
+      ATTLISTDECL_START = /^\s*<!ATTLIST/um
+      ATTLISTDECL_PATTERN = /^\s*<!ATTLIST\s+#{NAME}(?:#{ATTDEF})*\s*>/um
+      NOTATIONDECL_START = /^\s*<!NOTATION/um
+      PUBLIC = /^\s*<!NOTATION\s+(\w[\-\w]*)\s+(PUBLIC)\s+(["'])(.*?)\3(?:\s+(["'])(.*?)\5)?\s*>/um
+      SYSTEM = /^\s*<!NOTATION\s+(\w[\-\w]*)\s+(SYSTEM)\s+(["'])(.*?)\3\s*>/um
+
+      TEXT_PATTERN = /\A([^<]*)/um
+
+      # Entity constants
+      PUBIDCHAR = "\x20\x0D\x0Aa-zA-Z0-9\\-()+,./:=?;!*@$_%#"
+      SYSTEMLITERAL = %Q{((?:"[^"]*")|(?:'[^']*'))}
+      PUBIDLITERAL = %Q{("[#{PUBIDCHAR}']*"|'[#{PUBIDCHAR}]*')}
+      EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))"
+      NDATADECL = "\\s+NDATA\\s+#{NAME}"
+      PEREFERENCE = "%#{NAME};"
+      ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))}
+      PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})"
+      ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))"
+      PEDECL = "<!ENTITY\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>"
+      GEDECL = "<!ENTITY\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>"
+      ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um
+
+      EREFERENCE = /&(?!#{NAME};)/
+
+      DEFAULT_ENTITIES = { 
+        'gt' => [/&gt;/, '&gt;', '>', />/], 
+        'lt' => [/&lt;/, '&lt;', '<', /</], 
+        'quot' => [/&quot;/, '&quot;', '"', /"/], 
+        "apos" => [/&apos;/, "&apos;", "'", /'/] 
+      }
+
+
+      ######################################################################
+      # These are patterns to identify common markup errors, to make the
+      # error messages more informative.
+      ######################################################################
+      MISSING_ATTRIBUTE_QUOTES = /^<#{NAME_STR}\s+#{NAME_STR}\s*=\s*[^"']/um
+
+      def initialize( source )
+        self.stream = source
+      end
+
+      def add_listener( listener )
+        if !defined?(@listeners) or !@listeners
+          @listeners = []
+          instance_eval <<-EOL
+            alias :_old_pull :pull
+            def pull
+              event = _old_pull
+              @listeners.each do |listener|
+                listener.receive event
+              end
+              event
+            end
+          EOL
+        end
+        @listeners << listener
+      end
+
+      attr_reader :source
+
+      def stream=( source )
+        @source = SourceFactory.create_from( source )
+        @closed = nil
+        @document_status = nil
+        @tags = []
+        @stack = []
+        @entities = []
+      end
+
+      def position
+        if @source.respond_to? :position
+          @source.position
+        else
+          # FIXME
+          0
+        end
+      end
+
+      # Returns true if there are no more events
+      def empty?
+        return (@source.empty? and @stack.empty?)
+      end
+
+      # Returns true if there are more events.  Synonymous with !empty?
+      def has_next?
+        return !(@source.empty? and @stack.empty?)
+      end
+
+      # Push an event back on the head of the stream.  This method
+      # has (theoretically) infinite depth.
+      def unshift token
+        @stack.unshift(token)
+      end
+
+      # Peek at the +depth+ event in the stack.  The first element on the stack
+      # is at depth 0.  If +depth+ is -1, will parse to the end of the input
+      # stream and return the last event, which is always :end_document.
+      # Be aware that this causes the stream to be parsed up to the +depth+ 
+      # event, so you can effectively pre-parse the entire document (pull the 
+      # entire thing into memory) using this method.  
+      def peek depth=0
+        raise %Q[Illegal argument "#{depth}"] if depth < -1
+        temp = []
+        if depth == -1
+          temp.push(pull()) until empty?
+        else
+          while @stack.size+temp.size < depth+1
+            temp.push(pull())
+          end
+        end
+        @stack += temp if temp.size > 0
+        @stack[depth]
+      end
+
+      # Returns the next event.  This is a +PullEvent+ object.
+      def pull
+        if @closed
+          x, @closed = @closed, nil
+          return [ :end_element, x ]
+        end
+        return [ :end_document ] if empty?
+        return @stack.shift if @stack.size > 0
+        @source.read if @source.buffer.size<2
+        #STDERR.puts "BUFFER = #{@source.buffer.inspect}"
+        if @document_status == nil
+          #@source.consume( /^\s*/um )
+          word = @source.match( /^((?:\s+)|(?:<[^>]*>))/um )
+          word = word[1] unless word.nil?
+          #STDERR.puts "WORD = #{word.inspect}"
+          case word
+          when COMMENT_START
+            return [ :comment, @source.match( COMMENT_PATTERN, true )[1] ]
+          when XMLDECL_START
+            #STDERR.puts "XMLDECL"
+            results = @source.match( XMLDECL_PATTERN, true )[1]
+            version = VERSION.match( results )
+            version = version[1] unless version.nil?
+            encoding = ENCODING.match(results)
+            encoding = encoding[1] unless encoding.nil?
+            @source.encoding = encoding
+            standalone = STANDALONE.match(results)
+            standalone = standalone[1] unless standalone.nil?
+            return [ :xmldecl, version, encoding, standalone ]
+          when INSTRUCTION_START
+            return [ :processing_instruction, *@source.match(INSTRUCTION_PATTERN, true)[1,2] ]
+          when DOCTYPE_START
+            md = @source.match( DOCTYPE_PATTERN, true )
+            identity = md[1]
+            close = md[2]
+            identity =~ IDENTITY
+            name = $1
+            raise REXML::ParseException("DOCTYPE is missing a name") if name.nil?
+            pub_sys = $2.nil? ? nil : $2.strip
+            long_name = $3.nil? ? nil : $3.strip
+            uri = $4.nil? ? nil : $4.strip
+            args = [ :start_doctype, name, pub_sys, long_name, uri ]
+            if close == ">"
+              @document_status = :after_doctype
+              @source.read if @source.buffer.size<2
+              md = @source.match(/^\s*/um, true)
+              @stack << [ :end_doctype ]
+            else
+              @document_status = :in_doctype
+            end
+            return args
+          when /^\s+/
+          else
+            @document_status = :after_doctype
+            @source.read if @source.buffer.size<2
+            md = @source.match(/\s*/um, true)
+          end
+        end
+        if @document_status == :in_doctype
+          md = @source.match(/\s*(.*?>)/um)
+          case md[1]
+          when SYSTEMENTITY 
+            match = @source.match( SYSTEMENTITY, true )[1]
+            return [ :externalentity, match ]
+
+          when ELEMENTDECL_START
+            return [ :elementdecl, @source.match( ELEMENTDECL_PATTERN, true )[1] ]
+
+          when ENTITY_START
+            match = @source.match( ENTITYDECL, true ).to_a.compact
+            match[0] = :entitydecl
+            ref = false
+            if match[1] == '%'
+              ref = true
+              match.delete_at 1
+            end
+            # Now we have to sort out what kind of entity reference this is
+            if match[2] == 'SYSTEM'
+              # External reference
+              match[3] = match[3][1..-2] # PUBID
+              match.delete_at(4) if match.size > 4 # Chop out NDATA decl
+              # match is [ :entity, name, SYSTEM, pubid(, ndata)? ]
+            elsif match[2] == 'PUBLIC'
+              # External reference
+              match[3] = match[3][1..-2] # PUBID
+              match[4] = match[4][1..-2] # HREF
+              # match is [ :entity, name, PUBLIC, pubid, href ]
+            else
+              match[2] = match[2][1..-2]
+              match.pop if match.size == 4
+              # match is [ :entity, name, value ]
+            end
+            match << '%' if ref
+            return match
+          when ATTLISTDECL_START
+            md = @source.match( ATTLISTDECL_PATTERN, true )
+            raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil?
+            element = md[1]
+            contents = md[0]
+
+            pairs = {}
+            values = md[0].scan( ATTDEF_RE )
+            values.each do |attdef|
+              unless attdef[3] == "#IMPLIED"
+                attdef.compact!
+                val = attdef[3]
+                val = attdef[4] if val == "#FIXED "
+                pairs[attdef[0]] = val
+              end
+            end
+            return [ :attlistdecl, element, pairs, contents ]
+          when NOTATIONDECL_START
+            md = nil
+            if @source.match( PUBLIC )
+              md = @source.match( PUBLIC, true )
+              vals = [md[1],md[2],md[4],md[6]]
+            elsif @source.match( SYSTEM )
+              md = @source.match( SYSTEM, true )
+              vals = [md[1],md[2],nil,md[4]]
+            else
+              raise REXML::ParseException.new( "error parsing notation: no matching pattern", @source )
+            end
+            return [ :notationdecl, *vals ]
+          when CDATA_END
+            @document_status = :after_doctype
+            @source.match( CDATA_END, true )
+            return [ :end_doctype ]
+          end
+        end
+        begin
+          if @source.buffer[0] == ?<
+            if @source.buffer[1] == ?/
+              last_tag = @tags.pop
+              #md = @source.match_to_consume( '>', CLOSE_MATCH)
+              md = @source.match( CLOSE_MATCH, true )
+              raise REXML::ParseException.new( "Missing end tag for "+
+                "'#{last_tag}' (got \"#{md[1]}\")", 
+                @source) unless last_tag == md[1]
+              return [ :end_element, last_tag ]
+            elsif @source.buffer[1] == ?!
+              md = @source.match(/\A(\s*[^>]*>)/um)
+              #STDERR.puts "SOURCE BUFFER = #{source.buffer}, #{source.buffer.size}"
+              raise REXML::ParseException.new("Malformed node", @source) unless md
+              if md[0][2] == ?-
+                md = @source.match( COMMENT_PATTERN, true )
+                return [ :comment, md[1] ] if md
+              else
+                md = @source.match( CDATA_PATTERN, true )
+                return [ :cdata, md[1] ] if md
+              end
+              raise REXML::ParseException.new( "Declarations can only occur "+
+                "in the doctype declaration.", @source)
+            elsif @source.buffer[1] == ??
+              md = @source.match( INSTRUCTION_PATTERN, true )
+              return [ :processing_instruction, md[1], md[2] ] if md
+              raise REXML::ParseException.new( "Bad instruction declaration",
+                @source)
+            else
+              # Get the next tag
+              md = @source.match(TAG_MATCH, true)
+              unless md
+                # Check for missing attribute quotes
+                raise REXML::ParseException.new("missing attribute quote", @source) if @source.match(MISSING_ATTRIBUTE_QUOTES )
+                raise REXML::ParseException.new("malformed XML: missing tag start", @source) 
+              end
+              attrs = []
+              if md[2].size > 0
+                attrs = md[2].scan( ATTRIBUTE_PATTERN )
+                raise REXML::ParseException.new( "error parsing attributes: [#{attrs.join ', '}], excess = \"#$'\"", @source) if $' and $'.strip.size > 0
+              end
+        
+              if md[4]
+                @closed = md[1]
+              else
+                @tags.push( md[1] )
+              end
+              attributes = {}
+              attrs.each { |a,b,c| attributes[a] = c }
+              return [ :start_element, md[1], attributes ]
+            end
+          else
+            md = @source.match( TEXT_PATTERN, true )
+            if md[0].length == 0
+              @source.match( /(\s+)/, true )
+            end
+            #STDERR.puts "GOT #{md[1].inspect}" unless md[0].length == 0
+            #return [ :text, "" ] if md[0].length == 0
+            # unnormalized = Text::unnormalize( md[1], self )
+            # return PullEvent.new( :text, md[1], unnormalized )
+            return [ :text, md[1] ]
+          end
+        rescue REXML::ParseException
+          raise
+        rescue Exception, NameError => error
+          raise REXML::ParseException.new( "Exception parsing",
+            @source, self, (error ? error : $!) )
+        end
+        return [ :dummy ]
+      end
+
+      def entity( reference, entities )
+        value = nil
+        value = entities[ reference ] if entities
+        if not value
+          value = DEFAULT_ENTITIES[ reference ]
+          value = value[2] if value
+        end
+        unnormalize( value, entities ) if value
+      end
+
+      # Escapes all possible entities
+      def normalize( input, entities=nil, entity_filter=nil )
+        copy = input.clone
+        # Doing it like this rather than in a loop improves the speed
+        copy.gsub!( EREFERENCE, '&amp;' )
+        entities.each do |key, value|
+          copy.gsub!( value, "&#{key};" ) unless entity_filter and 
+                                      entity_filter.include?(entity)
+        end if entities
+        copy.gsub!( EREFERENCE, '&amp;' )
+        DEFAULT_ENTITIES.each do |key, value|
+          copy.gsub!( value[3], value[1] )
+        end
+        copy
+      end
+
+      # Unescapes all possible entities
+      def unnormalize( string, entities=nil, filter=nil )
+        rv = string.clone
+        rv.gsub!( /\r\n?/, "\n" )
+        matches = rv.scan( REFERENCE_RE )
+        return rv if matches.size == 0
+        rv.gsub!( /&#0*((?:\d+)|(?:x[a-fA-F0-9]+));/ ) {|m|
+          m=$1
+          m = "0#{m}" if m[0] == ?x
+          [Integer(m)].pack('U*')
+        }
+        matches.collect!{|x|x[0]}.compact!
+        if matches.size > 0
+          matches.each do |entity_reference|
+            unless filter and filter.include?(entity_reference)
+              entity_value = entity( entity_reference, entities )
+              if entity_value
+                re = /&#{entity_reference};/
+                rv.gsub!( re, entity_value )
+              end
+            end
+          end
+          matches.each do |entity_reference|
+            unless filter and filter.include?(entity_reference)
+              er = DEFAULT_ENTITIES[entity_reference]
+              rv.gsub!( er[0], er[2] ) if er
+            end
+          end
+          rv.gsub!( /&amp;/, '&' )
+        end
+        rv
+      end
+    end
+  end
+end
+
+=begin
+  case event[0]
+  when :start_element
+  when :text
+  when :end_element
+  when :processing_instruction
+  when :cdata
+  when :comment
+  when :xmldecl
+  when :start_doctype
+  when :end_doctype
+  when :externalentity
+  when :elementdecl
+  when :entity
+  when :attlistdecl
+  when :notationdecl
+  when :end_doctype
+  end
+=end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/lightparser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/lightparser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/lightparser.rb	(revision 18425)
@@ -0,0 +1,60 @@
+require 'rexml/parsers/streamparser'
+require 'rexml/parsers/baseparser'
+require 'rexml/light/node'
+
+module REXML
+	module Parsers
+		class LightParser
+			def initialize stream
+				@stream = stream
+				@parser = REXML::Parsers::BaseParser.new( stream )
+			end
+
+      def add_listener( listener )
+        @parser.add_listener( listener )
+      end
+
+      def rewind
+        @stream.rewind
+        @parser.stream = @stream
+      end
+
+			def parse
+				root = context = [ :document ]
+				while true
+					event = @parser.pull
+					case event[0]
+					when :end_document
+						break
+					when :end_doctype
+						context = context[1]
+					when :start_element, :start_doctype
+						new_node = event
+						context << new_node
+						new_node[1,0] = [context]
+						context = new_node
+					when :end_element, :end_doctype
+						context = context[1]
+					else
+						new_node = event
+						context << new_node
+						new_node[1,0] = [context]
+					end
+				end
+				root
+			end
+		end
+
+		# An element is an array.  The array contains:
+		#  0			The parent element
+		#  1			The tag name
+		#  2			A hash of attributes
+		#  3..-1	The child elements
+		# An element is an array of size > 3
+		# Text is a String
+		# PIs are [ :processing_instruction, target, data ]
+		# Comments are [ :comment, data ]
+		# DocTypes are DocType structs
+		# The root is an array with XMLDecls, Text, DocType, Array, Text
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/pullparser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/pullparser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/pullparser.rb	(revision 18425)
@@ -0,0 +1,196 @@
+require 'forwardable'
+
+require 'rexml/parseexception'
+require 'rexml/parsers/baseparser'
+require 'rexml/xmltokens'
+
+module REXML
+  module Parsers
+    # = Using the Pull Parser
+    # <em>This API is experimental, and subject to change.</em>
+    #  parser = PullParser.new( "<a>text<b att='val'/>txet</a>" )
+    #  while parser.has_next?
+    #    res = parser.next
+    #    puts res[1]['att'] if res.start_tag? and res[0] == 'b'
+    #  end
+    # See the PullEvent class for information on the content of the results.
+    # The data is identical to the arguments passed for the various events to
+    # the StreamListener API.
+    #
+    # Notice that:
+    #  parser = PullParser.new( "<a>BAD DOCUMENT" )
+    #  while parser.has_next?
+    #    res = parser.next
+    #    raise res[1] if res.error?
+    #  end
+    #
+    # Nat Price gave me some good ideas for the API.
+    class PullParser
+      include XMLTokens
+      extend Forwardable
+
+      def_delegators( :@parser, :has_next? )
+      def_delegators( :@parser, :entity )
+      def_delegators( :@parser, :empty? )
+      def_delegators( :@parser, :source )
+
+      def initialize stream
+        @entities = {}
+        @listeners = nil
+        @parser = BaseParser.new( stream )
+        @my_stack = []
+      end
+
+      def add_listener( listener )
+        @listeners = [] unless @listeners
+        @listeners << listener
+      end
+
+      def each
+        while has_next?
+          yield self.pull
+        end
+      end
+
+      def peek depth=0
+        if @my_stack.length <= depth
+          (depth - @my_stack.length + 1).times {
+            e = PullEvent.new(@parser.pull)
+            @my_stack.push(e)
+          }
+        end
+        @my_stack[depth]
+      end
+
+      def pull
+        return @my_stack.shift if @my_stack.length > 0
+
+        event = @parser.pull
+        case event[0]
+        when :entitydecl
+          @entities[ event[1] ] = 
+            event[2] unless event[2] =~ /PUBLIC|SYSTEM/
+        when :text
+          unnormalized = @parser.unnormalize( event[1], @entities )
+          event << unnormalized
+        end
+        PullEvent.new( event )
+      end
+
+      def unshift token
+        @my_stack.unshift token
+      end
+    end
+
+    # A parsing event.  The contents of the event are accessed as an +Array?,
+    # and the type is given either by the ...? methods, or by accessing the
+    # +type+ accessor.  The contents of this object vary from event to event,
+    # but are identical to the arguments passed to +StreamListener+s for each
+    # event.
+    class PullEvent
+      # The type of this event.  Will be one of :tag_start, :tag_end, :text,
+      # :processing_instruction, :comment, :doctype, :attlistdecl, :entitydecl,
+      # :notationdecl, :entity, :cdata, :xmldecl, or :error.
+      def initialize(arg)
+        @contents = arg
+      end
+
+      def []( start, endd=nil)
+        if start.kind_of? Range
+          @contents.slice( start.begin+1 .. start.end )
+        elsif start.kind_of? Numeric
+          if endd.nil?
+            @contents.slice( start+1 )
+          else
+            @contents.slice( start+1, endd )
+          end
+        else
+          raise "Illegal argument #{start.inspect} (#{start.class})"
+        end
+      end
+
+      def event_type
+        @contents[0]
+      end
+
+      # Content: [ String tag_name, Hash attributes ]
+      def start_element?
+        @contents[0] == :start_element
+      end
+
+      # Content: [ String tag_name ]
+      def end_element?
+        @contents[0] == :end_element
+      end
+
+      # Content: [ String raw_text, String unnormalized_text ]
+      def text?
+        @contents[0] == :text
+      end
+
+      # Content: [ String text ]
+      def instruction?
+        @contents[0] == :processing_instruction
+      end
+
+      # Content: [ String text ]
+      def comment?
+        @contents[0] == :comment
+      end
+
+      # Content: [ String name, String pub_sys, String long_name, String uri ]
+      def doctype?
+        @contents[0] == :start_doctype
+      end
+
+      # Content: [ String text ]
+      def attlistdecl?
+        @contents[0] == :attlistdecl
+      end
+
+      # Content: [ String text ]
+      def elementdecl?
+        @contents[0] == :elementdecl
+      end
+
+      # Due to the wonders of DTDs, an entity declaration can be just about
+      # anything.  There's no way to normalize it; you'll have to interpret the
+      # content yourself.  However, the following is true:
+      #
+      # * If the entity declaration is an internal entity:
+      #   [ String name, String value ]
+      # Content: [ String text ]
+      def entitydecl?
+        @contents[0] == :entitydecl
+      end
+
+      # Content: [ String text ]
+      def notationdecl?
+        @contents[0] == :notationdecl
+      end
+
+      # Content: [ String text ]
+      def entity?
+        @contents[0] == :entity
+      end
+
+      # Content: [ String text ]
+      def cdata?
+        @contents[0] == :cdata
+      end
+
+      # Content: [ String version, String encoding, String standalone ]
+      def xmldecl?
+        @contents[0] == :xmldecl
+      end
+
+      def error?
+        @contents[0] == :error
+      end
+
+      def inspect
+        @contents[0].to_s + ": " + @contents[1..-1].inspect
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/sax2parser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/sax2parser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/sax2parser.rb	(revision 18425)
@@ -0,0 +1,236 @@
+require 'rexml/parsers/baseparser'
+require 'rexml/parseexception'
+require 'rexml/namespace'
+require 'rexml/text'
+
+module REXML
+	module Parsers
+    # SAX2Parser
+		class SAX2Parser
+			def initialize source
+				@parser = BaseParser.new(source)
+				@listeners = []
+				@procs = []
+				@namespace_stack = []
+				@has_listeners = false
+				@tag_stack = []
+        @entities = {}
+			end
+
+      def source
+        @parser.source
+      end
+			
+      def add_listener( listener )
+        @parser.add_listener( listener )
+      end
+
+			# Listen arguments:
+			#
+			# Symbol, Array, Block
+			# 	Listen to Symbol events on Array elements
+			# Symbol, Block
+			#   Listen to Symbol events
+			# Array, Listener
+			# 	Listen to all events on Array elements
+			# Array, Block
+			# 	Listen to :start_element events on Array elements
+			# Listener
+			# 	Listen to All events
+			#
+			# Symbol can be one of: :start_element, :end_element,
+			# :start_prefix_mapping, :end_prefix_mapping, :characters,
+			# :processing_instruction, :doctype, :attlistdecl, :elementdecl,
+			# :entitydecl, :notationdecl, :cdata, :xmldecl, :comment
+      #
+      # There is an additional symbol that can be listened for: :progress.
+      # This will be called for every event generated, passing in the current 
+      # stream position.
+			#
+			# Array contains regular expressions or strings which will be matched
+			# against fully qualified element names.
+			#
+			# Listener must implement the methods in SAX2Listener
+			#
+			# Block will be passed the same arguments as a SAX2Listener method would
+			# be, where the method name is the same as the matched Symbol.
+			# See the SAX2Listener for more information.
+			def listen( *args, &blok )
+				if args[0].kind_of? Symbol
+					if args.size == 2
+						args[1].each { |match| @procs << [args[0], match, blok] }
+					else
+						add( [args[0], nil, blok] )
+					end
+				elsif args[0].kind_of? Array
+					if args.size == 2
+						args[0].each { |match| add( [nil, match, args[1]] ) }
+					else
+						args[0].each { |match| add( [ :start_element, match, blok ] ) }
+					end
+				else
+					add([nil, nil, args[0]])
+				end
+			end
+			
+			def deafen( listener=nil, &blok )
+				if listener
+					@listeners.delete_if {|item| item[-1] == listener }
+					@has_listeners = false if @listeners.size == 0
+				else
+					@procs.delete_if {|item| item[-1] == blok }
+				end
+			end
+			
+			def parse
+				@procs.each { |sym,match,block| block.call if sym == :start_document }
+				@listeners.each { |sym,match,block| 
+					block.start_document if sym == :start_document or sym.nil?
+				}
+				root = context = []
+				while true
+					event = @parser.pull
+					case event[0]
+					when :end_document
+						handle( :end_document )
+						break
+					when :end_doctype
+						context = context[1]
+					when :start_element
+						@tag_stack.push(event[1])
+						# find the observers for namespaces
+						procs = get_procs( :start_prefix_mapping, event[1] )
+						listeners = get_listeners( :start_prefix_mapping, event[1] )
+						if procs or listeners
+							# break out the namespace declarations
+							# The attributes live in event[2]
+							event[2].each {|n, v| event[2][n] = @parser.normalize(v)}
+							nsdecl = event[2].find_all { |n, value| n =~ /^xmlns(:|$)/ }
+							nsdecl.collect! { |n, value| [ n[6..-1], value ] }
+							@namespace_stack.push({})
+							nsdecl.each do |n,v|
+								@namespace_stack[-1][n] = v
+								# notify observers of namespaces
+								procs.each { |ob| ob.call( n, v ) } if procs
+								listeners.each { |ob| ob.start_prefix_mapping(n, v) } if listeners
+							end
+						end
+						event[1] =~ Namespace::NAMESPLIT
+						prefix = $1
+						local = $2
+						uri = get_namespace(prefix)
+						# find the observers for start_element
+						procs = get_procs( :start_element, event[1] )
+						listeners = get_listeners( :start_element, event[1] )
+						# notify observers
+						procs.each { |ob| ob.call( uri, local, event[1], event[2] ) } if procs
+						listeners.each { |ob| 
+							ob.start_element( uri, local, event[1], event[2] ) 
+						} if listeners
+					when :end_element
+						@tag_stack.pop
+						event[1] =~ Namespace::NAMESPLIT
+						prefix = $1
+						local = $2
+						uri = get_namespace(prefix)
+						# find the observers for start_element
+						procs = get_procs( :end_element, event[1] )
+						listeners = get_listeners( :end_element, event[1] )
+						# notify observers
+						procs.each { |ob| ob.call( uri, local, event[1] ) } if procs
+						listeners.each { |ob| 
+							ob.end_element( uri, local, event[1] ) 
+						} if listeners
+
+						namespace_mapping = @namespace_stack.pop
+						# find the observers for namespaces
+						procs = get_procs( :end_prefix_mapping, event[1] )
+						listeners = get_listeners( :end_prefix_mapping, event[1] )
+						if procs or listeners
+							namespace_mapping.each do |prefix, uri|
+								# notify observers of namespaces
+								procs.each { |ob| ob.call( prefix ) } if procs
+								listeners.each { |ob| ob.end_prefix_mapping(prefix) } if listeners
+							end
+						end
+					when :text
+            #normalized = @parser.normalize( event[1] )
+            #handle( :characters, normalized )
+            copy = event[1].clone
+            @entities.each { |key, value| copy = copy.gsub("&#{key};", value) }
+            copy.gsub!( Text::NUMERICENTITY ) {|m|
+              m=$1
+              m = "0#{m}" if m[0] == ?x
+              [Integer(m)].pack('U*')
+            }
+            handle( :characters, copy )
+          when :entitydecl
+            @entities[ event[1] ] = event[2] if event.size == 3
+						handle( *event )
+					when :processing_instruction, :comment, :doctype, :attlistdecl, 
+						:elementdecl, :cdata, :notationdecl, :xmldecl
+						handle( *event )
+					end
+          handle( :progress, @parser.position )
+				end
+			end
+
+			private
+			def handle( symbol, *arguments )
+				tag = @tag_stack[-1]
+				procs = get_procs( symbol, tag )
+				listeners = get_listeners( symbol, tag )
+				# notify observers
+				procs.each { |ob| ob.call( *arguments ) } if procs
+				listeners.each { |l| 
+					l.send( symbol.to_s, *arguments ) 
+				} if listeners
+			end
+
+			# The following methods are duplicates, but it is faster than using
+			# a helper
+			def get_procs( symbol, name )
+				return nil if @procs.size == 0
+				@procs.find_all do |sym, match, block|
+          #puts sym.inspect+"=="+symbol.inspect+ "\t"+match.inspect+"=="+name.inspect+ "\t"+( (sym.nil? or symbol == sym) and ((name.nil? and match.nil?) or match.nil? or ( (name == match) or (match.kind_of? Regexp and name =~ match)))).to_s
+					(
+						(sym.nil? or symbol == sym) and 
+						((name.nil? and match.nil?) or match.nil? or (
+							(name == match) or
+							(match.kind_of? Regexp and name =~ match)
+							)
+						)
+					)
+				end.collect{|x| x[-1]}
+			end
+			def get_listeners( symbol, name )
+				return nil if @listeners.size == 0
+				@listeners.find_all do |sym, match, block|
+					(
+						(sym.nil? or symbol == sym) and 
+						((name.nil? and match.nil?) or match.nil? or (
+							(name == match) or
+							(match.kind_of? Regexp and name =~ match)
+							)
+						)
+					)
+				end.collect{|x| x[-1]}
+			end
+
+			def add( pair )
+				if pair[-1].respond_to? :call
+					@procs << pair unless @procs.include? pair
+				else
+					@listeners << pair unless @listeners.include? pair
+					@has_listeners = true
+				end
+			end
+
+			def get_namespace( prefix ) 
+        uris = (@namespace_stack.find_all { |ns| not ns[prefix].nil? }) ||
+					(@namespace_stack.find { |ns| not ns[nil].nil? })
+				uris[-1][prefix] unless uris.nil? or 0 == uris.size
+			end
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/streamparser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/streamparser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/streamparser.rb	(revision 18425)
@@ -0,0 +1,46 @@
+module REXML
+  module Parsers
+    class StreamParser
+      def initialize source, listener
+        @listener = listener
+        @parser = BaseParser.new( source )
+      end
+      
+      def add_listener( listener )
+        @parser.add_listener( listener )
+      end
+      
+      def parse
+        # entity string
+        while true
+          event = @parser.pull
+          case event[0]
+          when :end_document
+            return
+          when :start_element
+            attrs = event[2].each do |n, v|
+              event[2][n] = @parser.unnormalize( v )
+            end
+            @listener.tag_start( event[1], attrs )
+          when :end_element
+            @listener.tag_end( event[1] )
+          when :text
+            normalized = @parser.unnormalize( event[1] )
+            @listener.text( normalized )
+          when :processing_instruction
+            @listener.instruction( *event[1,2] )
+          when :start_doctype
+            @listener.doctype( *event[1..-1] )
+          when :end_doctype
+            # FIXME: remove this condition for milestone:3.2
+            @listener.doctype_end if @listener.respond_to? :doctype_end
+          when :comment, :attlistdecl, :cdata, :xmldecl, :elementdecl
+            @listener.send( event[0].to_s, *event[1..-1] )
+          when :entitydecl, :notationdecl
+            @listener.send( event[0].to_s, event[1..-1] )
+          end
+        end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/treeparser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/treeparser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/treeparser.rb	(revision 18425)
@@ -0,0 +1,95 @@
+require 'rexml/validation/validationexception'
+
+module REXML
+  module Parsers
+    class TreeParser
+      def initialize( source, build_context = Document.new )
+        @build_context = build_context
+        @parser = Parsers::BaseParser.new( source )
+      end
+
+      def add_listener( listener )
+        @parser.add_listener( listener )
+      end
+
+      def parse
+        tag_stack = []
+        in_doctype = false
+        entities = nil
+        begin
+          while true
+            event = @parser.pull
+            #STDERR.puts "TREEPARSER GOT #{event.inspect}"
+            case event[0]
+            when :end_document
+              unless tag_stack.empty?
+                #raise ParseException.new("No close tag for #{tag_stack.inspect}")
+                raise ParseException.new("No close tag for #{@build_context.xpath}")
+              end
+              return
+            when :start_element
+              tag_stack.push(event[1])
+              # find the observers for namespaces
+              @build_context = @build_context.add_element( event[1], event[2] )
+            when :end_element
+              tag_stack.pop
+              @build_context = @build_context.parent
+            when :text
+              if not in_doctype
+                if @build_context[-1].instance_of? Text
+                  @build_context[-1] << event[1]
+                else
+                  @build_context.add( 
+                    Text.new(event[1], @build_context.whitespace, nil, true) 
+                  ) unless (
+                    @build_context.ignore_whitespace_nodes and
+                    event[1].strip.size==0
+                  )
+                end
+              end
+            when :comment
+              c = Comment.new( event[1] )
+              @build_context.add( c )
+            when :cdata
+              c = CData.new( event[1] )
+              @build_context.add( c )
+            when :processing_instruction
+              @build_context.add( Instruction.new( event[1], event[2] ) )
+            when :end_doctype
+              in_doctype = false
+              entities.each { |k,v| entities[k] = @build_context.entities[k].value }
+              @build_context = @build_context.parent
+            when :start_doctype
+              doctype = DocType.new( event[1..-1], @build_context )
+              @build_context = doctype
+              entities = {}
+              in_doctype = true
+            when :attlistdecl
+              n = AttlistDecl.new( event[1..-1] )
+              @build_context.add( n )
+            when :externalentity
+              n = ExternalEntity.new( event[1] )
+              @build_context.add( n )
+            when :elementdecl
+              n = ElementDecl.new( event[1] )
+              @build_context.add(n)
+            when :entitydecl
+              entities[ event[1] ] = event[2] unless event[2] =~ /PUBLIC|SYSTEM/
+              @build_context.add(Entity.new(event))
+            when :notationdecl
+              n = NotationDecl.new( *event[1..-1] )
+              @build_context.add( n )
+            when :xmldecl
+              x = XMLDecl.new( event[1], event[2], event[3] )
+              @build_context.add( x )
+            end
+          end
+        rescue REXML::Validation::ValidationException
+          raise
+        rescue
+          raise ParseException.new( $!.message, @parser.source, @parser, $! )
+        end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/ultralightparser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/ultralightparser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/ultralightparser.rb	(revision 18425)
@@ -0,0 +1,56 @@
+require 'rexml/parsers/streamparser'
+require 'rexml/parsers/baseparser'
+
+module REXML
+	module Parsers
+		class UltraLightParser
+			def initialize stream
+				@stream = stream
+				@parser = REXML::Parsers::BaseParser.new( stream )
+			end
+
+      def add_listener( listener )
+        @parser.add_listener( listener )
+      end
+
+      def rewind
+        @stream.rewind
+        @parser.stream = @stream
+      end
+
+			def parse
+				root = context = []
+				while true
+					event = @parser.pull
+					case event[0]
+					when :end_document
+						break
+					when :end_doctype
+						context = context[1]
+					when :start_element, :doctype
+						context << event
+						event[1,0] = [context]
+						context = event
+					when :end_element
+						context = context[1]
+					else
+						context << event
+					end
+				end
+				root
+			end
+		end
+
+		# An element is an array.  The array contains:
+		#  0			The parent element
+		#  1			The tag name
+		#  2			A hash of attributes
+		#  3..-1	The child elements
+		# An element is an array of size > 3
+		# Text is a String
+		# PIs are [ :processing_instruction, target, data ]
+		# Comments are [ :comment, data ]
+		# DocTypes are DocType structs
+		# The root is an array with XMLDecls, Text, DocType, Array, Text
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/xpathparser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/xpathparser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/parsers/xpathparser.rb	(revision 18425)
@@ -0,0 +1,698 @@
+require 'rexml/namespace'
+require 'rexml/xmltokens'
+
+module REXML
+  module Parsers
+    # You don't want to use this class.  Really.  Use XPath, which is a wrapper
+    # for this class.  Believe me.  You don't want to poke around in here.
+    # There is strange, dark magic at work in this code.  Beware.  Go back!  Go
+    # back while you still can!
+    class XPathParser
+      include XMLTokens
+      LITERAL    = /^'([^']*)'|^"([^"]*)"/u
+
+      def namespaces=( namespaces )
+        Functions::namespace_context = namespaces
+        @namespaces = namespaces
+      end
+
+      def parse path
+        path.gsub!(/([\(\[])\s+/, '\1') # Strip ignorable spaces
+        path.gsub!( /\s+([\]\)])/, '\1' )
+        parsed = []
+        path = OrExpr(path, parsed)
+        parsed
+      end
+
+      def predicate path
+        parsed = []
+        Predicate( "[#{path}]", parsed )
+        parsed
+      end
+
+      def abbreviate( path )
+        path = path.kind_of?(String) ? parse( path ) : path
+        string = ""
+        document = false
+        while path.size > 0
+          op = path.shift
+          case op
+          when :node
+          when :attribute
+						string << "/" if string.size > 0
+						string << "@"
+          when :child
+						string << "/" if string.size > 0
+          when :descendant_or_self
+            string << "/"
+          when :self
+            string << "."
+          when :parent
+            string << ".."
+          when :any
+            string << "*"
+					when :text
+						string << "text()"
+          when :following, :following_sibling, 
+                :ancestor, :ancestor_or_self, :descendant, 
+                :namespace, :preceding, :preceding_sibling
+            string << "/" unless string.size == 0
+            string << op.to_s.tr("_", "-")
+            string << "::"
+          when :qname
+            prefix = path.shift
+            name = path.shift
+            string << prefix+":" if prefix.size > 0
+            string << name
+          when :predicate
+            string << '['
+            string << predicate_to_string( path.shift ) {|x| abbreviate( x ) }
+            string << ']'
+          when :document
+            document = true
+					when :function
+						string << path.shift
+						string << "( "
+						string << predicate_to_string( path.shift[0] ) {|x| abbreviate( x )}
+						string << " )"
+					when :literal
+						string << %Q{ "#{path.shift}" }
+          else
+            string << "/" unless string.size == 0
+            string << "UNKNOWN("
+            string << op.inspect
+            string << ")"
+          end
+        end
+				string = "/"+string if document
+        return string
+      end
+
+      def expand( path )
+        path = path.kind_of?(String) ? parse( path ) : path
+        string = ""
+        document = false
+        while path.size > 0
+          op = path.shift
+          case op
+          when :node
+            string << "node()"
+          when :attribute, :child, :following, :following_sibling, 
+                :ancestor, :ancestor_or_self, :descendant, :descendant_or_self,
+                :namespace, :preceding, :preceding_sibling, :self, :parent
+            string << "/" unless string.size == 0
+            string << op.to_s.tr("_", "-")
+            string << "::"
+          when :any
+            string << "*"
+          when :qname
+            prefix = path.shift
+            name = path.shift
+            string << prefix+":" if prefix.size > 0
+            string << name
+          when :predicate
+            string << '['
+            string << predicate_to_string( path.shift ) { |x| expand(x) }
+            string << ']'
+          when :document
+            document = true
+          else
+            string << "/" unless string.size == 0
+            string << "UNKNOWN("
+            string << op.inspect
+            string << ")"
+          end
+        end
+        string = "/"+string if document
+        return string
+      end
+
+      def predicate_to_string( path, &block )
+        string = ""
+        case path[0]
+        when :and, :or, :mult, :plus, :minus, :neq, :eq, :lt, :gt, :lteq, :gteq, :div, :mod, :union
+          op = path.shift
+          case op
+          when :eq
+            op = "="
+          when :lt
+            op = "<"
+          when :gt
+            op = ">"
+          when :lteq
+            op = "<="
+          when :gteq
+            op = ">="
+          when :neq
+            op = "!="
+          when :union
+            op = "|"
+          end
+          left = predicate_to_string( path.shift, &block )
+          right = predicate_to_string( path.shift, &block )
+          string << " "
+          string << left
+          string << " "
+          string << op.to_s
+          string << " "
+          string << right
+          string << " "
+        when :function
+          path.shift
+          name = path.shift
+          string << name
+          string << "( "
+          string << predicate_to_string( path.shift, &block )
+          string << " )"
+        when :literal
+          path.shift
+          string << " "
+          string << path.shift.inspect
+          string << " "
+        else
+          string << " "
+          string << yield( path )
+          string << " "
+        end
+        return string.squeeze(" ")
+      end
+
+      private
+      #LocationPath
+      #  | RelativeLocationPath
+      #  | '/' RelativeLocationPath?
+      #  | '//' RelativeLocationPath
+      def LocationPath path, parsed
+        #puts "LocationPath '#{path}'"
+        path = path.strip
+        if path[0] == ?/
+          parsed << :document
+          if path[1] == ?/
+            parsed << :descendant_or_self
+            parsed << :node
+            path = path[2..-1]
+          else
+            path = path[1..-1]
+          end
+        end
+        #puts parsed.inspect
+        return RelativeLocationPath( path, parsed ) if path.size > 0
+      end
+
+      #RelativeLocationPath
+      #  |                                                    Step
+      #    | (AXIS_NAME '::' | '@' | '')                     AxisSpecifier
+      #      NodeTest
+      #        Predicate
+      #    | '.' | '..'                                      AbbreviatedStep
+      #  |  RelativeLocationPath '/' Step
+      #  | RelativeLocationPath '//' Step
+      AXIS = /^(ancestor|ancestor-or-self|attribute|child|descendant|descendant-or-self|following|following-sibling|namespace|parent|preceding|preceding-sibling|self)::/
+      def RelativeLocationPath path, parsed
+        #puts "RelativeLocationPath #{path}"
+        while path.size > 0
+          # (axis or @ or <child::>) nodetest predicate  >
+          # OR                                          >  / Step
+          # (. or ..)                                    >
+          if path[0] == ?.
+            if path[1] == ?.
+              parsed << :parent
+              parsed << :node
+              path = path[2..-1]
+            else
+              parsed << :self
+              parsed << :node
+              path = path[1..-1]
+            end
+          else
+            if path[0] == ?@
+              #puts "ATTRIBUTE"
+              parsed << :attribute
+              path = path[1..-1]
+              # Goto Nodetest
+            elsif path =~ AXIS
+              parsed << $1.tr('-','_').intern
+              path = $'
+              # Goto Nodetest
+            else
+              parsed << :child
+            end
+
+            #puts "NODETESTING '#{path}'"
+            n = []
+            path = NodeTest( path, n)
+            #puts "NODETEST RETURNED '#{path}'"
+
+            if path[0] == ?[
+              path = Predicate( path, n )
+            end
+
+            parsed.concat(n)
+          end
+          
+          if path.size > 0
+            if path[0] == ?/
+              if path[1] == ?/
+                parsed << :descendant_or_self
+                parsed << :node
+                path = path[2..-1]
+              else
+                path = path[1..-1]
+              end
+            else
+              return path
+            end
+          end
+        end
+        return path
+      end
+
+      # Returns a 1-1 map of the nodeset
+      # The contents of the resulting array are either:
+      #   true/false, if a positive match
+      #   String, if a name match
+      #NodeTest
+      #  | ('*' | NCNAME ':' '*' | QNAME)                NameTest
+      #  | NODE_TYPE '(' ')'                              NodeType
+      #  | PI '(' LITERAL ')'                            PI
+      #    | '[' expr ']'                                Predicate
+      NCNAMETEST= /^(#{NCNAME_STR}):\*/u
+      QNAME     = Namespace::NAMESPLIT
+      NODE_TYPE  = /^(comment|text|node)\(\s*\)/m
+      PI        = /^processing-instruction\(/
+      def NodeTest path, parsed
+        #puts "NodeTest with #{path}"
+        res = nil
+        case path
+        when /^\*/
+          path = $'
+          parsed << :any
+        when NODE_TYPE
+          type = $1
+          path = $'
+          parsed << type.tr('-', '_').intern
+        when PI
+          path = $'
+          literal = nil
+          if path !~ /^\s*\)/
+            path =~ LITERAL
+            literal = $1
+            path = $'
+            raise ParseException.new("Missing ')' after processing instruction") if path[0] != ?)
+            path = path[1..-1]
+          end
+          parsed << :processing_instruction
+          parsed << (literal || '')
+        when NCNAMETEST
+          #puts "NCNAMETEST"
+          prefix = $1
+          path = $'
+          parsed << :namespace
+          parsed << prefix
+        when QNAME
+          #puts "QNAME"
+          prefix = $1
+          name = $2
+          path = $'
+          prefix = "" unless prefix
+          parsed << :qname
+          parsed << prefix
+          parsed << name
+        end
+        return path
+      end
+
+      # Filters the supplied nodeset on the predicate(s)
+      def Predicate path, parsed
+        #puts "PREDICATE with #{path}"
+        return nil unless path[0] == ?[
+        predicates = []
+        while path[0] == ?[
+          path, expr = get_group(path)
+          predicates << expr[1..-2] if expr
+        end
+        #puts "PREDICATES = #{predicates.inspect}"
+        predicates.each{ |expr| 
+          #puts "ORING #{expr}"
+          preds = []
+          parsed << :predicate
+          parsed << preds
+          OrExpr(expr, preds) 
+        }
+        #puts "PREDICATES = #{predicates.inspect}"
+        path
+      end
+
+      # The following return arrays of true/false, a 1-1 mapping of the
+      # supplied nodeset, except for axe(), which returns a filtered
+      # nodeset
+
+      #| OrExpr S 'or' S AndExpr
+      #| AndExpr
+      def OrExpr path, parsed
+        #puts "OR >>> #{path}"
+        n = []
+        rest = AndExpr( path, n )
+        #puts "OR <<< #{rest}"
+        if rest != path
+          while rest =~ /^\s*( or )/
+            n = [ :or, n, [] ]
+            rest = AndExpr( $', n[-1] )
+          end
+        end
+        if parsed.size == 0 and n.size != 0
+          parsed.replace(n)
+        elsif n.size > 0
+          parsed << n
+        end
+        rest
+      end
+
+      #| AndExpr S 'and' S EqualityExpr
+      #| EqualityExpr
+      def AndExpr path, parsed
+        #puts "AND >>> #{path}"
+        n = []
+        rest = EqualityExpr( path, n )
+        #puts "AND <<< #{rest}"
+        if rest != path
+          while rest =~ /^\s*( and )/
+            n = [ :and, n, [] ]
+            #puts "AND >>> #{rest}"
+            rest = EqualityExpr( $', n[-1] )
+            #puts "AND <<< #{rest}"
+          end
+        end
+        if parsed.size == 0 and n.size != 0
+          parsed.replace(n)
+        elsif n.size > 0
+          parsed << n
+        end
+        rest
+      end
+
+      #| EqualityExpr ('=' | '!=')  RelationalExpr
+      #| RelationalExpr
+      def EqualityExpr path, parsed
+        #puts "EQUALITY >>> #{path}"
+        n = []
+        rest = RelationalExpr( path, n )
+        #puts "EQUALITY <<< #{rest}"
+        if rest != path
+          while rest =~ /^\s*(!?=)\s*/
+            if $1[0] == ?!
+              n = [ :neq, n, [] ]
+            else
+              n = [ :eq, n, [] ]
+            end
+            rest = RelationalExpr( $', n[-1] )
+          end
+        end
+        if parsed.size == 0 and n.size != 0
+          parsed.replace(n)
+        elsif n.size > 0
+          parsed << n
+        end
+        rest
+      end
+
+      #| RelationalExpr ('<' | '>' | '<=' | '>=') AdditiveExpr
+      #| AdditiveExpr
+      def RelationalExpr path, parsed
+        #puts "RELATION >>> #{path}"
+        n = []
+        rest = AdditiveExpr( path, n )
+        #puts "RELATION <<< #{rest}"
+        if rest != path
+          while rest =~ /^\s*([<>]=?)\s*/
+            if $1[0] == ?<
+              sym = "lt"
+            else
+              sym = "gt"
+            end
+            sym << "eq" if $1[-1] == ?=
+            n = [ sym.intern, n, [] ]
+            rest = AdditiveExpr( $', n[-1] )
+          end
+        end
+        if parsed.size == 0 and n.size != 0
+          parsed.replace(n)
+        elsif n.size > 0
+          parsed << n
+        end
+        rest
+      end
+
+      #| AdditiveExpr ('+' | S '-') MultiplicativeExpr
+      #| MultiplicativeExpr
+      def AdditiveExpr path, parsed
+        #puts "ADDITIVE >>> #{path}"
+        n = []
+        rest = MultiplicativeExpr( path, n )
+        #puts "ADDITIVE <<< #{rest}"
+        if rest != path
+          while rest =~ /^\s*(\+| -)\s*/
+            if $1[0] == ?+
+              n = [ :plus, n, [] ]
+            else
+              n = [ :minus, n, [] ]
+            end
+            rest = MultiplicativeExpr( $', n[-1] )
+          end
+        end
+        if parsed.size == 0 and n.size != 0
+          parsed.replace(n)
+        elsif n.size > 0
+          parsed << n
+        end
+        rest
+      end
+
+      #| MultiplicativeExpr ('*' | S ('div' | 'mod') S) UnaryExpr
+      #| UnaryExpr
+      def MultiplicativeExpr path, parsed
+        #puts "MULT >>> #{path}"
+        n = []
+        rest = UnaryExpr( path, n )
+        #puts "MULT <<< #{rest}"
+        if rest != path
+          while rest =~ /^\s*(\*| div | mod )\s*/
+            if $1[0] == ?*
+              n = [ :mult, n, [] ]
+            elsif $1.include?( "div" )
+              n = [ :div, n, [] ]
+            else
+              n = [ :mod, n, [] ]
+            end
+            rest = UnaryExpr( $', n[-1] )
+          end
+        end
+        if parsed.size == 0 and n.size != 0
+          parsed.replace(n)
+        elsif n.size > 0
+          parsed << n
+        end
+        rest
+      end
+
+      #| '-' UnaryExpr
+      #| UnionExpr
+      def UnaryExpr path, parsed
+        path =~ /^(\-*)/
+        path = $'
+        if $1 and (($1.size % 2) != 0)
+          mult = -1
+        else
+          mult = 1
+        end
+        parsed << :neg if mult < 0
+
+        #puts "UNARY >>> #{path}"
+        n = []
+        path = UnionExpr( path, n )
+        #puts "UNARY <<< #{path}"
+        parsed.concat( n )
+        path
+      end
+
+      #| UnionExpr '|' PathExpr
+      #| PathExpr
+      def UnionExpr path, parsed
+        #puts "UNION >>> #{path}"
+        n = []
+        rest = PathExpr( path, n )
+        #puts "UNION <<< #{rest}"
+        if rest != path
+          while rest =~ /^\s*(\|)\s*/
+            n = [ :union, n, [] ]
+            rest = PathExpr( $', n[-1] )
+          end
+        end
+        if parsed.size == 0 and n.size != 0
+          parsed.replace( n )
+        elsif n.size > 0
+          parsed << n
+        end
+        rest
+      end
+
+      #| LocationPath
+      #| FilterExpr ('/' | '//') RelativeLocationPath
+      def PathExpr path, parsed
+        path =~ /^\s*/
+        path = $'
+        #puts "PATH >>> #{path}"
+        n = []
+        rest = FilterExpr( path, n )
+        #puts "PATH <<< '#{rest}'"
+        if rest != path
+          if rest and rest[0] == ?/
+            return RelativeLocationPath(rest, n)
+          end
+        end
+        #puts "BEFORE WITH '#{rest}'"
+        rest = LocationPath(rest, n) if rest =~ /^[\/\.\@\[\w_*]/
+        parsed.concat(n)
+        return rest
+      end
+
+      #| FilterExpr Predicate
+      #| PrimaryExpr
+      def FilterExpr path, parsed
+        #puts "FILTER >>> #{path}"
+        n = []
+        path = PrimaryExpr( path, n )
+        #puts "FILTER <<< #{path}"
+        path = Predicate(path, n) if path and path[0] == ?[
+        #puts "FILTER <<< #{path}"
+        parsed.concat(n)
+        path
+      end
+
+      #| VARIABLE_REFERENCE
+      #| '(' expr ')'
+      #| LITERAL
+      #| NUMBER
+      #| FunctionCall
+      VARIABLE_REFERENCE  = /^\$(#{NAME_STR})/u
+      NUMBER              = /^(\d*\.?\d+)/
+      NT        = /^comment|text|processing-instruction|node$/
+      def PrimaryExpr path, parsed
+        arry = []
+        case path
+        when VARIABLE_REFERENCE
+          varname = $1
+          path = $'
+          parsed << :variable
+          parsed << varname
+          #arry << @variables[ varname ]
+        when /^(\w[-\w]*)(?:\()/
+          #puts "PrimaryExpr :: Function >>> #$1 -- '#$''"
+          fname = $1
+          tmp = $'
+          #puts "#{fname} =~ #{NT.inspect}"
+          return path if fname =~ NT
+          path = tmp
+          parsed << :function
+          parsed << fname
+          path = FunctionCall(path, parsed)
+        when NUMBER
+          #puts "LITERAL or NUMBER: #$1"
+          varname = $1.nil? ? $2 : $1
+          path = $'
+          parsed << :literal 
+          parsed << (varname.include?('.') ? varname.to_f : varname.to_i)
+        when LITERAL
+          #puts "LITERAL or NUMBER: #$1"
+          varname = $1.nil? ? $2 : $1
+          path = $'
+          parsed << :literal 
+          parsed << varname
+        when /^\(/                                               #/
+          path, contents = get_group(path)
+          contents = contents[1..-2]
+          n = []
+          OrExpr( contents, n )
+          parsed.concat(n)
+        end
+        path
+      end
+
+      #| FUNCTION_NAME '(' ( expr ( ',' expr )* )? ')'
+      def FunctionCall rest, parsed
+        path, arguments = parse_args(rest)
+        argset = []
+        for argument in arguments
+          args = []
+          OrExpr( argument, args )
+          argset << args
+        end
+        parsed << argset
+        path
+      end
+
+      # get_group( '[foo]bar' ) -> ['bar', '[foo]']
+      def get_group string
+        ind = 0
+        depth = 0
+        st = string[0,1]
+        en = (st == "(" ? ")" : "]")
+        begin
+          case string[ind,1]
+          when st
+            depth += 1
+          when en
+            depth -= 1
+          end
+          ind += 1
+        end while depth > 0 and ind < string.length
+        return nil unless depth==0
+        [string[ind..-1], string[0..ind-1]]
+      end
+      
+      def parse_args( string )
+        arguments = []
+        ind = 0
+				inquot = false
+				inapos = false
+        depth = 1
+        begin
+          case string[ind]
+          when ?"
+          	inquot = !inquot unless inapos
+          when ?'
+          	inapos = !inapos unless inquot
+          else
+          	unless inquot or inapos
+          		case string[ind]
+							when ?(
+								depth += 1
+                if depth == 1
+                	string = string[1..-1]
+                	ind -= 1
+                end
+							when ?)
+								depth -= 1
+								if depth == 0
+									s = string[0,ind].strip
+									arguments << s unless s == ""
+									string = string[ind+1..-1]
+								end
+							when ?,
+								if depth == 1
+									s = string[0,ind].strip
+									arguments << s unless s == ""
+									string = string[ind+1..-1]
+									ind = -1 
+								end
+							end
+            end
+          end
+          ind += 1
+        end while depth > 0 and ind < string.length
+        return nil unless depth==0
+        [string,arguments]
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/quickpath.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/quickpath.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/quickpath.rb	(revision 18425)
@@ -0,0 +1,266 @@
+require 'rexml/functions'
+require 'rexml/xmltokens'
+
+module REXML
+	class QuickPath
+		include Functions
+		include XMLTokens
+
+		EMPTY_HASH = {}
+
+		def QuickPath::first element, path, namespaces=EMPTY_HASH
+			match(element, path, namespaces)[0]
+		end
+
+		def QuickPath::each element, path, namespaces=EMPTY_HASH, &block
+			path = "*" unless path
+			match(element, path, namespaces).each( &block )
+		end
+
+		def QuickPath::match element, path, namespaces=EMPTY_HASH
+			raise "nil is not a valid xpath" unless path
+			results = nil
+			Functions::namespace_context = namespaces
+			case path
+			when /^\/([^\/]|$)/u
+				# match on root
+				path = path[1..-1]
+				return [element.root.parent] if path == ''
+				results = filter([element.root], path)
+			when /^[-\w]*::/u
+				results = filter([element], path)
+			when /^\*/u
+				results = filter(element.to_a, path)
+			when /^[\[!\w:]/u
+				# match on child
+				matches = []
+				children = element.to_a
+				results = filter(children, path)
+			else
+				results = filter([element], path)
+			end
+			return results
+		end
+
+		# Given an array of nodes it filters the array based on the path. The
+		# result is that when this method returns, the array will contain elements
+		# which match the path
+		def QuickPath::filter elements, path
+			return elements if path.nil? or path == '' or elements.size == 0
+			case path
+			when /^\/\//u											# Descendant
+				return axe( elements, "descendant-or-self", $' )
+			when /^\/?\b(\w[-\w]*)\b::/u							# Axe
+				axe_name = $1
+				rest = $'
+				return axe( elements, $1, $' )
+			when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u	# Child
+				rest = $'
+				results = []
+				elements.each do |element|
+					results |= filter( element.to_a, rest )
+				end
+				return results
+			when /^\/?(\w[-\w]*)\(/u							# / Function
+				return function( elements, $1, $' )
+			when Namespace::NAMESPLIT		# Element name
+				name = $2
+				ns = $1
+				rest = $'
+				elements.delete_if do |element|
+					!(element.kind_of? Element and 
+						(element.expanded_name == name or
+						 (element.name == name and
+						  element.namespace == Functions.namespace_context[ns])))
+				end
+				return filter( elements, rest )
+			when /^\/\[/u
+				matches = []
+				elements.each do |element|
+					matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element
+				end
+				return matches
+			when /^\[/u												# Predicate
+				return predicate( elements, path )
+			when /^\/?\.\.\./u										# Ancestor
+				return axe( elements, "ancestor", $' )
+			when /^\/?\.\./u											# Parent
+				return filter( elements.collect{|e|e.parent}, $' )
+			when /^\/?\./u												# Self
+				return filter( elements, $' )
+			when /^\*/u													# Any
+				results = []
+				elements.each do |element|
+					results |= filter( [element], $' ) if element.kind_of? Element
+					#if element.kind_of? Element
+					#	children = element.to_a
+					#	children.delete_if { |child| !child.kind_of?(Element) }
+					#	results |= filter( children, $' )
+					#end
+				end
+				return results
+			end
+			return []
+		end
+
+		def QuickPath::axe( elements, axe_name, rest )
+			matches = []
+			matches = filter( elements.dup, rest ) if axe_name =~ /-or-self$/u
+			case axe_name
+			when /^descendant/u
+				elements.each do |element|
+					matches |= filter( element.to_a, "descendant-or-self::#{rest}" ) if element.kind_of? Element
+				end
+			when /^ancestor/u
+				elements.each do |element|
+					while element.parent
+						matches << element.parent
+						element = element.parent
+					end
+				end
+				matches = filter( matches, rest )
+			when "self"
+				matches = filter( elements, rest )
+			when "child"
+				elements.each do |element|
+					matches |= filter( element.to_a, rest ) if element.kind_of? Element
+				end
+			when "attribute"
+				elements.each do |element|
+					matches << element.attributes[ rest ] if element.kind_of? Element
+				end
+			when "parent"
+				matches = filter(elements.collect{|element| element.parent}.uniq, rest)
+			when "following-sibling"
+				matches = filter(elements.collect{|element| element.next_sibling}.uniq,
+					rest)
+			when "previous-sibling"
+				matches = filter(elements.collect{|element| 
+					element.previous_sibling}.uniq, rest )
+			end
+			return matches.uniq
+		end
+
+		# A predicate filters a node-set with respect to an axis to produce a
+		# new node-set. For each node in the node-set to be filtered, the 
+		# PredicateExpr is evaluated with that node as the context node, with 
+		# the number of nodes in the node-set as the context size, and with the 
+		# proximity position of the node in the node-set with respect to the
+		# axis as the context position; if PredicateExpr evaluates to true for
+		# that node, the node is included in the new node-set; otherwise, it is
+		# not included.
+		#
+		# A PredicateExpr is evaluated by evaluating the Expr and converting
+		# the result to a boolean. If the result is a number, the result will
+		# be converted to true if the number is equal to the context position
+		# and will be converted to false otherwise; if the result is not a
+		# number, then the result will be converted as if by a call to the
+		# boolean function. Thus a location path para[3] is equivalent to
+		# para[position()=3].
+		def QuickPath::predicate( elements, path ) 
+			ind = 1
+			bcount = 1
+			while bcount > 0
+				bcount += 1 if path[ind] == ?[
+				bcount -= 1 if path[ind] == ?]
+				ind += 1
+			end
+			ind -= 1
+			predicate = path[1..ind-1]
+			rest = path[ind+1..-1]
+
+			# have to change 'a [=<>] b [=<>] c' into 'a [=<>] b and b [=<>] c'
+			predicate.gsub!( /([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)/u ) { 
+				"#$1 #$2 #$3 and #$3 #$4 #$5"
+			}
+			# Let's do some Ruby trickery to avoid some work:
+			predicate.gsub!( /&/u, "&&" )
+			predicate.gsub!( /=/u, "==" )
+			predicate.gsub!( /@(\w[-\w.]*)/u ) {
+				"attribute(\"#$1\")" 
+			}
+			predicate.gsub!( /\bmod\b/u, "%" )
+			predicate.gsub!( /\b(\w[-\w.]*\()/u ) {
+				fname = $1
+				fname.gsub( /-/u, "_" )
+			}
+			
+			Functions.pair = [ 0, elements.size ]
+			results = []
+			elements.each do |element|
+				Functions.pair[0] += 1
+				Functions.node = element
+				res = eval( predicate )
+				case res
+				when true
+					results << element
+				when Fixnum
+					results << element if Functions.pair[0] == res
+				when String
+					results << element
+				end
+			end
+			return filter( results, rest )
+		end
+
+		def QuickPath::attribute( name )
+			return Functions.node.attributes[name] if Functions.node.kind_of? Element
+		end
+
+		def QuickPath::name()
+			return Functions.node.name if Functions.node.kind_of? Element
+		end
+
+		def QuickPath::method_missing( id, *args )
+			begin
+				Functions.send( id.id2name, *args )
+			rescue Exception
+				raise "METHOD: #{id.id2name}(#{args.join ', '})\n#{$!.message}"
+			end
+		end
+
+		def QuickPath::function( elements, fname, rest )
+			args = parse_args( elements, rest )
+			Functions.pair = [0, elements.size]
+			results = []
+			elements.each do |element|
+				Functions.pair[0] += 1
+				Functions.node = element
+				res = Functions.send( fname, *args )
+				case res
+				when true
+					results << element
+				when Fixnum
+					results << element if Functions.pair[0] == res
+				end
+			end
+			return results
+		end
+
+		def QuickPath::parse_args( element, string )
+			# /.*?(?:\)|,)/
+			arguments = []
+			buffer = ""
+			while string and string != ""
+				c = string[0]
+				string.sub!(/^./u, "")
+				case c
+				when ?,
+					# if depth = 1, then we start a new argument
+					arguments << evaluate( buffer )
+					#arguments << evaluate( string[0..count] )
+				when ?(
+					# start a new method call
+					function( element, buffer, string )
+					buffer = ""
+				when ?)
+					# close the method call and return arguments
+					return arguments
+				else
+					buffer << c
+				end
+			end
+			""
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/rexml.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/rexml.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/rexml.rb	(revision 18425)
@@ -0,0 +1,29 @@
+# REXML is an XML toolkit for Ruby[http://www.ruby-lang.org], in Ruby.
+#
+# REXML is a _pure_ Ruby, XML 1.0 conforming,
+# non-validating[http://www.w3.org/TR/2004/REC-xml-20040204/#sec-conformance]
+# toolkit with an intuitive API.  REXML passes 100% of the non-validating Oasis
+# tests[http://www.oasis-open.org/committees/xml-conformance/xml-test-suite.shtml],
+# and provides tree, stream, SAX2, pull, and lightweight APIs.  REXML also 
+# includes a full XPath[http://www.w3c.org/tr/xpath] 1.0 implementation. Since 
+# Ruby 1.8, REXML is included in the standard Ruby distribution.
+#
+# Main page:: http://www.germane-software.com/software/rexml
+# Author:: Sean Russell <serATgermaneHYPHENsoftwareDOTcom>
+# Version:: 3.1.6
+# Date:: 2006/335
+# 
+# This API documentation can be downloaded from the REXML home page, or can
+# be accessed online[http://www.germane-software.com/software/rexml_doc]
+#
+# A tutorial is available in the REXML distribution in docs/tutorial.html,
+# or can be accessed 
+# online[http://www.germane-software.com/software/rexml/docs/tutorial.html]
+module REXML
+	COPYRIGHT = "Copyright Â© 2001-2006 Sean Russell <ser@germane-software.com>"
+  DATE = "2006/335"
+  VERSION = "3.1.6"
+
+  Copyright = COPYRIGHT
+  Version = VERSION
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/sax2listener.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/sax2listener.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/sax2listener.rb	(revision 18425)
@@ -0,0 +1,97 @@
+module REXML
+	# A template for stream parser listeners.
+	# Note that the declarations (attlistdecl, elementdecl, etc) are trivially
+	# processed; REXML doesn't yet handle doctype entity declarations, so you 
+	# have to parse them out yourself.
+	# === Missing methods from SAX2
+	#  ignorable_whitespace
+	# === Methods extending SAX2 
+	# +WARNING+
+	# These methods are certainly going to change, until DTDs are fully
+	# supported.  Be aware of this.
+	#  start_document
+	#  end_document
+	#  doctype
+	#  elementdecl
+	#  attlistdecl
+	#  entitydecl
+	#  notationdecl
+	#  cdata
+	#  xmldecl
+	#  comment
+	module SAX2Listener
+		def start_document
+		end
+		def end_document
+		end
+		def start_prefix_mapping prefix, uri
+		end
+		def end_prefix_mapping prefix
+		end
+		def start_element uri, localname, qname, attributes
+		end
+		def end_element uri, localname, qname
+		end
+		def characters text
+		end
+		def processing_instruction target, data
+		end
+		# Handles a doctype declaration. Any attributes of the doctype which are
+		# not supplied will be nil.  # EG, <!DOCTYPE me PUBLIC "foo" "bar">
+		# @p name the name of the doctype; EG, "me"
+		# @p pub_sys "PUBLIC", "SYSTEM", or nil.  EG, "PUBLIC"
+		# @p long_name the supplied long name, or nil.  EG, "foo"
+		# @p uri the uri of the doctype, or nil.  EG, "bar"
+		def doctype name, pub_sys, long_name, uri
+		end
+		# If a doctype includes an ATTLIST declaration, it will cause this
+		# method to be called.  The content is the declaration itself, unparsed.
+		# EG, <!ATTLIST el attr CDATA #REQUIRED> will come to this method as "el
+		# attr CDATA #REQUIRED".  This is the same for all of the .*decl
+		# methods.
+		def attlistdecl(element, pairs, contents)
+		end
+		# <!ELEMENT ...>
+		def elementdecl content
+		end
+		# <!ENTITY ...>
+		# The argument passed to this method is an array of the entity
+		# declaration.  It can be in a number of formats, but in general it
+		# returns (example, result):
+		#  <!ENTITY % YN '"Yes"'>  
+		#  ["%", "YN", "'\"Yes\"'", "\""]
+		#  <!ENTITY % YN 'Yes'>
+		#  ["%", "YN", "'Yes'", "s"]
+		#  <!ENTITY WhatHeSaid "He said %YN;">
+		#  ["WhatHeSaid", "\"He said %YN;\"", "YN"]
+		#  <!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
+		#  ["open-hatch", "SYSTEM", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
+		#  <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml">
+		#  ["open-hatch", "PUBLIC", "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\"", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
+		#  <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>
+		#  ["hatch-pic", "SYSTEM", "\"../grafix/OpenHatch.gif\"", "\n\t\t\t\t\t\t\tNDATA gif", "gif"]
+		def entitydecl name, decl
+		end
+		# <!NOTATION ...>
+		def notationdecl content
+		end
+		# Called when <![CDATA[ ... ]]> is encountered in a document.
+		# @p content "..."
+		def cdata content
+		end
+		# Called when an XML PI is encountered in the document.
+		# EG: <?xml version="1.0" encoding="utf"?>
+		# @p version the version attribute value.  EG, "1.0"
+		# @p encoding the encoding attribute value, or nil.  EG, "utf"
+		# @p standalone the standalone attribute value, or nil.  EG, nil
+    # @p spaced the declaration is followed by a line break
+		def xmldecl version, encoding, standalone
+		end
+		# Called when a comment is encountered.
+		# @p comment The content of the comment
+		def comment comment
+		end
+    def progress position
+    end
+	end	
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/source.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/source.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/source.rb	(revision 18425)
@@ -0,0 +1,244 @@
+require 'rexml/encoding'
+
+module REXML
+	# Generates Source-s.  USE THIS CLASS.
+	class SourceFactory
+		# Generates a Source object
+		# @param arg Either a String, or an IO
+		# @return a Source, or nil if a bad argument was given
+		def SourceFactory::create_from(arg)
+      if arg.kind_of? String
+			  Source.new(arg)
+      elsif arg.respond_to? :read and
+            arg.respond_to? :readline and
+            arg.respond_to? :nil? and
+            arg.respond_to? :eof?
+				IOSource.new(arg)
+      elsif arg.kind_of? Source
+        arg
+      else
+        raise "#{source.class} is not a valid input stream.  It must walk \n"+
+        "like either a String, IO, or Source."
+      end
+		end
+	end
+
+	# A Source can be searched for patterns, and wraps buffers and other
+	# objects and provides consumption of text
+	class Source
+		include Encoding
+		# The current buffer (what we're going to read next)
+		attr_reader :buffer
+		# The line number of the last consumed text
+		attr_reader :line
+		attr_reader :encoding
+
+		# Constructor
+		# @param arg must be a String, and should be a valid XML document
+    # @param encoding if non-null, sets the encoding of the source to this
+    # value, overriding all encoding detection
+		def initialize(arg, encoding=nil)
+			@orig = @buffer = arg
+      if encoding
+        self.encoding = encoding
+      else
+        self.encoding = check_encoding( @buffer )
+      end
+			@line = 0
+		end
+
+
+		# Inherited from Encoding
+		# Overridden to support optimized en/decoding
+		def encoding=(enc)
+			return unless super
+			@line_break = encode( '>' )
+			if enc != UTF_8
+				@buffer = decode(@buffer)
+				@to_utf = true
+			else
+				@to_utf = false
+			end
+		end
+
+		# Scans the source for a given pattern.  Note, that this is not your
+		# usual scan() method.  For one thing, the pattern argument has some
+		# requirements; for another, the source can be consumed.  You can easily
+		# confuse this method.  Originally, the patterns were easier
+		# to construct and this method more robust, because this method 
+		# generated search regexes on the fly; however, this was 
+		# computationally expensive and slowed down the entire REXML package 
+		# considerably, since this is by far the most commonly called method.
+		# @param pattern must be a Regexp, and must be in the form of
+		# /^\s*(#{your pattern, with no groups})(.*)/.  The first group
+		# will be returned; the second group is used if the consume flag is
+		# set.
+		# @param consume if true, the pattern returned will be consumed, leaving
+		# everything after it in the Source.
+		# @return the pattern, if found, or nil if the Source is empty or the
+		# pattern is not found.
+		def scan(pattern, cons=false)
+			return nil if @buffer.nil?
+			rv = @buffer.scan(pattern)
+			@buffer = $' if cons and rv.size>0
+			rv
+		end
+
+		def read
+		end
+
+		def consume( pattern )
+			@buffer = $' if pattern.match( @buffer )
+		end
+
+		def match_to( char, pattern )
+			return pattern.match(@buffer)
+		end
+
+		def match_to_consume( char, pattern )
+			md = pattern.match(@buffer)
+			@buffer = $'
+			return md
+		end
+
+		def match(pattern, cons=false)
+			md = pattern.match(@buffer)
+			@buffer = $' if cons and md
+			return md
+		end
+
+		# @return true if the Source is exhausted
+		def empty?
+			@buffer == ""
+		end
+
+    def position
+      @orig.index( @buffer )
+    end
+
+		# @return the current line in the source
+		def current_line
+			lines = @orig.split
+			res = lines.grep @buffer[0..30]
+			res = res[-1] if res.kind_of? Array
+			lines.index( res ) if res
+		end
+	end
+
+	# A Source that wraps an IO.  See the Source class for method
+	# documentation
+	class IOSource < Source
+		#attr_reader :block_size
+
+    # block_size has been deprecated
+		def initialize(arg, block_size=500, encoding=nil)
+			@er_source = @source = arg
+			@to_utf = false
+      # Determining the encoding is a deceptively difficult issue to resolve.
+      # First, we check the first two bytes for UTF-16.  Then we
+      # assume that the encoding is at least ASCII enough for the '>', and
+      # we read until we get one of those.  This gives us the XML declaration,
+      # if there is one.  If there isn't one, the file MUST be UTF-8, as per
+      # the XML spec.  If there is one, we can determine the encoding from
+      # it.
+      @buffer = ""
+      str = @source.read( 2 )
+      if encoding
+        self.encoding = encoding
+      elsif /\A(?:\xfe\xff|\xff\xfe)/n =~ str
+        self.encoding = check_encoding( str )
+      else
+        @line_break = '>'
+      end
+      super str+@source.readline( @line_break )
+    end
+
+		def scan(pattern, cons=false)
+			rv = super
+			# You'll notice that this next section is very similar to the same
+			# section in match(), but just a liiittle different.  This is
+			# because it is a touch faster to do it this way with scan()
+			# than the way match() does it; enough faster to warrent duplicating
+			# some code
+			if rv.size == 0
+				until @buffer =~ pattern or @source.nil?
+					begin
+						# READLINE OPT
+						#str = @source.read(@block_size)
+						str = @source.readline(@line_break)
+						str = decode(str) if @to_utf and str
+						@buffer << str
+          rescue Iconv::IllegalSequence
+            raise
+					rescue
+						@source = nil
+					end
+				end
+				rv = super
+			end
+			rv.taint
+			rv
+		end
+
+		def read
+			begin
+        str = @source.readline(@line_break)
+				str = decode(str) if @to_utf and str 
+				@buffer << str
+			rescue Exception, NameError
+				@source = nil
+			end
+		end
+
+		def consume( pattern )
+			match( pattern, true )
+		end
+
+		def match( pattern, cons=false )
+			rv = pattern.match(@buffer)
+			@buffer = $' if cons and rv
+			while !rv and @source
+				begin
+          str = @source.readline(@line_break)
+					str = decode(str) if @to_utf and str
+					@buffer << str
+					rv = pattern.match(@buffer)
+					@buffer = $' if cons and rv
+				rescue
+					@source = nil
+				end
+			end
+			rv.taint
+			rv
+		end
+		
+		def empty?
+			super and ( @source.nil? || @source.eof? )
+		end
+
+    def position
+      @er_source.stat.pipe? ? 0 : @er_source.pos
+    end
+
+		# @return the current line in the source
+		def current_line
+      begin
+        pos = @er_source.pos				# The byte position in the source
+        lineno = @er_source.lineno	# The XML < position in the source
+        @er_source.rewind
+        line = 0										# The \r\n position in the source
+        begin
+          while @er_source.pos < pos
+            @er_source.readline
+            line += 1
+          end
+        rescue
+        end
+      rescue IOError
+        pos = -1
+        line = -1
+      end
+			[pos, lineno, line]
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/streamlistener.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/streamlistener.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/streamlistener.rb	(revision 18425)
@@ -0,0 +1,92 @@
+module REXML
+	# A template for stream parser listeners.
+	# Note that the declarations (attlistdecl, elementdecl, etc) are trivially
+	# processed; REXML doesn't yet handle doctype entity declarations, so you 
+	# have to parse them out yourself.
+	module StreamListener
+		# Called when a tag is encountered.
+		# @p name the tag name
+		# @p attrs an array of arrays of attribute/value pairs, suitable for
+		# use with assoc or rassoc.  IE, <tag attr1="value1" attr2="value2">
+		# will result in 
+		# tag_start( "tag", # [["attr1","value1"],["attr2","value2"]])
+		def tag_start name, attrs
+		end
+		# Called when the end tag is reached.  In the case of <tag/>, tag_end
+		# will be called immidiately after tag_start
+		# @p the name of the tag
+		def tag_end name
+		end
+		# Called when text is encountered in the document
+		# @p text the text content.
+		def text text
+		end
+		# Called when an instruction is encountered.  EG: <?xsl sheet='foo'?>
+		# @p name the instruction name; in the example, "xsl"
+		# @p instruction the rest of the instruction.  In the example,
+		# "sheet='foo'"
+		def instruction name, instruction
+		end
+		# Called when a comment is encountered.
+		# @p comment The content of the comment
+		def comment comment
+		end
+		# Handles a doctype declaration. Any attributes of the doctype which are
+		# not supplied will be nil.  # EG, <!DOCTYPE me PUBLIC "foo" "bar">
+		# @p name the name of the doctype; EG, "me"
+		# @p pub_sys "PUBLIC", "SYSTEM", or nil.  EG, "PUBLIC"
+		# @p long_name the supplied long name, or nil.  EG, "foo"
+		# @p uri the uri of the doctype, or nil.  EG, "bar"
+		def doctype name, pub_sys, long_name, uri
+		end
+		# Called when the doctype is done
+		def doctype_end
+		end
+		# If a doctype includes an ATTLIST declaration, it will cause this
+		# method to be called.  The content is the declaration itself, unparsed.
+		# EG, <!ATTLIST el attr CDATA #REQUIRED> will come to this method as "el
+		# attr CDATA #REQUIRED".  This is the same for all of the .*decl
+		# methods.
+		def attlistdecl element_name, attributes, raw_content
+		end
+		# <!ELEMENT ...>
+		def elementdecl content
+		end
+		# <!ENTITY ...>
+		# The argument passed to this method is an array of the entity
+		# declaration.  It can be in a number of formats, but in general it
+		# returns (example, result):
+		#  <!ENTITY % YN '"Yes"'>  
+		#  ["%", "YN", "'\"Yes\"'", "\""]
+		#  <!ENTITY % YN 'Yes'>
+		#  ["%", "YN", "'Yes'", "s"]
+		#  <!ENTITY WhatHeSaid "He said %YN;">
+		#  ["WhatHeSaid", "\"He said %YN;\"", "YN"]
+		#  <!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
+		#  ["open-hatch", "SYSTEM", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
+		#  <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml">
+		#  ["open-hatch", "PUBLIC", "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\"", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
+		#  <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>
+		#  ["hatch-pic", "SYSTEM", "\"../grafix/OpenHatch.gif\"", "\n\t\t\t\t\t\t\tNDATA gif", "gif"]
+		def entitydecl content
+		end
+		# <!NOTATION ...>
+		def notationdecl content
+		end
+		# Called when %foo; is encountered in a doctype declaration.
+		# @p content "foo"
+		def entity content
+		end
+		# Called when <![CDATA[ ... ]]> is encountered in a document.
+		# @p content "..."
+		def cdata content
+		end
+		# Called when an XML PI is encountered in the document.
+		# EG: <?xml version="1.0" encoding="utf"?>
+		# @p version the version attribute value.  EG, "1.0"
+		# @p encoding the encoding attribute value, or nil.  EG, "utf"
+		# @p standalone the standalone attribute value, or nil.  EG, nil
+		def xmldecl version, encoding, standalone
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/syncenumerator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/syncenumerator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/syncenumerator.rb	(revision 18425)
@@ -0,0 +1,33 @@
+module REXML
+  class SyncEnumerator
+    include Enumerable
+
+    # Creates a new SyncEnumerator which enumerates rows of given
+    # Enumerable objects.
+    def initialize(*enums)
+      @gens = enums
+      @biggest = @gens[0]
+      @gens.each {|x| @biggest = x if x.size > @biggest.size }
+    end
+
+    # Returns the number of enumerated Enumerable objects, i.e. the size
+    # of each row.
+    def size
+      @gens.size
+    end
+
+    # Returns the number of enumerated Enumerable objects, i.e. the size
+    # of each row.
+    def length
+      @gens.length
+    end
+
+    # Enumerates rows of the Enumerable objects.
+    def each
+      @biggest.zip( *@gens ) {|a|
+        yield(*a[1..-1])
+      }
+      self
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/text.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/text.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/text.rb	(revision 18425)
@@ -0,0 +1,343 @@
+require 'rexml/entity'
+require 'rexml/doctype'
+require 'rexml/child'
+require 'rexml/doctype'
+require 'rexml/parseexception'
+
+module REXML
+  # Represents text nodes in an XML document
+  class Text < Child
+    include Comparable
+    # The order in which the substitutions occur
+    SPECIALS = [ /&(?!#?[\w-]+;)/u, /</u, />/u, /"/u, /'/u, /\r/u ]
+    SUBSTITUTES = ['&amp;', '&lt;', '&gt;', '&quot;', '&apos;', '&#13;']
+    # Characters which are substituted in written strings
+    SLAICEPS = [ '<', '>', '"', "'", '&' ]
+    SETUTITSBUS = [ /&lt;/u, /&gt;/u, /&quot;/u, /&apos;/u, /&amp;/u ]
+
+    # If +raw+ is true, then REXML leaves the value alone
+    attr_accessor :raw
+
+    ILLEGAL = /(<|&(?!(#{Entity::NAME})|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));))/um
+    NUMERICENTITY = /&#0*((?:\d+)|(?:x[a-fA-F0-9]+));/ 
+
+    # Constructor
+    # +arg+ if a String, the content is set to the String.  If a Text,
+    # the object is shallowly cloned.  
+    #
+    # +respect_whitespace+ (boolean, false) if true, whitespace is
+    # respected
+    #
+    # +parent+ (nil) if this is a Parent object, the parent
+    # will be set to this.  
+    #
+    # +raw+ (nil) This argument can be given three values.
+    # If true, then the value of used to construct this object is expected to 
+    # contain no unescaped XML markup, and REXML will not change the text. If 
+    # this value is false, the string may contain any characters, and REXML will
+    # escape any and all defined entities whose values are contained in the
+    # text.  If this value is nil (the default), then the raw value of the 
+    # parent will be used as the raw value for this node.  If there is no raw
+    # value for the parent, and no value is supplied, the default is false.
+    # Use this field if you have entities defined for some text, and you don't
+    # want REXML to escape that text in output.
+    #   Text.new( "<&", false, nil, false ) #-> "&lt;&amp;"
+    #   Text.new( "&lt;&amp;", false, nil, false ) #-> "&amp;lt;&amp;amp;"
+    #   Text.new( "<&", false, nil, true )  #-> Parse exception
+    #   Text.new( "&lt;&amp;", false, nil, true )  #-> "&lt;&amp;"
+    #   # Assume that the entity "s" is defined to be "sean"
+    #   # and that the entity    "r" is defined to be "russell"
+    #   Text.new( "sean russell" )          #-> "&s; &r;"
+    #   Text.new( "sean russell", false, nil, true ) #-> "sean russell"
+    #
+    # +entity_filter+ (nil) This can be an array of entities to match in the
+    # supplied text.  This argument is only useful if +raw+ is set to false.
+    #   Text.new( "sean russell", false, nil, false, ["s"] ) #-> "&s; russell"
+    #   Text.new( "sean russell", false, nil, true, ["s"] ) #-> "sean russell"
+    # In the last example, the +entity_filter+ argument is ignored.
+    #
+    # +pattern+ INTERNAL USE ONLY
+    def initialize(arg, respect_whitespace=false, parent=nil, raw=nil, 
+      entity_filter=nil, illegal=ILLEGAL )
+
+      @raw = false
+
+      if parent
+        super( parent )
+        @raw = parent.raw 
+      else
+        @parent = nil
+      end
+
+      @raw = raw unless raw.nil?
+      @entity_filter = entity_filter
+      @normalized = @unnormalized = nil
+
+      if arg.kind_of? String
+        @string = arg.clone
+        @string.squeeze!(" \n\t") unless respect_whitespace
+      elsif arg.kind_of? Text
+        @string = arg.to_s
+        @raw = arg.raw
+      elsif
+        raise "Illegal argument of type #{arg.type} for Text constructor (#{arg})"
+      end
+
+      @string.gsub!( /\r\n?/, "\n" )
+
+      # check for illegal characters
+      if @raw
+        if @string =~ illegal
+          raise "Illegal character '#{$1}' in raw string \"#{@string}\""
+        end
+      end
+    end
+
+    def node_type
+      :text
+    end
+
+    def empty?
+      @string.size==0
+    end
+
+
+    def clone
+      return Text.new(self)
+    end
+
+
+    # Appends text to this text node.  The text is appended in the +raw+ mode
+    # of this text node.
+    def <<( to_append )
+      @string << to_append.gsub( /\r\n?/, "\n" )
+    end
+
+
+    # +other+ a String or a Text
+    # +returns+ the result of (to_s <=> arg.to_s)
+    def <=>( other )
+      to_s() <=> other.to_s
+    end
+
+    REFERENCE = /#{Entity::REFERENCE}/
+    # Returns the string value of this text node.  This string is always
+    # escaped, meaning that it is a valid XML text node string, and all
+    # entities that can be escaped, have been inserted.  This method respects
+    # the entity filter set in the constructor.
+    #   
+    #   # Assume that the entity "s" is defined to be "sean", and that the 
+    #   # entity "r" is defined to be "russell"
+    #   t = Text.new( "< & sean russell", false, nil, false, ['s'] ) 
+    #   t.to_s   #-> "&lt; &amp; &s; russell"
+    #   t = Text.new( "< & &s; russell", false, nil, false ) 
+    #   t.to_s   #-> "&lt; &amp; &s; russell"
+    #   u = Text.new( "sean russell", false, nil, true )
+    #   u.to_s   #-> "sean russell"
+    def to_s
+      return @string if @raw
+      return @normalized if @normalized
+
+      doctype = nil
+      if @parent
+        doc = @parent.document
+        doctype = doc.doctype if doc
+      end
+
+      @normalized = Text::normalize( @string, doctype, @entity_filter )
+    end
+
+    def inspect
+      @string.inspect
+    end
+
+    # Returns the string value of this text.  This is the text without
+    # entities, as it might be used programmatically, or printed to the
+    # console.  This ignores the 'raw' attribute setting, and any
+    # entity_filter.
+    #
+    #   # Assume that the entity "s" is defined to be "sean", and that the 
+    #   # entity "r" is defined to be "russell"
+    #   t = Text.new( "< & sean russell", false, nil, false, ['s'] ) 
+    #   t.value   #-> "< & sean russell"
+    #   t = Text.new( "< & &s; russell", false, nil, false )
+    #   t.value   #-> "< & sean russell"
+    #   u = Text.new( "sean russell", false, nil, true )
+    #   u.value   #-> "sean russell"
+    def value
+      @unnormalized if @unnormalized
+      doctype = nil
+      if @parent
+        doc = @parent.document
+        doctype = doc.doctype if doc
+      end
+      @unnormalized = Text::unnormalize( @string, doctype )
+    end
+
+    # Sets the contents of this text node.  This expects the text to be 
+    # unnormalized.  It returns self.
+    #
+    #   e = Element.new( "a" )
+    #   e.add_text( "foo" )   # <a>foo</a>
+    #   e[0].value = "bar"    # <a>bar</a>
+    #   e[0].value = "<a>"    # <a>&lt;a&gt;</a>
+    def value=( val )
+      @string = val.gsub( /\r\n?/, "\n" )
+      @unnormalized = nil
+      @normalized = nil
+      @raw = false
+    end
+ 
+     def wrap(string, width, addnewline=false)
+       # Recursivly wrap string at width.
+       return string if string.length <= width
+       place = string.rindex(' ', width) # Position in string with last ' ' before cutoff
+       if addnewline then
+         return "\n" + string[0,place] + "\n" + wrap(string[place+1..-1], width)
+       else
+         return string[0,place] + "\n" + wrap(string[place+1..-1], width)
+       end
+     end
+
+    def indent_text(string, level=1, style="\t", indentfirstline=true)
+      return string if level < 0
+      new_string = ''
+      string.each { |line|
+        indent_string = style * level
+        new_line = (indent_string + line).sub(/[\s]+$/,'')
+        new_string << new_line
+      }
+      new_string.strip! unless indentfirstline
+      return new_string
+    end
+ 
+    def write( writer, indent=-1, transitive=false, ie_hack=false ) 
+      s = to_s()
+      if not (@parent and @parent.whitespace) then
+        s = wrap(s, 60, false) if @parent and @parent.context[:wordwrap] == :all
+        if @parent and not @parent.context[:indentstyle].nil? and indent > 0 and s.count("\n") > 0
+          s = indent_text(s, indent, @parent.context[:indentstyle], false)
+        end
+        s.squeeze!(" \n\t") if @parent and !@parent.whitespace
+      end
+      writer << s
+    end
+
+    # FIXME
+    # This probably won't work properly
+    def xpath
+      path = @parent.xpath
+      path += "/text()"
+      return path
+    end
+
+    # Writes out text, substituting special characters beforehand.
+    # +out+ A String, IO, or any other object supporting <<( String )
+    # +input+ the text to substitute and the write out
+    #
+    #   z=utf8.unpack("U*")
+    #   ascOut=""
+    #   z.each{|r|
+    #     if r <  0x100
+    #       ascOut.concat(r.chr)
+    #     else
+    #       ascOut.concat(sprintf("&#x%x;", r))
+    #     end
+    #   }
+    #   puts ascOut
+    def write_with_substitution out, input
+      copy = input.clone
+      # Doing it like this rather than in a loop improves the speed
+      copy.gsub!( SPECIALS[0], SUBSTITUTES[0] )
+      copy.gsub!( SPECIALS[1], SUBSTITUTES[1] )
+      copy.gsub!( SPECIALS[2], SUBSTITUTES[2] )
+      copy.gsub!( SPECIALS[3], SUBSTITUTES[3] )
+      copy.gsub!( SPECIALS[4], SUBSTITUTES[4] )
+      copy.gsub!( SPECIALS[5], SUBSTITUTES[5] )
+      out << copy
+    end
+
+    # Reads text, substituting entities
+    def Text::read_with_substitution( input, illegal=nil )
+      copy = input.clone
+
+      if copy =~ illegal
+        raise ParseException.new( "malformed text: Illegal character #$& in \"#{copy}\"" )
+      end if illegal
+      
+      copy.gsub!( /\r\n?/, "\n" )
+      if copy.include? ?&
+        copy.gsub!( SETUTITSBUS[0], SLAICEPS[0] )
+        copy.gsub!( SETUTITSBUS[1], SLAICEPS[1] )
+        copy.gsub!( SETUTITSBUS[2], SLAICEPS[2] )
+        copy.gsub!( SETUTITSBUS[3], SLAICEPS[3] )
+        copy.gsub!( SETUTITSBUS[4], SLAICEPS[4] )
+        copy.gsub!( /&#0*((?:\d+)|(?:x[a-f0-9]+));/ ) {|m|
+          m=$1
+          #m='0' if m==''
+          m = "0#{m}" if m[0] == ?x
+          [Integer(m)].pack('U*')
+        }
+      end
+      copy
+    end
+
+    EREFERENCE = /&(?!#{Entity::NAME};)/
+    # Escapes all possible entities
+    def Text::normalize( input, doctype=nil, entity_filter=nil )
+      copy = input
+      # Doing it like this rather than in a loop improves the speed
+      #copy = copy.gsub( EREFERENCE, '&amp;' )
+      copy = copy.gsub( "&", "&amp;" )
+      if doctype
+        # Replace all ampersands that aren't part of an entity
+        doctype.entities.each_value do |entity|
+          copy = copy.gsub( entity.value, 
+            "&#{entity.name};" ) if entity.value and 
+              not( entity_filter and entity_filter.include?(entity) )
+        end
+      else
+        # Replace all ampersands that aren't part of an entity
+        DocType::DEFAULT_ENTITIES.each_value do |entity|
+          copy = copy.gsub(entity.value, "&#{entity.name};" )
+        end
+      end
+      copy
+    end
+
+    # Unescapes all possible entities
+    def Text::unnormalize( string, doctype=nil, filter=nil, illegal=nil )
+      rv = string.clone
+      rv.gsub!( /\r\n?/, "\n" )
+      matches = rv.scan( REFERENCE )
+      return rv if matches.size == 0
+      rv.gsub!( NUMERICENTITY ) {|m|
+        m=$1
+        m = "0#{m}" if m[0] == ?x
+        [Integer(m)].pack('U*')
+      }
+      matches.collect!{|x|x[0]}.compact!
+      if matches.size > 0
+        if doctype
+          matches.each do |entity_reference|
+            unless filter and filter.include?(entity_reference)
+              entity_value = doctype.entity( entity_reference )
+              re = /&#{entity_reference};/
+              rv.gsub!( re, entity_value ) if entity_value
+            end
+          end
+        else
+          matches.each do |entity_reference|
+            unless filter and filter.include?(entity_reference)
+              entity_value = DocType::DEFAULT_ENTITIES[ entity_reference ]
+              re = /&#{entity_reference};/
+              rv.gsub!( re, entity_value.value ) if entity_value
+            end
+          end
+        end
+        rv.gsub!( /&amp;/, '&' )
+      end
+      rv
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/validation/relaxng.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/validation/relaxng.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/validation/relaxng.rb	(revision 18425)
@@ -0,0 +1,559 @@
+require "rexml/validation/validation"
+require "rexml/parsers/baseparser"
+
+module REXML
+  module Validation
+    # Implemented:
+    # * empty
+    # * element
+    # * attribute
+    # * text
+    # * optional
+    # * choice
+    # * oneOrMore
+    # * zeroOrMore
+    # * group
+    # * value
+    # * interleave
+    # * mixed
+    # * ref
+    # * grammar
+    # * start
+    # * define
+    #
+    # Not implemented:
+    # * data
+    # * param
+    # * include
+    # * externalRef
+    # * notAllowed
+    # * anyName
+    # * nsName
+    # * except
+    # * name
+    class RelaxNG
+      include Validator
+
+      INFINITY = 1.0 / 0.0
+      EMPTY = Event.new( nil )
+      TEXT = [:start_element, "text"]
+      attr_accessor :current
+      attr_accessor :count
+      attr_reader :references
+
+      # FIXME: Namespaces
+      def initialize source
+        parser = REXML::Parsers::BaseParser.new( source )
+
+        @count = 0
+        @references = {}
+        @root = @current = Sequence.new(self)
+        @root.previous = true
+        states = [ @current ]
+        begin
+          event = parser.pull
+          case event[0]
+          when :start_element
+            case event[1]
+            when "empty"
+            when "element", "attribute", "text", "value"
+              states[-1] << event
+            when "optional"
+              states << Optional.new( self )
+              states[-2] << states[-1]
+            when "choice"
+              states << Choice.new( self )
+              states[-2] << states[-1]
+            when "oneOrMore"
+              states << OneOrMore.new( self )
+              states[-2] << states[-1]
+            when "zeroOrMore"
+              states << ZeroOrMore.new( self )
+              states[-2] << states[-1]
+            when "group"
+              states << Sequence.new( self )
+              states[-2] << states[-1]
+            when "interleave"
+              states << Interleave.new( self )
+              states[-2] << states[-1]
+            when "mixed"
+              states << Interleave.new( self )
+              states[-2] << states[-1]
+              states[-1] << TEXT 
+            when "define"
+              states << [ event[2]["name"] ]
+            when "ref"
+              states[-1] << Ref.new( event[2]["name"] )
+            when "anyName"
+              states << AnyName.new( self )
+              states[-2] << states[-1]
+            when "nsName"
+            when "except"
+            when "name"
+            when "data"
+            when "param"
+            when "include"
+            when "grammar"
+            when "start"
+            when "externalRef"
+            when "notAllowed"
+            end
+          when :end_element
+            case event[1]
+            when "element", "attribute"
+              states[-1] << event
+            when "zeroOrMore", "oneOrMore", "choice", "optional", 
+              "interleave", "group", "mixed"
+              states.pop
+            when "define"
+              ref = states.pop
+              @references[ ref.shift ] = ref
+            #when "empty"
+            end
+          when :end_document
+            states[-1] << event
+          when :text
+            states[-1] << event
+          end
+        end while event[0] != :end_document
+      end
+
+      def receive event
+        validate( event )
+      end
+    end
+
+    class State
+      def initialize( context )
+        @previous = []
+        @events = []
+        @current = 0
+        @count = context.count += 1
+        @references = context.references
+        @value = false
+      end
+
+      def reset
+        return if @current == 0
+        @current = 0
+        @events.each {|s| s.reset if s.kind_of? State }
+      end
+
+      def previous=( previous ) 
+        @previous << previous
+      end
+
+      def next( event )
+        #print "In next with #{event.inspect}.  "
+        #puts "Next (#@current) is #{@events[@current]}"
+        #p @previous
+        return @previous.pop.next( event ) if @events[@current].nil?
+        expand_ref_in( @events, @current ) if @events[@current].class == Ref
+        if ( @events[@current].kind_of? State )
+          @current += 1
+          @events[@current-1].previous = self
+          return @events[@current-1].next( event )
+        end
+        #puts "Current isn't a state"
+        if ( @events[@current].matches?(event) )
+          @current += 1
+          if @events[@current].nil?
+            #puts "#{inspect[0,5]} 1RETURNING #{@previous.inspect[0,5]}"
+            return @previous.pop
+          elsif @events[@current].kind_of? State
+            @current += 1
+            #puts "#{inspect[0,5]} 2RETURNING (#{@current-1}) #{@events[@current-1].inspect[0,5]}; on return, next is #{@events[@current]}"
+            @events[@current-1].previous = self
+            return @events[@current-1]
+          else
+            #puts "#{inspect[0,5]} RETURNING self w/ next(#@current) = #{@events[@current]}"
+            return self
+          end
+        else
+          return nil
+        end
+      end
+
+      def to_s
+        # Abbreviated:
+        self.class.name =~ /(?:::)(\w)\w+$/
+        # Full:
+        #self.class.name =~ /(?:::)(\w+)$/
+        "#$1.#@count"
+      end
+
+      def inspect
+        "< #{to_s} #{@events.collect{|e| 
+          pre = e == @events[@current] ? '#' : ''
+          pre + e.inspect unless self == e
+        }.join(', ')} >"
+      end
+
+      def expected
+        return [@events[@current]]
+      end
+
+      def <<( event )
+        add_event_to_arry( @events, event )
+      end
+
+
+      protected
+      def expand_ref_in( arry, ind )
+        new_events = []
+        @references[ arry[ind].to_s ].each{ |evt| 
+          add_event_to_arry(new_events,evt)
+        }
+        arry[ind,1] = new_events
+      end
+
+      def add_event_to_arry( arry, evt ) 
+        evt = generate_event( evt )
+        if evt.kind_of? String 
+          arry[-1].event_arg = evt if arry[-1].kind_of? Event and @value
+          @value = false
+        else
+          arry << evt
+        end
+      end
+
+      def generate_event( event )
+        return event if event.kind_of? State or event.class == Ref
+        evt = nil
+        arg = nil
+        case event[0]
+        when :start_element
+          case event[1]
+          when "element"
+            evt = :start_element
+            arg = event[2]["name"]
+          when "attribute"
+            evt = :start_attribute
+            arg = event[2]["name"]
+          when "text"
+            evt = :text
+          when "value"
+            evt = :text
+            @value = true
+          end
+        when :text
+          return event[1]
+        when :end_document
+          return Event.new( event[0] )
+        else # then :end_element
+          case event[1]
+          when "element"
+            evt = :end_element
+          when "attribute"
+            evt = :end_attribute
+          end
+        end
+        return Event.new( evt, arg )
+      end
+    end
+
+
+    class Sequence < State
+      def matches?(event)
+        @events[@current].matches?( event )
+      end
+    end
+
+
+    class Optional < State
+      def next( event )
+        if @current == 0
+          rv = super
+          return rv if rv
+          @prior = @previous.pop
+          return @prior.next( event )
+        end
+        super
+      end
+
+      def matches?(event)
+        @events[@current].matches?(event) || 
+        (@current == 0 and @previous[-1].matches?(event))
+      end
+
+      def expected
+        return [ @prior.expected, @events[0] ].flatten if @current == 0
+        return [@events[@current]]
+      end
+    end
+
+
+    class ZeroOrMore < Optional
+      def next( event )
+        expand_ref_in( @events, @current ) if @events[@current].class == Ref
+        if ( @events[@current].matches?(event) )
+          @current += 1
+          if @events[@current].nil?
+            @current = 0
+            return self
+          elsif @events[@current].kind_of? State
+            @current += 1
+            @events[@current-1].previous = self
+            return @events[@current-1]
+          else
+            return self
+          end
+        else
+          @prior = @previous.pop
+          return @prior.next( event ) if @current == 0
+          return nil
+        end
+      end
+
+      def expected
+        return [ @prior.expected, @events[0] ].flatten if @current == 0
+        return [@events[@current]]
+      end
+    end
+
+
+    class OneOrMore < State
+      def initialize context
+        super
+        @ord = 0
+      end
+
+      def reset
+        super 
+        @ord = 0
+      end
+
+      def next( event )
+        expand_ref_in( @events, @current ) if @events[@current].class == Ref
+        if ( @events[@current].matches?(event) )
+          @current += 1
+          @ord += 1
+          if @events[@current].nil?
+            @current = 0
+            return self
+          elsif @events[@current].kind_of? State
+            @current += 1
+            @events[@current-1].previous = self
+            return @events[@current-1]
+          else
+            return self
+          end
+        else
+          return @previous.pop.next( event ) if @current == 0 and @ord > 0
+          return nil
+        end
+      end
+
+      def matches?( event )
+        @events[@current].matches?(event) || 
+        (@current == 0 and @ord > 0 and @previous[-1].matches?(event))
+      end
+
+      def expected
+        if @current == 0 and @ord > 0
+          return [@previous[-1].expected, @events[0]].flatten
+        else
+          return [@events[@current]]
+        end
+      end
+    end
+
+
+    class Choice < State
+      def initialize context
+        super
+        @choices = []
+      end
+
+      def reset
+        super
+        @events = []
+        @choices.each { |c| c.each { |s| s.reset if s.kind_of? State } }
+      end
+
+      def <<( event )
+        add_event_to_arry( @choices, event )
+      end
+
+      def next( event )
+        # Make the choice if we haven't
+        if @events.size == 0
+          c = 0 ; max = @choices.size
+          while c < max
+            if @choices[c][0].class == Ref
+              expand_ref_in( @choices[c], 0 )
+              @choices += @choices[c]
+              @choices.delete( @choices[c] )
+              max -= 1
+            else
+              c += 1
+            end
+          end
+          @events = @choices.find { |evt| evt[0].matches? event }
+          # Remove the references
+          # Find the events
+        end
+        #puts "In next with #{event.inspect}."
+        #puts "events is #{@events.inspect}"
+        unless @events
+          @events = []
+          return nil
+        end
+        #puts "current = #@current"
+        super
+      end
+
+      def matches?( event )
+        return @events[@current].matches?( event ) if @events.size > 0
+        !@choices.find{|evt| evt[0].matches?(event)}.nil?
+      end
+
+      def expected
+        #puts "IN CHOICE EXPECTED"
+        #puts "EVENTS = #{@events.inspect}"
+        return [@events[@current]] if @events.size > 0
+        return @choices.collect do |x| 
+          if x[0].kind_of? State
+            x[0].expected
+          else
+            x[0]
+          end
+        end.flatten
+      end
+
+      def inspect
+        "< #{to_s} #{@choices.collect{|e| e.collect{|f|f.to_s}.join(', ')}.join(' or ')} >"
+      end
+
+      protected
+      def add_event_to_arry( arry, evt ) 
+        if evt.kind_of? State or evt.class == Ref
+          arry << [evt]
+        elsif evt[0] == :text 
+         if arry[-1] and
+            arry[-1][-1].kind_of?( Event ) and 
+            arry[-1][-1].event_type == :text and @value
+
+            arry[-1][-1].event_arg = evt[1]
+            @value = false
+          end
+        else
+          arry << [] if evt[0] == :start_element
+          arry[-1] << generate_event( evt )
+        end
+      end
+    end
+
+
+    class Interleave < Choice
+      def initialize context
+        super
+        @choice = 0
+      end
+
+      def reset
+        @choice = 0
+      end
+
+      def next_current( event )
+        # Expand references
+        c = 0 ; max = @choices.size
+        while c < max
+          if @choices[c][0].class == Ref
+            expand_ref_in( @choices[c], 0 )
+            @choices += @choices[c]
+            @choices.delete( @choices[c] )
+            max -= 1
+          else
+            c += 1
+          end
+        end
+        @events = @choices[@choice..-1].find { |evt| evt[0].matches? event }
+        @current = 0
+        if @events
+          # reorder the choices
+          old = @choices[@choice]
+          idx = @choices.index( @events )
+          @choices[@choice] = @events
+          @choices[idx] = old
+          @choice += 1
+        end
+        
+       #puts "In next with #{event.inspect}."
+       #puts "events is #{@events.inspect}"
+        @events = [] unless @events
+      end
+
+
+      def next( event )
+        # Find the next series
+        next_current(event) unless @events[@current]
+        return nil unless @events[@current]
+
+        expand_ref_in( @events, @current ) if @events[@current].class == Ref 
+       #puts "In next with #{event.inspect}."
+       #puts "Next (#@current) is #{@events[@current]}"
+        if ( @events[@current].kind_of? State )
+          @current += 1
+          @events[@current-1].previous = self
+          return @events[@current-1].next( event )
+        end
+       #puts "Current isn't a state"
+        return @previous.pop.next( event ) if @events[@current].nil?
+        if ( @events[@current].matches?(event) )
+          @current += 1
+          if @events[@current].nil?
+           #puts "#{inspect[0,5]} 1RETURNING self" unless @choices[@choice].nil?
+            return self unless @choices[@choice].nil?
+           #puts "#{inspect[0,5]} 1RETURNING #{@previous[-1].inspect[0,5]}"
+            return @previous.pop
+          elsif @events[@current].kind_of? State
+            @current += 1
+           #puts "#{inspect[0,5]} 2RETURNING (#{@current-1}) #{@events[@current-1].inspect[0,5]}; on return, next is #{@events[@current]}"
+            @events[@current-1].previous = self
+            return @events[@current-1]
+          else
+           #puts "#{inspect[0,5]} RETURNING self w/ next(#@current) = #{@events[@current]}"
+            return self
+          end
+        else
+          return nil
+        end
+      end
+
+      def matches?( event )
+        return @events[@current].matches?( event ) if @events[@current]
+        !@choices[@choice..-1].find{|evt| evt[0].matches?(event)}.nil?
+      end
+
+      def expected
+        #puts "IN CHOICE EXPECTED"
+        #puts "EVENTS = #{@events.inspect}"
+        return [@events[@current]] if @events[@current]
+        return @choices[@choice..-1].collect do |x| 
+          if x[0].kind_of? State
+            x[0].expected
+          else
+            x[0]
+          end
+        end.flatten
+      end
+
+      def inspect
+        "< #{to_s} #{@choices.collect{|e| e.collect{|f|f.to_s}.join(', ')}.join(' and ')} >"
+      end
+    end
+
+    class Ref
+      def initialize value
+        @value = value
+      end
+      def to_s
+        @value
+      end
+      def inspect
+        "{#{to_s}}"
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/validation/validation.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/validation/validation.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/validation/validation.rb	(revision 18425)
@@ -0,0 +1,155 @@
+require 'rexml/validation/validationexception'
+
+module REXML
+  module Validation
+    module Validator
+      NILEVENT = [ nil ]
+      def reset
+        @current = @root
+        @root.reset
+        @root.previous = true
+        @attr_stack = []
+        self
+      end
+      def dump
+        puts @root.inspect
+      end
+      def validate( event ) 
+        #puts "Current: #@current"
+        #puts "Event: #{event.inspect}"
+        @attr_stack = [] unless defined? @attr_stack
+        match = @current.next(event)
+        raise ValidationException.new( "Validation error.  Expected: "+
+          @current.expected.join( " or " )+" from #{@current.inspect} "+
+          " but got #{Event.new( event[0], event[1] ).inspect}" ) unless match
+        @current = match
+
+        # Check for attributes
+        case event[0]
+        when :start_element
+          #puts "Checking attributes"
+          @attr_stack << event[2]
+          begin
+            sattr = [:start_attribute, nil]
+            eattr = [:end_attribute]
+            text = [:text, nil]
+            k,v = event[2].find { |k,v| 
+              sattr[1] = k
+              #puts "Looking for #{sattr.inspect}"
+              m = @current.next( sattr )
+              #puts "Got #{m.inspect}"
+              if m 
+                # If the state has text children...
+                #puts "Looking for #{eattr.inspect}"
+                #puts "Expect #{m.expected}"
+                if m.matches?( eattr )
+                  #puts "Got end"
+                  @current = m
+                else
+                  #puts "Didn't get end"
+                  text[1] = v
+                  #puts "Looking for #{text.inspect}"
+                  m = m.next( text )
+                  #puts "Got #{m.inspect}"
+                  text[1] = nil
+                  return false unless m
+                  @current = m if m
+                end
+                m = @current.next( eattr )
+                if m
+                  @current = m
+                  true
+                else
+                  false
+                end
+              else
+                false
+              end
+            }
+            event[2].delete(k) if k
+          end while k
+        when :end_element
+          attrs = @attr_stack.pop
+          raise ValidationException.new( "Validation error.  Illegal "+
+            " attributes: #{attrs.inspect}") if attrs.length > 0
+        end
+      end
+    end
+
+    class Event
+      def initialize(event_type, event_arg=nil )
+        @event_type = event_type
+        @event_arg = event_arg
+      end
+
+      attr_reader :event_type
+      attr_accessor :event_arg
+
+      def done?
+        @done
+      end
+
+      def single?
+        return (@event_type != :start_element and @event_type != :start_attribute)
+      end
+
+      def matches?( event )
+        #puts "#@event_type =? #{event[0]} && #@event_arg =? #{event[1]} "
+        return false unless event[0] == @event_type
+        case event[0]
+        when nil
+          return true
+        when :start_element
+          return true if event[1] == @event_arg
+        when :end_element
+          return true
+        when :start_attribute
+          return true if event[1] == @event_arg
+        when :end_attribute
+          return true
+        when :end_document
+          return true
+        when :text
+          return (@event_arg.nil? or @event_arg == event[1])
+=begin
+        when :processing_instruction
+          false
+        when :xmldecl
+          false
+        when :start_doctype
+          false
+        when :end_doctype
+          false
+        when :externalentity
+          false
+        when :elementdecl
+          false
+        when :entity
+          false
+        when :attlistdecl
+          false
+        when :notationdecl
+          false
+        when :end_doctype
+          false
+=end
+        else
+          false
+        end
+      end
+
+      def ==( other )
+        return false unless other.kind_of? Event
+        @event_type == other.event_type and @event_arg == other.event_arg
+      end
+
+      def to_s
+        inspect
+      end
+
+      def inspect
+        "#{@event_type.inspect}( #@event_arg )"
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/validation/validationexception.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/validation/validationexception.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/validation/validationexception.rb	(revision 18425)
@@ -0,0 +1,9 @@
+module REXML
+  module Validation
+    class ValidationException < RuntimeError
+      def initialize msg
+        super
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/xmldecl.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/xmldecl.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/xmldecl.rb	(revision 18425)
@@ -0,0 +1,114 @@
+require 'rexml/encoding'
+require 'rexml/source'
+
+module REXML
+	# NEEDS DOCUMENTATION
+	class XMLDecl < Child
+		include Encoding
+
+		DEFAULT_VERSION = "1.0";
+		DEFAULT_ENCODING = "UTF-8";
+		DEFAULT_STANDALONE = "no";
+		START = '<\?xml';
+		STOP = '\?>';
+
+		attr_accessor :version, :standalone
+    attr_reader :writeencoding
+
+		def initialize(version=DEFAULT_VERSION, encoding=nil, standalone=nil)
+      @writethis = true
+      @writeencoding = !encoding.nil?
+			if version.kind_of? XMLDecl
+				super()
+				@version = version.version
+				self.encoding = version.encoding
+        @writeencoding = version.writeencoding
+				@standalone = version.standalone
+			else
+				super()
+				@version = version
+				self.encoding = encoding
+				@standalone = standalone
+			end
+			@version = DEFAULT_VERSION if @version.nil?
+		end
+
+		def clone
+			XMLDecl.new(self)
+		end
+
+		def write writer, indent=-1, transitive=false, ie_hack=false
+      return nil unless @writethis or writer.kind_of? Output
+			indent( writer, indent )
+			writer << START.sub(/\\/u, '')
+      if writer.kind_of? Output
+        writer << " #{content writer.encoding}"
+      else
+        writer << " #{content encoding}"
+      end
+			writer << STOP.sub(/\\/u, '')
+		end
+
+		def ==( other )
+		  other.kind_of?(XMLDecl) and
+		  other.version == @version and
+		  other.encoding == self.encoding and
+		  other.standalone == @standalone
+		end
+
+		def xmldecl version, encoding, standalone
+			@version = version
+			self.encoding = encoding
+			@standalone = standalone
+		end
+
+		def node_type
+			:xmldecl
+		end
+
+		alias :stand_alone? :standalone
+    alias :old_enc= :encoding=
+
+    def encoding=( enc )
+      if enc.nil?
+        self.old_enc = "UTF-8"
+        @writeencoding = false
+      else
+        self.old_enc = enc
+        @writeencoding = true
+      end
+      self.dowrite
+    end
+
+    # Only use this if you do not want the XML declaration to be written;
+    # this object is ignored by the XML writer.  Otherwise, instantiate your
+    # own XMLDecl and add it to the document.
+    #
+    # Note that XML 1.1 documents *must* include an XML declaration
+    def XMLDecl.default
+      rv = XMLDecl.new( "1.0" )
+      rv.nowrite
+      rv
+    end
+
+    def nowrite
+      @writethis = false
+    end
+
+    def dowrite
+      @writethis = true
+    end
+
+    def inspect
+      START.sub(/\\/u, '') + " ... " + STOP.sub(/\\/u, '')
+    end
+
+		private
+		def content(enc)
+			rv = "version='#@version'"
+			rv << " encoding='#{enc}'" if @writeencoding || enc !~ /utf-8/i
+			rv << " standalone='#@standalone'" if @standalone
+			rv
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/xmltokens.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/xmltokens.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/xmltokens.rb	(revision 18425)
@@ -0,0 +1,18 @@
+module REXML
+	# Defines a number of tokens used for parsing XML.  Not for general
+	# consumption.
+	module XMLTokens
+		NCNAME_STR= '[\w:][\-\w\d.]*'
+		NAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
+
+		NAMECHAR = '[\-\w\d\.:]'
+		NAME = "([\\w:]#{NAMECHAR}*)"
+		NMTOKEN = "(?:#{NAMECHAR})+"
+		NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*"
+		REFERENCE = "(?:&#{NAME};|&#\\d+;|&#x[0-9a-fA-F]+;)"
+
+		#REFERENCE = "(?:#{ENTITYREF}|#{CHARREF})"
+		#ENTITYREF = "&#{NAME};"
+		#CHARREF = "&#\\d+;|&#x[0-9a-fA-F]+;"
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/xpath.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/xpath.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/xpath.rb	(revision 18425)
@@ -0,0 +1,66 @@
+require 'rexml/functions'
+require 'rexml/xpath_parser'
+
+module REXML
+	# Wrapper class.  Use this class to access the XPath functions.
+	class XPath
+		include Functions
+		EMPTY_HASH = {}
+
+		# Finds and returns the first node that matches the supplied xpath.
+		# element::
+		# 	The context element
+		# path::
+		# 	The xpath to search for.  If not supplied or nil, returns the first
+		# 	node matching '*'.
+		# namespaces::
+		# 	If supplied, a Hash which defines a namespace mapping.
+		#
+		#  XPath.first( node )
+		#  XPath.first( doc, "//b"} )
+		#  XPath.first( node, "a/x:b", { "x"=>"http://doofus" } )
+    def XPath::first element, path=nil, namespaces=nil, variables={}
+      raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
+      raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
+			parser = XPathParser.new
+			parser.namespaces = namespaces
+			parser.variables = variables
+			path = "*" unless path
+			element = [element] unless element.kind_of? Array
+			parser.parse(path, element).flatten[0]
+		end
+
+		# Itterates over nodes that match the given path, calling the supplied
+		# block with the match.
+		# element::
+		#   The context element
+		# path::
+		#   The xpath to search for.  If not supplied or nil, defaults to '*'
+		# namespaces::
+		# 	If supplied, a Hash which defines a namespace mapping
+		#
+		#  XPath.each( node ) { |el| ... }
+		#  XPath.each( node, '/*[@attr='v']' ) { |el| ... }
+		#  XPath.each( node, 'ancestor::x' ) { |el| ... }
+		def XPath::each element, path=nil, namespaces=nil, variables={}, &block
+      raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
+      raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
+			parser = XPathParser.new
+			parser.namespaces = namespaces
+			parser.variables = variables
+			path = "*" unless path
+			element = [element] unless element.kind_of? Array
+			parser.parse(path, element).each( &block )
+		end
+
+		# Returns an array of nodes matching a given XPath.  
+		def XPath::match element, path=nil, namespaces=nil, variables={}
+			parser = XPathParser.new
+			parser.namespaces = namespaces
+			parser.variables = variables
+			path = "*" unless path
+			element = [element] unless element.kind_of? Array
+			parser.parse(path,element)
+		end
+	end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/xpath_parser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/xpath_parser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rexml/xpath_parser.rb	(revision 18425)
@@ -0,0 +1,783 @@
+require 'rexml/namespace'
+require 'rexml/xmltokens'
+require 'rexml/attribute'
+require 'rexml/syncenumerator'
+require 'rexml/parsers/xpathparser'
+
+class Object
+  def dclone
+    clone
+  end
+end
+class Symbol
+  def dclone ; self ; end
+end
+class Fixnum
+  def dclone ; self ; end
+end
+class Float
+  def dclone ; self ; end
+end
+class Array
+  def dclone
+    klone = self.clone
+    klone.clear
+    self.each{|v| klone << v.dclone}
+    klone
+  end
+end
+
+module REXML
+  # You don't want to use this class.  Really.  Use XPath, which is a wrapper
+  # for this class.  Believe me.  You don't want to poke around in here.
+  # There is strange, dark magic at work in this code.  Beware.  Go back!  Go
+  # back while you still can!
+  class XPathParser
+    include XMLTokens
+    LITERAL    = /^'([^']*)'|^"([^"]*)"/u
+
+    def initialize( )
+      @parser = REXML::Parsers::XPathParser.new
+      @namespaces = nil
+      @variables = {}
+    end
+
+    def namespaces=( namespaces={} )
+      Functions::namespace_context = namespaces
+      @namespaces = namespaces
+    end
+
+    def variables=( vars={} )
+      Functions::variables = vars
+      @variables = vars
+    end
+
+    def parse path, nodeset
+     #puts "#"*40
+     path_stack = @parser.parse( path )
+     #puts "PARSE: #{path} => #{path_stack.inspect}"
+     #puts "PARSE: nodeset = #{nodeset.inspect}"
+     match( path_stack, nodeset )
+    end
+
+    def get_first path, nodeset
+     #puts "#"*40
+     path_stack = @parser.parse( path )
+     #puts "PARSE: #{path} => #{path_stack.inspect}"
+     #puts "PARSE: nodeset = #{nodeset.inspect}"
+     first( path_stack, nodeset )
+    end
+
+    def predicate path, nodeset
+      path_stack = @parser.parse( path )
+      expr( path_stack, nodeset )
+    end
+
+    def []=( variable_name, value )
+      @variables[ variable_name ] = value
+    end
+
+
+    # Performs a depth-first (document order) XPath search, and returns the
+    # first match.  This is the fastest, lightest way to return a single result.
+    #
+    # FIXME: This method is incomplete!
+    def first( path_stack, node )
+      #puts "#{depth}) Entering match( #{path.inspect}, #{tree.inspect} )"
+      return nil if path.size == 0
+
+      case path[0]
+      when :document
+        # do nothing 
+        return first( path[1..-1], node )
+      when :child
+        for c in node.children
+          #puts "#{depth}) CHILD checking #{name(c)}"
+          r = first( path[1..-1], c )
+          #puts "#{depth}) RETURNING #{r.inspect}" if r
+          return r if r
+        end
+      when :qname
+        name = path[2]
+        #puts "#{depth}) QNAME #{name(tree)} == #{name} (path => #{path.size})"
+        if node.name == name
+          #puts "#{depth}) RETURNING #{tree.inspect}" if path.size == 3
+          return node if path.size == 3
+          return first( path[3..-1], node )
+        else
+          return nil
+        end
+      when :descendant_or_self
+        r = first( path[1..-1], node )
+        return r if r
+        for c in node.children
+          r = first( path, c )
+          return r if r
+        end
+      when :node
+        return first( path[1..-1], node )
+      when :any
+        return first( path[1..-1], node )
+      end
+      return nil
+    end
+
+
+    def match( path_stack, nodeset ) 
+      #puts "MATCH: path_stack = #{path_stack.inspect}"
+      #puts "MATCH: nodeset = #{nodeset.inspect}"
+      r = expr( path_stack, nodeset )
+      #puts "MAIN EXPR => #{r.inspect}"
+      r
+    end
+
+    private
+
+
+    # Returns a String namespace for a node, given a prefix
+    # The rules are:
+    # 
+    #  1. Use the supplied namespace mapping first.
+    #  2. If no mapping was supplied, use the context node to look up the namespace
+    def get_namespace( node, prefix )
+      if @namespaces
+        return @namespaces[prefix] || ''
+      else
+        return node.namespace( prefix ) if node.node_type == :element
+        return ''
+      end
+    end
+
+
+    # Expr takes a stack of path elements and a set of nodes (either a Parent
+    # or an Array and returns an Array of matching nodes
+    ALL = [ :attribute, :element, :text, :processing_instruction, :comment ]
+    ELEMENTS = [ :element ]
+    def expr( path_stack, nodeset, context=nil )
+      #puts "#"*15
+      #puts "In expr with #{path_stack.inspect}"
+      #puts "Returning" if path_stack.length == 0 || nodeset.length == 0
+      node_types = ELEMENTS
+      return nodeset if path_stack.length == 0 || nodeset.length == 0
+      while path_stack.length > 0
+        #puts "Path stack = #{path_stack.inspect}"
+        #puts "Nodeset is #{nodeset.inspect}"
+        if nodeset.length == 0
+          path_stack.clear
+          return []
+        end
+        case (op = path_stack.shift)
+        when :document
+          nodeset = [ nodeset[0].root_node ]
+          #puts ":document, nodeset = #{nodeset.inspect}"
+
+        when :qname
+          #puts "IN QNAME"
+          prefix = path_stack.shift
+          name = path_stack.shift
+          nodeset.delete_if do |node|
+            # FIXME: This DOUBLES the time XPath searches take
+            ns = get_namespace( node, prefix )
+            #puts "NS = #{ns.inspect}"
+            #puts "node.node_type == :element => #{node.node_type == :element}"
+            if node.node_type == :element
+              #puts "node.name == #{name} => #{node.name == name}"
+              if node.name == name
+                #puts "node.namespace == #{ns.inspect} => #{node.namespace == ns}"
+              end
+            end
+            !(node.node_type == :element and 
+              node.name == name and 
+              node.namespace == ns )
+          end
+          node_types = ELEMENTS
+
+        when :any
+          #puts "ANY 1: nodeset = #{nodeset.inspect}"
+          #puts "ANY 1: node_types = #{node_types.inspect}"
+          nodeset.delete_if { |node| !node_types.include?(node.node_type) }
+          #puts "ANY 2: nodeset = #{nodeset.inspect}"
+
+        when :self
+          # This space left intentionally blank
+
+        when :processing_instruction
+          target = path_stack.shift
+          nodeset.delete_if do |node|
+            (node.node_type != :processing_instruction) or 
+            ( target!='' and ( node.target != target ) )
+          end
+
+        when :text
+          nodeset.delete_if { |node| node.node_type != :text }
+
+        when :comment
+          nodeset.delete_if { |node| node.node_type != :comment }
+
+        when :node
+          # This space left intentionally blank
+          node_types = ALL
+
+        when :child
+          new_nodeset = []
+          nt = nil
+          for node in nodeset
+            nt = node.node_type
+            new_nodeset += node.children if nt == :element or nt == :document
+          end
+          nodeset = new_nodeset
+          node_types = ELEMENTS
+
+        when :literal
+          return path_stack.shift
+        
+        when :attribute
+          new_nodeset = []
+          case path_stack.shift
+          when :qname
+            prefix = path_stack.shift
+            name = path_stack.shift
+            for element in nodeset
+              if element.node_type == :element
+                #puts "Element name = #{element.name}"
+                #puts "get_namespace( #{element.inspect}, #{prefix} ) = #{get_namespace(element, prefix)}"
+                attrib = element.attribute( name, get_namespace(element, prefix) )
+                #puts "attrib = #{attrib.inspect}"
+                new_nodeset << attrib if attrib
+              end
+            end
+          when :any
+            #puts "ANY"
+            for element in nodeset
+              if element.node_type == :element
+                new_nodeset += element.attributes.to_a
+              end
+            end
+          end
+          nodeset = new_nodeset
+
+        when :parent
+          #puts "PARENT 1: nodeset = #{nodeset}"
+          nodeset = nodeset.collect{|n| n.parent}.compact
+          #nodeset = expr(path_stack.dclone, nodeset.collect{|n| n.parent}.compact)
+          #puts "PARENT 2: nodeset = #{nodeset.inspect}"
+          node_types = ELEMENTS
+
+        when :ancestor
+          new_nodeset = []
+          for node in nodeset
+            while node.parent
+              node = node.parent
+              new_nodeset << node unless new_nodeset.include? node
+            end
+          end
+          nodeset = new_nodeset
+          node_types = ELEMENTS
+
+        when :ancestor_or_self
+          new_nodeset = []
+          for node in nodeset
+            if node.node_type == :element
+              new_nodeset << node
+              while ( node.parent )
+                node = node.parent
+                new_nodeset << node unless new_nodeset.include? node
+              end
+            end
+          end
+          nodeset = new_nodeset
+          node_types = ELEMENTS
+
+        when :predicate
+          new_nodeset = []
+          subcontext = { :size => nodeset.size }
+          pred = path_stack.shift
+          nodeset.each_with_index { |node, index|
+            subcontext[ :node ] = node
+            #puts "PREDICATE SETTING CONTEXT INDEX TO #{index+1}"
+            subcontext[ :index ] = index+1
+            pc = pred.dclone
+            #puts "#{node.hash}) Recursing with #{pred.inspect} and [#{node.inspect}]"
+            result = expr( pc, [node], subcontext )
+            result = result[0] if result.kind_of? Array and result.length == 1
+            #puts "#{node.hash}) Result = #{result.inspect} (#{result.class.name})"
+            if result.kind_of? Numeric
+              #puts "Adding node #{node.inspect}" if result == (index+1)
+              new_nodeset << node if result == (index+1)
+            elsif result.instance_of? Array
+              if result.size > 0 and result.inject(false) {|k,s| s or k}
+                #puts "Adding node #{node.inspect}" if result.size > 0
+                new_nodeset << node if result.size > 0
+              end
+            else
+              #puts "Adding node #{node.inspect}" if result
+              new_nodeset << node if result
+            end
+          }
+          #puts "New nodeset = #{new_nodeset.inspect}"
+          #puts "Path_stack  = #{path_stack.inspect}"
+          nodeset = new_nodeset
+=begin
+          predicate = path_stack.shift
+          ns = nodeset.clone
+          result = expr( predicate, ns )
+          #puts "Result = #{result.inspect} (#{result.class.name})"
+          #puts "nodeset = #{nodeset.inspect}"
+          if result.kind_of? Array
+            nodeset = result.zip(ns).collect{|m,n| n if m}.compact
+          else
+            nodeset = result ? nodeset : []
+          end
+          #puts "Outgoing NS = #{nodeset.inspect}"
+=end
+
+        when :descendant_or_self
+          rv = descendant_or_self( path_stack, nodeset )
+          path_stack.clear
+          nodeset = rv
+          node_types = ELEMENTS
+
+        when :descendant
+          results = []
+          nt = nil
+          for node in nodeset
+            nt = node.node_type
+            results += expr( path_stack.dclone.unshift( :descendant_or_self ),
+              node.children ) if nt == :element or nt == :document
+          end
+          nodeset = results
+          node_types = ELEMENTS
+
+        when :following_sibling
+          #puts "FOLLOWING_SIBLING 1: nodeset = #{nodeset}"
+          results = []
+          for node in nodeset
+            all_siblings = node.parent.children
+            current_index = all_siblings.index( node )
+            following_siblings = all_siblings[ current_index+1 .. -1 ]
+            results += expr( path_stack.dclone, following_siblings )
+          end
+          #puts "FOLLOWING_SIBLING 2: nodeset = #{nodeset}"
+          nodeset = results
+
+        when :preceding_sibling
+          results = []
+          for node in nodeset
+            all_siblings = node.parent.children
+            current_index = all_siblings.index( node )
+            preceding_siblings = all_siblings[ 0 .. current_index-1 ].reverse
+            #results += expr( path_stack.dclone, preceding_siblings )
+          end
+          nodeset = preceding_siblings || []
+          node_types = ELEMENTS
+
+        when :preceding
+          new_nodeset = []
+          for node in nodeset
+            new_nodeset += preceding( node )
+          end
+          #puts "NEW NODESET => #{new_nodeset.inspect}"
+          nodeset = new_nodeset
+          node_types = ELEMENTS
+
+        when :following
+          new_nodeset = []
+          for node in nodeset
+            new_nodeset += following( node )
+          end
+          nodeset = new_nodeset
+          node_types = ELEMENTS
+
+        when :namespace
+          new_nodeset = []
+          prefix = path_stack.shift
+          for node in nodeset
+            if (node.node_type == :element or node.node_type == :attribute)
+              if (node.node_type == :element)
+                namespaces = node.namespaces
+              else
+                namespaces = node.element.namesapces
+              end
+              if (node.namespace == namespaces[prefix])
+                new_nodeset << node
+              end
+            end
+          end
+          nodeset = new_nodeset
+
+        when :variable
+          var_name = path_stack.shift
+          return @variables[ var_name ]
+
+        # :and, :or, :eq, :neq, :lt, :lteq, :gt, :gteq
+				# TODO: Special case for :or and :and -- not evaluate the right
+				# operand if the left alone determines result (i.e. is true for
+				# :or and false for :and).
+        when :eq, :neq, :lt, :lteq, :gt, :gteq, :and, :or
+          left = expr( path_stack.shift, nodeset.dup, context )
+          #puts "LEFT => #{left.inspect} (#{left.class.name})"
+          right = expr( path_stack.shift, nodeset.dup, context )
+          #puts "RIGHT => #{right.inspect} (#{right.class.name})"
+          res = equality_relational_compare( left, op, right )
+          #puts "RES => #{res.inspect}"
+          return res
+
+        when :and
+          left = expr( path_stack.shift, nodeset.dup, context )
+          #puts "LEFT => #{left.inspect} (#{left.class.name})"
+          if left == false || left.nil? || !left.inject(false) {|a,b| a | b}
+            return []
+          end
+          right = expr( path_stack.shift, nodeset.dup, context )
+          #puts "RIGHT => #{right.inspect} (#{right.class.name})"
+          res = equality_relational_compare( left, op, right )
+          #puts "RES => #{res.inspect}"
+          return res
+
+        when :div
+          left = Functions::number(expr(path_stack.shift, nodeset, context)).to_f
+          right = Functions::number(expr(path_stack.shift, nodeset, context)).to_f
+          return (left / right)
+
+        when :mod
+          left = Functions::number(expr(path_stack.shift, nodeset, context )).to_f
+          right = Functions::number(expr(path_stack.shift, nodeset, context )).to_f
+          return (left % right)
+
+        when :mult
+          left = Functions::number(expr(path_stack.shift, nodeset, context )).to_f
+          right = Functions::number(expr(path_stack.shift, nodeset, context )).to_f
+          return (left * right)
+
+        when :plus
+          left = Functions::number(expr(path_stack.shift, nodeset, context )).to_f
+          right = Functions::number(expr(path_stack.shift, nodeset, context )).to_f
+          return (left + right)
+
+        when :minus
+          left = Functions::number(expr(path_stack.shift, nodeset, context )).to_f
+          right = Functions::number(expr(path_stack.shift, nodeset, context )).to_f
+          return (left - right)
+
+        when :union
+          left = expr( path_stack.shift, nodeset, context )
+          right = expr( path_stack.shift, nodeset, context )
+          return (left | right)
+
+        when :neg
+          res = expr( path_stack, nodeset, context )
+          return -(res.to_f)
+
+        when :not
+        when :function
+          func_name = path_stack.shift.tr('-','_')
+          arguments = path_stack.shift
+          #puts "FUNCTION 0: #{func_name}(#{arguments.collect{|a|a.inspect}.join(', ')})" 
+          subcontext = context ? nil : { :size => nodeset.size }
+
+          res = []
+          cont = context
+          nodeset.each_with_index { |n, i| 
+            if subcontext
+              subcontext[:node]  = n
+              subcontext[:index] = i
+              cont = subcontext
+            end
+            arg_clone = arguments.dclone
+            args = arg_clone.collect { |arg| 
+              #puts "FUNCTION 1: Calling expr( #{arg.inspect}, [#{n.inspect}] )"
+              expr( arg, [n], cont ) 
+            }
+            #puts "FUNCTION 2: #{func_name}(#{args.collect{|a|a.inspect}.join(', ')})" 
+            Functions.context = cont
+            res << Functions.send( func_name, *args )
+            #puts "FUNCTION 3: #{res[-1].inspect}"
+          }
+          return res
+
+        end
+      end # while
+      #puts "EXPR returning #{nodeset.inspect}"
+      return nodeset
+    end
+
+
+    ##########################################################
+    # FIXME
+    # The next two methods are BAD MOJO!
+    # This is my achilles heel.  If anybody thinks of a better
+    # way of doing this, be my guest.  This really sucks, but 
+    # it is a wonder it works at all.
+    # ########################################################
+    
+    def descendant_or_self( path_stack, nodeset )
+      rs = []
+      #puts "#"*80
+      #puts "PATH_STACK = #{path_stack.inspect}"
+      #puts "NODESET = #{nodeset.collect{|n|n.inspect}.inspect}"
+      d_o_s( path_stack, nodeset, rs )
+      #puts "RS = #{rs.collect{|n|n.inspect}.inspect}"
+      document_order(rs.flatten.compact)
+      #rs.flatten.compact
+    end
+
+    def d_o_s( p, ns, r )
+      #puts "IN DOS with #{ns.inspect}; ALREADY HAVE #{r.inspect}"
+      nt = nil
+      ns.each_index do |i|
+        n = ns[i]
+        #puts "P => #{p.inspect}"
+        x = expr( p.dclone, [ n ] )
+        nt = n.node_type
+        d_o_s( p, n.children, x ) if nt == :element or nt == :document and n.children.size > 0
+        r.concat(x) if x.size > 0
+      end
+    end
+
+
+    # Reorders an array of nodes so that they are in document order
+    # It tries to do this efficiently.
+    #
+    # FIXME: I need to get rid of this, but the issue is that most of the XPath 
+    # interpreter functions as a filter, which means that we lose context going
+    # in and out of function calls.  If I knew what the index of the nodes was,
+    # I wouldn't have to do this.  Maybe add a document IDX for each node?
+    # Problems with mutable documents.  Or, rewrite everything.
+    def document_order( array_of_nodes )
+      new_arry = []
+      array_of_nodes.each { |node|
+        node_idx = [] 
+        np = node.node_type == :attribute ? node.element : node
+        while np.parent and np.parent.node_type == :element
+          node_idx << np.parent.index( np )
+          np = np.parent
+        end
+        new_arry << [ node_idx.reverse, node ]
+      }
+      #puts "new_arry = #{new_arry.inspect}"
+      new_arry.sort{ |s1, s2| s1[0] <=> s2[0] }.collect{ |s| s[1] }
+    end
+
+
+    def recurse( nodeset, &block )
+      for node in nodeset
+        yield node
+        recurse( node, &block ) if node.node_type == :element
+      end
+    end
+
+
+
+    # Builds a nodeset of all of the preceding nodes of the supplied node,
+    # in reverse document order
+    # preceding:: includes every element in the document that precedes this node, 
+    # except for ancestors
+    def preceding( node )
+      #puts "IN PRECEDING"
+      ancestors = []
+      p = node.parent
+      while p
+        ancestors << p
+        p = p.parent
+      end
+
+      acc = []
+      p = preceding_node_of( node )
+      #puts "P = #{p.inspect}"
+      while p
+        if ancestors.include? p
+          ancestors.delete(p)
+        else
+          acc << p
+        end
+        p = preceding_node_of( p )
+        #puts "P = #{p.inspect}"
+      end
+      acc
+    end
+
+    def preceding_node_of( node )
+     #puts "NODE: #{node.inspect}"
+     #puts "PREVIOUS NODE: #{node.previous_sibling_node.inspect}"
+     #puts "PARENT NODE: #{node.parent}"
+      psn = node.previous_sibling_node 
+      if psn.nil?
+        if node.parent.nil? or node.parent.class == Document 
+          return nil
+        end
+        return node.parent
+        #psn = preceding_node_of( node.parent )
+      end
+      while psn and psn.kind_of? Element and psn.children.size > 0
+        psn = psn.children[-1]
+      end
+      psn
+    end
+
+    def following( node )
+      #puts "IN PRECEDING"
+      acc = []
+      p = next_sibling_node( node )
+      #puts "P = #{p.inspect}"
+      while p
+        acc << p
+        p = following_node_of( p )
+        #puts "P = #{p.inspect}"
+      end
+      acc
+    end
+
+    def following_node_of( node )
+      #puts "NODE: #{node.inspect}"
+      #puts "PREVIOUS NODE: #{node.previous_sibling_node.inspect}"
+      #puts "PARENT NODE: #{node.parent}"
+      if node.kind_of? Element and node.children.size > 0
+        return node.children[0]
+      end
+      return next_sibling_node(node)
+    end
+
+    def next_sibling_node(node)
+      psn = node.next_sibling_node 
+      while psn.nil?
+        if node.parent.nil? or node.parent.class == Document 
+          return nil
+        end
+        node = node.parent
+        psn = node.next_sibling_node
+        #puts "psn = #{psn.inspect}"
+      end
+      return psn
+    end
+
+    def norm b
+      case b
+      when true, false
+        return b
+      when 'true', 'false'
+        return Functions::boolean( b )
+      when /^\d+(\.\d+)?$/
+        return Functions::number( b )
+      else
+        return Functions::string( b )
+      end
+    end
+
+    def equality_relational_compare( set1, op, set2 )
+      #puts "EQ_REL_COMP(#{set1.inspect} #{op.inspect} #{set2.inspect})"
+      if set1.kind_of? Array and set2.kind_of? Array
+			  #puts "#{set1.size} & #{set2.size}"
+        if set1.size == 1 and set2.size == 1
+          set1 = set1[0]
+          set2 = set2[0]
+        elsif set1.size == 0 or set2.size == 0
+          nd = set1.size==0 ? set2 : set1
+          rv = nd.collect { |il| compare( il, op, nil ) }
+          #puts "RV = #{rv.inspect}"
+          return rv
+        else
+          res = []
+          enum = SyncEnumerator.new( set1, set2 ).each { |i1, i2|
+            #puts "i1 = #{i1.inspect} (#{i1.class.name})"
+            #puts "i2 = #{i2.inspect} (#{i2.class.name})"
+            i1 = norm( i1 )
+            i2 = norm( i2 )
+            res << compare( i1, op, i2 )
+          }
+          return res
+        end
+      end
+		  #puts "EQ_REL_COMP: #{set1.inspect} (#{set1.class.name}), #{op}, #{set2.inspect} (#{set2.class.name})"
+      #puts "COMPARING VALUES"
+      # If one is nodeset and other is number, compare number to each item
+      # in nodeset s.t. number op number(string(item))
+      # If one is nodeset and other is string, compare string to each item
+      # in nodeset s.t. string op string(item)
+      # If one is nodeset and other is boolean, compare boolean to each item
+      # in nodeset s.t. boolean op boolean(item)
+      if set1.kind_of? Array or set2.kind_of? Array
+			  #puts "ISA ARRAY"
+        if set1.kind_of? Array
+          a = set1
+          b = set2
+        else
+          a = set2
+          b = set1
+        end
+
+        case b
+        when true, false
+          return a.collect {|v| compare( Functions::boolean(v), op, b ) }
+        when Numeric
+          return a.collect {|v| compare( Functions::number(v), op, b )}
+        when /^\d+(\.\d+)?$/
+          b = Functions::number( b )
+          #puts "B = #{b.inspect}"
+          return a.collect {|v| compare( Functions::number(v), op, b )}
+        else
+				  #puts "Functions::string( #{b}(#{b.class.name}) ) = #{Functions::string(b)}"
+          b = Functions::string( b )
+          return a.collect { |v| compare( Functions::string(v), op, b ) }
+        end
+      else
+        # If neither is nodeset,
+        #   If op is = or !=
+        #     If either boolean, convert to boolean
+        #     If either number, convert to number
+        #     Else, convert to string
+        #   Else
+        #     Convert both to numbers and compare
+        s1 = set1.to_s
+        s2 = set2.to_s
+        #puts "EQ_REL_COMP: #{set1}=>#{s1}, #{set2}=>#{s2}"
+        if s1 == 'true' or s1 == 'false' or s2 == 'true' or s2 == 'false'
+          #puts "Functions::boolean(#{set1})=>#{Functions::boolean(set1)}"
+          #puts "Functions::boolean(#{set2})=>#{Functions::boolean(set2)}"
+          set1 = Functions::boolean( set1 )
+          set2 = Functions::boolean( set2 )
+        else
+          if op == :eq or op == :neq
+            if s1 =~ /^\d+(\.\d+)?$/ or s2 =~ /^\d+(\.\d+)?$/
+              set1 = Functions::number( s1 )
+              set2 = Functions::number( s2 )
+            else
+              set1 = Functions::string( set1 )
+              set2 = Functions::string( set2 )
+            end
+          else
+            set1 = Functions::number( set1 )
+            set2 = Functions::number( set2 )
+          end
+        end
+        #puts "EQ_REL_COMP: #{set1} #{op} #{set2}"
+        #puts ">>> #{compare( set1, op, set2 )}"
+        return compare( set1, op, set2 )
+      end
+      return false
+    end
+
+    def compare a, op, b
+      #puts "COMPARE #{a.inspect}(#{a.class.name}) #{op} #{b.inspect}(#{b.class.name})"
+      case op
+      when :eq
+        a == b
+      when :neq
+        a != b
+      when :lt
+        a < b
+      when :lteq
+        a <= b
+      when :gt
+        a > b
+      when :gteq
+        a >= b
+      when :and
+        a and b
+      when :or
+        a or b
+      else
+        false
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rinda/rinda.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rinda/rinda.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rinda/rinda.rb	(revision 18425)
@@ -0,0 +1,283 @@
+require 'drb/drb'
+require 'thread'
+
+##
+# A module to implement the Linda distributed computing paradigm in Ruby.
+#
+# Rinda is part of DRb (dRuby).
+#
+# == Example(s)
+#
+# See the sample/drb/ directory in the Ruby distribution, from 1.8.2 onwards.
+#
+#--
+# TODO
+# == Introduction to Linda/rinda?
+#
+# == Why is this library separate from DRb?
+
+module Rinda
+
+  ##
+  # Rinda error base class
+
+  class RindaError < RuntimeError; end
+
+  ##
+  # Raised when a hash-based tuple has an invalid key.
+
+  class InvalidHashTupleKey < RindaError; end
+
+  ##
+  # Raised when trying to use a canceled tuple.
+
+  class RequestCanceledError < ThreadError; end
+
+  ##
+  # Raised when trying to use an expired tuple.
+
+  class RequestExpiredError < ThreadError; end
+
+  ##
+  # A tuple is the elementary object in Rinda programming.
+  # Tuples may be matched against templates if the tuple and
+  # the template are the same size.
+
+  class Tuple
+
+    ##
+    # Creates a new Tuple from +ary_or_hash+ which must be an Array or Hash.
+
+    def initialize(ary_or_hash)
+      if hash?(ary_or_hash)
+        init_with_hash(ary_or_hash)
+      else
+        init_with_ary(ary_or_hash)
+      end
+    end
+
+    ##
+    # The number of elements in the tuple.
+    
+    def size
+      @tuple.size
+    end
+
+    ##
+    # Accessor method for elements of the tuple.
+
+    def [](k)
+      @tuple[k]
+    end
+
+    ##
+    # Fetches item +k+ from the tuple.
+
+    def fetch(k)
+      @tuple.fetch(k)
+    end
+
+    ##
+    # Iterate through the tuple, yielding the index or key, and the
+    # value, thus ensuring arrays are iterated similarly to hashes.
+
+    def each # FIXME
+      if Hash === @tuple
+        @tuple.each { |k, v| yield(k, v) }
+      else
+        @tuple.each_with_index { |v, k| yield(k, v) }
+      end
+    end
+
+    ##
+    # Return the tuple itself
+    def value
+      @tuple
+    end
+
+    private
+
+    def hash?(ary_or_hash)
+      ary_or_hash.respond_to?(:keys)
+    end
+
+    ##
+    # Munges +ary+ into a valid Tuple.
+
+    def init_with_ary(ary)
+      @tuple = Array.new(ary.size)
+      @tuple.size.times do |i|
+        @tuple[i] = ary[i]
+      end
+    end
+
+    ##
+    # Ensures +hash+ is a valid Tuple.
+
+    def init_with_hash(hash)
+      @tuple = Hash.new
+      hash.each do |k, v|
+        raise InvalidHashTupleKey unless String === k
+        @tuple[k] = v
+      end
+    end
+
+  end
+
+  ##
+  # Templates are used to match tuples in Rinda.
+
+  class Template < Tuple
+
+    ##
+    # Matches this template against +tuple+.  The +tuple+ must be the same
+    # size as the template.  An element with a +nil+ value in a template acts
+    # as a wildcard, matching any value in the corresponding position in the
+    # tuple.  Elements of the template match the +tuple+ if the are #== or
+    # #===.
+    #
+    #   Template.new([:foo, 5]).match   Tuple.new([:foo, 5]) # => true
+    #   Template.new([:foo, nil]).match Tuple.new([:foo, 5]) # => true
+    #   Template.new([String]).match    Tuple.new(['hello']) # => true
+    #
+    #   Template.new([:foo]).match      Tuple.new([:foo, 5]) # => false
+    #   Template.new([:foo, 6]).match   Tuple.new([:foo, 5]) # => false
+    #   Template.new([:foo, nil]).match Tuple.new([:foo])    # => false
+    #   Template.new([:foo, 6]).match   Tuple.new([:foo])    # => false
+
+    def match(tuple)
+      return false unless tuple.respond_to?(:size)
+      return false unless tuple.respond_to?(:fetch)
+      return false unless self.size == tuple.size
+      each do |k, v|
+        begin
+          it = tuple.fetch(k)
+        rescue
+          return false
+        end
+        next if v.nil?
+        next if v == it
+        next if v === it
+        return false
+      end
+      return true
+    end
+    
+    ##
+    # Alias for #match.
+
+    def ===(tuple)
+      match(tuple)
+    end
+
+  end
+  
+  ##
+  # <i>Documentation?</i>
+
+  class DRbObjectTemplate
+
+    ##
+    # Creates a new DRbObjectTemplate that will match against +uri+ and +ref+.
+
+    def initialize(uri=nil, ref=nil)
+      @drb_uri = uri
+      @drb_ref = ref
+    end
+    
+    ##
+    # This DRbObjectTemplate matches +ro+ if the remote object's drburi and
+    # drbref are the same.  +nil+ is used as a wildcard.
+
+    def ===(ro)
+      return true if super(ro)
+      unless @drb_uri.nil?
+        return false unless (@drb_uri === ro.__drburi rescue false)
+      end
+      unless @drb_ref.nil?
+        return false unless (@drb_ref === ro.__drbref rescue false)
+      end
+      true
+    end
+
+  end
+
+  ##
+  # TupleSpaceProxy allows a remote Tuplespace to appear as local.
+
+  class TupleSpaceProxy
+
+    ##
+    # Creates a new TupleSpaceProxy to wrap +ts+.
+
+    def initialize(ts)
+      @ts = ts
+    end
+    
+    ##
+    # Adds +tuple+ to the proxied TupleSpace.  See TupleSpace#write.
+
+    def write(tuple, sec=nil)
+      @ts.write(tuple, sec)
+    end
+    
+    ##
+    # Takes +tuple+ from the proxied TupleSpace.  See TupleSpace#take.
+
+    def take(tuple, sec=nil, &block)
+      port = []
+      @ts.move(DRbObject.new(port), tuple, sec, &block)
+      port[0]
+    end
+    
+    ##
+    # Reads +tuple+ from the proxied TupleSpace.  See TupleSpace#read.
+
+    def read(tuple, sec=nil, &block)
+      @ts.read(tuple, sec, &block)
+    end
+    
+    ##
+    # Reads all tuples matching +tuple+ from the proxied TupleSpace.  See
+    # TupleSpace#read_all.
+
+    def read_all(tuple)
+      @ts.read_all(tuple)
+    end
+    
+    ##
+    # Registers for notifications of event +ev+ on the proxied TupleSpace.
+    # See TupleSpace#notify
+
+    def notify(ev, tuple, sec=nil)
+      @ts.notify(ev, tuple, sec)
+    end
+
+  end
+
+  ##
+  # An SimpleRenewer allows a TupleSpace to check if a TupleEntry is still
+  # alive.
+
+  class SimpleRenewer
+
+    include DRbUndumped
+
+    ##
+    # Creates a new SimpleRenewer that keeps an object alive for another +sec+
+    # seconds.
+
+    def initialize(sec=180)
+      @sec = sec
+    end
+
+    ##
+    # Called by the TupleSpace to check if the object is still alive.
+
+    def renew
+      @sec
+    end
+  end
+
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rinda/ring.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rinda/ring.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rinda/ring.rb	(revision 18425)
@@ -0,0 +1,271 @@
+#
+# Note: Rinda::Ring API is unstable.
+#
+require 'drb/drb'
+require 'rinda/rinda'
+require 'thread'
+
+module Rinda
+
+  ##
+  # The default port Ring discovery will use.
+
+  Ring_PORT = 7647
+
+  ##
+  # A RingServer allows a Rinda::TupleSpace to be located via UDP broadcasts.
+  # Service location uses the following steps:
+  #
+  # 1. A RingServer begins listening on the broadcast UDP address.
+  # 2. A RingFinger sends a UDP packet containing the DRb URI where it will
+  #    listen for a reply.
+  # 3. The RingServer recieves the UDP packet and connects back to the
+  #    provided DRb URI with the DRb service.
+
+  class RingServer
+
+    include DRbUndumped
+
+    ##
+    # Advertises +ts+ on the UDP broadcast address at +port+.
+
+    def initialize(ts, port=Ring_PORT)
+      @ts = ts
+      @soc = UDPSocket.open
+      @soc.bind('', port)
+      @w_service = write_service
+      @r_service = reply_service
+    end
+
+    ##
+    # Creates a thread that picks up UDP packets and passes them to do_write
+    # for decoding.
+
+    def write_service
+      Thread.new do
+	loop do
+	  msg = @soc.recv(1024)
+	  do_write(msg)
+	end
+      end
+    end
+  
+    ##
+    # Extracts the response URI from +msg+ and adds it to TupleSpace where it
+    # will be picked up by +reply_service+ for notification.
+
+    def do_write(msg)
+      Thread.new do
+	begin
+	  tuple, sec = Marshal.load(msg)
+	  @ts.write(tuple, sec)
+	rescue
+	end
+      end
+    end
+
+    ##
+    # Creates a thread that notifies waiting clients from the TupleSpace.
+
+    def reply_service
+      Thread.new do
+	loop do
+	  do_reply
+	end
+      end
+    end
+    
+    ##
+    # Pulls lookup tuples out of the TupleSpace and sends their DRb object the
+    # address of the local TupleSpace.
+
+    def do_reply
+      tuple = @ts.take([:lookup_ring, nil])
+      Thread.new { tuple[1].call(@ts) rescue nil}
+    rescue
+    end
+
+  end
+
+  ##
+  # RingFinger is used by RingServer clients to discover the RingServer's
+  # TupleSpace.  Typically, all a client needs to do is call
+  # RingFinger.primary to retrieve the remote TupleSpace, which it can then
+  # begin using.
+
+  class RingFinger
+
+    @@broadcast_list = ['<broadcast>', 'localhost']
+
+    @@finger = nil
+
+    ##
+    # Creates a singleton RingFinger and looks for a RingServer.  Returns the
+    # created RingFinger.
+
+    def self.finger
+      unless @@finger 
+	@@finger = self.new
+	@@finger.lookup_ring_any
+      end
+      @@finger
+    end
+
+    ##
+    # Returns the first advertised TupleSpace.
+
+    def self.primary
+      finger.primary
+    end
+
+    ##
+    # Contains all discoverd TupleSpaces except for the primary.
+
+    def self.to_a
+      finger.to_a
+    end
+
+    ##
+    # The list of addresses where RingFinger will send query packets.
+
+    attr_accessor :broadcast_list
+
+    ##
+    # The port that RingFinger will send query packets to.
+
+    attr_accessor :port
+
+    ##
+    # Contain the first advertised TupleSpace after lookup_ring_any is called.
+
+    attr_accessor :primary
+
+    ##
+    # Creates a new RingFinger that will look for RingServers at +port+ on
+    # the addresses in +broadcast_list+.
+
+    def initialize(broadcast_list=@@broadcast_list, port=Ring_PORT)
+      @broadcast_list = broadcast_list || ['localhost']
+      @port = port
+      @primary = nil
+      @rings = []
+    end
+
+    ##
+    # Contains all discovered TupleSpaces except for the primary.
+
+    def to_a
+      @rings
+    end
+
+    ##
+    # Iterates over all discovered TupleSpaces starting with the primary.
+
+    def each
+      lookup_ring_any unless @primary
+      return unless @primary
+      yield(@primary)
+      @rings.each { |x| yield(x) }
+    end
+
+    ##
+    # Looks up RingServers waiting +timeout+ seconds.  RingServers will be
+    # given +block+ as a callback, which will be called with the remote
+    # TupleSpace.
+
+    def lookup_ring(timeout=5, &block)
+      return lookup_ring_any(timeout) unless block_given?
+
+      msg = Marshal.dump([[:lookup_ring, DRbObject.new(block)], timeout])
+      @broadcast_list.each do |it|
+	soc = UDPSocket.open
+	begin
+	  soc.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
+	  soc.send(msg, 0, it, @port)
+	rescue
+	  nil
+	ensure
+	  soc.close
+	end
+      end
+      sleep(timeout)
+    end
+
+    ##
+    # Returns the first found remote TupleSpace.  Any further recovered
+    # TupleSpaces can be found by calling +to_a+.
+
+    def lookup_ring_any(timeout=5)
+      queue = Queue.new
+
+      th = Thread.new do
+	self.lookup_ring(timeout) do |ts|
+	  queue.push(ts)
+	end
+	queue.push(nil)
+	while it = queue.pop
+	  @rings.push(it)
+	end
+      end
+      
+      @primary = queue.pop
+      raise('RingNotFound') if @primary.nil?
+      @primary
+    end
+
+  end
+
+  ##
+  # RingProvider uses a RingServer advertised TupleSpace as a name service.
+  # TupleSpace clients can register themselves with the remote TupleSpace and
+  # look up other provided services via the remote TupleSpace.
+  #
+  # Services are registered with a tuple of the format [:name, klass,
+  # DRbObject, description].
+
+  class RingProvider
+
+    ##
+    # Creates a RingProvider that will provide a +klass+ service running on
+    # +front+, with a +description+.  +renewer+ is optional.
+
+    def initialize(klass, front, desc, renewer = nil)
+      @tuple = [:name, klass, front, desc]
+      @renewer = renewer || Rinda::SimpleRenewer.new
+    end
+
+    ##
+    # Advertises this service on the primary remote TupleSpace.
+
+    def provide
+      ts = Rinda::RingFinger.primary
+      ts.write(@tuple, @renewer)
+    end
+
+  end
+
+end
+
+if __FILE__ == $0
+  DRb.start_service
+  case ARGV.shift
+  when 's'
+    require 'rinda/tuplespace'
+    ts = Rinda::TupleSpace.new
+    place = Rinda::RingServer.new(ts)
+    $stdin.gets
+  when 'w'
+    finger = Rinda::RingFinger.new(nil)
+    finger.lookup_ring do |ts|
+      p ts
+      ts.write([:hello, :world])
+    end
+  when 'r'
+    finger = Rinda::RingFinger.new(nil)
+    finger.lookup_ring do |ts|
+      p ts
+      p ts.take([nil, nil])
+    end
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rinda/tuplespace.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rinda/tuplespace.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rinda/tuplespace.rb	(revision 18425)
@@ -0,0 +1,589 @@
+require 'monitor'
+require 'thread'
+require 'drb/drb'
+require 'rinda/rinda'
+
+module Rinda
+
+  ##
+  # A TupleEntry is a Tuple (i.e. a possible entry in some Tuplespace)
+  # together with expiry and cancellation data.
+
+  class TupleEntry
+
+    include DRbUndumped
+
+    attr_accessor :expires
+
+    ##
+    # Creates a TupleEntry based on +ary+ with an optional renewer or expiry
+    # time +sec+.
+    #
+    # A renewer must implement the +renew+ method which returns a Numeric,
+    # nil, or true to indicate when the tuple has expired.
+
+    def initialize(ary, sec=nil)
+      @cancel = false
+      @expires = nil
+      @tuple = make_tuple(ary)
+      @renewer = nil
+      renew(sec)
+    end
+
+    ##
+    # Marks this TupleEntry as canceled.
+
+    def cancel
+      @cancel = true
+    end
+
+    ##
+    # A TupleEntry is dead when it is canceled or expired.
+
+    def alive?
+      !canceled? && !expired?
+    end
+
+    ##
+    # Return the object which makes up the tuple itself: the Array
+    # or Hash.
+
+    def value; @tuple.value; end
+
+    ##
+    # Returns the canceled status.
+
+    def canceled?; @cancel; end
+
+    ##
+    # Has this tuple expired? (true/false).
+    #
+    # A tuple has expired when its expiry timer based on the +sec+ argument to
+    # #initialize runs out.
+
+    def expired?
+      return true unless @expires
+      return false if @expires > Time.now
+      return true if @renewer.nil?
+      renew(@renewer)
+      return true unless @expires
+      return @expires < Time.now
+    end
+
+    ##
+    # Reset the expiry time according to +sec_or_renewer+.  
+    #
+    # +nil+::    it is set to expire in the far future.
+    # +false+::  it has expired.
+    # Numeric::  it will expire in that many seconds.
+    #
+    # Otherwise the argument refers to some kind of renewer object
+    # which will reset its expiry time. 
+
+    def renew(sec_or_renewer)
+      sec, @renewer = get_renewer(sec_or_renewer)
+      @expires = make_expires(sec)
+    end
+
+    ##
+    # Returns an expiry Time based on +sec+ which can be one of:
+    # Numeric:: +sec+ seconds into the future
+    # +true+::  the expiry time is the start of 1970 (i.e. expired)
+    # +nil+::   it is  Tue Jan 19 03:14:07 GMT Standard Time 2038 (i.e. when
+    #           UNIX clocks will die)
+
+    def make_expires(sec=nil)
+      case sec
+      when Numeric
+        Time.now + sec
+      when true
+        Time.at(1)
+      when nil
+        Time.at(2**31-1)
+      end
+    end
+
+    ##
+    # Retrieves +key+ from the tuple.
+
+    def [](key)
+      @tuple[key]
+    end
+
+    ##
+    # Fetches +key+ from the tuple.
+
+    def fetch(key)
+      @tuple.fetch(key)
+    end
+
+    ##
+    # The size of the tuple.
+
+    def size
+      @tuple.size
+    end
+
+    ##
+    # Creates a Rinda::Tuple for +ary+.
+
+    def make_tuple(ary)
+      Rinda::Tuple.new(ary)
+    end
+
+    private
+
+    ##
+    # Returns a valid argument to make_expires and the renewer or nil.
+    #
+    # Given +true+, +nil+, or Numeric, returns that value and +nil+ (no actual
+    # renewer).  Otherwise it returns an expiry value from calling +it.renew+
+    # and the renewer.
+
+    def get_renewer(it)
+      case it
+      when Numeric, true, nil
+        return it, nil
+      else
+        begin
+          return it.renew, it
+        rescue Exception
+          return it, nil
+        end
+      end
+    end
+
+  end
+
+  ##
+  # A TemplateEntry is a Template together with expiry and cancellation data.
+
+  class TemplateEntry < TupleEntry
+    ##
+    # Matches this TemplateEntry against +tuple+.  See Template#match for
+    # details on how a Template matches a Tuple.
+
+    def match(tuple)
+      @tuple.match(tuple)
+    end
+    
+    alias === match
+
+    def make_tuple(ary) # :nodoc:
+      Rinda::Template.new(ary)
+    end
+
+  end
+
+  ##
+  # <i>Documentation?</i>
+
+  class WaitTemplateEntry < TemplateEntry
+
+    attr_reader :found
+
+    def initialize(place, ary, expires=nil)
+      super(ary, expires)
+      @place = place
+      @cond = place.new_cond
+      @found = nil
+    end
+
+    def cancel
+      super
+      signal
+    end
+
+    def wait
+      @cond.wait
+    end
+
+    def read(tuple)
+      @found = tuple
+      signal
+    end
+
+    def signal
+      @place.synchronize do
+        @cond.signal
+      end
+    end
+
+  end
+
+  ##
+  # A NotifyTemplateEntry is returned by TupleSpace#notify and is notified of
+  # TupleSpace changes.  You may receive either your subscribed event or the
+  # 'close' event when iterating over notifications.
+  #
+  # See TupleSpace#notify_event for valid notification types.
+  #
+  # == Example
+  #
+  #   ts = Rinda::TupleSpace.new
+  #   observer = ts.notify 'write', [nil]
+  #   
+  #   Thread.start do
+  #     observer.each { |t| p t }
+  #   end
+  #   
+  #   3.times { |i| ts.write [i] }
+  #
+  # Outputs:
+  #
+  #   ['write', [0]]
+  #   ['write', [1]]
+  #   ['write', [2]]
+
+  class NotifyTemplateEntry < TemplateEntry
+
+    ##
+    # Creates a new NotifyTemplateEntry that watches +place+ for +event+s that
+    # match +tuple+.
+
+    def initialize(place, event, tuple, expires=nil)
+      ary = [event, Rinda::Template.new(tuple)]
+      super(ary, expires)
+      @queue = Queue.new
+      @done = false
+    end
+
+    ##
+    # Called by TupleSpace to notify this NotifyTemplateEntry of a new event.
+
+    def notify(ev)
+      @queue.push(ev)
+    end
+
+    ##
+    # Retrieves a notification.  Raises RequestExpiredError when this
+    # NotifyTemplateEntry expires.
+
+    def pop
+      raise RequestExpiredError if @done
+      it = @queue.pop
+      @done = true if it[0] == 'close'
+      return it
+    end
+
+    ##
+    # Yields event/tuple pairs until this NotifyTemplateEntry expires.
+
+    def each # :yields: event, tuple
+      while !@done
+        it = pop
+        yield(it)
+      end
+    rescue 
+    ensure
+      cancel
+    end
+
+  end
+
+  ##
+  # TupleBag is an unordered collection of tuples. It is the basis
+  # of Tuplespace.
+
+  class TupleBag
+
+    def initialize # :nodoc:
+      @hash = {}
+    end
+
+    ##
+    # +true+ if the TupleBag to see if it has any expired entries.
+
+    def has_expires?
+      @hash.each do |k, v|
+        v.each do |tuple|
+          return true if tuple.expires
+        end
+      end
+      false
+    end
+
+    ##
+    # Add +ary+ to the TupleBag.
+
+    def push(ary)
+      size = ary.size
+      @hash[size] ||= []
+      @hash[size].push(ary)
+    end
+
+    ##
+    # Removes +ary+ from the TupleBag.
+
+    def delete(ary)
+      size = ary.size
+      @hash.fetch(size, []).delete(ary)
+    end
+
+    ##
+    # Finds all live tuples that match +template+.
+
+    def find_all(template)
+      @hash.fetch(template.size, []).find_all do |tuple|
+        tuple.alive? && template.match(tuple)
+      end
+    end
+
+    ##
+    # Finds a live tuple that matches +template+.
+
+    def find(template)
+      @hash.fetch(template.size, []).find do |tuple|
+        tuple.alive? && template.match(tuple)
+      end
+    end
+
+    ##
+    # Finds all tuples in the TupleBag which when treated as templates, match
+    # +tuple+ and are alive.
+
+    def find_all_template(tuple)
+      @hash.fetch(tuple.size, []).find_all do |template|
+        template.alive? && template.match(tuple)
+      end
+    end
+
+    ##
+    # Delete tuples which dead tuples from the TupleBag, returning the deleted
+    # tuples.
+
+    def delete_unless_alive
+      deleted = []
+      @hash.keys.each do |size|
+        ary = []
+        @hash[size].each do |tuple|
+          if tuple.alive?
+            ary.push(tuple)
+          else
+            deleted.push(tuple)
+          end
+        end
+        @hash[size] = ary
+      end
+      deleted
+    end
+
+  end
+
+  ##
+  # The Tuplespace manages access to the tuples it contains,
+  # ensuring mutual exclusion requirements are met.
+  #
+  # The +sec+ option for the write, take, move, read and notify methods may
+  # either be a number of seconds or a Renewer object.
+
+  class TupleSpace
+
+    include DRbUndumped
+    include MonitorMixin
+
+    ##
+    # Creates a new TupleSpace.  +period+ is used to control how often to look
+    # for dead tuples after modifications to the TupleSpace.
+    #
+    # If no dead tuples are found +period+ seconds after the last
+    # modification, the TupleSpace will stop looking for dead tuples.
+
+    def initialize(period=60)
+      super()
+      @bag = TupleBag.new
+      @read_waiter = TupleBag.new
+      @take_waiter = TupleBag.new
+      @notify_waiter = TupleBag.new
+      @period = period
+      @keeper = nil
+    end
+
+    ##
+    # Adds +tuple+
+
+    def write(tuple, sec=nil)
+      entry = TupleEntry.new(tuple, sec)
+      start_keeper
+      synchronize do
+        if entry.expired?
+          @read_waiter.find_all_template(entry).each do |template|
+            template.read(tuple)
+          end
+          notify_event('write', entry.value)
+          notify_event('delete', entry.value)
+        else
+          @bag.push(entry)
+          @read_waiter.find_all_template(entry).each do |template|
+            template.read(tuple)
+          end
+          @take_waiter.find_all_template(entry).each do |template|
+            template.signal
+          end
+          notify_event('write', entry.value)
+        end
+      end
+      entry
+    end
+
+    ##
+    # Removes +tuple+
+
+    def take(tuple, sec=nil, &block)
+      move(nil, tuple, sec, &block)
+    end
+
+    ##
+    # Moves +tuple+ to +port+.
+
+    def move(port, tuple, sec=nil)
+      template = WaitTemplateEntry.new(self, tuple, sec)
+      yield(template) if block_given?
+      start_keeper
+      synchronize do
+        entry = @bag.find(template)
+        if entry
+          port.push(entry.value) if port
+          @bag.delete(entry)
+          notify_event('take', entry.value)
+          return entry.value
+        end
+        raise RequestExpiredError if template.expired?
+
+        begin
+          @take_waiter.push(template)
+          while true
+            raise RequestCanceledError if template.canceled?
+            raise RequestExpiredError if template.expired?
+            entry = @bag.find(template)
+            if entry
+              port.push(entry.value) if port
+              @bag.delete(entry)
+              notify_event('take', entry.value)
+              return entry.value
+            end
+            template.wait
+          end
+        ensure
+          @take_waiter.delete(template)
+        end
+      end
+    end
+
+    ##
+    # Reads +tuple+, but does not remove it.
+
+    def read(tuple, sec=nil)
+      template = WaitTemplateEntry.new(self, tuple, sec)
+      yield(template) if block_given?
+      start_keeper
+      synchronize do
+        entry = @bag.find(template)
+        return entry.value if entry
+        raise RequestExpiredError if template.expired?
+
+        begin
+          @read_waiter.push(template)
+          template.wait
+          raise RequestCanceledError if template.canceled?
+          raise RequestExpiredError if template.expired?
+          return template.found
+        ensure
+          @read_waiter.delete(template)
+        end
+      end
+    end
+
+    ##
+    # Returns all tuples matching +tuple+.  Does not remove the found tuples.
+
+    def read_all(tuple)
+      template = WaitTemplateEntry.new(self, tuple, nil)
+      synchronize do
+        entry = @bag.find_all(template)
+        entry.collect do |e|
+          e.value
+        end
+      end
+    end
+
+    ##
+    # Registers for notifications of +event+.  Returns a NotifyTemplateEntry.
+    # See NotifyTemplateEntry for examples of how to listen for notifications.
+    #
+    # +event+ can be:
+    # 'write'::  A tuple was added
+    # 'take'::   A tuple was taken or moved
+    # 'delete':: A tuple was lost after being overwritten or expiring
+    #
+    # The TupleSpace will also notify you of the 'close' event when the
+    # NotifyTemplateEntry has expired.
+
+    def notify(event, tuple, sec=nil)
+      template = NotifyTemplateEntry.new(self, event, tuple, sec)
+      synchronize do
+        @notify_waiter.push(template)
+      end
+      template
+    end
+
+    private
+
+    ##
+    # Removes dead tuples.
+
+    def keep_clean
+      synchronize do
+        @read_waiter.delete_unless_alive.each do |e|
+          e.signal
+        end
+        @take_waiter.delete_unless_alive.each do |e|
+          e.signal
+        end
+        @notify_waiter.delete_unless_alive.each do |e|
+          e.notify(['close'])
+        end
+        @bag.delete_unless_alive.each do |e|
+          notify_event('delete', e.value)
+        end
+      end
+    end
+
+    ##
+    # Notifies all registered listeners for +event+ of a status change of
+    # +tuple+.
+
+    def notify_event(event, tuple)
+      ev = [event, tuple]
+      @notify_waiter.find_all_template(ev).each do |template|
+        template.notify(ev)
+      end
+    end
+
+    ##
+    # Creates a thread that scans the tuplespace for expired tuples.
+
+    def start_keeper
+      return if @keeper && @keeper.alive?
+      @keeper = Thread.new do
+        while need_keeper?
+          keep_clean
+          sleep(@period)
+        end
+      end
+    end
+
+    ##
+    # Checks the tuplespace to see if it needs cleaning.
+
+    def need_keeper?
+      return true if @bag.has_expires?
+      return true if @read_waiter.has_expires?
+      return true if @take_waiter.has_expires?
+      return true if @notify_waiter.has_expires?
+    end
+
+  end
+
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss.rb	(revision 18425)
@@ -0,0 +1,16 @@
+# Copyright (c) 2003-2005 Kouhei Sutou.  You can redistribute it and/or
+# modify it under the same terms as Ruby.
+#
+# Author:: Kouhei Sutou <kou@cozmixng.org>
+# Tutorial:: http://www.cozmixng.org/~rwiki/?cmd=view;name=RSS+Parser%3A%3ATutorial.en
+
+require 'rss/1.0'
+require 'rss/2.0'
+require 'rss/content'
+require 'rss/dublincore'
+require 'rss/image'
+require 'rss/syndication'
+#require 'rss/taxonomy'
+require 'rss/trackback'
+
+require "rss/maker"
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/0.9.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/0.9.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/0.9.rb	(revision 18425)
@@ -0,0 +1,422 @@
+require "rss/parser"
+
+module RSS
+
+  module RSS09
+    NSPOOL = {}
+    ELEMENTS = []
+
+    def self.append_features(klass)
+      super
+      
+      klass.install_must_call_validator('', "")
+    end
+  end
+
+  class Rss < Element
+
+    include RSS09
+    include RootElementMixin
+
+    %w(channel).each do |name|
+      install_have_child_element(name, "", nil)
+    end
+
+    attr_accessor :rss_version, :version, :encoding, :standalone
+    
+    def initialize(rss_version, version=nil, encoding=nil, standalone=nil)
+      super
+    end
+
+    def items
+      if @channel
+        @channel.items
+      else
+        []
+      end
+    end
+
+    def image
+      if @channel
+        @channel.image
+      else
+        nil
+      end
+    end
+
+    def textinput
+      if @channel
+        @channel.textInput
+      else
+        nil
+      end
+    end
+
+    def setup_maker_elements(maker)
+      super
+      items.each do |item|
+        item.setup_maker(maker.items)
+      end
+    end
+
+    private
+    def _attrs
+      [
+        ["version", true, "rss_version"],
+      ]
+    end
+
+    class Channel < Element
+
+      include RSS09
+
+      [
+        ["title", nil, :text],
+        ["link", nil, :text],
+        ["description", nil, :text],
+        ["language", nil, :text],
+        ["copyright", "?", :text],
+        ["managingEditor", "?", :text],
+        ["webMaster", "?", :text],
+        ["rating", "?", :text],
+        ["pubDate", "?", :date, :rfc822],
+        ["lastBuildDate", "?", :date, :rfc822],
+        ["docs", "?", :text],
+        ["cloud", "?", :have_attribute],
+        ["skipDays", "?", :have_child],
+        ["skipHours", "?", :have_child],
+        ["image", nil, :have_child],
+        ["item", "*", :have_children],
+        ["textInput", "?", :have_child],
+      ].each do |name, occurs, type, *args|
+        __send__("install_#{type}_element", name, "", occurs, name, *args)
+      end
+      alias date pubDate
+      alias date= pubDate=
+
+      private
+      def maker_target(maker)
+        maker.channel
+      end
+
+      def setup_maker_elements(channel)
+        super
+        [
+          [skipDays, "day"],
+          [skipHours, "hour"],
+        ].each do |skip, key|
+          if skip
+            skip.__send__("#{key}s").each do |val|
+              target_skips = channel.__send__("skip#{key.capitalize}s")
+              new_target = target_skips.__send__("new_#{key}")
+              new_target.content = val.content
+            end
+          end
+        end
+      end
+
+      def not_need_to_call_setup_maker_variables
+        %w(image textInput)
+      end
+    
+      class SkipDays < Element
+        include RSS09
+
+        [
+          ["day", "*"]
+        ].each do |name, occurs|
+          install_have_children_element(name, "", occurs)
+        end
+
+        class Day < Element
+          include RSS09
+
+          content_setup
+
+          def initialize(*args)
+            if Utils.element_initialize_arguments?(args)
+              super
+            else
+              super()
+              self.content = args[0]
+            end
+          end
+      
+        end
+        
+      end
+      
+      class SkipHours < Element
+        include RSS09
+
+        [
+          ["hour", "*"]
+        ].each do |name, occurs|
+          install_have_children_element(name, "", occurs)
+        end
+
+        class Hour < Element
+          include RSS09
+
+          content_setup(:integer)
+
+          def initialize(*args)
+            if Utils.element_initialize_arguments?(args)
+              super
+            else
+              super()
+              self.content = args[0]
+            end
+          end
+        end
+        
+      end
+      
+      class Image < Element
+
+        include RSS09
+        
+        %w(url title link).each do |name|
+          install_text_element(name, "", nil)
+        end
+        [
+          ["width", :integer],
+          ["height", :integer],
+          ["description"],
+        ].each do |name, type|
+          install_text_element(name, "", "?", name, type)
+        end
+
+        def initialize(*args)
+          if Utils.element_initialize_arguments?(args)
+            super
+          else
+            super()
+            self.url = args[0]
+            self.title = args[1]
+            self.link = args[2]
+            self.width = args[3]
+            self.height = args[4]
+            self.description = args[5]
+          end
+        end
+
+        private
+        def maker_target(maker)
+          maker.image
+        end
+      end
+
+      class Cloud < Element
+
+        include RSS09
+
+        [
+          ["domain", "", true],
+          ["port", "", true, :integer],
+          ["path", "", true],
+          ["registerProcedure", "", true],
+          ["protocol", "", true],
+        ].each do |name, uri, required, type|
+          install_get_attribute(name, uri, required, type)
+        end
+
+        def initialize(*args)
+          if Utils.element_initialize_arguments?(args)
+            super
+          else
+            super()
+            self.domain = args[0]
+            self.port = args[1]
+            self.path = args[2]
+            self.registerProcedure = args[3]
+            self.protocol = args[4]
+          end
+        end
+      end
+      
+      class Item < Element
+        
+        include RSS09
+
+        [
+          ["title", '?', :text],
+          ["link", '?', :text],
+          ["description", '?', :text],
+          ["category", '*', :have_children, "categories"],
+          ["source", '?', :have_child],
+          ["enclosure", '?', :have_child],
+        ].each do |tag, occurs, type, *args|
+          __send__("install_#{type}_element", tag, "", occurs, tag, *args)
+        end
+
+        private
+        def maker_target(items)
+          if items.respond_to?("items")
+            # For backward compatibility
+            items = items.items
+          end
+          items.new_item
+        end
+
+        def setup_maker_element(item)
+          super
+          @enclosure.setup_maker(item) if @enclosure
+          @source.setup_maker(item) if @source
+        end
+        
+        class Source < Element
+
+          include RSS09
+
+          [
+            ["url", "", true]
+          ].each do |name, uri, required|
+            install_get_attribute(name, uri, required)
+          end
+          
+          content_setup
+
+          def initialize(*args)
+            if Utils.element_initialize_arguments?(args)
+              super
+            else
+              super()
+              self.url = args[0]
+              self.content = args[1]
+            end
+          end
+
+          private
+          def maker_target(item)
+            item.source
+          end
+
+          def setup_maker_attributes(source)
+            source.url = url
+            source.content = content
+          end
+        end
+
+        class Enclosure < Element
+
+          include RSS09
+
+          [
+            ["url", "", true],
+            ["length", "", true, :integer],
+            ["type", "", true],
+          ].each do |name, uri, required, type|
+            install_get_attribute(name, uri, required, type)
+          end
+
+          def initialize(*args)
+            if Utils.element_initialize_arguments?(args)
+              super
+            else
+              super()
+              self.url = args[0]
+              self.length = args[1]
+              self.type = args[2]
+            end
+          end
+
+          private
+          def maker_target(item)
+            item.enclosure
+          end
+
+          def setup_maker_attributes(enclosure)
+            enclosure.url = url
+            enclosure.length = length
+            enclosure.type = type
+          end
+        end
+
+        class Category < Element
+
+          include RSS09
+          
+          [
+            ["domain", "", false]
+          ].each do |name, uri, required|
+            install_get_attribute(name, uri, required)
+          end
+
+          content_setup
+
+          def initialize(*args)
+            if Utils.element_initialize_arguments?(args)
+              super
+            else
+              super()
+              self.domain = args[0]
+              self.content = args[1]
+            end
+          end
+
+          private
+          def maker_target(item)
+            item.new_category
+          end
+
+          def setup_maker_attributes(category)
+            category.domain = domain
+            category.content = content
+          end
+          
+        end
+
+      end
+      
+      class TextInput < Element
+
+        include RSS09
+
+        %w(title description name link).each do |name|
+          install_text_element(name, "", nil)
+        end
+
+        def initialize(*args)
+          if Utils.element_initialize_arguments?(args)
+            super
+          else
+            super()
+            self.title = args[0]
+            self.description = args[1]
+            self.name = args[2]
+            self.link = args[3]
+          end
+        end
+
+        private
+        def maker_target(maker)
+          maker.textinput
+        end
+      end
+      
+    end
+    
+  end
+
+  RSS09::ELEMENTS.each do |name|
+    BaseListener.install_get_text_element("", name, "#{name}=")
+  end
+
+  module ListenerMixin
+    private
+    def start_rss(tag_name, prefix, attrs, ns)
+      check_ns(tag_name, prefix, ns, "")
+      
+      @rss = Rss.new(attrs['version'], @version, @encoding, @standalone)
+      @rss.do_validate = @do_validate
+      @rss.xml_stylesheets = @xml_stylesheets
+      @last_element = @rss
+      @proc_stack.push Proc.new { |text, tags|
+        @rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate
+      }
+    end
+    
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/1.0.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/1.0.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/1.0.rb	(revision 18425)
@@ -0,0 +1,451 @@
+require "rss/parser"
+
+module RSS
+
+  module RSS10
+    NSPOOL = {}
+    ELEMENTS = []
+
+    def self.append_features(klass)
+      super
+      
+      klass.install_must_call_validator('', ::RSS::URI)
+    end
+
+  end
+
+  class RDF < Element
+
+    include RSS10
+    include RootElementMixin
+
+    class << self
+
+      def required_uri
+        URI
+      end
+
+    end
+
+    @tag_name = 'RDF'
+
+    PREFIX = 'rdf'
+    URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+
+    install_ns('', ::RSS::URI)
+    install_ns(PREFIX, URI)
+
+    [
+      ["channel", nil],
+      ["image", "?"],
+      ["item", "+", :children],
+      ["textinput", "?"],
+    ].each do |tag, occurs, type|
+      type ||= :child
+      __send__("install_have_#{type}_element", tag, ::RSS::URI, occurs)
+    end
+
+    attr_accessor :rss_version, :version, :encoding, :standalone
+    
+    def initialize(version=nil, encoding=nil, standalone=nil)
+      super('1.0', version, encoding, standalone)
+    end
+
+    def full_name
+      tag_name_with_prefix(PREFIX)
+    end
+
+    class Li < Element
+
+      include RSS10
+
+      class << self
+        def required_uri
+          URI
+        end
+      end
+      
+      [
+        ["resource", [URI, ""], true]
+      ].each do |name, uri, required|
+        install_get_attribute(name, uri, required)
+      end
+      
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.resource = args[0]
+        end
+      end
+
+      def full_name
+        tag_name_with_prefix(PREFIX)
+      end
+    end
+
+    class Seq < Element
+
+      include RSS10
+
+      Li = ::RSS::RDF::Li
+
+      class << self
+        def required_uri
+          URI
+        end
+      end
+
+      @tag_name = 'Seq'
+      
+      install_have_children_element("li", URI, "*")
+      install_must_call_validator('rdf', ::RSS::RDF::URI)
+      
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          @li = args[0] if args[0]
+        end
+      end
+
+      def full_name
+        tag_name_with_prefix(PREFIX)
+      end
+      
+      def setup_maker(target)
+        lis.each do |li|
+          target << li.resource
+        end
+      end
+    end
+
+    class Bag < Element
+
+      include RSS10
+
+      Li = ::RSS::RDF::Li
+
+      class << self
+        def required_uri
+          URI
+        end
+      end
+
+      @tag_name = 'Bag'
+      
+      install_have_children_element("li", URI, "*")
+      install_must_call_validator('rdf', URI)
+      
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          @li = args[0] if args[0]
+        end
+      end
+
+      def full_name
+        tag_name_with_prefix(PREFIX)
+      end
+      
+      def setup_maker(target)
+        lis.each do |li|
+          target << li.resource
+        end
+      end
+    end
+
+    class Channel < Element
+
+      include RSS10
+      
+      class << self
+
+        def required_uri
+          ::RSS::URI
+        end
+
+      end
+
+      [
+        ["about", URI, true]
+      ].each do |name, uri, required|
+        install_get_attribute(name, uri, required, nil, nil,
+                              "#{PREFIX}:#{name}")
+      end
+
+      [
+        ['title', nil, :text],
+        ['link', nil, :text],
+        ['description', nil, :text],
+        ['image', '?', :have_child],
+        ['items', nil, :have_child],
+        ['textinput', '?', :have_child],
+      ].each do |tag, occurs, type|
+        __send__("install_#{type}_element", tag, ::RSS::URI, occurs)
+      end
+
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.about = args[0]
+        end
+      end
+
+      private
+      def maker_target(maker)
+        maker.channel
+      end
+      
+      def setup_maker_attributes(channel)
+        channel.about = about
+      end
+
+      class Image < Element
+        
+        include RSS10
+
+        class << self
+          
+          def required_uri
+            ::RSS::URI
+          end
+
+        end
+
+        [
+          ["resource", URI, true]
+        ].each do |name, uri, required|
+          install_get_attribute(name, uri, required, nil, nil,
+                                "#{PREFIX}:#{name}")
+        end
+      
+        def initialize(*args)
+          if Utils.element_initialize_arguments?(args)
+            super
+          else
+            super()
+            self.resource = args[0]
+          end
+        end
+      end
+
+      class Textinput < Element
+        
+        include RSS10
+
+        class << self
+          
+          def required_uri
+            ::RSS::URI
+          end
+
+        end
+
+        [
+          ["resource", URI, true]
+        ].each do |name, uri, required|
+          install_get_attribute(name, uri, required, nil, nil,
+                                "#{PREFIX}:#{name}")
+        end
+      
+        def initialize(*args)
+          if Utils.element_initialize_arguments?(args)
+            super
+          else
+            super()
+            self.resource = args[0]
+          end
+        end
+      end
+      
+      class Items < Element
+
+        include RSS10
+
+        Seq = ::RSS::RDF::Seq
+
+        class << self
+          
+          def required_uri
+            ::RSS::URI
+          end
+          
+        end
+
+        install_have_child_element("Seq", URI, nil)
+        install_must_call_validator('rdf', URI)
+        
+        def initialize(*args)
+          if Utils.element_initialize_arguments?(args)
+            super
+          else
+            super()
+            self.Seq = args[0]
+          end
+          self.Seq ||= Seq.new
+        end
+
+        def resources
+          if @Seq
+            @Seq.lis.collect do |li|
+              li.resource
+            end
+          else
+            []
+          end
+        end
+      end
+    end
+
+    class Image < Element
+
+      include RSS10
+
+      class << self
+        
+        def required_uri
+          ::RSS::URI
+        end
+
+      end
+
+      [
+        ["about", URI, true]
+      ].each do |name, uri, required|
+        install_get_attribute(name, uri, required, nil, nil,
+                              "#{PREFIX}:#{name}")
+      end
+
+      %w(title url link).each do |name|
+        install_text_element(name, ::RSS::URI, nil)
+      end
+
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.about = args[0]
+        end
+      end
+
+      private
+      def maker_target(maker)
+        maker.image
+      end
+    end
+
+    class Item < Element
+
+      include RSS10
+
+      class << self
+
+        def required_uri
+          ::RSS::URI
+        end
+        
+      end
+
+
+      [
+        ["about", URI, true]
+      ].each do |name, uri, required|
+        install_get_attribute(name, uri, required, nil, nil,
+                              "#{PREFIX}:#{name}")
+      end
+
+      [
+        ["title", nil],
+        ["link", nil],
+        ["description", "?"],
+      ].each do |tag, occurs|
+        install_text_element(tag, ::RSS::URI, occurs)
+      end
+
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.about = args[0]
+        end
+      end
+
+      private
+      def maker_target(items)
+        if items.respond_to?("items")
+          # For backward compatibility
+          items = items.items
+        end
+        items.new_item
+      end
+    end
+
+    class Textinput < Element
+
+      include RSS10
+
+      class << self
+
+        def required_uri
+          ::RSS::URI
+        end
+
+      end
+
+      [
+        ["about", URI, true]
+      ].each do |name, uri, required|
+        install_get_attribute(name, uri, required, nil, nil,
+                              "#{PREFIX}:#{name}")
+      end
+
+      %w(title description name link).each do |name|
+        install_text_element(name, ::RSS::URI, nil)
+      end
+
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.about = args[0]
+        end
+      end
+
+      private
+      def maker_target(maker)
+        maker.textinput
+      end
+    end
+
+  end
+
+  RSS10::ELEMENTS.each do |name|
+    BaseListener.install_get_text_element(URI, name, "#{name}=")
+  end
+
+  module ListenerMixin
+    private
+    def start_RDF(tag_name, prefix, attrs, ns)
+      check_ns(tag_name, prefix, ns, RDF::URI)
+
+      @rss = RDF.new(@version, @encoding, @standalone)
+      @rss.do_validate = @do_validate
+      @rss.xml_stylesheets = @xml_stylesheets
+      @last_element = @rss
+      @proc_stack.push Proc.new { |text, tags|
+        @rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate
+      }
+    end
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/2.0.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/2.0.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/2.0.rb	(revision 18425)
@@ -0,0 +1,111 @@
+require "rss/0.9"
+
+module RSS
+
+  class Rss
+
+    class Channel
+
+      [
+        ["generator"],
+        ["ttl", :integer],
+      ].each do |name, type|
+        install_text_element(name, "", "?", name, type)
+      end
+
+      [
+        %w(category categories),
+      ].each do |name, plural_name|
+        install_have_children_element(name, "", "*", name, plural_name)
+      end
+
+      [
+        ["image", "?"],
+        ["language", "?"],
+      ].each do |name, occurs|
+        install_model(name, "", occurs)
+      end
+
+      Category = Item::Category
+
+      class Item
+      
+        [
+          ["comments", "?"],
+          ["author", "?"],
+        ].each do |name, occurs|
+          install_text_element(name, "", occurs)
+        end
+
+        [
+          ["pubDate", '?'],
+        ].each do |name, occurs|
+          install_date_element(name, "", occurs, name, 'rfc822')
+        end
+        alias date pubDate
+        alias date= pubDate=
+
+        [
+          ["guid", '?'],
+        ].each do |name, occurs|
+          install_have_child_element(name, "", occurs)
+        end
+
+        private
+        alias _setup_maker_element setup_maker_element
+        def setup_maker_element(item)
+          _setup_maker_element(item)
+          @guid.setup_maker(item) if @guid
+        end
+        
+        class Guid < Element
+          
+          include RSS09
+
+          [
+            ["isPermaLink", "", false, :boolean]
+          ].each do |name, uri, required, type|
+            install_get_attribute(name, uri, required, type)
+          end
+
+          content_setup
+
+          def initialize(*args)
+            if Utils.element_initialize_arguments?(args)
+              super
+            else
+              super()
+              self.isPermaLink = args[0]
+              self.content = args[1]
+            end
+          end
+
+          alias_method :_PermaLink?, :PermaLink?
+          private :_PermaLink?
+          def PermaLink?
+            perma = _PermaLink?
+            perma or perma.nil?
+          end
+
+          private
+          def maker_target(item)
+            item.guid
+          end
+
+          def setup_maker_attributes(guid)
+            guid.isPermaLink = isPermaLink
+            guid.content = content
+          end
+        end
+
+      end
+
+    end
+
+  end
+
+  RSS09::ELEMENTS.each do |name|
+    BaseListener.install_get_text_element("", name, "#{name}=")
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/content.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/content.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/content.rb	(revision 18425)
@@ -0,0 +1,38 @@
+require "rss/1.0"
+
+module RSS
+
+  CONTENT_PREFIX = 'content'
+  CONTENT_URI = "http://purl.org/rss/1.0/modules/content/"
+
+  RDF.install_ns(CONTENT_PREFIX, CONTENT_URI)
+
+  module ContentModel
+
+    extend BaseModel
+
+    ELEMENTS = []
+
+    def self.append_features(klass)
+      super
+
+      klass.install_must_call_validator(CONTENT_PREFIX, CONTENT_URI)
+      %w(encoded).each do |name|
+        klass.install_text_element(name, CONTENT_URI, "?",
+                                   "#{CONTENT_PREFIX}_#{name}")
+      end
+    end
+  end
+
+  class RDF
+    class Item; include ContentModel; end
+  end
+
+  prefix_size = CONTENT_PREFIX.size + 1
+  ContentModel::ELEMENTS.uniq!
+  ContentModel::ELEMENTS.each do |full_name|
+    name = full_name[prefix_size..-1]
+    BaseListener.install_get_text_element(CONTENT_URI, name, "#{full_name}=")
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/converter.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/converter.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/converter.rb	(revision 18425)
@@ -0,0 +1,158 @@
+require "rss/utils"
+
+module RSS
+
+  class Converter
+    
+    include Utils
+
+    def initialize(to_enc, from_enc=nil)
+      normalized_to_enc = to_enc.downcase.gsub(/-/, '_')
+      from_enc ||= 'utf-8'
+      normalized_from_enc = from_enc.downcase.gsub(/-/, '_')
+      if normalized_to_enc == normalized_from_enc
+        def_same_enc()
+      else
+        def_diff_enc = "def_to_#{normalized_to_enc}_from_#{normalized_from_enc}"
+        if respond_to?(def_diff_enc)
+          __send__(def_diff_enc)
+        else
+          def_else_enc(to_enc, from_enc)
+        end
+      end
+    end
+
+    def convert(value)
+      value
+    end
+
+    def def_convert(depth=0)
+      instance_eval(<<-EOC, *get_file_and_line_from_caller(depth))
+      def convert(value)
+        if value.kind_of?(String)
+          #{yield('value')}
+        else
+          value
+        end
+      end
+      EOC
+    end
+
+    def def_iconv_convert(to_enc, from_enc, depth=0)
+      begin
+        require "iconv"
+        @iconv = Iconv.new(to_enc, from_enc)
+        def_convert(depth+1) do |value|
+          <<-EOC
+          begin
+            @iconv.iconv(#{value})
+          rescue Iconv::Failure
+            raise ConversionError.new(#{value}, "#{to_enc}", "#{from_enc}")
+          end
+          EOC
+        end
+      rescue LoadError, ArgumentError, SystemCallError
+        raise UnknownConversionMethodError.new(to_enc, from_enc)
+      end
+    end
+    
+    def def_else_enc(to_enc, from_enc)
+      def_iconv_convert(to_enc, from_enc, 0)
+    end
+    
+    def def_same_enc()
+      def_convert do |value|
+        value
+      end
+    end
+
+    def def_uconv_convert_if_can(meth, to_enc, from_enc, nkf_arg)
+      begin
+        require "uconv"
+        def_convert(1) do |value|
+          <<-EOC
+          begin
+            Uconv.#{meth}(#{value})
+          rescue Uconv::Error
+            raise ConversionError.new(#{value}, "#{to_enc}", "#{from_enc}")
+          end
+          EOC
+        end
+      rescue LoadError
+        require 'nkf'
+        def_convert(1) do |value|
+          "NKF.nkf(#{nkf_arg.dump}, #{value})"
+        end
+      end
+    end
+
+    def def_to_euc_jp_from_utf_8
+      def_uconv_convert_if_can('u8toeuc', 'EUC-JP', 'UTF-8', '-We')
+    end
+    
+    def def_to_utf_8_from_euc_jp
+      def_uconv_convert_if_can('euctou8', 'UTF-8', 'EUC-JP', '-Ew')
+    end
+    
+    def def_to_shift_jis_from_utf_8
+      def_uconv_convert_if_can('u8tosjis', 'Shift_JIS', 'UTF-8', '-Ws')
+    end
+    
+    def def_to_utf_8_from_shift_jis
+      def_uconv_convert_if_can('sjistou8', 'UTF-8', 'Shift_JIS', '-Sw')
+    end
+    
+    def def_to_euc_jp_from_shift_jis
+      require "nkf"
+      def_convert do |value|
+        "NKF.nkf('-Se', #{value})"
+      end
+    end
+    
+    def def_to_shift_jis_from_euc_jp
+      require "nkf"
+      def_convert do |value|
+        "NKF.nkf('-Es', #{value})"
+      end
+    end
+    
+    def def_to_euc_jp_from_iso_2022_jp
+      require "nkf"
+      def_convert do |value|
+        "NKF.nkf('-Je', #{value})"
+      end
+    end
+    
+    def def_to_iso_2022_jp_from_euc_jp
+      require "nkf"
+      def_convert do |value|
+        "NKF.nkf('-Ej', #{value})"
+      end
+    end
+
+    def def_to_utf_8_from_iso_8859_1
+      def_convert do |value|
+        "#{value}.unpack('C*').pack('U*')"
+      end
+    end
+    
+    def def_to_iso_8859_1_from_utf_8
+      def_convert do |value|
+        <<-EOC
+        array_utf8 = #{value}.unpack('U*')
+        array_enc = []
+        array_utf8.each do |num|
+          if num <= 0xFF
+            array_enc << num
+          else
+            array_enc.concat "&\#\#{num};".unpack('C*')
+          end
+        end
+        array_enc.pack('C*')
+        EOC
+      end
+    end
+    
+  end
+  
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/dublincore.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/dublincore.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/dublincore.rb	(revision 18425)
@@ -0,0 +1,154 @@
+require "rss/1.0"
+
+module RSS
+
+  DC_PREFIX = 'dc'
+  DC_URI = "http://purl.org/dc/elements/1.1/"
+  
+  RDF.install_ns(DC_PREFIX, DC_URI)
+
+  module BaseDublinCoreModel
+    def append_features(klass)
+      super
+
+      return if klass.instance_of?(Module)
+      DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
+        plural = plural_name || "#{name}s"
+        full_name = "#{DC_PREFIX}_#{name}"
+        full_plural_name = "#{DC_PREFIX}_#{plural}"
+        klass_name = "DublinCore#{Utils.to_class_name(name)}"
+        klass.install_must_call_validator(DC_PREFIX, DC_URI)
+        klass.install_have_children_element(name, DC_URI, "*",
+                                            full_name, full_plural_name)
+        klass.module_eval(<<-EOC, *get_file_and_line_from_caller(0))
+          remove_method :#{full_name}
+          remove_method :#{full_name}=
+          remove_method :set_#{full_name}
+
+          def #{full_name}
+            @#{full_name}.first and @#{full_name}.first.value
+          end
+          
+          def #{full_name}=(new_value)
+            @#{full_name}[0] = Utils.new_with_value_if_need(#{klass_name}, new_value)
+          end
+          alias set_#{full_name} #{full_name}=
+        EOC
+      end
+      klass.module_eval(<<-EOC, *get_file_and_line_from_caller(0))
+        alias date #{DC_PREFIX}_date
+        alias date= #{DC_PREFIX}_date=
+      EOC
+    end
+  end
+  
+  module DublinCoreModel
+
+    extend BaseModel
+    extend BaseDublinCoreModel
+
+    TEXT_ELEMENTS = {
+      "title" => nil,
+      "description" => nil,
+      "creator" => nil,
+      "subject" => nil,
+      "publisher" => nil,
+      "contributor" => nil,
+      "type" => nil,
+      "format" => nil,
+      "identifier" => nil,
+      "source" => nil,
+      "language" => nil,
+      "relation" => nil,
+      "coverage" => nil,
+      "rights" => "rightses" # FIXME
+    }
+
+    DATE_ELEMENTS = {
+      "date" => "w3cdtf",
+    }
+    
+    ELEMENT_NAME_INFOS = DublinCoreModel::TEXT_ELEMENTS.to_a
+    DublinCoreModel::DATE_ELEMENTS.each do |name, |
+      ELEMENT_NAME_INFOS << [name, nil]
+    end
+    
+    ELEMENTS = TEXT_ELEMENTS.keys + DATE_ELEMENTS.keys
+
+    ELEMENTS.each do |name, plural_name|
+      module_eval(<<-EOC, *get_file_and_line_from_caller(0))
+        class DublinCore#{Utils.to_class_name(name)} < Element
+          include RSS10
+          
+          content_setup
+
+          class << self
+            def required_prefix
+              DC_PREFIX
+            end
+        
+            def required_uri
+              DC_URI
+            end
+          end
+
+          @tag_name = #{name.dump}
+
+          alias_method(:value, :content)
+          alias_method(:value=, :content=)
+          
+          def initialize(*args)
+            if Utils.element_initialize_arguments?(args)
+              super
+            else
+              super()
+              self.content = args[0]
+            end
+          end
+      
+          def full_name
+            tag_name_with_prefix(DC_PREFIX)
+          end
+
+          def maker_target(target)
+            target.new_#{name}
+          end
+
+          def setup_maker_attributes(#{name})
+            #{name}.content = content
+          end
+        end
+      EOC
+    end
+
+    DATE_ELEMENTS.each do |name, type|
+      module_eval(<<-EOC, *get_file_and_line_from_caller(0))
+        class DublinCore#{Utils.to_class_name(name)} < Element
+          remove_method(:content=)
+          remove_method(:value=)
+
+          date_writer("content", #{type.dump}, #{name.dump})
+          
+          alias_method(:value=, :content=)
+        end
+      EOC
+    end
+  end
+
+  # For backward compatibility
+  DublincoreModel = DublinCoreModel
+
+  class RDF
+    class Channel; include DublinCoreModel; end
+    class Image; include DublinCoreModel; end
+    class Item; include DublinCoreModel; end
+    class Textinput; include DublinCoreModel; end
+  end
+
+  DublinCoreModel::ELEMENTS.each do |name|
+    class_name = Utils.to_class_name(name)
+    BaseListener.install_class_name(DC_URI, name, "DublinCore#{class_name}")
+  end
+
+  DublinCoreModel::ELEMENTS.collect! {|name| "#{DC_PREFIX}_#{name}"}
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/image.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/image.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/image.rb	(revision 18425)
@@ -0,0 +1,193 @@
+require 'rss/1.0'
+require 'rss/dublincore'
+
+module RSS
+
+  IMAGE_PREFIX = 'image'
+  IMAGE_URI = 'http://web.resource.org/rss/1.0/modules/image/'
+
+  RDF.install_ns(IMAGE_PREFIX, IMAGE_URI)
+
+  IMAGE_ELEMENTS = []
+
+  %w(item favicon).each do |name|
+    class_name = Utils.to_class_name(name)
+    BaseListener.install_class_name(IMAGE_URI, name, "Image#{class_name}")
+    IMAGE_ELEMENTS << "#{IMAGE_PREFIX}_#{name}"
+  end
+  
+  module ImageModelUtils
+    def validate_one_tag_name(ignore_unknown_element, name, tags)
+      if !ignore_unknown_element
+        invalid = tags.find {|tag| tag != name}
+        raise UnknownTagError.new(invalid, IMAGE_URI) if invalid
+      end
+      raise TooMuchTagError.new(name, tag_name) if tags.size > 1
+    end
+  end
+  
+  module ImageItemModel
+    include ImageModelUtils
+    extend BaseModel
+
+    def self.append_features(klass)
+      super
+
+      klass.install_have_child_element("item", IMAGE_URI, "?",
+                                       "#{IMAGE_PREFIX}_item")
+      klass.install_must_call_validator(IMAGE_PREFIX, IMAGE_URI)
+    end
+
+    class ImageItem < Element
+      include RSS10
+      include DublinCoreModel
+
+      @tag_name = "item"
+      
+      class << self
+        def required_prefix
+          IMAGE_PREFIX
+        end
+        
+        def required_uri
+          IMAGE_URI
+        end
+      end
+
+      install_must_call_validator(IMAGE_PREFIX, IMAGE_URI)
+
+      [
+        ["about", ::RSS::RDF::URI, true],
+        ["resource", ::RSS::RDF::URI, false],
+      ].each do |name, uri, required|
+        install_get_attribute(name, uri, required, nil, nil,
+                              "#{::RSS::RDF::PREFIX}:#{name}")
+      end
+
+      %w(width height).each do |tag|
+        full_name = "#{IMAGE_PREFIX}_#{tag}"
+        disp_name = "#{IMAGE_PREFIX}:#{tag}"
+        install_text_element(tag, IMAGE_URI, "?",
+                             full_name, :integer, disp_name)
+        BaseListener.install_get_text_element(IMAGE_URI, tag, "#{full_name}=")
+      end
+
+      alias width= image_width=
+      alias width image_width
+      alias height= image_height=
+      alias height image_height
+
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.about = args[0]
+          self.resource = args[1]
+        end
+      end
+
+      def full_name
+        tag_name_with_prefix(IMAGE_PREFIX)
+      end
+
+      private
+      def maker_target(target)
+        target.image_item
+      end
+
+      def setup_maker_attributes(item)
+        item.about = self.about
+        item.resource = self.resource
+      end
+    end
+  end
+  
+  module ImageFaviconModel
+    include ImageModelUtils
+    extend BaseModel
+    
+    def self.append_features(klass)
+      super
+
+      unless klass.class == Module
+        klass.install_have_child_element("favicon", IMAGE_URI, "?",
+                                         "#{IMAGE_PREFIX}_favicon")
+        klass.install_must_call_validator(IMAGE_PREFIX, IMAGE_URI)
+      end
+    end
+
+    class ImageFavicon < Element
+      include RSS10
+      include DublinCoreModel
+
+      @tag_name = "favicon"
+      
+      class << self
+        def required_prefix
+          IMAGE_PREFIX
+        end
+        
+        def required_uri
+          IMAGE_URI
+        end
+      end
+
+      [
+        ["about", ::RSS::RDF::URI, true, ::RSS::RDF::PREFIX],
+        ["size", IMAGE_URI, true, IMAGE_PREFIX],
+      ].each do |name, uri, required, prefix|
+        install_get_attribute(name, uri, required, nil, nil,
+                              "#{prefix}:#{name}")
+      end
+
+      AVAILABLE_SIZES = %w(small medium large)
+      alias_method :_size=, :size=
+      private :_size=
+      def size=(new_value)
+        if @do_validate and !new_value.nil?
+          new_value = new_value.strip
+          unless AVAILABLE_SIZES.include?(new_value)
+            attr_name = "#{IMAGE_PREFIX}:size"
+            raise NotAvailableValueError.new(full_name, new_value, attr_name)
+          end
+        end
+        __send__(:_size=, new_value)
+      end
+      
+      alias image_size= size=
+      alias image_size size
+
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.about = args[0]
+          self.size = args[1]
+        end
+      end
+
+      def full_name
+        tag_name_with_prefix(IMAGE_PREFIX)
+      end
+
+      private
+      def maker_target(target)
+        target.image_favicon
+      end
+
+      def setup_maker_attributes(favicon)
+        favicon.about = self.about
+        favicon.size = self.size
+      end
+    end
+
+  end
+
+  class RDF
+    class Channel; include ImageFaviconModel; end
+    class Item; include ImageItemModel; end
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker.rb	(revision 18425)
@@ -0,0 +1,37 @@
+require "rss/rss"
+
+module RSS
+
+  module Maker
+
+    MAKERS = {}
+    
+    class << self
+      def make(version, &block)
+        maker(version).make(&block)
+      end
+
+      def maker(version)
+        MAKERS[version]
+      end
+
+      def add_maker(version, maker)
+        MAKERS[version] = maker
+      end
+
+      def filename_to_version(filename)
+        File.basename(filename, ".*")
+      end
+    end
+  end
+  
+end
+
+require "rss/maker/1.0"
+require "rss/maker/2.0"
+require "rss/maker/content"
+require "rss/maker/dublincore"
+require "rss/maker/syndication"
+require "rss/maker/taxonomy"
+require "rss/maker/trackback"
+require "rss/maker/image"
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/0.9.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/0.9.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/0.9.rb	(revision 18425)
@@ -0,0 +1,224 @@
+require "rss/0.9"
+
+require "rss/maker/base"
+
+module RSS
+  module Maker
+    
+    class RSS09 < RSSBase
+      
+      def initialize(rss_version="0.91")
+        super
+      end
+      
+      private
+      def make_rss
+        Rss.new(@rss_version, @version, @encoding, @standalone)
+      end
+
+      def setup_elements(rss)
+        setup_channel(rss)
+      end
+
+      class Channel < ChannelBase
+        
+        def to_rss(rss)
+          channel = Rss::Channel.new
+          set = setup_values(channel)
+          if set
+            rss.channel = channel
+            setup_items(rss)
+            setup_image(rss)
+            setup_textinput(rss)
+            setup_other_elements(rss)
+            if rss.channel.image
+              rss
+            else
+              nil
+            end
+          elsif variable_is_set?
+            raise NotSetError.new("maker.channel", not_set_required_variables)
+          end
+        end
+        
+        def have_required_values?
+          @title and @link and @description and @language
+        end
+        
+        private
+        def setup_items(rss)
+          @maker.items.to_rss(rss)
+        end
+        
+        def setup_image(rss)
+          @maker.image.to_rss(rss)
+        end
+        
+        def setup_textinput(rss)
+          @maker.textinput.to_rss(rss)
+        end
+        
+        def variables
+          super + ["pubDate"]
+        end
+
+        def required_variable_names
+          %w(title link description language)
+        end
+        
+        class SkipDays < SkipDaysBase
+          def to_rss(rss, channel)
+            unless @days.empty?
+              skipDays = Rss::Channel::SkipDays.new
+              channel.skipDays = skipDays
+              @days.each do |day|
+                day.to_rss(rss, skipDays.days)
+              end
+            end
+          end
+          
+          class Day < DayBase
+            def to_rss(rss, days)
+              day = Rss::Channel::SkipDays::Day.new
+              set = setup_values(day)
+              if set
+                days << day
+                setup_other_elements(rss)
+              end
+            end
+
+            def have_required_values?
+              @content
+            end
+          end
+        end
+        
+        class SkipHours < SkipHoursBase
+          def to_rss(rss, channel)
+            unless @hours.empty?
+              skipHours = Rss::Channel::SkipHours.new
+              channel.skipHours = skipHours
+              @hours.each do |hour|
+                hour.to_rss(rss, skipHours.hours)
+              end
+            end
+          end
+          
+          class Hour < HourBase
+            def to_rss(rss, hours)
+              hour = Rss::Channel::SkipHours::Hour.new
+              set = setup_values(hour)
+              if set
+                hours << hour
+                setup_other_elements(rss)
+              end
+            end
+
+            def have_required_values?
+              @content
+            end
+          end
+        end
+        
+        class Cloud < CloudBase
+          def to_rss(*args)
+          end
+        end
+
+        class Categories < CategoriesBase
+          def to_rss(*args)
+          end
+
+          class Category < CategoryBase
+          end
+        end
+      end
+      
+      class Image < ImageBase
+        def to_rss(rss)
+          image = Rss::Channel::Image.new
+          set = setup_values(image)
+          if set
+            image.link = link
+            rss.channel.image = image
+            setup_other_elements(rss)
+          end
+        end
+        
+        def have_required_values?
+          @url and @title and link
+        end
+      end
+      
+      class Items < ItemsBase
+        def to_rss(rss)
+          if rss.channel
+            normalize.each do |item|
+              item.to_rss(rss)
+            end
+            setup_other_elements(rss)
+          end
+        end
+        
+        class Item < ItemBase
+          def to_rss(rss)
+            item = Rss::Channel::Item.new
+            set = setup_values(item)
+            if set
+              rss.items << item
+              setup_other_elements(rss)
+            end
+          end
+          
+          private
+          def have_required_values?
+            @title and @link
+          end
+
+          class Guid < GuidBase
+            def to_rss(*args)
+            end
+          end
+        
+          class Enclosure < EnclosureBase
+            def to_rss(*args)
+            end
+          end
+        
+          class Source < SourceBase
+            def to_rss(*args)
+            end
+          end
+        
+          class Categories < CategoriesBase
+            def to_rss(*args)
+            end
+
+            class Category < CategoryBase
+            end
+          end
+          
+        end
+      end
+      
+      class Textinput < TextinputBase
+        def to_rss(rss)
+          textInput = Rss::Channel::TextInput.new
+          set = setup_values(textInput)
+          if set
+            rss.channel.textInput = textInput
+            setup_other_elements(rss)
+          end
+        end
+
+        private
+        def have_required_values?
+          @title and @description and @name and @link
+        end
+      end
+    end
+    
+    add_maker(filename_to_version(__FILE__), RSS09)
+    add_maker(filename_to_version(__FILE__) + "1", RSS09)
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/1.0.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/1.0.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/1.0.rb	(revision 18425)
@@ -0,0 +1,204 @@
+require "rss/1.0"
+
+require "rss/maker/base"
+
+module RSS
+  module Maker
+
+    class RSS10 < RSSBase
+
+      def initialize
+        super("1.0")
+      end
+
+      private
+      def make_rss
+        RDF.new(@version, @encoding, @standalone)
+      end
+
+      def setup_elements(rss)
+        setup_channel(rss)
+        setup_image(rss)
+        setup_items(rss)
+        setup_textinput(rss)
+      end
+
+      class Channel < ChannelBase
+
+        def to_rss(rss)
+          set = false
+          if @about
+            channel = RDF::Channel.new(@about)
+            set = setup_values(channel)
+            if set
+              channel.dc_dates.clear
+              rss.channel = channel
+              setup_items(rss)
+              setup_image(rss)
+              setup_textinput(rss)
+              setup_other_elements(rss)
+            end
+          end
+
+          if (!@about or !set) and variable_is_set?
+            raise NotSetError.new("maker.channel", not_set_required_variables)
+          end
+        end
+
+        def have_required_values?
+          @about and @title and @link and @description
+        end
+
+        private
+        def setup_items(rss)
+          items = RDF::Channel::Items.new
+          seq = items.Seq
+          @maker.items.normalize.each do |item|
+            seq.lis << RDF::Channel::Items::Seq::Li.new(item.link)
+          end
+          rss.channel.items = items
+        end
+        
+        def setup_image(rss)
+          if @maker.image.have_required_values?
+            rss.channel.image = RDF::Channel::Image.new(@maker.image.url)
+          end
+        end
+
+        def setup_textinput(rss)
+          if @maker.textinput.have_required_values?
+            textinput = RDF::Channel::Textinput.new(@maker.textinput.link)
+            rss.channel.textinput = textinput
+          end
+        end
+
+        def required_variable_names
+          %w(about title link description)
+        end
+        
+        class SkipDays < SkipDaysBase
+          def to_rss(*args)
+          end
+          
+          class Day < DayBase
+          end
+        end
+        
+        class SkipHours < SkipHoursBase
+          def to_rss(*args)
+          end
+
+          class Hour < HourBase
+          end
+        end
+        
+        class Cloud < CloudBase
+          def to_rss(*args)
+          end
+        end
+
+        class Categories < CategoriesBase
+          def to_rss(*args)
+          end
+
+          class Category < CategoryBase
+          end
+        end
+      end
+
+      class Image < ImageBase
+        def to_rss(rss)
+          if @url
+            image = RDF::Image.new(@url)
+            set = setup_values(image)
+            if set
+              rss.image = image
+              setup_other_elements(rss)
+            end
+          end
+        end
+
+        def have_required_values?
+          @url and @title and link and @maker.channel.have_required_values?
+        end
+
+        private
+        def variables
+          super + ["link"]
+        end
+      end
+
+      class Items < ItemsBase
+        def to_rss(rss)
+          if rss.channel
+            normalize.each do |item|
+              item.to_rss(rss)
+            end
+            setup_other_elements(rss)
+          end
+        end
+
+        class Item < ItemBase
+          def to_rss(rss)
+            if @link
+              item = RDF::Item.new(@link)
+              set = setup_values(item)
+              if set
+                item.dc_dates.clear
+                rss.items << item
+                setup_other_elements(rss)
+              end
+            end
+          end
+
+          def have_required_values?
+            @title and @link
+          end
+
+          class Guid < GuidBase
+            def to_rss(*args)
+            end
+          end
+        
+          class Enclosure < EnclosureBase
+            def to_rss(*args)
+            end
+          end
+        
+          class Source < SourceBase
+            def to_rss(*args)
+            end
+          end
+        
+          class Categories < CategoriesBase
+            def to_rss(*args)
+            end
+
+            class Category < CategoryBase
+            end
+          end
+        end
+      end
+      
+      class Textinput < TextinputBase
+        def to_rss(rss)
+          if @link
+            textinput = RDF::Textinput.new(@link)
+            set = setup_values(textinput)
+            if set
+              rss.textinput = textinput
+              setup_other_elements(rss)
+            end
+          end
+        end
+
+        def have_required_values?
+          @title and @description and @name and @link and
+            @maker.channel.have_required_values?
+        end
+      end
+    end
+
+    add_maker(filename_to_version(__FILE__), RSS10)
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/2.0.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/2.0.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/2.0.rb	(revision 18425)
@@ -0,0 +1,168 @@
+require "rss/2.0"
+
+require "rss/maker/0.9"
+
+module RSS
+  module Maker
+    
+    class RSS20 < RSS09
+      
+      def initialize(rss_version="2.0")
+        super
+      end
+
+      class Channel < RSS09::Channel
+
+        def have_required_values?
+          @title and @link and @description
+        end
+
+        def required_variable_names
+          %w(title link description)
+        end
+        
+        class SkipDays < RSS09::Channel::SkipDays
+          class Day < RSS09::Channel::SkipDays::Day
+          end
+        end
+        
+        class SkipHours < RSS09::Channel::SkipHours
+          class Hour < RSS09::Channel::SkipHours::Hour
+          end
+        end
+        
+        class Cloud < RSS09::Channel::Cloud
+          def to_rss(rss, channel)
+            cloud = Rss::Channel::Cloud.new
+            set = setup_values(cloud)
+            if set
+              channel.cloud = cloud
+              setup_other_elements(rss)
+            end
+          end
+
+          def have_required_values?
+            @domain and @port and @path and
+              @registerProcedure and @protocol
+          end
+        end
+
+        class Categories < RSS09::Channel::Categories
+          def to_rss(rss, channel)
+            @categories.each do |category|
+              category.to_rss(rss, channel)
+            end
+          end
+          
+          class Category < RSS09::Channel::Categories::Category
+            def to_rss(rss, channel)
+              category = Rss::Channel::Category.new
+              set = setup_values(category)
+              if set
+                channel.categories << category
+                setup_other_elements(rss)
+              end
+            end
+            
+            def have_required_values?
+              @content
+            end
+          end
+        end
+        
+      end
+      
+      class Image < RSS09::Image
+      end
+      
+      class Items < RSS09::Items
+        
+        class Item < RSS09::Items::Item
+
+          def have_required_values?
+            @title or @description
+          end
+
+          private
+          def variables
+            super + ["pubDate"]
+          end
+
+          class Guid < RSS09::Items::Item::Guid
+            def to_rss(rss, item)
+              guid = Rss::Channel::Item::Guid.new
+              set = setup_values(guid)
+              if set
+                item.guid = guid
+                setup_other_elements(rss)
+              end
+            end
+            
+            def have_required_values?
+              @content
+            end
+          end
+
+          class Enclosure < RSS09::Items::Item::Enclosure
+            def to_rss(rss, item)
+              enclosure = Rss::Channel::Item::Enclosure.new
+              set = setup_values(enclosure)
+              if set
+                item.enclosure = enclosure
+                setup_other_elements(rss)
+              end
+            end
+            
+            def have_required_values?
+              @url and @length and @type
+            end
+          end
+
+          class Source < RSS09::Items::Item::Source
+            def to_rss(rss, item)
+              source = Rss::Channel::Item::Source.new
+              set = setup_values(source)
+              if set
+                item.source = source
+                setup_other_elements(rss)
+              end
+            end
+            
+            def have_required_values?
+              @url and @content
+            end
+          end
+
+          class Categories < RSS09::Items::Item::Categories
+            def to_rss(rss, item)
+              @categories.each do |category|
+                category.to_rss(rss, item)
+              end
+            end
+          
+            class Category < RSS09::Items::Item::Categories::Category
+              def to_rss(rss, item)
+                category = Rss::Channel::Item::Category.new
+                set = setup_values(category)
+                if set
+                  item.categories << category
+                  setup_other_elements(rss)
+                end
+              end
+              
+              def have_required_values?
+                @content
+              end
+            end
+          end
+        end
+        
+      end
+      
+      class Textinput < RSS09::Textinput
+      end
+    end
+    
+    add_maker(filename_to_version(__FILE__), RSS20)
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/base.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/base.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/base.rb	(revision 18425)
@@ -0,0 +1,546 @@
+require 'forwardable'
+
+require 'rss/rss'
+
+module RSS
+  module Maker
+
+    module Base
+
+      def self.append_features(klass)
+        super
+
+        klass.module_eval(<<-EOC, __FILE__, __LINE__)
+
+        OTHER_ELEMENTS = []
+        NEED_INITIALIZE_VARIABLES = []
+
+        def self.inherited(subclass)
+          subclass.const_set("OTHER_ELEMENTS", [])
+          subclass.const_set("NEED_INITIALIZE_VARIABLES", [])
+
+          subclass.module_eval(<<-EOEOC, __FILE__, __LINE__)
+            def self.other_elements
+              OTHER_ELEMENTS + super
+            end
+
+            def self.need_initialize_variables
+              NEED_INITIALIZE_VARIABLES + super
+            end
+          EOEOC
+        end
+
+        def self.add_other_element(variable_name)
+          OTHER_ELEMENTS << variable_name
+        end
+
+        def self.other_elements
+          OTHER_ELEMENTS
+        end
+
+        def self.add_need_initialize_variable(variable_name, init_value="nil")
+          NEED_INITIALIZE_VARIABLES << [variable_name, init_value]
+        end
+
+        def self.need_initialize_variables
+          NEED_INITIALIZE_VARIABLES
+        end
+
+        def self.def_array_element(name)
+          include Enumerable
+          extend Forwardable
+
+          def_delegators("@\#{name}", :<<, :[], :[]=, :first, :last)
+          def_delegators("@\#{name}", :push, :pop, :shift, :unshift)
+          def_delegators("@\#{name}", :each, :size)
+          
+          add_need_initialize_variable(name, "[]")
+        end
+        EOC
+      end
+      
+      def initialize(maker)
+        @maker = maker
+        initialize_variables
+      end
+
+      def have_required_values?
+        true
+      end
+      
+      private
+      def initialize_variables
+        self.class.need_initialize_variables.each do |variable_name, init_value|
+          instance_eval("@#{variable_name} = #{init_value}", __FILE__, __LINE__)
+        end
+      end
+
+      def setup_other_elements(rss)
+        self.class.other_elements.each do |element|
+          __send__("setup_#{element}", rss, current_element(rss))
+        end
+      end
+
+      def current_element(rss)
+        rss
+      end
+      
+      def setup_values(target)
+        set = false
+        if have_required_values?
+          variables.each do |var|
+            setter = "#{var}="
+            if target.respond_to?(setter)
+              value = __send__(var)
+              if value
+                target.__send__(setter, value)
+                set = true
+              end
+            end
+          end
+        end
+        set
+      end
+
+      def variables
+        self.class.need_initialize_variables.find_all do |name, init|
+          "nil" == init
+        end.collect do |name, init|
+          name
+        end
+      end
+
+      def variable_is_set?
+        variables.find {|var| !__send__(var).nil?}
+      end
+
+      def not_set_required_variables
+        required_variable_names.find_all do |var|
+          __send__(var).nil?
+        end
+      end
+
+      def required_variables_are_set?
+        required_variable_names.each do |var|
+          return false if __send__(var).nil?
+        end
+        true
+      end
+      
+    end
+
+    class RSSBase
+      include Base
+
+      class << self
+        def make(&block)
+          new.make(&block)
+        end
+      end
+
+      %w(xml_stylesheets channel image items textinput).each do |element|
+        attr_reader element
+        add_need_initialize_variable(element, "make_#{element}")
+        module_eval(<<-EOC, __FILE__, __LINE__)
+          private
+          def setup_#{element}(rss)
+            @#{element}.to_rss(rss)
+          end
+
+          def make_#{element}
+            self.class::#{Utils.to_class_name(element)}.new(self)
+          end
+EOC
+      end
+      
+      attr_reader :rss_version
+      attr_accessor :version, :encoding, :standalone
+      
+      def initialize(rss_version)
+        super(self)
+        @rss_version = rss_version
+        @version = "1.0"
+        @encoding = "UTF-8"
+        @standalone = nil
+      end
+      
+      def make
+        if block_given?
+          yield(self)
+          to_rss
+        else
+          nil
+        end
+      end
+
+      def to_rss
+        rss = make_rss
+        setup_xml_stylesheets(rss)
+        setup_elements(rss)
+        setup_other_elements(rss)
+        if rss.channel
+          rss
+        else
+          nil
+        end
+      end
+      
+      private
+      remove_method :make_xml_stylesheets
+      def make_xml_stylesheets
+        XMLStyleSheets.new(self)
+      end
+      
+    end
+
+    class XMLStyleSheets
+      include Base
+
+      def_array_element("xml_stylesheets")
+
+      def to_rss(rss)
+        @xml_stylesheets.each do |xss|
+          xss.to_rss(rss)
+        end
+      end
+
+      def new_xml_stylesheet
+        xss = XMLStyleSheet.new(@maker)
+        @xml_stylesheets << xss
+        if block_given?
+          yield xss
+        else
+          xss
+        end
+      end
+
+      class XMLStyleSheet
+        include Base
+
+        ::RSS::XMLStyleSheet::ATTRIBUTES.each do |attribute|
+          attr_accessor attribute
+          add_need_initialize_variable(attribute)
+        end
+        
+        def to_rss(rss)
+          xss = ::RSS::XMLStyleSheet.new
+          guess_type_if_need(xss)
+          set = setup_values(xss)
+          if set
+            rss.xml_stylesheets << xss
+          end
+        end
+
+        def have_required_values?
+          @href and @type
+        end
+
+        private
+        def guess_type_if_need(xss)
+          if @type.nil?
+            xss.href = @href
+            @type = xss.type
+          end
+        end
+      end
+    end
+    
+    class ChannelBase
+      include Base
+
+      %w(cloud categories skipDays skipHours).each do |element|
+        attr_reader element
+        add_other_element(element)
+        add_need_initialize_variable(element, "make_#{element}")
+        module_eval(<<-EOC, __FILE__, __LINE__)
+          private
+          def setup_#{element}(rss, current)
+            @#{element}.to_rss(rss, current)
+          end
+
+          def make_#{element}
+            self.class::#{Utils.to_class_name(element)}.new(@maker)
+          end
+EOC
+      end
+
+      %w(about title link description language copyright
+         managingEditor webMaster rating docs date
+         lastBuildDate generator ttl).each do |element|
+        attr_accessor element
+        add_need_initialize_variable(element)
+      end
+
+      alias_method(:pubDate, :date)
+      alias_method(:pubDate=, :date=)
+
+      def current_element(rss)
+        rss.channel
+      end
+
+      class SkipDaysBase
+        include Base
+
+        def_array_element("days")
+
+        def new_day
+          day = self.class::Day.new(@maker)
+          @days << day
+          if block_given?
+            yield day
+          else
+            day
+          end
+        end
+        
+        def current_element(rss)
+          rss.channel.skipDays
+        end
+
+        class DayBase
+          include Base
+          
+          %w(content).each do |element|
+            attr_accessor element
+            add_need_initialize_variable(element)
+          end
+
+          def current_element(rss)
+            rss.channel.skipDays.last
+          end
+
+        end
+      end
+      
+      class SkipHoursBase
+        include Base
+
+        def_array_element("hours")
+
+        def new_hour
+          hour = self.class::Hour.new(@maker)
+          @hours << hour
+          if block_given?
+            yield hour
+          else
+            hour
+          end
+        end
+        
+        def current_element(rss)
+          rss.channel.skipHours
+        end
+
+        class HourBase
+          include Base
+          
+          %w(content).each do |element|
+            attr_accessor element
+            add_need_initialize_variable(element)
+          end
+
+          def current_element(rss)
+            rss.channel.skipHours.last
+          end
+
+        end
+      end
+      
+      class CloudBase
+        include Base
+        
+        %w(domain port path registerProcedure protocol).each do |element|
+          attr_accessor element
+          add_need_initialize_variable(element)
+        end
+        
+        def current_element(rss)
+          rss.channel.cloud
+        end
+
+      end
+
+      class CategoriesBase
+        include Base
+        
+        def_array_element("categories")
+
+        def new_category
+          category = self.class::Category.new(@maker)
+          @categories << category
+          if block_given?
+            yield category
+          else
+            category
+          end
+        end
+
+        class CategoryBase
+          include Base
+
+          %w(domain content).each do |element|
+            attr_accessor element
+            add_need_initialize_variable(element)
+          end
+        end
+      end
+    end
+    
+    class ImageBase
+      include Base
+
+      %w(title url width height description).each do |element|
+        attr_accessor element
+        add_need_initialize_variable(element)
+      end
+      
+      def link
+        @maker.channel.link
+      end
+
+      def current_element(rss)
+        rss.image
+      end
+    end
+    
+    class ItemsBase
+      include Base
+
+      def_array_element("items")
+      
+      attr_accessor :do_sort, :max_size
+      
+      def initialize(maker)
+        super
+        @do_sort = false
+        @max_size = -1
+      end
+      
+      def normalize
+        if @max_size >= 0
+          sort_if_need[0...@max_size]
+        else
+          sort_if_need[0..@max_size]
+        end
+      end
+      
+      def current_element(rss)
+        rss.items
+      end
+
+      def new_item
+        item = self.class::Item.new(@maker)
+        @items << item
+        if block_given?
+          yield item
+        else
+          item
+        end
+      end
+      
+      private
+      def sort_if_need
+        if @do_sort.respond_to?(:call)
+          @items.sort do |x, y|
+            @do_sort.call(x, y)
+          end
+        elsif @do_sort
+          @items.sort do |x, y|
+            y <=> x
+          end
+        else
+          @items
+        end
+      end
+
+      class ItemBase
+        include Base
+        
+        %w(guid enclosure source categories).each do |element|
+          attr_reader element
+          add_other_element(element)
+          add_need_initialize_variable(element, "make_#{element}")
+          module_eval(<<-EOC, __FILE__, __LINE__)
+          private
+          def setup_#{element}(rss, current)
+            @#{element}.to_rss(rss, current)
+          end
+
+          def make_#{element}
+            self.class::#{Utils.to_class_name(element)}.new(@maker)
+          end
+EOC
+        end
+      
+        %w(title link description date author comments).each do |element|
+          attr_accessor element
+          add_need_initialize_variable(element)
+        end
+
+        alias_method(:pubDate, :date)
+        alias_method(:pubDate=, :date=)
+
+        def <=>(other)
+          if date and other.date
+            date <=> other.date
+          elsif date
+            1
+          elsif other.date
+            -1
+          else
+            0
+          end
+        end
+      
+        def current_element(rss)
+          rss.items.last
+        end
+
+        class GuidBase
+          include Base
+
+          %w(isPermaLink content).each do |element|
+            attr_accessor element
+            add_need_initialize_variable(element)
+          end
+        end
+      
+        class EnclosureBase
+          include Base
+
+          %w(url length type).each do |element|
+            attr_accessor element
+            add_need_initialize_variable(element)
+          end
+        end
+      
+        class SourceBase
+          include Base
+
+          %w(url content).each do |element|
+            attr_accessor element
+            add_need_initialize_variable(element)
+          end
+        end
+      
+        CategoriesBase = ChannelBase::CategoriesBase
+      
+      end
+    end
+
+    class TextinputBase
+      include Base
+
+      %w(title description name link).each do |element|
+        attr_accessor element
+        add_need_initialize_variable(element)
+      end
+      
+      def current_element(rss)
+        rss.textinput
+      end
+
+    end
+    
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/content.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/content.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/content.rb	(revision 18425)
@@ -0,0 +1,29 @@
+require 'rss/content'
+require 'rss/maker/1.0'
+
+module RSS
+  module Maker
+    module ContentModel
+      def self.append_features(klass)
+        super
+
+        ::RSS::ContentModel::ELEMENTS.each do |element|
+          klass.add_need_initialize_variable(element)
+          klass.add_other_element(element)
+          klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
+            attr_accessor :#{element}
+            def setup_#{element}(rss, current)
+              if #{element} and current.respond_to?(:#{element}=)
+                current.#{element} = @#{element} if @#{element}
+              end
+            end
+          EOC
+        end
+      end
+    end
+
+    class ItemsBase
+      class ItemBase; include ContentModel; end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/dublincore.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/dublincore.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/dublincore.rb	(revision 18425)
@@ -0,0 +1,169 @@
+require 'rss/dublincore'
+require 'rss/maker/1.0'
+
+module RSS
+  module Maker
+    module DublinCoreModel
+      def self.append_features(klass)
+        super
+
+        ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
+          plural_name ||= "#{name}s"
+          full_name = "#{RSS::DC_PREFIX}_#{name}"
+          full_plural_name = "#{RSS::DC_PREFIX}_#{plural_name}"
+          klass_name = Utils.to_class_name(name)
+          plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
+          full_plural_klass_name = "self.class::#{plural_klass_name}"
+          full_klass_name = "#{full_plural_klass_name}::#{klass_name}"
+          klass.add_need_initialize_variable(full_plural_name,
+                                             "make_#{full_plural_name}")
+          klass.add_other_element(full_plural_name)
+          klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
+            attr_accessor :#{full_plural_name}
+            def make_#{full_plural_name}
+              #{full_plural_klass_name}.new(@maker)
+            end
+            
+            def setup_#{full_plural_name}(rss, current)
+              @#{full_plural_name}.to_rss(rss, current)
+            end
+
+            def #{full_name}
+              @#{full_plural_name}[0] and @#{full_plural_name}[0].value
+            end
+            
+            def #{full_name}=(new_value)
+              @#{full_plural_name}[0] = #{full_klass_name}.new(self)
+              @#{full_plural_name}[0].value = new_value
+            end
+EOC
+        end
+      end
+
+      ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
+        plural_name ||= "#{name}s"
+        klass_name = Utils.to_class_name(name)
+        plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
+        module_eval(<<-EOC, __FILE__, __LINE__)
+        class #{plural_klass_name}Base
+          include Base
+
+          def_array_element(#{plural_name.dump})
+                            
+          def new_#{name}
+            #{name} = self.class::#{klass_name}.new(self)
+            @#{plural_name} << #{name}
+            if block_given?
+              yield #{name}
+            else
+              #{name}
+            end
+          end
+
+          def to_rss(rss, current)
+            @#{plural_name}.each do |#{name}|
+              #{name}.to_rss(rss, current)
+            end
+          end
+        
+          class #{klass_name}Base
+            include Base
+
+            attr_accessor :value
+            add_need_initialize_variable("value")
+            alias_method(:content, :value)
+            alias_method(:content=, :value=)
+
+            def have_required_values?
+              @value
+            end
+          end
+        end
+        EOC
+      end
+
+      def self.install_dublin_core(klass)
+        ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
+          plural_name ||= "#{name}s"
+          klass_name = Utils.to_class_name(name)
+          plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
+          full_klass_name = "DublinCore#{klass_name}"
+          klass.module_eval(<<-EOC, *Utils.get_file_and_line_from_caller(1))
+          class #{plural_klass_name} < #{plural_klass_name}Base
+            class #{klass_name} < #{klass_name}Base
+              def to_rss(rss, current)
+                if value and current.respond_to?(:dc_#{name})
+                  new_item = current.class::#{full_klass_name}.new(value)
+                  current.dc_#{plural_name} << new_item
+                end
+              end
+            end
+          end
+EOC
+        end
+      end
+    end
+
+    class ChannelBase
+      include DublinCoreModel
+      
+      remove_method(:date)
+      remove_method(:date=)
+      alias_method(:date, :dc_date)
+      alias_method(:date=, :dc_date=)
+    end
+    
+    class ImageBase; include DublinCoreModel; end
+    class ItemsBase
+      class ItemBase
+        include DublinCoreModel
+        
+        remove_method(:date)
+        remove_method(:date=)
+        alias_method(:date, :dc_date)
+        alias_method(:date=, :dc_date=)
+      end
+    end
+    class TextinputBase; include DublinCoreModel; end
+
+    class RSS10
+      class Channel
+        DublinCoreModel.install_dublin_core(self)
+      end
+
+      class Image
+        DublinCoreModel.install_dublin_core(self)
+      end
+
+      class Items
+        class Item
+          DublinCoreModel.install_dublin_core(self)
+        end
+      end
+
+      class Textinput
+        DublinCoreModel.install_dublin_core(self)
+      end
+    end
+    
+    class RSS09
+      class Channel
+        DublinCoreModel.install_dublin_core(self)
+      end
+
+      class Image
+        DublinCoreModel.install_dublin_core(self)
+      end
+
+      class Items
+        class Item
+          DublinCoreModel.install_dublin_core(self)
+        end
+      end
+
+      class Textinput
+        DublinCoreModel.install_dublin_core(self)
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/image.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/image.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/image.rb	(revision 18425)
@@ -0,0 +1,145 @@
+require 'rss/image'
+require 'rss/maker/1.0'
+require 'rss/maker/dublincore'
+
+module RSS
+  module Maker
+    module ImageItemModel
+      def self.append_features(klass)
+        super
+
+        name = "#{RSS::IMAGE_PREFIX}_item"
+        klass.add_need_initialize_variable(name, "make_#{name}")
+        klass.add_other_element(name)
+        klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
+          attr_reader :#{name}
+          def setup_#{name}(rss, current)
+            if @#{name}
+              @#{name}.to_rss(rss, current)
+            end
+          end
+
+          def make_#{name}
+            self.class::#{Utils.to_class_name(name)}.new(@maker)
+          end
+EOC
+      end
+
+      class ImageItemBase
+        include Base
+        include Maker::DublinCoreModel
+
+        attr_accessor :about, :resource, :image_width, :image_height
+        add_need_initialize_variable("about")
+        add_need_initialize_variable("resource")
+        add_need_initialize_variable("image_width")
+        add_need_initialize_variable("image_height")
+        alias width= image_width=
+        alias width image_width
+        alias height= image_height=
+        alias height image_height
+
+        def have_required_values?
+          @about
+        end
+      end
+    end
+
+    module ImageFaviconModel
+      def self.append_features(klass)
+        super
+
+        name = "#{RSS::IMAGE_PREFIX}_favicon"
+        klass.add_need_initialize_variable(name, "make_#{name}")
+        klass.add_other_element(name)
+        klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
+          attr_reader :#{name}
+          def setup_#{name}(rss, current)
+            if @#{name}
+              @#{name}.to_rss(rss, current)
+            end
+          end
+
+          def make_#{name}
+            self.class::#{Utils.to_class_name(name)}.new(@maker)
+          end
+EOC
+      end
+
+      class ImageFaviconBase
+        include Base
+        include Maker::DublinCoreModel
+
+        attr_accessor :about, :image_size
+        add_need_initialize_variable("about")
+        add_need_initialize_variable("image_size")
+        alias size image_size
+        alias size= image_size=
+
+        def have_required_values?
+          @about and @image_size
+        end
+      end
+    end
+
+    class ChannelBase; include Maker::ImageFaviconModel; end
+    
+    class ItemsBase
+      class ItemBase; include Maker::ImageItemModel; end
+    end
+
+    class RSS10
+      class Items
+        class Item
+          class ImageItem < ImageItemBase
+            DublinCoreModel.install_dublin_core(self)
+            def to_rss(rss, current)
+              if @about
+                item = ::RSS::ImageItemModel::ImageItem.new(@about, @resource)
+                setup_values(item)
+                setup_other_elements(item)
+                current.image_item = item
+              end
+            end
+          end
+        end
+      end
+      
+      class Channel
+        class ImageFavicon < ImageFaviconBase
+          DublinCoreModel.install_dublin_core(self)
+          def to_rss(rss, current)
+            if @about and @image_size
+              args = [@about, @image_size]
+              favicon = ::RSS::ImageFaviconModel::ImageFavicon.new(*args)
+              setup_values(favicon)
+              setup_other_elements(favicon)
+              current.image_favicon = favicon
+            end
+          end
+        end
+      end
+    end
+
+    class RSS09
+      class Items
+        class Item
+          class ImageItem < ImageItemBase
+            DublinCoreModel.install_dublin_core(self)
+            def to_rss(*args)
+            end
+          end
+        end
+      end
+      
+      class Channel
+        class ImageFavicon < ImageFaviconBase
+          DublinCoreModel.install_dublin_core(self)
+          def to_rss(*args)
+          end
+        end
+      end
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/syndication.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/syndication.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/syndication.rb	(revision 18425)
@@ -0,0 +1,27 @@
+require 'rss/syndication'
+require 'rss/maker/1.0'
+
+module RSS
+  module Maker
+    module SyndicationModel
+      def self.append_features(klass)
+        super
+
+        ::RSS::SyndicationModel::ELEMENTS.each do |element|
+          klass.add_need_initialize_variable(element)
+          klass.add_other_element(element)
+          klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
+            attr_accessor :#{element}
+            def setup_#{element}(rss, current)
+              if #{element} and current.respond_to?(:#{element}=)
+                current.#{element} = @#{element} if @#{element}
+              end
+            end
+          EOC
+        end
+      end
+    end
+
+    class ChannelBase; include SyndicationModel; end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/taxonomy.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/taxonomy.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/taxonomy.rb	(revision 18425)
@@ -0,0 +1,182 @@
+require 'rss/taxonomy'
+require 'rss/maker/1.0'
+require 'rss/maker/dublincore'
+
+module RSS
+  module Maker
+    module TaxonomyTopicsModel
+      def self.append_features(klass)
+        super
+
+        klass.add_need_initialize_variable("taxo_topics", "make_taxo_topics")
+        klass.add_other_element("taxo_topics")
+        klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
+          attr_reader :taxo_topics
+          def make_taxo_topics
+            self.class::TaxonomyTopics.new(@maker)
+          end
+            
+          def setup_taxo_topics(rss, current)
+            @taxo_topics.to_rss(rss, current)
+          end
+EOC
+      end
+
+      def self.install_taxo_topics(klass)
+        klass.module_eval(<<-EOC, *Utils.get_file_and_line_from_caller(1))
+          class TaxonomyTopics < TaxonomyTopicsBase
+            def to_rss(rss, current)
+              if current.respond_to?(:taxo_topics)
+                topics = current.class::TaxonomyTopics.new
+                bag = topics.Bag
+                @resources.each do |resource|
+                  bag.lis << RDF::Bag::Li.new(resource)
+                end
+                current.taxo_topics = topics
+              end
+            end
+          end
+EOC
+      end
+
+      class TaxonomyTopicsBase
+        include Base
+
+        attr_reader :resources
+        def_array_element("resources")
+      end
+    end
+
+    module TaxonomyTopicModel
+      def self.append_features(klass)
+        super
+
+        klass.add_need_initialize_variable("taxo_topics", "make_taxo_topics")
+        klass.add_other_element("taxo_topics")
+        klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
+          attr_reader :taxo_topics
+          def make_taxo_topics
+            self.class::TaxonomyTopics.new(@maker)
+          end
+            
+          def setup_taxo_topics(rss, current)
+            @taxo_topics.to_rss(rss, current)
+          end
+
+          def taxo_topic
+            @taxo_topics[0] and @taxo_topics[0].value
+          end
+            
+          def taxo_topic=(new_value)
+            @taxo_topic[0] = self.class::TaxonomyTopic.new(self)
+            @taxo_topic[0].value = new_value
+          end
+EOC
+      end
+    
+      def self.install_taxo_topic(klass)
+        klass.module_eval(<<-EOC, *Utils.get_file_and_line_from_caller(1))
+          class TaxonomyTopics < TaxonomyTopicsBase
+            class TaxonomyTopic < TaxonomyTopicBase
+              DublinCoreModel.install_dublin_core(self)
+              TaxonomyTopicsModel.install_taxo_topics(self)
+
+              def to_rss(rss, current)
+                if current.respond_to?(:taxo_topics)
+                  topic = current.class::TaxonomyTopic.new(value)
+                  topic.taxo_link = value
+                  taxo_topics.to_rss(rss, topic) if taxo_topics
+                  current.taxo_topics << topic
+                  setup_other_elements(rss)
+                end
+              end
+
+              def current_element(rss)
+                super.taxo_topics.last
+              end
+            end
+          end
+EOC
+      end
+
+      class TaxonomyTopicsBase
+        include Base
+        
+        def_array_element("taxo_topics")
+                            
+        def new_taxo_topic
+          taxo_topic = self.class::TaxonomyTopic.new(self)
+          @taxo_topics << taxo_topic
+          if block_given?
+            yield taxo_topic
+          else
+            taxo_topic
+          end
+        end
+
+        def to_rss(rss, current)
+          @taxo_topics.each do |taxo_topic|
+            taxo_topic.to_rss(rss, current)
+          end
+        end
+        
+        class TaxonomyTopicBase
+          include Base
+          include DublinCoreModel
+          include TaxonomyTopicsModel
+          
+          attr_accessor :value
+          add_need_initialize_variable("value")
+          alias_method(:taxo_link, :value)
+          alias_method(:taxo_link=, :value=)
+          
+          def have_required_values?
+            @value
+          end
+        end
+      end
+    end
+
+    class RSSBase
+      include TaxonomyTopicModel
+    end
+    
+    class ChannelBase
+      include TaxonomyTopicsModel
+    end
+    
+    class ItemsBase
+      class ItemBase
+        include TaxonomyTopicsModel
+      end
+    end
+
+    class RSS10
+      TaxonomyTopicModel.install_taxo_topic(self)
+      
+      class Channel
+        TaxonomyTopicsModel.install_taxo_topics(self)
+      end
+
+      class Items
+        class Item
+          TaxonomyTopicsModel.install_taxo_topics(self)
+        end
+      end
+    end
+    
+    class RSS09
+      TaxonomyTopicModel.install_taxo_topic(self)
+      
+      class Channel
+        TaxonomyTopicsModel.install_taxo_topics(self)
+      end
+
+      class Items
+        class Item
+          TaxonomyTopicsModel.install_taxo_topics(self)
+        end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/trackback.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/trackback.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/trackback.rb	(revision 18425)
@@ -0,0 +1,130 @@
+require 'rss/trackback'
+require 'rss/maker/1.0'
+require 'rss/maker/2.0'
+
+module RSS
+  module Maker
+    module TrackBackModel
+      def self.append_features(klass)
+        super
+
+        name = "#{RSS::TRACKBACK_PREFIX}_ping"
+        klass.add_need_initialize_variable(name)
+        klass.add_other_element(name)
+        klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
+          attr_accessor :#{name}
+          def setup_#{name}(rss, current)
+            if #{name} and current.respond_to?(:#{name}=)
+              current.#{name} = #{name}
+            end
+          end
+        EOC
+
+        name = "#{RSS::TRACKBACK_PREFIX}_abouts"
+        klass.add_need_initialize_variable(name, "make_#{name}")
+        klass.add_other_element(name)
+        klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
+          attr_accessor :#{name}
+          def make_#{name}
+            self.class::TrackBackAbouts.new(self)
+          end
+
+          def setup_#{name}(rss, current)
+            @#{name}.to_rss(rss, current)
+          end
+        EOC
+      end
+
+      class TrackBackAboutsBase
+        include Base
+
+        def_array_element("abouts")
+        
+        def new_about
+          about = self.class::TrackBackAbout.new(@maker)
+          @abouts << about
+          if block_given?
+            yield about
+          else
+            about
+          end
+        end
+
+        def to_rss(rss, current)
+          @abouts.each do |about|
+            about.to_rss(rss, current)
+          end
+        end
+        
+        class TrackBackAboutBase
+          include Base
+
+          attr_accessor :value
+          add_need_initialize_variable("value")
+          
+          alias_method(:resource, :value)
+          alias_method(:resource=, :value=)
+          alias_method(:content, :value)
+          alias_method(:content=, :value=)
+        
+          def have_required_values?
+            @value
+          end
+          
+        end
+      end
+    end
+
+    class ItemsBase
+      class ItemBase; include TrackBackModel; end
+    end
+
+    class RSS10
+      class Items
+        class Item
+          class TrackBackAbouts < TrackBackAboutsBase
+            class TrackBackAbout < TrackBackAboutBase
+              def to_rss(rss, current)
+                if resource
+                  about = ::RSS::TrackBackModel10::TrackBackAbout.new(resource)
+                  current.trackback_abouts << about
+                end
+              end
+            end
+          end
+        end
+      end
+    end
+
+    class RSS09
+      class Items
+        class Item
+          class TrackBackAbouts < TrackBackAboutsBase
+            def to_rss(*args)
+            end
+            class TrackBackAbout < TrackBackAboutBase
+            end
+          end
+        end
+      end
+    end
+    
+    class RSS20
+      class Items
+        class Item
+          class TrackBackAbouts < TrackBackAboutsBase
+            class TrackBackAbout < TrackBackAboutBase
+              def to_rss(rss, current)
+                if content
+                  about = ::RSS::TrackBackModel20::TrackBackAbout.new(content)
+                  current.trackback_abouts << about
+                end
+              end
+            end
+          end
+        end
+      end
+    end
+    
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/parser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/parser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/parser.rb	(revision 18425)
@@ -0,0 +1,476 @@
+require "forwardable"
+require "open-uri"
+
+require "rss/rss"
+
+module RSS
+
+  class NotWellFormedError < Error
+    attr_reader :line, :element
+
+    # Create a new NotWellFormedError for an error at +line+
+    # in +element+.  If a block is given the return value of
+    # the block ends up in the error message.
+    def initialize(line=nil, element=nil)
+      message = "This is not well formed XML"
+      if element or line
+        message << "\nerror occurred"
+        message << " in #{element}" if element
+        message << " at about #{line} line" if line
+      end
+      message << "\n#{yield}" if block_given?
+      super(message)
+    end
+  end
+
+  class XMLParserNotFound < Error
+    def initialize
+      super("available XML parser was not found in " <<
+            "#{AVAILABLE_PARSER_LIBRARIES.inspect}.")
+    end
+  end
+
+  class NotValidXMLParser < Error
+    def initialize(parser)
+      super("#{parser} is not an available XML parser. " <<
+            "Available XML parser"<<
+            (AVAILABLE_PARSERS.size > 1 ? "s are ": " is ") <<
+            "#{AVAILABLE_PARSERS.inspect}.")
+    end
+  end
+
+  class NSError < InvalidRSSError
+    attr_reader :tag, :prefix, :uri
+    def initialize(tag, prefix, require_uri)
+      @tag, @prefix, @uri = tag, prefix, require_uri
+      super("prefix <#{prefix}> doesn't associate uri " <<
+            "<#{require_uri}> in tag <#{tag}>")
+    end
+  end
+
+  class Parser
+
+    extend Forwardable
+
+    class << self
+
+      @@default_parser = nil
+
+      def default_parser
+        @@default_parser || AVAILABLE_PARSERS.first
+      end
+
+      # Set @@default_parser to new_value if it is one of the
+      # available parsers. Else raise NotValidXMLParser error.
+      def default_parser=(new_value)
+        if AVAILABLE_PARSERS.include?(new_value)
+          @@default_parser = new_value
+        else
+          raise NotValidXMLParser.new(new_value)
+        end
+      end
+
+      def parse(rss, do_validate=true, ignore_unknown_element=true,
+                parser_class=default_parser)
+        parser = new(rss, parser_class)
+        parser.do_validate = do_validate
+        parser.ignore_unknown_element = ignore_unknown_element
+        parser.parse
+      end
+    end
+
+    def_delegators(:@parser, :parse, :rss,
+                   :ignore_unknown_element,
+                   :ignore_unknown_element=, :do_validate,
+                   :do_validate=)
+
+    def initialize(rss, parser_class=self.class.default_parser)
+      @parser = parser_class.new(normalize_rss(rss))
+    end
+
+    private
+
+    # Try to get the XML associated with +rss+.
+    # Return +rss+ if it already looks like XML, or treat it as a URI,
+    # or a file to get the XML,
+    def normalize_rss(rss)
+      return rss if maybe_xml?(rss)
+
+      uri = to_uri(rss)
+      
+      if uri.respond_to?(:read)
+        uri.read
+      elsif !rss.tainted? and File.readable?(rss)
+        File.open(rss) {|f| f.read}
+      else
+        rss
+      end
+    end
+
+    # maybe_xml? tests if source is a string that looks like XML.
+    def maybe_xml?(source)
+      source.is_a?(String) and /</ =~ source
+    end
+
+    # Attempt to convert rss to a URI, but just return it if 
+    # there's a ::URI::Error
+    def to_uri(rss)
+      return rss if rss.is_a?(::URI::Generic)
+
+      begin
+        URI(rss)
+      rescue ::URI::Error
+        rss
+      end
+    end
+  end
+
+  class BaseParser
+
+    class << self
+      def raise_for_undefined_entity?
+        listener.raise_for_undefined_entity?
+      end
+    end
+    
+    def initialize(rss)
+      @listener = self.class.listener.new
+      @rss = rss
+    end
+
+    def rss
+      @listener.rss
+    end
+
+    def ignore_unknown_element
+      @listener.ignore_unknown_element
+    end
+
+    def ignore_unknown_element=(new_value)
+      @listener.ignore_unknown_element = new_value
+    end
+
+    def do_validate
+      @listener.do_validate
+    end
+
+    def do_validate=(new_value)
+      @listener.do_validate = new_value
+    end
+
+    def parse
+      if @listener.rss.nil?
+        _parse
+      end
+      @listener.rss
+    end
+
+  end
+
+  class BaseListener
+
+    extend Utils
+
+    class << self
+
+      @@setters = {}
+      @@registered_uris = {}
+      @@class_names = {}
+
+      # return the setter for the uri, tag_name pair, or nil.
+      def setter(uri, tag_name)
+        begin
+          @@setters[uri][tag_name]
+        rescue NameError
+          nil
+        end
+      end
+
+
+      # return the tag_names for setters associated with uri
+      def available_tags(uri)
+        begin
+          @@setters[uri].keys
+        rescue NameError
+          []
+        end
+      end
+      
+      # register uri against this name.
+      def register_uri(uri, name)
+        @@registered_uris[name] ||= {}
+        @@registered_uris[name][uri] = nil
+      end
+      
+      # test if this uri is registered against this name
+      def uri_registered?(uri, name)
+        @@registered_uris[name].has_key?(uri)
+      end
+
+      # record class_name for the supplied uri and tag_name
+      def install_class_name(uri, tag_name, class_name)
+        @@class_names[uri] ||= {}
+        @@class_names[uri][tag_name] = class_name
+      end
+
+      # retrieve class_name for the supplied uri and tag_name
+      # If it doesn't exist, capitalize the tag_name
+      def class_name(uri, tag_name)
+        begin
+          @@class_names[uri][tag_name]
+        rescue NameError
+          tag_name[0,1].upcase + tag_name[1..-1]
+        end
+      end
+
+      def install_get_text_element(uri, name, setter)
+        install_setter(uri, name, setter)
+        def_get_text_element(uri, name, *get_file_and_line_from_caller(1))
+      end
+      
+      def raise_for_undefined_entity?
+        true
+      end
+    
+      private
+      # set the setter for the uri, tag_name pair
+      def install_setter(uri, tag_name, setter)
+        @@setters[uri] ||= {}
+        @@setters[uri][tag_name] = setter
+      end
+
+      def def_get_text_element(uri, name, file, line)
+        register_uri(uri, name)
+        unless private_instance_methods(false).include?("start_#{name}")
+          module_eval(<<-EOT, file, line)
+          def start_#{name}(name, prefix, attrs, ns)
+            uri = _ns(ns, prefix)
+            if self.class.uri_registered?(uri, #{name.inspect})
+              start_get_text_element(name, prefix, ns, uri)
+            else
+              start_else_element(name, prefix, attrs, ns)
+            end
+          end
+          EOT
+          __send__("private", "start_#{name}")
+        end
+      end
+
+    end
+
+  end
+
+  module ListenerMixin
+
+    attr_reader :rss
+
+    attr_accessor :ignore_unknown_element
+    attr_accessor :do_validate
+
+    def initialize
+      @rss = nil
+      @ignore_unknown_element = true
+      @do_validate = true
+      @ns_stack = [{}]
+      @tag_stack = [[]]
+      @text_stack = ['']
+      @proc_stack = []
+      @last_element = nil
+      @version = @encoding = @standalone = nil
+      @xml_stylesheets = []
+    end
+    
+    # set instance vars for version, encoding, standalone
+    def xmldecl(version, encoding, standalone)
+      @version, @encoding, @standalone = version, encoding, standalone
+    end
+
+    def instruction(name, content)
+      if name == "xml-stylesheet"
+        params = parse_pi_content(content)
+        if params.has_key?("href")
+          @xml_stylesheets << XMLStyleSheet.new(*params)
+        end
+      end
+    end
+
+    def tag_start(name, attributes)
+      @text_stack.push('')
+
+      ns = @ns_stack.last.dup
+      attrs = {}
+      attributes.each do |n, v|
+        if /\Axmlns(?:\z|:)/ =~ n
+          ns[$POSTMATCH] = v
+        else
+          attrs[n] = v
+        end
+      end
+      @ns_stack.push(ns)
+
+      prefix, local = split_name(name)
+      @tag_stack.last.push([_ns(ns, prefix), local])
+      @tag_stack.push([])
+      if respond_to?("start_#{local}", true)
+        __send__("start_#{local}", local, prefix, attrs, ns.dup)
+      else
+        start_else_element(local, prefix, attrs, ns.dup)
+      end
+    end
+
+    def tag_end(name)
+      if DEBUG
+        p "end tag #{name}"
+        p @tag_stack
+      end
+      text = @text_stack.pop
+      tags = @tag_stack.pop
+      pr = @proc_stack.pop
+      pr.call(text, tags) unless pr.nil?
+      @ns_stack.pop
+    end
+
+    def text(data)
+      @text_stack.last << data
+    end
+
+    private
+    def _ns(ns, prefix)
+      ns.fetch(prefix, "")
+    end
+
+    CONTENT_PATTERN = /\s*([^=]+)=(["'])([^\2]+?)\2/
+    # Extract the first name="value" pair from content.
+    # Works with single quotes according to the constant
+    # CONTENT_PATTERN. Return a Hash.
+    def parse_pi_content(content)
+      params = {}
+      content.scan(CONTENT_PATTERN) do |name, quote, value|
+        params[name] = value
+      end
+      params
+    end
+
+    def start_else_element(local, prefix, attrs, ns)
+      class_name = self.class.class_name(_ns(ns, prefix), local)
+      current_class = @last_element.class
+      if current_class.constants.include?(class_name)
+        next_class = current_class.const_get(class_name)
+        start_have_something_element(local, prefix, attrs, ns, next_class)
+      else
+        if !@do_validate or @ignore_unknown_element
+          @proc_stack.push(nil)
+        else
+          parent = "ROOT ELEMENT???"
+          if current_class.tag_name
+            parent = current_class.tag_name
+          end
+          raise NotExpectedTagError.new(local, _ns(ns, prefix), parent)
+        end
+      end
+    end
+
+    NAMESPLIT = /^(?:([\w:][-\w\d.]*):)?([\w:][-\w\d.]*)/
+    def split_name(name)
+      name =~ NAMESPLIT
+      [$1 || '', $2]
+    end
+
+    def check_ns(tag_name, prefix, ns, require_uri)
+      if @do_validate
+        if _ns(ns, prefix) == require_uri
+          #ns.delete(prefix)
+        else
+          raise NSError.new(tag_name, prefix, require_uri)
+        end
+      end
+    end
+
+    def start_get_text_element(tag_name, prefix, ns, required_uri)
+      @proc_stack.push Proc.new {|text, tags|
+        setter = self.class.setter(required_uri, tag_name)
+        if @last_element.respond_to?(setter)
+          @last_element.__send__(setter, text.to_s)
+        else
+          if @do_validate and !@ignore_unknown_element
+            raise NotExpectedTagError.new(tag_name, _ns(ns, prefix),
+                                          @last_element.tag_name)
+          end
+        end
+      }
+    end
+
+    def start_have_something_element(tag_name, prefix, attrs, ns, klass)
+
+      check_ns(tag_name, prefix, ns, klass.required_uri)
+
+      attributes = {}
+      klass.get_attributes.each do |a_name, a_uri, required, element_name|
+
+        if a_uri.is_a?(String) or !a_uri.respond_to?(:include?)
+          a_uri = [a_uri]
+        end
+        unless a_uri == [""]
+          for prefix, uri in ns
+            if a_uri.include?(uri)
+              val = attrs["#{prefix}:#{a_name}"]
+              break if val
+            end
+          end
+        end
+        if val.nil? and a_uri.include?("")
+          val = attrs[a_name]
+        end
+
+        if @do_validate and required and val.nil?
+          unless a_uri.include?("")
+            for prefix, uri in ns
+              if a_uri.include?(uri)
+                a_name = "#{prefix}:#{a_name}"
+              end
+            end
+          end
+          raise MissingAttributeError.new(tag_name, a_name)
+        end
+
+        attributes[a_name] = val
+      end
+
+      previous = @last_element
+      next_element = klass.new(@do_validate, attributes)
+      previous.instance_eval {set_next_element(tag_name, next_element)}
+      @last_element = next_element
+      @proc_stack.push Proc.new { |text, tags|
+        p(@last_element.class) if DEBUG
+        @last_element.content = text if klass.have_content?
+        if @do_validate
+          @last_element.validate_for_stream(tags, @ignore_unknown_element)
+        end
+        @last_element = previous
+      }
+    end
+
+  end
+
+  unless const_defined? :AVAILABLE_PARSER_LIBRARIES
+    AVAILABLE_PARSER_LIBRARIES = [
+      ["rss/xmlparser", :XMLParserParser],
+      ["rss/xmlscanner", :XMLScanParser],
+      ["rss/rexmlparser", :REXMLParser],
+    ]
+  end
+
+  AVAILABLE_PARSERS = []
+
+  AVAILABLE_PARSER_LIBRARIES.each do |lib, parser|
+    begin
+      require lib
+      AVAILABLE_PARSERS.push(const_get(parser))
+    rescue LoadError
+    end
+  end
+
+  if AVAILABLE_PARSERS.empty?
+    raise XMLParserNotFound
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/rexmlparser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/rexmlparser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/rexmlparser.rb	(revision 18425)
@@ -0,0 +1,54 @@
+require "rexml/document"
+require "rexml/streamlistener"
+
+/\A(\d+)\.(\d+)(?:\.\d+)+\z/ =~ REXML::Version
+if ([$1.to_i, $2.to_i] <=> [2, 5]) < 0
+  raise LoadError, "needs REXML 2.5 or later (#{REXML::Version})"
+end
+
+module RSS
+  
+  class REXMLParser < BaseParser
+
+    class << self
+      def listener
+        REXMLListener
+      end
+    end
+    
+    private
+    def _parse
+      begin
+        REXML::Document.parse_stream(@rss, @listener)
+      rescue RuntimeError => e
+        raise NotWellFormedError.new{e.message}
+      rescue REXML::ParseException => e
+        context = e.context
+        line = context[0] if context
+        raise NotWellFormedError.new(line){e.message}
+      end
+    end
+    
+  end
+  
+  class REXMLListener < BaseListener
+
+    include REXML::StreamListener
+    include ListenerMixin
+
+    class << self
+      def raise_for_undefined_entity?
+        false
+      end
+    end
+    
+    def xmldecl(version, encoding, standalone)
+      super(version, encoding, standalone == "yes")
+      # Encoding is converted to UTF-8 when REXML parse XML.
+      @encoding = 'UTF-8'
+    end
+
+    alias_method(:cdata, :text)
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/rss.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/rss.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/rss.rb	(revision 18425)
@@ -0,0 +1,1015 @@
+require "time"
+
+class Time
+  class << self
+    unless respond_to?(:w3cdtf)
+      def w3cdtf(date)
+        if /\A\s*
+            (-?\d+)-(\d\d)-(\d\d)
+            (?:T
+            (\d\d):(\d\d)(?::(\d\d))?
+            (\.\d+)?
+            (Z|[+-]\d\d:\d\d)?)?
+            \s*\z/ix =~ date and (($5 and $8) or (!$5 and !$8))
+          datetime = [$1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i] 
+          datetime << $7.to_f * 1000000 if $7
+          if $8
+            Time.utc(*datetime) - zone_offset($8)
+          else
+            Time.local(*datetime)
+          end
+        else
+          raise ArgumentError.new("invalid date: #{date.inspect}")
+        end
+      end
+    end
+  end
+
+  unless instance_methods.include?("w3cdtf")
+    alias w3cdtf iso8601
+  end
+end
+
+require "English"
+require "rss/utils"
+require "rss/converter"
+require "rss/xml-stylesheet"
+
+module RSS
+
+  VERSION = "0.1.6"
+
+  URI = "http://purl.org/rss/1.0/"
+
+  DEBUG = false
+
+  class Error < StandardError; end
+
+  class OverlappedPrefixError < Error
+    attr_reader :prefix
+    def initialize(prefix)
+      @prefix = prefix
+    end
+  end
+
+  class InvalidRSSError < Error; end
+
+  class MissingTagError < InvalidRSSError
+    attr_reader :tag, :parent
+    def initialize(tag, parent)
+      @tag, @parent = tag, parent
+      super("tag <#{tag}> is missing in tag <#{parent}>")
+    end
+  end
+
+  class TooMuchTagError < InvalidRSSError
+    attr_reader :tag, :parent
+    def initialize(tag, parent)
+      @tag, @parent = tag, parent
+      super("tag <#{tag}> is too much in tag <#{parent}>")
+    end
+  end
+
+  class MissingAttributeError < InvalidRSSError
+    attr_reader :tag, :attribute
+    def initialize(tag, attribute)
+      @tag, @attribute = tag, attribute
+      super("attribute <#{attribute}> is missing in tag <#{tag}>")
+    end
+  end
+
+  class UnknownTagError < InvalidRSSError
+    attr_reader :tag, :uri
+    def initialize(tag, uri)
+      @tag, @uri = tag, uri
+      super("tag <#{tag}> is unknown in namespace specified by uri <#{uri}>")
+    end
+  end
+
+  class NotExpectedTagError < InvalidRSSError
+    attr_reader :tag, :uri, :parent
+    def initialize(tag, uri, parent)
+      @tag, @uri, @parent = tag, uri, parent
+      super("tag <{#{uri}}#{tag}> is not expected in tag <#{parent}>")
+    end
+  end
+  # For backward compatibility :X
+  NotExceptedTagError = NotExpectedTagError
+
+  class NotAvailableValueError < InvalidRSSError
+    attr_reader :tag, :value, :attribute
+    def initialize(tag, value, attribute=nil)
+      @tag, @value, @attribute = tag, value, attribute
+      message = "value <#{value}> of "
+      message << "attribute <#{attribute}> of " if attribute
+      message << "tag <#{tag}> is not available."
+      super(message)
+    end
+  end
+
+  class UnknownConversionMethodError < Error
+    attr_reader :to, :from
+    def initialize(to, from)
+      @to = to
+      @from = from
+      super("can't convert to #{to} from #{from}.")
+    end
+  end
+  # for backward compatibility
+  UnknownConvertMethod = UnknownConversionMethodError
+
+  class ConversionError < Error
+    attr_reader :string, :to, :from
+    def initialize(string, to, from)
+      @string = string
+      @to = to
+      @from = from
+      super("can't convert #{@string} to #{to} from #{from}.")
+    end
+  end
+
+  class NotSetError < Error
+    attr_reader :name, :variables
+    def initialize(name, variables)
+      @name = name
+      @variables = variables
+      super("required variables of #{@name} are not set: #{@variables.join(', ')}")
+    end
+  end
+  
+  module BaseModel
+
+    include Utils
+
+    def install_have_child_element(tag_name, uri, occurs, name=nil)
+      name ||= tag_name
+      add_need_initialize_variable(name)
+      install_model(tag_name, uri, occurs, name)
+
+      attr_accessor name
+      install_element(name) do |n, elem_name|
+        <<-EOC
+        if @#{n}
+          "\#{@#{n}.to_s(need_convert, indent)}"
+        else
+          ''
+        end
+EOC
+      end
+    end
+    alias_method(:install_have_attribute_element, :install_have_child_element)
+
+    def install_have_children_element(tag_name, uri, occurs, name=nil, plural_name=nil)
+      name ||= tag_name
+      plural_name ||= "#{name}s"
+      add_have_children_element(name, plural_name)
+      add_plural_form(name, plural_name)
+      install_model(tag_name, uri, occurs, plural_name)
+
+      def_children_accessor(name, plural_name)
+      install_element(name, "s") do |n, elem_name|
+        <<-EOC
+        rv = []
+        @#{n}.each do |x|
+          value = "\#{x.to_s(need_convert, indent)}"
+          rv << value if /\\A\\s*\\z/ !~ value
+        end
+        rv.join("\n")
+EOC
+      end
+    end
+
+    def install_text_element(tag_name, uri, occurs, name=nil, type=nil, disp_name=nil)
+      name ||= tag_name
+      disp_name ||= name
+      self::ELEMENTS << name
+      add_need_initialize_variable(name)
+      install_model(tag_name, uri, occurs, name)
+
+      def_corresponded_attr_writer name, type, disp_name
+      convert_attr_reader name
+      install_element(name) do |n, elem_name|
+        <<-EOC
+        if @#{n}
+          rv = "\#{indent}<#{elem_name}>"
+          value = html_escape(@#{n})
+          if need_convert
+            rv << convert(value)
+          else
+            rv << value
+          end
+    	    rv << "</#{elem_name}>"
+          rv
+        else
+          ''
+        end
+EOC
+      end
+    end
+
+    def install_date_element(tag_name, uri, occurs, name=nil, type=nil, disp_name=nil)
+      name ||= tag_name
+      type ||= :w3cdtf
+      disp_name ||= name
+      self::ELEMENTS << name
+      add_need_initialize_variable(name)
+      install_model(tag_name, uri, occurs, name)
+
+      # accessor
+      convert_attr_reader name
+      date_writer(name, type, disp_name)
+      
+      install_element(name) do |n, elem_name|
+        <<-EOC
+        if @#{n}
+          rv = "\#{indent}<#{elem_name}>"
+          value = html_escape(@#{n}.#{type})
+          if need_convert
+            rv << convert(value)
+          else
+            rv << value
+          end
+    	    rv << "</#{elem_name}>"
+          rv
+        else
+          ''
+        end
+EOC
+      end
+
+    end
+
+    private
+    def install_element(name, postfix="")
+      elem_name = name.sub('_', ':')
+      method_name = "#{name}_element#{postfix}"
+      add_to_element_method(method_name)
+      module_eval(<<-EOC, *get_file_and_line_from_caller(2))
+      def #{method_name}(need_convert=true, indent='')
+        #{yield(name, elem_name)}
+      end
+      private :#{method_name}
+EOC
+    end
+
+    def convert_attr_reader(*attrs)
+      attrs.each do |attr|
+        attr = attr.id2name if attr.kind_of?(Integer)
+        module_eval(<<-EOC, *get_file_and_line_from_caller(2))
+        def #{attr}
+          if @converter
+            @converter.convert(@#{attr})
+          else
+            @#{attr}
+          end
+        end
+EOC
+      end
+    end
+
+    def date_writer(name, type, disp_name=name)
+      module_eval(<<-EOC, *get_file_and_line_from_caller(2))
+      def #{name}=(new_value)
+        if new_value.nil? or new_value.kind_of?(Time)
+          @#{name} = new_value
+        else
+          if @do_validate
+            begin
+              @#{name} = Time.__send__('#{type}', new_value)
+            rescue ArgumentError
+              raise NotAvailableValueError.new('#{disp_name}', new_value)
+            end
+          else
+            @#{name} = nil
+            if /\\A\\s*\\z/ !~ new_value.to_s
+              begin
+                @#{name} = Time.parse(new_value)
+              rescue ArgumentError
+              end
+            end
+          end
+        end
+
+        # Is it need?
+        if @#{name}
+          class << @#{name}
+            undef_method(:to_s)
+            alias_method(:to_s, :#{type})
+          end
+        end
+
+      end
+EOC
+    end
+
+    def integer_writer(name, disp_name=name)
+      module_eval(<<-EOC, *get_file_and_line_from_caller(2))
+      def #{name}=(new_value)
+        if new_value.nil?
+          @#{name} = new_value
+        else
+          if @do_validate
+            begin
+              @#{name} = Integer(new_value)
+            rescue ArgumentError
+              raise NotAvailableValueError.new('#{disp_name}', new_value)
+            end
+          else
+            @#{name} = new_value.to_i
+          end
+        end
+      end
+EOC
+    end
+
+    def positive_integer_writer(name, disp_name=name)
+      module_eval(<<-EOC, *get_file_and_line_from_caller(2))
+      def #{name}=(new_value)
+        if new_value.nil?
+          @#{name} = new_value
+        else
+          if @do_validate
+            begin
+              tmp = Integer(new_value)
+              raise ArgumentError if tmp <= 0
+              @#{name} = tmp
+            rescue ArgumentError
+              raise NotAvailableValueError.new('#{disp_name}', new_value)
+            end
+          else
+            @#{name} = new_value.to_i
+          end
+        end
+      end
+EOC
+    end
+
+    def boolean_writer(name, disp_name=name)
+      module_eval(<<-EOC, *get_file_and_line_from_caller(2))
+      def #{name}=(new_value)
+        if new_value.nil?
+          @#{name} = new_value
+        else
+          if @do_validate and
+              ![true, false, "true", "false"].include?(new_value)
+            raise NotAvailableValueError.new('#{disp_name}', new_value)
+          end
+          if [true, false].include?(new_value)
+            @#{name} = new_value
+          else
+            @#{name} = new_value == "true"
+          end
+        end
+      end
+EOC
+    end
+
+    def def_children_accessor(accessor_name, plural_name)
+      module_eval(<<-EOC, *get_file_and_line_from_caller(2))
+      def #{plural_name}
+        @#{accessor_name}
+      end
+
+      def #{accessor_name}(*args)
+        if args.empty?
+          @#{accessor_name}.first
+        else
+          @#{accessor_name}[*args]
+        end
+      end
+
+      def #{accessor_name}=(*args)
+        warn("Warning:\#{caller.first.sub(/:in `.*'\z/, '')}: " \
+             "Don't use `#{accessor_name} = XXX'/`set_#{accessor_name}(XXX)'. " \
+             "Those APIs are not sense of Ruby. " \
+             "Use `#{plural_name} << XXX' instead of them.")
+        if args.size == 1
+          @#{accessor_name}.push(args[0])
+        else
+          @#{accessor_name}.__send__("[]=", *args)
+        end
+      end
+      alias_method(:set_#{accessor_name}, :#{accessor_name}=)
+EOC
+    end
+  end
+
+  class Element
+
+    extend BaseModel
+    include Utils
+
+    INDENT = "  "
+    
+    MUST_CALL_VALIDATORS = {}
+    MODELS = []
+    GET_ATTRIBUTES = []
+    HAVE_CHILDREN_ELEMENTS = []
+    TO_ELEMENT_METHODS = []
+    NEED_INITIALIZE_VARIABLES = []
+    PLURAL_FORMS = {}
+    
+    class << self
+
+      def must_call_validators
+        MUST_CALL_VALIDATORS
+      end
+      def models
+        MODELS
+      end
+      def get_attributes
+        GET_ATTRIBUTES
+      end
+      def have_children_elements
+        HAVE_CHILDREN_ELEMENTS
+      end
+      def to_element_methods
+        TO_ELEMENT_METHODS
+      end
+      def need_initialize_variables
+        NEED_INITIALIZE_VARIABLES
+      end
+      def plural_forms
+        PLURAL_FORMS
+      end
+
+      
+      def inherited(klass)
+        klass.const_set("MUST_CALL_VALIDATORS", {})
+        klass.const_set("MODELS", [])
+        klass.const_set("GET_ATTRIBUTES", [])
+        klass.const_set("HAVE_CHILDREN_ELEMENTS", [])
+        klass.const_set("TO_ELEMENT_METHODS", [])
+        klass.const_set("NEED_INITIALIZE_VARIABLES", [])
+        klass.const_set("PLURAL_FORMS", {})
+
+        klass.module_eval(<<-EOC)
+        public
+        
+        @tag_name = name.split(/::/).last
+        @tag_name[0,1] = @tag_name[0,1].downcase
+        @have_content = false
+
+        def self.must_call_validators
+          super.merge(MUST_CALL_VALIDATORS)
+        end
+        def self.models
+          MODELS + super
+        end
+        def self.get_attributes
+          GET_ATTRIBUTES + super
+        end
+        def self.have_children_elements
+          HAVE_CHILDREN_ELEMENTS + super
+        end
+        def self.to_element_methods
+          TO_ELEMENT_METHODS + super
+        end
+        def self.need_initialize_variables
+          NEED_INITIALIZE_VARIABLES + super
+        end
+        def self.plural_forms
+          super.merge(PLURAL_FORMS)
+        end
+
+      
+        def self.install_must_call_validator(prefix, uri)
+          MUST_CALL_VALIDATORS[uri] = prefix
+        end
+        
+        def self.install_model(tag, uri, occurs=nil, getter=nil)
+          getter ||= tag
+          if m = MODELS.find {|t, u, o, g| t == tag and u == uri}
+            m[2] = occurs
+          else
+            MODELS << [tag, uri, occurs, getter]
+          end
+        end
+
+        def self.install_get_attribute(name, uri, required=true,
+                                       type=nil, disp_name=nil,
+                                       element_name=nil)
+          disp_name ||= name
+          element_name ||= name
+          def_corresponded_attr_writer name, type, disp_name
+          convert_attr_reader name
+          if type == :boolean and /^is/ =~ name
+            alias_method "\#{$POSTMATCH}?", name
+          end
+          GET_ATTRIBUTES << [name, uri, required, element_name]
+          add_need_initialize_variable(disp_name)
+        end
+
+        def self.def_corresponded_attr_writer(name, type=nil, disp_name=name)
+          case type
+          when :integer
+            integer_writer name, disp_name
+          when :positive_integer
+            positive_integer_writer name, disp_name
+          when :boolean
+            boolean_writer name, disp_name
+          when :w3cdtf, :rfc822, :rfc2822
+            date_writer name, type, disp_name
+          else
+            attr_writer name
+          end
+        end
+
+        def self.content_setup(type=nil)
+          def_corresponded_attr_writer "content", type
+          convert_attr_reader :content
+          @have_content = true
+        end
+
+        def self.have_content?
+          @have_content
+        end
+
+        def self.add_have_children_element(variable_name, plural_name)
+          HAVE_CHILDREN_ELEMENTS << [variable_name, plural_name]
+        end
+        
+        def self.add_to_element_method(method_name)
+          TO_ELEMENT_METHODS << method_name
+        end
+
+        def self.add_need_initialize_variable(variable_name)
+          NEED_INITIALIZE_VARIABLES << variable_name
+        end
+        
+        def self.add_plural_form(singular, plural)
+          PLURAL_FORMS[singular] = plural
+        end
+        
+        EOC
+      end
+
+      def required_prefix
+        nil
+      end
+
+      def required_uri
+        ""
+      end
+      
+      def install_ns(prefix, uri)
+        if self::NSPOOL.has_key?(prefix)
+          raise OverlappedPrefixError.new(prefix)
+        end
+        self::NSPOOL[prefix] = uri
+      end
+
+      def tag_name
+        @tag_name
+      end
+    end
+
+    attr_accessor :do_validate
+
+    def initialize(do_validate=true, attrs={})
+      @converter = nil
+      @do_validate = do_validate
+      initialize_variables(attrs)
+    end
+
+    def tag_name
+      self.class.tag_name
+    end
+
+    def full_name
+      tag_name
+    end
+    
+    def converter=(converter)
+      @converter = converter
+      targets = children.dup
+      self.class.have_children_elements.each do |variable_name, plural_name|
+        targets.concat(__send__(plural_name))
+      end
+      targets.each do |target|
+        target.converter = converter unless target.nil?
+      end
+    end
+
+    def convert(value)
+      if @converter
+        @converter.convert(value)
+      else
+        value
+      end
+    end
+    
+    def validate(ignore_unknown_element=true)
+      validate_attribute
+      __validate(ignore_unknown_element)
+    end
+    
+    def validate_for_stream(tags, ignore_unknown_element=true)
+      validate_attribute
+      __validate(ignore_unknown_element, tags, false)
+    end
+
+    def setup_maker(maker)
+      target = maker_target(maker)
+      unless target.nil?
+        setup_maker_attributes(target)
+        setup_maker_element(target)
+        setup_maker_elements(target)
+      end
+    end
+
+    def to_s(need_convert=true, indent='')
+      if self.class.have_content?
+        return "" unless @content
+        rv = tag(indent) do |next_indent|
+          h(@content)
+        end
+      else
+        rv = tag(indent) do |next_indent|
+          self.class.to_element_methods.collect do |method_name|
+            __send__(method_name, false, next_indent)
+          end
+        end
+      end
+      rv = convert(rv) if need_convert
+      rv
+    end
+
+    private
+    def initialize_variables(attrs)
+      normalized_attrs = {}
+      attrs.each do |key, value|
+        normalized_attrs[key.to_s] = value
+      end
+      self.class.need_initialize_variables.each do |variable_name|
+        value = normalized_attrs[variable_name.to_s]
+        if value
+          __send__("#{variable_name}=", value)
+        else
+          instance_eval("@#{variable_name} = nil")
+        end
+      end
+      initialize_have_children_elements
+      @content = "" if self.class.have_content?
+    end
+
+    def initialize_have_children_elements
+      self.class.have_children_elements.each do |variable_name, plural_name|
+        instance_eval("@#{variable_name} = []")
+      end
+    end
+
+    def tag(indent, additional_attrs={}, &block)
+      next_indent = indent + INDENT
+
+      attrs = collect_attrs
+      return "" if attrs.nil?
+
+      attrs.update(additional_attrs)
+      start_tag = make_start_tag(indent, next_indent, attrs)
+
+      if block
+        content = block.call(next_indent)
+      else
+        content = []
+      end
+
+      if content.is_a?(String)
+        content = [content]
+        start_tag << ">"
+        end_tag = "</#{full_name}>"
+      else
+        content = content.reject{|x| x.empty?}
+        if content.empty?
+          end_tag = "/>"
+        else
+          start_tag << ">\n"
+          end_tag = "\n#{indent}</#{full_name}>"
+        end
+      end
+      
+      start_tag + content.join("\n") + end_tag
+    end
+
+    def make_start_tag(indent, next_indent, attrs)
+      start_tag = ["#{indent}<#{full_name}"]
+      unless attrs.empty?
+        start_tag << attrs.collect do |key, value|
+          %Q[#{h key}="#{h value}"]
+        end.join("\n#{next_indent}")
+      end
+      start_tag.join(" ")
+    end
+
+    def collect_attrs
+      attrs = {}
+      _attrs.each do |name, required, alias_name|
+        value = __send__(alias_name || name)
+        return nil if required and value.nil?
+        next if value.nil?
+        return nil if attrs.has_key?(name)
+        attrs[name] = value
+      end
+      attrs
+    end
+    
+    def tag_name_with_prefix(prefix)
+      "#{prefix}:#{tag_name}"
+    end
+
+    # For backward compatibility
+    def calc_indent
+      ''
+    end
+
+    def maker_target(maker)
+      nil
+    end
+    
+    def setup_maker_attributes(target)
+    end
+    
+    def setup_maker_element(target)
+      self.class.need_initialize_variables.each do |var|
+        value = __send__(var)
+        if value.respond_to?("setup_maker") and
+            !not_need_to_call_setup_maker_variables.include?(var)
+          value.setup_maker(target)
+        else
+          setter = "#{var}="
+          if target.respond_to?(setter)
+            target.__send__(setter, value)
+          end
+        end
+      end
+    end
+
+    def not_need_to_call_setup_maker_variables
+      []
+    end
+    
+    def setup_maker_elements(parent)
+      self.class.have_children_elements.each do |name, plural_name|
+        if parent.respond_to?(plural_name)
+          target = parent.__send__(plural_name)
+          __send__(plural_name).each do |elem|
+            elem.setup_maker(target)
+          end
+        end
+      end
+    end
+
+    def set_next_element(tag_name, next_element)
+      klass = next_element.class
+      prefix = ""
+      prefix << "#{klass.required_prefix}_" if klass.required_prefix
+      key = "#{prefix}#{tag_name}"
+      if self.class.plural_forms.has_key?(key)
+        ary = __send__("#{self.class.plural_forms[key]}")
+        ary << next_element
+      else
+        __send__("#{prefix}#{tag_name}=", next_element)
+      end
+    end
+
+    def children
+      rv = []
+      self.class.models.each do |name, uri, occurs, getter|
+        value = __send__(getter)
+        next if value.nil?
+        value = [value] unless value.is_a?(Array)
+        value.each do |v|
+          rv << v if v.is_a?(Element)
+        end
+      end
+      rv
+    end
+
+    def _tags
+      rv = []
+      self.class.models.each do |name, uri, occurs, getter|
+        value = __send__(getter)
+        next if value.nil?
+        if value.is_a?(Array)
+          rv.concat([[uri, name]] * value.size)
+        else
+          rv << [uri, name]
+        end
+      end
+      rv
+    end
+
+    def _attrs
+      self.class.get_attributes.collect do |name, uri, required, element_name|
+        [element_name, required, name]
+      end
+    end
+
+    def __validate(ignore_unknown_element, tags=_tags, recursive=true)
+      if recursive
+        children.compact.each do |child|
+          child.validate
+        end
+      end
+      must_call_validators = self.class.must_call_validators
+      tags = tag_filter(tags.dup)
+      p tags if DEBUG
+      must_call_validators.each do |uri, prefix|
+        _validate(ignore_unknown_element, tags[uri], uri)
+        meth = "#{prefix}_validate"
+        if respond_to?(meth, true)
+          __send__(meth, ignore_unknown_element, tags[uri], uri)
+        end
+      end
+    end
+
+    def validate_attribute
+      _attrs.each do |a_name, required, alias_name|
+        if required and __send__(alias_name || a_name).nil?
+          raise MissingAttributeError.new(tag_name, a_name)
+        end
+      end
+    end
+
+    def _validate(ignore_unknown_element, tags, uri, models=self.class.models)
+      count = 1
+      do_redo = false
+      not_shift = false
+      tag = nil
+      models = models.find_all {|model| model[1] == uri}
+      element_names = models.collect {|model| model[0]}
+      if tags
+        tags_size = tags.size
+        tags = tags.sort_by {|x| element_names.index(x) || tags_size}
+      end
+
+      models.each_with_index do |model, i|
+        name, model_uri, occurs, getter = model
+
+        if DEBUG
+          p "before" 
+          p tags
+          p model
+        end
+
+        if not_shift
+          not_shift = false
+        elsif tags
+          tag = tags.shift
+        end
+
+        if DEBUG
+          p "mid"
+          p count
+        end
+
+        case occurs
+        when '?'
+          if count > 2
+            raise TooMuchTagError.new(name, tag_name)
+          else
+            if name == tag
+              do_redo = true
+            else
+              not_shift = true
+            end
+          end
+        when '*'
+          if name == tag
+            do_redo = true
+          else
+            not_shift = true
+          end
+        when '+'
+          if name == tag
+            do_redo = true
+          else
+            if count > 1
+              not_shift = true
+            else
+              raise MissingTagError.new(name, tag_name)
+            end
+          end
+        else
+          if name == tag
+            if models[i+1] and models[i+1][0] != name and
+                tags and tags.first == name
+              raise TooMuchTagError.new(name, tag_name)
+            end
+          else
+            raise MissingTagError.new(name, tag_name)
+          end
+        end
+
+        if DEBUG
+          p "after"
+          p not_shift
+          p do_redo
+          p tag
+        end
+
+        if do_redo
+          do_redo = false
+          count += 1
+          redo
+        else
+          count = 1
+        end
+
+      end
+
+      if !ignore_unknown_element and !tags.nil? and !tags.empty?
+        raise NotExpectedTagError.new(tags.first, uri, tag_name)
+      end
+
+    end
+
+    def tag_filter(tags)
+      rv = {}
+      tags.each do |tag|
+        rv[tag[0]] = [] unless rv.has_key?(tag[0])
+        rv[tag[0]].push(tag[1])
+      end
+      rv
+    end
+
+  end
+
+  module RootElementMixin
+
+    include XMLStyleSheetMixin
+    
+    attr_reader :output_encoding
+
+    def initialize(rss_version, version=nil, encoding=nil, standalone=nil)
+      super()
+      @rss_version = rss_version
+      @version = version || '1.0'
+      @encoding = encoding
+      @standalone = standalone
+      @output_encoding = nil
+    end
+
+    def output_encoding=(enc)
+      @output_encoding = enc
+      self.converter = Converter.new(@output_encoding, @encoding)
+    end
+
+    def setup_maker(maker)
+      maker.version = version
+      maker.encoding = encoding
+      maker.standalone = standalone
+
+      xml_stylesheets.each do |xss|
+        xss.setup_maker(maker)
+      end
+
+      setup_maker_elements(maker)
+    end
+
+    def to_xml(version=nil, &block)
+      if version.nil? or version == @rss_version
+        to_s
+      else
+        RSS::Maker.make(version) do |maker|
+          setup_maker(maker)
+          block.call(maker) if block
+        end.to_s
+      end
+    end
+
+    private
+    def tag(indent, attrs={}, &block)
+      rv = xmldecl + xml_stylesheet_pi
+      rv << super(indent, ns_declarations.merge(attrs), &block)
+      rv
+    end
+
+    def xmldecl
+      rv = %Q[<?xml version="#{@version}"]
+      if @output_encoding or @encoding
+        rv << %Q[ encoding="#{@output_encoding or @encoding}"]
+      end
+      rv << %Q[ standalone="yes"] if @standalone
+      rv << "?>\n"
+      rv
+    end
+    
+    def ns_declarations
+      decls = {}
+      self.class::NSPOOL.collect do |prefix, uri|
+        prefix = ":#{prefix}" unless prefix.empty?
+        decls["xmlns#{prefix}"] = uri
+      end
+      decls
+    end
+    
+    def setup_maker_elements(maker)
+      channel.setup_maker(maker) if channel
+      image.setup_maker(maker) if image
+      textinput.setup_maker(maker) if textinput
+      super(maker)
+    end
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/syndication.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/syndication.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/syndication.rb	(revision 18425)
@@ -0,0 +1,64 @@
+require "rss/1.0"
+
+module RSS
+
+  SY_PREFIX = 'sy'
+  SY_URI = "http://purl.org/rss/1.0/modules/syndication/"
+
+  RDF.install_ns(SY_PREFIX, SY_URI)
+
+  module SyndicationModel
+    
+    extend BaseModel
+    
+    ELEMENTS = []
+    
+    def self.append_features(klass)
+      super
+
+      klass.install_must_call_validator(SY_PREFIX, SY_URI)
+      klass.module_eval do
+        [
+          ["updatePeriod"],
+          ["updateFrequency", :positive_integer]
+        ].each do |name, type|
+          install_text_element(name, SY_URI, "?",
+                               "#{SY_PREFIX}_#{name}", type,
+                               "#{SY_PREFIX}:#{name}")
+        end
+
+        %w(updateBase).each do |name|
+          install_date_element(name, SY_URI, "?",
+                               "#{SY_PREFIX}_#{name}", 'w3cdtf', name)
+        end
+
+        alias_method(:_sy_updatePeriod=, :sy_updatePeriod=)
+        def sy_updatePeriod=(new_value)
+          new_value = new_value.strip
+          validate_sy_updatePeriod(new_value) if @do_validate
+          self._sy_updatePeriod = new_value
+        end
+      end
+    end
+
+    private
+    SY_UPDATEPERIOD_AVAILABLE_VALUES = %w(hourly daily weekly monthly yearly)
+    def validate_sy_updatePeriod(value)
+      unless SY_UPDATEPERIOD_AVAILABLE_VALUES.include?(value)
+        raise NotAvailableValueError.new("updatePeriod", value)
+      end
+    end
+  end
+
+  class RDF
+    class Channel; include SyndicationModel; end
+  end
+
+  prefix_size = SY_PREFIX.size + 1
+  SyndicationModel::ELEMENTS.uniq!
+  SyndicationModel::ELEMENTS.each do |full_name|
+    name = full_name[prefix_size..-1]
+    BaseListener.install_get_text_element(SY_URI, name, "#{full_name}=")
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/taxonomy.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/taxonomy.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/taxonomy.rb	(revision 18425)
@@ -0,0 +1,145 @@
+require "rss/1.0"
+require "rss/dublincore"
+
+module RSS
+
+  TAXO_PREFIX = "taxo"
+  TAXO_URI = "http://purl.org/rss/1.0/modules/taxonomy/"
+
+  RDF.install_ns(TAXO_PREFIX, TAXO_URI)
+
+  TAXO_ELEMENTS = []
+
+  %w(link).each do |name|
+    full_name = "#{TAXO_PREFIX}_#{name}"
+    BaseListener.install_get_text_element(TAXO_URI, name, "#{full_name}=")
+    TAXO_ELEMENTS << "#{TAXO_PREFIX}_#{name}"
+  end
+
+  %w(topic topics).each do |name|
+    class_name = Utils.to_class_name(name)
+    BaseListener.install_class_name(TAXO_URI, name, "Taxonomy#{class_name}")
+    TAXO_ELEMENTS << "#{TAXO_PREFIX}_#{name}"
+  end
+
+  module TaxonomyTopicsModel
+    extend BaseModel
+    
+    def self.append_features(klass)
+      super
+
+      klass.install_must_call_validator(TAXO_PREFIX, TAXO_URI)
+      %w(topics).each do |name|
+        klass.install_have_child_element(name, TAXO_URI, "?",
+                                         "#{TAXO_PREFIX}_#{name}")
+      end
+    end
+
+    class TaxonomyTopics < Element
+      include RSS10
+      
+      Bag = ::RSS::RDF::Bag
+
+      class << self
+        def required_prefix
+          TAXO_PREFIX
+        end
+        
+        def required_uri
+          TAXO_URI
+        end
+      end
+
+      @tag_name = "topics"
+      
+      install_have_child_element("Bag", RDF::URI, nil)
+      install_must_call_validator('rdf', RDF::URI)
+
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.Bag = args[0]
+        end
+        self.Bag ||= Bag.new
+      end
+
+      def full_name
+        tag_name_with_prefix(TAXO_PREFIX)
+      end
+
+      def maker_target(target)
+        target.taxo_topics
+      end
+
+      def resources
+        if @Bag
+          @Bag.lis.collect do |li|
+            li.resource
+          end
+        else
+          []
+        end
+      end
+    end
+  end
+  
+  module TaxonomyTopicModel
+    extend BaseModel
+    
+    def self.append_features(klass)
+      super
+      var_name = "#{TAXO_PREFIX}_topic"
+      klass.install_have_children_element("topic", TAXO_URI, "*", var_name)
+    end
+
+    class TaxonomyTopic < Element
+      include RSS10
+
+      include DublinCoreModel
+      include TaxonomyTopicsModel
+      
+      class << self
+        def required_prefix
+          TAXO_PREFIX
+        end
+        
+        def required_uri
+          TAXO_URI
+        end
+      end
+
+      @tag_name = "topic"
+
+      install_get_attribute("about", ::RSS::RDF::URI, true, nil, nil,
+                            "#{RDF::PREFIX}:about")
+      install_text_element("link", TAXO_URI, "?", "#{TAXO_PREFIX}_link")
+        
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.about = args[0]
+        end
+      end
+
+      def full_name
+        tag_name_with_prefix(TAXO_PREFIX)
+      end
+
+      def maker_target(target)
+        target.new_taxo_topic
+      end
+    end
+  end
+
+  class RDF
+    include TaxonomyTopicModel
+    class Channel
+      include TaxonomyTopicsModel
+    end
+    class Item; include TaxonomyTopicsModel; end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/trackback.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/trackback.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/trackback.rb	(revision 18425)
@@ -0,0 +1,288 @@
+require 'rss/1.0'
+require 'rss/2.0'
+
+module RSS
+
+  TRACKBACK_PREFIX = 'trackback'
+  TRACKBACK_URI = 'http://madskills.com/public/xml/rss/module/trackback/'
+
+  RDF.install_ns(TRACKBACK_PREFIX, TRACKBACK_URI)
+  Rss.install_ns(TRACKBACK_PREFIX, TRACKBACK_URI)
+
+  module TrackBackUtils
+    private
+    def trackback_validate(ignore_unknown_element, tags, uri)
+      return if tags.nil?
+      if tags.find {|tag| tag == "about"} and
+          !tags.find {|tag| tag == "ping"}
+        raise MissingTagError.new("#{TRACKBACK_PREFIX}:ping", tag_name)
+      end
+    end
+  end
+
+  module BaseTrackBackModel
+
+    ELEMENTS = %w(ping about)
+    
+    def append_features(klass)
+      super
+
+      unless klass.class == Module
+        klass.module_eval {include TrackBackUtils}
+
+        klass.install_must_call_validator(TRACKBACK_PREFIX, TRACKBACK_URI)
+        %w(ping).each do |name|
+          var_name = "#{TRACKBACK_PREFIX}_#{name}"
+          klass_name = "TrackBack#{Utils.to_class_name(name)}"
+          klass.install_have_child_element(name, TRACKBACK_URI, "?", var_name)
+          klass.module_eval(<<-EOC, __FILE__, __LINE__)
+            remove_method :#{var_name}
+            def #{var_name}
+              @#{var_name} and @#{var_name}.value
+            end
+
+            remove_method :#{var_name}=
+            def #{var_name}=(value)
+              @#{var_name} = Utils.new_with_value_if_need(#{klass_name}, value)
+            end
+          EOC
+        end
+        
+        [%w(about s)].each do |name, postfix|
+          var_name = "#{TRACKBACK_PREFIX}_#{name}"
+          klass_name = "TrackBack#{Utils.to_class_name(name)}"
+          klass.install_have_children_element(name, TRACKBACK_URI, "*",
+                                              var_name)
+          klass.module_eval(<<-EOC, __FILE__, __LINE__)
+            remove_method :#{var_name}
+            def #{var_name}(*args)
+              if args.empty?
+                @#{var_name}.first and @#{var_name}.first.value
+              else
+                ret = @#{var_name}.__send__("[]", *args)
+                if ret.is_a?(Array)
+                  ret.collect {|x| x.value}
+                else
+                  ret.value
+                end
+              end
+            end
+
+            remove_method :#{var_name}=
+            remove_method :set_#{var_name}
+            def #{var_name}=(*args)
+              if args.size == 1
+                item = Utils.new_with_value_if_need(#{klass_name}, args[0])
+                @#{var_name}.push(item)
+              else
+                new_val = args.last
+                if new_val.is_a?(Array)
+                  new_val = new_value.collect do |val|
+                    Utils.new_with_value_if_need(#{klass_name}, val)
+                  end
+                else
+                  new_val = Utils.new_with_value_if_need(#{klass_name}, new_val)
+                end
+                @#{var_name}.__send__("[]=", *(args[0..-2] + [new_val]))
+              end
+            end
+            alias set_#{var_name} #{var_name}=
+          EOC
+        end
+      end
+    end
+  end
+
+  module TrackBackModel10
+    extend BaseModel
+    extend BaseTrackBackModel
+
+    class TrackBackPing < Element
+      include RSS10
+
+      class << self
+
+        def required_prefix
+          TRACKBACK_PREFIX
+        end
+        
+        def required_uri
+          TRACKBACK_URI
+        end
+
+      end
+
+      @tag_name = "ping"
+
+      [
+        ["resource", ::RSS::RDF::URI, true]
+      ].each do |name, uri, required|
+        install_get_attribute(name, uri, required, nil, nil,
+                              "#{::RSS::RDF::PREFIX}:#{name}")
+      end
+
+      alias_method(:value, :resource)
+      alias_method(:value=, :resource=)
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.resource = args[0]
+        end
+      end
+
+      def full_name
+        tag_name_with_prefix(TRACKBACK_PREFIX)
+      end
+    end
+
+    class TrackBackAbout < Element
+      include RSS10
+
+      class << self
+        
+        def required_prefix
+          TRACKBACK_PREFIX
+        end
+        
+        def required_uri
+          TRACKBACK_URI
+        end
+
+      end
+      
+      @tag_name = "about"
+
+      [
+        ["resource", ::RSS::RDF::URI, true]
+      ].each do |name, uri, required|
+        install_get_attribute(name, uri, required, nil, nil,
+                              "#{::RSS::RDF::PREFIX}:#{name}")
+      end
+
+      alias_method(:value, :resource)
+      alias_method(:value=, :resource=)
+      
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.resource = args[0]
+        end
+      end
+
+      def full_name
+        tag_name_with_prefix(TRACKBACK_PREFIX)
+      end
+
+      private
+      def maker_target(abouts)
+        abouts.new_about
+      end
+
+      def setup_maker_attributes(about)
+        about.resource = self.resource
+      end
+      
+    end
+  end
+
+  module TrackBackModel20
+    extend BaseModel
+    extend BaseTrackBackModel
+
+    class TrackBackPing < Element
+      include RSS09
+
+      @tag_name = "ping"
+      
+      content_setup
+
+      class << self
+
+        def required_prefix
+          TRACKBACK_PREFIX
+        end
+        
+        def required_uri
+          TRACKBACK_URI
+        end
+
+      end
+      
+      alias_method(:value, :content)
+      alias_method(:value=, :content=)
+
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.content = args[0]
+        end
+      end
+      
+      def full_name
+        tag_name_with_prefix(TRACKBACK_PREFIX)
+      end
+      
+    end
+
+    class TrackBackAbout < Element
+      include RSS09
+
+      @tag_name = "about"
+      
+      content_setup
+
+      class << self
+        
+        def required_prefix
+          TRACKBACK_PREFIX
+        end
+        
+        def required_uri
+          TRACKBACK_URI
+        end
+
+      end
+
+      alias_method(:value, :content)
+      alias_method(:value=, :content=)
+
+      def initialize(*args)
+        if Utils.element_initialize_arguments?(args)
+          super
+        else
+          super()
+          self.content = args[0]
+        end
+      end
+      
+      def full_name
+        tag_name_with_prefix(TRACKBACK_PREFIX)
+      end
+      
+    end
+  end
+
+  class RDF
+    class Item; include TrackBackModel10; end
+  end
+
+  class Rss
+    class Channel
+      class Item; include TrackBackModel20; end
+    end
+  end
+
+  BaseTrackBackModel::ELEMENTS.each do |name|
+    class_name = Utils.to_class_name(name)
+    BaseListener.install_class_name(TRACKBACK_URI, name,
+                                    "TrackBack#{class_name}")
+  end
+
+  BaseTrackBackModel::ELEMENTS.collect! {|name| "#{TRACKBACK_PREFIX}_#{name}"}
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/utils.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/utils.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/utils.rb	(revision 18425)
@@ -0,0 +1,37 @@
+module RSS
+  module Utils
+    module_function
+
+    # Convert a name_with_underscores to CamelCase.
+    def to_class_name(name)
+      name.split(/_/).collect do |part|
+        "#{part[0, 1].upcase}#{part[1..-1]}"
+      end.join("")
+    end
+    
+    def get_file_and_line_from_caller(i=0)
+      file, line, = caller[i].split(':')
+      [file, line.to_i]
+    end
+
+    # escape '&', '"', '<' and '>' for use in HTML.
+    def html_escape(s)
+      s.to_s.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
+    end
+    alias h html_escape
+    
+    # If +value+ is an instance of class +klass+, return it, else
+    # create a new instance of +klass+ with value +value+.
+    def new_with_value_if_need(klass, value)
+      if value.is_a?(klass)
+        value
+      else
+        klass.new(value)
+      end
+    end
+
+    def element_initialize_arguments?(args)
+      [true, false].include?(args[0]) and args[1].is_a?(Hash)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/xml-stylesheet.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/xml-stylesheet.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/xml-stylesheet.rb	(revision 18425)
@@ -0,0 +1,101 @@
+require "rss/utils"
+
+module RSS
+
+  module XMLStyleSheetMixin
+    attr_accessor :xml_stylesheets
+    def initialize(*args)
+      super
+      @xml_stylesheets = []
+    end
+    
+    private
+    def xml_stylesheet_pi
+      xsss = @xml_stylesheets.collect do |xss|
+        pi = xss.to_s
+        pi = nil if /\A\s*\z/ =~ pi
+        pi
+      end.compact
+      xsss.push("") unless xsss.empty?
+      xsss.join("\n")
+    end
+  end
+
+  class XMLStyleSheet
+
+    include Utils
+
+    ATTRIBUTES = %w(href type title media charset alternate)
+
+    GUESS_TABLE = {
+      "xsl" => "text/xsl",
+      "css" => "text/css",
+    }
+
+    attr_accessor(*ATTRIBUTES)
+    attr_accessor(:do_validate)
+    def initialize(*attrs)
+      @do_validate = true
+      ATTRIBUTES.each do |attr|
+        __send__("#{attr}=", nil)
+      end
+      vars = ATTRIBUTES.dup
+      vars.unshift(:do_validate)
+      attrs.each do |name, value|
+        if vars.include?(name.to_s)
+          __send__("#{name}=", value)
+        end
+      end
+    end
+
+    def to_s
+      rv = ""
+      if @href
+        rv << %Q[<?xml-stylesheet]
+        ATTRIBUTES.each do |name|
+          if __send__(name)
+            rv << %Q[ #{name}="#{h __send__(name)}"]
+          end
+        end
+        rv << %Q[?>]
+      end
+      rv
+    end
+
+    remove_method(:href=)
+    def href=(value)
+      @href = value
+      if @href and @type.nil?
+        @type = guess_type(@href)
+      end
+      @href
+    end
+
+    remove_method(:alternate=)
+    def alternate=(value)
+      if value.nil? or /\A(?:yes|no)\z/ =~ value
+        @alternate = value
+      else
+        if @do_validate
+          args = ["?xml-stylesheet?", %Q[alternate="#{value}"]]
+          raise NotAvailableValueError.new(*args)
+        end
+      end
+      @alternate
+    end
+
+    def setup_maker(maker)
+      xss = maker.xml_stylesheets.new_xml_stylesheet
+      ATTRIBUTES.each do |attr|
+        xss.__send__("#{attr}=", __send__(attr))
+      end
+    end
+    
+    private
+    def guess_type(filename)
+      /\.([^.]+)$/ =~ filename
+      GUESS_TABLE[$1]
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/xmlparser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/xmlparser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/xmlparser.rb	(revision 18425)
@@ -0,0 +1,93 @@
+begin
+  require "xml/parser"
+rescue LoadError
+  require "xmlparser"
+end
+
+begin
+  require "xml/encoding-ja"
+rescue LoadError
+  require "xmlencoding-ja"
+  if defined?(Kconv)
+    module XMLEncoding_ja
+      class SJISHandler
+        include Kconv
+      end
+    end
+  end
+end
+
+module XML
+  class Parser
+    unless defined?(Error)
+      Error = ::XMLParserError
+    end
+  end
+end
+
+module RSS
+  
+  class REXMLLikeXMLParser < ::XML::Parser
+    
+    include ::XML::Encoding_ja
+
+    def listener=(listener)
+      @listener = listener
+    end
+
+    def startElement(name, attrs)
+      @listener.tag_start(name, attrs)
+    end
+    
+    def endElement(name)
+      @listener.tag_end(name)
+    end
+
+    def character(data)
+      @listener.text(data)
+    end
+
+    def xmlDecl(version, encoding, standalone)
+      @listener.xmldecl(version, encoding, standalone == 1)
+    end
+
+    def processingInstruction(target, content)
+      @listener.instruction(target, content)
+    end
+
+  end
+
+  class XMLParserParser < BaseParser
+
+    class << self
+      def listener
+        XMLParserListener
+      end
+    end
+    
+    private
+    def _parse
+      begin
+        parser = REXMLLikeXMLParser.new
+        parser.listener = @listener
+        parser.parse(@rss)
+      rescue ::XML::Parser::Error => e
+        raise NotWellFormedError.new(parser.line){e.message}
+      end
+    end
+    
+  end
+  
+  class XMLParserListener < BaseListener
+
+    include ListenerMixin
+    
+    def xmldecl(version, encoding, standalone)
+      super
+      # Encoding is converted to UTF-8 when XMLParser parses XML.
+      @encoding = 'UTF-8'
+    end
+
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/xmlscanner.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/xmlscanner.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/xmlscanner.rb	(revision 18425)
@@ -0,0 +1,121 @@
+require 'xmlscan/scanner'
+require 'stringio'
+
+module RSS
+  
+  class XMLScanParser < BaseParser
+    
+    class << self
+      def listener
+        XMLScanListener
+      end
+    end
+    
+    private
+    def _parse
+      begin
+        if @rss.is_a?(String)
+          input = StringIO.new(@rss)
+        else
+          input = @rss
+        end
+        scanner = XMLScan::XMLScanner.new(@listener)
+        scanner.parse(input)
+      rescue XMLScan::Error => e
+        lineno = e.lineno || scanner.lineno || input.lineno
+        raise NotWellFormedError.new(lineno){e.message}
+      end
+    end
+    
+  end
+
+  class XMLScanListener < BaseListener
+    
+    include XMLScan::Visitor
+    include ListenerMixin
+
+    ENTITIES = {
+      'lt' => '<',
+      'gt' => '>',
+      'amp' => '&',
+      'quot' => '"',
+      'apos' => '\''
+    }
+
+    def on_xmldecl_version(str)
+      @version = str
+    end
+
+    def on_xmldecl_encoding(str)
+      @encoding = str
+    end
+
+    def on_xmldecl_standalone(str)
+      @standalone = str
+    end
+
+    def on_xmldecl_end
+      xmldecl(@version, @encoding, @standalone == "yes")
+    end
+
+    alias_method(:on_pi, :instruction)
+    alias_method(:on_chardata, :text)
+    alias_method(:on_cdata, :text)
+
+    def on_etag(name)
+      tag_end(name)
+    end
+
+    def on_entityref(ref)
+      text(entity(ref))
+    end
+
+    def on_charref(code)
+      text([code].pack('U'))
+    end
+
+    alias_method(:on_charref_hex, :on_charref)
+
+    def on_stag(name)
+      @attrs = {}
+    end
+
+    def on_attribute(name)
+      @attrs[name] = @current_attr = ''
+    end
+
+    def on_attr_value(str)
+      @current_attr << str
+    end
+
+    def on_attr_entityref(ref)
+      @current_attr << entity(ref)
+    end
+
+    def on_attr_charref(code)
+      @current_attr << [code].pack('U')
+    end
+
+    alias_method(:on_attr_charref_hex, :on_attr_charref)
+
+    def on_stag_end(name)
+      tag_start(name, @attrs)
+    end
+
+    def on_stag_end_empty(name)
+      tag_start(name, @attrs)
+      tag_end(name)
+    end
+
+    private
+    def entity(ref)
+      ent = ENTITIES[ref]
+      if ent
+        ent
+      else
+        wellformed_error("undefined entity: #{ref}")
+      end
+    end
+  end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rubyunit.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rubyunit.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rubyunit.rb	(revision 18425)
@@ -0,0 +1,6 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'runit/testcase'
+require 'test/unit'
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/assert.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/assert.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/assert.rb	(revision 18425)
@@ -0,0 +1,73 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/assertions'
+require 'runit/error'
+
+module RUNIT
+  module Assert
+    include Test::Unit::Assertions
+
+    def setup_assert
+    end
+
+    def assert_no_exception(*args, &block)
+      assert_nothing_raised(*args, &block)
+    end
+
+    # To deal with the fact that RubyUnit does not check that the
+    # regular expression is, indeed, a regular expression, if it is
+    # not, we do our own assertion using the same semantics as
+    # RubyUnit
+    def assert_match(actual_string, expected_re, message="")
+      _wrap_assertion {
+        full_message = build_message(message, "Expected <?> to match <?>", actual_string, expected_re)
+        assert_block(full_message) {
+          expected_re =~ actual_string
+        }
+        Regexp.last_match
+      }
+    end
+
+    def assert_not_nil(actual, message="")
+      assert(!actual.nil?, message)
+    end
+
+    def assert_not_match(actual_string, expected_re, message="")
+      assert_no_match(expected_re, actual_string, message)
+    end
+
+    def assert_matches(*args)
+      assert_match(*args)
+    end
+
+    def assert_fail(message="")
+      flunk(message)
+    end
+
+    def assert_equal_float(expected, actual, delta, message="")
+      assert_in_delta(expected, actual, delta, message)
+    end
+
+    def assert_send(object, method, *args)
+      super([object, method, *args])
+    end
+
+    def assert_exception(exception, message="", &block)
+      assert_raises(exception, message, &block)
+    end
+
+    def assert_respond_to(method, object, message="")
+      if (called_internally?)
+        super
+      else
+        super(object, method, message)
+      end
+    end
+
+    def called_internally?
+      /assertions\.rb/.match(caller[1])
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/cui/testrunner.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/cui/testrunner.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/cui/testrunner.rb	(revision 18425)
@@ -0,0 +1,51 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/ui/console/testrunner'
+require 'runit/testresult'
+
+module RUNIT
+  module CUI
+    class TestRunner < Test::Unit::UI::Console::TestRunner
+      @@quiet_mode = false
+      
+      def self.run(suite)
+        self.new().run(suite)
+      end
+      
+      def initialize
+        super nil
+      end
+      
+      def run(suite, quiet_mode=@@quiet_mode)
+        @suite = suite
+        def @suite.suite
+          self
+        end
+        @output_level = (quiet_mode ? Test::Unit::UI::PROGRESS_ONLY : Test::Unit::UI::VERBOSE)
+        start
+      end
+      
+      def create_mediator(suite)
+        mediator = Test::Unit::UI::TestRunnerMediator.new(suite)
+        class << mediator
+          attr_writer :result_delegate
+          def create_result
+            return @result_delegate.create_result
+          end
+        end
+        mediator.result_delegate = self
+        return mediator
+      end
+      
+      def create_result
+        return RUNIT::TestResult.new
+      end
+      
+      def self.quiet_mode=(boolean)
+        @@quiet_mode = boolean
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/error.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/error.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/error.rb	(revision 18425)
@@ -0,0 +1,9 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/assertionfailederror.rb'
+
+module RUNIT
+  AssertionFailedError = Test::Unit::AssertionFailedError
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/testcase.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/testcase.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/testcase.rb	(revision 18425)
@@ -0,0 +1,45 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'runit/testresult'
+require 'runit/testsuite'
+require 'runit/assert'
+require 'runit/error'
+require 'test/unit/testcase'
+
+module RUNIT
+  class TestCase < Test::Unit::TestCase  
+    include RUNIT::Assert
+    
+    def self.suite
+      method_names = instance_methods(true)
+      tests = method_names.delete_if { |method_name| method_name !~ /^test/ }
+      suite = TestSuite.new(name)
+      tests.each {
+        |test|
+        catch(:invalid_test) {
+          suite << new(test, name)
+        }
+      }
+      return suite
+    end
+    
+    def initialize(test_name, suite_name=self.class.name)
+      super(test_name)
+    end
+    
+    def assert_equals(*args)
+      assert_equal(*args)
+    end
+    
+    def name
+      super.sub(/^(.*?)\((.*)\)$/, '\2#\1')
+    end
+    
+    def run(result, &progress_block)
+      progress_block = proc {} unless (block_given?)
+      super(result, &progress_block)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/testresult.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/testresult.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/testresult.rb	(revision 18425)
@@ -0,0 +1,44 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/testresult'
+
+module RUNIT
+  class TestResult < Test::Unit::TestResult
+    attr_reader(:errors, :failures)
+    def succeed?
+      return passed?
+    end
+    def failure_size
+      return failure_count
+    end
+    def run_asserts
+      return assertion_count
+    end
+    def error_size
+      return error_count
+    end
+    def run_tests
+      return run_count
+    end
+    def add_failure(failure)
+      def failure.at
+        return location
+      end
+      def failure.err
+        return message
+      end
+      super(failure)
+    end
+    def add_error(error)
+      def error.at
+        return location
+      end
+      def error.err
+        return exception
+      end
+      super(error)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/testsuite.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/testsuite.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/testsuite.rb	(revision 18425)
@@ -0,0 +1,26 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/testsuite'
+
+module RUNIT
+  class TestSuite < Test::Unit::TestSuite
+    def add_test(*args)
+      add(*args)
+    end
+    
+    def add(*args)
+      self.<<(*args)
+    end
+    
+    def count_test_cases
+      return size
+    end
+    
+    def run(result, &progress_block)
+      progress_block = proc {} unless (block_given?)
+      super(result, &progress_block)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/topublic.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/topublic.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/runit/topublic.rb	(revision 18425)
@@ -0,0 +1,8 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+module RUNIT
+  module ToPublic
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/scanf.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/scanf.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/scanf.rb	(revision 18425)
@@ -0,0 +1,702 @@
+# scanf for Ruby
+#
+# $Revision: 11708 $
+# $Id: scanf.rb 11708 2007-02-12 23:01:19Z shyouhei $
+# $Author: shyouhei $
+# $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#
+# A product of the Austin Ruby Codefest (Austin, Texas, August 2002)
+
+=begin
+
+=scanf for Ruby
+
+==Description
+
+scanf for Ruby is an implementation of the C function scanf(3),
+modified as necessary for Ruby compatibility.
+
+The methods provided are String#scanf, IO#scanf, and
+Kernel#scanf. Kernel#scanf is a wrapper around STDIN.scanf.  IO#scanf
+can be used on any IO stream, including file handles and sockets.
+scanf can be called either with or without a block.
+
+scanf for Ruby scans an input string or stream according to a
+<b>format</b>, as described below ("Conversions"), and returns an
+array of matches between the format and the input.  The format is
+defined in a string, and is similar (though not identical) to the
+formats used in Kernel#printf and Kernel#sprintf.
+
+The format may contain <b>conversion specifiers</b>, which tell scanf
+what form (type) each particular matched substring should be converted
+to (e.g., decimal integer, floating point number, literal string,
+etc.)  The matches and conversions take place from left to right, and
+the conversions themselves are returned as an array.
+
+The format string may also contain characters other than those in the
+conversion specifiers.  White space (blanks, tabs, or newlines) in the
+format string matches any amount of white space, including none, in
+the input.  Everything else matches only itself.
+
+Scanning stops, and scanf returns, when any input character fails to
+match the specifications in the format string, or when input is
+exhausted, or when everything in the format string has been
+matched. All matches found up to the stopping point are returned in
+the return array (or yielded to the block, if a block was given).
+
+
+==Basic usage
+
+   require 'scanf.rb'
+
+   # String#scanf and IO#scanf take a single argument (a format string)
+   array = aString.scanf("%d%s")
+   array = anIO.scanf("%d%s")
+
+   # Kernel#scanf reads from STDIN
+   array = scanf("%d%s")
+
+==Block usage
+
+When called with a block, scanf keeps scanning the input, cycling back
+to the beginning of the format string, and yields a new array of
+conversions to the block every time the format string is matched
+(including partial matches, but not including complete failures).  The
+actual return value of scanf when called with a block is an array
+containing the results of all the executions of the block. 
+
+   str = "123 abc 456 def 789 ghi"
+   str.scanf("%d%s") { |num,str| [ num * 2, str.upcase ] }
+     # => [[246, "ABC"], [912, "DEF"], [1578, "GHI"]]
+
+==Conversions
+
+The single argument to scanf is a format string, which generally
+includes one or more conversion specifiers. Conversion specifiers
+begin with the percent character ('%') and include information about
+what scanf should next scan for (string, decimal number, single
+character, etc.).
+
+There may be an optional maximum field width, expressed as a decimal
+integer, between the % and the conversion. If no width is given, a
+default of `infinity' is used (with the exception of the %c specifier;
+see below).  Otherwise, given a field width of <em>n</em> for a given
+conversion, at most <em>n</em> characters are scanned in processing
+that conversion.  Before conversion begins, most conversions skip
+white space in the input string; this white space is not counted
+against the field width.
+
+The following conversions are available. (See the files EXAMPLES
+and <tt>tests/scanftests.rb</tt> for examples.)
+
+[%]
+  Matches a literal `%'. That is, `%%' in the format string matches a
+  single input `%' character. No conversion is done, and the resulting
+  '%' is not included in the return array.
+
+[d]
+  Matches an optionally signed decimal integer.
+
+[u]
+  Same as d.
+
+[i] 
+  Matches an optionally signed integer. The integer is read in base
+  16 if it begins with `0x' or `0X', in base 8 if it begins with `0',
+  and in base 10 other- wise. Only characters that correspond to the
+  base are recognized.
+
+[o]
+  Matches an optionally signed octal integer.
+
+[x,X]
+  Matches an optionally signed hexadecimal integer,
+
+[f,g,e,E]
+  Matches an optionally signed floating-point number.
+
+[s]
+  Matches a sequence of non-white-space character. The input string stops at
+  white space or at the maximum field width, whichever occurs first.
+
+[c]
+  Matches a single character, or a sequence of <em>n</em> characters if a
+  field width of <em>n</em> is specified. The usual skip of leading white
+  space is suppressed. To skip white space first, use an explicit space in
+  the format.
+
+[<tt>[</tt>]
+  Matches a nonempty sequence of characters from the specified set
+  of accepted characters.  The usual skip of leading white space is
+  suppressed.  This bracketed sub-expression is interpreted exactly like a
+  character class in a Ruby regular expression.  (In fact, it is placed as-is
+  in a regular expression.)  The matching against the input string ends with
+  the appearance of a character not in (or, with a circumflex, in) the set,
+  or when the field width runs out, whichever comes first.
+
+===Assignment suppression
+
+To require that a particular match occur, but without including the result
+in the return array, place the <b>assignment suppression flag</b>, which is
+the star character ('*'), immediately after the leading '%' of a format
+specifier (just before the field width, if any).
+
+==Examples
+
+See the files <tt>EXAMPLES</tt> and <tt>tests/scanftests.rb</tt>.
+
+==scanf for Ruby compared with scanf in C
+
+scanf for Ruby is based on the C function scanf(3), but with modifications,
+dictated mainly by the underlying differences between the languages.
+
+===Unimplemented flags and specifiers
+
+* The only flag implemented in scanf for Ruby is '<tt>*</tt>' (ignore
+  upcoming conversion). Many of the flags available in C versions of scanf(4)
+  have to do with the type of upcoming pointer arguments, and are literally
+  meaningless in Ruby.
+
+* The <tt>n</tt> specifier (store number of characters consumed so far in
+  next pointer) is not implemented.
+
+* The <tt>p</tt> specifier (match a pointer value) is not implemented.
+
+===Altered specifiers
+
+[o,u,x,X]
+  In scanf for Ruby, all of these specifiers scan for an optionally signed
+  integer, rather than for an unsigned integer like their C counterparts.
+
+===Return values
+
+scanf for Ruby returns an array of successful conversions, whereas
+scanf(3) returns the number of conversions successfully
+completed. (See below for more details on scanf for Ruby's return
+values.)
+
+==Return values
+
+Without a block, scanf returns an array containing all the conversions
+it has found. If none are found, scanf will return an empty array. An
+unsuccesful match is never ignored, but rather always signals the end
+of the scanning operation. If the first unsuccessful match takes place
+after one or more successful matches have already taken place, the
+returned array will contain the results of those successful matches.
+
+With a block scanf returns a 'map'-like array of transformations from
+the block -- that is, an array reflecting what the block did with each
+yielded result from the iterative scanf operation.  (See "Block
+usage", above.)
+
+==Test suite
+
+scanf for Ruby includes a suite of unit tests (requiring the
+<tt>TestUnit</tt> package), which can be run with the command <tt>ruby
+tests/scanftests.rb</tt> or the command <tt>make test</tt>.
+
+==Current limitations and bugs
+
+When using IO#scanf under Windows, make sure you open your files in
+binary mode:
+
+    File.open("filename", "rb")
+
+so that scanf can keep track of characters correctly.
+
+Support for character classes is reasonably complete (since it
+essentially piggy-backs on Ruby's regular expression handling of
+character classes), but users are advised that character class testing
+has not been exhaustive, and that they should exercise some caution
+in using any of the more complex and/or arcane character class
+idioms.
+
+
+==Technical notes
+
+===Rationale behind scanf for Ruby
+
+The impetus for a scanf implementation in Ruby comes chiefly from the fact
+that existing pattern matching operations, such as Regexp#match and
+String#scan, return all results as strings, which have to be converted to
+integers or floats explicitly in cases where what's ultimately wanted are
+integer or float values.
+
+===Design of scanf for Ruby
+
+scanf for Ruby is essentially a <format string>-to-<regular
+expression> converter.
+
+When scanf is called, a FormatString object is generated from the
+format string ("%d%s...") argument. The FormatString object breaks the
+format string down into atoms ("%d", "%5f", "blah", etc.), and from
+each atom it creates a FormatSpecifier object, which it
+saves.
+
+Each FormatSpecifier has a regular expression fragment and a "handler"
+associated with it. For example, the regular expression fragment
+associated with the format "%d" is "([-+]?\d+)", and the handler
+associated with it is a wrapper around String#to_i. scanf itself calls
+FormatString#match, passing in the input string. FormatString#match
+iterates through its FormatSpecifiers; for each one, it matches the
+corresponding regular expression fragment against the string. If
+there's a match, it sends the matched string to the handler associated
+with the FormatSpecifier.
+
+Thus, to follow up the "%d" example: if "123" occurs in the input
+string when a FormatSpecifier consisting of "%d" is reached, the "123"
+will be matched against "([-+]?\d+)", and the matched string will be
+rendered into an integer by a call to to_i.
+
+The rendered match is then saved to an accumulator array, and the
+input string is reduced to the post-match substring. Thus the string
+is "eaten" from the left as the FormatSpecifiers are applied in
+sequence.  (This is done to a duplicate string; the original string is
+not altered.)
+
+As soon as a regular expression fragment fails to match the string, or
+when the FormatString object runs out of FormatSpecifiers, scanning
+stops and results accumulated so far are returned in an array.
+
+==License and copyright
+
+Copyright:: (c) 2002-2003 David Alan Black
+License:: Distributed on the same licensing terms as Ruby itself
+
+==Warranty disclaimer
+
+This software is provided "as is" and without any express or implied
+warranties, including, without limitation, the implied warranties of
+merchantibility and fitness for a particular purpose.
+
+==Credits and acknowledgements
+
+scanf for Ruby was developed as the major activity of the Austin
+Ruby Codefest (Austin, Texas, August 2002).
+
+Principal author:: David Alan Black (mailto:dblack@superlink.net)
+Co-author:: Hal Fulton (mailto:hal9000@hypermetrics.com)
+Project contributors:: Nolan Darilek, Jason Johnston
+
+Thanks to Hal Fulton for hosting the Codefest.
+
+Thanks to Matz for suggestions about the class design.  
+
+Thanks to Gavin Sinclair for some feedback on the documentation.
+
+The text for parts of this document, especially the Description and
+Conversions sections, above, were adapted from the Linux Programmer's
+Manual manpage for scanf(3), dated 1995-11-01.
+
+==Bugs and bug reports
+
+scanf for Ruby is based on something of an amalgam of C scanf
+implementations and documentation, rather than on a single canonical
+description. Suggestions for features and behaviors which appear in
+other scanfs, and would be meaningful in Ruby, are welcome, as are
+reports of suspicious behaviors and/or bugs. (Please see "Credits and
+acknowledgements", above, for email addresses.)
+
+=end
+
+module Scanf
+
+  class FormatSpecifier
+
+    attr_reader :re_string, :matched_string, :conversion, :matched
+
+    private
+
+    def skip;  /^\s*%\*/.match(@spec_string); end
+
+    def extract_float(s); s.to_f if s &&! skip; end
+    def extract_decimal(s); s.to_i if s &&! skip; end
+    def extract_hex(s); s.hex if s &&! skip; end
+    def extract_octal(s); s.oct if s &&! skip; end
+    def extract_integer(s); Integer(s) if s &&! skip; end
+    def extract_plain(s); s unless skip; end
+
+    def nil_proc(s); nil; end
+
+    public
+
+    def to_s
+      @spec_string
+    end
+
+    def count_space?
+      /(?:\A|\S)%\*?\d*c|\[/.match(@spec_string)
+    end
+
+    def initialize(str)
+      @spec_string = str
+      h = '[A-Fa-f0-9]'
+
+      @re_string, @handler = 
+        case @spec_string
+
+          # %[[:...:]]
+        when /%\*?(\[\[:[a-z]+:\]\])/
+          [ "(#{$1}+)", :extract_plain ]
+
+          # %5[[:...:]]
+        when /%\*?(\d+)(\[\[:[a-z]+:\]\])/
+          [ "(#{$2}{1,#{$1}})", :extract_plain ]
+
+          # %[...]
+        when /%\*?\[([^\]]*)\]/
+          yes = $1
+          if /^\^/.match(yes) then no = yes[1..-1] else no = '^' + yes end
+          [ "([#{yes}]+)(?=[#{no}]|\\z)", :extract_plain ]
+
+          # %5[...]
+        when /%\*?(\d+)\[([^\]]*)\]/
+          yes = $2
+          w = $1
+          [ "([#{yes}]{1,#{w}})", :extract_plain ]
+
+          # %i
+        when /%\*?i/
+          [ "([-+]?(?:(?:0[0-7]+)|(?:0[Xx]#{h}+)|(?:[1-9]\\d+)))", :extract_integer ]
+
+          # %5i
+        when /%\*?(\d+)i/
+          n = $1.to_i
+          s = "("
+          if n > 1 then s += "[1-9]\\d{1,#{n-1}}|" end
+          if n > 1 then s += "0[0-7]{1,#{n-1}}|" end
+          if n > 2 then s += "[-+]0[0-7]{1,#{n-2}}|" end
+          if n > 2 then s += "[-+][1-9]\\d{1,#{n-2}}|" end
+          if n > 2 then s += "0[Xx]#{h}{1,#{n-2}}|" end
+          if n > 3 then s += "[-+]0[Xx]#{h}{1,#{n-3}}|" end
+          s += "\\d"
+          s += ")"
+          [ s, :extract_integer ]
+
+          # %d, %u
+        when /%\*?[du]/
+          [ '([-+]?\d+)', :extract_decimal ]
+
+          # %5d, %5u
+        when /%\*?(\d+)[du]/
+          n = $1.to_i
+          s = "("
+          if n > 1 then s += "[-+]\\d{1,#{n-1}}|" end
+          s += "\\d{1,#{$1}})"
+          [ s, :extract_decimal ]
+
+          # %x
+        when /%\*?[Xx]/
+          [ "([-+]?(?:0[Xx])?#{h}+)", :extract_hex ]
+
+          # %5x
+        when /%\*?(\d+)[Xx]/
+          n = $1.to_i
+          s = "("
+          if n > 3 then s += "[-+]0[Xx]#{h}{1,#{n-3}}|" end
+          if n > 2 then s += "0[Xx]#{h}{1,#{n-2}}|" end
+          if n > 1 then s += "[-+]#{h}{1,#{n-1}}|" end
+          s += "#{h}{1,#{n}}"
+          s += ")"
+          [ s, :extract_hex ]
+
+          # %o
+        when /%\*?o/
+          [ '([-+]?[0-7]+)', :extract_octal ]
+
+          # %5o
+        when /%\*?(\d+)o/
+          [ "([-+][0-7]{1,#{$1.to_i-1}}|[0-7]{1,#{$1}})", :extract_octal ]
+
+          # %f
+        when /%\*?f/
+          [ '([-+]?((\d+(?>(?=[^\d.]|$)))|(\d*(\.(\d*([eE][-+]?\d+)?)))))', :extract_float ]
+
+          # %5f
+        when /%\*?(\d+)f/
+          [ "(\\S{1,#{$1}})", :extract_float ]
+
+          # %5s
+        when /%\*?(\d+)s/
+          [ "(\\S{1,#{$1}})", :extract_plain ]
+
+          # %s
+        when /%\*?s/
+          [ '(\S+)', :extract_plain ]
+
+          # %c
+        when /\s%\*?c/
+          [ "\\s*(.)", :extract_plain ]
+
+          # %c
+        when /%\*?c/
+          [ "(.)", :extract_plain ]
+
+          # %5c (whitespace issues are handled by the count_*_space? methods)
+        when /%\*?(\d+)c/
+          [ "(.{1,#{$1}})", :extract_plain ]
+
+          # %%
+        when /%%/
+          [ '(\s*%)', :nil_proc ]
+
+          # literal characters
+        else
+          [ "(#{Regexp.escape(@spec_string)})", :nil_proc ]
+        end
+
+      @re_string = '\A' + @re_string
+    end
+
+    def to_re
+      Regexp.new(@re_string,Regexp::MULTILINE)
+    end
+
+    def match(str)
+      @matched = false
+      s = str.dup
+      s.sub!(/\A\s+/,'') unless count_space?
+      res = to_re.match(s)
+      if res
+        @conversion = send(@handler, res[1])
+        @matched_string = @conversion.to_s
+        @matched = true
+      end
+      res
+    end
+
+    def letter
+      /%\*?\d*([a-z\[])/.match(@spec_string).to_a[1]
+    end
+
+    def width
+      w = /%\*?(\d+)/.match(@spec_string).to_a[1]
+      w && w.to_i
+    end
+
+    def mid_match?
+      return false unless @matched
+      cc_no_width    = letter == '[' &&! width
+      c_or_cc_width  = (letter == 'c' || letter == '[') && width
+      width_left     = c_or_cc_width && (matched_string.size < width)
+
+      return width_left || cc_no_width
+    end
+    
+  end
+
+  class FormatString
+
+    attr_reader :string_left, :last_spec_tried,
+                :last_match_tried, :matched_count, :space
+
+    SPECIFIERS = 'diuXxofeEgsc'
+    REGEX = /
+        # possible space, followed by...
+          (?:\s*
+          # percent sign, followed by...
+            %
+            # another percent sign, or...
+              (?:%|
+        	 # optional assignment suppression flag
+        	 \*?
+        	 # optional maximum field width
+        	 \d*
+        	   # named character class, ...
+        	   (?:\[\[:\w+:\]\]|
+        	   # traditional character class, or...
+        	      \[[^\]]*\]|
+        	   # specifier letter.
+        	      [#{SPECIFIERS}])))|
+            # or miscellaneous characters
+              [^%\s]+/ix
+
+    def initialize(str)
+      @specs = []
+      @i = 1
+      s = str.to_s
+      return unless /\S/.match(s)
+      @space = true if /\s\z/.match(s)
+      @specs.replace s.scan(REGEX).map {|spec| FormatSpecifier.new(spec) }
+    end
+
+    def to_s
+      @specs.join('')
+    end
+
+    def prune(n=matched_count)
+      n.times { @specs.shift }
+    end
+
+    def spec_count
+      @specs.size
+    end
+
+    def last_spec
+      @i == spec_count - 1
+    end
+
+    def match(str)
+      accum = []
+      @string_left = str
+      @matched_count = 0
+
+      @specs.each_with_index do |spec,@i|
+        @last_spec_tried = spec
+        @last_match_tried = spec.match(@string_left)
+        break unless @last_match_tried
+        @matched_count += 1
+
+        accum << spec.conversion
+
+        @string_left = @last_match_tried.post_match
+        break if @string_left.empty?
+      end
+      return accum.compact
+    end
+  end
+end
+
+class IO
+
+# The trick here is doing a match where you grab one *line*
+# of input at a time.  The linebreak may or may not occur
+# at the boundary where the string matches a format specifier.
+# And if it does, some rule about whitespace may or may not
+# be in effect...
+#
+# That's why this is much more elaborate than the string
+# version.
+#
+# For each line:
+# Match succeeds (non-emptily)
+# and the last attempted spec/string sub-match succeeded:
+#
+#   could the last spec keep matching?
+#     yes: save interim results and continue (next line)
+#
+# The last attempted spec/string did not match:
+#
+# are we on the next-to-last spec in the string?
+#   yes:
+#     is fmt_string.string_left all spaces?
+#       yes: does current spec care about input space?
+#         yes: fatal failure
+#         no: save interim results and continue
+#   no: continue  [this state could be analyzed further]
+#
+#
+
+  def scanf(str,&b)
+    return block_scanf(str,&b) if b
+    return [] unless str.size > 0
+
+    start_position = pos rescue 0
+    matched_so_far = 0
+    source_buffer = ""
+    result_buffer = []
+    final_result = []
+
+    fstr = Scanf::FormatString.new(str)
+
+    loop do
+      if eof || (tty? &&! fstr.match(source_buffer))
+        final_result.concat(result_buffer)
+        break
+      end
+
+      source_buffer << gets
+
+      current_match = fstr.match(source_buffer)
+
+      spec = fstr.last_spec_tried
+
+      if spec.matched
+        if spec.mid_match?
+          result_buffer.replace(current_match)
+          next
+        end
+
+      elsif (fstr.matched_count == fstr.spec_count - 1)
+        if /\A\s*\z/.match(fstr.string_left)
+          break if spec.count_space?
+          result_buffer.replace(current_match)
+          next
+        end
+      end
+
+      final_result.concat(current_match)
+
+      matched_so_far += source_buffer.size
+      source_buffer.replace(fstr.string_left)
+      matched_so_far -= source_buffer.size
+      break if fstr.last_spec
+      fstr.prune
+    end
+    seek(start_position + matched_so_far, IO::SEEK_SET) rescue Errno::ESPIPE
+    soak_up_spaces if fstr.last_spec && fstr.space
+
+    return final_result
+  end
+
+  private
+
+  def soak_up_spaces
+    c = getc
+    ungetc(c) if c
+    until eof ||! c || /\S/.match(c.chr)
+      c = getc
+    end
+    ungetc(c) if (c && /\S/.match(c.chr))
+  end
+
+  def block_scanf(str)
+    final = []
+# Sub-ideal, since another FS gets created in scanf.
+# But used here to determine the number of specifiers.
+    fstr = Scanf::FormatString.new(str)
+    last_spec = fstr.last_spec
+    begin
+      current = scanf(str)
+      break if current.empty?
+      final.push(yield(current))
+    end until eof || fstr.last_spec_tried == last_spec
+    return final
+  end
+end
+
+class String
+
+  def scanf(fstr,&b)
+    if b
+      block_scanf(fstr,&b)
+    else
+      fs = 
+        if fstr.is_a? Scanf::FormatString
+          fstr 
+        else 
+          Scanf::FormatString.new(fstr)
+        end
+      fs.match(self)
+    end
+  end
+
+  def block_scanf(fstr,&b)
+    fs = Scanf::FormatString.new(fstr)
+    str = self.dup
+    final = []
+    begin
+      current = str.scanf(fs)
+      final.push(yield(current)) unless current.empty?
+      str = fs.string_left
+    end until current.empty? || str.empty?
+    return final
+  end
+end
+
+module Kernel
+  private
+  def scanf(fs,&b)
+    STDIN.scanf(fs,&b)
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/set.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/set.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/set.rb	(revision 18425)
@@ -0,0 +1,1227 @@
+#!/usr/bin/env ruby
+#--
+# set.rb - defines the Set class
+#++
+# Copyright (c) 2002 Akinori MUSHA <knu@iDaemons.org>
+#
+# Documentation by Akinori MUSHA and Gavin Sinclair. 
+#
+# All rights reserved.  You can redistribute and/or modify it under the same
+# terms as Ruby.
+#
+#   $Id: set.rb 11980 2007-03-03 16:06:45Z knu $
+#
+# == Overview 
+# 
+# This library provides the Set class, which deals with a collection
+# of unordered values with no duplicates.  It is a hybrid of Array's
+# intuitive inter-operation facilities and Hash's fast lookup.  If you
+# need to keep values ordered, use the SortedSet class.
+#
+# The method +to_set+ is added to Enumerable for convenience.
+#
+# See the Set class for an example of usage.
+
+
+#
+# Set implements a collection of unordered values with no duplicates.
+# This is a hybrid of Array's intuitive inter-operation facilities and
+# Hash's fast lookup.
+#
+# Several methods accept any Enumerable object (implementing +each+)
+# for greater flexibility: new, replace, merge, subtract, |, &, -, ^.
+#
+# The equality of each couple of elements is determined according to
+# Object#eql? and Object#hash, since Set uses Hash as storage.
+#
+# Finally, if you are using class Set, you can also use Enumerable#to_set
+# for convenience.
+#
+# == Example
+#
+#   require 'set'
+#   s1 = Set.new [1, 2]                   # -> #<Set: {1, 2}>
+#   s2 = [1, 2].to_set                    # -> #<Set: {1, 2}>
+#   s1 == s2                              # -> true
+#   s1.add("foo")                         # -> #<Set: {1, 2, "foo"}>
+#   s1.merge([2, 6])                      # -> #<Set: {6, 1, 2, "foo"}>
+#   s1.subset? s2                         # -> false
+#   s2.subset? s1                         # -> true
+#
+class Set
+  include Enumerable
+
+  # Creates a new set containing the given objects.
+  def self.[](*ary)
+    new(ary)
+  end
+
+  # Creates a new set containing the elements of the given enumerable
+  # object.
+  #
+  # If a block is given, the elements of enum are preprocessed by the
+  # given block.
+  def initialize(enum = nil, &block) # :yields: o
+    @hash ||= Hash.new
+
+    enum.nil? and return
+
+    if block
+      enum.each { |o| add(block[o]) }
+    else
+      merge(enum)
+    end
+  end
+
+  # Copy internal hash.
+  def initialize_copy(orig)
+    @hash = orig.instance_eval{@hash}.dup
+  end
+
+  # Returns the number of elements.
+  def size
+    @hash.size
+  end
+  alias length size
+
+  # Returns true if the set contains no elements.
+  def empty?
+    @hash.empty?
+  end
+
+  # Removes all elements and returns self.
+  def clear
+    @hash.clear
+    self
+  end
+
+  # Replaces the contents of the set with the contents of the given
+  # enumerable object and returns self.
+  def replace(enum)
+    if enum.class == self.class
+      @hash.replace(enum.instance_eval { @hash })
+    else
+      enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
+      clear
+      enum.each { |o| add(o) }
+    end
+
+    self
+  end
+
+  # Converts the set to an array.  The order of elements is uncertain.
+  def to_a
+    @hash.keys
+  end
+
+  def flatten_merge(set, seen = Set.new)
+    set.each { |e|
+      if e.is_a?(Set)
+	if seen.include?(e_id = e.object_id)
+	  raise ArgumentError, "tried to flatten recursive Set"
+	end
+
+	seen.add(e_id)
+	flatten_merge(e, seen)
+	seen.delete(e_id)
+      else
+	add(e)
+      end
+    }
+
+    self
+  end
+  protected :flatten_merge
+
+  # Returns a new set that is a copy of the set, flattening each
+  # containing set recursively.
+  def flatten
+    self.class.new.flatten_merge(self)
+  end
+
+  # Equivalent to Set#flatten, but replaces the receiver with the
+  # result in place.  Returns nil if no modifications were made.
+  def flatten!
+    if detect { |e| e.is_a?(Set) }
+      replace(flatten())
+    else
+      nil
+    end
+  end
+
+  # Returns true if the set contains the given object.
+  def include?(o)
+    @hash.include?(o)
+  end
+  alias member? include?
+
+  # Returns true if the set is a superset of the given set.
+  def superset?(set)
+    set.is_a?(Set) or raise ArgumentError, "value must be a set"
+    return false if size < set.size
+    set.all? { |o| include?(o) }
+  end
+
+  # Returns true if the set is a proper superset of the given set.
+  def proper_superset?(set)
+    set.is_a?(Set) or raise ArgumentError, "value must be a set"
+    return false if size <= set.size
+    set.all? { |o| include?(o) }
+  end
+
+  # Returns true if the set is a subset of the given set.
+  def subset?(set)
+    set.is_a?(Set) or raise ArgumentError, "value must be a set"
+    return false if set.size < size
+    all? { |o| set.include?(o) }
+  end
+
+  # Returns true if the set is a proper subset of the given set.
+  def proper_subset?(set)
+    set.is_a?(Set) or raise ArgumentError, "value must be a set"
+    return false if set.size <= size
+    all? { |o| set.include?(o) }
+  end
+
+  # Calls the given block once for each element in the set, passing
+  # the element as parameter.
+  def each
+    @hash.each_key { |o| yield(o) }
+    self
+  end
+
+  # Adds the given object to the set and returns self.  Use +merge+ to
+  # add several elements at once.
+  def add(o)
+    @hash[o] = true
+    self
+  end
+  alias << add
+
+  # Adds the given object to the set and returns self.  If the
+  # object is already in the set, returns nil.
+  def add?(o)
+    if include?(o)
+      nil
+    else
+      add(o)
+    end
+  end
+
+  # Deletes the given object from the set and returns self.  Use +subtract+ to
+  # delete several items at once.
+  def delete(o)
+    @hash.delete(o)
+    self
+  end
+
+  # Deletes the given object from the set and returns self.  If the
+  # object is not in the set, returns nil.
+  def delete?(o)
+    if include?(o)
+      delete(o)
+    else
+      nil
+    end
+  end
+
+  # Deletes every element of the set for which block evaluates to
+  # true, and returns self.
+  def delete_if
+    @hash.delete_if { |o,| yield(o) }
+    self
+  end
+
+  # Do collect() destructively.
+  def collect!
+    set = self.class.new
+    each { |o| set << yield(o) }
+    replace(set)
+  end
+  alias map! collect!
+
+  # Equivalent to Set#delete_if, but returns nil if no changes were
+  # made.
+  def reject!
+    n = size
+    delete_if { |o| yield(o) }
+    size == n ? nil : self
+  end
+
+  # Merges the elements of the given enumerable object to the set and
+  # returns self.
+  def merge(enum)
+    if enum.is_a?(Set)
+      @hash.update(enum.instance_eval { @hash })
+    else
+      enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
+      enum.each { |o| add(o) }
+    end
+
+    self
+  end
+
+  # Deletes every element that appears in the given enumerable object
+  # and returns self.
+  def subtract(enum)
+    enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
+    enum.each { |o| delete(o) }
+    self
+  end
+
+  # Returns a new set built by merging the set and the elements of the
+  # given enumerable object.
+  def |(enum)
+    enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
+    dup.merge(enum)
+  end
+  alias + |		##
+  alias union |		##
+
+  # Returns a new set built by duplicating the set, removing every
+  # element that appears in the given enumerable object.
+  def -(enum)
+    enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
+    dup.subtract(enum)
+  end
+  alias difference -	##
+
+  # Returns a new set containing elements common to the set and the
+  # given enumerable object.
+  def &(enum)
+    enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
+    n = self.class.new
+    enum.each { |o| n.add(o) if include?(o) }
+    n
+  end
+  alias intersection &	##
+
+  # Returns a new set containing elements exclusive between the set
+  # and the given enumerable object.  (set ^ enum) is equivalent to
+  # ((set | enum) - (set & enum)).
+  def ^(enum)
+    enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
+    n = Set.new(enum)
+    each { |o| if n.include?(o) then n.delete(o) else n.add(o) end }
+    n
+  end
+
+  # Returns true if two sets are equal.  The equality of each couple
+  # of elements is defined according to Object#eql?.
+  def ==(set)
+    equal?(set) and return true
+
+    set.is_a?(Set) && size == set.size or return false
+
+    hash = @hash.dup
+    set.all? { |o| hash.include?(o) }
+  end
+
+  def hash	# :nodoc:
+    @hash.hash
+  end
+
+  def eql?(o)	# :nodoc:
+    return false unless o.is_a?(Set)
+    @hash.eql?(o.instance_eval{@hash})
+  end
+
+  # Classifies the set by the return value of the given block and
+  # returns a hash of {value => set of elements} pairs.  The block is
+  # called once for each element of the set, passing the element as
+  # parameter.
+  #
+  # e.g.:
+  #
+  #   require 'set'
+  #   files = Set.new(Dir.glob("*.rb"))
+  #   hash = files.classify { |f| File.mtime(f).year }
+  #   p hash    # => {2000=>#<Set: {"a.rb", "b.rb"}>,
+  #             #     2001=>#<Set: {"c.rb", "d.rb", "e.rb"}>,
+  #             #     2002=>#<Set: {"f.rb"}>}
+  def classify # :yields: o
+    h = {}
+
+    each { |i|
+      x = yield(i)
+      (h[x] ||= self.class.new).add(i)
+    }
+
+    h
+  end
+
+  # Divides the set into a set of subsets according to the commonality
+  # defined by the given block.
+  #
+  # If the arity of the block is 2, elements o1 and o2 are in common
+  # if block.call(o1, o2) is true.  Otherwise, elements o1 and o2 are
+  # in common if block.call(o1) == block.call(o2).
+  #
+  # e.g.:
+  #
+  #   require 'set'
+  #   numbers = Set[1, 3, 4, 6, 9, 10, 11]
+  #   set = numbers.divide { |i,j| (i - j).abs == 1 }
+  #   p set     # => #<Set: {#<Set: {1}>,
+  #             #            #<Set: {11, 9, 10}>,
+  #             #            #<Set: {3, 4}>,
+  #             #            #<Set: {6}>}>
+  def divide(&func)
+    if func.arity == 2
+      require 'tsort'
+
+      class << dig = {}		# :nodoc:
+	include TSort
+
+	alias tsort_each_node each_key
+	def tsort_each_child(node, &block)
+	  fetch(node).each(&block)
+	end
+      end
+
+      each { |u|
+	dig[u] = a = []
+	each{ |v| func.call(u, v) and a << v }
+      }
+
+      set = Set.new()
+      dig.each_strongly_connected_component { |css|
+	set.add(self.class.new(css))
+      }
+      set
+    else
+      Set.new(classify(&func).values)
+    end
+  end
+
+  InspectKey = :__inspect_key__         # :nodoc:
+
+  # Returns a string containing a human-readable representation of the
+  # set. ("#<Set: {element1, element2, ...}>")
+  def inspect
+    ids = (Thread.current[InspectKey] ||= [])
+
+    if ids.include?(object_id)
+      return sprintf('#<%s: {...}>', self.class.name)
+    end
+
+    begin
+      ids << object_id
+      return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2])
+    ensure
+      ids.pop
+    end
+  end
+
+  def pretty_print(pp)	# :nodoc:
+    pp.text sprintf('#<%s: {', self.class.name)
+    pp.nest(1) {
+      pp.seplist(self) { |o|
+	pp.pp o
+      }
+    }
+    pp.text "}>"
+  end
+
+  def pretty_print_cycle(pp)	# :nodoc:
+    pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...')
+  end
+end
+
+# SortedSet implements a set which elements are sorted in order.  See Set.
+class SortedSet < Set
+  @@setup = false
+
+  class << self
+    def [](*ary)	# :nodoc:
+      new(ary)
+    end
+
+    def setup	# :nodoc:
+      @@setup and return
+
+      module_eval {
+        # a hack to shut up warning
+        alias old_init initialize
+        remove_method :old_init
+      }
+      begin
+	require 'rbtree'
+
+	module_eval %{
+	  def initialize(*args, &block)
+	    @hash = RBTree.new
+	    super
+	  end
+	}
+      rescue LoadError
+	module_eval %{
+	  def initialize(*args, &block)
+	    @keys = nil
+	    super
+	  end
+
+	  def clear
+	    @keys = nil
+	    super
+	  end
+
+	  def replace(enum)
+	    @keys = nil
+	    super
+	  end
+
+	  def add(o)
+	    @keys = nil
+	    @hash[o] = true
+	    self
+	  end
+	  alias << add
+
+	  def delete(o)
+	    @keys = nil
+	    @hash.delete(o)
+	    self
+	  end
+
+	  def delete_if
+	    n = @hash.size
+	    @hash.delete_if { |o,| yield(o) }
+	    @keys = nil if @hash.size != n
+	    self
+	  end
+
+	  def merge(enum)
+	    @keys = nil
+	    super
+	  end
+
+	  def each
+	    to_a.each { |o| yield(o) }
+	  end
+
+	  def to_a
+	    (@keys = @hash.keys).sort! unless @keys
+	    @keys
+	  end
+	}
+      end
+
+      @@setup = true
+    end
+  end
+
+  def initialize(*args, &block)	# :nodoc:
+    SortedSet.setup
+    initialize(*args, &block)
+  end
+end
+
+module Enumerable
+  # Makes a set from the enumerable object with given arguments.
+  # Needs to +require "set"+ to use this method.
+  def to_set(klass = Set, *args, &block)
+    klass.new(self, *args, &block)
+  end
+end
+
+# =begin
+# == RestricedSet class
+# RestricedSet implements a set with restrictions defined by a given
+# block.
+# 
+# === Super class
+#     Set
+# 
+# === Class Methods
+# --- RestricedSet::new(enum = nil) { |o| ... }
+# --- RestricedSet::new(enum = nil) { |rset, o| ... }
+#     Creates a new restricted set containing the elements of the given
+#     enumerable object.  Restrictions are defined by the given block.
+# 
+#     If the block's arity is 2, it is called with the RestrictedSet
+#     itself and an object to see if the object is allowed to be put in
+#     the set.
+# 
+#     Otherwise, the block is called with an object to see if the object
+#     is allowed to be put in the set.
+# 
+# === Instance Methods
+# --- restriction_proc
+#     Returns the restriction procedure of the set.
+# 
+# =end
+# 
+# class RestricedSet < Set
+#   def initialize(*args, &block)
+#     @proc = block or raise ArgumentError, "missing a block"
+# 
+#     if @proc.arity == 2
+#       instance_eval %{
+# 	def add(o)
+# 	  @hash[o] = true if @proc.call(self, o)
+# 	  self
+# 	end
+# 	alias << add
+# 
+# 	def add?(o)
+# 	  if include?(o) || !@proc.call(self, o)
+# 	    nil
+# 	  else
+# 	    @hash[o] = true
+# 	    self
+# 	  end
+# 	end
+# 
+# 	def replace(enum)
+# 	  enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
+# 	  clear
+# 	  enum.each { |o| add(o) }
+# 
+# 	  self
+# 	end
+# 
+# 	def merge(enum)
+# 	  enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
+# 	  enum.each { |o| add(o) }
+# 
+# 	  self
+# 	end
+#       }
+#     else
+#       instance_eval %{
+# 	def add(o)
+#         if @proc.call(o)
+# 	    @hash[o] = true 
+#         end
+# 	  self
+# 	end
+# 	alias << add
+# 
+# 	def add?(o)
+# 	  if include?(o) || !@proc.call(o)
+# 	    nil
+# 	  else
+# 	    @hash[o] = true
+# 	    self
+# 	  end
+# 	end
+#       }
+#     end
+# 
+#     super(*args)
+#   end
+# 
+#   def restriction_proc
+#     @proc
+#   end
+# end
+
+if $0 == __FILE__
+  eval DATA.read, nil, $0, __LINE__+4
+end
+
+__END__
+
+require 'test/unit'
+
+class TC_Set < Test::Unit::TestCase
+  def test_aref
+    assert_nothing_raised {
+      Set[]
+      Set[nil]
+      Set[1,2,3]
+    }
+
+    assert_equal(0, Set[].size)
+    assert_equal(1, Set[nil].size)
+    assert_equal(1, Set[[]].size)
+    assert_equal(1, Set[[nil]].size)
+
+    set = Set[2,4,6,4]
+    assert_equal(Set.new([2,4,6]), set)
+  end
+
+  def test_s_new
+    assert_nothing_raised {
+      Set.new()
+      Set.new(nil)
+      Set.new([])
+      Set.new([1,2])
+      Set.new('a'..'c')
+      Set.new('XYZ')
+    }
+    assert_raises(ArgumentError) {
+      Set.new(false)
+    }
+    assert_raises(ArgumentError) {
+      Set.new(1)
+    }
+    assert_raises(ArgumentError) {
+      Set.new(1,2)
+    }
+
+    assert_equal(0, Set.new().size)
+    assert_equal(0, Set.new(nil).size)
+    assert_equal(0, Set.new([]).size)
+    assert_equal(1, Set.new([nil]).size)
+
+    ary = [2,4,6,4]
+    set = Set.new(ary)
+    ary.clear
+    assert_equal(false, set.empty?)
+    assert_equal(3, set.size)
+
+    ary = [1,2,3]
+
+    s = Set.new(ary) { |o| o * 2 }
+    assert_equal([2,4,6], s.sort)
+  end
+
+  def test_clone
+    set1 = Set.new
+    set2 = set1.clone
+    set1 << 'abc'
+    assert_equal(Set.new, set2)
+  end
+
+  def test_dup
+    set1 = Set[1,2]
+    set2 = set1.dup
+
+    assert_not_same(set1, set2)
+
+    assert_equal(set1, set2)
+
+    set1.add(3)
+
+    assert_not_equal(set1, set2)
+  end
+
+  def test_size
+    assert_equal(0, Set[].size)
+    assert_equal(2, Set[1,2].size)
+    assert_equal(2, Set[1,2,1].size)
+  end
+
+  def test_empty?
+    assert_equal(true, Set[].empty?)
+    assert_equal(false, Set[1, 2].empty?)
+  end
+
+  def test_clear
+    set = Set[1,2]
+    ret = set.clear
+
+    assert_same(set, ret)
+    assert_equal(true, set.empty?)
+  end
+
+  def test_replace
+    set = Set[1,2]
+    ret = set.replace('a'..'c')
+
+    assert_same(set, ret)
+    assert_equal(Set['a','b','c'], set)
+  end
+
+  def test_to_a
+    set = Set[1,2,3,2]
+    ary = set.to_a
+
+    assert_equal([1,2,3], ary.sort)
+  end
+
+  def test_flatten
+    # test1
+    set1 = Set[
+      1,
+      Set[
+	5,
+	Set[7,
+	  Set[0]
+	],
+	Set[6,2],
+	1
+      ],
+      3,
+      Set[3,4]
+    ]
+
+    set2 = set1.flatten
+    set3 = Set.new(0..7)
+
+    assert_not_same(set2, set1)
+    assert_equal(set3, set2)
+
+    # test2; destructive
+    orig_set1 = set1
+    set1.flatten!
+
+    assert_same(orig_set1, set1)
+    assert_equal(set3, set1)
+
+    # test3; multiple occurrences of a set in an set
+    set1 = Set[1, 2]
+    set2 = Set[set1, Set[set1, 4], 3]
+
+    assert_nothing_raised {
+      set2.flatten!
+    }
+
+    assert_equal(Set.new(1..4), set2)
+
+    # test4; recursion
+    set2 = Set[]
+    set1 = Set[1, set2]
+    set2.add(set1)
+
+    assert_raises(ArgumentError) {
+      set1.flatten!
+    }
+
+    # test5; miscellaneous
+    empty = Set[]
+    set =  Set[Set[empty, "a"],Set[empty, "b"]]
+
+    assert_nothing_raised {
+      set.flatten
+    }
+
+    set1 = empty.merge(Set["no_more", set])
+
+    assert_nil(Set.new(0..31).flatten!)
+
+    x = Set[Set[],Set[1,2]].flatten!
+    y = Set[1,2]
+
+    assert_equal(x, y)
+  end
+
+  def test_include?
+    set = Set[1,2,3]
+
+    assert_equal(true, set.include?(1))
+    assert_equal(true, set.include?(2))
+    assert_equal(true, set.include?(3))
+    assert_equal(false, set.include?(0))
+    assert_equal(false, set.include?(nil))
+
+    set = Set["1",nil,"2",nil,"0","1",false]
+    assert_equal(true, set.include?(nil))
+    assert_equal(true, set.include?(false))
+    assert_equal(true, set.include?("1"))
+    assert_equal(false, set.include?(0))
+    assert_equal(false, set.include?(true))
+  end
+
+  def test_superset?
+    set = Set[1,2,3]
+
+    assert_raises(ArgumentError) {
+      set.superset?()
+    }
+
+    assert_raises(ArgumentError) {
+      set.superset?(2)
+    }
+
+    assert_raises(ArgumentError) {
+      set.superset?([2])
+    }
+
+    assert_equal(true, set.superset?(Set[]))
+    assert_equal(true, set.superset?(Set[1,2]))
+    assert_equal(true, set.superset?(Set[1,2,3]))
+    assert_equal(false, set.superset?(Set[1,2,3,4]))
+    assert_equal(false, set.superset?(Set[1,4]))
+
+    assert_equal(true, Set[].superset?(Set[]))
+  end
+
+  def test_proper_superset?
+    set = Set[1,2,3]
+
+    assert_raises(ArgumentError) {
+      set.proper_superset?()
+    }
+
+    assert_raises(ArgumentError) {
+      set.proper_superset?(2)
+    }
+
+    assert_raises(ArgumentError) {
+      set.proper_superset?([2])
+    }
+
+    assert_equal(true, set.proper_superset?(Set[]))
+    assert_equal(true, set.proper_superset?(Set[1,2]))
+    assert_equal(false, set.proper_superset?(Set[1,2,3]))
+    assert_equal(false, set.proper_superset?(Set[1,2,3,4]))
+    assert_equal(false, set.proper_superset?(Set[1,4]))
+
+    assert_equal(false, Set[].proper_superset?(Set[]))
+  end
+
+  def test_subset?
+    set = Set[1,2,3]
+
+    assert_raises(ArgumentError) {
+      set.subset?()
+    }
+
+    assert_raises(ArgumentError) {
+      set.subset?(2)
+    }
+
+    assert_raises(ArgumentError) {
+      set.subset?([2])
+    }
+
+    assert_equal(true, set.subset?(Set[1,2,3,4]))
+    assert_equal(true, set.subset?(Set[1,2,3]))
+    assert_equal(false, set.subset?(Set[1,2]))
+    assert_equal(false, set.subset?(Set[]))
+
+    assert_equal(true, Set[].subset?(Set[1]))
+    assert_equal(true, Set[].subset?(Set[]))
+  end
+
+  def test_proper_subset?
+    set = Set[1,2,3]
+
+    assert_raises(ArgumentError) {
+      set.proper_subset?()
+    }
+
+    assert_raises(ArgumentError) {
+      set.proper_subset?(2)
+    }
+
+    assert_raises(ArgumentError) {
+      set.proper_subset?([2])
+    }
+
+    assert_equal(true, set.proper_subset?(Set[1,2,3,4]))
+    assert_equal(false, set.proper_subset?(Set[1,2,3]))
+    assert_equal(false, set.proper_subset?(Set[1,2]))
+    assert_equal(false, set.proper_subset?(Set[]))
+
+    assert_equal(false, Set[].proper_subset?(Set[]))
+  end
+
+  def test_each
+    ary = [1,3,5,7,10,20]
+    set = Set.new(ary)
+
+    assert_raises(LocalJumpError) {
+      set.each
+    }
+
+    assert_nothing_raised {
+      set.each { |o|
+	ary.delete(o) or raise "unexpected element: #{o}"
+      }
+
+      ary.empty? or raise "forgotten elements: #{ary.join(', ')}"
+    }
+  end
+
+  def test_add
+    set = Set[1,2,3]
+
+    ret = set.add(2)
+    assert_same(set, ret)
+    assert_equal(Set[1,2,3], set)
+
+    ret = set.add?(2)
+    assert_nil(ret)
+    assert_equal(Set[1,2,3], set)
+
+    ret = set.add(4)
+    assert_same(set, ret)
+    assert_equal(Set[1,2,3,4], set)
+
+    ret = set.add?(5)
+    assert_same(set, ret)
+    assert_equal(Set[1,2,3,4,5], set)
+  end
+
+  def test_delete
+    set = Set[1,2,3]
+
+    ret = set.delete(4)
+    assert_same(set, ret)
+    assert_equal(Set[1,2,3], set)
+
+    ret = set.delete?(4)
+    assert_nil(ret)
+    assert_equal(Set[1,2,3], set)
+
+    ret = set.delete(2)
+    assert_equal(set, ret)
+    assert_equal(Set[1,3], set)
+
+    ret = set.delete?(1)
+    assert_equal(set, ret)
+    assert_equal(Set[3], set)
+  end
+
+  def test_delete_if
+    set = Set.new(1..10)
+    ret = set.delete_if { |i| i > 10 }
+    assert_same(set, ret)
+    assert_equal(Set.new(1..10), set)
+
+    set = Set.new(1..10)
+    ret = set.delete_if { |i| i % 3 == 0 }
+    assert_same(set, ret)
+    assert_equal(Set[1,2,4,5,7,8,10], set)
+  end
+
+  def test_collect!
+    set = Set[1,2,3,'a','b','c',-1..1,2..4]
+
+    ret = set.collect! { |i|
+      case i
+      when Numeric
+	i * 2
+      when String
+	i.upcase
+      else
+	nil
+      end
+    }
+
+    assert_same(set, ret)
+    assert_equal(Set[2,4,6,'A','B','C',nil], set)
+  end
+
+  def test_reject!
+    set = Set.new(1..10)
+
+    ret = set.reject! { |i| i > 10 }
+    assert_nil(ret)
+    assert_equal(Set.new(1..10), set)
+
+    ret = set.reject! { |i| i % 3 == 0 }
+    assert_same(set, ret)
+    assert_equal(Set[1,2,4,5,7,8,10], set)
+  end
+
+  def test_merge
+    set = Set[1,2,3]
+
+    ret = set.merge([2,4,6])
+    assert_same(set, ret)
+    assert_equal(Set[1,2,3,4,6], set)
+  end
+
+  def test_subtract
+    set = Set[1,2,3]
+
+    ret = set.subtract([2,4,6])
+    assert_same(set, ret)
+    assert_equal(Set[1,3], set)
+  end
+
+  def test_plus
+    set = Set[1,2,3]
+
+    ret = set + [2,4,6]
+    assert_not_same(set, ret)
+    assert_equal(Set[1,2,3,4,6], ret)
+  end
+
+  def test_minus
+    set = Set[1,2,3]
+
+    ret = set - [2,4,6]
+    assert_not_same(set, ret)
+    assert_equal(Set[1,3], ret)
+  end
+
+  def test_and
+    set = Set[1,2,3,4]
+
+    ret = set & [2,4,6]
+    assert_not_same(set, ret)
+    assert_equal(Set[2,4], ret)
+  end
+
+  def test_xor
+    set = Set[1,2,3,4]
+    ret = set ^ [2,4,5,5]
+    assert_not_same(set, ret)
+    assert_equal(Set[1,3,5], ret)
+  end
+
+  def test_eq
+    set1 = Set[2,3,1]
+    set2 = Set[1,2,3]
+
+    assert_equal(set1, set1)
+    assert_equal(set1, set2)
+    assert_not_equal(Set[1], [1])
+
+    set1 = Class.new(Set)["a", "b"]
+    set2 = Set["a", "b", set1]
+    set1 = set1.add(set1.clone)
+
+#    assert_equal(set1, set2)
+#    assert_equal(set2, set1)
+    assert_equal(set2, set2.clone)
+    assert_equal(set1.clone, set1)
+
+    assert_not_equal(Set[Exception.new,nil], Set[Exception.new,Exception.new], "[ruby-dev:26127]")
+  end
+
+  # def test_hash
+  # end
+
+  # def test_eql?
+  # end
+
+  def test_classify
+    set = Set.new(1..10)
+    ret = set.classify { |i| i % 3 }
+
+    assert_equal(3, ret.size)
+    assert_instance_of(Hash, ret)
+    ret.each_value { |value| assert_instance_of(Set, value) }
+    assert_equal(Set[3,6,9], ret[0])
+    assert_equal(Set[1,4,7,10], ret[1])
+    assert_equal(Set[2,5,8], ret[2])
+  end
+
+  def test_divide
+    set = Set.new(1..10)
+    ret = set.divide { |i| i % 3 }
+
+    assert_equal(3, ret.size)
+    n = 0
+    ret.each { |s| n += s.size }
+    assert_equal(set.size, n)
+    assert_equal(set, ret.flatten)
+
+    set = Set[7,10,5,11,1,3,4,9,0]
+    ret = set.divide { |a,b| (a - b).abs == 1 }
+
+    assert_equal(4, ret.size)
+    n = 0
+    ret.each { |s| n += s.size }
+    assert_equal(set.size, n)
+    assert_equal(set, ret.flatten)
+    ret.each { |s|
+      if s.include?(0)
+	assert_equal(Set[0,1], s)
+      elsif s.include?(3)
+	assert_equal(Set[3,4,5], s)
+      elsif s.include?(7)
+	assert_equal(Set[7], s)
+      elsif s.include?(9)
+	assert_equal(Set[9,10,11], s)
+      else
+	raise "unexpected group: #{s.inspect}"
+      end
+    }
+  end
+
+  def test_inspect
+    set1 = Set[1]
+
+    assert_equal('#<Set: {1}>', set1.inspect)
+
+    set2 = Set[Set[0], 1, 2, set1]
+    assert_equal(false, set2.inspect.include?('#<Set: {...}>'))
+
+    set1.add(set2)
+    assert_equal(true, set1.inspect.include?('#<Set: {...}>'))
+  end
+
+  # def test_pretty_print
+  # end
+
+  # def test_pretty_print_cycle
+  # end
+end
+
+class TC_SortedSet < Test::Unit::TestCase
+  def test_sortedset
+    s = SortedSet[4,5,3,1,2]
+
+    assert_equal([1,2,3,4,5], s.to_a)
+
+    prev = nil
+    s.each { |o| assert(prev < o) if prev; prev = o }
+    assert_not_nil(prev)
+
+    s.map! { |o| -2 * o }
+
+    assert_equal([-10,-8,-6,-4,-2], s.to_a)
+
+    prev = nil
+    s.each { |o| assert(prev < o) if prev; prev = o }
+    assert_not_nil(prev)
+
+    s = SortedSet.new([2,1,3]) { |o| o * -2 }
+    assert_equal([-6,-4,-2], s.to_a)
+  end
+end
+
+class TC_Enumerable < Test::Unit::TestCase
+  def test_to_set
+    ary = [2,5,4,3,2,1,3]
+
+    set = ary.to_set
+    assert_instance_of(Set, set)
+    assert_equal([1,2,3,4,5], set.sort)
+
+    set = ary.to_set { |o| o * -2 }
+    assert_instance_of(Set, set)
+    assert_equal([-10,-8,-6,-4,-2], set.sort)
+
+    set = ary.to_set(SortedSet)
+    assert_instance_of(SortedSet, set)
+    assert_equal([1,2,3,4,5], set.to_a)
+
+    set = ary.to_set(SortedSet) { |o| o * -2 }
+    assert_instance_of(SortedSet, set)
+    assert_equal([-10,-8,-6,-4,-2], set.sort)
+  end
+end
+
+# class TC_RestricedSet < Test::Unit::TestCase
+#   def test_s_new
+#     assert_raises(ArgumentError) { RestricedSet.new }
+# 
+#     s = RestricedSet.new([-1,2,3]) { |o| o > 0 }
+#     assert_equal([2,3], s.sort)
+#   end
+# 
+#   def test_restriction_proc
+#     s = RestricedSet.new([-1,2,3]) { |o| o > 0 }
+# 
+#     f = s.restriction_proc
+#     assert_instance_of(Proc, f)
+#     assert(f[1])
+#     assert(!f[0])
+#   end
+# 
+#   def test_replace
+#     s = RestricedSet.new(-3..3) { |o| o > 0 }
+#     assert_equal([1,2,3], s.sort)
+# 
+#     s.replace([-2,0,3,4,5])
+#     assert_equal([3,4,5], s.sort)
+#   end
+# 
+#   def test_merge
+#     s = RestricedSet.new { |o| o > 0 }
+#     s.merge(-5..5)
+#     assert_equal([1,2,3,4,5], s.sort)
+# 
+#     s.merge([10,-10,-8,8])
+#     assert_equal([1,2,3,4,5,8,10], s.sort)
+#   end
+# end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/sha1.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/sha1.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/sha1.rb	(revision 18425)
@@ -0,0 +1,23 @@
+# just for compatibility; requiring "sha1" is obsoleted
+#
+# $RoughId: sha1.rb,v 1.4 2001/07/13 15:38:27 knu Exp $
+# $Id: sha1.rb 12008 2007-03-06 10:12:12Z knu $
+
+require 'digest/sha1'
+
+class SHA1 < Digest::SHA1
+  class << self
+    alias orig_new new
+    def new(str = nil)
+      if str
+        orig_new.update(str)
+      else
+        orig_new
+      end
+    end
+
+    def sha1(*args)
+      new(*args)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell.rb	(revision 18425)
@@ -0,0 +1,269 @@
+#
+#   shell.rb - 
+#   	$Release Version: 0.6.0 $
+#   	$Revision: 1.8 $
+#   	$Date: 2001/03/19 09:01:11 $
+#   	by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#   
+#
+
+require "e2mmap"
+require "thread"
+
+require "shell/error"
+require "shell/command-processor"
+require "shell/process-controller"
+
+class Shell
+  @RCS_ID='-$Id: shell.rb,v 1.8 2001/03/19 09:01:11 keiju Exp keiju $-'
+
+  include Error
+  extend Exception2MessageMapper
+
+#  @cascade = true
+  # debug: true -> normal debug
+  # debug: 1    -> eval definition debug
+  # debug: 2    -> detail inspect debug
+  @debug = false
+  @verbose = true
+
+  class << Shell
+    attr :cascade, true
+    attr :debug, true
+    attr :verbose, true
+
+#    alias cascade? cascade
+    alias debug? debug
+    alias verbose? verbose
+    @verbose = true
+
+    def debug=(val)
+      @debug = val
+      @verbose = val if val
+    end
+
+    def cd(path)
+      sh = new
+      sh.cd path
+      sh
+    end
+
+    def default_system_path
+      if @default_system_path
+	@default_system_path
+      else
+	ENV["PATH"].split(":")
+      end
+    end
+
+    def default_system_path=(path)
+      @default_system_path = path
+    end
+
+    def default_record_separator
+      if @default_record_separator
+	@default_record_separator
+      else
+	$/
+      end
+    end
+
+    def default_record_separator=(rs)
+      @default_record_separator = rs
+    end
+  end
+
+  def initialize
+    @cwd = Dir.pwd
+    @dir_stack = []
+    @umask = nil
+
+    @system_path = Shell.default_system_path
+    @record_separator = Shell.default_record_separator
+
+    @command_processor = CommandProcessor.new(self)
+    @process_controller = ProcessController.new(self)
+
+    @verbose = Shell.verbose
+    @debug = Shell.debug
+  end
+
+  attr_reader :system_path
+
+  def system_path=(path)
+    @system_path = path
+    rehash
+  end
+
+  attr :umask, true
+  attr :record_separator, true
+
+  attr :verbose, true
+  attr :debug, true
+
+  def debug=(val)
+    @debug = val
+    @verbose = val if val
+  end
+
+  alias verbose? verbose
+  alias debug? debug
+
+  attr_reader :command_processor
+  attr_reader :process_controller
+
+  def expand_path(path)
+    File.expand_path(path, @cwd)
+  end
+
+  # Most Shell commands are defined via CommandProcessor
+
+  #
+  # Dir related methods
+  #
+  # Shell#cwd/dir/getwd/pwd
+  # Shell#chdir/cd
+  # Shell#pushdir/pushd
+  # Shell#popdir/popd
+  # Shell#mkdir
+  # Shell#rmdir
+
+  attr :cwd
+  alias dir cwd
+  alias getwd cwd
+  alias pwd cwd
+
+  attr :dir_stack
+  alias dirs dir_stack
+
+  # If called as iterator, it restores the current directory when the
+  # block ends.
+  def chdir(path = nil)
+    if iterator?
+      cwd_old = @cwd
+      begin
+	chdir(path)
+	yield
+      ensure
+	chdir(cwd_old)
+      end
+    else
+      path = "~" unless path
+      @cwd = expand_path(path)
+      notify "current dir: #{@cwd}"
+      rehash
+      self
+    end
+  end
+  alias cd chdir
+
+  def pushdir(path = nil)
+    if iterator?
+      pushdir(path)
+      begin
+	yield
+      ensure
+	popdir
+      end
+    elsif path
+      @dir_stack.push @cwd
+      chdir path
+      notify "dir stack: [#{@dir_stack.join ', '}]"
+      self
+    else
+      if pop = @dir_stack.pop
+	@dir_stack.push @cwd
+	chdir pop
+	notify "dir stack: [#{@dir_stack.join ', '}]"
+	self
+      else
+	Shell.Fail DirStackEmpty
+      end
+    end
+  end
+  alias pushd pushdir
+
+  def popdir
+    if pop = @dir_stack.pop
+      chdir pop
+      notify "dir stack: [#{@dir_stack.join ', '}]"
+      self
+    else
+      Shell.Fail DirStackEmpty
+    end
+  end
+  alias popd popdir
+
+
+  #
+  # process management
+  #
+  def jobs
+    @process_controller.jobs
+  end
+
+  def kill(sig, command)
+    @process_controller.kill_job(sig, command)
+  end
+
+  #
+  # command definitions
+  #
+  def Shell.def_system_command(command, path = command)
+    CommandProcessor.def_system_command(command, path)
+  end
+
+  def Shell.undef_system_command(command)
+    CommandProcessor.undef_system_command(command)
+  end
+
+  def Shell.alias_command(ali, command, *opts, &block)
+    CommandProcessor.alias_command(ali, command, *opts, &block)
+  end
+
+  def Shell.unalias_command(ali)
+    CommandProcessor.unalias_command(ali)
+  end
+
+  def Shell.install_system_commands(pre = "sys_")
+    CommandProcessor.install_system_commands(pre)
+  end
+
+  #
+  def inspect
+    if debug.kind_of?(Integer) && debug > 2
+      super
+    else
+      to_s
+    end
+  end
+
+  def self.notify(*opts, &block)
+    Thread.exclusive do
+    if opts[-1].kind_of?(String)
+      yorn = verbose?
+    else
+      yorn = opts.pop
+    end
+    return unless yorn
+
+    _head = true
+    print opts.collect{|mes|
+      mes = mes.dup
+      yield mes if iterator?
+      if _head
+	_head = false
+	"shell: " + mes
+      else
+	"       " + mes
+      end
+    }.join("\n")+"\n"
+    end
+  end
+
+  CommandProcessor.initialize
+  CommandProcessor.run_config
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/builtin-command.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/builtin-command.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/builtin-command.rb	(revision 18425)
@@ -0,0 +1,154 @@
+#
+#   shell/builtin-command.rb - 
+#   	$Release Version: 0.6.0 $
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
+#
+# --
+#
+#   
+#
+
+require "shell/filter"
+
+class Shell
+  class BuiltInCommand<Filter
+    def wait?
+      false
+    end
+    def active?
+      true
+    end
+  end
+
+  class Echo < BuiltInCommand
+    def initialize(sh, *strings)
+      super sh
+      @strings = strings
+    end
+    
+    def each(rs = nil)
+      rs =  @shell.record_separator unless rs
+      for str  in @strings
+	yield str + rs
+      end
+    end
+  end
+
+  class Cat < BuiltInCommand
+    def initialize(sh, *filenames)
+      super sh
+      @cat_files = filenames
+    end
+
+    def each(rs = nil)
+      if @cat_files.empty?
+	super
+      else
+	for src in @cat_files
+	  @shell.foreach(src, rs){|l| yield l}
+	end
+      end
+    end
+  end
+
+  class Glob < BuiltInCommand
+    def initialize(sh, pattern)
+      super sh
+
+      @pattern = pattern
+      Thread.critical = true
+      back = Dir.pwd
+      begin
+	Dir.chdir @shell.cwd
+	@files = Dir[pattern]
+      ensure
+	Dir.chdir back
+	Thread.critical = false
+      end
+    end
+
+    def each(rs = nil)
+      rs =  @shell.record_separator unless rs
+      for f  in @files
+	yield f+rs
+      end
+    end
+  end
+
+#   class Sort < Cat
+#     def initialize(sh, *filenames)
+#       super
+#     end
+#
+#     def each(rs = nil)
+#       ary = []
+#       super{|l|	ary.push l}
+#       for l in ary.sort!
+# 	yield l
+#       end
+#     end
+#   end
+
+  class AppendIO < BuiltInCommand
+    def initialize(sh, io, filter)
+      super sh
+      @input = filter
+      @io = io
+    end
+
+    def input=(filter)
+      @input.input=filter
+      for l in @input
+	@io << l
+      end
+    end
+
+  end
+
+  class AppendFile < AppendIO
+    def initialize(sh, to_filename, filter)
+      @file_name = to_filename
+      io = sh.open(to_filename, "a")
+      super(sh, io, filter)
+    end
+
+    def input=(filter)
+      begin
+	super
+      ensure
+	@io.close
+      end
+    end
+  end
+
+  class Tee < BuiltInCommand
+    def initialize(sh, filename)
+      super sh
+      @to_filename = filename
+    end
+
+    def each(rs = nil)
+      to = @shell.open(@to_filename, "w")
+      begin
+	super{|l| to << l; yield l}
+      ensure
+	to.close
+      end
+    end
+  end
+
+  class Concat < BuiltInCommand
+    def initialize(sh, *jobs)
+      super(sh)
+      @jobs = jobs
+    end
+
+    def each(rs = nil)
+      while job = @jobs.shift
+	job.each{|l| yield l}
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/command-processor.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/command-processor.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/command-processor.rb	(revision 18425)
@@ -0,0 +1,592 @@
+#
+#   shell/command-controller.rb - 
+#   	$Release Version: 0.6.0 $
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#   
+#
+
+require "e2mmap"
+require "ftools"
+require "thread"
+
+require "shell/error"
+require "shell/filter"
+require "shell/system-command"
+require "shell/builtin-command"
+
+class Shell
+  class CommandProcessor
+#    include Error
+
+    #
+    # initialize of Shell and related classes.
+    #
+    NoDelegateMethods = ["initialize", "expand_path"]
+    def self.initialize
+
+      install_builtin_commands
+
+      # define CommandProccessor#methods to Shell#methods and Filter#methods
+      for m in CommandProcessor.instance_methods(false) - NoDelegateMethods
+	add_delegate_command_to_shell(m)
+      end
+      
+      def self.method_added(id)
+	add_delegate_command_to_shell(id)
+      end
+    end
+
+    #
+    # include run file.
+    #
+    def self.run_config
+      begin
+	load File.expand_path("~/.rb_shell") if ENV.key?("HOME")
+      rescue LoadError, Errno::ENOENT
+      rescue
+	print "load error: #{rc}\n"
+	print $!.class, ": ", $!, "\n"
+	for err in $@[0, $@.size - 2]
+	  print "\t", err, "\n"
+	end
+      end
+    end
+
+    def initialize(shell)
+      @shell = shell
+      @system_commands = {}
+    end
+
+    #
+    # CommandProcessor#expand_path(path)
+    #	  path:	  String
+    #	  return: String
+    #	returns the absolute path for <path>
+    #
+    def expand_path(path)
+      @shell.expand_path(path)
+    end
+
+    #
+    # File related commands
+    # Shell#foreach
+    # Shell#open
+    # Shell#unlink
+    # Shell#test
+    #
+    # -
+    #	
+    # CommandProcessor#foreach(path, rs)
+    #	  path: String
+    #	  rs:	String - record separator
+    #	  iterator
+    #	Same as:
+    #	  File#foreach (when path is file)
+    #	  Dir#foreach (when path is directory)
+    #	path is relative to pwd
+    #
+    def foreach(path = nil, *rs)
+      path = "." unless path
+      path = expand_path(path)
+
+      if File.directory?(path)
+	Dir.foreach(path){|fn| yield fn}
+      else
+	IO.foreach(path, *rs){|l| yield l}
+      end
+    end
+
+    #
+    # CommandProcessor#open(path, mode)
+    #	  path:	  String
+    #	  mode:	  String
+    #	  return: File or Dir
+    #	Same as:
+    #	  File#open (when path is file)
+    #	  Dir#open  (when path is directory)
+    #	mode has an effect only when path is a file
+    #
+    def open(path, mode)
+      path = expand_path(path)
+      if File.directory?(path)
+	Dir.open(path)
+      else
+	effect_umask do
+	  File.open(path, mode)
+	end
+      end
+    end
+    #  public :open
+
+    #
+    # CommandProcessor#unlink(path)
+    #	same as:
+    #	  Dir#unlink  (when path is directory)
+    #	  File#unlink (when path is file)
+    #
+    def unlink(path)
+      path = expand_path(path)
+      if File.directory?(path)
+	Dir.unlink(path)
+      else
+	IO.unlink(path)
+      end
+    end
+
+    #
+    # CommandProcessor#test(command, file1, file2)
+    # CommandProcessor#[command, file1, file2]
+    #	  command: char or String or Symbol
+    #	  file1:   String
+    #	  file2:   String(optional)
+    #	  return: Boolean
+    #	same as:
+    #	  test()	   (when command is char or length 1 string or symbol)
+    #	  FileTest.command (others)
+    #	example:
+    #	  sh[?e, "foo"]
+    #	  sh[:e, "foo"]
+    #	  sh["e", "foo"]
+    #	  sh[:exists?, "foo"]
+    #	  sh["exists?", "foo"]
+    #	  
+    def test(command, file1, file2=nil)
+      file1 = expand_path(file1)
+      file2 = expand_path(file2) if file2
+      command = command.id2name if command.kind_of?(Symbol)
+
+      case command
+      when Integer
+	top_level_test(command, file1, file2)
+      when String
+	if command.size == 1
+	  if file2
+	    top_level_test(command, file1, file2)
+	  else
+	    top_level_test(command, file1)
+	  end
+	else
+	  if file2
+	    FileTest.send(command, file1, file2)
+	  else
+	    FileTest.send(command, file1)
+	  end
+	end
+      end
+    end
+    alias [] test
+
+    #
+    # Dir related methods
+    #
+    # Shell#mkdir
+    # Shell#rmdir
+    #
+    #--
+    #
+    # CommandProcessor#mkdir(*path)
+    #	  path: String
+    #	same as Dir.mkdir()
+    #	  
+    def mkdir(*path)
+      for dir in path
+	Dir.mkdir(expand_path(dir))
+      end
+    end
+
+    #
+    # CommandProcessor#rmdir(*path)
+    #	  path: String
+    #	same as Dir.rmdir()
+    #	  
+    def rmdir(*path)
+      for dir in path
+	Dir.rmdir(expand_path(dir))
+      end
+    end
+
+    #
+    # CommandProcessor#system(command, *opts)
+    #	  command: String
+    #	  opts:	   String
+    #	  return:  SystemCommand
+    #	Same as system() function
+    #	example:
+    #	  print sh.system("ls", "-l")
+    #	  sh.system("ls", "-l") | sh.head > STDOUT
+    # 
+    def system(command, *opts)
+      if opts.empty?
+	if command =~ /\*|\?|\{|\}|\[|\]|<|>|\(|\)|~|&|\||\\|\$|;|'|`|"|\n/
+	  return SystemCommand.new(@shell, find_system_command("sh"), "-c", command)
+	else
+	  command, *opts = command.split(/\s+/)
+	end
+      end
+      SystemCommand.new(@shell, find_system_command(command), *opts)
+    end
+
+    #
+    # ProcessCommand#rehash
+    #	clear command hash table.
+    #
+    def rehash
+      @system_commands = {}
+    end
+
+    #
+    # ProcessCommand#transact
+    #
+    def check_point
+      @shell.process_controller.wait_all_jobs_execution
+    end
+    alias finish_all_jobs check_point
+
+    def transact(&block)
+      begin
+	@shell.instance_eval(&block)
+      ensure
+	check_point
+      end
+    end
+
+    #
+    # internal commands
+    #
+    def out(dev = STDOUT, &block)
+      dev.print transact(&block)
+    end
+
+    def echo(*strings)
+      Echo.new(@shell, *strings)
+    end
+
+    def cat(*filenames)
+      Cat.new(@shell, *filenames)
+    end
+
+    #   def sort(*filenames)
+    #     Sort.new(self, *filenames)
+    #   end
+
+    def glob(pattern)
+      Glob.new(@shell, pattern)
+    end
+
+    def append(to, filter)
+      case to
+      when String
+	AppendFile.new(@shell, to, filter)
+      when IO
+	AppendIO.new(@shell, to, filter)
+      else
+	Shell.Fail Error::CantApplyMethod, "append", to.class
+      end
+    end
+
+    def tee(file)
+      Tee.new(@shell, file)
+    end
+
+    def concat(*jobs)
+      Concat.new(@shell, *jobs)
+    end
+
+    # %pwd, %cwd -> @pwd
+    def notify(*opts, &block)
+      Thread.exclusive do
+	Shell.notify(*opts) {|mes|
+	  yield mes if iterator?
+	
+	  mes.gsub!("%pwd", "#{@cwd}")
+	  mes.gsub!("%cwd", "#{@cwd}")
+	}
+      end
+    end
+
+    #
+    # private functions
+    #
+    def effect_umask
+      if @shell.umask
+	Thread.critical = true
+	save = File.umask
+	begin
+	  yield
+	ensure
+	  File.umask save
+	  Thread.critical = false
+	end
+      else
+	yield
+      end
+    end
+    private :effect_umask
+
+    def find_system_command(command)
+      return command if /^\// =~ command
+      case path = @system_commands[command]
+      when String
+	if exists?(path)
+	  return path
+	else
+	  Shell.Fail Error::CommandNotFound, command
+	end
+      when false
+	Shell.Fail Error::CommandNotFound, command
+      end
+
+      for p in @shell.system_path
+	path = join(p, command)
+	if FileTest.exists?(path)
+	  @system_commands[command] = path
+	  return path
+	end
+      end
+      @system_commands[command] = false
+      Shell.Fail Error::CommandNotFound, command
+    end
+
+    #
+    # CommandProcessor.def_system_command(command, path)
+    #	  command:  String
+    #	  path:	    String
+    #	define 'command()' method as method.
+    #
+    def self.def_system_command(command, path = command)
+      begin
+	eval((d = %Q[def #{command}(*opts)
+     	          SystemCommand.new(@shell, '#{path}', *opts)
+               end]), nil, __FILE__, __LINE__ - 1)
+      rescue SyntaxError
+	Shell.notify "warn: Can't define #{command} path: #{path}." 
+      end
+      Shell.notify "Define #{command} path: #{path}.", Shell.debug?
+      Shell.notify("Definition of #{command}: ", d, 
+	     Shell.debug.kind_of?(Integer) && Shell.debug > 1)
+    end
+
+    def self.undef_system_command(command)
+      command = command.id2name if command.kind_of?(Symbol)
+      remove_method(command)
+      Shell.module_eval{remove_method(command)}
+      Filter.module_eval{remove_method(command)}
+      self
+    end
+
+    # define command alias
+    # ex)
+    # def_alias_command("ls_c", "ls", "-C", "-F")
+    # def_alias_command("ls_c", "ls"){|*opts| ["-C", "-F", *opts]}
+    #
+    @alias_map = {}
+    def self.alias_map
+      @alias_map
+    end
+    def self.alias_command(ali, command, *opts, &block)
+      ali = ali.id2name if ali.kind_of?(Symbol)
+      command = command.id2name if command.kind_of?(Symbol)
+      begin
+	if iterator?
+	  @alias_map[ali.intern] = proc
+
+	  eval((d = %Q[def #{ali}(*opts)
+                          @shell.__send__(:#{command},
+                                          *(CommandProcessor.alias_map[:#{ali}].call *opts))
+	                end]), nil, __FILE__, __LINE__ - 1)
+    
+	else
+           args = opts.collect{|opt| '"' + opt + '"'}.join(",")
+           eval((d = %Q[def #{ali}(*opts)
+                          @shell.__send__(:#{command}, #{args}, *opts)
+                        end]), nil, __FILE__, __LINE__ - 1)
+	end
+      rescue SyntaxError
+	Shell.notify "warn: Can't alias #{ali} command: #{command}." 
+	Shell.notify("Definition of #{ali}: ", d)
+	raise
+      end
+      Shell.notify "Define #{ali} command: #{command}.", Shell.debug?
+      Shell.notify("Definition of #{ali}: ", d, 
+	     Shell.debug.kind_of?(Integer) && Shell.debug > 1)
+      self
+    end
+   
+    def self.unalias_command(ali)
+      ali = ali.id2name if ali.kind_of?(Symbol)
+      @alias_map.delete ali.intern
+      undef_system_command(ali)
+    end
+   
+    #
+    # CommandProcessor.def_builtin_commands(delegation_class, command_specs)
+    #	  delegation_class: Class or Module
+    #	  command_specs: [[command_name, [argument,...]],...]
+    #	     command_name: String
+    #	     arguments:	   String
+    #		FILENAME?? -> expand_path(filename??)
+    #		*FILENAME?? -> filename??.collect{|f|expand_path(f)}.join(", ")
+    #	define command_name(argument,...) as
+    #	    delegation_class.command_name(argument,...)
+    #
+    def self.def_builtin_commands(delegation_class, command_specs)
+      for meth, args in command_specs
+	arg_str = args.collect{|arg| arg.downcase}.join(", ")
+	call_arg_str = args.collect{
+	  |arg|
+	  case arg
+	  when /^(FILENAME.*)$/
+	    format("expand_path(%s)", $1.downcase)
+	  when /^(\*FILENAME.*)$/
+	    # \*FILENAME* -> filenames.collect{|fn| expand_path(fn)}.join(", ")
+	    $1.downcase + '.collect{|fn| expand_path(fn)}'
+	  else
+	    arg
+	  end
+	}.join(", ")
+	d = %Q[def #{meth}(#{arg_str})
+		    #{delegation_class}.#{meth}(#{call_arg_str})
+		 end]
+	Shell.notify "Define #{meth}(#{arg_str})", Shell.debug?
+	Shell.notify("Definition of #{meth}: ", d, 
+	     Shell.debug.kind_of?(Integer) && Shell.debug > 1)
+	eval d
+      end
+    end
+
+    #
+    # CommandProcessor.install_system_commands(pre)
+    #	    pre: String - command name prefix
+    # defines every command which belongs in default_system_path via
+    # CommandProcessor.command().  It doesn't define already defined
+    # methods twice.  By default, "pre_" is prefixes to each method
+    # name.  Characters that may not be used in a method name are
+    # all converted to '_'.  Definition errors are just ignored.
+    #
+    def self.install_system_commands(pre = "sys_")
+      defined_meth = {}
+      for m in Shell.methods
+	defined_meth[m] = true
+      end
+      sh = Shell.new
+      for path in Shell.default_system_path
+	next unless sh.directory? path
+	sh.cd path
+	sh.foreach do
+	  |cn|
+	  if !defined_meth[pre + cn] && sh.file?(cn) && sh.executable?(cn)
+	    command = (pre + cn).gsub(/\W/, "_").sub(/^([0-9])/, '_\1')
+	    begin
+	      def_system_command(command, sh.expand_path(cn))
+	    rescue
+	      Shell.notify "warn: Can't define #{command} path: #{cn}"
+	    end
+	    defined_meth[command] = command
+	  end
+	end
+      end
+    end
+
+    #----------------------------------------------------------------------
+    #
+    #  class initializing methods  - 
+    #
+    #----------------------------------------------------------------------
+    def self.add_delegate_command_to_shell(id)
+      id = id.intern if id.kind_of?(String)
+      name = id.id2name
+      if Shell.method_defined?(id)
+	Shell.notify "warn: override definnition of Shell##{name}."
+	Shell.notify "warn: alias Shell##{name} to Shell##{name}_org.\n"
+	Shell.module_eval "alias #{name}_org #{name}"
+      end
+      Shell.notify "method added: Shell##{name}.", Shell.debug?
+      Shell.module_eval(%Q[def #{name}(*args, &block)
+			    begin
+			      @command_processor.__send__(:#{name}, *args, &block)
+			    rescue Exception
+			      $@.delete_if{|s| /:in `__getobj__'$/ =~ s} #`
+	                      $@.delete_if{|s| /^\\(eval\\):/ =~ s}
+			    raise
+			    end
+                          end], __FILE__, __LINE__)
+
+      if Shell::Filter.method_defined?(id)
+	Shell.notify "warn: override definnition of Shell::Filter##{name}."
+	Shell.notify "warn: alias Shell##{name} to Shell::Filter##{name}_org."
+	Filter.module_eval "alias #{name}_org #{name}"
+      end
+      Shell.notify "method added: Shell::Filter##{name}.", Shell.debug?
+      Filter.module_eval(%Q[def #{name}(*args, &block)
+			    begin
+			      self | @shell.__send__(:#{name}, *args, &block)
+			    rescue Exception
+			      $@.delete_if{|s| /:in `__getobj__'$/ =~ s} #`
+	                      $@.delete_if{|s| /^\\(eval\\):/ =~ s}
+			    raise
+			    end
+                          end], __FILE__, __LINE__)
+    end
+
+    #
+    # define default builtin commands
+    #
+    def self.install_builtin_commands
+      # method related File.
+      #	(exclude open/foreach/unlink)
+      normal_delegation_file_methods = [
+	["atime", ["FILENAME"]],
+	["basename", ["fn", "*opts"]],
+	["chmod", ["mode", "*FILENAMES"]], 
+	["chown", ["owner", "group", "*FILENAME"]],
+	["ctime", ["FILENAMES"]],
+	["delete", ["*FILENAMES"]],
+	["dirname", ["FILENAME"]],
+	["ftype", ["FILENAME"]],
+	["join", ["*items"]],
+	["link", ["FILENAME_O", "FILENAME_N"]],
+	["lstat", ["FILENAME"]],
+	["mtime", ["FILENAME"]],
+	["readlink", ["FILENAME"]],
+	["rename", ["FILENAME_FROM", "FILENAME_TO"]],
+	#      ["size", ["FILENAME"]],
+	["split", ["pathname"]],
+	["stat", ["FILENAME"]],
+	["symlink", ["FILENAME_O", "FILENAME_N"]],
+	["truncate", ["FILENAME", "length"]],
+	["utime", ["atime", "mtime", "*FILENAMES"]]]
+
+      def_builtin_commands(File, normal_delegation_file_methods)
+      alias_method :rm, :delete
+
+      # method related FileTest
+      def_builtin_commands(FileTest, 
+		   FileTest.singleton_methods(false).collect{|m| [m, ["FILENAME"]]})
+
+      # method related ftools
+      normal_delegation_ftools_methods = [
+	["syscopy", ["FILENAME_FROM", "FILENAME_TO"]],
+	["copy", ["FILENAME_FROM", "FILENAME_TO"]],
+	["move", ["FILENAME_FROM", "FILENAME_TO"]],
+	["compare", ["FILENAME_FROM", "FILENAME_TO"]],
+	["safe_unlink", ["*FILENAMES"]],
+	["makedirs", ["*FILENAMES"]],
+	#    ["chmod", ["mode", "*FILENAMES"]],
+	["install", ["FILENAME_FROM", "FILENAME_TO", "mode"]],
+      ]
+      def_builtin_commands(File,
+		   normal_delegation_ftools_methods)
+      alias_method :cmp, :compare
+      alias_method :mv, :move
+      alias_method :cp, :copy
+      alias_method :rm_f, :safe_unlink
+      alias_method :mkpath, :makedirs
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/error.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/error.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/error.rb	(revision 18425)
@@ -0,0 +1,26 @@
+#
+#   shell/error.rb - 
+#   	$Release Version: 0.6.0 $
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
+#
+# --
+#
+#   
+#
+
+require "e2mmap"
+
+class Shell
+  module Error
+    extend Exception2MessageMapper
+    def_e2message TypeError, "wrong argument type %s (expected %s)"
+
+    def_exception :DirStackEmpty, "Directory stack empty."
+    def_exception :CantDefine, "Can't define method(%s, %s)."
+    def_exception :CantApplyMethod, "This method(%s) does not apply to this type(%s)."
+    def_exception :CommandNotFound, "Command not found(%s)."
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/filter.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/filter.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/filter.rb	(revision 18425)
@@ -0,0 +1,110 @@
+#
+#   shell/filter.rb - 
+#   	$Release Version: 0.6.0 $
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
+#
+# --
+#
+#   
+#
+
+class Shell
+  #
+  # Filter
+  # A method to require
+  #    each()
+  #
+  class Filter
+    include Enumerable
+
+    def initialize(sh)
+      @shell = sh	  # parent shell
+      @input = nil	  # input filter
+    end
+
+    attr_reader :input
+
+    def input=(filter)
+      @input = filter
+    end
+    
+    def each(rs = nil)
+      rs = @shell.record_separator unless rs
+      if @input
+	@input.each(rs){|l| yield l}
+      end
+    end
+
+    def < (src)
+      case src
+      when String
+	cat = Cat.new(@shell, src)
+	cat | self
+      when IO
+	self.input = src
+	self
+      else
+	Shell.Fail Error::CantApplyMethod, "<", to.class
+      end
+    end
+
+    def > (to)
+      case to
+      when String
+	dst = @shell.open(to, "w")
+	begin
+	  each(){|l| dst << l}
+	ensure
+	  dst.close
+	end
+      when IO
+	each(){|l| to << l}
+      else
+	Shell.Fail Error::CantApplyMethod, ">", to.class
+      end
+      self
+    end
+
+    def >> (to)
+      begin
+	Shell.cd(@shell.pwd).append(to, self)
+      rescue CantApplyMethod
+	Shell.Fail Error::CantApplyMethod, ">>", to.class
+      end
+    end
+
+    def | (filter)
+      filter.input = self
+      if active?
+	@shell.process_controller.start_job filter
+      end
+      filter
+    end
+
+    def + (filter)
+      Join.new(@shell, self, filter)
+    end
+
+    def to_a
+      ary = []
+      each(){|l| ary.push l}
+      ary
+    end
+
+    def to_s
+      str = ""
+      each(){|l| str.concat l}
+      str
+    end
+
+    def inspect
+      if @shell.debug.kind_of?(Integer) && @shell.debug > 2
+	super
+      else
+	to_s
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/process-controller.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/process-controller.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/process-controller.rb	(revision 18425)
@@ -0,0 +1,260 @@
+#
+#   shell/process-controller.rb - 
+#   	$Release Version: 0.6.0 $
+#   	$Revision: 12008 $
+#   	$Date: 2007-03-06 19:12:12 +0900 (Tue, 06 Mar 2007) $
+#   	by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
+#
+# --
+#
+#   
+#
+
+require "mutex_m"
+require "monitor"
+require "sync"
+
+class Shell
+  class ProcessController
+
+    @ProcessControllers = {}
+    @ProcessControllers.extend Mutex_m
+
+    class<<self
+
+      def process_controllers_exclusive
+	begin
+	  @ProcessControllers.lock unless Thread.critical 
+	  yield
+	ensure
+	  @ProcessControllers.unlock unless Thread.critical 
+	end
+      end
+
+      def activate(pc)
+	process_controllers_exclusive do
+	  @ProcessControllers[pc] ||= 0
+	  @ProcessControllers[pc] += 1
+	end
+      end
+
+      def inactivate(pc)
+	process_controllers_exclusive do
+	  if @ProcessControllers[pc]
+	    if (@ProcessControllers[pc] -= 1) == 0
+	      @ProcessControllers.delete(pc)
+	    end
+	  end
+	end
+      end
+
+      def each_active_object
+	process_controllers_exclusive do
+	  for ref in @ProcessControllers.keys
+	    yield ref
+	  end
+	end
+      end
+    end
+
+    def initialize(shell)
+      @shell = shell
+      @waiting_jobs = []
+      @active_jobs = []
+      @jobs_sync = Sync.new
+
+      @job_monitor = Mutex.new
+      @job_condition = ConditionVariable.new
+    end
+
+    def jobs
+      jobs = []
+      @jobs_sync.synchronize(:SH) do
+	jobs.concat @waiting_jobs
+	jobs.concat @active_jobs
+      end
+      jobs
+    end
+
+    def active_jobs
+      @active_jobs
+    end
+
+    def waiting_jobs
+      @waiting_jobs
+    end
+    
+    def jobs_exist?
+      @jobs_sync.synchronize(:SH) do
+	@active_jobs.empty? or @waiting_jobs.empty?
+      end
+    end
+
+    def active_jobs_exist?
+      @jobs_sync.synchronize(:SH) do
+	@active_jobs.empty?
+      end
+    end
+
+    def waiting_jobs_exist?
+      @jobs_sync.synchronize(:SH) do
+	@waiting_jobs.empty?
+      end
+    end
+
+    # schedule a command
+    def add_schedule(command)
+      @jobs_sync.synchronize(:EX) do
+	ProcessController.activate(self)
+	if @active_jobs.empty?
+	  start_job command
+	else
+	  @waiting_jobs.push(command)
+	end
+      end
+    end
+
+    # start a job
+    def start_job(command = nil)
+      @jobs_sync.synchronize(:EX) do
+	if command
+	  return if command.active?
+	  @waiting_jobs.delete command
+	else
+	  command = @waiting_jobs.shift
+	  return unless command
+	end
+	@active_jobs.push command
+	command.start
+
+	# start all jobs that input from the job
+	for job in @waiting_jobs
+	  start_job(job) if job.input == command
+	end
+      end
+    end
+
+    def waiting_job?(job)
+      @jobs_sync.synchronize(:SH) do
+	@waiting_jobs.include?(job)
+      end
+    end
+
+    def active_job?(job)
+      @jobs_sync.synchronize(:SH) do
+	@active_jobs.include?(job)
+      end
+    end
+
+    # terminate a job
+    def terminate_job(command)
+      @jobs_sync.synchronize(:EX) do
+	@active_jobs.delete command
+	ProcessController.inactivate(self)
+	if @active_jobs.empty?
+	  start_job
+	end
+      end
+    end
+
+    # kill a job
+    def kill_job(sig, command)
+      @jobs_sync.synchronize(:SH) do
+	if @waiting_jobs.delete command
+	  ProcessController.inactivate(self)
+	  return
+	elsif @active_jobs.include?(command)
+	  begin
+	    r = command.kill(sig)
+	    ProcessController.inactivate(self)
+	  rescue
+	    print "Shell: Warn: $!\n" if @shell.verbose?
+	    return nil
+	  end
+	  @active_jobs.delete command
+	  r
+	end
+      end
+    end
+
+    # wait for all jobs to terminate
+    def wait_all_jobs_execution
+      @job_monitor.synchronize do
+	begin
+	  while !jobs.empty?
+	    @job_condition.wait(@job_monitor)
+	  end
+	ensure
+	  redo unless jobs.empty?
+	end
+      end
+    end
+
+    # simple fork
+    def sfork(command, &block)
+      pipe_me_in, pipe_peer_out = IO.pipe
+      pipe_peer_in, pipe_me_out = IO.pipe
+      Thread.critical = true
+
+      STDOUT.flush
+      ProcessController.each_active_object do |pc|
+	for jobs in pc.active_jobs
+	  jobs.flush
+	end
+      end
+      
+      pid = fork {
+	Thread.critical = true
+
+	Thread.list.each do |th| 
+	  th.kill unless [Thread.main, Thread.current].include?(th)
+	end
+
+	STDIN.reopen(pipe_peer_in)
+	STDOUT.reopen(pipe_peer_out)
+
+	ObjectSpace.each_object(IO) do |io| 
+	  if ![STDIN, STDOUT, STDERR].include?(io)
+	    io.close unless io.closed?
+	  end
+	end
+	yield
+      }
+
+      pipe_peer_in.close
+      pipe_peer_out.close
+      command.notify "job(%name:##{pid}) start", @shell.debug?
+      Thread.critical = false
+
+      th = Thread.start {
+	Thread.critical = true
+	begin
+	  _pid = nil
+	  command.notify("job(%id) start to waiting finish.", @shell.debug?)
+	  Thread.critical = false
+	  _pid = Process.waitpid(pid, nil)
+	rescue Errno::ECHILD
+	  command.notify "warn: job(%id) was done already waitipd."
+	  _pid = true
+	ensure
+	  # when the process ends, wait until the command termintes
+	  if _pid
+	  else
+	    command.notify("notice: Process finishing...",
+			   "wait for Job[%id] to finish.",
+			   "You can use Shell#transact or Shell#check_point for more safe execution.")
+	    redo
+	  end
+	  Thread.exclusive do
+	    @job_monitor.synchronize do 
+	      terminate_job(command)
+	      @job_condition.signal
+	      command.notify "job(%id) finish.", @shell.debug?
+	    end
+	  end
+	end
+      }
+      return pid, pipe_me_in, pipe_me_out
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/system-command.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/system-command.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/system-command.rb	(revision 18425)
@@ -0,0 +1,168 @@
+#
+#   shell/system-command.rb - 
+#   	$Release Version: 0.6.0 $
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
+#
+# --
+#
+#   
+#
+
+require "shell/filter"
+
+class Shell
+  class SystemCommand < Filter
+    def initialize(sh, command, *opts)
+      if t = opts.find{|opt| !opt.kind_of?(String) && opt.class}
+	Shell.Fail Error::TypeError, t.class, "String"
+      end
+      super(sh)
+      @command = command
+      @opts = opts
+      
+      @input_queue = Queue.new
+      @pid = nil
+
+      sh.process_controller.add_schedule(self)
+    end
+
+    attr_reader :command
+    alias name command
+
+    def wait?
+      @shell.process_controller.waiting_job?(self)
+    end
+
+    def active?
+      @shell.process_controller.active_job?(self)
+    end
+
+    def input=(inp)
+      super
+      if active?
+	start_export
+      end
+    end
+
+    def start
+      @pid, @pipe_in, @pipe_out = @shell.process_controller.sfork(self) {
+	Dir.chdir @shell.pwd
+	exec(@command, *@opts)
+      }
+      if @input
+	start_export
+      end
+      start_import
+    end
+
+    def flush
+      @pipe_out.flush if @pipe_out and !@pipe_out.closed?
+    end
+
+    def terminate
+      begin
+	@pipe_in.close
+      rescue IOError
+      end
+      begin
+	@pipe_out.close
+      rescue IOError
+      end
+    end
+
+    def kill(sig)
+      if @pid
+	Process.kill(sig, @pid)
+      end
+    end
+
+
+    def start_import
+#      Thread.critical = true
+      notify "Job(%id) start imp-pipe.", @shell.debug?
+      rs = @shell.record_separator unless rs
+      _eop = true
+#      Thread.critical = false
+      th = Thread.start {
+	Thread.critical = true
+	begin
+	  Thread.critical = false
+	  while l = @pipe_in.gets
+	    @input_queue.push l
+	  end
+	  _eop = false
+	rescue Errno::EPIPE
+	  _eop = false
+	ensure
+	  if _eop
+	    notify("warn: Process finishing...",
+		   "wait for Job[%id] to finish pipe importing.",
+		   "You can use Shell#transact or Shell#check_point for more safe execution.")
+#	    Tracer.on
+	    Thread.current.run
+	    redo
+	  end
+	  Thread.exclusive do
+	    notify "job(%id}) close imp-pipe.", @shell.debug?
+	    @input_queue.push :EOF
+	    @pipe_in.close
+	  end
+	end
+      }
+    end
+
+    def start_export
+      notify "job(%id) start exp-pipe.", @shell.debug?
+      _eop = true
+      th = Thread.start{
+	Thread.critical = true
+	begin
+	  Thread.critical = false
+	  @input.each{|l| @pipe_out.print l}
+	  _eop = false
+	rescue Errno::EPIPE
+	  _eop = false
+	ensure
+	  if _eop
+	    notify("shell: warn: Process finishing...",
+		   "wait for Job(%id) to finish pipe exporting.",
+		   "You can use Shell#transact or Shell#check_point for more safe execution.")
+#	    Tracer.on
+	    redo
+	  end
+	  Thread.exclusive do
+	    notify "job(%id) close exp-pipe.", @shell.debug?
+	    @pipe_out.close
+	  end
+	end
+      }
+    end
+
+    alias super_each each
+    def each(rs = nil)
+      while (l = @input_queue.pop) != :EOF
+	yield l
+      end
+    end
+
+    # ex)
+    #    if you wish to output: 
+    #	    "shell: job(#{@command}:#{@pid}) close pipe-out."
+    #	 then 
+    #	    mes: "job(%id) close pipe-out."
+    #    yorn: Boolean(@shell.debug? or @shell.verbose?)
+    def notify(*opts, &block)
+      Thread.exclusive do
+	@shell.notify(*opts) {|mes|
+	  yield mes if iterator?
+
+	  mes.gsub!("%id", "#{@command}:##{@pid}")
+	  mes.gsub!("%name", "#{@command}")
+	  mes.gsub!("%pid", "#{@pid}")
+	}
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/version.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/version.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shell/version.rb	(revision 18425)
@@ -0,0 +1,16 @@
+#
+#   version.rb - shell version definition file
+#   	$Release Version: 0.6.0$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
+#
+# --
+#
+#   
+#
+
+class Shell
+  @RELEASE_VERSION = "0.6.0"
+  @LAST_UPDATE_DATE = "01/03/19"
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shellwords.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shellwords.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/shellwords.rb	(revision 18425)
@@ -0,0 +1,60 @@
+#
+# shellwords.rb: Split text into an array of tokens a la UNIX shell
+#
+
+#
+# This module is originally a port of shellwords.pl, but modified to
+# conform to POSIX / SUSv3 (IEEE Std 1003.1-2001).
+#
+# Examples:
+#
+#   require 'shellwords'
+#   words = Shellwords.shellwords(line)
+#
+# or
+#
+#   require 'shellwords'
+#   include Shellwords
+#   words = shellwords(line)
+#
+module Shellwords
+
+  #
+  # Split text into an array of tokens in the same way the UNIX Bourne
+  # shell does.
+  #
+  # See the +Shellwords+ module documentation for an example.
+  #
+  def shellwords(line)
+    line = String.new(line) rescue
+      raise(ArgumentError, "Argument must be a string")
+    line.lstrip!
+    words = []
+    until line.empty?
+      field = ''
+      loop do
+	if line.sub!(/\A"(([^"\\]|\\.)*)"/, '') then
+	  snippet = $1.gsub(/\\(.)/, '\1')
+	elsif line =~ /\A"/ then
+	  raise ArgumentError, "Unmatched double quote: #{line}"
+	elsif line.sub!(/\A'([^']*)'/, '') then
+	  snippet = $1
+	elsif line =~ /\A'/ then
+	  raise ArgumentError, "Unmatched single quote: #{line}"
+	elsif line.sub!(/\A\\(.)?/, '') then
+	  snippet = $1 || '\\'
+	elsif line.sub!(/\A([^\s\\'"]+)/, '') then
+	  snippet = $1
+	else
+	  line.lstrip!
+	  break
+	end
+	field.concat(snippet)
+      end
+      words.push(field)
+    end
+    words
+  end
+
+  module_function :shellwords
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/singleton.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/singleton.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/singleton.rb	(revision 18425)
@@ -0,0 +1,360 @@
+# The Singleton module implements the Singleton pattern.
+#
+# Usage:
+#    class Klass
+#       include Singleton
+#       # ...
+#    end
+#
+# *  this ensures that only one instance of Klass lets call it
+#    ``the instance'' can be created.
+#
+#    a,b  = Klass.instance, Klass.instance
+#    a == b   # => true
+#    a.new    #  NoMethodError - new is private ...
+#
+# *  ``The instance'' is created at instantiation time, in other
+#    words the first call of Klass.instance(), thus
+#
+#      class OtherKlass
+#        include Singleton
+#        # ...
+#      end
+#      ObjectSpace.each_object(OtherKlass){} # => 0.
+#
+# *  This behavior is preserved under inheritance and cloning.
+#
+#
+#
+# This is achieved by marking
+# *  Klass.new and Klass.allocate - as private
+#
+# Providing (or modifying) the class methods
+# *  Klass.inherited(sub_klass) and Klass.clone()  - 
+#    to ensure that the Singleton pattern is properly
+#    inherited and cloned.
+#
+# *  Klass.instance()  -  returning ``the instance''. After a
+#    successful self modifying (normally the first) call the
+#    method body is a simple:
+#
+#       def Klass.instance()
+#         return @__instance__
+#       end
+#
+# *  Klass._load(str)  -  calling Klass.instance()
+#
+# *  Klass._instantiate?()  -  returning ``the instance'' or
+#    nil. This hook method puts a second (or nth) thread calling
+#    Klass.instance() on a waiting loop. The return value
+#    signifies the successful completion or premature termination
+#    of the first, or more generally, current "instantiation thread".
+#
+#
+# The instance method of Singleton are
+# * clone and dup - raising TypeErrors to prevent cloning or duping
+#
+# *  _dump(depth) - returning the empty string.  Marshalling strips
+#    by default all state information, e.g. instance variables and
+#    taint state, from ``the instance''.  Providing custom _load(str)
+#    and _dump(depth) hooks allows the (partially) resurrections of
+#    a previous state of ``the instance''.
+
+
+
+module Singleton
+  #  disable build-in copying methods
+  def clone
+    raise TypeError, "can't clone instance of singleton #{self.class}"
+  end
+  def dup
+    raise TypeError, "can't dup instance of singleton #{self.class}"
+  end
+  
+  private 
+  #  default marshalling strategy
+  def _dump(depth=-1) 
+    ''
+  end
+end
+
+
+class << Singleton
+  #  Method body of first instance call.
+  FirstInstanceCall = proc do
+    #  @__instance__ takes on one of the following values
+    #  * nil     -  before and after a failed creation
+    #  * false  -  during creation
+    #  * sub_class instance  -  after a successful creation
+    #  the form makes up for the lack of returns in progs
+    Thread.critical = true
+    if  @__instance__.nil?
+      @__instance__  = false
+      Thread.critical = false
+      begin
+        @__instance__ = new
+      ensure
+        if @__instance__
+          class <<self
+            remove_method :instance
+            def instance; @__instance__ end
+          end
+        else
+          @__instance__ = nil #  failed instance creation
+        end
+      end
+    elsif  _instantiate?()
+      Thread.critical = false    
+    else
+      @__instance__  = false
+      Thread.critical = false
+      begin
+        @__instance__ = new
+      ensure
+        if @__instance__
+          class <<self
+            remove_method :instance
+            def instance; @__instance__ end
+          end
+        else
+          @__instance__ = nil
+        end
+      end
+    end
+    @__instance__
+  end
+  
+  module SingletonClassMethods  
+    # properly clone the Singleton pattern - did you know
+    # that duping doesn't copy class methods?  
+    def clone
+      Singleton.__init__(super)
+    end
+    
+    private
+    
+    #  ensure that the Singleton pattern is properly inherited   
+    def inherited(sub_klass)
+      super
+      Singleton.__init__(sub_klass)
+    end
+    
+    def _load(str) 
+      instance 
+    end
+    
+    # waiting-loop hook
+    def _instantiate?()
+      while false.equal?(@__instance__)
+        Thread.critical = false
+        sleep(0.08)   # timeout
+        Thread.critical = true
+      end
+      @__instance__
+    end
+  end
+  
+  def __init__(klass)
+    klass.instance_eval { @__instance__ = nil }
+    class << klass
+      define_method(:instance,FirstInstanceCall)
+    end
+    klass
+  end
+  
+  private
+  #  extending an object with Singleton is a bad idea
+  undef_method :extend_object
+  
+  def append_features(mod)
+    #  help out people counting on transitive mixins
+    unless mod.instance_of?(Class)
+      raise TypeError, "Inclusion of the OO-Singleton module in module #{mod}"
+    end
+    super
+  end
+  
+  def included(klass)
+    super
+    klass.private_class_method  :new, :allocate
+    klass.extend SingletonClassMethods
+    Singleton.__init__(klass)
+  end
+end
+ 
+
+
+if __FILE__ == $0
+
+def num_of_instances(klass)
+    "#{ObjectSpace.each_object(klass){}} #{klass} instance(s)"
+end 
+
+# The basic and most important example.
+
+class SomeSingletonClass
+  include Singleton
+end
+puts "There are #{num_of_instances(SomeSingletonClass)}" 
+
+a = SomeSingletonClass.instance
+b = SomeSingletonClass.instance # a and b are same object
+puts "basic test is #{a == b}"
+
+begin
+  SomeSingletonClass.new
+rescue  NoMethodError => mes
+  puts mes
+end
+
+
+
+puts "\nThreaded example with exception and customized #_instantiate?() hook"; p
+Thread.abort_on_exception = false
+
+class Ups < SomeSingletonClass
+  def initialize
+    self.class.__sleep
+    puts "initialize called by thread ##{Thread.current[:i]}"
+  end
+end
+  
+class << Ups
+  def _instantiate?
+    @enter.push Thread.current[:i]
+    while false.equal?(@__instance__)
+      Thread.critical = false
+      sleep 0.08 
+      Thread.critical = true
+    end
+    @leave.push Thread.current[:i]
+    @__instance__
+  end
+  
+  def __sleep
+    sleep(rand(0.08))
+  end
+  
+  def new
+    begin
+      __sleep
+      raise  "boom - thread ##{Thread.current[:i]} failed to create instance"
+    ensure
+      # simple flip-flop
+      class << self
+        remove_method :new
+      end
+    end
+  end
+  
+  def instantiate_all
+    @enter = []
+    @leave = []
+    1.upto(9) {|i|  
+      Thread.new { 
+        begin
+          Thread.current[:i] = i
+          __sleep
+          instance
+        rescue RuntimeError => mes
+          puts mes
+        end
+      }
+    }
+    puts "Before there were #{num_of_instances(self)}"
+    sleep 3
+    puts "Now there is #{num_of_instances(self)}"
+    puts "#{@enter.join '; '} was the order of threads entering the waiting loop"
+    puts "#{@leave.join '; '} was the order of threads leaving the waiting loop"
+  end
+end
+
+
+Ups.instantiate_all
+# results in message like
+# Before there were 0 Ups instance(s)
+# boom - thread #6 failed to create instance
+# initialize called by thread #3
+# Now there is 1 Ups instance(s)
+# 3; 2; 1; 8; 4; 7; 5 was the order of threads entering the waiting loop
+# 3; 2; 1; 7; 4; 8; 5 was the order of threads leaving the waiting loop
+
+
+puts "\nLets see if class level cloning really works"
+Yup = Ups.clone
+def Yup.new
+  begin
+    __sleep
+    raise  "boom - thread ##{Thread.current[:i]} failed to create instance"
+  ensure
+    # simple flip-flop
+    class << self
+      remove_method :new
+    end
+  end
+end
+Yup.instantiate_all
+
+
+puts "\n\n","Customized marshalling"
+class A
+  include Singleton
+  attr_accessor :persist, :die
+  def _dump(depth)
+    # this strips the @die information from the instance
+    Marshal.dump(@persist,depth)
+  end
+end
+
+def A._load(str)
+  instance.persist = Marshal.load(str)
+  instance
+end
+
+a = A.instance
+a.persist = ["persist"]
+a.die = "die"
+a.taint
+
+stored_state = Marshal.dump(a)
+# change state
+a.persist = nil
+a.die = nil
+b = Marshal.load(stored_state)
+p a == b  #  => true
+p a.persist  #  => ["persist"]
+p a.die      #  => nil
+
+
+puts "\n\nSingleton with overridden default #inherited() hook"
+class Up
+end
+def Up.inherited(sub_klass)
+  puts "#{sub_klass} subclasses #{self}"
+end
+
+
+class Middle < Up
+  include Singleton
+end
+
+class Down < Middle; end
+
+puts  "and basic \"Down test\" is #{Down.instance == Down.instance}\n
+Various exceptions"  
+
+begin
+  module AModule
+    include Singleton
+  end
+rescue TypeError => mes
+  puts mes  #=> Inclusion of the OO-Singleton module in module AModule
+end
+
+begin
+  'aString'.extend Singleton
+rescue NoMethodError => mes
+  puts mes  #=> undefined method `extend_object' for Singleton:Module
+end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/attachment.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/attachment.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/attachment.rb	(revision 18425)
@@ -0,0 +1,107 @@
+# soap/attachment.rb: SOAP4R - SwA implementation.
+# Copyright (C) 2002, 2003  Jamie Herre and NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/baseData'
+require 'soap/mapping'
+
+
+module SOAP
+
+
+class SOAPAttachment < SOAPExternalReference
+  attr_reader :data
+
+  def initialize(value)
+    super()
+    @data = value
+  end
+
+private
+
+  def external_contentid
+    @data.contentid
+  end
+end
+
+
+class Attachment
+  attr_reader :io
+  attr_accessor :contenttype
+
+  def initialize(string_or_readable = nil)
+    @string_or_readable = string_or_readable
+    @contenttype = "application/octet-stream"
+    @contentid = nil
+  end
+
+  def contentid
+    @contentid ||= Attachment.contentid(self)
+  end
+
+  def contentid=(contentid)
+    @contentid = contentid
+  end
+
+  def mime_contentid
+    '<' + contentid + '>'
+  end
+
+  def content
+    if @content == nil and @string_or_readable != nil
+      @content = @string_or_readable.respond_to?(:read) ?
+	@string_or_readable.read : @string_or_readable
+    end
+    @content
+  end
+
+  def to_s
+    content
+  end
+
+  def write(out)
+    out.write(content)
+  end
+
+  def save(filename)
+    File.open(filename, "wb") do |f|
+      write(f)
+    end
+  end
+
+  def self.contentid(obj)
+    # this needs to be fixed
+    [obj.__id__.to_s, Process.pid.to_s].join('.')
+  end
+
+  def self.mime_contentid(obj)
+    '<' + contentid(obj) + '>'
+  end
+end
+
+
+module Mapping
+  class AttachmentFactory < SOAP::Mapping::Factory
+    def obj2soap(soap_class, obj, info, map)
+      soap_obj = soap_class.new(obj)
+      mark_marshalled_obj(obj, soap_obj)
+      soap_obj
+    end
+
+    def soap2obj(obj_class, node, info, map)
+      obj = node.data
+      mark_unmarshalled_obj(node, obj)
+      return true, obj
+    end
+  end
+
+  DefaultRegistry.add(::SOAP::Attachment, ::SOAP::SOAPAttachment,
+    AttachmentFactory.new, nil)
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/baseData.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/baseData.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/baseData.rb	(revision 18425)
@@ -0,0 +1,942 @@
+# soap/baseData.rb: SOAP4R - Base type library
+# Copyright (C) 2000, 2001, 2003-2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/datatypes'
+require 'soap/soap'
+
+
+module SOAP
+
+
+###
+## Mix-in module for SOAP base type classes.
+#
+module SOAPModuleUtils
+  include SOAP
+
+public
+
+  def decode(elename)
+    d = self.new
+    d.elename = elename
+    d
+  end
+end
+
+
+###
+## for SOAP type(base and compound)
+#
+module SOAPType
+  attr_accessor :encodingstyle
+  attr_accessor :elename
+  attr_accessor :id
+  attr_reader :precedents
+  attr_accessor :root
+  attr_accessor :parent
+  attr_accessor :position
+  attr_reader :extraattr
+  attr_accessor :definedtype
+
+  def initialize(*arg)
+    super
+    @encodingstyle = nil
+    @elename = XSD::QName::EMPTY
+    @id = nil
+    @precedents = []
+    @root = false
+    @parent = nil
+    @position = nil
+    @definedtype = nil
+    @extraattr = {}
+  end
+
+  def inspect
+    if self.is_a?(XSD::NSDBase)
+      sprintf("#<%s:0x%x %s %s>", self.class.name, __id__, self.elename, self.type)
+    else
+      sprintf("#<%s:0x%x %s>", self.class.name, __id__, self.elename)
+    end
+  end
+
+  def rootnode
+    node = self
+    while node = node.parent
+      break if SOAPEnvelope === node
+    end
+    node
+  end
+end
+
+
+###
+## for SOAP base type
+#
+module SOAPBasetype
+  include SOAPType
+  include SOAP
+
+  def initialize(*arg)
+    super
+  end
+end
+
+
+###
+## for SOAP compound type
+#
+module SOAPCompoundtype
+  include SOAPType
+  include SOAP
+
+  def initialize(*arg)
+    super
+  end
+end
+
+
+###
+## Convenience datatypes.
+#
+class SOAPReference < XSD::NSDBase
+  include SOAPBasetype
+  extend SOAPModuleUtils
+
+public
+
+  attr_accessor :refid
+
+  # Override the definition in SOAPBasetype.
+  def initialize(obj = nil)
+    super()
+    @type = XSD::QName::EMPTY
+    @refid = nil
+    @obj = nil
+    __setobj__(obj) if obj
+  end
+
+  def __getobj__
+    @obj
+  end
+
+  def __setobj__(obj)
+    @obj = obj
+    @refid = @obj.id || SOAPReference.create_refid(@obj)
+    @obj.id = @refid unless @obj.id
+    @obj.precedents << self
+    # Copies NSDBase information
+    @obj.type = @type unless @obj.type
+  end
+
+  # Why don't I use delegate.rb?
+  # -> delegate requires target object type at initialize time.
+  # Why don't I use forwardable.rb?
+  # -> forwardable requires a list of forwarding methods.
+  #
+  # ToDo: Maybe I should use forwardable.rb and give it a methods list like
+  # delegate.rb...
+  #
+  def method_missing(msg_id, *params)
+    if @obj
+      @obj.send(msg_id, *params)
+    else
+      nil
+    end
+  end
+
+  def refidstr
+    '#' + @refid
+  end
+
+  def self.create_refid(obj)
+    'id' + obj.__id__.to_s
+  end
+
+  def self.decode(elename, refidstr)
+    if /\A#(.*)\z/ =~ refidstr
+      refid = $1
+    elsif /\Acid:(.*)\z/ =~ refidstr
+      refid = $1
+    else
+      raise ArgumentError.new("illegal refid #{refidstr}")
+    end
+    d = super(elename)
+    d.refid = refid
+    d
+  end
+end
+
+
+class SOAPExternalReference < XSD::NSDBase
+  include SOAPBasetype
+  extend SOAPModuleUtils
+
+  def initialize
+    super()
+    @type = XSD::QName::EMPTY
+  end
+
+  def referred
+    rootnode.external_content[external_contentid] = self
+  end
+
+  def refidstr
+    'cid:' + external_contentid
+  end
+
+private
+
+  def external_contentid
+    raise NotImplementedError.new
+  end
+end
+
+
+class SOAPNil < XSD::XSDNil
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+# SOAPRawString is for sending raw string.  In contrast to SOAPString,
+# SOAP4R does not do XML encoding and does not convert its CES.  The string it
+# holds is embedded to XML instance directly as a 'xsd:string'.
+class SOAPRawString < XSD::XSDString
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+
+###
+## Basic datatypes.
+#
+class SOAPAnySimpleType < XSD::XSDAnySimpleType
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPString < XSD::XSDString
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPBoolean < XSD::XSDBoolean
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPDecimal < XSD::XSDDecimal
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPFloat < XSD::XSDFloat
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPDouble < XSD::XSDDouble
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPDuration < XSD::XSDDuration
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPDateTime < XSD::XSDDateTime
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPTime < XSD::XSDTime
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPDate < XSD::XSDDate
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPGYearMonth < XSD::XSDGYearMonth
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPGYear < XSD::XSDGYear
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPGMonthDay < XSD::XSDGMonthDay
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPGDay < XSD::XSDGDay
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPGMonth < XSD::XSDGMonth
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPHexBinary < XSD::XSDHexBinary
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPBase64 < XSD::XSDBase64Binary
+  include SOAPBasetype
+  extend SOAPModuleUtils
+  Type = QName.new(EncodingNamespace, Base64Literal)
+
+public
+  # Override the definition in SOAPBasetype.
+  def initialize(value = nil)
+    super(value)
+    @type = Type
+  end
+
+  def as_xsd
+    @type = XSD::XSDBase64Binary::Type
+  end
+end
+
+class SOAPAnyURI < XSD::XSDAnyURI
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPQName < XSD::XSDQName
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+
+class SOAPInteger < XSD::XSDInteger
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPNonPositiveInteger < XSD::XSDNonPositiveInteger
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPNegativeInteger < XSD::XSDNegativeInteger
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPLong < XSD::XSDLong
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPInt < XSD::XSDInt
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPShort < XSD::XSDShort
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPByte < XSD::XSDByte
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPNonNegativeInteger < XSD::XSDNonNegativeInteger
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPUnsignedLong < XSD::XSDUnsignedLong
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPUnsignedInt < XSD::XSDUnsignedInt
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPUnsignedShort < XSD::XSDUnsignedShort
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPUnsignedByte < XSD::XSDUnsignedByte
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+class SOAPPositiveInteger < XSD::XSDPositiveInteger
+  include SOAPBasetype
+  extend SOAPModuleUtils
+end
+
+
+###
+## Compound datatypes.
+#
+class SOAPStruct < XSD::NSDBase
+  include SOAPCompoundtype
+  include Enumerable
+
+public
+
+  def initialize(type = nil)
+    super()
+    @type = type || XSD::QName::EMPTY
+    @array = []
+    @data = []
+  end
+
+  def to_s()
+    str = ''
+    self.each do |key, data|
+      str << "#{key}: #{data}\n"
+    end
+    str
+  end
+
+  def add(name, value)
+    add_member(name, value)
+  end
+
+  def [](idx)
+    if idx.is_a?(Range)
+      @data[idx]
+    elsif idx.is_a?(Integer)
+      if (idx > @array.size)
+        raise ArrayIndexOutOfBoundsError.new('In ' << @type.name)
+      end
+      @data[idx]
+    else
+      if @array.include?(idx)
+	@data[@array.index(idx)]
+      else
+	nil
+      end
+    end
+  end
+
+  def []=(idx, data)
+    if @array.include?(idx)
+      data.parent = self if data.respond_to?(:parent=)
+      @data[@array.index(idx)] = data
+    else
+      add(idx, data)
+    end
+  end
+
+  def key?(name)
+    @array.include?(name)
+  end
+
+  def members
+    @array
+  end
+
+  def to_obj
+    hash = {}
+    proptype = {}
+    each do |k, v|
+      value = v.respond_to?(:to_obj) ? v.to_obj : v.to_s
+      case proptype[k]
+      when :single
+        hash[k] = [hash[k], value]
+        proptype[k] = :multi
+      when :multi
+        hash[k] << value
+      else
+        hash[k] = value
+        proptype[k] = :single
+      end
+    end
+    hash
+  end
+
+  def each
+    idx = 0
+    while idx < @array.length
+      yield(@array[idx], @data[idx])
+      idx += 1
+    end
+  end
+
+  def replace
+    members.each do |member|
+      self[member] = yield(self[member])
+    end
+  end
+
+  def self.decode(elename, type)
+    s = SOAPStruct.new(type)
+    s.elename = elename
+    s
+  end
+
+private
+
+  def add_member(name, value = nil)
+    value = SOAPNil.new() if value.nil?
+    @array.push(name)
+    value.elename = value.elename.dup_name(name)
+    @data.push(value)
+    value.parent = self if value.respond_to?(:parent=)
+    value
+  end
+end
+
+
+# SOAPElement is not typed so it is not derived from NSDBase.
+class SOAPElement
+  include Enumerable
+
+  attr_accessor :encodingstyle
+
+  attr_accessor :elename
+  attr_accessor :id
+  attr_reader :precedents
+  attr_accessor :root
+  attr_accessor :parent
+  attr_accessor :position
+  attr_accessor :extraattr
+
+  attr_accessor :qualified
+
+  def initialize(elename, text = nil)
+    if !elename.is_a?(XSD::QName)
+      elename = XSD::QName.new(nil, elename)
+    end
+    @encodingstyle = LiteralNamespace
+    @elename = elename
+    @id = nil
+    @precedents = []
+    @root = false
+    @parent = nil
+    @position = nil
+    @extraattr = {}
+
+    @qualified = nil
+
+    @array = []
+    @data = []
+    @text = text
+  end
+
+  def inspect
+    sprintf("#<%s:0x%x %s>", self.class.name, __id__, self.elename)
+  end
+
+  # Text interface.
+  attr_accessor :text
+  alias data text
+
+  # Element interfaces.
+  def add(value)
+    add_member(value.elename.name, value)
+  end
+
+  def [](idx)
+    if @array.include?(idx)
+      @data[@array.index(idx)]
+    else
+      nil
+    end
+  end
+
+  def []=(idx, data)
+    if @array.include?(idx)
+      data.parent = self if data.respond_to?(:parent=)
+      @data[@array.index(idx)] = data
+    else
+      add(data)
+    end
+  end
+
+  def key?(name)
+    @array.include?(name)
+  end
+
+  def members
+    @array
+  end
+
+  def to_obj
+    if members.empty?
+      @text
+    else
+      hash = {}
+      proptype = {}
+      each do |k, v|
+        value = v.respond_to?(:to_obj) ? v.to_obj : v.to_s
+        case proptype[k]
+        when :single
+          hash[k] = [hash[k], value]
+          proptype[k] = :multi
+        when :multi
+          hash[k] << value
+        else
+          hash[k] = value
+          proptype[k] = :single
+        end
+      end
+      hash
+    end
+  end
+
+  def each
+    idx = 0
+    while idx < @array.length
+      yield(@array[idx], @data[idx])
+      idx += 1
+    end
+  end
+
+  def self.decode(elename)
+    o = SOAPElement.new(elename)
+    o
+  end
+
+  def self.from_obj(obj, namespace = nil)
+    o = SOAPElement.new(nil)
+    case obj
+    when nil
+      o.text = nil
+    when Hash
+      obj.each do |elename, value|
+        if value.is_a?(Array)
+          value.each do |subvalue|
+            child = from_obj(subvalue, namespace)
+            child.elename = to_elename(elename, namespace)
+            o.add(child)
+          end
+        else
+          child = from_obj(value, namespace)
+          child.elename = to_elename(elename, namespace)
+          o.add(child)
+        end
+      end
+    else
+      o.text = obj.to_s
+    end
+    o
+  end
+
+  def self.to_elename(obj, namespace = nil)
+    if obj.is_a?(XSD::QName)
+      obj
+    elsif /\A(.+):([^:]+)\z/ =~ obj.to_s
+      XSD::QName.new($1, $2)
+    else
+      XSD::QName.new(namespace, obj.to_s)
+    end
+  end
+
+private
+
+  def add_member(name, value)
+    add_accessor(name)
+    @array.push(name)
+    @data.push(value)
+    value.parent = self if value.respond_to?(:parent=)
+    value
+  end
+
+  if RUBY_VERSION > "1.7.0"
+    def add_accessor(name)
+      methodname = name
+      if self.respond_to?(methodname)
+        methodname = safe_accessor_name(methodname)
+      end
+      Mapping.define_singleton_method(self, methodname) do
+        @data[@array.index(name)]
+      end
+      Mapping.define_singleton_method(self, methodname + '=') do |value|
+        @data[@array.index(name)] = value
+      end
+    end
+  else
+    def add_accessor(name)
+      methodname = safe_accessor_name(name)
+      instance_eval <<-EOS
+        def #{methodname}
+          @data[@array.index(#{name.dump})]
+        end
+
+        def #{methodname}=(value)
+          @data[@array.index(#{name.dump})] = value
+        end
+      EOS
+    end
+  end
+
+  def safe_accessor_name(name)
+    "var_" << name.gsub(/[^a-zA-Z0-9_]/, '')
+  end
+end
+
+
+class SOAPArray < XSD::NSDBase
+  include SOAPCompoundtype
+  include Enumerable
+
+public
+
+  attr_accessor :sparse
+
+  attr_reader :offset, :rank
+  attr_accessor :size, :size_fixed
+  attr_reader :arytype
+
+  def initialize(type = nil, rank = 1, arytype = nil)
+    super()
+    @type = type || ValueArrayName
+    @rank = rank
+    @data = Array.new
+    @sparse = false
+    @offset = Array.new(rank, 0)
+    @size = Array.new(rank, 0)
+    @size_fixed = false
+    @position = nil
+    @arytype = arytype
+  end
+
+  def offset=(var)
+    @offset = var
+    @sparse = true
+  end
+
+  def add(value)
+    self[*(@offset)] = value
+  end
+
+  def [](*idxary)
+    if idxary.size != @rank
+      raise ArgumentError.new("given #{idxary.size} params does not match rank: #{@rank}")
+    end
+
+    retrieve(idxary)
+  end
+
+  def []=(*idxary)
+    value = idxary.slice!(-1)
+
+    if idxary.size != @rank
+      raise ArgumentError.new("given #{idxary.size} params(#{idxary})" +
+        " does not match rank: #{@rank}")
+    end
+
+    idx = 0
+    while idx < idxary.size
+      if idxary[idx] + 1 > @size[idx]
+	@size[idx] = idxary[idx] + 1
+      end
+      idx += 1
+    end
+
+    data = retrieve(idxary[0, idxary.size - 1])
+    data[idxary.last] = value
+
+    if value.is_a?(SOAPType)
+      value.elename = ITEM_NAME
+      # Sync type
+      unless @type.name
+	@type = XSD::QName.new(value.type.namespace,
+	  SOAPArray.create_arytype(value.type.name, @rank))
+      end
+      value.type ||= @type
+    end
+
+    @offset = idxary
+    value.parent = self if value.respond_to?(:parent=)
+    offsetnext
+  end
+
+  def each
+    @data.each do |data|
+      yield(data)
+    end
+  end
+
+  def to_a
+    @data.dup
+  end
+
+  def replace
+    @data = deep_map(@data) do |ele|
+      yield(ele)
+    end
+  end
+
+  def deep_map(ary, &block)
+    ary.collect do |ele|
+      if ele.is_a?(Array)
+	deep_map(ele, &block)
+      else
+	new_obj = block.call(ele)
+	new_obj.elename = ITEM_NAME
+	new_obj
+      end
+    end
+  end
+
+  def include?(var)
+    traverse_data(@data) do |v, *rank|
+      if v.is_a?(SOAPBasetype) && v.data == var
+	return true
+      end
+    end
+    false
+  end
+
+  def traverse
+    traverse_data(@data) do |v, *rank|
+      unless @sparse
+       yield(v)
+      else
+       yield(v, *rank) if v && !v.is_a?(SOAPNil)
+      end
+    end
+  end
+
+  def soap2array(ary)
+    traverse_data(@data) do |v, *position|
+      iteary = ary
+      rank = 1
+      while rank < position.size
+	idx = position[rank - 1]
+	if iteary[idx].nil?
+	  iteary = iteary[idx] = Array.new
+	else
+	  iteary = iteary[idx]
+	end
+        rank += 1
+      end
+      if block_given?
+	iteary[position.last] = yield(v)
+      else
+	iteary[position.last] = v
+      end
+    end
+  end
+
+  def position
+    @position
+  end
+
+private
+
+  ITEM_NAME = XSD::QName.new(nil, 'item')
+
+  def retrieve(idxary)
+    data = @data
+    rank = 1
+    while rank <= idxary.size
+      idx = idxary[rank - 1]
+      if data[idx].nil?
+	data = data[idx] = Array.new
+      else
+	data = data[idx]
+      end
+      rank += 1
+    end
+    data
+  end
+
+  def traverse_data(data, rank = 1)
+    idx = 0
+    while idx < ranksize(rank)
+      if rank < @rank
+	traverse_data(data[idx], rank + 1) do |*v|
+	  v[1, 0] = idx
+       	  yield(*v)
+	end
+      else
+	yield(data[idx], idx)
+      end
+      idx += 1
+    end
+  end
+
+  def ranksize(rank)
+    @size[rank - 1]
+  end
+
+  def offsetnext
+    move = false
+    idx = @offset.size - 1
+    while !move && idx >= 0
+      @offset[idx] += 1
+      if @size_fixed
+	if @offset[idx] < @size[idx]
+	  move = true
+	else
+	  @offset[idx] = 0
+	  idx -= 1
+	end
+      else
+	move = true
+      end
+    end
+  end
+
+  # Module function
+
+public
+
+  def self.decode(elename, type, arytype)
+    typestr, nofary = parse_type(arytype.name)
+    rank = nofary.count(',') + 1
+    plain_arytype = XSD::QName.new(arytype.namespace, typestr)
+    o = SOAPArray.new(type, rank, plain_arytype)
+    size = []
+    nofary.split(',').each do |s|
+      if s.empty?
+	size.clear
+	break
+      else
+	size << s.to_i
+      end
+    end
+    unless size.empty?
+      o.size = size
+      o.size_fixed = true
+    end
+    o.elename = elename
+    o
+  end
+
+private
+
+  def self.create_arytype(typename, rank)
+    "#{typename}[" << ',' * (rank - 1) << ']'
+  end
+
+  TypeParseRegexp = Regexp.new('^(.+)\[([\d,]*)\]$')
+
+  def self.parse_type(string)
+    TypeParseRegexp =~ string
+    return $1, $2
+  end
+end
+
+
+require 'soap/mapping/typeMap'
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/element.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/element.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/element.rb	(revision 18425)
@@ -0,0 +1,258 @@
+# SOAP4R - SOAP elements library
+# Copyright (C) 2000, 2001, 2003-2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/qname'
+require 'soap/baseData'
+
+
+module SOAP
+
+
+###
+## SOAP elements
+#
+module SOAPEnvelopeElement; end
+
+class SOAPFault < SOAPStruct
+  include SOAPEnvelopeElement
+  include SOAPCompoundtype
+
+public
+
+  def faultcode
+    self['faultcode']
+  end
+
+  def faultstring
+    self['faultstring']
+  end
+
+  def faultactor
+    self['faultactor']
+  end
+
+  def detail
+    self['detail']
+  end
+
+  def faultcode=(rhs)
+    self['faultcode'] = rhs
+  end
+
+  def faultstring=(rhs)
+    self['faultstring'] = rhs
+  end
+
+  def faultactor=(rhs)
+    self['faultactor'] = rhs
+  end
+
+  def detail=(rhs)
+    self['detail'] = rhs
+  end
+
+  def initialize(faultcode = nil, faultstring = nil, faultactor = nil, detail = nil)
+    super(EleFaultName)
+    @elename = EleFaultName
+    @encodingstyle = EncodingNamespace
+
+    if faultcode
+      self.faultcode = faultcode
+      self.faultstring = faultstring
+      self.faultactor = faultactor
+      self.detail = detail
+      self.faultcode.elename = EleFaultCodeName if self.faultcode
+      self.faultstring.elename = EleFaultStringName if self.faultstring
+      self.faultactor.elename = EleFaultActorName if self.faultactor
+      self.detail.elename = EleFaultDetailName if self.detail
+    end
+    faultcode.parent = self if faultcode
+    faultstring.parent = self if faultstring
+    faultactor.parent = self if faultactor
+    detail.parent = self if detail
+  end
+
+  def encode(generator, ns, attrs = {})
+    SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace)
+    SOAPGenerator.assign_ns(attrs, ns, EncodingNamespace)
+    attrs[ns.name(AttrEncodingStyleName)] = EncodingNamespace
+    name = ns.name(@elename)
+    generator.encode_tag(name, attrs)
+    yield(self.faultcode)
+    yield(self.faultstring)
+    yield(self.faultactor)
+    yield(self.detail) if self.detail
+    generator.encode_tag_end(name, true)
+  end
+end
+
+
+class SOAPBody < SOAPStruct
+  include SOAPEnvelopeElement
+
+  def initialize(data = nil, is_fault = false)
+    super(nil)
+    @elename = EleBodyName
+    @encodingstyle = nil
+    if data
+      if data.respond_to?(:elename)
+        add(data.elename.name, data)
+      else
+        data.to_a.each do |datum|
+          add(datum.elename.name, datum)
+        end
+      end
+    end
+    @is_fault = is_fault
+  end
+
+  def encode(generator, ns, attrs = {})
+    name = ns.name(@elename)
+    generator.encode_tag(name, attrs)
+    if @is_fault
+      yield(@data)
+    else
+      @data.each do |data|
+	yield(data)
+      end
+    end
+    generator.encode_tag_end(name, true)
+  end
+
+  def root_node
+    @data.each do |node|
+      if node.root == 1
+	return node
+      end
+    end
+    # No specified root...
+    @data.each do |node|
+      if node.root != 0
+	return node
+      end
+    end
+
+    raise Parser::FormatDecodeError.new('no root element')
+  end
+end
+
+
+class SOAPHeaderItem < XSD::NSDBase
+  include SOAPEnvelopeElement
+  include SOAPCompoundtype
+
+public
+
+  attr_accessor :element
+  attr_accessor :mustunderstand
+  attr_accessor :encodingstyle
+
+  def initialize(element, mustunderstand = true, encodingstyle = nil)
+    super()
+    @type = nil
+    @element = element
+    @mustunderstand = mustunderstand
+    @encodingstyle = encodingstyle
+    element.parent = self if element
+  end
+
+  def encode(generator, ns, attrs = {})
+    attrs.each do |key, value|
+      @element.extraattr[key] = value
+    end
+    @element.extraattr[ns.name(AttrMustUnderstandName)] =
+      (@mustunderstand ? '1' : '0')
+    if @encodingstyle
+      @element.extraattr[ns.name(AttrEncodingStyleName)] = @encodingstyle
+    end
+    @element.encodingstyle = @encodingstyle if !@element.encodingstyle
+    yield(@element)
+  end
+end
+
+
+class SOAPHeader < SOAPStruct
+  include SOAPEnvelopeElement
+
+  def initialize
+    super(nil)
+    @elename = EleHeaderName
+    @encodingstyle = nil
+  end
+
+  def encode(generator, ns, attrs = {})
+    name = ns.name(@elename)
+    generator.encode_tag(name, attrs)
+    @data.each do |data|
+      yield(data)
+    end
+    generator.encode_tag_end(name, true)
+  end
+
+  def add(name, value)
+    mu = (value.extraattr[AttrMustUnderstandName] == '1')
+    encstyle = value.extraattr[AttrEncodingStyleName]
+    item = SOAPHeaderItem.new(value, mu, encstyle)
+    super(name, item)
+  end
+
+  def length
+    @data.length
+  end
+  alias size length
+end
+
+
+class SOAPEnvelope < XSD::NSDBase
+  include SOAPEnvelopeElement
+  include SOAPCompoundtype
+
+  attr_reader :header
+  attr_reader :body
+  attr_reader :external_content
+
+  def initialize(header = nil, body = nil)
+    super()
+    @type = nil
+    @elename = EleEnvelopeName
+    @encodingstyle = nil
+    @header = header
+    @body = body
+    @external_content = {}
+    header.parent = self if header
+    body.parent = self if body
+  end
+
+  def header=(header)
+    header.parent = self
+    @header = header
+  end
+
+  def body=(body)
+    body.parent = self
+    @body = body
+  end
+
+  def encode(generator, ns, attrs = {})
+    SOAPGenerator.assign_ns(attrs, ns, elename.namespace, SOAPNamespaceTag)
+    name = ns.name(@elename)
+    generator.encode_tag(name, attrs)
+
+    yield(@header) if @header and @header.length > 0
+    yield(@body)
+
+    generator.encode_tag_end(name, true)
+  end
+
+  def to_ary
+    [header, body]
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/encodingstyle/aspDotNetHandler.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/encodingstyle/aspDotNetHandler.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/encodingstyle/aspDotNetHandler.rb	(revision 18425)
@@ -0,0 +1,213 @@
+# SOAP4R - ASP.NET EncodingStyle handler library
+# Copyright (C) 2001, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/encodingstyle/handler'
+
+
+module SOAP
+module EncodingStyle
+
+
+class ASPDotNetHandler < Handler
+  Namespace = 'http://tempuri.org/ASP.NET'
+  add_handler
+
+  def initialize(charset = nil)
+    super(charset)
+    @textbuf = ''
+    @decode_typemap = nil
+  end
+
+
+  ###
+  ## encode interface.
+  #
+  def encode_data(generator, ns, data, parent)
+    attrs = {}
+    # ASPDotNetHandler is intended to be used for accessing an ASP.NET doc/lit
+    # service as an rpc/encoded service.  in the situation, local elements
+    # should be qualified.  propagate parent's namespace to children.
+    if data.elename.namespace.nil?
+      data.elename.namespace = parent.elename.namespace
+    end
+    name = generator.encode_name(ns, data, attrs)
+    case data
+    when SOAPRawString
+      generator.encode_tag(name, attrs)
+      generator.encode_rawstring(data.to_s)
+    when XSD::XSDString
+      generator.encode_tag(name, attrs)
+      generator.encode_string(@charset ?
+        XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
+    when XSD::XSDAnySimpleType
+      generator.encode_tag(name, attrs)
+      generator.encode_string(data.to_s)
+    when SOAPStruct
+      generator.encode_tag(name, attrs)
+      data.each do |key, value|
+        generator.encode_child(ns, value, data)
+      end
+    when SOAPArray
+      generator.encode_tag(name, attrs)
+      data.traverse do |child, *rank|
+	data.position = nil
+        generator.encode_child(ns, child, data)
+      end
+    else
+      raise EncodingStyleError.new(
+        "unknown object:#{data} in this encodingStyle")
+    end
+  end
+
+  def encode_data_end(generator, ns, data, parent)
+    name = generator.encode_name_end(ns, data)
+    cr = data.is_a?(SOAPCompoundtype)
+    generator.encode_tag_end(name, cr)
+  end
+
+
+  ###
+  ## decode interface.
+  #
+  class SOAPTemporalObject
+    attr_accessor :parent
+
+    def initialize
+      @parent = nil
+    end
+  end
+
+  class SOAPUnknown < SOAPTemporalObject
+    def initialize(handler, elename)
+      super()
+      @handler = handler
+      @elename = elename
+    end
+
+    def as_struct
+      o = SOAPStruct.decode(@elename, XSD::AnyTypeName)
+      o.parent = @parent
+      o.type.name = @name
+      @handler.decode_parent(@parent, o)
+      o
+    end
+
+    def as_string
+      o = SOAPString.decode(@elename)
+      o.parent = @parent
+      @handler.decode_parent(@parent, o)
+      o
+    end
+
+    def as_nil
+      o = SOAPNil.decode(@elename)
+      o.parent = @parent
+      @handler.decode_parent(@parent, o)
+      o
+    end
+  end
+
+  def decode_tag(ns, elename, attrs, parent)
+    @textbuf = ''
+    o = SOAPUnknown.new(self, elename)
+    o.parent = parent
+    o
+  end
+
+  def decode_tag_end(ns, node)
+    o = node.node
+    if o.is_a?(SOAPUnknown)
+      newnode = o.as_string
+#	if /\A\s*\z/ =~ @textbuf
+#	  o.as_struct
+#	else
+#	  o.as_string
+#	end
+      node.replace_node(newnode)
+      o = node.node
+    end
+
+    decode_textbuf(o)
+    @textbuf = ''
+  end
+
+  def decode_text(ns, text)
+    # @textbuf is set at decode_tag_end.
+    @textbuf << text
+  end
+
+  def decode_prologue
+  end
+
+  def decode_epilogue
+  end
+
+  def decode_parent(parent, node)
+    case parent.node
+    when SOAPUnknown
+      newparent = parent.node.as_struct
+      node.parent = newparent
+      parent.replace_node(newparent)
+      decode_parent(parent, node)
+
+    when SOAPStruct
+      data = parent.node[node.elename.name]
+      case data
+      when nil
+	parent.node.add(node.elename.name, node)
+      when SOAPArray
+	name, type_ns = node.elename.name, node.type.namespace
+	data.add(node)
+	node.elename, node.type.namespace = name, type_ns
+      else
+	parent.node[node.elename.name] = SOAPArray.new
+	name, type_ns = data.elename.name, data.type.namespace
+	parent.node[node.elename.name].add(data)
+	data.elename.name, data.type.namespace = name, type_ns
+	name, type_ns = node.elename.name, node.type.namespace
+	parent.node[node.elename.name].add(node)
+	node.elename.name, node.type.namespace = name, type_ns
+      end
+
+    when SOAPArray
+      if node.position
+	parent.node[*(decode_arypos(node.position))] = node
+	parent.node.sparse = true
+      else
+	parent.node.add(node)
+      end
+
+    when SOAPBasetype
+      raise EncodingStyleError.new("SOAP base type must not have a child")
+
+    else
+      # SOAPUnknown does not have parent.
+      # raise EncodingStyleError.new("illegal parent: #{parent}")
+    end
+  end
+
+private
+
+  def decode_textbuf(node)
+    if node.is_a?(XSD::XSDString)
+      if @charset
+	node.set(XSD::Charset.encoding_from_xml(@textbuf, @charset))
+      else
+	node.set(@textbuf)
+      end
+    else
+      # Nothing to do...
+    end
+  end
+end
+
+ASPDotNetHandler.new
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/encodingstyle/handler.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/encodingstyle/handler.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/encodingstyle/handler.rb	(revision 18425)
@@ -0,0 +1,100 @@
+# SOAP4R - EncodingStyle handler library
+# Copyright (C) 2001, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/soap'
+require 'soap/baseData'
+require 'soap/element'
+
+
+module SOAP
+module EncodingStyle
+
+
+class Handler
+  @@handlers = {}
+
+  class EncodingStyleError < Error; end
+
+  class << self
+    def uri
+      self::Namespace
+    end
+
+    def handler(uri)
+      @@handlers[uri]
+    end
+
+    def each
+      @@handlers.each do |key, value|
+	yield(value)
+      end
+    end
+
+  private
+
+    def add_handler
+      @@handlers[self.uri] = self
+    end
+  end
+
+  attr_reader :charset
+  attr_accessor :generate_explicit_type
+  def decode_typemap=(definedtypes)
+    @decode_typemap = definedtypes
+  end
+
+  def initialize(charset)
+    @charset = charset
+    @generate_explicit_type = true
+    @decode_typemap = nil
+  end
+
+  ###
+  ## encode interface.
+  #
+  # Returns a XML instance as a string.
+  def encode_data(generator, ns, data, parent)
+    raise NotImplementError
+  end
+
+  def encode_data_end(generator, ns, data, parent)
+    raise NotImplementError
+  end
+
+  def encode_prologue
+  end
+
+  def encode_epilogue
+  end
+
+  ###
+  ## decode interface.
+  #
+  # Returns SOAP/OM data.
+  def decode_tag(ns, name, attrs, parent)
+    raise NotImplementError.new('Method decode_tag must be defined in derived class.')
+  end
+
+  def decode_tag_end(ns, name)
+    raise NotImplementError.new('Method decode_tag_end must be defined in derived class.')
+  end
+
+  def decode_text(ns, text)
+    raise NotImplementError.new('Method decode_text must be defined in derived class.')
+  end
+
+  def decode_prologue
+  end
+
+  def decode_epilogue
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/encodingstyle/literalHandler.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/encodingstyle/literalHandler.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/encodingstyle/literalHandler.rb	(revision 18425)
@@ -0,0 +1,226 @@
+# SOAP4R - XML Literal EncodingStyle handler library
+# Copyright (C) 2001, 2003-2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/encodingstyle/handler'
+
+
+module SOAP
+module EncodingStyle
+
+
+class LiteralHandler < Handler
+  Namespace = SOAP::LiteralNamespace
+  add_handler
+
+  def initialize(charset = nil)
+    super(charset)
+    @textbuf = ''
+  end
+
+
+  ###
+  ## encode interface.
+  #
+  def encode_data(generator, ns, data, parent)
+    attrs = {}
+    name = generator.encode_name(ns, data, attrs)
+    data.extraattr.each do |k, v|
+      # ToDo: check generator.attributeformdefault here
+      if k.is_a?(XSD::QName)
+        if k.namespace
+          SOAPGenerator.assign_ns(attrs, ns, k.namespace)
+          k = ns.name(k)
+        else
+          k = k.name
+        end
+      end
+      attrs[k] = v
+    end
+    case data
+    when SOAPRawString
+      generator.encode_tag(name, attrs)
+      generator.encode_rawstring(data.to_s)
+    when XSD::XSDString
+      generator.encode_tag(name, attrs)
+      str = data.to_s
+      str = XSD::Charset.encoding_to_xml(str, @charset) if @charset
+      generator.encode_string(str)
+    when XSD::XSDAnySimpleType
+      generator.encode_tag(name, attrs)
+      generator.encode_string(data.to_s)
+    when SOAPStruct
+      generator.encode_tag(name, attrs)
+      data.each do |key, value|
+        generator.encode_child(ns, value, data)
+      end
+    when SOAPArray
+      generator.encode_tag(name, attrs)
+      data.traverse do |child, *rank|
+	data.position = nil
+        generator.encode_child(ns, child, data)
+      end
+    when SOAPElement
+      # passes 2 times for simplifying namespace definition
+      data.each do |key, value|
+        if value.elename.namespace
+          SOAPGenerator.assign_ns(attrs, ns, value.elename.namespace)
+        end
+      end
+      generator.encode_tag(name, attrs)
+      generator.encode_rawstring(data.text) if data.text
+      data.each do |key, value|
+        generator.encode_child(ns, value, data)
+      end
+    else
+      raise EncodingStyleError.new(
+        "unknown object:#{data} in this encodingStyle")
+    end
+  end
+
+  def encode_data_end(generator, ns, data, parent)
+    name = generator.encode_name_end(ns, data)
+    cr = (data.is_a?(SOAPCompoundtype) or
+      (data.is_a?(SOAPElement) and !data.text))
+    generator.encode_tag_end(name, cr)
+  end
+
+
+  ###
+  ## decode interface.
+  #
+  class SOAPTemporalObject
+    attr_accessor :parent
+
+    def initialize
+      @parent = nil
+    end
+  end
+
+  class SOAPUnknown < SOAPTemporalObject
+    def initialize(handler, elename, extraattr)
+      super()
+      @handler = handler
+      @elename = elename
+      @extraattr = extraattr
+    end
+
+    def as_element
+      o = SOAPElement.decode(@elename)
+      o.parent = @parent
+      o.extraattr.update(@extraattr)
+      @handler.decode_parent(@parent, o)
+      o
+    end
+
+    def as_string
+      o = SOAPString.decode(@elename)
+      o.parent = @parent
+      o.extraattr.update(@extraattr)
+      @handler.decode_parent(@parent, o)
+      o
+    end
+
+    def as_nil
+      o = SOAPNil.decode(@elename)
+      o.parent = @parent
+      o.extraattr.update(@extraattr)
+      @handler.decode_parent(@parent, o)
+      o
+    end
+  end
+
+  def decode_tag(ns, elename, attrs, parent)
+    @textbuf = ''
+    o = SOAPUnknown.new(self, elename, decode_attrs(ns, attrs))
+    o.parent = parent
+    o
+  end
+
+  def decode_tag_end(ns, node)
+    o = node.node
+    if o.is_a?(SOAPUnknown)
+      newnode = if /\A\s*\z/ =~ @textbuf
+	  o.as_element
+	else
+	  o.as_string
+	end
+      node.replace_node(newnode)
+      o = node.node
+    end
+
+    decode_textbuf(o)
+    @textbuf = ''
+  end
+
+  def decode_text(ns, text)
+    # @textbuf is set at decode_tag_end.
+    @textbuf << text
+  end
+
+  def decode_attrs(ns, attrs)
+    extraattr = {}
+    attrs.each do |key, value|
+      qname = ns.parse_local(key)
+      extraattr[qname] = value
+    end
+    extraattr
+  end
+
+  def decode_prologue
+  end
+
+  def decode_epilogue
+  end
+
+  def decode_parent(parent, node)
+    return unless parent.node
+    case parent.node
+    when SOAPUnknown
+      newparent = parent.node.as_element
+      node.parent = newparent
+      parent.replace_node(newparent)
+      decode_parent(parent, node)
+    when SOAPElement
+      parent.node.add(node)
+      node.parent = parent.node
+    when SOAPStruct
+      parent.node.add(node.elename.name, node)
+      node.parent = parent.node
+    when SOAPArray
+      if node.position
+	parent.node[*(decode_arypos(node.position))] = node
+	parent.node.sparse = true
+      else
+	parent.node.add(node)
+      end
+      node.parent = parent.node
+    else
+      raise EncodingStyleError.new("illegal parent: #{parent.node}")
+    end
+  end
+
+private
+
+  def decode_textbuf(node)
+    if node.is_a?(XSD::XSDString)
+      if @charset
+	node.set(XSD::Charset.encoding_from_xml(@textbuf, @charset))
+      else
+	node.set(@textbuf)
+      end
+    else
+      # Nothing to do...
+    end
+  end
+end
+
+LiteralHandler.new
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/encodingstyle/soapHandler.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/encodingstyle/soapHandler.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/encodingstyle/soapHandler.rb	(revision 18425)
@@ -0,0 +1,582 @@
+# SOAP4R - SOAP EncodingStyle handler library
+# Copyright (C) 2001, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/encodingstyle/handler'
+
+
+module SOAP
+module EncodingStyle
+
+
+class SOAPHandler < Handler
+  Namespace = SOAP::EncodingNamespace
+  add_handler
+
+  def initialize(charset = nil)
+    super(charset)
+    @refpool = []
+    @idpool = []
+    @textbuf = ''
+    @is_first_top_ele = true
+  end
+
+
+  ###
+  ## encode interface.
+  #
+  def encode_data(generator, ns, data, parent)
+    attrs = encode_attrs(generator, ns, data, parent)
+    if parent && parent.is_a?(SOAPArray) && parent.position
+      attrs[ns.name(AttrPositionName)] = "[#{parent.position.join(',')}]"
+    end
+    name = generator.encode_name(ns, data, attrs)
+    case data
+    when SOAPReference
+      attrs['href'] = data.refidstr
+      generator.encode_tag(name, attrs)
+    when SOAPExternalReference
+      data.referred
+      attrs['href'] = data.refidstr
+      generator.encode_tag(name, attrs)
+    when SOAPRawString
+      generator.encode_tag(name, attrs)
+      generator.encode_rawstring(data.to_s)
+    when XSD::XSDString
+      generator.encode_tag(name, attrs)
+      generator.encode_string(@charset ?
+	XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
+    when XSD::XSDAnySimpleType
+      generator.encode_tag(name, attrs)
+      generator.encode_string(data.to_s)
+    when SOAPStruct
+      generator.encode_tag(name, attrs)
+      data.each do |key, value|
+        generator.encode_child(ns, value, data)
+      end
+    when SOAPArray
+      generator.encode_tag(name, attrs)
+      data.traverse do |child, *rank|
+	data.position = data.sparse ? rank : nil
+        generator.encode_child(ns, child, data)
+      end
+    else
+      raise EncodingStyleError.new(
+	"unknown object:#{data} in this encodingStyle")
+    end
+  end
+
+  def encode_data_end(generator, ns, data, parent)
+    name = generator.encode_name_end(ns, data)
+    cr = data.is_a?(SOAPCompoundtype)
+    generator.encode_tag_end(name, cr)
+  end
+
+
+  ###
+  ## decode interface.
+  #
+  class SOAPTemporalObject
+    attr_accessor :parent
+    attr_accessor :position
+    attr_accessor :id
+    attr_accessor :root
+
+    def initialize
+      @parent = nil
+      @position = nil
+      @id = nil
+      @root = nil
+    end
+  end
+
+  class SOAPUnknown < SOAPTemporalObject
+    attr_reader :type
+    attr_accessor :definedtype
+    attr_reader :extraattr
+
+    def initialize(handler, elename, type, extraattr)
+      super()
+      @handler = handler
+      @elename = elename
+      @type = type
+      @extraattr = extraattr
+      @definedtype = nil
+    end
+
+    def as_struct
+      o = SOAPStruct.decode(@elename, @type)
+      o.id = @id
+      o.root = @root
+      o.parent = @parent
+      o.position = @position
+      o.extraattr.update(@extraattr)
+      @handler.decode_parent(@parent, o)
+      o
+    end
+
+    def as_string
+      o = SOAPString.decode(@elename)
+      o.id = @id
+      o.root = @root
+      o.parent = @parent
+      o.position = @position
+      o.extraattr.update(@extraattr)
+      @handler.decode_parent(@parent, o)
+      o
+    end
+
+    def as_nil
+      o = SOAPNil.decode(@elename)
+      o.id = @id
+      o.root = @root
+      o.parent = @parent
+      o.position = @position
+      o.extraattr.update(@extraattr)
+      @handler.decode_parent(@parent, o)
+      o
+    end
+  end
+
+  def decode_tag(ns, elename, attrs, parent)
+    @textbuf = ''
+    is_nil, type, arytype, root, offset, position, href, id, extraattr =
+      decode_attrs(ns, attrs)
+    o = nil
+    if is_nil
+      o = SOAPNil.decode(elename)
+    elsif href
+      o = SOAPReference.decode(elename, href)
+      @refpool << o
+    elsif @decode_typemap
+      o = decode_tag_by_wsdl(ns, elename, type, parent.node, arytype, extraattr)
+    else
+      o = decode_tag_by_type(ns, elename, type, parent.node, arytype, extraattr)
+    end
+
+    if o.is_a?(SOAPArray)
+      if offset
+	o.offset = decode_arypos(offset)
+	o.sparse = true
+      else
+	o.sparse = false
+      end
+    end
+
+    o.parent = parent
+    o.id = id
+    o.root = root
+    o.position = position
+
+    unless o.is_a?(SOAPTemporalObject)
+      @idpool << o if o.id
+      decode_parent(parent, o)
+    end
+    o
+  end
+
+  def decode_tag_end(ns, node)
+    o = node.node
+    if o.is_a?(SOAPUnknown)
+      newnode = if /\A\s*\z/ =~ @textbuf
+	o.as_struct
+      else
+	o.as_string
+      end
+      if newnode.id
+	@idpool << newnode
+      end
+      node.replace_node(newnode)
+      o = node.node
+    end
+    decode_textbuf(o)
+    # unlink definedtype
+    o.definedtype = nil
+  end
+
+  def decode_text(ns, text)
+    @textbuf << text
+  end
+
+  def decode_prologue
+    @refpool.clear
+    @idpool.clear
+    @is_first_top_ele = true
+  end
+
+  def decode_epilogue
+    decode_resolve_id
+  end
+
+  def decode_parent(parent, node)
+    return unless parent.node
+    case parent.node
+    when SOAPUnknown
+      newparent = parent.node.as_struct
+      node.parent = newparent
+      if newparent.id
+	@idpool << newparent
+      end
+      parent.replace_node(newparent)
+      decode_parent(parent, node)
+    when SOAPStruct
+      parent.node.add(node.elename.name, node)
+      node.parent = parent.node
+    when SOAPArray
+      if node.position
+	parent.node[*(decode_arypos(node.position))] = node
+	parent.node.sparse = true
+      else
+	parent.node.add(node)
+      end
+      node.parent = parent.node
+    else
+      raise EncodingStyleError.new("illegal parent: #{parent.node}")
+    end
+  end
+
+private
+
+  def content_ranksize(typename)
+    typename.scan(/\[[\d,]*\]$/)[0]
+  end
+
+  def content_typename(typename)
+    typename.sub(/\[,*\]$/, '')
+  end
+
+  def create_arytype(ns, data)
+    XSD::QName.new(data.arytype.namespace,
+      content_typename(data.arytype.name) + "[#{data.size.join(',')}]")
+  end
+
+  def encode_attrs(generator, ns, data, parent)
+    attrs = {}
+    return attrs if data.is_a?(SOAPReference)
+
+    if !parent || parent.encodingstyle != EncodingNamespace
+      if @generate_explicit_type
+        SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace)
+        attrs[ns.name(AttrEncodingStyleName)] = EncodingNamespace
+      end
+      data.encodingstyle = EncodingNamespace
+    end
+
+    if data.is_a?(SOAPNil)
+      attrs[ns.name(XSD::AttrNilName)] = XSD::NilValue
+    elsif @generate_explicit_type
+      if data.type.namespace
+        SOAPGenerator.assign_ns(attrs, ns, data.type.namespace)
+      end
+      if data.is_a?(SOAPArray)
+	if data.arytype.namespace
+          SOAPGenerator.assign_ns(attrs, ns, data.arytype.namespace)
+   	end
+	SOAPGenerator.assign_ns(attrs, ns, EncodingNamespace)
+	attrs[ns.name(AttrArrayTypeName)] = ns.name(create_arytype(ns, data))
+	if data.type.name
+	  attrs[ns.name(XSD::AttrTypeName)] = ns.name(data.type)
+	end
+      elsif parent && parent.is_a?(SOAPArray) && (parent.arytype == data.type)
+	# No need to add.
+      elsif !data.type.namespace
+	# No need to add.
+      else
+	attrs[ns.name(XSD::AttrTypeName)] = ns.name(data.type)
+      end
+    end
+
+    data.extraattr.each do |key, value|
+      SOAPGenerator.assign_ns(attrs, ns, key.namespace)
+      attrs[ns.name(key)] = encode_attr_value(generator, ns, key, value)
+    end
+    if data.id
+      attrs['id'] = data.id
+    end
+    attrs
+  end
+
+  def encode_attr_value(generator, ns, qname, value)
+    if value.is_a?(SOAPType)
+      ref = SOAPReference.new(value)
+      generator.add_reftarget(qname.name, value)
+      ref.refidstr
+    else
+      value.to_s
+    end
+  end
+
+  def decode_tag_by_wsdl(ns, elename, typestr, parent, arytypestr, extraattr)
+    o = nil
+    if parent.class == SOAPBody
+      # root element: should branch by root attribute?
+      if @is_first_top_ele
+	# Unqualified name is allowed here.
+	@is_first_top_ele = false
+	type = @decode_typemap[elename] ||
+	  @decode_typemap.find_name(elename.name)
+	if type
+	  o = SOAPStruct.new(elename)
+	  o.definedtype = type
+	  return o
+	end
+      end
+      # multi-ref element.
+      if typestr
+	typename = ns.parse(typestr)
+	typedef = @decode_typemap[typename]
+	if typedef
+          return decode_definedtype(elename, typename, typedef, arytypestr)
+	end
+      end
+      return decode_tag_by_type(ns, elename, typestr, parent, arytypestr,
+	extraattr)
+    end
+
+    if parent.type == XSD::AnyTypeName
+      return decode_tag_by_type(ns, elename, typestr, parent, arytypestr,
+	extraattr)
+    end
+
+    # parent.definedtype == nil means the parent is SOAPUnknown.  SOAPUnknown
+    # is generated by decode_tag_by_type when its type is anyType.
+    parenttype = parent.definedtype || @decode_typemap[parent.type]
+    unless parenttype
+      return decode_tag_by_type(ns, elename, typestr, parent, arytypestr,
+	extraattr)
+    end
+
+    definedtype_name = parenttype.child_type(elename)
+    if definedtype_name and (klass = TypeMap[definedtype_name])
+      return decode_basetype(klass, elename)
+    elsif definedtype_name == XSD::AnyTypeName
+      return decode_tag_by_type(ns, elename, typestr, parent, arytypestr,
+	extraattr)
+    end
+
+    if definedtype_name
+      typedef = @decode_typemap[definedtype_name]
+    else
+      typedef = parenttype.child_defined_complextype(elename)
+    end
+    decode_definedtype(elename, definedtype_name, typedef, arytypestr)
+  end
+
+  def decode_definedtype(elename, typename, typedef, arytypestr)
+    unless typedef
+      raise EncodingStyleError.new("unknown type '#{typename}'")
+    end
+    if typedef.is_a?(::WSDL::XMLSchema::SimpleType)
+      decode_defined_simpletype(elename, typename, typedef, arytypestr)
+    else
+      decode_defined_complextype(elename, typename, typedef, arytypestr)
+    end
+  end
+
+  def decode_basetype(klass, elename)
+    klass.decode(elename)
+  end
+
+  def decode_defined_simpletype(elename, typename, typedef, arytypestr)
+    o = decode_basetype(TypeMap[typedef.base], elename)
+    o.definedtype = typedef
+    o
+  end
+
+  def decode_defined_complextype(elename, typename, typedef, arytypestr)
+    case typedef.compoundtype
+    when :TYPE_STRUCT, :TYPE_MAP
+      o = SOAPStruct.decode(elename, typename)
+      o.definedtype = typedef
+      return o
+    when :TYPE_ARRAY
+      expected_arytype = typedef.find_arytype
+      if arytypestr
+	actual_arytype = XSD::QName.new(expected_arytype.namespace,
+	  content_typename(expected_arytype.name) <<
+	  content_ranksize(arytypestr))
+	o = SOAPArray.decode(elename, typename, actual_arytype)
+      else
+	o = SOAPArray.new(typename, 1, expected_arytype)
+	o.elename = elename
+      end
+      o.definedtype = typedef
+      return o
+    when :TYPE_EMPTY
+      o = SOAPNil.decode(elename)
+      o.definedtype = typedef
+      return o
+    else
+      raise RuntimeError.new(
+        "Unknown kind of complexType: #{typedef.compoundtype}")
+    end
+    nil
+  end
+
+  def decode_tag_by_type(ns, elename, typestr, parent, arytypestr, extraattr)
+    if arytypestr
+      type = typestr ? ns.parse(typestr) : ValueArrayName
+      node = SOAPArray.decode(elename, type, ns.parse(arytypestr))
+      node.extraattr.update(extraattr)
+      return node
+    end
+
+    type = nil
+    if typestr
+      type = ns.parse(typestr)
+    elsif parent.is_a?(SOAPArray)
+      type = parent.arytype
+    else
+      # Since it's in dynamic(without any type) encoding process,
+      # assumes entity as its type itself.
+      #   <SOAP-ENC:Array ...> => type Array in SOAP-ENC.
+      #   <Country xmlns="foo"> => type Country in foo.
+      type = elename
+    end
+
+    if (klass = TypeMap[type])
+      node = decode_basetype(klass, elename)
+      node.extraattr.update(extraattr)
+      return node
+    end
+
+    # Unknown type... Struct or String
+    SOAPUnknown.new(self, elename, type, extraattr)
+  end
+
+  def decode_textbuf(node)
+    case node
+    when XSD::XSDHexBinary, XSD::XSDBase64Binary
+      node.set_encoded(@textbuf)
+    when XSD::XSDString
+      if @charset
+	@textbuf = XSD::Charset.encoding_from_xml(@textbuf, @charset)
+      end
+      if node.definedtype
+        node.definedtype.check_lexical_format(@textbuf)
+      end
+      node.set(@textbuf)
+    when SOAPNil
+      # Nothing to do.
+    when SOAPBasetype
+      node.set(@textbuf)
+    else
+      # Nothing to do...
+    end
+    @textbuf = ''
+  end
+
+  NilLiteralMap = {
+    'true' => true,
+    '1' => true,
+    'false' => false,
+    '0' => false
+  }
+  RootLiteralMap = {
+    '1' => 1,
+    '0' => 0
+  }
+  def decode_attrs(ns, attrs)
+    is_nil = false
+    type = nil
+    arytype = nil
+    root = nil
+    offset = nil
+    position = nil
+    href = nil
+    id = nil
+    extraattr = {}
+
+    attrs.each do |key, value|
+      qname = ns.parse(key)
+      case qname.namespace
+      when XSD::InstanceNamespace
+        case qname.name
+        when XSD::NilLiteral
+          is_nil = NilLiteralMap[value] or
+            raise EncodingStyleError.new("cannot accept attribute value: #{value} as the value of xsi:#{XSD::NilLiteral} (expected 'true', 'false', '1', or '0')")
+          next
+        when XSD::AttrType
+          type = value
+          next
+        end
+      when EncodingNamespace
+        case qname.name
+        when AttrArrayType
+          arytype = value
+          next
+        when AttrRoot
+          root = RootLiteralMap[value] or
+            raise EncodingStyleError.new(
+	      "illegal root attribute value: #{value}")
+          next
+        when AttrOffset
+          offset = value
+          next
+        when AttrPosition
+          position = value
+          next
+        end
+      end
+      if key == 'href'
+        href = value
+        next
+      elsif key == 'id'
+        id = value
+        next
+      end
+      qname = ns.parse_local(key)
+      extraattr[qname] = decode_attr_value(ns, qname, value)
+    end
+
+    return is_nil, type, arytype, root, offset, position, href, id, extraattr
+  end
+
+  def decode_attr_value(ns, qname, value)
+    if /\A#/ =~ value
+      o = SOAPReference.decode(nil, value)
+      @refpool << o
+      o
+    else
+      value
+    end
+  end
+
+  def decode_arypos(position)
+    /^\[(.+)\]$/ =~ position
+    $1.split(',').collect { |s| s.to_i }
+  end
+
+  def decode_resolve_id
+    count = @refpool.length	# To avoid infinite loop
+    while !@refpool.empty? && count > 0
+      @refpool = @refpool.find_all { |ref|
+	o = @idpool.find { |item|
+	  item.id == ref.refid
+	}
+	if o.is_a?(SOAPReference)
+	  true	# link of link.
+	elsif o
+	  ref.__setobj__(o)
+	  false
+	elsif o = ref.rootnode.external_content[ref.refid]
+	  ref.__setobj__(o)
+      	  false
+	else
+	  raise EncodingStyleError.new("unresolved reference: #{ref.refid}")
+	end
+      }
+      count -= 1
+    end
+  end
+end
+
+SOAPHandler.new
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/generator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/generator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/generator.rb	(revision 18425)
@@ -0,0 +1,268 @@
+# SOAP4R - SOAP XML Instance Generator library.
+# Copyright (C) 2001, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/ns'
+require 'soap/soap'
+require 'soap/baseData'
+require 'soap/encodingstyle/handler'
+
+
+module SOAP
+
+
+###
+## CAUTION: MT-unsafe
+#
+class SOAPGenerator
+  include SOAP
+
+  class FormatEncodeError < Error; end
+
+public
+
+  attr_accessor :charset
+  attr_accessor :default_encodingstyle
+  attr_accessor :generate_explicit_type
+  attr_accessor :use_numeric_character_reference
+
+  def initialize(opt = {})
+    @reftarget = nil
+    @handlers = {}
+    @charset = opt[:charset] || XSD::Charset.xml_encoding_label
+    @default_encodingstyle = opt[:default_encodingstyle] || EncodingNamespace
+    @generate_explicit_type =
+      opt.key?(:generate_explicit_type) ? opt[:generate_explicit_type] : true
+    @elementformdefault = opt[:elementformdefault]
+    @attributeformdefault = opt[:attributeformdefault]
+    @use_numeric_character_reference = opt[:use_numeric_character_reference]
+    @indentstr = opt[:no_indent] ? '' : '  '
+    @buf = @indent = @curr = nil
+  end
+
+  def generate(obj, io = nil)
+    @buf = io || ''
+    @indent = ''
+
+    prologue
+    @handlers.each do |uri, handler|
+      handler.encode_prologue
+    end
+
+    ns = XSD::NS.new
+    @buf << xmldecl
+    encode_data(ns, obj, nil)
+
+    @handlers.each do |uri, handler|
+      handler.encode_epilogue
+    end
+    epilogue
+
+    @buf
+  end
+
+  def encode_data(ns, obj, parent)
+    if obj.is_a?(SOAPEnvelopeElement)
+      encode_element(ns, obj, parent)
+      return
+    end
+    if @reftarget && !obj.precedents.empty?
+      add_reftarget(obj.elename.name, obj)
+      ref = SOAPReference.new(obj)
+      ref.elename = ref.elename.dup_name(obj.elename.name)
+      obj.precedents.clear	# Avoid cyclic delay.
+      obj.encodingstyle = parent.encodingstyle
+      # SOAPReference is encoded here.
+      obj = ref
+    end
+    encodingstyle = obj.encodingstyle
+    # Children's encodingstyle is derived from its parent.
+    encodingstyle ||= parent.encodingstyle if parent
+    obj.encodingstyle = encodingstyle
+    handler = find_handler(encodingstyle || @default_encodingstyle)
+    unless handler
+      raise FormatEncodeError.new("Unknown encodingStyle: #{ encodingstyle }.")
+    end
+    if !obj.elename.name
+      raise FormatEncodeError.new("Element name not defined: #{ obj }.")
+    end
+    handler.encode_data(self, ns, obj, parent)
+    handler.encode_data_end(self, ns, obj, parent)
+  end
+
+  def add_reftarget(name, node)
+    unless @reftarget
+      raise FormatEncodeError.new("Reftarget is not defined.")
+    end
+    @reftarget.add(name, node)
+  end
+
+  def encode_child(ns, child, parent)
+    indent_backup, @indent = @indent, @indent + @indentstr
+    encode_data(ns.clone_ns, child, parent)
+    @indent = indent_backup
+  end
+
+  def encode_element(ns, obj, parent)
+    attrs = {}
+    if obj.is_a?(SOAPBody)
+      @reftarget = obj
+      obj.encode(self, ns, attrs) do |child|
+	indent_backup, @indent = @indent, @indent + @indentstr
+        encode_data(ns.clone_ns, child, obj)
+	@indent = indent_backup
+      end
+      @reftarget = nil
+    else
+      if obj.is_a?(SOAPEnvelope)
+        # xsi:nil="true" can appear even if dumping without explicit type.
+        SOAPGenerator.assign_ns(attrs, ns,
+	  XSD::InstanceNamespace, XSINamespaceTag)
+        if @generate_explicit_type
+          SOAPGenerator.assign_ns(attrs, ns, XSD::Namespace, XSDNamespaceTag)
+        end
+      end
+      obj.encode(self, ns, attrs) do |child|
+	indent_backup, @indent = @indent, @indent + @indentstr
+        encode_data(ns.clone_ns, child, obj)
+	@indent = indent_backup
+      end
+    end
+  end
+
+  def encode_name(ns, data, attrs)
+    if element_local?(data)
+      data.elename.name
+    else
+      if element_qualified?(data)
+        SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace, '')
+      else
+        SOAPGenerator.assign_ns(attrs, ns, data.elename.namespace)
+      end
+      ns.name(data.elename)
+    end
+  end
+
+  def encode_name_end(ns, data)
+    if element_local?(data)
+      data.elename.name
+    else
+      ns.name(data.elename)
+    end
+  end
+
+  def encode_tag(elename, attrs = nil)
+    if !attrs or attrs.empty?
+      @buf << "\n#{ @indent }<#{ elename }>"
+    elsif attrs.size == 1
+      key, value = attrs.shift
+      @buf << %Q[\n#{ @indent }<#{ elename } #{ key }="#{ value }">]
+    else
+      @buf << "\n#{ @indent }<#{ elename } " <<
+        attrs.collect { |key, value|
+          %Q[#{ key }="#{ value }"]
+        }.join("\n#{ @indent }#{ @indentstr * 2 }") <<
+	'>'
+    end
+  end
+
+  def encode_tag_end(elename, cr = nil)
+    if cr
+      @buf << "\n#{ @indent }</#{ elename }>"
+    else
+      @buf << "</#{ elename }>"
+    end
+  end
+
+  def encode_rawstring(str)
+    @buf << str
+  end
+
+  EncodeMap = {
+    '&' => '&amp;',
+    '<' => '&lt;',
+    '>' => '&gt;',
+    '"' => '&quot;',
+    '\'' => '&apos;',
+    "\r" => '&#xd;'
+  }
+  EncodeCharRegexp = Regexp.new("[#{EncodeMap.keys.join}]")
+  def encode_string(str)
+    if @use_numeric_character_reference and !XSD::Charset.is_us_ascii(str)
+      str.gsub!(EncodeCharRegexp) { |c| EncodeMap[c] }
+      @buf << str.unpack("U*").collect { |c|
+        if c == 0x9 or c == 0xa or c == 0xd or (c >= 0x20 and c <= 0x7f)
+          c.chr
+        else
+          sprintf("&#x%x;", c)
+        end
+      }.join
+    else
+      @buf << str.gsub(EncodeCharRegexp) { |c| EncodeMap[c] }
+    end
+  end
+
+  def element_local?(element)
+    element.elename.namespace.nil?
+  end
+
+  def element_qualified?(element)
+    if element.respond_to?(:qualified)
+      if element.qualified.nil?
+        @elementformdefault
+      else
+        element.qualified
+      end
+    else
+      @elementformdefault
+    end
+  end
+
+  def self.assign_ns(attrs, ns, namespace, tag = nil)
+    if namespace.nil?
+      raise FormatEncodeError.new("empty namespace")
+    end
+    unless ns.assigned?(namespace)
+      tag = ns.assign(namespace, tag)
+      if tag == ''
+        attr = 'xmlns'
+      else
+        attr = "xmlns:#{tag}"
+      end
+      attrs[attr] = namespace
+    end
+  end
+
+private
+
+  def prologue
+  end
+
+  def epilogue
+  end
+
+  def find_handler(encodingstyle)
+    unless @handlers.key?(encodingstyle)
+      handler = SOAP::EncodingStyle::Handler.handler(encodingstyle).new(@charset)
+      handler.generate_explicit_type = @generate_explicit_type
+      handler.encode_prologue
+      @handlers[encodingstyle] = handler
+    end
+    @handlers[encodingstyle]
+  end
+
+  def xmldecl
+    if @charset
+      %Q[<?xml version="1.0" encoding="#{ @charset }" ?>]
+    else
+      %Q[<?xml version="1.0" ?>]
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/header/handler.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/header/handler.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/header/handler.rb	(revision 18425)
@@ -0,0 +1,57 @@
+# SOAP4R - SOAP Header handler item
+# Copyright (C) 2003, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/element'
+
+
+module SOAP
+module Header
+
+
+class Handler
+  attr_reader :elename
+  attr_reader :mustunderstand
+  attr_reader :encodingstyle
+
+  def initialize(elename)
+    @elename = elename
+    @mustunderstand = false
+    @encodingstyle = nil
+  end
+
+  # Should return a SOAP/OM, a SOAPHeaderItem or nil.
+  def on_outbound
+    nil
+  end
+
+  # Given header is a SOAPHeaderItem or nil.
+  def on_inbound(header, mustunderstand = false)
+    # do something.
+  end
+
+  def on_outbound_headeritem
+    item = on_outbound
+    if item.nil?
+      nil
+    elsif item.is_a?(::SOAP::SOAPHeaderItem)
+      item.elename = @elename
+      item
+    else
+      item.elename = @elename
+      ::SOAP::SOAPHeaderItem.new(item, @mustunderstand, @encodingstyle)
+    end
+  end
+
+  def on_inbound_headeritem(header)
+    on_inbound(header.element, header.mustunderstand)
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/header/handlerset.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/header/handlerset.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/header/handlerset.rb	(revision 18425)
@@ -0,0 +1,70 @@
+# SOAP4R - SOAP Header handler set
+# Copyright (C) 2003, 2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/namedelements'
+
+
+module SOAP
+module Header
+
+
+class HandlerSet
+  def initialize
+    @store = XSD::NamedElements.new
+  end
+
+  def dup
+    obj = HandlerSet.new
+    obj.store = @store.dup
+    obj
+  end
+
+  def add(handler)
+    @store << handler
+  end
+  alias << add
+
+  def delete(handler)
+    @store.delete(handler)
+  end
+
+  def include?(handler)
+    @store.include?(handler)
+  end
+
+  # returns: Array of SOAPHeaderItem
+  def on_outbound
+    @store.collect { |handler|
+      handler.on_outbound_headeritem
+    }.compact
+  end
+
+  # headers: SOAPHeaderItem enumerable object
+  def on_inbound(headers)
+    headers.each do |name, item|
+      handler = @store.find { |handler|
+        handler.elename == item.element.elename
+      }
+      if handler
+        handler.on_inbound_headeritem(item)
+      elsif item.mustunderstand
+        raise UnhandledMustUnderstandHeaderError.new(item.element.elename.to_s)
+      end
+    end
+  end
+
+protected
+
+  def store=(store)
+    @store = store
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/header/simplehandler.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/header/simplehandler.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/header/simplehandler.rb	(revision 18425)
@@ -0,0 +1,44 @@
+# SOAP4R - SOAP Simple header item handler
+# Copyright (C) 2003-2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/header/handler'
+require 'soap/baseData'
+
+
+module SOAP
+module Header
+
+
+class SimpleHandler < SOAP::Header::Handler
+  def initialize(elename)
+    super(elename)
+  end
+
+  # Should return a Hash, String or nil.
+  def on_simple_outbound
+    nil
+  end
+
+  # Given header is a Hash, String or nil.
+  def on_simple_inbound(header, mustunderstand)
+  end
+
+  def on_outbound
+    h = on_simple_outbound
+    h ? SOAPElement.from_obj(h, elename.namespace) : nil
+  end
+
+  def on_inbound(header, mustunderstand)
+    h = header.respond_to?(:to_obj) ? header.to_obj : header.data
+    on_simple_inbound(h, mustunderstand)
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/httpconfigloader.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/httpconfigloader.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/httpconfigloader.rb	(revision 18425)
@@ -0,0 +1,119 @@
+# SOAP4R - HTTP config loader.
+# Copyright (C) 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/property'
+
+
+module SOAP
+
+
+module HTTPConfigLoader
+module_function
+
+  def set_options(client, options)
+    client.proxy = options["proxy"]
+    options.add_hook("proxy") do |key, value|
+      client.proxy = value
+    end
+    client.no_proxy = options["no_proxy"]
+    options.add_hook("no_proxy") do |key, value|
+      client.no_proxy = value
+    end
+    if client.respond_to?(:protocol_version=)
+      client.protocol_version = options["protocol_version"]
+      options.add_hook("protocol_version") do |key, value|
+        client.protocol_version = value
+      end
+    end
+    ssl_config = options["ssl_config"] ||= ::SOAP::Property.new
+    set_ssl_config(client, ssl_config)
+    ssl_config.add_hook(true) do |key, value|
+      set_ssl_config(client, ssl_config)
+    end
+    basic_auth = options["basic_auth"] ||= ::SOAP::Property.new
+    set_basic_auth(client, basic_auth)
+    basic_auth.add_hook do |key, value|
+      set_basic_auth(client, basic_auth)
+    end
+    options.add_hook("connect_timeout") do |key, value|
+      client.connect_timeout = value
+    end
+    options.add_hook("send_timeout") do |key, value|
+      client.send_timeout = value
+    end
+    options.add_hook("receive_timeout") do |key, value|
+      client.receive_timeout = value
+    end
+  end
+
+  def set_basic_auth(client, basic_auth)
+    basic_auth.values.each do |url, userid, passwd|
+      client.set_basic_auth(url, userid, passwd)
+    end
+  end
+
+  def set_ssl_config(client, ssl_config)
+    ssl_config.each do |key, value|
+      cfg = client.ssl_config
+      if cfg.nil?
+        raise NotImplementedError.new("SSL not supported")
+      end
+      case key
+      when 'client_cert'
+        cfg.client_cert = cert_from_file(value)
+      when 'client_key'
+        cfg.client_key = key_from_file(value)
+      when 'client_ca'
+        cfg.client_ca = value
+      when 'ca_path'
+        cfg.set_trust_ca(value)
+      when 'ca_file'
+        cfg.set_trust_ca(value)
+      when 'crl'
+        cfg.set_crl(value)
+      when 'verify_mode'
+        cfg.verify_mode = ssl_config_int(value)
+      when 'verify_depth'
+        cfg.verify_depth = ssl_config_int(value)
+      when 'options'
+        cfg.options = value
+      when 'ciphers'
+        cfg.ciphers = value
+      when 'verify_callback'
+        cfg.verify_callback = value
+      when 'cert_store'
+        cfg.cert_store = value
+      else
+        raise ArgumentError.new("unknown ssl_config property #{key}")
+      end
+    end
+  end
+
+  def ssl_config_int(value)
+    if value.nil? or value.to_s.empty?
+      nil
+    else
+      begin
+        Integer(value)
+      rescue ArgumentError
+        ::SOAP::Property::Util.const_from_name(value.to_s)
+      end
+    end
+  end
+
+  def cert_from_file(filename)
+    OpenSSL::X509::Certificate.new(File.open(filename) { |f| f.read })
+  end
+
+  def key_from_file(filename)
+    OpenSSL::PKey::RSA.new(File.open(filename) { |f| f.read })
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping.rb	(revision 18425)
@@ -0,0 +1,10 @@
+# SOAP4R - Ruby type mapping utility.
+# Copyright (C) 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/mapping/mapping'
+require 'soap/mapping/registry'
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/factory.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/factory.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/factory.rb	(revision 18425)
@@ -0,0 +1,355 @@
+# SOAP4R - Mapping factory.
+# Copyright (C) 2000, 2001, 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+module SOAP
+module Mapping
+
+
+class Factory
+  include TraverseSupport
+
+  def initialize
+    # nothing to do
+  end
+
+  def obj2soap(soap_class, obj, info, map)
+    raise NotImplementError.new
+    # return soap_obj
+  end
+
+  def soap2obj(obj_class, node, info, map)
+    raise NotImplementError.new
+    # return convert_succeeded_or_not, obj
+  end
+
+  def setiv2obj(obj, node, map)
+    return if node.nil?
+    if obj.is_a?(Array)
+      setiv2ary(obj, node, map)
+    else
+      setiv2struct(obj, node, map)
+    end
+  end
+
+  def setiv2soap(node, obj, map)
+    if obj.class.class_variables.include?('@@schema_element')
+      obj.class.class_eval('@@schema_element').each do |name, info|
+        type, qname = info
+        if qname
+          elename = qname.name
+        else
+          elename = Mapping.name2elename(name)
+        end
+        node.add(elename,
+          Mapping._obj2soap(obj.instance_variable_get('@' + name), map))
+      end
+    else
+      # should we sort instance_variables?
+      obj.instance_variables.each do |var|
+        name = var.sub(/^@/, '')
+        elename = Mapping.name2elename(name)
+        node.add(elename,
+          Mapping._obj2soap(obj.instance_variable_get(var), map))
+      end
+    end
+  end
+
+private
+
+  def setiv2ary(obj, node, map)
+    node.each do |name, value|
+      Array.instance_method(:<<).bind(obj).call(Mapping._soap2obj(value, map))
+    end
+  end
+
+  def setiv2struct(obj, node, map)
+    vars = {}
+    node.each do |name, value|
+      vars[Mapping.elename2name(name)] = Mapping._soap2obj(value, map)
+    end
+    Mapping.set_attributes(obj, vars)
+  end
+end
+
+class StringFactory_ < Factory
+  def initialize(allow_original_mapping = false)
+    super()
+    @allow_original_mapping = allow_original_mapping
+  end
+
+  def obj2soap(soap_class, obj, info, map)
+    if !@allow_original_mapping and !obj.instance_variables.empty?
+      return nil
+    end
+    begin
+      unless XSD::Charset.is_ces(obj, Thread.current[:SOAPExternalCES])
+        return nil
+      end
+      encoded = XSD::Charset.encoding_conv(obj,
+        Thread.current[:SOAPExternalCES], XSD::Charset.encoding)
+      soap_obj = soap_class.new(encoded)
+    rescue XSD::ValueSpaceError
+      return nil
+    end
+    mark_marshalled_obj(obj, soap_obj)
+    soap_obj
+  end
+
+  def soap2obj(obj_class, node, info, map)
+    obj = Mapping.create_empty_object(obj_class)
+    decoded = XSD::Charset.encoding_conv(node.data, XSD::Charset.encoding,
+      Thread.current[:SOAPExternalCES])
+    obj.replace(decoded)
+    mark_unmarshalled_obj(node, obj)
+    return true, obj
+  end
+end
+
+class BasetypeFactory_ < Factory
+  def initialize(allow_original_mapping = false)
+    super()
+    @allow_original_mapping = allow_original_mapping
+  end
+
+  def obj2soap(soap_class, obj, info, map)
+    if !@allow_original_mapping and !obj.instance_variables.empty?
+      return nil
+    end
+    soap_obj = nil
+    begin
+      soap_obj = soap_class.new(obj)
+    rescue XSD::ValueSpaceError
+      return nil
+    end
+    if @allow_original_mapping
+      # Basetype except String should not be multiref-ed in SOAP/1.1.
+      mark_marshalled_obj(obj, soap_obj)
+    end
+    soap_obj
+  end
+
+  def soap2obj(obj_class, node, info, map)
+    obj = node.data
+    mark_unmarshalled_obj(node, obj)
+    return true, obj
+  end
+end
+
+class DateTimeFactory_ < Factory
+  def initialize(allow_original_mapping = false)
+    super()
+    @allow_original_mapping = allow_original_mapping
+  end
+
+  def obj2soap(soap_class, obj, info, map)
+    if !@allow_original_mapping and
+	Time === obj and !obj.instance_variables.empty?
+      return nil
+    end
+    soap_obj = nil
+    begin
+      soap_obj = soap_class.new(obj)
+    rescue XSD::ValueSpaceError
+      return nil
+    end
+    mark_marshalled_obj(obj, soap_obj)
+    soap_obj
+  end
+
+  def soap2obj(obj_class, node, info, map)
+    if node.respond_to?(:to_obj)
+      obj = node.to_obj(obj_class)
+      return false if obj.nil?
+      mark_unmarshalled_obj(node, obj)
+      return true, obj
+    else
+      return false
+    end
+  end
+end
+
+class Base64Factory_ < Factory
+  def obj2soap(soap_class, obj, info, map)
+    return nil unless obj.instance_variables.empty?
+    soap_obj = soap_class.new(obj)
+    mark_marshalled_obj(obj, soap_obj) if soap_obj
+    soap_obj
+  end
+
+  def soap2obj(obj_class, node, info, map)
+    obj = node.string
+    mark_unmarshalled_obj(node, obj)
+    return true, obj
+  end
+end
+
+class URIFactory_ < Factory
+  def obj2soap(soap_class, obj, info, map)
+    soap_obj = soap_class.new(obj)
+    mark_marshalled_obj(obj, soap_obj) if soap_obj
+    soap_obj
+  end
+
+  def soap2obj(obj_class, node, info, map)
+    obj = node.data
+    mark_unmarshalled_obj(node, obj)
+    return true, obj
+  end
+end
+
+class ArrayFactory_ < Factory
+  def initialize(allow_original_mapping = false)
+    super()
+    @allow_original_mapping = allow_original_mapping
+  end
+
+  # [[1], [2]] is converted to Array of Array, not 2-D Array.
+  # To create M-D Array, you must call Mapping.ary2md.
+  def obj2soap(soap_class, obj, info, map)
+    if !@allow_original_mapping and !obj.instance_variables.empty?
+      return nil
+    end
+    arytype = Mapping.obj2element(obj)
+    if arytype.name
+      arytype.namespace ||= RubyTypeNamespace
+    else
+      arytype = XSD::AnyTypeName
+    end
+    soap_obj = SOAPArray.new(ValueArrayName, 1, arytype)
+    mark_marshalled_obj(obj, soap_obj)
+    obj.each do |item|
+      soap_obj.add(Mapping._obj2soap(item, map))
+    end
+    soap_obj
+  end
+
+  def soap2obj(obj_class, node, info, map)
+    obj = Mapping.create_empty_object(obj_class)
+    mark_unmarshalled_obj(node, obj)
+    node.soap2array(obj) do |elem|
+      elem ? Mapping._soap2obj(elem, map) : nil
+    end
+    return true, obj
+  end
+end
+
+class TypedArrayFactory_ < Factory
+  def initialize(allow_original_mapping = false)
+    super()
+    @allow_original_mapping = allow_original_mapping
+  end
+
+  def obj2soap(soap_class, obj, info, map)
+    if !@allow_original_mapping and !obj.instance_variables.empty?
+      return nil
+    end
+    arytype = info[:type] || info[0]
+    soap_obj = SOAPArray.new(ValueArrayName, 1, arytype)
+    mark_marshalled_obj(obj, soap_obj)
+    obj.each do |var|
+      soap_obj.add(Mapping._obj2soap(var, map))
+    end
+    soap_obj
+  end
+
+  def soap2obj(obj_class, node, info, map)
+    if node.rank > 1
+      return false
+    end
+    arytype = info[:type] || info[0]
+    unless node.arytype == arytype
+      return false
+    end
+    obj = Mapping.create_empty_object(obj_class)
+    mark_unmarshalled_obj(node, obj)
+    node.soap2array(obj) do |elem|
+      elem ? Mapping._soap2obj(elem, map) : nil
+    end
+    return true, obj
+  end
+end
+
+class TypedStructFactory_ < Factory
+  def obj2soap(soap_class, obj, info, map)
+    type = info[:type] || info[0]
+    soap_obj = soap_class.new(type)
+    mark_marshalled_obj(obj, soap_obj)
+    if obj.class <= SOAP::Marshallable
+      setiv2soap(soap_obj, obj, map)
+    else
+      setiv2soap(soap_obj, obj, map)
+    end
+    soap_obj
+  end
+
+  def soap2obj(obj_class, node, info, map)
+    type = info[:type] || info[0]
+    unless node.type == type
+      return false
+    end
+    obj = Mapping.create_empty_object(obj_class)
+    mark_unmarshalled_obj(node, obj)
+    setiv2obj(obj, node, map)
+    return true, obj
+  end
+end
+
+MapQName = XSD::QName.new(ApacheSOAPTypeNamespace, 'Map')
+class HashFactory_ < Factory
+  def initialize(allow_original_mapping = false)
+    super()
+    @allow_original_mapping = allow_original_mapping
+  end
+
+  def obj2soap(soap_class, obj, info, map)
+    if !@allow_original_mapping and !obj.instance_variables.empty?
+      return nil
+    end
+    if !obj.default.nil? or
+	(obj.respond_to?(:default_proc) and obj.default_proc)
+      return nil
+    end
+    soap_obj = SOAPStruct.new(MapQName)
+    mark_marshalled_obj(obj, soap_obj)
+    obj.each do |key, value|
+      elem = SOAPStruct.new
+      elem.add("key", Mapping._obj2soap(key, map))
+      elem.add("value", Mapping._obj2soap(value, map))
+      # ApacheAxis allows only 'item' here.
+      soap_obj.add("item", elem)
+    end
+    soap_obj
+  end
+
+  def soap2obj(obj_class, node, info, map)
+    unless node.type == MapQName
+      return false
+    end
+    if node.class == SOAPStruct and node.key?('default')
+      return false
+    end
+    obj = Mapping.create_empty_object(obj_class)
+    mark_unmarshalled_obj(node, obj)
+    if node.class == SOAPStruct
+      node.each do |key, value|
+	obj[Mapping._soap2obj(value['key'], map)] =
+	  Mapping._soap2obj(value['value'], map)
+      end
+    else
+      node.each do |value|
+	obj[Mapping._soap2obj(value['key'], map)] =
+	  Mapping._soap2obj(value['value'], map)
+      end
+    end
+    return true, obj
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/mapping.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/mapping.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/mapping.rb	(revision 18425)
@@ -0,0 +1,381 @@
+# SOAP4R - Ruby type mapping utility.
+# Copyright (C) 2000, 2001, 2003-2005  NAKAMURA Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/codegen/gensupport'
+
+
+module SOAP
+
+
+module Mapping
+  RubyTypeNamespace = 'http://www.ruby-lang.org/xmlns/ruby/type/1.6'
+  RubyTypeInstanceNamespace =
+    'http://www.ruby-lang.org/xmlns/ruby/type-instance'
+  RubyCustomTypeNamespace = 'http://www.ruby-lang.org/xmlns/ruby/type/custom'
+  ApacheSOAPTypeNamespace = 'http://xml.apache.org/xml-soap'
+
+
+  # TraverseSupport breaks following thread variables.
+  #   Thread.current[:SOAPMarshalDataKey]
+  module TraverseSupport
+    def mark_marshalled_obj(obj, soap_obj)
+      raise if obj.nil?
+      Thread.current[:SOAPMarshalDataKey][obj.__id__] = soap_obj
+    end
+
+    def mark_unmarshalled_obj(node, obj)
+      return if obj.nil?
+      # node.id is not Object#id but SOAPReference#id
+      Thread.current[:SOAPMarshalDataKey][node.id] = obj
+    end
+  end
+
+
+  EMPTY_OPT = {}
+  def self.obj2soap(obj, registry = nil, type = nil, opt = EMPTY_OPT)
+    registry ||= Mapping::DefaultRegistry
+    soap_obj = nil
+    protect_threadvars(:SOAPMarshalDataKey, :SOAPExternalCES, :SOAPMarshalNoReference) do
+      Thread.current[:SOAPMarshalDataKey] = {}
+      Thread.current[:SOAPExternalCES] = opt[:external_ces] || $KCODE
+      Thread.current[:SOAPMarshalNoReference] = opt[:no_reference]
+      soap_obj = _obj2soap(obj, registry, type)
+    end
+    soap_obj
+  end
+
+  def self.soap2obj(node, registry = nil, klass = nil, opt = EMPTY_OPT)
+    registry ||= Mapping::DefaultRegistry
+    obj = nil
+    protect_threadvars(:SOAPMarshalDataKey, :SOAPExternalCES, :SOAPMarshalNoReference) do
+      Thread.current[:SOAPMarshalDataKey] = {}
+      Thread.current[:SOAPExternalCES] = opt[:external_ces] || $KCODE
+      Thread.current[:SOAPMarshalNoReference] = opt[:no_reference]
+      obj = _soap2obj(node, registry, klass)
+    end
+    obj
+  end
+
+  def self.ary2soap(ary, type_ns = XSD::Namespace, typename = XSD::AnyTypeLiteral, registry = nil, opt = EMPTY_OPT)
+    registry ||= Mapping::DefaultRegistry
+    type = XSD::QName.new(type_ns, typename)
+    soap_ary = SOAPArray.new(ValueArrayName, 1, type)
+    protect_threadvars(:SOAPMarshalDataKey, :SOAPExternalCES, :SOAPMarshalNoReference) do
+      Thread.current[:SOAPMarshalDataKey] = {}
+      Thread.current[:SOAPExternalCES] = opt[:external_ces] || $KCODE
+      Thread.current[:SOAPMarshalNoReference] = opt[:no_reference]
+      ary.each do |ele|
+        soap_ary.add(_obj2soap(ele, registry, type))
+      end
+    end
+    soap_ary
+  end
+
+  def self.ary2md(ary, rank, type_ns = XSD::Namespace, typename = XSD::AnyTypeLiteral, registry = nil, opt = EMPTY_OPT)
+    registry ||= Mapping::DefaultRegistry
+    type = XSD::QName.new(type_ns, typename)
+    md_ary = SOAPArray.new(ValueArrayName, rank, type)
+    protect_threadvars(:SOAPMarshalDataKey, :SOAPExternalCES, :SOAPMarshalNoReference) do
+      Thread.current[:SOAPMarshalDataKey] = {}
+      Thread.current[:SOAPExternalCES] = opt[:external_ces] || $KCODE
+      Thread.current[:SOAPMarshalNoReference] = opt[:no_reference]
+      add_md_ary(md_ary, ary, [], registry)
+    end
+    md_ary
+  end
+
+  def self.fault2exception(fault, registry = nil)
+    registry ||= Mapping::DefaultRegistry
+    detail = if fault.detail
+        soap2obj(fault.detail, registry) || ""
+      else
+        ""
+      end
+    if detail.is_a?(Mapping::SOAPException)
+      begin
+        e = detail.to_e
+	remote_backtrace = e.backtrace
+        e.set_backtrace(nil)
+        raise e # ruby sets current caller as local backtrace of e => e2.
+      rescue Exception => e
+	e.set_backtrace(remote_backtrace + e.backtrace[1..-1])
+        raise
+      end
+    else
+      fault.detail = detail
+      fault.set_backtrace(
+        if detail.is_a?(Array)
+	  detail
+        else
+          [detail.to_s]
+        end
+      )
+      raise
+    end
+  end
+
+  def self._obj2soap(obj, registry, type = nil)
+    if referent = Thread.current[:SOAPMarshalDataKey][obj.__id__] and
+        !Thread.current[:SOAPMarshalNoReference]
+      SOAPReference.new(referent)
+    elsif registry
+      registry.obj2soap(obj, type)
+    else
+      raise MappingError.new("no mapping registry given")
+    end
+  end
+
+  def self._soap2obj(node, registry, klass = nil)
+    if node.nil?
+      return nil
+    elsif node.is_a?(SOAPReference)
+      target = node.__getobj__
+      # target.id is not Object#id but SOAPReference#id
+      if referent = Thread.current[:SOAPMarshalDataKey][target.id] and
+          !Thread.current[:SOAPMarshalNoReference]
+        return referent
+      else
+        return _soap2obj(target, registry, klass)
+      end
+    end
+    return registry.soap2obj(node, klass)
+  end
+
+  if Object.respond_to?(:allocate)
+    # ruby/1.7 or later.
+    def self.create_empty_object(klass)
+      klass.allocate
+    end
+  else
+    MARSHAL_TAG = {
+      String => ['"', 1],
+      Regexp => ['/', 2],
+      Array => ['[', 1],
+      Hash => ['{', 1]
+    }
+    def self.create_empty_object(klass)
+      if klass <= Struct
+	name = klass.name
+	return ::Marshal.load(sprintf("\004\006S:%c%s\000", name.length + 5, name))
+      end
+      if MARSHAL_TAG.has_key?(klass)
+	tag, terminate = MARSHAL_TAG[klass]
+	return ::Marshal.load(sprintf("\004\006%s%s", tag, "\000" * terminate))
+      end
+      MARSHAL_TAG.each do |k, v|
+	if klass < k
+	  name = klass.name
+	  tag, terminate = v
+	  return ::Marshal.load(sprintf("\004\006C:%c%s%s%s", name.length + 5, name, tag, "\000" * terminate))
+	end
+      end
+      name = klass.name
+      ::Marshal.load(sprintf("\004\006o:%c%s\000", name.length + 5, name))
+    end
+  end
+
+  # Allow only (Letter | '_') (Letter | Digit | '-' | '_')* here.
+  # Caution: '.' is not allowed here.
+  # To follow XML spec., it should be NCName.
+  #   (denied chars) => .[0-F][0-F]
+  #   ex. a.b => a.2eb
+  #
+  def self.name2elename(name)
+    name.gsub(/([^a-zA-Z0-9:_\-]+)/n) {
+      '.' << $1.unpack('H2' * $1.size).join('.')
+    }.gsub(/::/n, '..')
+  end
+
+  def self.elename2name(name)
+    name.gsub(/\.\./n, '::').gsub(/((?:\.[0-9a-fA-F]{2})+)/n) {
+      [$1.delete('.')].pack('H*')
+    }
+  end
+
+  def self.const_from_name(name, lenient = false)
+    const = ::Object
+    name.sub(/\A::/, '').split('::').each do |const_str|
+      if XSD::CodeGen::GenSupport.safeconstname?(const_str)
+        if const.const_defined?(const_str)
+          const = const.const_get(const_str)
+          next
+        end
+      elsif lenient
+        const_str = XSD::CodeGen::GenSupport.safeconstname(const_str)
+        if const.const_defined?(const_str)
+          const = const.const_get(const_str)
+          next
+        end
+      end
+      return nil
+    end
+    const
+  end
+
+  def self.class_from_name(name, lenient = false)
+    const = const_from_name(name, lenient)
+    if const.is_a?(::Class)
+      const
+    else
+      nil
+    end
+  end
+
+  def self.module_from_name(name, lenient = false)
+    const = const_from_name(name, lenient)
+    if const.is_a?(::Module)
+      const
+    else
+      nil
+    end
+  end
+
+  def self.class2qname(klass)
+    name = schema_type_definition(klass)
+    namespace = schema_ns_definition(klass)
+    XSD::QName.new(namespace, name)
+  end
+
+  def self.class2element(klass)
+    type = Mapping.class2qname(klass)
+    type.name ||= Mapping.name2elename(klass.name)
+    type.namespace ||= RubyCustomTypeNamespace
+    type
+  end
+
+  def self.obj2element(obj)
+    name = namespace = nil
+    ivars = obj.instance_variables
+    if ivars.include?('@schema_type')
+      name = obj.instance_variable_get('@schema_type')
+    end
+    if ivars.include?('@schema_ns')
+      namespace = obj.instance_variable_get('@schema_ns')
+    end
+    if !name or !namespace
+      class2qname(obj.class)
+    else
+      XSD::QName.new(namespace, name)
+    end
+  end
+
+  def self.define_singleton_method(obj, name, &block)
+    sclass = (class << obj; self; end)
+    sclass.class_eval {
+      define_method(name, &block)
+    }
+  end
+
+  def self.get_attribute(obj, attr_name)
+    if obj.is_a?(::Hash)
+      obj[attr_name] || obj[attr_name.intern]
+    else
+      name = XSD::CodeGen::GenSupport.safevarname(attr_name)
+      if obj.instance_variables.include?('@' + name)
+        obj.instance_variable_get('@' + name)
+      elsif ((obj.is_a?(::Struct) or obj.is_a?(Marshallable)) and
+          obj.respond_to?(name))
+        obj.__send__(name)
+      end
+    end
+  end
+
+  def self.set_attributes(obj, values)
+    if obj.is_a?(::SOAP::Mapping::Object)
+      values.each do |attr_name, value|
+        obj.__add_xmlele_value(attr_name, value)
+      end
+    else
+      values.each do |attr_name, value|
+        name = XSD::CodeGen::GenSupport.safevarname(attr_name)
+        setter = name + "="
+        if obj.respond_to?(setter)
+          obj.__send__(setter, value)
+        else
+          obj.instance_variable_set('@' + name, value)
+          begin
+            define_attr_accessor(obj, name,
+              proc { instance_variable_get('@' + name) },
+              proc { |value| instance_variable_set('@' + name, value) })
+          rescue TypeError
+            # singleton class may not exist (e.g. Float)
+          end
+        end
+      end
+    end
+  end
+
+  def self.define_attr_accessor(obj, name, getterproc, setterproc = nil)
+    define_singleton_method(obj, name, &getterproc)
+    define_singleton_method(obj, name + '=', &setterproc) if setterproc
+  end
+
+  def self.schema_type_definition(klass)
+    class_schema_variable(:schema_type, klass)
+  end
+
+  def self.schema_ns_definition(klass)
+    class_schema_variable(:schema_ns, klass)
+  end
+
+  def self.schema_element_definition(klass)
+    schema_element = class_schema_variable(:schema_element, klass) or return nil
+    schema_ns = schema_ns_definition(klass)
+    elements = []
+    as_array = []
+    schema_element.each do |varname, definition|
+      class_name, name = definition
+      if /\[\]$/ =~ class_name
+        class_name = class_name.sub(/\[\]$/, '')
+        as_array << (name ? name.name : varname)
+      end
+      elements << [name || XSD::QName.new(schema_ns, varname), class_name]
+    end
+    [elements, as_array]
+  end
+
+  def self.schema_attribute_definition(klass)
+    class_schema_variable(:schema_attribute, klass)
+  end
+
+  class << Mapping
+  private
+
+    def class_schema_variable(sym, klass)
+      var = "@@#{sym}"
+      klass.class_variables.include?(var) ? klass.class_eval(var) : nil
+    end
+
+    def protect_threadvars(*symbols)
+      backup = {}
+      begin
+        symbols.each do |sym|
+          backup[sym] = Thread.current[sym]
+        end
+        yield
+      ensure
+        symbols.each do |sym|
+          Thread.current[sym] = backup[sym]
+        end
+      end
+    end
+
+    def add_md_ary(md_ary, ary, indices, registry)
+      for idx in 0..(ary.size - 1)
+        if ary[idx].is_a?(Array)
+          add_md_ary(md_ary, ary[idx], indices + [idx], registry)
+        else
+          md_ary[*(indices + [idx])] = _obj2soap(ary[idx], registry)
+        end
+      end
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/registry.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/registry.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/registry.rb	(revision 18425)
@@ -0,0 +1,541 @@
+# SOAP4R - Mapping registry.
+# Copyright (C) 2000, 2001, 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/baseData'
+require 'soap/mapping/mapping'
+require 'soap/mapping/typeMap'
+require 'soap/mapping/factory'
+require 'soap/mapping/rubytypeFactory'
+
+
+module SOAP
+
+
+module Marshallable
+  # @@type_ns = Mapping::RubyCustomTypeNamespace
+end
+
+
+module Mapping
+
+  
+module MappedException; end
+
+
+RubyTypeName = XSD::QName.new(RubyTypeInstanceNamespace, 'rubyType')
+RubyExtendName = XSD::QName.new(RubyTypeInstanceNamespace, 'extends')
+RubyIVarName = XSD::QName.new(RubyTypeInstanceNamespace, 'ivars')
+
+
+# Inner class to pass an exception.
+class SOAPException; include Marshallable
+  attr_reader :excn_type_name, :cause
+  def initialize(e)
+    @excn_type_name = Mapping.name2elename(e.class.to_s)
+    @cause = e
+  end
+
+  def to_e
+    if @cause.is_a?(::Exception)
+      @cause.extend(::SOAP::Mapping::MappedException)
+      return @cause
+    elsif @cause.respond_to?(:message) and @cause.respond_to?(:backtrace)
+      e = RuntimeError.new(@cause.message)
+      e.set_backtrace(@cause.backtrace)
+      return e
+    end
+    klass = Mapping.class_from_name(Mapping.elename2name(@excn_type_name.to_s))
+    if klass.nil? or not klass <= ::Exception
+      return RuntimeError.new(@cause.inspect)
+    end
+    obj = klass.new(@cause.message)
+    obj.extend(::SOAP::Mapping::MappedException)
+    obj
+  end
+end
+
+
+# For anyType object: SOAP::Mapping::Object not ::Object
+class Object; include Marshallable
+  def initialize
+    @__xmlele_type = {}
+    @__xmlele = []
+    @__xmlattr = {}
+  end
+
+  def inspect
+    sprintf("#<%s:0x%x%s>", self.class.name, __id__,
+      @__xmlele.collect { |name, value| " #{name}=#{value.inspect}" }.join)
+  end
+
+  def __xmlattr
+    @__xmlattr
+  end
+
+  def __xmlele
+    @__xmlele
+  end
+
+  def [](qname)
+    unless qname.is_a?(XSD::QName)
+      qname = XSD::QName.new(nil, qname)
+    end
+    @__xmlele.each do |k, v|
+      return v if k == qname
+    end
+    # fallback
+    @__xmlele.each do |k, v|
+      return v if k.name == qname.name
+    end
+    nil
+  end
+
+  def []=(qname, value)
+    unless qname.is_a?(XSD::QName)
+      qname = XSD::QName.new(nil, qname)
+    end
+    found = false
+    @__xmlele.each do |pair|
+      if pair[0] == qname
+        found = true
+        pair[1] = value
+      end
+    end
+    unless found
+      __define_attr_accessor(qname)
+      @__xmlele << [qname, value]
+    end
+    @__xmlele_type[qname] = :single
+  end
+
+  def __add_xmlele_value(qname, value)
+    found = false
+    @__xmlele.map! do |k, v|
+      if k == qname
+        found = true
+        [k, __set_xmlele_value(k, v, value)]
+      else
+        [k, v]
+      end
+    end
+    unless found
+      __define_attr_accessor(qname)
+      @__xmlele << [qname, value]
+      @__xmlele_type[qname] = :single
+    end
+    value
+  end
+
+private
+
+  if RUBY_VERSION > "1.7.0"
+    def __define_attr_accessor(qname)
+      name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
+      Mapping.define_attr_accessor(self, name,
+        proc { self[qname] },
+        proc { |value| self[qname] = value })
+    end
+  else
+    def __define_attr_accessor(qname)
+      name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
+      instance_eval <<-EOS
+        def #{name}
+          self[#{qname.dump}]
+        end
+
+        def #{name}=(value)
+          self[#{qname.dump}] = value
+        end
+      EOS
+    end
+  end
+
+  def __set_xmlele_value(key, org, value)
+    case @__xmlele_type[key]
+    when :multi
+      org << value
+      org
+    when :single
+      @__xmlele_type[key] = :multi
+      [org, value]
+    else
+      raise RuntimeError.new("unknown type")
+    end
+  end
+end
+
+
+class MappingError < Error; end
+
+
+class Registry
+  class Map
+    def initialize(registry)
+      @obj2soap = {}
+      @soap2obj = {}
+      @registry = registry
+    end
+
+    def obj2soap(obj)
+      klass = obj.class
+      if map = @obj2soap[klass]
+        map.each do |soap_class, factory, info|
+          ret = factory.obj2soap(soap_class, obj, info, @registry)
+          return ret if ret
+        end
+      end
+      ancestors = klass.ancestors
+      ancestors.delete(klass)
+      ancestors.delete(::Object)
+      ancestors.delete(::Kernel)
+      ancestors.each do |klass|
+        if map = @obj2soap[klass]
+          map.each do |soap_class, factory, info|
+            if info[:derived_class]
+              ret = factory.obj2soap(soap_class, obj, info, @registry)
+              return ret if ret
+            end
+          end
+        end
+      end
+      nil
+    end
+
+    def soap2obj(node, klass = nil)
+      if map = @soap2obj[node.class]
+        map.each do |obj_class, factory, info|
+          next if klass and obj_class != klass
+          conv, obj = factory.soap2obj(obj_class, node, info, @registry)
+          return true, obj if conv
+        end
+      end
+      return false, nil
+    end
+
+    # Give priority to former entry.
+    def init(init_map = [])
+      clear
+      init_map.reverse_each do |obj_class, soap_class, factory, info|
+        add(obj_class, soap_class, factory, info)
+      end
+    end
+
+    # Give priority to latter entry.
+    def add(obj_class, soap_class, factory, info)
+      info ||= {}
+      (@obj2soap[obj_class] ||= []).unshift([soap_class, factory, info])
+      (@soap2obj[soap_class] ||= []).unshift([obj_class, factory, info])
+    end
+
+    def clear
+      @obj2soap.clear
+      @soap2obj.clear
+    end
+
+    def find_mapped_soap_class(target_obj_class)
+      map = @obj2soap[target_obj_class]
+      map.empty? ? nil : map[0][1]
+    end
+
+    def find_mapped_obj_class(target_soap_class)
+      map = @soap2obj[target_soap_class]
+      map.empty? ? nil : map[0][0]
+    end
+  end
+
+  StringFactory = StringFactory_.new
+  BasetypeFactory = BasetypeFactory_.new
+  DateTimeFactory = DateTimeFactory_.new
+  ArrayFactory = ArrayFactory_.new
+  Base64Factory = Base64Factory_.new
+  URIFactory = URIFactory_.new
+  TypedArrayFactory = TypedArrayFactory_.new
+  TypedStructFactory = TypedStructFactory_.new
+
+  HashFactory = HashFactory_.new
+
+  SOAPBaseMap = [
+    [::NilClass,     ::SOAP::SOAPNil,        BasetypeFactory],
+    [::TrueClass,    ::SOAP::SOAPBoolean,    BasetypeFactory],
+    [::FalseClass,   ::SOAP::SOAPBoolean,    BasetypeFactory],
+    [::String,       ::SOAP::SOAPString,     StringFactory],
+    [::DateTime,     ::SOAP::SOAPDateTime,   DateTimeFactory],
+    [::Date,         ::SOAP::SOAPDate,       DateTimeFactory],
+    [::Time,         ::SOAP::SOAPDateTime,   DateTimeFactory],
+    [::Time,         ::SOAP::SOAPTime,       DateTimeFactory],
+    [::Float,        ::SOAP::SOAPDouble,     BasetypeFactory,
+      {:derived_class => true}],
+    [::Float,        ::SOAP::SOAPFloat,      BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPInt,        BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPLong,       BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPInteger,    BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPShort,      BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPByte,       BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPNonPositiveInteger, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPNegativeInteger, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPNonNegativeInteger, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPPositiveInteger, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPUnsignedLong, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPUnsignedInt, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPUnsignedShort, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPUnsignedByte, BasetypeFactory,
+      {:derived_class => true}],
+    [::URI::Generic, ::SOAP::SOAPAnyURI,     URIFactory,
+      {:derived_class => true}],
+    [::String,       ::SOAP::SOAPBase64,     Base64Factory],
+    [::String,       ::SOAP::SOAPHexBinary,  Base64Factory],
+    [::String,       ::SOAP::SOAPDecimal,    BasetypeFactory],
+    [::String,       ::SOAP::SOAPDuration,   BasetypeFactory],
+    [::String,       ::SOAP::SOAPGYearMonth, BasetypeFactory],
+    [::String,       ::SOAP::SOAPGYear,      BasetypeFactory],
+    [::String,       ::SOAP::SOAPGMonthDay,  BasetypeFactory],
+    [::String,       ::SOAP::SOAPGDay,       BasetypeFactory],
+    [::String,       ::SOAP::SOAPGMonth,     BasetypeFactory],
+    [::String,       ::SOAP::SOAPQName,      BasetypeFactory],
+
+    [::Hash,         ::SOAP::SOAPArray,      HashFactory],
+    [::Hash,         ::SOAP::SOAPStruct,     HashFactory],
+
+    [::Array,        ::SOAP::SOAPArray,      ArrayFactory,
+      {:derived_class => true}],
+
+    [::SOAP::Mapping::SOAPException,
+		     ::SOAP::SOAPStruct,     TypedStructFactory,
+      {:type => XSD::QName.new(RubyCustomTypeNamespace, "SOAPException")}],
+ ]
+
+  RubyOriginalMap = [
+    [::NilClass,     ::SOAP::SOAPNil,        BasetypeFactory],
+    [::TrueClass,    ::SOAP::SOAPBoolean,    BasetypeFactory],
+    [::FalseClass,   ::SOAP::SOAPBoolean,    BasetypeFactory],
+    [::String,       ::SOAP::SOAPString,     StringFactory],
+    [::DateTime,     ::SOAP::SOAPDateTime,   DateTimeFactory],
+    [::Date,         ::SOAP::SOAPDate,       DateTimeFactory],
+    [::Time,         ::SOAP::SOAPDateTime,   DateTimeFactory],
+    [::Time,         ::SOAP::SOAPTime,       DateTimeFactory],
+    [::Float,        ::SOAP::SOAPDouble,     BasetypeFactory,
+      {:derived_class => true}],
+    [::Float,        ::SOAP::SOAPFloat,      BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPInt,        BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPLong,       BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPInteger,    BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPShort,      BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPByte,       BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPNonPositiveInteger, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPNegativeInteger, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPNonNegativeInteger, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPPositiveInteger, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPUnsignedLong, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPUnsignedInt, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPUnsignedShort, BasetypeFactory,
+      {:derived_class => true}],
+    [::Integer,      ::SOAP::SOAPUnsignedByte, BasetypeFactory,
+      {:derived_class => true}],
+    [::URI::Generic, ::SOAP::SOAPAnyURI,     URIFactory,
+      {:derived_class => true}],
+    [::String,       ::SOAP::SOAPBase64,     Base64Factory],
+    [::String,       ::SOAP::SOAPHexBinary,  Base64Factory],
+    [::String,       ::SOAP::SOAPDecimal,    BasetypeFactory],
+    [::String,       ::SOAP::SOAPDuration,   BasetypeFactory],
+    [::String,       ::SOAP::SOAPGYearMonth, BasetypeFactory],
+    [::String,       ::SOAP::SOAPGYear,      BasetypeFactory],
+    [::String,       ::SOAP::SOAPGMonthDay,  BasetypeFactory],
+    [::String,       ::SOAP::SOAPGDay,       BasetypeFactory],
+    [::String,       ::SOAP::SOAPGMonth,     BasetypeFactory],
+    [::String,       ::SOAP::SOAPQName,      BasetypeFactory],
+
+    [::Hash,         ::SOAP::SOAPArray,      HashFactory],
+    [::Hash,         ::SOAP::SOAPStruct,     HashFactory],
+
+    # Does not allow Array's subclass here.
+    [::Array,        ::SOAP::SOAPArray,      ArrayFactory],
+
+    [::SOAP::Mapping::SOAPException,
+                     ::SOAP::SOAPStruct,     TypedStructFactory,
+      {:type => XSD::QName.new(RubyCustomTypeNamespace, "SOAPException")}],
+  ]
+
+  attr_accessor :default_factory
+  attr_accessor :excn_handler_obj2soap
+  attr_accessor :excn_handler_soap2obj
+
+  def initialize(config = {})
+    @config = config
+    @map = Map.new(self)
+    if @config[:allow_original_mapping]
+      @allow_original_mapping = true
+      @map.init(RubyOriginalMap)
+    else
+      @allow_original_mapping = false
+      @map.init(SOAPBaseMap)
+    end
+    @allow_untyped_struct = @config.key?(:allow_untyped_struct) ?
+      @config[:allow_untyped_struct] : true
+    @rubytype_factory = RubytypeFactory.new(
+      :allow_untyped_struct => @allow_untyped_struct,
+      :allow_original_mapping => @allow_original_mapping
+    )
+    @default_factory = @rubytype_factory
+    @excn_handler_obj2soap = nil
+    @excn_handler_soap2obj = nil
+  end
+
+  def add(obj_class, soap_class, factory, info = nil)
+    @map.add(obj_class, soap_class, factory, info)
+  end
+  alias set add
+
+  # general Registry ignores type_qname
+  def obj2soap(obj, type_qname = nil)
+    soap = _obj2soap(obj)
+    if @allow_original_mapping
+      addextend2soap(soap, obj)
+    end
+    soap
+  end
+
+  def soap2obj(node, klass = nil)
+    obj = _soap2obj(node, klass)
+    if @allow_original_mapping
+      addextend2obj(obj, node.extraattr[RubyExtendName])
+      addiv2obj(obj, node.extraattr[RubyIVarName])
+    end
+    obj
+  end
+
+  def find_mapped_soap_class(obj_class)
+    @map.find_mapped_soap_class(obj_class)
+  end
+
+  def find_mapped_obj_class(soap_class)
+    @map.find_mapped_obj_class(soap_class)
+  end
+
+private
+
+  def _obj2soap(obj)
+    ret = nil
+    if obj.is_a?(SOAPStruct) or obj.is_a?(SOAPArray)
+      obj.replace do |ele|
+        Mapping._obj2soap(ele, self)
+      end
+      return obj
+    elsif obj.is_a?(SOAPBasetype)
+      return obj
+    end
+    begin 
+      ret = @map.obj2soap(obj) ||
+        @default_factory.obj2soap(nil, obj, nil, self)
+      return ret if ret
+    rescue MappingError
+    end
+    if @excn_handler_obj2soap
+      ret = @excn_handler_obj2soap.call(obj) { |yield_obj|
+        Mapping._obj2soap(yield_obj, self)
+      }
+      return ret if ret
+    end
+    raise MappingError.new("Cannot map #{ obj.class.name } to SOAP/OM.")
+  end
+
+  # Might return nil as a mapping result.
+  def _soap2obj(node, klass = nil)
+    if node.extraattr.key?(RubyTypeName)
+      conv, obj = @rubytype_factory.soap2obj(nil, node, nil, self)
+      return obj if conv
+    else
+      conv, obj = @map.soap2obj(node, klass)
+      return obj if conv
+      conv, obj = @default_factory.soap2obj(nil, node, nil, self)
+      return obj if conv
+    end
+    if @excn_handler_soap2obj
+      begin
+        return @excn_handler_soap2obj.call(node) { |yield_node|
+	    Mapping._soap2obj(yield_node, self)
+	  }
+      rescue Exception
+      end
+    end
+    raise MappingError.new("Cannot map #{ node.type.name } to Ruby object.")
+  end
+
+  def addiv2obj(obj, attr)
+    return unless attr
+    vars = {}
+    attr.__getobj__.each do |name, value|
+      vars[name] = Mapping._soap2obj(value, self)
+    end
+    Mapping.set_attributes(obj, vars)
+  end
+
+  if RUBY_VERSION >= '1.8.0'
+    def addextend2obj(obj, attr)
+      return unless attr
+      attr.split(/ /).reverse_each do |mstr|
+	obj.extend(Mapping.module_from_name(mstr))
+      end
+    end
+  else
+    # (class < false; self; end).ancestors includes "TrueClass" under 1.6...
+    def addextend2obj(obj, attr)
+      return unless attr
+      attr.split(/ /).reverse_each do |mstr|
+	m = Mapping.module_from_name(mstr)
+	obj.extend(m)
+      end
+    end
+  end
+
+  def addextend2soap(node, obj)
+    return if obj.is_a?(Symbol) or obj.is_a?(Fixnum)
+    list = (class << obj; self; end).ancestors - obj.class.ancestors
+    unless list.empty?
+      node.extraattr[RubyExtendName] = list.collect { |c|
+	if c.name.empty?
+  	  raise TypeError.new("singleton can't be dumped #{ obj }")
+   	end
+	c.name
+      }.join(" ")
+    end
+  end
+
+end
+
+
+DefaultRegistry = Registry.new
+RubyOriginalRegistry = Registry.new(:allow_original_mapping => true)
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/rubytypeFactory.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/rubytypeFactory.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/rubytypeFactory.rb	(revision 18425)
@@ -0,0 +1,475 @@
+# SOAP4R - Ruby type mapping factory.
+# Copyright (C) 2000-2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+module SOAP
+module Mapping
+
+
+class RubytypeFactory < Factory
+  TYPE_STRING = XSD::QName.new(RubyTypeNamespace, 'String')
+  TYPE_TIME = XSD::QName.new(RubyTypeNamespace, 'Time')
+  TYPE_ARRAY = XSD::QName.new(RubyTypeNamespace, 'Array')
+  TYPE_REGEXP = XSD::QName.new(RubyTypeNamespace, 'Regexp')
+  TYPE_RANGE = XSD::QName.new(RubyTypeNamespace, 'Range')
+  TYPE_CLASS = XSD::QName.new(RubyTypeNamespace, 'Class')
+  TYPE_MODULE = XSD::QName.new(RubyTypeNamespace, 'Module')
+  TYPE_SYMBOL = XSD::QName.new(RubyTypeNamespace, 'Symbol')
+  TYPE_STRUCT = XSD::QName.new(RubyTypeNamespace, 'Struct')
+  TYPE_HASH = XSD::QName.new(RubyTypeNamespace, 'Map')
+
+  def initialize(config = {})
+    @config = config
+    @allow_untyped_struct = @config.key?(:allow_untyped_struct) ?
+      @config[:allow_untyped_struct] : true
+    @allow_original_mapping = @config.key?(:allow_original_mapping) ?
+      @config[:allow_original_mapping] : false
+    @string_factory = StringFactory_.new(true)
+    @basetype_factory = BasetypeFactory_.new(true)
+    @datetime_factory = DateTimeFactory_.new(true)
+    @array_factory = ArrayFactory_.new(true)
+    @hash_factory = HashFactory_.new(true)
+  end
+
+  def obj2soap(soap_class, obj, info, map)
+    param = nil
+    case obj
+    when ::String
+      unless @allow_original_mapping
+        return nil
+      end
+      param = @string_factory.obj2soap(SOAPString, obj, info, map)
+      if obj.class != String
+        param.extraattr[RubyTypeName] = obj.class.name
+      end
+      addiv2soapattr(param, obj, map)
+    when ::Time
+      unless @allow_original_mapping
+        return nil
+      end
+      param = @datetime_factory.obj2soap(SOAPDateTime, obj, info, map)
+      if obj.class != Time
+        param.extraattr[RubyTypeName] = obj.class.name
+      end
+      addiv2soapattr(param, obj, map)
+    when ::Array
+      unless @allow_original_mapping
+        return nil
+      end
+      param = @array_factory.obj2soap(nil, obj, info, map)
+      if obj.class != Array
+        param.extraattr[RubyTypeName] = obj.class.name
+      end
+      addiv2soapattr(param, obj, map)
+    when ::NilClass
+      unless @allow_original_mapping
+        return nil
+      end
+      param = @basetype_factory.obj2soap(SOAPNil, obj, info, map)
+      addiv2soapattr(param, obj, map)
+    when ::FalseClass, ::TrueClass
+      unless @allow_original_mapping
+        return nil
+      end
+      param = @basetype_factory.obj2soap(SOAPBoolean, obj, info, map)
+      addiv2soapattr(param, obj, map)
+    when ::Integer
+      unless @allow_original_mapping
+        return nil
+      end
+      param = @basetype_factory.obj2soap(SOAPInt, obj, info, map)
+      param ||= @basetype_factory.obj2soap(SOAPInteger, obj, info, map)
+      param ||= @basetype_factory.obj2soap(SOAPDecimal, obj, info, map)
+      addiv2soapattr(param, obj, map)
+    when ::Float
+      unless @allow_original_mapping
+        return nil
+      end
+      param = @basetype_factory.obj2soap(SOAPDouble, obj, info, map)
+      if obj.class != Float
+        param.extraattr[RubyTypeName] = obj.class.name
+      end
+      addiv2soapattr(param, obj, map)
+    when ::Hash
+      unless @allow_original_mapping
+        return nil
+      end
+      if obj.respond_to?(:default_proc) && obj.default_proc
+        raise TypeError.new("cannot dump hash with default proc")
+      end
+      param = SOAPStruct.new(TYPE_HASH)
+      mark_marshalled_obj(obj, param)
+      if obj.class != Hash
+        param.extraattr[RubyTypeName] = obj.class.name
+      end
+      obj.each do |key, value|
+        elem = SOAPStruct.new # Undefined type.
+        elem.add("key", Mapping._obj2soap(key, map))
+        elem.add("value", Mapping._obj2soap(value, map))
+        param.add("item", elem)
+      end
+      param.add('default', Mapping._obj2soap(obj.default, map))
+      addiv2soapattr(param, obj, map)
+    when ::Regexp
+      unless @allow_original_mapping
+        return nil
+      end
+      param = SOAPStruct.new(TYPE_REGEXP)
+      mark_marshalled_obj(obj, param)
+      if obj.class != Regexp
+        param.extraattr[RubyTypeName] = obj.class.name
+      end
+      param.add('source', SOAPBase64.new(obj.source))
+      if obj.respond_to?('options')
+        # Regexp#options is from Ruby/1.7
+        options = obj.options
+      else
+        options = 0
+        obj.inspect.sub(/^.*\//, '').each_byte do |c|
+          options += case c
+            when ?i
+              1
+            when ?x
+              2
+            when ?m
+              4
+            when ?n
+              16
+            when ?e
+              32
+            when ?s
+              48
+            when ?u
+              64
+            end
+        end
+      end
+      param.add('options', SOAPInt.new(options))
+      addiv2soapattr(param, obj, map)
+    when ::Range
+      unless @allow_original_mapping
+        return nil
+      end
+      param = SOAPStruct.new(TYPE_RANGE)
+      mark_marshalled_obj(obj, param)
+      if obj.class != Range
+        param.extraattr[RubyTypeName] = obj.class.name
+      end
+      param.add('begin', Mapping._obj2soap(obj.begin, map))
+      param.add('end', Mapping._obj2soap(obj.end, map))
+      param.add('exclude_end', SOAP::SOAPBoolean.new(obj.exclude_end?))
+      addiv2soapattr(param, obj, map)
+    when ::Class
+      unless @allow_original_mapping
+        return nil
+      end
+      if obj.to_s[0] == ?#
+        raise TypeError.new("can't dump anonymous class #{obj}")
+      end
+      param = SOAPStruct.new(TYPE_CLASS)
+      mark_marshalled_obj(obj, param)
+      param.add('name', SOAPString.new(obj.name))
+      addiv2soapattr(param, obj, map)
+    when ::Module
+      unless @allow_original_mapping
+        return nil
+      end
+      if obj.to_s[0] == ?#
+        raise TypeError.new("can't dump anonymous module #{obj}")
+      end
+      param = SOAPStruct.new(TYPE_MODULE)
+      mark_marshalled_obj(obj, param)
+      param.add('name', SOAPString.new(obj.name))
+      addiv2soapattr(param, obj, map)
+    when ::Symbol
+      unless @allow_original_mapping
+        return nil
+      end
+      param = SOAPStruct.new(TYPE_SYMBOL)
+      mark_marshalled_obj(obj, param)
+      param.add('id', SOAPString.new(obj.id2name))
+      addiv2soapattr(param, obj, map)
+    when ::Struct
+      unless @allow_original_mapping
+        # treat it as an user defined class. [ruby-talk:104980]
+        #param = unknownobj2soap(soap_class, obj, info, map)
+        param = SOAPStruct.new(XSD::AnyTypeName)
+        mark_marshalled_obj(obj, param)
+        obj.members.each do |member|
+          param.add(Mapping.name2elename(member),
+            Mapping._obj2soap(obj[member], map))
+        end
+      else
+        param = SOAPStruct.new(TYPE_STRUCT)
+        mark_marshalled_obj(obj, param)
+        param.add('type', ele_type = SOAPString.new(obj.class.to_s))
+        ele_member = SOAPStruct.new
+        obj.members.each do |member|
+          ele_member.add(Mapping.name2elename(member),
+            Mapping._obj2soap(obj[member], map))
+        end
+        param.add('member', ele_member)
+        addiv2soapattr(param, obj, map)
+      end
+    when ::IO, ::Binding, ::Continuation, ::Data, ::Dir, ::File::Stat,
+        ::MatchData, Method, ::Proc, ::Thread, ::ThreadGroup
+        # from 1.8: Process::Status, UnboundMethod
+      return nil
+    when ::SOAP::Mapping::Object
+      param = SOAPStruct.new(XSD::AnyTypeName)
+      mark_marshalled_obj(obj, param)
+      obj.__xmlele.each do |key, value|
+        param.add(key.name, Mapping._obj2soap(value, map))
+      end
+      obj.__xmlattr.each do |key, value|
+        param.extraattr[key] = value
+      end
+    when ::Exception
+      typestr = Mapping.name2elename(obj.class.to_s)
+      param = SOAPStruct.new(XSD::QName.new(RubyTypeNamespace, typestr))
+      mark_marshalled_obj(obj, param)
+      param.add('message', Mapping._obj2soap(obj.message, map))
+      param.add('backtrace', Mapping._obj2soap(obj.backtrace, map))
+      addiv2soapattr(param, obj, map)
+    else
+      param = unknownobj2soap(soap_class, obj, info, map)
+    end
+    param
+  end
+
+  def soap2obj(obj_class, node, info, map)
+    rubytype = node.extraattr[RubyTypeName]
+    if rubytype or node.type.namespace == RubyTypeNamespace
+      rubytype2obj(node, info, map, rubytype)
+    elsif node.type == XSD::AnyTypeName or node.type == XSD::AnySimpleTypeName
+      anytype2obj(node, info, map)
+    else
+      unknowntype2obj(node, info, map)
+    end
+  end
+
+private
+
+  def addiv2soapattr(node, obj, map)
+    return if obj.instance_variables.empty?
+    ivars = SOAPStruct.new    # Undefined type.
+    setiv2soap(ivars, obj, map)
+    node.extraattr[RubyIVarName] = ivars
+  end
+
+  def unknownobj2soap(soap_class, obj, info, map)
+    if obj.class.name.empty?
+      raise TypeError.new("can't dump anonymous class #{obj}")
+    end
+    singleton_class = class << obj; self; end
+    if !singleton_methods_true(obj).empty? or
+	!singleton_class.instance_variables.empty?
+      raise TypeError.new("singleton can't be dumped #{obj}")
+    end
+    if !(singleton_class.ancestors - obj.class.ancestors).empty?
+      typestr = Mapping.name2elename(obj.class.to_s)
+      type = XSD::QName.new(RubyTypeNamespace, typestr)
+    else
+      type = Mapping.class2element(obj.class)
+    end
+    param = SOAPStruct.new(type)
+    mark_marshalled_obj(obj, param)
+    setiv2soap(param, obj, map)
+    param
+  end
+
+  if RUBY_VERSION >= '1.8.0'
+    def singleton_methods_true(obj)
+      obj.singleton_methods(true)
+    end
+  else
+    def singleton_methods_true(obj)
+      obj.singleton_methods
+    end
+  end
+
+  def rubytype2obj(node, info, map, rubytype)
+    klass = rubytype ? Mapping.class_from_name(rubytype) : nil
+    obj = nil
+    case node
+    when SOAPString
+      return @string_factory.soap2obj(klass || String, node, info, map)
+    when SOAPDateTime
+      #return @datetime_factory.soap2obj(klass || Time, node, info, map)
+      klass ||= Time
+      t = node.to_time
+      arg = [t.year, t.month, t.mday, t.hour, t.min, t.sec, t.usec]
+      obj = t.gmt? ? klass.gm(*arg) : klass.local(*arg)
+      mark_unmarshalled_obj(node, obj)
+      return true, obj
+    when SOAPArray
+      return @array_factory.soap2obj(klass || Array, node, info, map)
+    when SOAPNil, SOAPBoolean, SOAPInt, SOAPInteger, SOAPDecimal, SOAPDouble
+      return @basetype_factory.soap2obj(nil, node, info, map)
+    when SOAPStruct
+      return rubytypestruct2obj(node, info, map, rubytype)
+    else
+      raise
+    end
+  end
+
+  def rubytypestruct2obj(node, info, map, rubytype)
+    klass = rubytype ? Mapping.class_from_name(rubytype) : nil
+    obj = nil
+    case node.type
+    when TYPE_HASH
+      klass = rubytype ? Mapping.class_from_name(rubytype) : Hash
+      obj = Mapping.create_empty_object(klass)
+      mark_unmarshalled_obj(node, obj)
+      node.each do |key, value|
+        next unless key == 'item'
+        obj[Mapping._soap2obj(value['key'], map)] =
+          Mapping._soap2obj(value['value'], map)
+      end
+      if node.key?('default')
+        obj.default = Mapping._soap2obj(node['default'], map)
+      end
+    when TYPE_REGEXP
+      klass = rubytype ? Mapping.class_from_name(rubytype) : Regexp
+      obj = Mapping.create_empty_object(klass)
+      mark_unmarshalled_obj(node, obj)
+      source = node['source'].string
+      options = node['options'].data || 0
+      Regexp.instance_method(:initialize).bind(obj).call(source, options)
+    when TYPE_RANGE
+      klass = rubytype ? Mapping.class_from_name(rubytype) : Range
+      obj = Mapping.create_empty_object(klass)
+      mark_unmarshalled_obj(node, obj)
+      first = Mapping._soap2obj(node['begin'], map)
+      last = Mapping._soap2obj(node['end'], map)
+      exclude_end = node['exclude_end'].data
+      Range.instance_method(:initialize).bind(obj).call(first, last, exclude_end)
+    when TYPE_CLASS
+      obj = Mapping.class_from_name(node['name'].data)
+    when TYPE_MODULE
+      obj = Mapping.class_from_name(node['name'].data)
+    when TYPE_SYMBOL
+      obj = node['id'].data.intern
+    when TYPE_STRUCT
+      typestr = Mapping.elename2name(node['type'].data)
+      klass = Mapping.class_from_name(typestr)
+      if klass.nil?
+        return false
+      end
+      unless klass <= ::Struct
+        return false
+      end
+      obj = Mapping.create_empty_object(klass)
+      mark_unmarshalled_obj(node, obj)
+      node['member'].each do |name, value|
+        obj[Mapping.elename2name(name)] = Mapping._soap2obj(value, map)
+      end
+    else
+      return unknowntype2obj(node, info, map)
+    end
+    return true, obj
+  end
+
+  def anytype2obj(node, info, map)
+    case node
+    when SOAPBasetype
+      return true, node.data
+    when SOAPStruct
+      klass = ::SOAP::Mapping::Object
+      obj = klass.new
+      mark_unmarshalled_obj(node, obj)
+      node.each do |name, value|
+        obj.__add_xmlele_value(XSD::QName.new(nil, name),
+          Mapping._soap2obj(value, map))
+      end
+      unless node.extraattr.empty?
+        obj.instance_variable_set('@__xmlattr', node.extraattr)
+      end
+      return true, obj
+    else
+      return false
+    end
+  end
+
+  def unknowntype2obj(node, info, map)
+    case node
+    when SOAPBasetype
+      return true, node.data
+    when SOAPArray
+      return @array_factory.soap2obj(Array, node, info, map)
+    when SOAPStruct
+      obj = unknownstruct2obj(node, info, map)
+      return true, obj if obj
+      if !@allow_untyped_struct
+        return false
+      end
+      return anytype2obj(node, info, map)
+    else
+      # Basetype which is not defined...
+      return false
+    end
+  end
+
+  def unknownstruct2obj(node, info, map)
+    unless node.type.name
+      return nil
+    end
+    typestr = Mapping.elename2name(node.type.name)
+    klass = Mapping.class_from_name(typestr)
+    if klass.nil? and @allow_untyped_struct
+      klass = Mapping.class_from_name(typestr, true)    # lenient
+    end
+    if klass.nil?
+      return nil
+    end
+    if klass <= ::Exception
+      return exception2obj(klass, node, map)
+    end
+    klass_type = Mapping.class2qname(klass)
+    return nil unless node.type.match(klass_type)
+    obj = nil
+    begin
+      obj = Mapping.create_empty_object(klass)
+    rescue
+      # type name "data" tries Data.new which raises TypeError
+      nil
+    end
+    mark_unmarshalled_obj(node, obj)
+    setiv2obj(obj, node, map)
+    obj
+  end
+
+  def exception2obj(klass, node, map)
+    message = Mapping._soap2obj(node['message'], map)
+    backtrace = Mapping._soap2obj(node['backtrace'], map)
+    obj = Mapping.create_empty_object(klass)
+    obj = obj.exception(message)
+    mark_unmarshalled_obj(node, obj)
+    obj.set_backtrace(backtrace)
+    obj
+  end
+
+  # Only creates empty array.  Do String#replace it with real string.
+  def array2obj(node, map, rubytype)
+    klass = rubytype ? Mapping.class_from_name(rubytype) : Array
+    obj = Mapping.create_empty_object(klass)
+    mark_unmarshalled_obj(node, obj)
+    obj
+  end
+
+  # Only creates empty string.  Do String#replace it with real string.
+  def string2obj(node, map, rubytype)
+    klass = rubytype ? Mapping.class_from_name(rubytype) : String
+    obj = Mapping.create_empty_object(klass)
+    mark_unmarshalled_obj(node, obj)
+    obj
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/typeMap.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/typeMap.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/typeMap.rb	(revision 18425)
@@ -0,0 +1,50 @@
+# SOAP4R - Base type mapping definition
+# Copyright (C) 2000, 2001, 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+module SOAP
+
+
+TypeMap = {
+  XSD::XSDAnySimpleType::Type => SOAPAnySimpleType,
+  XSD::XSDString::Type => SOAPString,
+  XSD::XSDBoolean::Type => SOAPBoolean,
+  XSD::XSDDecimal::Type => SOAPDecimal,
+  XSD::XSDFloat::Type => SOAPFloat,
+  XSD::XSDDouble::Type => SOAPDouble,
+  XSD::XSDDuration::Type => SOAPDuration,
+  XSD::XSDDateTime::Type => SOAPDateTime,
+  XSD::XSDTime::Type => SOAPTime,
+  XSD::XSDDate::Type => SOAPDate,
+  XSD::XSDGYearMonth::Type => SOAPGYearMonth,
+  XSD::XSDGYear::Type => SOAPGYear,
+  XSD::XSDGMonthDay::Type => SOAPGMonthDay,
+  XSD::XSDGDay::Type => SOAPGDay,
+  XSD::XSDGMonth::Type => SOAPGMonth,
+  XSD::XSDHexBinary::Type => SOAPHexBinary,
+  XSD::XSDBase64Binary::Type => SOAPBase64,
+  XSD::XSDAnyURI::Type => SOAPAnyURI,
+  XSD::XSDQName::Type => SOAPQName,
+  XSD::XSDInteger::Type => SOAPInteger,
+  XSD::XSDNonPositiveInteger::Type => SOAPNonPositiveInteger,
+  XSD::XSDNegativeInteger::Type => SOAPNegativeInteger,
+  XSD::XSDLong::Type => SOAPLong,
+  XSD::XSDInt::Type => SOAPInt,
+  XSD::XSDShort::Type => SOAPShort,
+  XSD::XSDByte::Type => SOAPByte,
+  XSD::XSDNonNegativeInteger::Type => SOAPNonNegativeInteger,
+  XSD::XSDUnsignedLong::Type => SOAPUnsignedLong,
+  XSD::XSDUnsignedInt::Type => SOAPUnsignedInt,
+  XSD::XSDUnsignedShort::Type => SOAPUnsignedShort,
+  XSD::XSDUnsignedByte::Type => SOAPUnsignedByte,
+  XSD::XSDPositiveInteger::Type => SOAPPositiveInteger,
+
+  SOAP::SOAPBase64::Type => SOAPBase64,
+}
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/wsdlencodedregistry.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/wsdlencodedregistry.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/wsdlencodedregistry.rb	(revision 18425)
@@ -0,0 +1,280 @@
+# SOAP4R - WSDL encoded mapping registry.
+# Copyright (C) 2000-2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/qname'
+require 'xsd/namedelements'
+require 'soap/baseData'
+require 'soap/mapping/mapping'
+require 'soap/mapping/typeMap'
+
+
+module SOAP
+module Mapping
+
+
+class WSDLEncodedRegistry < Registry
+  include TraverseSupport
+
+  attr_reader :definedelements
+  attr_reader :definedtypes
+  attr_accessor :excn_handler_obj2soap
+  attr_accessor :excn_handler_soap2obj
+
+  def initialize(definedtypes = XSD::NamedElements::Empty)
+    @definedtypes = definedtypes
+    # @definedelements = definedelements  needed?
+    @excn_handler_obj2soap = nil
+    @excn_handler_soap2obj = nil
+    # For mapping AnyType element.
+    @rubytype_factory = RubytypeFactory.new(
+      :allow_untyped_struct => true,
+      :allow_original_mapping => true
+    )
+    @schema_element_cache = {}
+  end
+
+  def obj2soap(obj, qname = nil)
+    soap_obj = nil
+    if type = @definedtypes[qname]
+      soap_obj = obj2typesoap(obj, type)
+    else
+      soap_obj = any2soap(obj, qname)
+    end
+    return soap_obj if soap_obj
+    if @excn_handler_obj2soap
+      soap_obj = @excn_handler_obj2soap.call(obj) { |yield_obj|
+        Mapping._obj2soap(yield_obj, self)
+      }
+      return soap_obj if soap_obj
+    end
+    if qname
+      raise MappingError.new("cannot map #{obj.class.name} as #{qname}")
+    else
+      raise MappingError.new("cannot map #{obj.class.name} to SOAP/OM")
+    end
+  end
+
+  # map anything for now: must refer WSDL while mapping.  [ToDo]
+  def soap2obj(node, obj_class = nil)
+    begin
+      return any2obj(node, obj_class)
+    rescue MappingError
+    end
+    if @excn_handler_soap2obj
+      begin
+        return @excn_handler_soap2obj.call(node) { |yield_node|
+	    Mapping._soap2obj(yield_node, self)
+	  }
+      rescue Exception
+      end
+    end
+    raise MappingError.new("cannot map #{node.type.name} to Ruby object")
+  end
+
+private
+
+  def any2soap(obj, qname)
+    if obj.nil?
+      SOAPNil.new
+    elsif qname.nil? or qname == XSD::AnyTypeName
+      @rubytype_factory.obj2soap(nil, obj, nil, self)
+    elsif obj.is_a?(XSD::NSDBase)
+      soap2soap(obj, qname)
+    elsif (type = TypeMap[qname])
+      base2soap(obj, type)
+    else
+      nil
+    end
+  end
+
+  def soap2soap(obj, type_qname)
+    if obj.is_a?(SOAPBasetype)
+      obj
+    elsif obj.is_a?(SOAPStruct) && (type = @definedtypes[type_qname])
+      soap_obj = obj
+      mark_marshalled_obj(obj, soap_obj)
+      elements2soap(obj, soap_obj, type.content.elements)
+      soap_obj
+    elsif obj.is_a?(SOAPArray) && (type = @definedtypes[type_qname])
+      soap_obj = obj
+      contenttype = type.child_type
+      mark_marshalled_obj(obj, soap_obj)
+      obj.replace do |ele|
+	Mapping._obj2soap(ele, self, contenttype)
+      end
+      soap_obj
+    else
+      nil
+    end
+  end
+
+  def obj2typesoap(obj, type)
+    if type.is_a?(::WSDL::XMLSchema::SimpleType)
+      simpleobj2soap(obj, type)
+    else
+      complexobj2soap(obj, type)
+    end
+  end
+
+  def simpleobj2soap(obj, type)
+    type.check_lexical_format(obj)
+    return SOAPNil.new if obj.nil?      # ToDo: check nillable.
+    o = base2soap(obj, TypeMap[type.base])
+    o
+  end
+
+  def complexobj2soap(obj, type)
+    case type.compoundtype
+    when :TYPE_STRUCT
+      struct2soap(obj, type.name, type)
+    when :TYPE_ARRAY
+      array2soap(obj, type.name, type)
+    when :TYPE_MAP
+      map2soap(obj, type.name, type)
+    when :TYPE_SIMPLE
+      simpleobj2soap(obj, type.simplecontent)
+    when :TYPE_EMPTY
+      raise MappingError.new("should be empty") unless obj.nil?
+      SOAPNil.new
+    else
+      raise MappingError.new("unknown compound type: #{type.compoundtype}")
+    end
+  end
+
+  def base2soap(obj, type)
+    soap_obj = nil
+    if type <= XSD::XSDString
+      str = XSD::Charset.encoding_conv(obj.to_s,
+        Thread.current[:SOAPExternalCES], XSD::Charset.encoding)
+      soap_obj = type.new(str)
+      mark_marshalled_obj(obj, soap_obj)
+    else
+      soap_obj = type.new(obj)
+    end
+    soap_obj
+  end
+
+  def struct2soap(obj, type_qname, type)
+    return SOAPNil.new if obj.nil?      # ToDo: check nillable.
+    soap_obj = SOAPStruct.new(type_qname)
+    unless obj.nil?
+      mark_marshalled_obj(obj, soap_obj)
+      elements2soap(obj, soap_obj, type.content.elements)
+    end
+    soap_obj
+  end
+
+  def array2soap(obj, type_qname, type)
+    return SOAPNil.new if obj.nil?      # ToDo: check nillable.
+    arytype = type.child_type
+    soap_obj = SOAPArray.new(ValueArrayName, 1, arytype)
+    unless obj.nil?
+      mark_marshalled_obj(obj, soap_obj)
+      obj.each do |item|
+        soap_obj.add(Mapping._obj2soap(item, self, arytype))
+      end
+    end
+    soap_obj
+  end
+
+  MapKeyName = XSD::QName.new(nil, "key")
+  MapValueName = XSD::QName.new(nil, "value")
+  def map2soap(obj, type_qname, type)
+    return SOAPNil.new if obj.nil?      # ToDo: check nillable.
+    keytype = type.child_type(MapKeyName) || XSD::AnyTypeName
+    valuetype = type.child_type(MapValueName) || XSD::AnyTypeName
+    soap_obj = SOAPStruct.new(MapQName)
+    unless obj.nil?
+      mark_marshalled_obj(obj, soap_obj)
+      obj.each do |key, value|
+        elem = SOAPStruct.new
+        elem.add("key", Mapping._obj2soap(key, self, keytype))
+        elem.add("value", Mapping._obj2soap(value, self, valuetype))
+        # ApacheAxis allows only 'item' here.
+        soap_obj.add("item", elem)
+      end
+    end
+    soap_obj
+  end
+
+  def elements2soap(obj, soap_obj, elements)
+    elements.each do |element|
+      name = element.name.name
+      child_obj = Mapping.get_attribute(obj, name)
+      soap_obj.add(name,
+        Mapping._obj2soap(child_obj, self, element.type || element.name))
+    end
+  end
+
+  def any2obj(node, obj_class)
+    unless obj_class
+      typestr = XSD::CodeGen::GenSupport.safeconstname(node.elename.name)
+      obj_class = Mapping.class_from_name(typestr)
+    end
+    if obj_class and obj_class.class_variables.include?('@@schema_element')
+      soap2stubobj(node, obj_class)
+    else
+      Mapping._soap2obj(node, Mapping::DefaultRegistry, obj_class)
+    end
+  end
+
+  def soap2stubobj(node, obj_class)
+    obj = Mapping.create_empty_object(obj_class)
+    unless node.is_a?(SOAPNil)
+      add_elements2stubobj(node, obj)
+    end
+    obj
+  end
+
+  def add_elements2stubobj(node, obj)
+    elements, as_array = schema_element_definition(obj.class)
+    vars = {}
+    node.each do |name, value|
+      item = elements.find { |k, v| k.name == name }
+      if item
+        elename, class_name = item
+        if klass = Mapping.class_from_name(class_name)
+          # klass must be a SOAPBasetype or a class
+          if klass.ancestors.include?(::SOAP::SOAPBasetype)
+            if value.respond_to?(:data)
+              child = klass.new(value.data).data
+            else
+              child = klass.new(nil).data
+            end
+          else
+            child = Mapping._soap2obj(value, self, klass)
+          end
+        elsif klass = Mapping.module_from_name(class_name)
+          # simpletype
+          if value.respond_to?(:data)
+            child = value.data
+          else
+            raise MappingError.new(
+              "cannot map to a module value: #{class_name}")
+          end
+        else
+          raise MappingError.new("unknown class: #{class_name}")
+        end
+      else      # untyped element is treated as anyType.
+        child = Mapping._soap2obj(value, self)
+      end
+      vars[name] = child
+    end
+    Mapping.set_attributes(obj, vars)
+  end
+
+  # it caches @@schema_element.  this means that @@schema_element must not be
+  # changed while a lifetime of a WSDLLiteralRegistry.
+  def schema_element_definition(klass)
+    @schema_element_cache[klass] ||= Mapping.schema_element_definition(klass)
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb	(revision 18425)
@@ -0,0 +1,418 @@
+# SOAP4R - WSDL literal mapping registry.
+# Copyright (C) 2004, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/baseData'
+require 'soap/mapping/mapping'
+require 'soap/mapping/typeMap'
+require 'xsd/codegen/gensupport'
+require 'xsd/namedelements'
+
+
+module SOAP
+module Mapping
+
+
+class WSDLLiteralRegistry < Registry
+  attr_reader :definedelements
+  attr_reader :definedtypes
+  attr_accessor :excn_handler_obj2soap
+  attr_accessor :excn_handler_soap2obj
+
+  def initialize(definedtypes = XSD::NamedElements::Empty,
+      definedelements = XSD::NamedElements::Empty)
+    @definedtypes = definedtypes
+    @definedelements = definedelements
+    @excn_handler_obj2soap = nil
+    @excn_handler_soap2obj = nil
+    @schema_element_cache = {}
+    @schema_attribute_cache = {}
+  end
+
+  def obj2soap(obj, qname)
+    soap_obj = nil
+    if ele = @definedelements[qname]
+      soap_obj = obj2elesoap(obj, ele)
+    elsif type = @definedtypes[qname]
+      soap_obj = obj2typesoap(obj, type, true)
+    else
+      soap_obj = any2soap(obj, qname)
+    end
+    return soap_obj if soap_obj
+    if @excn_handler_obj2soap
+      soap_obj = @excn_handler_obj2soap.call(obj) { |yield_obj|
+        Mapping.obj2soap(yield_obj, nil, nil, MAPPING_OPT)
+      }
+      return soap_obj if soap_obj
+    end
+    raise MappingError.new("cannot map #{obj.class.name} as #{qname}")
+  end
+
+  # node should be a SOAPElement
+  def soap2obj(node, obj_class = nil)
+    # obj_class is given when rpc/literal service.  but ignored for now.
+    begin
+      return any2obj(node)
+    rescue MappingError
+    end
+    if @excn_handler_soap2obj
+      begin
+        return @excn_handler_soap2obj.call(node) { |yield_node|
+	    Mapping.soap2obj(yield_node, nil, nil, MAPPING_OPT)
+	  }
+      rescue Exception
+      end
+    end
+    if node.respond_to?(:type)
+      raise MappingError.new("cannot map #{node.type.name} to Ruby object")
+    else
+      raise MappingError.new("cannot map #{node.elename.name} to Ruby object")
+    end
+  end
+
+private
+
+  MAPPING_OPT = { :no_reference => true }
+
+  def obj2elesoap(obj, ele)
+    o = nil
+    qualified = (ele.elementform == 'qualified')
+    if ele.type
+      if type = @definedtypes[ele.type]
+        o = obj2typesoap(obj, type, qualified)
+      elsif type = TypeMap[ele.type]
+        o = base2soap(obj, type)
+      else
+        raise MappingError.new("cannot find type #{ele.type}")
+      end
+    elsif ele.local_complextype
+      o = obj2typesoap(obj, ele.local_complextype, qualified)
+      add_attributes2soap(obj, o)
+    elsif ele.local_simpletype
+      o = obj2typesoap(obj, ele.local_simpletype, qualified)
+    else
+      raise MappingError.new('illegal schema?')
+    end
+    o.elename = ele.name
+    o
+  end
+
+  def obj2typesoap(obj, type, qualified)
+    if type.is_a?(::WSDL::XMLSchema::SimpleType)
+      simpleobj2soap(obj, type)
+    else
+      complexobj2soap(obj, type, qualified)
+    end
+  end
+
+  def simpleobj2soap(obj, type)
+    type.check_lexical_format(obj)
+    return SOAPNil.new if obj.nil?      # ToDo: check nillable.
+    o = base2soap(obj, TypeMap[type.base])
+    o
+  end
+
+  def complexobj2soap(obj, type, qualified)
+    o = SOAPElement.new(type.name)
+    o.qualified = qualified
+    type.each_element do |child_ele|
+      child = Mapping.get_attribute(obj, child_ele.name.name)
+      if child.nil?
+        if child_ele.nillable
+          # ToDo: test
+          # add empty element
+          child_soap = obj2elesoap(nil, child_ele)
+          o.add(child_soap)
+        elsif Integer(child_ele.minoccurs) == 0
+          # nothing to do
+        else
+          raise MappingError.new("nil not allowed: #{child_ele.name.name}")
+        end
+      elsif child_ele.map_as_array?
+        child.each do |item|
+          child_soap = obj2elesoap(item, child_ele)
+          o.add(child_soap)
+        end
+      else
+        child_soap = obj2elesoap(child, child_ele)
+        o.add(child_soap)
+      end
+    end
+    o
+  end
+
+  def any2soap(obj, qname)
+    if obj.is_a?(SOAPElement)
+      obj
+    elsif obj.class.class_variables.include?('@@schema_element')
+      stubobj2soap(obj, qname)
+    elsif obj.is_a?(SOAP::Mapping::Object)
+      mappingobj2soap(obj, qname)
+    elsif obj.is_a?(Hash)
+      ele = SOAPElement.from_obj(obj)
+      ele.elename = qname
+      ele
+    else
+      # expected to be a basetype or an anyType.
+      # SOAPStruct, etc. is used instead of SOAPElement.
+      begin
+        ele = Mapping.obj2soap(obj, nil, nil, MAPPING_OPT)
+        ele.elename = qname
+        ele
+      rescue MappingError
+        ele = SOAPElement.new(qname, obj.to_s)
+      end
+      if obj.respond_to?(:__xmlattr)
+        obj.__xmlattr.each do |key, value|
+          ele.extraattr[key] = value
+        end
+      end
+      ele
+    end
+  end
+
+  def stubobj2soap(obj, qname)
+    ele = SOAPElement.new(qname)
+    ele.qualified =
+      (obj.class.class_variables.include?('@@schema_qualified') and
+      obj.class.class_eval('@@schema_qualified'))
+    add_elements2soap(obj, ele)
+    add_attributes2soap(obj, ele)
+    ele
+  end
+
+  def mappingobj2soap(obj, qname)
+    ele = SOAPElement.new(qname)
+    obj.__xmlele.each do |key, value|
+      if value.is_a?(::Array)
+        value.each do |item|
+          ele.add(obj2soap(item, key))
+        end
+      else
+        ele.add(obj2soap(value, key))
+      end
+    end
+    obj.__xmlattr.each do |key, value|
+      ele.extraattr[key] = value
+    end
+    ele
+  end
+
+  def add_elements2soap(obj, ele)
+    elements, as_array = schema_element_definition(obj.class)
+    if elements
+      elements.each do |elename, type|
+        if child = Mapping.get_attribute(obj, elename.name)
+          if as_array.include?(elename.name)
+            child.each do |item|
+              ele.add(obj2soap(item, elename))
+            end
+          else
+            ele.add(obj2soap(child, elename))
+          end
+        elsif obj.is_a?(::Array) and as_array.include?(elename.name)
+          obj.each do |item|
+            ele.add(obj2soap(item, elename))
+          end
+        end
+      end
+    end
+  end
+  
+  def add_attributes2soap(obj, ele)
+    attributes = schema_attribute_definition(obj.class)
+    if attributes
+      attributes.each do |qname, param|
+        attr = obj.__send__('xmlattr_' +
+          XSD::CodeGen::GenSupport.safevarname(qname.name))
+        ele.extraattr[qname] = attr
+      end
+    end
+  end
+
+  def base2soap(obj, type)
+    soap_obj = nil
+    if type <= XSD::XSDString
+      str = XSD::Charset.encoding_conv(obj.to_s,
+        Thread.current[:SOAPExternalCES], XSD::Charset.encoding)
+      soap_obj = type.new(str)
+    else
+      soap_obj = type.new(obj)
+    end
+    soap_obj
+  end
+
+  def anytype2obj(node)
+    if node.is_a?(::SOAP::SOAPBasetype)
+      return node.data
+    end
+    klass = ::SOAP::Mapping::Object
+    obj = klass.new
+    obj
+  end
+
+  def any2obj(node, obj_class = nil)
+    unless obj_class
+      typestr = XSD::CodeGen::GenSupport.safeconstname(node.elename.name)
+      obj_class = Mapping.class_from_name(typestr)
+    end
+    if obj_class and obj_class.class_variables.include?('@@schema_element')
+      soapele2stubobj(node, obj_class)
+    elsif node.is_a?(SOAPElement) or node.is_a?(SOAPStruct)
+        # SOAPArray for literal?
+      soapele2plainobj(node)
+    else
+      obj = Mapping.soap2obj(node, nil, obj_class, MAPPING_OPT)
+      add_attributes2plainobj(node, obj)
+      obj
+    end
+  end
+
+  def soapele2stubobj(node, obj_class)
+    obj = Mapping.create_empty_object(obj_class)
+    add_elements2stubobj(node, obj)
+    add_attributes2stubobj(node, obj)
+    obj
+  end
+
+  def soapele2plainobj(node)
+    obj = anytype2obj(node)
+    add_elements2plainobj(node, obj)
+    add_attributes2plainobj(node, obj)
+    obj
+  end
+
+  def add_elements2stubobj(node, obj)
+    elements, as_array = schema_element_definition(obj.class)
+    vars = {}
+    node.each do |name, value|
+      item = elements.find { |k, v| k.name == name }
+      if item
+        elename, class_name = item
+        if klass = Mapping.class_from_name(class_name)
+          # klass must be a SOAPBasetype or a class
+          if klass.ancestors.include?(::SOAP::SOAPBasetype)
+            if value.respond_to?(:data)
+              child = klass.new(value.data).data
+            else
+              child = klass.new(nil).data
+            end
+          else
+            child = any2obj(value, klass)
+          end
+        elsif klass = Mapping.module_from_name(class_name)
+          # simpletype
+          if value.respond_to?(:data)
+            child = value.data
+          else
+            raise MappingError.new(
+              "cannot map to a module value: #{class_name}")
+          end
+        else
+          raise MappingError.new("unknown class/module: #{class_name}")
+        end
+      else      # untyped element is treated as anyType.
+        child = any2obj(value)
+      end
+      if as_array.include?(elename.name)
+        (vars[name] ||= []) << child
+      else
+        vars[name] = child
+      end
+    end
+    Mapping.set_attributes(obj, vars)
+  end
+
+  def add_attributes2stubobj(node, obj)
+    if attributes = schema_attribute_definition(obj.class)
+      define_xmlattr(obj)
+      attributes.each do |qname, class_name|
+        attr = node.extraattr[qname]
+        next if attr.nil? or attr.empty?
+        klass = Mapping.class_from_name(class_name)
+        if klass.ancestors.include?(::SOAP::SOAPBasetype)
+          child = klass.new(attr).data
+        else
+          child = attr
+        end
+        obj.__xmlattr[qname] = child
+        define_xmlattr_accessor(obj, qname)
+      end
+    end
+  end
+
+  def add_elements2plainobj(node, obj)
+    node.each do |name, value|
+      obj.__add_xmlele_value(value.elename, any2obj(value))
+    end
+  end
+
+  def add_attributes2plainobj(node, obj)
+    return if node.extraattr.empty?
+    define_xmlattr(obj)
+    node.extraattr.each do |qname, value|
+      obj.__xmlattr[qname] = value
+      define_xmlattr_accessor(obj, qname)
+    end
+  end
+
+  if RUBY_VERSION > "1.7.0"
+    def define_xmlattr_accessor(obj, qname)
+      name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
+      Mapping.define_attr_accessor(obj, 'xmlattr_' + name,
+        proc { @__xmlattr[qname] },
+        proc { |value| @__xmlattr[qname] = value })
+    end
+  else
+    def define_xmlattr_accessor(obj, qname)
+      name = XSD::CodeGen::GenSupport.safemethodname(qname.name)
+      obj.instance_eval <<-EOS
+        def #{name}
+          @__xmlattr[#{qname.dump}]
+        end
+
+        def #{name}=(value)
+          @__xmlattr[#{qname.dump}] = value
+        end
+      EOS
+    end
+  end
+
+  if RUBY_VERSION > "1.7.0"
+    def define_xmlattr(obj)
+      obj.instance_variable_set('@__xmlattr', {})
+      unless obj.respond_to?(:__xmlattr)
+        Mapping.define_attr_accessor(obj, :__xmlattr, proc { @__xmlattr })
+      end
+    end
+  else
+    def define_xmlattr(obj)
+      obj.instance_variable_set('@__xmlattr', {})
+      unless obj.respond_to?(:__xmlattr)
+        obj.instance_eval <<-EOS
+          def __xmlattr
+            @__xmlattr
+          end
+        EOS
+      end
+    end
+  end
+
+  # it caches @@schema_element.  this means that @@schema_element must not be
+  # changed while a lifetime of a WSDLLiteralRegistry.
+  def schema_element_definition(klass)
+    @schema_element_cache[klass] ||= Mapping.schema_element_definition(klass)
+  end
+
+  def schema_attribute_definition(klass)
+    @schema_attribute_cache[klass] ||= Mapping.schema_attribute_definition(klass)
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/marshal.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/marshal.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/marshal.rb	(revision 18425)
@@ -0,0 +1,59 @@
+# SOAP4R - Marshalling/Unmarshalling Ruby's object using SOAP Encoding.
+# Copyright (C) 2001, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require "soap/mapping"
+require "soap/processor"
+
+
+module SOAP
+
+
+module Marshal
+  # Trying xsd:dateTime data to be recovered as aTime.
+  MarshalMappingRegistry = Mapping::Registry.new(
+    :allow_original_mapping => true)
+  MarshalMappingRegistry.add(
+    Time,
+    ::SOAP::SOAPDateTime,
+    ::SOAP::Mapping::Registry::DateTimeFactory
+  )
+
+  class << self
+  public
+    def dump(obj, io = nil)
+      marshal(obj, MarshalMappingRegistry, io)
+    end
+
+    def load(stream)
+      unmarshal(stream, MarshalMappingRegistry)
+    end
+
+    def marshal(obj, mapping_registry = MarshalMappingRegistry, io = nil)
+      elename = Mapping.name2elename(obj.class.to_s)
+      soap_obj = Mapping.obj2soap(obj, mapping_registry)
+      body = SOAPBody.new
+      body.add(elename, soap_obj)
+      env = SOAPEnvelope.new(nil, body)
+      SOAP::Processor.marshal(env, {}, io)
+    end
+
+    def unmarshal(stream, mapping_registry = MarshalMappingRegistry)
+      env = SOAP::Processor.unmarshal(stream)
+      if env.nil?
+	raise ArgumentError.new("Illegal SOAP marshal format.")
+      end
+      Mapping.soap2obj(env.body.root_node, mapping_registry)
+    end
+  end
+end
+
+
+end
+
+
+SOAPMarshal = SOAP::Marshal
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mimemessage.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mimemessage.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/mimemessage.rb	(revision 18425)
@@ -0,0 +1,240 @@
+# SOAP4R - MIME Message implementation.
+# Copyright (C) 2002  Jamie Herre.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/attachment'
+
+
+module SOAP
+
+
+# Classes for MIME message handling.  Should be put somewhere else!
+# Tried using the 'tmail' module but found that I needed something
+# lighter in weight.
+
+
+class MIMEMessage
+  class MIMEMessageError < StandardError; end
+
+  MultipartContentType = 'multipart/\w+'
+
+  class Header
+    attr_accessor :str, :key, :root
+
+    def initialize
+      @attrs = {}
+    end
+
+    def [](key)
+      @attrs[key]
+    end
+
+    def []=(key, value)
+      @attrs[key] = value
+    end
+
+    def to_s
+      @key + ": " + @str
+    end
+  end
+
+  class Headers < Hash
+    def self.parse(str)
+      new.parse(str)
+    end
+
+    def parse(str)
+      header_cache = nil
+      str.each do |line|
+	case line
+	when /^\A[^\: \t]+:\s*.+$/
+	  parse_line(header_cache) if header_cache
+	  header_cache = line.sub(/\r?\n\z/, '')
+	when /^\A\s+(.*)$/
+	  # a continuous line at the beginning line crashes here.
+	  header_cache << line
+	else
+	  raise RuntimeError.new("unexpected header: #{line.inspect}")
+	end
+      end
+      parse_line(header_cache) if header_cache
+      self
+    end
+
+    def parse_line(line)
+      if /^\A([^\: \t]+):\s*(.+)\z/ =~ line
+    	header = parse_rhs($2.strip)
+	header.key = $1.strip
+	self[header.key.downcase] = header
+      else
+	raise RuntimeError.new("unexpected header line: #{line.inspect}")
+      end
+    end
+
+    def parse_rhs(str)
+      a = str.split(/;+\s+/)
+      header = Header.new
+      header.str = str
+      header.root = a.shift
+      a.each do |pair|
+	if pair =~ /(\w+)\s*=\s*"?([^"]+)"?/
+	  header[$1.downcase] = $2
+	else
+	  raise RuntimeError.new("unexpected header component: #{pair.inspect}")
+	end
+      end
+      header
+    end
+
+    def add(key, value)
+      if key != nil and value != nil
+	header = parse_rhs(value)
+	header.key = key
+	self[key.downcase] = header
+      end
+    end
+
+    def to_s
+      self.values.collect { |hdr|
+	hdr.to_s
+      }.join("\r\n")
+    end
+  end
+
+  class Part
+    attr_accessor :headers, :body
+
+    def initialize
+      @headers = Headers.new
+      @headers.add("Content-Transfer-Encoding", "8bit")
+      @body = nil
+      @contentid = nil
+    end
+
+    def self.parse(str)
+      new.parse(str)
+    end
+
+    def parse(str)
+      headers, body = str.split(/\r\n\r\n/s)
+      if headers != nil and body != nil
+	@headers = Headers.parse(headers)
+	@body = body.sub(/\r\n\z/, '')
+      else
+	raise RuntimeError.new("unexpected part: #{str.inspect}")
+      end
+      self
+    end
+
+    def contentid
+      if @contentid == nil and @headers.key?('content-id')
+	@contentid = @headers['content-id'].str
+	@contentid = $1 if @contentid =~ /^<(.+)>$/
+      end
+      @contentid
+    end
+
+    alias content body
+
+    def to_s
+      @headers.to_s + "\r\n\r\n" + @body
+    end
+  end
+
+  def initialize
+    @parts = []
+    @headers = Headers.new
+    @root = nil
+  end
+
+  def self.parse(head, str)
+    new.parse(head, str)
+  end
+
+  attr_reader :parts, :headers
+
+  def close
+    @headers.add(
+      "Content-Type",
+      "multipart/related; type=\"text/xml\"; boundary=\"#{boundary}\"; start=\"#{@parts[0].contentid}\""
+    )
+  end
+
+  def parse(head, str)
+    @headers = Headers.parse(head + "\r\n" + "From: jfh\r\n")
+    boundary = @headers['content-type']['boundary']
+    if boundary != nil
+      parts = str.split(/--#{Regexp.quote(boundary)}\s*(?:\r\n|--\r\n)/)
+      part = parts.shift	# preamble must be ignored.
+      @parts = parts.collect { |part| Part.parse(part) }
+    else
+      @parts = [Part.parse(str)]
+    end
+    if @parts.length < 1
+      raise MIMEMessageError.new("This message contains no valid parts!")
+    end
+    self
+  end
+
+  def root
+    if @root == nil
+      start = @headers['content-type']['start']
+      @root = (start && @parts.find { |prt| prt.contentid == start }) ||
+	@parts[0]
+    end
+    @root
+  end
+
+  def boundary
+    if @boundary == nil
+      @boundary = "----=Part_" + __id__.to_s + rand.to_s
+    end
+    @boundary
+  end
+
+  def add_part(content)
+    part = Part.new
+    part.headers.add("Content-Type",
+      "text/xml; charset=" + XSD::Charset.xml_encoding_label)
+    part.headers.add("Content-ID", Attachment.contentid(part))
+    part.body = content
+    @parts.unshift(part)
+  end
+
+  def add_attachment(attach)
+    part = Part.new
+    part.headers.add("Content-Type", attach.contenttype)
+    part.headers.add("Content-ID", attach.mime_contentid)
+    part.body = attach.content
+    @parts.unshift(part)
+  end
+
+  def has_parts?
+    (@parts.length > 0)
+  end
+
+  def headers_str
+    @headers.to_s
+  end
+
+  def content_str
+    str = ''
+    @parts.each do |prt|
+      str << "--" + boundary + "\r\n"
+      str << prt.to_s + "\r\n"
+    end
+    str << '--' + boundary + "--\r\n"
+    str
+  end
+
+  def to_s
+    str = headers_str + "\r\n\r\n" + conent_str
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/netHttpClient.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/netHttpClient.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/netHttpClient.rb	(revision 18425)
@@ -0,0 +1,190 @@
+# SOAP4R - net/http wrapper
+# Copyright (C) 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'net/http'
+
+
+module SOAP
+
+
+class NetHttpClient
+
+  SSLEnabled = begin
+      require 'net/https'
+      true
+    rescue LoadError
+      false
+    end
+
+  attr_reader :proxy
+  attr_accessor :no_proxy
+  attr_accessor :debug_dev
+  attr_accessor :ssl_config		# ignored for now.
+  attr_accessor :protocol_version	# ignored for now.
+  attr_accessor :connect_timeout
+  attr_accessor :send_timeout           # ignored for now.
+  attr_accessor :receive_timeout
+
+  def initialize(proxy = nil, agent = nil)
+    @proxy = proxy ? URI.parse(proxy) : nil
+    @agent = agent
+    @debug_dev = nil
+    @session_manager = SessionManager.new
+    @no_proxy = @ssl_config = @protocol_version = nil
+    @connect_timeout = @send_timeout = @receive_timeout = nil
+  end
+
+  def test_loopback_response
+    raise NotImplementedError.new("not supported for now")
+  end
+  
+  def proxy=(proxy)
+    if proxy.nil?
+      @proxy = nil
+    else
+      if proxy.is_a?(URI)
+        @proxy = proxy
+      else
+        @proxy = URI.parse(proxy)
+      end
+      if @proxy.scheme == nil or @proxy.scheme.downcase != 'http' or
+	  @proxy.host == nil or @proxy.port == nil
+	raise ArgumentError.new("unsupported proxy `#{proxy}'")
+      end
+    end
+    reset_all
+    @proxy
+  end
+
+  def set_basic_auth(uri, user_id, passwd)
+    # net/http does not handle url.
+    @basic_auth = [user_id, passwd]
+    raise NotImplementedError.new("basic_auth is not supported under soap4r + net/http.")
+  end
+
+  def set_cookie_store(filename)
+    raise NotImplementedError.new
+  end
+
+  def save_cookie_store(filename)
+    raise NotImplementedError.new
+  end
+
+  def reset(url)
+    # no persistent connection.  ignored.
+  end
+
+  def reset_all
+    # no persistent connection.  ignored.
+  end
+
+  def post(url, req_body, header = {})
+    unless url.is_a?(URI)
+      url = URI.parse(url)
+    end
+    extra = header.dup
+    extra['User-Agent'] = @agent if @agent
+    res = start(url) { |http|
+      http.post(url.request_uri, req_body, extra)
+    }
+    Response.new(res)
+  end
+
+  def get_content(url, header = {})
+    unless url.is_a?(URI)
+      url = URI.parse(url)
+    end
+    extra = header.dup
+    extra['User-Agent'] = @agent if @agent
+    res = start(url) { |http|
+	http.get(url.request_uri, extra)
+      }
+    res.body
+  end
+
+private
+
+  def start(url)
+    http = create_connection(url)
+    response = nil
+    http.start { |worker|
+      response = yield(worker)
+      worker.finish
+    }
+    @debug_dev << response.body if @debug_dev
+    response
+  end
+
+  def create_connection(url)
+    proxy_host = proxy_port = nil
+    unless no_proxy?(url)
+      proxy_host = @proxy.host
+      proxy_port = @proxy.port
+    end
+    http = Net::HTTP::Proxy(proxy_host, proxy_port).new(url.host, url.port)
+    if http.respond_to?(:set_debug_output)
+      http.set_debug_output(@debug_dev)
+    end
+    http.open_timeout = @connect_timeout if @connect_timeout
+    http.read_timeout = @receive_timeout if @receive_timeout
+    case url
+    when URI::HTTPS
+      if SSLEnabled
+	http.use_ssl = true
+      else
+	raise RuntimeError.new("Cannot connect to #{url} (OpenSSL is not installed.)")
+      end
+    when URI::HTTP
+      # OK
+    else
+      raise RuntimeError.new("Cannot connect to #{url} (Not HTTP.)")
+    end
+    http
+  end
+
+  NO_PROXY_HOSTS = ['localhost']
+
+  def no_proxy?(uri)
+    if !@proxy or NO_PROXY_HOSTS.include?(uri.host)
+      return true
+    end
+    if @no_proxy
+      @no_proxy.scan(/([^:,]*)(?::(\d+))?/) do |host, port|
+  	if /(\A|\.)#{Regexp.quote(host)}\z/i =~ uri.host &&
+	    (!port || uri.port == port.to_i)
+	  return true
+	end
+      end
+    else
+      false
+    end
+  end
+
+  class SessionManager
+    attr_accessor :connect_timeout
+    attr_accessor :send_timeout
+    attr_accessor :receive_timeout
+  end
+
+  class Response
+    attr_reader :content
+    attr_reader :status
+    attr_reader :reason
+    attr_reader :contenttype
+
+    def initialize(res)
+      @status = res.code.to_i
+      @reason = res.message
+      @contenttype = res['content-type']
+      @content = res.body
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/parser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/parser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/parser.rb	(revision 18425)
@@ -0,0 +1,251 @@
+# SOAP4R - SOAP XML Instance Parser library.
+# Copyright (C) 2001, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/ns'
+require 'xsd/xmlparser'
+require 'soap/soap'
+require 'soap/baseData'
+require 'soap/encodingstyle/handler'
+
+
+module SOAP
+
+
+class Parser
+  include SOAP
+
+  class ParseError < Error; end
+  class FormatDecodeError < ParseError; end
+  class UnexpectedElementError < ParseError; end
+
+private
+
+  class ParseFrame
+    attr_reader :node
+    attr_reader :name
+    attr_reader :ns, :encodingstyle
+
+    class NodeContainer
+      def initialize(node)
+	@node = node
+      end
+
+      def node
+	@node
+      end
+
+      def replace_node(node)
+	@node = node
+      end
+    end
+
+  public
+
+    def initialize(ns, name, node, encodingstyle)
+      @ns = ns
+      @name = name
+      self.node = node
+      @encodingstyle = encodingstyle
+    end
+
+    def node=(node)
+      @node = NodeContainer.new(node)
+    end
+  end
+
+public
+
+  attr_accessor :envelopenamespace
+  attr_accessor :default_encodingstyle
+  attr_accessor :decode_typemap
+  attr_accessor :allow_unqualified_element
+
+  def initialize(opt = {})
+    @opt = opt
+    @parser = XSD::XMLParser.create_parser(self, opt)
+    @parsestack = nil
+    @lastnode = nil
+    @handlers = {}
+    @envelopenamespace = opt[:envelopenamespace] || EnvelopeNamespace
+    @default_encodingstyle = opt[:default_encodingstyle] || EncodingNamespace
+    @decode_typemap = opt[:decode_typemap] || nil
+    @allow_unqualified_element = opt[:allow_unqualified_element] || false
+  end
+
+  def charset
+    @parser.charset
+  end
+
+  def parse(string_or_readable)
+    @parsestack = []
+    @lastnode = nil
+
+    @handlers.each do |uri, handler|
+      handler.decode_prologue
+    end
+
+    @parser.do_parse(string_or_readable)
+
+    unless @parsestack.empty?
+      raise FormatDecodeError.new("Unbalanced tag in XML.")
+    end
+
+    @handlers.each do |uri, handler|
+      handler.decode_epilogue
+    end
+
+    @lastnode
+  end
+
+  def start_element(name, attrs)
+    lastframe = @parsestack.last
+    ns = parent = parent_encodingstyle = nil
+    if lastframe
+      ns = lastframe.ns.clone_ns
+      parent = lastframe.node
+      parent_encodingstyle = lastframe.encodingstyle
+    else
+      ns = XSD::NS.new
+      parent = ParseFrame::NodeContainer.new(nil)
+      parent_encodingstyle = nil
+    end
+
+    attrs = XSD::XMLParser.filter_ns(ns, attrs)
+    encodingstyle = find_encodingstyle(ns, attrs)
+
+    # Children's encodingstyle is derived from its parent.
+    if encodingstyle.nil?
+      if parent.node.is_a?(SOAPHeader)
+        encodingstyle = LiteralNamespace
+      else
+        encodingstyle = parent_encodingstyle || @default_encodingstyle
+      end
+    end
+
+    node = decode_tag(ns, name, attrs, parent, encodingstyle)
+
+    @parsestack << ParseFrame.new(ns, name, node, encodingstyle)
+  end
+
+  def characters(text)
+    lastframe = @parsestack.last
+    if lastframe
+      # Need not to be cloned because character does not have attr.
+      decode_text(lastframe.ns, text, lastframe.encodingstyle)
+    else
+      # Ignore Text outside of SOAP Envelope.
+      p text if $DEBUG
+    end
+  end
+
+  def end_element(name)
+    lastframe = @parsestack.pop
+    unless name == lastframe.name
+      raise UnexpectedElementError.new("Closing element name '#{ name }' does not match with opening element '#{ lastframe.name }'.")
+    end
+    decode_tag_end(lastframe.ns, lastframe.node, lastframe.encodingstyle)
+    @lastnode = lastframe.node.node
+  end
+
+private
+
+  def find_encodingstyle(ns, attrs)
+    attrs.each do |key, value|
+      if (ns.compare(@envelopenamespace, AttrEncodingStyle, key))
+	return value
+      end
+    end
+    nil
+  end
+
+  def decode_tag(ns, name, attrs, parent, encodingstyle)
+    ele = ns.parse(name)
+
+    # Envelope based parsing.
+    if ((ele.namespace == @envelopenamespace) ||
+	(@allow_unqualified_element && ele.namespace.nil?))
+      o = decode_soap_envelope(ns, ele, attrs, parent)
+      return o if o
+    end
+
+    # Encoding based parsing.
+    handler = find_handler(encodingstyle)
+    if handler
+      return handler.decode_tag(ns, ele, attrs, parent)
+    else
+      raise FormatDecodeError.new("Unknown encodingStyle: #{ encodingstyle }.")
+    end
+  end
+
+  def decode_tag_end(ns, node, encodingstyle)
+    return unless encodingstyle
+
+    handler = find_handler(encodingstyle)
+    if handler
+      return handler.decode_tag_end(ns, node)
+    else
+      raise FormatDecodeError.new("Unknown encodingStyle: #{ encodingstyle }.")
+    end
+  end
+
+  def decode_text(ns, text, encodingstyle)
+    handler = find_handler(encodingstyle)
+
+    if handler
+      handler.decode_text(ns, text)
+    else
+      # How should I do?
+    end
+  end
+
+  def decode_soap_envelope(ns, ele, attrs, parent)
+    o = nil
+    if ele.name == EleEnvelope
+      o = SOAPEnvelope.new
+      if ext = @opt[:external_content]
+	ext.each do |k, v|
+	  o.external_content[k] = v
+	end
+      end
+    elsif ele.name == EleHeader
+      unless parent.node.is_a?(SOAPEnvelope)
+	raise FormatDecodeError.new("Header should be a child of Envelope.")
+      end
+      o = SOAPHeader.new
+      parent.node.header = o
+    elsif ele.name == EleBody
+      unless parent.node.is_a?(SOAPEnvelope)
+	raise FormatDecodeError.new("Body should be a child of Envelope.")
+      end
+      o = SOAPBody.new
+      parent.node.body = o
+    elsif ele.name == EleFault
+      unless parent.node.is_a?(SOAPBody)
+	raise FormatDecodeError.new("Fault should be a child of Body.")
+      end
+      o = SOAPFault.new
+      parent.node.fault = o
+    end
+    o
+  end
+
+  def find_handler(encodingstyle)
+    unless @handlers.key?(encodingstyle)
+      handler_factory = SOAP::EncodingStyle::Handler.handler(encodingstyle) ||
+	SOAP::EncodingStyle::Handler.handler(EncodingNamespace)
+      handler = handler_factory.new(@parser.charset)
+      handler.decode_typemap = @decode_typemap
+      handler.decode_prologue
+      @handlers[encodingstyle] = handler
+    end
+    @handlers[encodingstyle]
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/processor.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/processor.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/processor.rb	(revision 18425)
@@ -0,0 +1,66 @@
+# SOAP4R - marshal/unmarshal interface.
+# Copyright (C) 2000, 2001, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/datatypes'
+require 'soap/soap'
+require 'soap/element'
+require 'soap/parser'
+require 'soap/generator'
+require 'soap/encodingstyle/soapHandler'
+require 'soap/encodingstyle/literalHandler'
+require 'soap/encodingstyle/aspDotNetHandler'
+
+
+module SOAP
+
+
+module Processor
+  @@default_parser_option = {}
+
+  class << self
+  public
+
+    def marshal(env, opt = {}, io = nil)
+      generator = create_generator(opt)
+      marshalled_str = generator.generate(env, io)
+      unless env.external_content.empty?
+	opt[:external_content] = env.external_content
+      end
+      marshalled_str
+    end
+
+    def unmarshal(stream, opt = {})
+      parser = create_parser(opt)
+      parser.parse(stream)
+    end
+
+    def default_parser_option=(rhs)
+      @@default_parser_option = rhs
+    end
+
+    def default_parser_option
+      @@default_parser_option
+    end
+
+  private
+
+    def create_generator(opt)
+      SOAPGenerator.new(opt)
+    end
+
+    def create_parser(opt)
+      if opt.empty?
+	opt = @@default_parser_option
+      end
+      ::SOAP::Parser.new(opt)
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/property.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/property.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/property.rb	(revision 18425)
@@ -0,0 +1,333 @@
+# soap/property.rb: SOAP4R - Property implementation.
+# Copyright (C) 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+module SOAP
+
+
+# Property stream format:
+#
+#   line separator is \r?\n.  1 line per a property.
+#   line which begins with '#' is a comment line.  empty line is ignored, too.
+#   key/value separator is ':' or '='.
+#   '\' as escape character.  but line separator cannot be escaped.
+#   \s at the head/tail of key/value are trimmed.
+#
+#   '[' + key + ']' indicates property section.  for example,
+#
+#     [aaa.bbb]
+#     ccc = ddd
+#     eee.fff = ggg
+#     []
+#     aaa.hhh = iii
+#
+#   is the same as;
+#
+#     aaa.bbb.ccc = ddd
+#     aaa.bbb.eee.fff = ggg
+#     aaa.hhh = iii
+#
+class Property
+  FrozenError = (RUBY_VERSION >= "1.9.0") ? RuntimeError : TypeError
+
+  include Enumerable
+
+  module Util
+    def const_from_name(fqname)
+      fqname.split("::").inject(Kernel) { |klass, name| klass.const_get(name) }
+    end
+    module_function :const_from_name
+
+    def require_from_name(fqname)
+      require File.join(fqname.split("::").collect { |ele| ele.downcase })
+    end
+    module_function :require_from_name
+  end
+
+  def self.load(stream)
+    new.load(stream)
+  end
+
+  def self.loadproperty(propname)
+    new.loadproperty(propname)
+  end
+
+  def initialize
+    @store = Hash.new
+    @hook = Hash.new
+    @self_hook = Array.new
+    @locked = false
+  end
+
+  KEY_REGSRC = '([^=:\\\\]*(?:\\\\.[^=:\\\\]*)*)'
+  DEF_REGSRC = '\\s*' + KEY_REGSRC + '\\s*[=:]\\s*(.*)'
+  COMMENT_REGEXP = Regexp.new('^(?:#.*|)$')
+  CATDEF_REGEXP = Regexp.new("^\\[\\s*#{KEY_REGSRC}\\s*\\]$")
+  LINE_REGEXP = Regexp.new("^#{DEF_REGSRC}$")
+  def load(stream)
+    key_prefix = ""
+    stream.each_with_index do |line, lineno|
+      line.sub!(/\r?\n\z/, '')
+      case line
+      when COMMENT_REGEXP
+	next
+      when CATDEF_REGEXP
+	key_prefix = $1.strip
+      when LINE_REGEXP
+	key, value = $1.strip, $2.strip
+	key = "#{key_prefix}.#{key}" unless key_prefix.empty?
+	key, value = loadstr(key), loadstr(value)
+	self[key] = value
+      else
+	raise TypeError.new(
+	  "property format error at line #{lineno + 1}: `#{line}'")
+      end
+    end
+    self
+  end
+
+  # find property from $:.
+  def loadproperty(propname)
+    return loadpropertyfile(propname) if File.file?(propname)
+    $:.each do |path|
+      if File.file?(file = File.join(path, propname))
+        return loadpropertyfile(file)
+      end
+    end
+    nil
+  end
+
+  # name: a Symbol, String or an Array
+  def [](name)
+    referent(name_to_a(name))
+  end
+
+  # name: a Symbol, String or an Array
+  # value: an Object
+  def []=(name, value)
+    name_pair = name_to_a(name).freeze
+    hooks = assign(name_pair, value)
+    hooks.each do |hook|
+      hook.call(name_pair, value)
+    end
+    value
+  end
+
+  # value: an Object
+  # key is generated by property
+  def <<(value)
+    self[generate_new_key] = value
+  end
+
+  # name: a Symbol, String or an Array; nil means hook to the root
+  # cascade: true/false; for cascading hook of sub key
+  # hook: block which will be called with 2 args, name and value
+  def add_hook(name = nil, cascade = false, &hook)
+    if name == nil or name == true or name == false
+      cascade = name
+      assign_self_hook(cascade, &hook)
+    else
+      assign_hook(name_to_a(name), cascade, &hook)
+    end
+  end
+
+  def each
+    @store.each do |key, value|
+      yield(key, value)
+    end
+  end
+
+  def empty?
+    @store.empty?
+  end
+
+  def keys
+    @store.keys
+  end
+
+  def values
+    @store.values
+  end
+
+  def lock(cascade = false)
+    if cascade
+      each_key do |key|
+	key.lock(cascade)
+      end
+    end
+    @locked = true
+    self
+  end
+
+  def unlock(cascade = false)
+    @locked = false
+    if cascade
+      each_key do |key|
+	key.unlock(cascade)
+      end
+    end
+    self
+  end
+
+  def locked?
+    @locked
+  end
+
+protected
+
+  def deref_key(key)
+    check_lock(key)
+    ref = @store[key] ||= self.class.new
+    unless propkey?(ref)
+      raise ArgumentError.new("key `#{key}' already defined as a value")
+    end
+    ref
+  end
+
+  def local_referent(key)
+    check_lock(key)
+    if propkey?(@store[key]) and @store[key].locked?
+      raise FrozenError.new("cannot split any key from locked property")
+    end
+    @store[key]
+  end
+
+  def local_assign(key, value)
+    check_lock(key)
+    if @locked
+      if propkey?(value)
+	raise FrozenError.new("cannot add any key to locked property")
+      elsif propkey?(@store[key])
+	raise FrozenError.new("cannot override any key in locked property")
+      end
+    end
+    @store[key] = value
+  end
+
+  def local_hook(key, direct)
+    hooks = []
+    (@self_hook + (@hook[key] || NO_HOOK)).each do |hook, cascade|
+      hooks << hook if direct or cascade
+    end
+    hooks
+  end
+
+  def local_assign_hook(key, cascade, &hook)
+    check_lock(key)
+    @store[key] ||= nil
+    (@hook[key] ||= []) << [hook, cascade]
+  end
+
+private
+
+  NO_HOOK = [].freeze
+
+  def referent(ary)
+    ary[0..-2].inject(self) { |ref, name|
+      ref.deref_key(to_key(name))
+    }.local_referent(to_key(ary.last))
+  end
+
+  def assign(ary, value)
+    ref = self
+    hook = NO_HOOK
+    ary[0..-2].each do |name|
+      key = to_key(name)
+      hook += ref.local_hook(key, false)
+      ref = ref.deref_key(key)
+    end
+    last_key = to_key(ary.last)
+    ref.local_assign(last_key, value)
+    hook + ref.local_hook(last_key, true)
+  end
+
+  def assign_hook(ary, cascade, &hook)
+    ary[0..-2].inject(self) { |ref, name|
+      ref.deref_key(to_key(name))
+    }.local_assign_hook(to_key(ary.last), cascade, &hook)
+  end
+
+  def assign_self_hook(cascade, &hook)
+    check_lock(nil)
+    @self_hook << [hook, cascade]
+  end
+
+  def each_key
+    self.each do |key, value|
+      if propkey?(value)
+	yield(value)
+      end
+    end
+  end
+
+  def check_lock(key)
+    if @locked and (key.nil? or !@store.key?(key))
+      raise FrozenError.new("cannot add any key to locked property")
+    end
+  end
+
+  def propkey?(value)
+    value.is_a?(::SOAP::Property)
+  end
+
+  def name_to_a(name)
+    case name
+    when Symbol
+      [name]
+    when String
+      name.scan(/[^.\\]+(?:\\.[^.\\])*/)	# split with unescaped '.'
+    when Array
+      name
+    else
+      raise ArgumentError.new("Unknown name #{name}(#{name.class})")
+    end
+  end
+
+  def to_key(name)
+    name.to_s.downcase
+  end
+
+  def generate_new_key
+    if @store.empty?
+      "0"
+    else
+      (key_max + 1).to_s
+    end
+  end
+
+  def key_max
+    (@store.keys.max { |l, r| l.to_s.to_i <=> r.to_s.to_i }).to_s.to_i
+  end
+
+  def loadpropertyfile(file)
+    puts "find property at #{file}" if $DEBUG
+    File.open(file) do |f|
+      load(f)
+    end
+  end
+
+  def loadstr(str)
+    str.gsub(/\\./) { |c| eval("\"#{c}\"") }
+  end
+end
+
+
+end
+
+
+# for ruby/1.6.
+unless Enumerable.instance_methods.include?('inject')
+  module Enumerable
+    def inject(init)
+      result = init
+      each do |item|
+	result = yield(result, item)
+      end
+      result
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/cgistub.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/cgistub.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/cgistub.rb	(revision 18425)
@@ -0,0 +1,206 @@
+# SOAP4R - CGI/mod_ruby stub library
+# Copyright (C) 2001, 2003-2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/streamHandler'
+require 'webrick/httpresponse'
+require 'webrick/httpstatus'
+require 'logger'
+require 'soap/rpc/soaplet'
+
+
+module SOAP
+module RPC
+
+
+###
+# SYNOPSIS
+#   CGIStub.new
+#
+# DESCRIPTION
+#   To be written...
+#
+class CGIStub < Logger::Application
+  include SOAP
+  include WEBrick
+
+  class SOAPRequest
+    attr_reader :body
+
+    def [](var); end
+
+    def meta_vars; end
+  end
+
+  class SOAPStdinRequest < SOAPRequest
+    attr_reader :body
+
+    def initialize(stream)
+      size = ENV['CONTENT_LENGTH'].to_i || 0
+      @body = stream.read(size)
+    end
+
+    def [](var)
+      ENV[var.gsub(/-/, '_').upcase]
+    end
+
+    def meta_vars
+      {
+        'HTTP_SOAPACTION' => ENV['HTTP_SOAPAction']
+      }
+    end
+  end
+
+  class SOAPFCGIRequest < SOAPRequest
+    attr_reader :body
+
+    def initialize(request)
+      @request = request
+      @body = @request.in.read
+    end
+
+    def [](var)
+      @request.env[var.gsub(/-/, '_').upcase]
+    end
+
+    def meta_vars
+      {
+        'HTTP_SOAPACTION' => @request.env['HTTP_SOAPAction']
+      }
+    end
+  end
+
+  def initialize(appname, default_namespace)
+    super(appname)
+    set_log(STDERR)
+    self.level = ERROR
+    @default_namespace = default_namespace
+    @remote_host = ENV['REMOTE_HOST'] || ENV['REMOTE_ADDR'] || 'unknown'
+    @router = ::SOAP::RPC::Router.new(self.class.name)
+    @soaplet = ::SOAP::RPC::SOAPlet.new(@router)
+    on_init
+  end
+  
+  def on_init
+    # do extra initialization in a derived class if needed.
+  end
+
+  def mapping_registry
+    @router.mapping_registry
+  end
+
+  def mapping_registry=(value)
+    @router.mapping_registry = value
+  end
+
+  def generate_explicit_type
+    @router.generate_explicit_type
+  end
+
+  def generate_explicit_type=(generate_explicit_type)
+    @router.generate_explicit_type = generate_explicit_type
+  end
+
+  # servant entry interface
+
+  def add_rpc_servant(obj, namespace = @default_namespace)
+    @router.add_rpc_servant(obj, namespace)
+  end
+  alias add_servant add_rpc_servant
+
+  def add_headerhandler(obj)
+    @router.add_headerhandler(obj)
+  end
+  alias add_rpc_headerhandler add_headerhandler
+
+  # method entry interface
+
+  def add_rpc_method(obj, name, *param)
+    add_rpc_method_with_namespace_as(@default_namespace, obj, name, name, *param)
+  end
+  alias add_method add_rpc_method
+
+  def add_rpc_method_as(obj, name, name_as, *param)
+    add_rpc_method_with_namespace_as(@default_namespace, obj, name, name_as, *param)
+  end
+  alias add_method_as add_rpc_method_as
+
+  def add_rpc_method_with_namespace(namespace, obj, name, *param)
+    add_rpc_method_with_namespace_as(namespace, obj, name, name, *param)
+  end
+  alias add_method_with_namespace add_rpc_method_with_namespace
+
+  def add_rpc_method_with_namespace_as(namespace, obj, name, name_as, *param)
+    qname = XSD::QName.new(namespace, name_as)
+    soapaction = nil
+    param_def = SOAPMethod.derive_rpc_param_def(obj, name, *param)
+    @router.add_rpc_operation(obj, qname, soapaction, name, param_def)
+  end
+  alias add_method_with_namespace_as add_rpc_method_with_namespace_as
+
+  def add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {})
+    @router.add_rpc_operation(receiver, qname, soapaction, name, param_def, opt)
+  end
+
+  def add_document_operation(receiver, soapaction, name, param_def, opt = {})
+    @router.add_document_operation(receiver, soapaction, name, param_def, opt)
+  end
+
+  def set_fcgi_request(request)
+    @fcgi = request
+  end
+
+private
+
+  HTTPVersion = WEBrick::HTTPVersion.new('1.0')       # dummy; ignored
+
+  def run
+    res = WEBrick::HTTPResponse.new({:HTTPVersion => HTTPVersion})
+    begin
+      @log.info { "received a request from '#{ @remote_host }'" }
+      if @fcgi
+        req = SOAPFCGIRequest.new(@fcgi)
+      else
+        req = SOAPStdinRequest.new($stdin)
+      end
+      @soaplet.do_POST(req, res)
+    rescue HTTPStatus::EOFError, HTTPStatus::RequestTimeout => ex
+      res.set_error(ex)
+    rescue HTTPStatus::Error => ex
+      res.set_error(ex)
+    rescue HTTPStatus::Status => ex
+      res.status = ex.code
+    rescue StandardError, NameError => ex # for Ruby 1.6
+      res.set_error(ex, true)
+    ensure
+      if defined?(MOD_RUBY)
+        r = Apache.request
+        r.status = res.status
+        r.content_type = res.content_type
+        r.send_http_header
+        buf = res.body
+      else
+        buf = ''
+        res.send_response(buf)
+        buf.sub!(/^[^\r]+\r\n/, '')       # Trim status line.
+      end
+      @log.debug { "SOAP CGI Response:\n#{ buf }" }
+      if @fcgi
+        @fcgi.out.print buf
+        @fcgi.finish
+        @fcgi = nil
+      else
+        print buf
+      end
+    end
+    0
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/driver.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/driver.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/driver.rb	(revision 18425)
@@ -0,0 +1,254 @@
+# SOAP4R - SOAP RPC driver
+# Copyright (C) 2000, 2001, 2003-2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/soap'
+require 'soap/mapping'
+require 'soap/mapping/wsdlliteralregistry'
+require 'soap/rpc/rpc'
+require 'soap/rpc/proxy'
+require 'soap/rpc/element'
+require 'soap/streamHandler'
+require 'soap/property'
+require 'soap/header/handlerset'
+
+
+module SOAP
+module RPC
+
+
+class Driver
+  class << self
+    if RUBY_VERSION >= "1.7.0"
+      def __attr_proxy(symbol, assignable = false)
+        name = symbol.to_s
+        define_method(name) {
+          @proxy.__send__(name)
+        }
+        if assignable
+          aname = name + '='
+          define_method(aname) { |rhs|
+            @proxy.__send__(aname, rhs)
+          }
+        end
+      end
+    else
+      def __attr_proxy(symbol, assignable = false)
+        name = symbol.to_s
+        module_eval <<-EOS
+          def #{name}
+            @proxy.#{name}
+          end
+        EOS
+        if assignable
+          module_eval <<-EOS
+            def #{name}=(value)
+              @proxy.#{name} = value
+            end
+          EOS
+        end
+      end
+    end
+  end
+
+  __attr_proxy :endpoint_url, true
+  __attr_proxy :mapping_registry, true
+  __attr_proxy :default_encodingstyle, true
+  __attr_proxy :generate_explicit_type, true
+  __attr_proxy :allow_unqualified_element, true
+  __attr_proxy :headerhandler
+  __attr_proxy :streamhandler
+  __attr_proxy :test_loopback_response
+  __attr_proxy :reset_stream
+
+  attr_reader :proxy
+  attr_reader :options
+  attr_accessor :soapaction
+
+  def inspect
+    "#<#{self.class}:#{@proxy.inspect}>"
+  end
+
+  def httpproxy
+    options["protocol.http.proxy"]
+  end
+
+  def httpproxy=(httpproxy)
+    options["protocol.http.proxy"] = httpproxy
+  end
+
+  def wiredump_dev
+    options["protocol.http.wiredump_dev"]
+  end
+
+  def wiredump_dev=(wiredump_dev)
+    options["protocol.http.wiredump_dev"] = wiredump_dev
+  end
+
+  def mandatorycharset
+    options["protocol.mandatorycharset"]
+  end
+
+  def mandatorycharset=(mandatorycharset)
+    options["protocol.mandatorycharset"] = mandatorycharset
+  end
+
+  def wiredump_file_base
+    options["protocol.wiredump_file_base"]
+  end
+
+  def wiredump_file_base=(wiredump_file_base)
+    options["protocol.wiredump_file_base"] = wiredump_file_base
+  end
+
+  def initialize(endpoint_url, namespace = nil, soapaction = nil)
+    @namespace = namespace
+    @soapaction = soapaction
+    @options = setup_options
+    @wiredump_file_base = nil
+    @proxy = Proxy.new(endpoint_url, @soapaction, @options)
+  end
+
+  def loadproperty(propertyname)
+    unless options.loadproperty(propertyname)
+      raise LoadError.new("No such property to load -- #{propertyname}")
+    end
+  end
+
+  def add_rpc_method(name, *params)
+    add_rpc_method_with_soapaction_as(name, name, @soapaction, *params)
+  end
+
+  def add_rpc_method_as(name, name_as, *params)
+    add_rpc_method_with_soapaction_as(name, name_as, @soapaction, *params)
+  end
+
+  def add_rpc_method_with_soapaction(name, soapaction, *params)
+    add_rpc_method_with_soapaction_as(name, name, soapaction, *params)
+  end
+
+  def add_rpc_method_with_soapaction_as(name, name_as, soapaction, *params)
+    param_def = SOAPMethod.create_rpc_param_def(params)
+    qname = XSD::QName.new(@namespace, name_as)
+    @proxy.add_rpc_method(qname, soapaction, name, param_def)
+    add_rpc_method_interface(name, param_def)
+  end
+
+  # add_method is for shortcut of typical rpc/encoded method definition.
+  alias add_method add_rpc_method
+  alias add_method_as add_rpc_method_as
+  alias add_method_with_soapaction add_rpc_method_with_soapaction
+  alias add_method_with_soapaction_as add_rpc_method_with_soapaction_as
+
+  def add_document_method(name, soapaction, req_qname, res_qname)
+    param_def = SOAPMethod.create_doc_param_def(req_qname, res_qname)
+    @proxy.add_document_method(soapaction, name, param_def)
+    add_document_method_interface(name, param_def)
+  end
+
+  def add_rpc_operation(qname, soapaction, name, param_def, opt = {})
+    @proxy.add_rpc_operation(qname, soapaction, name, param_def, opt)
+    add_rpc_method_interface(name, param_def)
+  end
+
+  def add_document_operation(soapaction, name, param_def, opt = {})
+    @proxy.add_document_operation(soapaction, name, param_def, opt)
+    add_document_method_interface(name, param_def)
+  end
+
+  def invoke(headers, body)
+    if headers and !headers.is_a?(SOAPHeader)
+      headers = create_header(headers)
+    end
+    set_wiredump_file_base(body.elename.name)
+    env = @proxy.invoke(headers, body)
+    if env.nil?
+      return nil, nil
+    else
+      return env.header, env.body
+    end
+  end
+
+  def call(name, *params)
+    set_wiredump_file_base(name)
+    @proxy.call(name, *params)
+  end
+
+private
+
+  def set_wiredump_file_base(name)
+    if @wiredump_file_base
+      @proxy.set_wiredump_file_base("#{@wiredump_file_base}_#{name}")
+    end
+  end
+
+  def create_header(headers)
+    header = SOAPHeader.new()
+    headers.each do |content, mustunderstand, encodingstyle|
+      header.add(SOAPHeaderItem.new(content, mustunderstand, encodingstyle))
+    end
+    header
+  end
+
+  def setup_options
+    if opt = Property.loadproperty(::SOAP::PropertyName)
+      opt = opt["client"]
+    end
+    opt ||= Property.new
+    opt.add_hook("protocol.mandatorycharset") do |key, value|
+      @proxy.mandatorycharset = value
+    end
+    opt.add_hook("protocol.wiredump_file_base") do |key, value|
+      @wiredump_file_base = value
+    end
+    opt["protocol.http.charset"] ||= XSD::Charset.xml_encoding_label
+    opt["protocol.http.proxy"] ||= Env::HTTP_PROXY
+    opt["protocol.http.no_proxy"] ||= Env::NO_PROXY
+    opt
+  end
+
+  def add_rpc_method_interface(name, param_def)
+    param_count = RPC::SOAPMethod.param_count(param_def,
+      RPC::SOAPMethod::IN, RPC::SOAPMethod::INOUT)
+    add_method_interface(name, param_count)
+  end
+
+  def add_document_method_interface(name, param_def)
+    param_count = RPC::SOAPMethod.param_count(param_def, RPC::SOAPMethod::IN)
+    add_method_interface(name, param_count)
+  end
+
+  if RUBY_VERSION > "1.7.0"
+    def add_method_interface(name, param_count)
+      ::SOAP::Mapping.define_singleton_method(self, name) do |*arg|
+        unless arg.size == param_count
+          raise ArgumentError.new(
+          "wrong number of arguments (#{arg.size} for #{param_count})")
+        end
+        call(name, *arg)
+      end
+      self.method(name)
+    end
+  else
+    def add_method_interface(name, param_count)
+      instance_eval <<-EOS
+        def #{name}(*arg)
+          unless arg.size == #{param_count}
+            raise ArgumentError.new(
+              "wrong number of arguments (\#{arg.size} for #{param_count})")
+          end
+          call(#{name.dump}, *arg)
+        end
+      EOS
+      self.method(name)
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/element.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/element.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/element.rb	(revision 18425)
@@ -0,0 +1,325 @@
+# SOAP4R - RPC element definition.
+# Copyright (C) 2000, 2001, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/baseData'
+
+
+module SOAP
+
+# Add method definitions for RPC to common definition in element.rb
+class SOAPBody < SOAPStruct
+  public
+
+  def request
+    root_node
+  end
+
+  def response
+    root = root_node
+    if !@is_fault
+      if root.nil?
+        nil
+      elsif root.is_a?(SOAPBasetype)
+        root
+      else
+        # Initial element is [retval].
+        root[0]
+      end
+    else
+      root
+    end
+  end
+
+  def outparams
+    root = root_node
+    if !@is_fault and !root.nil? and !root.is_a?(SOAPBasetype)
+      op = root[1..-1]
+      op = nil if op && op.empty?
+      op
+    else
+      nil
+    end
+  end
+
+  def fault
+    if @is_fault
+      self['fault']
+    else
+      nil
+    end
+  end
+
+  def fault=(fault)
+    @is_fault = true
+    add_member('fault', fault)
+  end
+end
+
+
+module RPC
+
+
+class RPCError < Error; end
+class MethodDefinitionError < RPCError; end
+class ParameterError < RPCError; end
+
+class SOAPMethod < SOAPStruct
+  RETVAL = 'retval'
+  IN = 'in'
+  OUT = 'out'
+  INOUT = 'inout'
+
+  attr_reader :param_def
+  attr_reader :inparam
+  attr_reader :outparam
+  attr_reader :retval_name
+  attr_reader :retval_class_name
+
+  def initialize(qname, param_def = nil)
+    super(nil)
+    @elename = qname
+    @encodingstyle = nil
+
+    @param_def = param_def
+
+    @signature = []
+    @inparam_names = []
+    @inoutparam_names = []
+    @outparam_names = []
+
+    @inparam = {}
+    @outparam = {}
+    @retval_name = nil
+    @retval_class_name = nil
+
+    init_param(@param_def) if @param_def
+  end
+
+  def have_outparam?
+    @outparam_names.size > 0
+  end
+
+  def input_params
+    collect_params(IN, INOUT)
+  end
+
+  def output_params
+    collect_params(OUT, INOUT)
+  end
+
+  def set_param(params)
+    params.each do |param, data|
+      @inparam[param] = data
+      data.elename.name = param
+      data.parent = self
+    end
+  end
+
+  def set_outparam(params)
+    params.each do |param, data|
+      @outparam[param] = data
+      data.elename.name = param
+    end
+  end
+
+  def SOAPMethod.param_count(param_def, *type)
+    count = 0
+    param_def.each do |io_type, name, param_type|
+      if type.include?(io_type)
+        count += 1
+      end
+    end
+    count
+  end
+
+  def SOAPMethod.derive_rpc_param_def(obj, name, *param)
+    if param.size == 1 and param[0].is_a?(Array)
+      return param[0]
+    end
+    if param.empty?
+      method = obj.method(name)
+      param_names = (1..method.arity.abs).collect { |i| "p#{i}" }
+    else
+      param_names = param
+    end
+    create_rpc_param_def(param_names)
+  end
+
+  def SOAPMethod.create_rpc_param_def(param_names)
+    param_def = []
+    param_names.each do |param_name|
+      param_def.push([IN, param_name, nil])
+    end
+    param_def.push([RETVAL, 'return', nil])
+    param_def
+  end
+
+  def SOAPMethod.create_doc_param_def(req_qnames, res_qnames)
+    req_qnames = [req_qnames] if req_qnames.is_a?(XSD::QName)
+    res_qnames = [res_qnames] if res_qnames.is_a?(XSD::QName)
+    param_def = []
+    req_qnames.each do |qname|
+      param_def << [IN, qname.name, [nil, qname.namespace, qname.name]]
+    end
+    res_qnames.each do |qname|
+      param_def << [OUT, qname.name, [nil, qname.namespace, qname.name]]
+    end
+    param_def
+  end
+
+private
+
+  def collect_params(*type)
+    names = []
+    @signature.each do |io_type, name, param_type|
+      names << name if type.include?(io_type)
+    end
+    names
+  end
+
+  def init_param(param_def)
+    param_def.each do |io_type, name, param_type|
+      case io_type
+      when IN
+        @signature.push([IN, name, param_type])
+        @inparam_names.push(name)
+      when OUT
+        @signature.push([OUT, name, param_type])
+        @outparam_names.push(name)
+      when INOUT
+        @signature.push([INOUT, name, param_type])
+        @inoutparam_names.push(name)
+      when RETVAL
+        if @retval_name
+          raise MethodDefinitionError.new('duplicated retval')
+        end
+        @retval_name = name
+        @retval_class_name = nil
+        if param_type
+          if param_type[0].is_a?(String)
+            @retval_class_name = Mapping.class_from_name(param_type[0])
+          else
+            @retval_class_name = param_type[0]
+          end
+        end
+      else
+        raise MethodDefinitionError.new("unknown type: #{io_type}")
+      end
+    end
+  end
+end
+
+
+class SOAPMethodRequest < SOAPMethod
+  attr_accessor :soapaction
+
+  def SOAPMethodRequest.create_request(qname, *params)
+    param_def = []
+    param_value = []
+    i = 0
+    params.each do |param|
+      param_name = "p#{i}"
+      i += 1
+      param_def << [IN, param_name, nil]
+      param_value << [param_name, param]
+    end
+    param_def << [RETVAL, 'return', nil]
+    o = new(qname, param_def)
+    o.set_param(param_value)
+    o
+  end
+
+  def initialize(qname, param_def = nil, soapaction = nil)
+    check_elename(qname)
+    super(qname, param_def)
+    @soapaction = soapaction
+  end
+
+  def each
+    input_params.each do |name|
+      unless @inparam[name]
+        raise ParameterError.new("parameter: #{name} was not given")
+      end
+      yield(name, @inparam[name])
+    end
+  end
+
+  def dup
+    req = self.class.new(@elename.dup, @param_def, @soapaction)
+    req.encodingstyle = @encodingstyle
+    req
+  end
+
+  def create_method_response(response_name = nil)
+    response_name ||=
+      XSD::QName.new(@elename.namespace, @elename.name + 'Response')
+    SOAPMethodResponse.new(response_name, @param_def)
+  end
+
+private
+
+  def check_elename(qname)
+    # NCName & ruby's method name
+    unless /\A[\w_][\w\d_\-]*\z/ =~ qname.name
+      raise MethodDefinitionError.new("element name '#{qname.name}' not allowed")
+    end
+  end
+end
+
+
+class SOAPMethodResponse < SOAPMethod
+
+  def initialize(qname, param_def = nil)
+    super(qname, param_def)
+    @retval = nil
+  end
+
+  def retval=(retval)
+    @retval = retval
+    @retval.elename = @retval.elename.dup_name(@retval_name || 'return')
+    retval.parent = self
+    retval
+  end
+
+  def each
+    if @retval_name and !@retval.is_a?(SOAPVoid)
+      yield(@retval_name, @retval)
+    end
+
+    output_params.each do |name|
+      unless @outparam[name]
+        raise ParameterError.new("parameter: #{name} was not given")
+      end
+      yield(name, @outparam[name])
+    end
+  end
+end
+
+
+# To return(?) void explicitly.
+#  def foo(input_var)
+#    ...
+#    return SOAP::RPC::SOAPVoid.new
+#  end
+class SOAPVoid < XSD::XSDAnySimpleType
+  include SOAPBasetype
+  extend SOAPModuleUtils
+  Name = XSD::QName.new(Mapping::RubyCustomTypeNamespace, nil)
+
+public
+  def initialize()
+    @elename = Name
+    @id = nil
+    @precedents = []
+    @parent = nil
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/httpserver.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/httpserver.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/httpserver.rb	(revision 18425)
@@ -0,0 +1,129 @@
+# SOAP4R - WEBrick HTTP Server
+# Copyright (C) 2003, 2004 by NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'logger'
+require 'soap/rpc/soaplet'
+require 'soap/streamHandler'
+require 'webrick'
+
+
+module SOAP
+module RPC
+
+
+class HTTPServer < Logger::Application
+  attr_reader :server
+  attr_accessor :default_namespace
+
+  def initialize(config)
+    super(config[:SOAPHTTPServerApplicationName] || self.class.name)
+    @default_namespace = config[:SOAPDefaultNamespace]
+    @webrick_config = config.dup
+    self.level = Logger::Severity::ERROR # keep silent by default
+    @webrick_config[:Logger] ||= @log
+    @log = @webrick_config[:Logger]     # sync logger of App and HTTPServer
+    @router = ::SOAP::RPC::Router.new(self.class.name)
+    @soaplet = ::SOAP::RPC::SOAPlet.new(@router)
+    on_init
+    @server = WEBrick::HTTPServer.new(@webrick_config)
+    @server.mount('/', @soaplet)
+  end
+
+  def on_init
+    # do extra initialization in a derived class if needed.
+  end
+
+  def status
+    @server.status if @server
+  end
+
+  def shutdown
+    @server.shutdown if @server
+  end
+
+  def mapping_registry
+    @router.mapping_registry
+  end
+
+  def mapping_registry=(mapping_registry)
+    @router.mapping_registry = mapping_registry
+  end
+
+  def generate_explicit_type
+    @router.generate_explicit_type
+  end
+
+  def generate_explicit_type=(generate_explicit_type)
+    @router.generate_explicit_type = generate_explicit_type
+  end
+
+  # servant entry interface
+
+  def add_rpc_request_servant(factory, namespace = @default_namespace)
+    @router.add_rpc_request_servant(factory, namespace)
+  end
+
+  def add_rpc_servant(obj, namespace = @default_namespace)
+    @router.add_rpc_servant(obj, namespace)
+  end
+  
+  def add_request_headerhandler(factory)
+    @router.add_request_headerhandler(factory)
+  end
+
+  def add_headerhandler(obj)
+    @router.add_headerhandler(obj)
+  end
+  alias add_rpc_headerhandler add_headerhandler
+
+  # method entry interface
+
+  def add_rpc_method(obj, name, *param)
+    add_rpc_method_as(obj, name, name, *param)
+  end
+  alias add_method add_rpc_method
+
+  def add_rpc_method_as(obj, name, name_as, *param)
+    qname = XSD::QName.new(@default_namespace, name_as)
+    soapaction = nil
+    param_def = SOAPMethod.derive_rpc_param_def(obj, name, *param)
+    @router.add_rpc_operation(obj, qname, soapaction, name, param_def)
+  end
+  alias add_method_as add_rpc_method_as
+
+  def add_document_method(obj, soapaction, name, req_qnames, res_qnames)
+    param_def = SOAPMethod.create_doc_param_def(req_qnames, res_qnames)
+    @router.add_document_operation(obj, soapaction, name, param_def)
+  end
+
+  def add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {})
+    @router.add_rpc_operation(receiver, qname, soapaction, name, param_def, opt)
+  end
+
+  def add_rpc_request_operation(factory, qname, soapaction, name, param_def, opt = {})
+    @router.add_rpc_request_operation(factory, qname, soapaction, name, param_def, opt)
+  end
+
+  def add_document_operation(receiver, soapaction, name, param_def, opt = {})
+    @router.add_document_operation(receiver, soapaction, name, param_def, opt)
+  end
+
+  def add_document_request_operation(factory, soapaction, name, param_def, opt = {})
+    @router.add_document_request_operation(factory, soapaction, name, param_def, opt)
+  end
+
+private
+
+  def run
+    @server.start
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/proxy.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/proxy.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/proxy.rb	(revision 18425)
@@ -0,0 +1,497 @@
+# SOAP4R - RPC Proxy library.
+# Copyright (C) 2000, 2003-2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/soap'
+require 'soap/processor'
+require 'soap/mapping'
+require 'soap/rpc/rpc'
+require 'soap/rpc/element'
+require 'soap/streamHandler'
+require 'soap/mimemessage'
+
+
+module SOAP
+module RPC
+
+
+class Proxy
+  include SOAP
+
+public
+
+  attr_accessor :soapaction
+  attr_accessor :mandatorycharset
+  attr_accessor :allow_unqualified_element
+  attr_accessor :default_encodingstyle
+  attr_accessor :generate_explicit_type
+  attr_reader :headerhandler
+  attr_reader :streamhandler
+
+  attr_accessor :mapping_registry
+  attr_accessor :literal_mapping_registry
+
+  attr_reader :operation
+
+  def initialize(endpoint_url, soapaction, options)
+    @endpoint_url = endpoint_url
+    @soapaction = soapaction
+    @options = options
+    @streamhandler = HTTPStreamHandler.new(
+      @options["protocol.http"] ||= ::SOAP::Property.new)
+    @operation = {}
+    @mandatorycharset = nil
+    @allow_unqualified_element = true
+    @default_encodingstyle = nil
+    @generate_explicit_type = true
+    @headerhandler = Header::HandlerSet.new
+    @mapping_registry = nil
+    @literal_mapping_registry = ::SOAP::Mapping::WSDLLiteralRegistry.new
+  end
+
+  def inspect
+    "#<#{self.class}:#{@endpoint_url}>"
+  end
+
+  def endpoint_url
+    @endpoint_url
+  end
+
+  def endpoint_url=(endpoint_url)
+    @endpoint_url = endpoint_url
+    reset_stream
+  end
+
+  def reset_stream
+    @streamhandler.reset(@endpoint_url)
+  end
+
+  def set_wiredump_file_base(wiredump_file_base)
+    @streamhandler.wiredump_file_base = wiredump_file_base
+  end
+
+  def test_loopback_response
+    @streamhandler.test_loopback_response
+  end
+
+  def add_rpc_operation(qname, soapaction, name, param_def, opt = {})
+    opt[:request_qname] = qname
+    opt[:request_style] ||= :rpc
+    opt[:response_style] ||= :rpc
+    opt[:request_use] ||= :encoded
+    opt[:response_use] ||= :encoded
+    @operation[name] = Operation.new(soapaction, param_def, opt)
+  end
+
+  def add_document_operation(soapaction, name, param_def, opt = {})
+    opt[:request_style] ||= :document
+    opt[:response_style] ||= :document
+    opt[:request_use] ||= :literal
+    opt[:response_use] ||= :literal
+    # default values of these values are unqualified in XML Schema.
+    # set true for backward compatibility.
+    unless opt.key?(:elementformdefault)
+      opt[:elementformdefault] = true
+    end
+    unless opt.key?(:attributeformdefault)
+      opt[:attributeformdefault] = true
+    end
+    @operation[name] = Operation.new(soapaction, param_def, opt)
+  end
+
+  # add_method is for shortcut of typical rpc/encoded method definition.
+  alias add_method add_rpc_operation
+  alias add_rpc_method add_rpc_operation
+  alias add_document_method add_document_operation
+
+  def invoke(req_header, req_body, opt = nil)
+    opt ||= create_encoding_opt
+    route(req_header, req_body, opt, opt)
+  end
+
+  def call(name, *params)
+    unless op_info = @operation[name]
+      raise MethodDefinitionError, "method: #{name} not defined"
+    end
+    mapping_opt = create_mapping_opt
+    req_header = create_request_header
+    req_body = SOAPBody.new(
+      op_info.request_body(params, @mapping_registry,
+        @literal_mapping_registry, mapping_opt)
+    )
+    reqopt = create_encoding_opt(
+      :soapaction => op_info.soapaction || @soapaction,
+      :envelopenamespace => @options["soap.envelope.requestnamespace"],
+      :default_encodingstyle =>
+        @default_encodingstyle || op_info.request_default_encodingstyle,
+      :elementformdefault => op_info.elementformdefault,
+      :attributeformdefault => op_info.attributeformdefault
+    )
+    resopt = create_encoding_opt(
+      :envelopenamespace => @options["soap.envelope.responsenamespace"],
+      :default_encodingstyle =>
+        @default_encodingstyle || op_info.response_default_encodingstyle,
+      :elementformdefault => op_info.elementformdefault,
+      :attributeformdefault => op_info.attributeformdefault
+    )
+    env = route(req_header, req_body, reqopt, resopt)
+    raise EmptyResponseError unless env
+    receive_headers(env.header)
+    begin
+      check_fault(env.body)
+    rescue ::SOAP::FaultError => e
+      op_info.raise_fault(e, @mapping_registry, @literal_mapping_registry)
+    end
+    op_info.response_obj(env.body, @mapping_registry,
+      @literal_mapping_registry, mapping_opt)
+  end
+
+  def route(req_header, req_body, reqopt, resopt)
+    req_env = ::SOAP::SOAPEnvelope.new(req_header, req_body)
+    unless reqopt[:envelopenamespace].nil?
+      set_envelopenamespace(req_env, reqopt[:envelopenamespace])
+    end
+    reqopt[:external_content] = nil
+    conn_data = marshal(req_env, reqopt)
+    if ext = reqopt[:external_content]
+      mime = MIMEMessage.new
+      ext.each do |k, v|
+      	mime.add_attachment(v.data)
+      end
+      mime.add_part(conn_data.send_string + "\r\n")
+      mime.close
+      conn_data.send_string = mime.content_str
+      conn_data.send_contenttype = mime.headers['content-type'].str
+    end
+    conn_data = @streamhandler.send(@endpoint_url, conn_data,
+      reqopt[:soapaction])
+    if conn_data.receive_string.empty?
+      return nil
+    end
+    unmarshal(conn_data, resopt)
+  end
+
+  def check_fault(body)
+    if body.fault
+      raise SOAP::FaultError.new(body.fault)
+    end
+  end
+
+private
+
+  def set_envelopenamespace(env, namespace)
+    env.elename = XSD::QName.new(namespace, env.elename.name)
+    if env.header
+      env.header.elename = XSD::QName.new(namespace, env.header.elename.name)
+    end
+    if env.body
+      env.body.elename = XSD::QName.new(namespace, env.body.elename.name)
+    end
+  end
+
+  def create_request_header
+    headers = @headerhandler.on_outbound
+    if headers.empty?
+      nil
+    else
+      h = ::SOAP::SOAPHeader.new
+      headers.each do |header|
+        h.add(header.elename.name, header)
+      end
+      h
+    end
+  end
+
+  def receive_headers(headers)
+    @headerhandler.on_inbound(headers) if headers
+  end
+
+  def marshal(env, opt)
+    send_string = Processor.marshal(env, opt)
+    StreamHandler::ConnectionData.new(send_string)
+  end
+
+  def unmarshal(conn_data, opt)
+    contenttype = conn_data.receive_contenttype
+    if /#{MIMEMessage::MultipartContentType}/i =~ contenttype
+      opt[:external_content] = {}
+      mime = MIMEMessage.parse("Content-Type: " + contenttype,
+	conn_data.receive_string)
+      mime.parts.each do |part|
+	value = Attachment.new(part.content)
+	value.contentid = part.contentid
+	obj = SOAPAttachment.new(value)
+	opt[:external_content][value.contentid] = obj if value.contentid
+      end
+      opt[:charset] = @mandatorycharset ||
+	StreamHandler.parse_media_type(mime.root.headers['content-type'].str)
+      env = Processor.unmarshal(mime.root.content, opt)
+    else
+      opt[:charset] = @mandatorycharset ||
+	::SOAP::StreamHandler.parse_media_type(contenttype)
+      env = Processor.unmarshal(conn_data.receive_string, opt)
+    end
+    unless env.is_a?(::SOAP::SOAPEnvelope)
+      raise ResponseFormatError.new(
+        "response is not a SOAP envelope: #{conn_data.receive_string}")
+    end
+    env
+  end
+
+  def create_header(headers)
+    header = SOAPHeader.new()
+    headers.each do |content, mustunderstand, encodingstyle|
+      header.add(SOAPHeaderItem.new(content, mustunderstand, encodingstyle))
+    end
+    header
+  end
+
+  def create_encoding_opt(hash = nil)
+    opt = {}
+    opt[:default_encodingstyle] = @default_encodingstyle
+    opt[:allow_unqualified_element] = @allow_unqualified_element
+    opt[:generate_explicit_type] = @generate_explicit_type
+    opt[:no_indent] = @options["soap.envelope.no_indent"]
+    opt[:use_numeric_character_reference] =
+      @options["soap.envelope.use_numeric_character_reference"]
+    opt.update(hash) if hash
+    opt
+  end
+
+  def create_mapping_opt(hash = nil)
+    opt = {
+      :external_ces => @options["soap.mapping.external_ces"]
+    }
+    opt.update(hash) if hash
+    opt
+  end
+
+  class Operation
+    attr_reader :soapaction
+    attr_reader :request_style
+    attr_reader :response_style
+    attr_reader :request_use
+    attr_reader :response_use
+    attr_reader :elementformdefault
+    attr_reader :attributeformdefault
+
+    def initialize(soapaction, param_def, opt)
+      @soapaction = soapaction
+      @request_style = opt[:request_style]
+      @response_style = opt[:response_style]
+      @request_use = opt[:request_use]
+      @response_use = opt[:response_use]
+      # set nil(unqualified) by default
+      @elementformdefault = opt[:elementformdefault]
+      @attributeformdefault = opt[:attributeformdefault]
+      check_style(@request_style)
+      check_style(@response_style)
+      check_use(@request_use)
+      check_use(@response_use)
+      if @request_style == :rpc
+        @rpc_request_qname = opt[:request_qname]
+        if @rpc_request_qname.nil?
+          raise MethodDefinitionError.new("rpc_request_qname must be given")
+        end
+        @rpc_method_factory =
+          RPC::SOAPMethodRequest.new(@rpc_request_qname, param_def, @soapaction)
+      else
+        @doc_request_qnames = []
+        @doc_request_qualified = []
+        @doc_response_qnames = []
+        @doc_response_qualified = []
+        param_def.each do |inout, paramname, typeinfo, eleinfo|
+          klass_not_used, nsdef, namedef = typeinfo
+          qualified = eleinfo
+          if namedef.nil?
+            raise MethodDefinitionError.new("qname must be given")
+          end
+          case inout
+          when SOAPMethod::IN
+            @doc_request_qnames << XSD::QName.new(nsdef, namedef)
+            @doc_request_qualified << qualified
+          when SOAPMethod::OUT
+            @doc_response_qnames << XSD::QName.new(nsdef, namedef)
+            @doc_response_qualified << qualified
+          else
+            raise MethodDefinitionError.new(
+              "illegal inout definition for document style: #{inout}")
+          end
+        end
+      end
+    end
+
+    def request_default_encodingstyle
+      (@request_use == :encoded) ? EncodingNamespace : LiteralNamespace
+    end
+
+    def response_default_encodingstyle
+      (@response_use == :encoded) ? EncodingNamespace : LiteralNamespace
+    end
+
+    def request_body(values, mapping_registry, literal_mapping_registry, opt)
+      if @request_style == :rpc
+        request_rpc(values, mapping_registry, literal_mapping_registry, opt)
+      else
+        request_doc(values, mapping_registry, literal_mapping_registry, opt)
+      end
+    end
+
+    def response_obj(body, mapping_registry, literal_mapping_registry, opt)
+      if @response_style == :rpc
+        response_rpc(body, mapping_registry, literal_mapping_registry, opt)
+      else
+        response_doc(body, mapping_registry, literal_mapping_registry, opt)
+      end
+    end
+
+    def raise_fault(e, mapping_registry, literal_mapping_registry)
+      if @response_style == :rpc
+        Mapping.fault2exception(e, mapping_registry)
+      else
+        Mapping.fault2exception(e, literal_mapping_registry)
+      end
+    end
+
+  private
+
+    def check_style(style)
+      unless [:rpc, :document].include?(style)
+        raise MethodDefinitionError.new("unknown style: #{style}")
+      end
+    end
+
+    def check_use(use)
+      unless [:encoded, :literal].include?(use)
+        raise MethodDefinitionError.new("unknown use: #{use}")
+      end
+    end
+
+    def request_rpc(values, mapping_registry, literal_mapping_registry, opt)
+      if @request_use == :encoded
+        request_rpc_enc(values, mapping_registry, opt)
+      else
+        request_rpc_lit(values, literal_mapping_registry, opt)
+      end
+    end
+
+    def request_doc(values, mapping_registry, literal_mapping_registry, opt)
+      if @request_use == :encoded
+        request_doc_enc(values, mapping_registry, opt)
+      else
+        request_doc_lit(values, literal_mapping_registry, opt)
+      end
+    end
+
+    def request_rpc_enc(values, mapping_registry, opt)
+      method = @rpc_method_factory.dup
+      names = method.input_params
+      obj = create_request_obj(names, values)
+      soap = Mapping.obj2soap(obj, mapping_registry, @rpc_request_qname, opt)
+      method.set_param(soap)
+      method
+    end
+
+    def request_rpc_lit(values, mapping_registry, opt)
+      method = @rpc_method_factory.dup
+      params = {}
+      idx = 0
+      method.input_params.each do |name|
+        params[name] = Mapping.obj2soap(values[idx], mapping_registry, 
+          XSD::QName.new(nil, name), opt)
+        idx += 1
+      end
+      method.set_param(params)
+      method
+    end
+
+    def request_doc_enc(values, mapping_registry, opt)
+      (0...values.size).collect { |idx|
+        ele = Mapping.obj2soap(values[idx], mapping_registry, nil, opt)
+        ele.elename = @doc_request_qnames[idx]
+        ele
+      }
+    end
+
+    def request_doc_lit(values, mapping_registry, opt)
+      (0...values.size).collect { |idx|
+        ele = Mapping.obj2soap(values[idx], mapping_registry,
+          @doc_request_qnames[idx], opt)
+        ele.encodingstyle = LiteralNamespace
+        if ele.respond_to?(:qualified)
+          ele.qualified = @doc_request_qualified[idx]
+        end
+        ele
+      }
+    end
+
+    def response_rpc(body, mapping_registry, literal_mapping_registry, opt)
+      if @response_use == :encoded
+        response_rpc_enc(body, mapping_registry, opt)
+      else
+        response_rpc_lit(body, literal_mapping_registry, opt)
+      end
+    end
+
+    def response_doc(body, mapping_registry, literal_mapping_registry, opt)
+      if @response_use == :encoded
+        return *response_doc_enc(body, mapping_registry, opt)
+      else
+        return *response_doc_lit(body, literal_mapping_registry, opt)
+      end
+    end
+
+    def response_rpc_enc(body, mapping_registry, opt)
+      ret = nil
+      if body.response
+        ret = Mapping.soap2obj(body.response, mapping_registry,
+          @rpc_method_factory.retval_class_name, opt)
+      end
+      if body.outparams
+        outparams = body.outparams.collect { |outparam|
+          Mapping.soap2obj(outparam, mapping_registry, nil, opt)
+        }
+        [ret].concat(outparams)
+      else
+        ret
+      end
+    end
+
+    def response_rpc_lit(body, mapping_registry, opt)
+      body.root_node.collect { |key, value|
+        Mapping.soap2obj(value, mapping_registry,
+          @rpc_method_factory.retval_class_name, opt)
+      }
+    end
+
+    def response_doc_enc(body, mapping_registry, opt)
+      body.collect { |key, value|
+        Mapping.soap2obj(value, mapping_registry, nil, opt)
+      }
+    end
+
+    def response_doc_lit(body, mapping_registry, opt)
+      body.collect { |key, value|
+        Mapping.soap2obj(value, mapping_registry)
+      }
+    end
+
+    def create_request_obj(names, params)
+      o = Object.new
+      idx = 0
+      while idx < params.length
+        o.instance_variable_set('@' + names[idx], params[idx])
+        idx += 1
+      end
+      o
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/router.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/router.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/router.rb	(revision 18425)
@@ -0,0 +1,594 @@
+# SOAP4R - RPC Routing library
+# Copyright (C) 2001, 2002, 2004, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/soap'
+require 'soap/processor'
+require 'soap/mapping'
+require 'soap/mapping/wsdlliteralregistry'
+require 'soap/rpc/rpc'
+require 'soap/rpc/element'
+require 'soap/streamHandler'
+require 'soap/mimemessage'
+require 'soap/header/handlerset'
+
+
+module SOAP
+module RPC
+
+
+class Router
+  include SOAP
+
+  attr_reader :actor
+  attr_accessor :mapping_registry
+  attr_accessor :literal_mapping_registry
+  attr_accessor :generate_explicit_type
+  attr_accessor :external_ces
+
+  def initialize(actor)
+    @actor = actor
+    @mapping_registry = nil
+    @headerhandler = Header::HandlerSet.new
+    @literal_mapping_registry = ::SOAP::Mapping::WSDLLiteralRegistry.new
+    @generate_explicit_type = true
+    @external_ces = nil
+    @operation_by_soapaction = {}
+    @operation_by_qname = {}
+    @headerhandlerfactory = []
+  end
+
+  ###
+  ## header handler interface
+  #
+  def add_request_headerhandler(factory)
+    unless factory.respond_to?(:create)
+      raise TypeError.new("factory must respond to 'create'")
+    end
+    @headerhandlerfactory << factory
+  end
+
+  def add_headerhandler(handler)
+    @headerhandler.add(handler)
+  end
+
+  ###
+  ## servant definition interface
+  #
+  def add_rpc_request_servant(factory, namespace)
+    unless factory.respond_to?(:create)
+      raise TypeError.new("factory must respond to 'create'")
+    end
+    obj = factory.create        # a dummy instance for introspection
+    ::SOAP::RPC.defined_methods(obj).each do |name|
+      begin
+        qname = XSD::QName.new(namespace, name)
+        param_def = ::SOAP::RPC::SOAPMethod.derive_rpc_param_def(obj, name)
+        opt = create_styleuse_option(:rpc, :encoded)
+        add_rpc_request_operation(factory, qname, nil, name, param_def, opt)
+      rescue SOAP::RPC::MethodDefinitionError => e
+        p e if $DEBUG
+      end
+    end
+  end
+
+  def add_rpc_servant(obj, namespace)
+    ::SOAP::RPC.defined_methods(obj).each do |name|
+      begin
+        qname = XSD::QName.new(namespace, name)
+        param_def = ::SOAP::RPC::SOAPMethod.derive_rpc_param_def(obj, name)
+        opt = create_styleuse_option(:rpc, :encoded)
+        add_rpc_operation(obj, qname, nil, name, param_def, opt)
+      rescue SOAP::RPC::MethodDefinitionError => e
+        p e if $DEBUG
+      end
+    end
+  end
+  alias add_servant add_rpc_servant
+
+  ###
+  ## operation definition interface
+  #
+  def add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {})
+    ensure_styleuse_option(opt, :rpc, :encoded)
+    opt[:request_qname] = qname
+    op = ApplicationScopeOperation.new(soapaction, receiver, name, param_def,
+      opt)
+    if opt[:request_style] != :rpc
+      raise RPCRoutingError.new("illegal request_style given")
+    end
+    assign_operation(soapaction, qname, op)
+  end
+  alias add_method add_rpc_operation
+  alias add_rpc_method add_rpc_operation
+
+  def add_rpc_request_operation(factory, qname, soapaction, name, param_def, opt = {})
+    ensure_styleuse_option(opt, :rpc, :encoded)
+    opt[:request_qname] = qname
+    op = RequestScopeOperation.new(soapaction, factory, name, param_def, opt)
+    if opt[:request_style] != :rpc
+      raise RPCRoutingError.new("illegal request_style given")
+    end
+    assign_operation(soapaction, qname, op)
+  end
+
+  def add_document_operation(receiver, soapaction, name, param_def, opt = {})
+    #
+    # adopt workaround for doc/lit wrapper method
+    # (you should consider to simply use rpc/lit service)
+    #
+    #unless soapaction
+    #  raise RPCRoutingError.new("soapaction is a must for document method")
+    #end
+    ensure_styleuse_option(opt, :document, :literal)
+    op = ApplicationScopeOperation.new(soapaction, receiver, name, param_def,
+      opt)
+    if opt[:request_style] != :document
+      raise RPCRoutingError.new("illegal request_style given")
+    end
+    assign_operation(soapaction, first_input_part_qname(param_def), op)
+  end
+  alias add_document_method add_document_operation
+
+  def add_document_request_operation(factory, soapaction, name, param_def, opt = {})
+    #
+    # adopt workaround for doc/lit wrapper method
+    # (you should consider to simply use rpc/lit service)
+    #
+    #unless soapaction
+    #  raise RPCRoutingError.new("soapaction is a must for document method")
+    #end
+    ensure_styleuse_option(opt, :document, :literal)
+    op = RequestScopeOperation.new(soapaction, receiver, name, param_def, opt)
+    if opt[:request_style] != :document
+      raise RPCRoutingError.new("illegal request_style given")
+    end
+    assign_operation(soapaction, first_input_part_qname(param_def), op)
+  end
+
+  def route(conn_data)
+    # we cannot set request_default_encodingsyle before parsing the content.
+    env = unmarshal(conn_data)
+    if env.nil?
+      raise ArgumentError.new("illegal SOAP marshal format")
+    end
+    op = lookup_operation(conn_data.soapaction, env.body)
+    headerhandler = @headerhandler.dup
+    @headerhandlerfactory.each do |f|
+      headerhandler.add(f.create)
+    end
+    receive_headers(headerhandler, env.header)
+    soap_response = default_encodingstyle = nil
+    begin
+      soap_response =
+        op.call(env.body, @mapping_registry, @literal_mapping_registry,
+          create_mapping_opt)
+      default_encodingstyle = op.response_default_encodingstyle
+    rescue Exception
+      soap_response = fault($!)
+      default_encodingstyle = nil
+    end
+    conn_data.is_fault = true if soap_response.is_a?(SOAPFault)
+    header = call_headers(headerhandler)
+    body = SOAPBody.new(soap_response)
+    env = SOAPEnvelope.new(header, body)
+    marshal(conn_data, env, default_encodingstyle)
+  end
+
+  # Create fault response string.
+  def create_fault_response(e)
+    env = SOAPEnvelope.new(SOAPHeader.new, SOAPBody.new(fault(e)))
+    opt = {}
+    opt[:external_content] = nil
+    response_string = Processor.marshal(env, opt)
+    conn_data = StreamHandler::ConnectionData.new(response_string)
+    conn_data.is_fault = true
+    if ext = opt[:external_content]
+      mimeize(conn_data, ext)
+    end
+    conn_data
+  end
+
+private
+
+  def first_input_part_qname(param_def)
+    param_def.each do |inout, paramname, typeinfo|
+      if inout == SOAPMethod::IN
+        klass, nsdef, namedef = typeinfo
+        return XSD::QName.new(nsdef, namedef)
+      end
+    end
+    nil
+  end
+
+  def create_styleuse_option(style, use)
+    opt = {}
+    opt[:request_style] = opt[:response_style] = style
+    opt[:request_use] = opt[:response_use] = use
+    opt
+  end
+
+  def ensure_styleuse_option(opt, style, use)
+    opt[:request_style] ||= style
+    opt[:response_style] ||= style
+    opt[:request_use] ||= use
+    opt[:response_use] ||= use
+  end
+
+  def assign_operation(soapaction, qname, op)
+    assigned = false
+    if soapaction and !soapaction.empty?
+      @operation_by_soapaction[soapaction] = op
+      assigned = true
+    end
+    if qname
+      @operation_by_qname[qname] = op
+      assigned = true
+    end
+    unless assigned
+      raise RPCRoutingError.new("cannot assign operation")
+    end
+  end
+
+  def lookup_operation(soapaction, body)
+    if op = @operation_by_soapaction[soapaction]
+      return op
+    end
+    qname = body.root_node.elename
+    if op = @operation_by_qname[qname]
+      return op
+    end
+    if soapaction
+      raise RPCRoutingError.new(
+        "operation: #{soapaction} #{qname} not supported")
+    else
+      raise RPCRoutingError.new("operation: #{qname} not supported")
+    end
+  end
+
+  def call_headers(headerhandler)
+    headers = headerhandler.on_outbound
+    if headers.empty?
+      nil
+    else
+      h = ::SOAP::SOAPHeader.new
+      headers.each do |header|
+        h.add(header.elename.name, header)
+      end
+      h
+    end
+  end
+
+  def receive_headers(headerhandler, headers)
+    headerhandler.on_inbound(headers) if headers
+  end
+
+  def unmarshal(conn_data)
+    opt = {}
+    contenttype = conn_data.receive_contenttype
+    if /#{MIMEMessage::MultipartContentType}/i =~ contenttype
+      opt[:external_content] = {}
+      mime = MIMEMessage.parse("Content-Type: " + contenttype,
+        conn_data.receive_string)
+      mime.parts.each do |part|
+	value = Attachment.new(part.content)
+	value.contentid = part.contentid
+	obj = SOAPAttachment.new(value)
+	opt[:external_content][value.contentid] = obj if value.contentid
+      end
+      opt[:charset] =
+	StreamHandler.parse_media_type(mime.root.headers['content-type'].str)
+      env = Processor.unmarshal(mime.root.content, opt)
+    else
+      opt[:charset] = ::SOAP::StreamHandler.parse_media_type(contenttype)
+      env = Processor.unmarshal(conn_data.receive_string, opt)
+    end
+    charset = opt[:charset]
+    conn_data.send_contenttype = "text/xml; charset=\"#{charset}\""
+    env
+  end
+
+  def marshal(conn_data, env, default_encodingstyle = nil)
+    opt = {}
+    opt[:external_content] = nil
+    opt[:default_encodingstyle] = default_encodingstyle
+    opt[:generate_explicit_type] = @generate_explicit_type
+    response_string = Processor.marshal(env, opt)
+    conn_data.send_string = response_string
+    if ext = opt[:external_content]
+      mimeize(conn_data, ext)
+    end
+    conn_data
+  end
+
+  def mimeize(conn_data, ext)
+    mime = MIMEMessage.new
+    ext.each do |k, v|
+      mime.add_attachment(v.data)
+    end
+    mime.add_part(conn_data.send_string + "\r\n")
+    mime.close
+    conn_data.send_string = mime.content_str
+    conn_data.send_contenttype = mime.headers['content-type'].str
+    conn_data
+  end
+
+  # Create fault response.
+  def fault(e)
+    detail = Mapping::SOAPException.new(e)
+    SOAPFault.new(
+      SOAPString.new('Server'),
+      SOAPString.new(e.to_s),
+      SOAPString.new(@actor),
+      Mapping.obj2soap(detail, @mapping_registry))
+  end
+
+  def create_mapping_opt
+    { :external_ces => @external_ces }
+  end
+
+  class Operation
+    attr_reader :name
+    attr_reader :soapaction
+    attr_reader :request_style
+    attr_reader :response_style
+    attr_reader :request_use
+    attr_reader :response_use
+
+    def initialize(soapaction, name, param_def, opt)
+      @soapaction = soapaction
+      @name = name
+      @request_style = opt[:request_style]
+      @response_style = opt[:response_style]
+      @request_use = opt[:request_use]
+      @response_use = opt[:response_use]
+      check_style(@request_style)
+      check_style(@response_style)
+      check_use(@request_use)
+      check_use(@response_use)
+      if @response_style == :rpc
+        request_qname = opt[:request_qname] or raise
+        @rpc_method_factory =
+          RPC::SOAPMethodRequest.new(request_qname, param_def, @soapaction)
+        @rpc_response_qname = opt[:response_qname]
+      else
+        @doc_request_qnames = []
+        @doc_request_qualified = []
+        @doc_response_qnames = []
+        @doc_response_qualified = []
+        param_def.each do |inout, paramname, typeinfo, eleinfo|
+          klass, nsdef, namedef = typeinfo
+          qualified = eleinfo
+          case inout
+          when SOAPMethod::IN
+            @doc_request_qnames << XSD::QName.new(nsdef, namedef)
+            @doc_request_qualified << qualified
+          when SOAPMethod::OUT
+            @doc_response_qnames << XSD::QName.new(nsdef, namedef)
+            @doc_response_qualified << qualified
+          else
+            raise ArgumentError.new(
+              "illegal inout definition for document style: #{inout}")
+          end
+        end
+      end
+    end
+
+    def request_default_encodingstyle
+      (@request_use == :encoded) ? EncodingNamespace : LiteralNamespace
+    end
+
+    def response_default_encodingstyle
+      (@response_use == :encoded) ? EncodingNamespace : LiteralNamespace
+    end
+
+    def call(body, mapping_registry, literal_mapping_registry, opt)
+      if @request_style == :rpc
+        values = request_rpc(body, mapping_registry, literal_mapping_registry,
+          opt)
+      else
+        values = request_document(body, mapping_registry,
+          literal_mapping_registry, opt)
+      end
+      result = receiver.method(@name.intern).call(*values)
+      return result if result.is_a?(SOAPFault)
+      if @response_style == :rpc
+        response_rpc(result, mapping_registry, literal_mapping_registry, opt)
+      else
+        response_doc(result, mapping_registry, literal_mapping_registry, opt)
+      end
+    end
+
+  private
+
+    def receiver
+      raise NotImplementedError.new('must be defined in derived class')
+    end
+
+    def request_rpc(body, mapping_registry, literal_mapping_registry, opt)
+      request = body.request
+      unless request.is_a?(SOAPStruct)
+        raise RPCRoutingError.new("not an RPC style")
+      end
+      if @request_use == :encoded
+        request_rpc_enc(request, mapping_registry, opt)
+      else
+        request_rpc_lit(request, literal_mapping_registry, opt)
+      end
+    end
+
+    def request_document(body, mapping_registry, literal_mapping_registry, opt)
+      # ToDo: compare names with @doc_request_qnames
+      if @request_use == :encoded
+        request_doc_enc(body, mapping_registry, opt)
+      else
+        request_doc_lit(body, literal_mapping_registry, opt)
+      end
+    end
+
+    def request_rpc_enc(request, mapping_registry, opt)
+      param = Mapping.soap2obj(request, mapping_registry, nil, opt)
+      request.collect { |key, value|
+        param[key]
+      }
+    end
+
+    def request_rpc_lit(request, mapping_registry, opt)
+      request.collect { |key, value|
+        Mapping.soap2obj(value, mapping_registry, nil, opt)
+      }
+    end
+
+    def request_doc_enc(body, mapping_registry, opt)
+      body.collect { |key, value|
+        Mapping.soap2obj(value, mapping_registry, nil, opt)
+      }
+    end
+
+    def request_doc_lit(body, mapping_registry, opt)
+      body.collect { |key, value|
+        Mapping.soap2obj(value, mapping_registry, nil, opt)
+      }
+    end
+
+    def response_rpc(result, mapping_registry, literal_mapping_registry, opt)
+      if @response_use == :encoded
+        response_rpc_enc(result, mapping_registry, opt)
+      else
+        response_rpc_lit(result, literal_mapping_registry, opt)
+      end
+    end
+    
+    def response_doc(result, mapping_registry, literal_mapping_registry, opt)
+      if @doc_response_qnames.size == 1 and !result.is_a?(Array)
+        result = [result]
+      end
+      if result.size != @doc_response_qnames.size
+        raise "required #{@doc_response_qnames.size} responses " +
+          "but #{result.size} given"
+      end
+      if @response_use == :encoded
+        response_doc_enc(result, mapping_registry, opt)
+      else
+        response_doc_lit(result, literal_mapping_registry, opt)
+      end
+    end
+
+    def response_rpc_enc(result, mapping_registry, opt)
+      soap_response =
+        @rpc_method_factory.create_method_response(@rpc_response_qname)
+      if soap_response.have_outparam?
+        unless result.is_a?(Array)
+          raise RPCRoutingError.new("out parameter was not returned")
+        end
+        outparams = {}
+        i = 1
+        soap_response.output_params.each do |outparam|
+          outparams[outparam] = Mapping.obj2soap(result[i], mapping_registry,
+            nil, opt)
+          i += 1
+        end
+        soap_response.set_outparam(outparams)
+        soap_response.retval = Mapping.obj2soap(result[0], mapping_registry,
+          nil, opt)
+      else
+        soap_response.retval = Mapping.obj2soap(result, mapping_registry, nil,
+          opt)
+      end
+      soap_response
+    end
+
+    def response_rpc_lit(result, mapping_registry, opt)
+      soap_response =
+        @rpc_method_factory.create_method_response(@rpc_response_qname)
+      if soap_response.have_outparam?
+        unless result.is_a?(Array)
+          raise RPCRoutingError.new("out parameter was not returned")
+        end
+        outparams = {}
+        i = 1
+        soap_response.output_params.each do |outparam|
+          outparams[outparam] = Mapping.obj2soap(result[i], mapping_registry,
+            XSD::QName.new(nil, outparam), opt)
+          i += 1
+        end
+        soap_response.set_outparam(outparams)
+        soap_response.retval = Mapping.obj2soap(result[0], mapping_registry,
+          XSD::QName.new(nil, soap_response.elename), opt)
+      else
+        soap_response.retval = Mapping.obj2soap(result, mapping_registry,
+          XSD::QName.new(nil, soap_response.elename), opt)
+      end
+      soap_response
+    end
+
+    def response_doc_enc(result, mapping_registry, opt)
+      (0...result.size).collect { |idx|
+        ele = Mapping.obj2soap(result[idx], mapping_registry, nil, opt)
+        ele.elename = @doc_response_qnames[idx]
+        ele
+      }
+    end
+
+    def response_doc_lit(result, mapping_registry, opt)
+      (0...result.size).collect { |idx|
+        ele = Mapping.obj2soap(result[idx], mapping_registry,
+          @doc_response_qnames[idx])
+        ele.encodingstyle = LiteralNamespace
+        if ele.respond_to?(:qualified)
+          ele.qualified = @doc_response_qualified[idx]
+        end
+        ele
+      }
+    end
+
+    def check_style(style)
+      unless [:rpc, :document].include?(style)
+        raise ArgumentError.new("unknown style: #{style}")
+      end
+    end
+
+    def check_use(use)
+      unless [:encoded, :literal].include?(use)
+        raise ArgumentError.new("unknown use: #{use}")
+      end
+    end
+  end
+
+  class ApplicationScopeOperation < Operation
+    def initialize(soapaction, receiver, name, param_def, opt)
+      super(soapaction, name, param_def, opt)
+      @receiver = receiver
+    end
+
+  private
+
+    def receiver
+      @receiver
+    end
+  end
+
+  class RequestScopeOperation < Operation
+    def initialize(soapaction, receiver_factory, name, param_def, opt)
+      super(soapaction, name, param_def, opt)
+      unless receiver_factory.respond_to?(:create)
+        raise TypeError.new("factory must respond to 'create'")
+      end
+      @receiver_factory = receiver_factory
+    end
+
+  private
+
+    def receiver
+      @receiver_factory.create
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/rpc.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/rpc.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/rpc.rb	(revision 18425)
@@ -0,0 +1,25 @@
+# SOAP4R - RPC utility.
+# Copyright (C) 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+module SOAP
+
+
+module RPC
+  ServerException = Mapping::MappedException
+
+  def self.defined_methods(obj)
+    if obj.is_a?(Module)
+      obj.methods - Module.methods
+    else
+      obj.methods - Object.instance_methods(true)
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/soaplet.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/soaplet.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/soaplet.rb	(revision 18425)
@@ -0,0 +1,162 @@
+# SOAP4R - SOAP handler servlet for WEBrick
+# Copyright (C) 2001-2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'webrick/httpservlet/abstract'
+require 'webrick/httpstatus'
+require 'soap/rpc/router'
+require 'soap/streamHandler'
+begin
+  require 'stringio'
+  require 'zlib'
+rescue LoadError
+  warn("Loading stringio or zlib failed.  No gzipped response supported.") if $DEBUG
+end
+
+
+warn("Overriding WEBrick::Log#debug") if $DEBUG
+require 'webrick/log'
+module WEBrick
+  class Log < BasicLog
+    alias __debug debug
+    def debug(msg = nil)
+      if block_given? and msg.nil?
+        __debug(yield)
+      else
+        __debug(msg)
+      end
+    end
+  end
+end
+
+
+module SOAP
+module RPC
+
+
+class SOAPlet < WEBrick::HTTPServlet::AbstractServlet
+public
+  attr_reader :options
+
+  def initialize(router = nil)
+    @router = router || ::SOAP::RPC::Router.new(self.class.name)
+    @options = {}
+    @config = {}
+  end
+
+  # for backward compatibility
+  def app_scope_router
+    @router
+  end
+
+  # for backward compatibility
+  def add_servant(obj, namespace)
+    @router.add_rpc_servant(obj, namespace)
+  end
+
+  def allow_content_encoding_gzip=(allow)
+    @options[:allow_content_encoding_gzip] = allow
+  end
+
+  ###
+  ## Servlet interfaces for WEBrick.
+  #
+  def get_instance(config, *options)
+    @config = config
+    self
+  end
+
+  def require_path_info?
+    false
+  end
+
+  def do_GET(req, res)
+    res.header['Allow'] = 'POST'
+    raise WEBrick::HTTPStatus::MethodNotAllowed, "GET request not allowed"
+  end
+
+  def do_POST(req, res)
+    logger.debug { "SOAP request: " + req.body } if logger
+    begin
+      conn_data = ::SOAP::StreamHandler::ConnectionData.new
+      setup_req(conn_data, req)
+      @router.external_ces = @options[:external_ces]
+      conn_data = @router.route(conn_data)
+      setup_res(conn_data, req, res)
+    rescue Exception => e
+      conn_data = @router.create_fault_response(e)
+      res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
+      res.body = conn_data.send_string
+      res['content-type'] = conn_data.send_contenttype || "text/xml"
+    end
+    if res.body.is_a?(IO)
+      res.chunked = true
+      logger.debug { "SOAP response: (chunked response not logged)" } if logger
+    else
+      logger.debug { "SOAP response: " + res.body } if logger
+    end
+  end
+
+private
+
+  def logger
+    @config[:Logger]
+  end
+
+  def setup_req(conn_data, req)
+    conn_data.receive_string = req.body
+    conn_data.receive_contenttype = req['content-type']
+    conn_data.soapaction = parse_soapaction(req.meta_vars['HTTP_SOAPACTION'])
+  end
+
+  def setup_res(conn_data, req, res)
+    res['content-type'] = conn_data.send_contenttype
+    if conn_data.is_fault
+      res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
+    end
+    if outstring = encode_gzip(req, conn_data.send_string)
+      res['content-encoding'] = 'gzip'
+      res['content-length'] = outstring.size
+      res.body = outstring
+    else
+      res.body = conn_data.send_string
+    end
+  end
+
+  def parse_soapaction(soapaction)
+    if !soapaction.nil? and !soapaction.empty?
+      if /^"(.+)"$/ =~ soapaction
+        return $1
+      end
+    end
+    nil
+  end
+
+  def encode_gzip(req, outstring)
+    unless encode_gzip?(req)
+      return nil
+    end
+    begin
+      ostream = StringIO.new
+      gz = Zlib::GzipWriter.new(ostream)
+      gz.write(outstring)
+      ostream.string
+    ensure
+      gz.close
+    end
+  end
+
+  def encode_gzip?(req)
+    @options[:allow_content_encoding_gzip] and defined?(::Zlib) and
+      req['accept-encoding'] and
+      req['accept-encoding'].split(/,\s*/).include?('gzip')
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/standaloneServer.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/standaloneServer.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/rpc/standaloneServer.rb	(revision 18425)
@@ -0,0 +1,43 @@
+# SOAP4R - WEBrick Server
+# Copyright (C) 2003 by NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/rpc/httpserver'
+
+
+module SOAP
+module RPC
+
+
+class StandaloneServer < HTTPServer
+  def initialize(appname, default_namespace, host = "0.0.0.0", port = 8080)
+    @appname = appname
+    @default_namespace = default_namespace
+    @host = host
+    @port = port
+    super(create_config)
+  end
+
+  alias add_servant add_rpc_servant
+  alias add_headerhandler add_rpc_headerhandler
+
+private
+
+  def create_config
+    {
+      :BindAddress => @host,
+      :Port => @port,
+      :AccessLog => [],
+      :SOAPDefaultNamespace => @default_namespace,
+      :SOAPHTTPServerApplicationName => @appname,
+    }
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/soap.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/soap.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/soap.rb	(revision 18425)
@@ -0,0 +1,140 @@
+# soap/soap.rb: SOAP4R - Base definitions.
+# Copyright (C) 2000-2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/qname'
+require 'xsd/charset'
+
+
+module SOAP
+
+
+VERSION = Version = '1.5.5'
+PropertyName = 'soap/property'
+
+EnvelopeNamespace = 'http://schemas.xmlsoap.org/soap/envelope/'
+EncodingNamespace = 'http://schemas.xmlsoap.org/soap/encoding/'
+LiteralNamespace = 'http://xml.apache.org/xml-soap/literalxml'
+
+NextActor = 'http://schemas.xmlsoap.org/soap/actor/next'
+
+EleEnvelope = 'Envelope'
+EleHeader = 'Header'
+EleBody = 'Body'
+EleFault = 'Fault'
+EleFaultString = 'faultstring'
+EleFaultActor = 'faultactor'
+EleFaultCode = 'faultcode'
+EleFaultDetail = 'detail'
+
+AttrMustUnderstand = 'mustUnderstand'
+AttrEncodingStyle = 'encodingStyle'
+AttrActor = 'actor'
+AttrRoot = 'root'
+AttrArrayType = 'arrayType'
+AttrOffset = 'offset'
+AttrPosition = 'position'
+ValueArray = 'Array'
+
+EleEnvelopeName = XSD::QName.new(EnvelopeNamespace, EleEnvelope).freeze
+EleHeaderName = XSD::QName.new(EnvelopeNamespace, EleHeader).freeze
+EleBodyName = XSD::QName.new(EnvelopeNamespace, EleBody).freeze
+EleFaultName = XSD::QName.new(EnvelopeNamespace, EleFault).freeze
+EleFaultStringName = XSD::QName.new(nil, EleFaultString).freeze
+EleFaultActorName = XSD::QName.new(nil, EleFaultActor).freeze
+EleFaultCodeName = XSD::QName.new(nil, EleFaultCode).freeze
+EleFaultDetailName = XSD::QName.new(nil, EleFaultDetail).freeze
+AttrMustUnderstandName = XSD::QName.new(EnvelopeNamespace, AttrMustUnderstand).freeze
+AttrEncodingStyleName = XSD::QName.new(EnvelopeNamespace, AttrEncodingStyle).freeze
+AttrRootName = XSD::QName.new(EncodingNamespace, AttrRoot).freeze
+AttrArrayTypeName = XSD::QName.new(EncodingNamespace, AttrArrayType).freeze
+AttrOffsetName = XSD::QName.new(EncodingNamespace, AttrOffset).freeze
+AttrPositionName = XSD::QName.new(EncodingNamespace, AttrPosition).freeze
+ValueArrayName = XSD::QName.new(EncodingNamespace, ValueArray).freeze
+
+Base64Literal = 'base64'
+
+SOAPNamespaceTag = 'env'
+XSDNamespaceTag = 'xsd'
+XSINamespaceTag = 'xsi'
+
+MediaType = 'text/xml'
+
+class Error < StandardError; end
+
+class StreamError < Error; end
+class HTTPStreamError < StreamError; end
+class PostUnavailableError < HTTPStreamError; end
+class MPostUnavailableError < HTTPStreamError; end
+
+class ArrayIndexOutOfBoundsError < Error; end
+class ArrayStoreError < Error; end
+
+class RPCRoutingError < Error; end
+class EmptyResponseError < Error; end
+class ResponseFormatError < Error; end
+
+class UnhandledMustUnderstandHeaderError < Error; end
+
+class FaultError < Error
+  attr_reader :faultcode
+  attr_reader :faultstring
+  attr_reader :faultactor
+  attr_accessor :detail
+
+  def initialize(fault)
+    @faultcode = fault.faultcode
+    @faultstring = fault.faultstring
+    @faultactor = fault.faultactor
+    @detail = fault.detail
+    super(self.to_s)
+  end
+
+  def to_s
+    str = nil
+    if @faultstring and @faultstring.respond_to?('data')
+      str = @faultstring.data
+    end
+    str || '(No faultstring)'
+  end
+end
+
+
+module Env
+  def self.getenv(name)
+    ENV[name.downcase] || ENV[name.upcase]
+  end
+
+  use_proxy = getenv('soap_use_proxy') == 'on'
+  HTTP_PROXY = use_proxy ? getenv('http_proxy') : nil
+  NO_PROXY = use_proxy ? getenv('no_proxy') : nil
+end
+
+
+end
+
+
+unless Object.respond_to?(:instance_variable_get)
+  class Object
+    def instance_variable_get(ivarname)
+      instance_eval(ivarname)
+    end
+
+    def instance_variable_set(ivarname, value)
+      instance_eval("#{ivarname} = value")
+    end
+  end
+end
+
+
+unless Kernel.respond_to?(:warn)
+  module Kernel
+    def warn(msg)
+      STDERR.puts(msg + "\n") unless $VERBOSE.nil?
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/streamHandler.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/streamHandler.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/streamHandler.rb	(revision 18425)
@@ -0,0 +1,229 @@
+# SOAP4R - Stream handler.
+# Copyright (C) 2000, 2001, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/soap'
+require 'soap/httpconfigloader'
+begin
+  require 'stringio'
+  require 'zlib'
+rescue LoadError
+  warn("Loading stringio or zlib failed.  No gzipped response support.") if $DEBUG
+end
+
+
+module SOAP
+
+
+class StreamHandler
+  RUBY_VERSION_STRING = "ruby #{ RUBY_VERSION } (#{ RUBY_RELEASE_DATE }) [#{ RUBY_PLATFORM }]"
+
+  class ConnectionData
+    attr_accessor :send_string
+    attr_accessor :send_contenttype
+    attr_accessor :receive_string
+    attr_accessor :receive_contenttype
+    attr_accessor :is_fault
+    attr_accessor :soapaction
+
+    def initialize(send_string = nil)
+      @send_string = send_string
+      @send_contenttype = nil
+      @receive_string = nil
+      @receive_contenttype = nil
+      @is_fault = false
+      @soapaction = nil
+    end
+  end
+
+  def self.parse_media_type(str)
+    if /^#{ MediaType }(?:\s*;\s*charset=([^"]+|"[^"]+"))?$/i !~ str
+      return nil
+    end
+    charset = $1
+    charset.gsub!(/"/, '') if charset
+    charset || 'us-ascii'
+  end
+
+  def self.create_media_type(charset)
+    "#{ MediaType }; charset=#{ charset }"
+  end
+end
+
+
+class HTTPStreamHandler < StreamHandler
+  include SOAP
+
+  begin
+    require 'http-access2'
+    if HTTPAccess2::VERSION < "2.0"
+      raise LoadError.new("http-access/2.0 or later is required.")
+    end
+    Client = HTTPAccess2::Client
+    RETRYABLE = true
+  rescue LoadError
+    warn("Loading http-access2 failed.  Net/http is used.") if $DEBUG
+    require 'soap/netHttpClient'
+    Client = SOAP::NetHttpClient
+    RETRYABLE = false
+  end
+
+
+public
+  
+  attr_reader :client
+  attr_accessor :wiredump_file_base
+  
+  MAX_RETRY_COUNT = 10       	# [times]
+
+  def initialize(options)
+    super()
+    @client = Client.new(nil, "SOAP4R/#{ Version }")
+    @wiredump_file_base = nil
+    @charset = @wiredump_dev = nil
+    @options = options
+    set_options
+    @client.debug_dev = @wiredump_dev
+    @cookie_store = nil
+    @accept_encoding_gzip = false
+  end
+
+  def test_loopback_response
+    @client.test_loopback_response
+  end
+
+  def accept_encoding_gzip=(allow)
+    @accept_encoding_gzip = allow
+  end
+
+  def inspect
+    "#<#{self.class}>"
+  end
+
+  def send(endpoint_url, conn_data, soapaction = nil, charset = @charset)
+    conn_data.soapaction ||= soapaction # for backward conpatibility
+    send_post(endpoint_url, conn_data, charset)
+  end
+
+  def reset(endpoint_url = nil)
+    if endpoint_url.nil?
+      @client.reset_all
+    else
+      @client.reset(endpoint_url)
+    end
+    @client.save_cookie_store if @cookie_store
+  end
+
+private
+
+  def set_options
+    HTTPConfigLoader.set_options(@client, @options)
+    @charset = @options["charset"] || XSD::Charset.xml_encoding_label
+    @options.add_hook("charset") do |key, value|
+      @charset = value
+    end
+    @wiredump_dev = @options["wiredump_dev"]
+    @options.add_hook("wiredump_dev") do |key, value|
+      @wiredump_dev = value
+      @client.debug_dev = @wiredump_dev
+    end
+    set_cookie_store_file(@options["cookie_store_file"])
+    @options.add_hook("cookie_store_file") do |key, value|
+      set_cookie_store_file(value)
+    end
+    ssl_config = @options["ssl_config"]
+    basic_auth = @options["basic_auth"]
+    @options.lock(true)
+    ssl_config.unlock
+    basic_auth.unlock
+  end
+
+  def set_cookie_store_file(value)
+    value = nil if value and value.empty?
+    @cookie_store = value
+    @client.set_cookie_store(@cookie_store) if @cookie_store
+  end
+
+  def send_post(endpoint_url, conn_data, charset)
+    conn_data.send_contenttype ||= StreamHandler.create_media_type(charset)
+
+    if @wiredump_file_base
+      filename = @wiredump_file_base + '_request.xml'
+      f = File.open(filename, "w")
+      f << conn_data.send_string
+      f.close
+    end
+
+    extra = {}
+    extra['Content-Type'] = conn_data.send_contenttype
+    extra['SOAPAction'] = "\"#{ conn_data.soapaction }\""
+    extra['Accept-Encoding'] = 'gzip' if send_accept_encoding_gzip?
+    send_string = conn_data.send_string
+    @wiredump_dev << "Wire dump:\n\n" if @wiredump_dev
+    begin
+      retry_count = 0
+      while true
+        res = @client.post(endpoint_url, send_string, extra)
+        if RETRYABLE and HTTP::Status.redirect?(res.status)
+          retry_count += 1
+          if retry_count >= MAX_RETRY_COUNT
+            raise HTTPStreamError.new("redirect count exceeded")
+          end
+          endpoint_url = res.header["location"][0]
+          puts "redirected to #{endpoint_url}" if $DEBUG
+        else
+          break
+        end
+      end
+    rescue
+      @client.reset(endpoint_url)
+      raise
+    end
+    @wiredump_dev << "\n\n" if @wiredump_dev
+    receive_string = res.content
+    if @wiredump_file_base
+      filename = @wiredump_file_base + '_response.xml'
+      f = File.open(filename, "w")
+      f << receive_string
+      f.close
+    end
+    case res.status
+    when 405
+      raise PostUnavailableError.new("#{ res.status }: #{ res.reason }")
+    when 200, 500
+      # Nothing to do.
+    else
+      raise HTTPStreamError.new("#{ res.status }: #{ res.reason }")
+    end
+    if res.respond_to?(:header) and !res.header['content-encoding'].empty? and
+        res.header['content-encoding'][0].downcase == 'gzip'
+      receive_string = decode_gzip(receive_string)
+    end
+    conn_data.receive_string = receive_string
+    conn_data.receive_contenttype = res.contenttype
+    conn_data
+  end
+
+  def send_accept_encoding_gzip?
+    @accept_encoding_gzip and defined?(::Zlib)
+  end
+
+  def decode_gzip(instring)
+    unless send_accept_encoding_gzip?
+      raise HTTPStreamError.new("Gzipped response content.")
+    end
+    begin
+      gz = Zlib::GzipReader.new(StringIO.new(instring))
+      gz.read
+    ensure
+      gz.close
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/wsdlDriver.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/wsdlDriver.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/soap/wsdlDriver.rb	(revision 18425)
@@ -0,0 +1,575 @@
+# SOAP4R - SOAP WSDL driver
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/parser'
+require 'wsdl/importer'
+require 'xsd/qname'
+require 'xsd/codegen/gensupport'
+require 'soap/mapping/wsdlencodedregistry'
+require 'soap/mapping/wsdlliteralregistry'
+require 'soap/rpc/driver'
+require 'wsdl/soap/methodDefCreator'
+
+
+module SOAP
+
+
+class WSDLDriverFactory
+  class FactoryError < StandardError; end
+
+  attr_reader :wsdl
+
+  def initialize(wsdl)
+    @wsdl = import(wsdl)
+    @methoddefcreator = WSDL::SOAP::MethodDefCreator.new(@wsdl)
+  end
+  
+  def inspect
+    "#<#{self.class}:#{@wsdl.name}>"
+  end
+
+  def create_rpc_driver(servicename = nil, portname = nil)
+    port = find_port(servicename, portname)
+    drv = SOAP::RPC::Driver.new(port.soap_address.location)
+    init_driver(drv, port)
+    add_operation(drv, port)
+    drv
+  end
+
+  # depricated old interface
+  def create_driver(servicename = nil, portname = nil)
+    warn("WSDLDriverFactory#create_driver is depricated.  Use create_rpc_driver instead.")
+    port = find_port(servicename, portname)
+    WSDLDriver.new(@wsdl, port, nil)
+  end
+
+  # Backward compatibility.
+  alias createDriver create_driver
+
+private
+
+  def find_port(servicename = nil, portname = nil)
+    service = port = nil
+    if servicename
+      service = @wsdl.service(
+        XSD::QName.new(@wsdl.targetnamespace, servicename))
+    else
+      service = @wsdl.services[0]
+    end
+    if service.nil?
+      raise FactoryError.new("service #{servicename} not found in WSDL")
+    end
+    if portname
+      port = service.ports[XSD::QName.new(@wsdl.targetnamespace, portname)]
+      if port.nil?
+        raise FactoryError.new("port #{portname} not found in WSDL")
+      end
+    else
+      port = service.ports.find { |port| !port.soap_address.nil? }
+      if port.nil?
+        raise FactoryError.new("no ports have soap:address")
+      end
+    end
+    if port.soap_address.nil?
+      raise FactoryError.new("soap:address element not found in WSDL")
+    end
+    port
+  end
+
+  def init_driver(drv, port)
+    wsdl_elements = @wsdl.collect_elements
+    wsdl_types = @wsdl.collect_complextypes + @wsdl.collect_simpletypes
+    rpc_decode_typemap = wsdl_types +
+      @wsdl.soap_rpc_complextypes(port.find_binding)
+    drv.proxy.mapping_registry =
+      Mapping::WSDLEncodedRegistry.new(rpc_decode_typemap)
+    drv.proxy.literal_mapping_registry =
+      Mapping::WSDLLiteralRegistry.new(wsdl_types, wsdl_elements)
+  end
+
+  def add_operation(drv, port)
+    port.find_binding.operations.each do |op_bind|
+      op_name = op_bind.soapoperation_name
+      soapaction = op_bind.soapaction || ''
+      orgname = op_name.name
+      name = XSD::CodeGen::GenSupport.safemethodname(orgname)
+      param_def = create_param_def(op_bind)
+      opt = {
+        :request_style => op_bind.soapoperation_style,
+        :response_style => op_bind.soapoperation_style,
+        :request_use => op_bind.input.soapbody_use,
+        :response_use => op_bind.output.soapbody_use,
+        :elementformdefault => false,
+        :attributeformdefault => false
+      }
+      if op_bind.soapoperation_style == :rpc
+        drv.add_rpc_operation(op_name, soapaction, name, param_def, opt)
+      else
+        drv.add_document_operation(soapaction, name, param_def, opt)
+      end
+      if orgname != name and orgname.capitalize == name.capitalize
+        ::SOAP::Mapping.define_singleton_method(drv, orgname) do |*arg|
+          __send__(name, *arg)
+        end
+      end
+    end
+  end
+
+  def import(location)
+    WSDL::Importer.import(location)
+  end
+
+  def create_param_def(op_bind)
+    op = op_bind.find_operation
+    if op_bind.soapoperation_style == :rpc
+      param_def = @methoddefcreator.collect_rpcparameter(op)
+    else
+      param_def = @methoddefcreator.collect_documentparameter(op)
+    end
+    # the first element of typedef in param_def is a String like
+    # "::SOAP::SOAPStruct".  turn this String to a class.
+    param_def.collect { |io, name, typedef|
+      typedef[0] = Mapping.class_from_name(typedef[0])
+      [io, name, typedef]
+    }
+  end
+
+  def partqname(part)
+    if part.type
+      part.type
+    else
+      part.element
+    end
+  end
+
+  def param_def(type, name, klass, partqname)
+    [type, name, [klass, partqname.namespace, partqname.name]]
+  end
+
+  def filter_parts(partsdef, partssource)
+    parts = partsdef.split(/\s+/)
+    partssource.find_all { |part| parts.include?(part.name) }
+  end
+end
+
+
+class WSDLDriver
+  class << self
+    if RUBY_VERSION >= "1.7.0"
+      def __attr_proxy(symbol, assignable = false)
+        name = symbol.to_s
+        define_method(name) {
+          @servant.__send__(name)
+        }
+        if assignable
+          aname = name + '='
+          define_method(aname) { |rhs|
+            @servant.__send__(aname, rhs)
+          }
+        end
+      end
+    else
+      def __attr_proxy(symbol, assignable = false)
+        name = symbol.to_s
+        module_eval <<-EOS
+          def #{name}
+            @servant.#{name}
+          end
+        EOS
+        if assignable
+          module_eval <<-EOS
+            def #{name}=(value)
+              @servant.#{name} = value
+            end
+          EOS
+        end
+      end
+    end
+  end
+
+  __attr_proxy :options
+  __attr_proxy :headerhandler
+  __attr_proxy :streamhandler
+  __attr_proxy :test_loopback_response
+  __attr_proxy :endpoint_url, true
+  __attr_proxy :mapping_registry, true		# for RPC unmarshal
+  __attr_proxy :wsdl_mapping_registry, true	# for RPC marshal
+  __attr_proxy :default_encodingstyle, true
+  __attr_proxy :generate_explicit_type, true
+  __attr_proxy :allow_unqualified_element, true
+
+  def httpproxy
+    @servant.options["protocol.http.proxy"]
+  end
+
+  def httpproxy=(httpproxy)
+    @servant.options["protocol.http.proxy"] = httpproxy
+  end
+
+  def wiredump_dev
+    @servant.options["protocol.http.wiredump_dev"]
+  end
+
+  def wiredump_dev=(wiredump_dev)
+    @servant.options["protocol.http.wiredump_dev"] = wiredump_dev
+  end
+
+  def mandatorycharset
+    @servant.options["protocol.mandatorycharset"]
+  end
+
+  def mandatorycharset=(mandatorycharset)
+    @servant.options["protocol.mandatorycharset"] = mandatorycharset
+  end
+
+  def wiredump_file_base
+    @servant.options["protocol.wiredump_file_base"]
+  end
+
+  def wiredump_file_base=(wiredump_file_base)
+    @servant.options["protocol.wiredump_file_base"] = wiredump_file_base
+  end
+
+  def initialize(wsdl, port, logdev)
+    @servant = Servant__.new(self, wsdl, port, logdev)
+  end
+
+  def inspect
+    "#<#{self.class}:#{@servant.port.name}>"
+  end
+
+  def reset_stream
+    @servant.reset_stream
+  end
+
+  # Backward compatibility.
+  alias generateEncodeType= generate_explicit_type=
+
+  class Servant__
+    include SOAP
+
+    attr_reader :options
+    attr_reader :port
+
+    attr_accessor :soapaction
+    attr_accessor :default_encodingstyle
+    attr_accessor :allow_unqualified_element
+    attr_accessor :generate_explicit_type
+    attr_accessor :mapping_registry
+    attr_accessor :wsdl_mapping_registry
+
+    def initialize(host, wsdl, port, logdev)
+      @host = host
+      @wsdl = wsdl
+      @port = port
+      @logdev = logdev
+      @soapaction = nil
+      @options = setup_options
+      @default_encodingstyle = nil
+      @allow_unqualified_element = nil
+      @generate_explicit_type = false
+      @mapping_registry = nil		# for rpc unmarshal
+      @wsdl_mapping_registry = nil	# for rpc marshal
+      @wiredump_file_base = nil
+      @mandatorycharset = nil
+      @wsdl_elements = @wsdl.collect_elements
+      @wsdl_types = @wsdl.collect_complextypes + @wsdl.collect_simpletypes
+      @rpc_decode_typemap = @wsdl_types +
+	@wsdl.soap_rpc_complextypes(port.find_binding)
+      @wsdl_mapping_registry = Mapping::WSDLEncodedRegistry.new(
+        @rpc_decode_typemap)
+      @doc_mapper = Mapping::WSDLLiteralRegistry.new(
+        @wsdl_types, @wsdl_elements)
+      endpoint_url = @port.soap_address.location
+      # Convert a map which key is QName, to a Hash which key is String.
+      @operation = {}
+      @port.inputoperation_map.each do |op_name, op_info|
+        orgname = op_name.name
+        name = XSD::CodeGen::GenSupport.safemethodname(orgname)
+	@operation[name] = @operation[orgname] = op_info
+	add_method_interface(op_info)
+      end
+      @proxy = ::SOAP::RPC::Proxy.new(endpoint_url, @soapaction, @options)
+    end
+
+    def inspect
+      "#<#{self.class}:#{@proxy.inspect}>"
+    end
+
+    def endpoint_url
+      @proxy.endpoint_url
+    end
+
+    def endpoint_url=(endpoint_url)
+      @proxy.endpoint_url = endpoint_url
+    end
+
+    def headerhandler
+      @proxy.headerhandler
+    end
+
+    def streamhandler
+      @proxy.streamhandler
+    end
+
+    def test_loopback_response
+      @proxy.test_loopback_response
+    end
+
+    def reset_stream
+      @proxy.reset_stream
+    end
+
+    def rpc_call(name, *values)
+      set_wiredump_file_base(name)
+      unless op_info = @operation[name]
+        raise RuntimeError, "method: #{name} not defined"
+      end
+      req_header = create_request_header
+      req_body = create_request_body(op_info, *values)
+      reqopt = create_options({
+        :soapaction => op_info.soapaction || @soapaction})
+      resopt = create_options({
+        :decode_typemap => @rpc_decode_typemap})
+      env = @proxy.route(req_header, req_body, reqopt, resopt)
+      raise EmptyResponseError unless env
+      receive_headers(env.header)
+      begin
+        @proxy.check_fault(env.body)
+      rescue ::SOAP::FaultError => e
+	Mapping.fault2exception(e)
+      end
+      ret = env.body.response ?
+	Mapping.soap2obj(env.body.response, @mapping_registry) : nil
+      if env.body.outparams
+	outparams = env.body.outparams.collect { |outparam|
+  	  Mapping.soap2obj(outparam)
+   	}
+    	return [ret].concat(outparams)
+      else
+      	return ret
+      end
+    end
+
+    # req_header: [[element, mustunderstand, encodingstyle(QName/String)], ...]
+    # req_body: SOAPBasetype/SOAPCompoundtype
+    def document_send(name, header_obj, body_obj)
+      set_wiredump_file_base(name)
+      unless op_info = @operation[name]
+        raise RuntimeError, "method: #{name} not defined"
+      end
+      req_header = header_obj ? header_from_obj(header_obj, op_info) : nil
+      req_body = body_from_obj(body_obj, op_info)
+      opt = create_options({
+        :soapaction => op_info.soapaction || @soapaction,
+        :decode_typemap => @wsdl_types})
+      env = @proxy.invoke(req_header, req_body, opt)
+      raise EmptyResponseError unless env
+      if env.body.fault
+	raise ::SOAP::FaultError.new(env.body.fault)
+      end
+      res_body_obj = env.body.response ?
+	Mapping.soap2obj(env.body.response, @mapping_registry) : nil
+      return env.header, res_body_obj
+    end
+
+  private
+
+    def create_options(hash = nil)
+      opt = {}
+      opt[:default_encodingstyle] = @default_encodingstyle
+      opt[:allow_unqualified_element] = @allow_unqualified_element
+      opt[:generate_explicit_type] = @generate_explicit_type
+      opt.update(hash) if hash
+      opt
+    end
+
+    def set_wiredump_file_base(name)
+      if @wiredump_file_base
+      	@proxy.set_wiredump_file_base(@wiredump_file_base + "_#{name}")
+      end
+    end
+
+    def create_request_header
+      headers = @proxy.headerhandler.on_outbound
+      if headers.empty?
+	nil
+      else
+	h = SOAPHeader.new
+	headers.each do |header|
+	  h.add(header.elename.name, header)
+	end
+	h
+      end
+    end
+
+    def receive_headers(headers)
+      @proxy.headerhandler.on_inbound(headers) if headers
+    end
+
+    def create_request_body(op_info, *values)
+      method = create_method_struct(op_info, *values)
+      SOAPBody.new(method)
+    end
+
+    def create_method_struct(op_info, *params)
+      parts_names = op_info.bodyparts.collect { |part| part.name }
+      obj = create_method_obj(parts_names, params)
+      method = Mapping.obj2soap(obj, @wsdl_mapping_registry, op_info.op_name)
+      if method.members.size != parts_names.size
+	new_method = SOAPStruct.new
+	method.each do |key, value|
+	  if parts_names.include?(key)
+	    new_method.add(key, value)
+	  end
+	end
+	method = new_method
+      end
+      method.elename = op_info.op_name
+      method.type = XSD::QName.new	# Request should not be typed.
+      method
+    end
+
+    def create_method_obj(names, params)
+      o = Object.new
+      idx = 0
+      while idx < params.length
+        o.instance_variable_set('@' + names[idx], params[idx])
+        idx += 1
+      end
+      o
+    end
+
+    def header_from_obj(obj, op_info)
+      if obj.is_a?(SOAPHeader)
+	obj
+      elsif op_info.headerparts.empty?
+	if obj.nil?
+	  nil
+	else
+	  raise RuntimeError.new("no header definition in schema: #{obj}")
+	end
+      elsif op_info.headerparts.size == 1
+       	part = op_info.headerparts[0]
+	header = SOAPHeader.new()
+	header.add(headeritem_from_obj(obj, part.element || part.eletype))
+	header
+      else
+	header = SOAPHeader.new()
+	op_info.headerparts.each do |part|
+	  child = Mapping.get_attribute(obj, part.name)
+	  ele = headeritem_from_obj(child, part.element || part.eletype)
+	  header.add(part.name, ele)
+	end
+	header
+      end
+    end
+
+    def headeritem_from_obj(obj, name)
+      if obj.nil?
+	SOAPElement.new(name)
+      elsif obj.is_a?(SOAPHeaderItem)
+	obj
+      else
+        Mapping.obj2soap(obj, @doc_mapper, name)
+      end
+    end
+
+    def body_from_obj(obj, op_info)
+      if obj.is_a?(SOAPBody)
+	obj
+      elsif op_info.bodyparts.empty?
+	if obj.nil?
+	  nil
+	else
+	  raise RuntimeError.new("no body found in schema")
+	end
+      elsif op_info.bodyparts.size == 1
+       	part = op_info.bodyparts[0]
+	ele = bodyitem_from_obj(obj, part.element || part.type)
+	SOAPBody.new(ele)
+      else
+	body = SOAPBody.new
+	op_info.bodyparts.each do |part|
+	  child = Mapping.get_attribute(obj, part.name)
+	  ele = bodyitem_from_obj(child, part.element || part.type)
+	  body.add(ele.elename.name, ele)
+	end
+	body
+      end
+    end
+
+    def bodyitem_from_obj(obj, name)
+      if obj.nil?
+	SOAPElement.new(name)
+      elsif obj.is_a?(SOAPElement)
+	obj
+      else
+        Mapping.obj2soap(obj, @doc_mapper, name)
+      end
+    end
+
+    def add_method_interface(op_info)
+      name = XSD::CodeGen::GenSupport.safemethodname(op_info.op_name.name)
+      orgname = op_info.op_name.name
+      parts_names = op_info.bodyparts.collect { |part| part.name }
+      case op_info.style
+      when :document
+        if orgname != name and orgname.capitalize == name.capitalize
+          add_document_method_interface(orgname, parts_names)
+        end
+	add_document_method_interface(name, parts_names)
+      when :rpc
+        if orgname != name and orgname.capitalize == name.capitalize
+          add_rpc_method_interface(orgname, parts_names)
+        end
+	add_rpc_method_interface(name, parts_names)
+      else
+	raise RuntimeError.new("unknown style: #{op_info.style}")
+      end
+    end
+
+    def add_rpc_method_interface(name, parts_names)
+      ::SOAP::Mapping.define_singleton_method(@host, name) do |*arg|
+        unless arg.size == parts_names.size
+          raise ArgumentError.new(
+            "wrong number of arguments (#{arg.size} for #{parts_names.size})")
+        end
+        @servant.rpc_call(name, *arg)
+      end
+      @host.method(name)
+    end
+
+    def add_document_method_interface(name, parts_names)
+      ::SOAP::Mapping.define_singleton_method(@host, name) do |h, b|
+        @servant.document_send(name, h, b)
+      end
+      @host.method(name)
+    end
+
+    def setup_options
+      if opt = Property.loadproperty(::SOAP::PropertyName)
+	opt = opt["client"]
+      end
+      opt ||= Property.new
+      opt.add_hook("protocol.mandatorycharset") do |key, value|
+	@mandatorycharset = value
+      end
+      opt.add_hook("protocol.wiredump_file_base") do |key, value|
+	@wiredump_file_base = value
+      end
+      opt["protocol.http.charset"] ||= XSD::Charset.xml_encoding_label
+      opt["protocol.http.proxy"] ||= Env::HTTP_PROXY
+      opt["protocol.http.no_proxy"] ||= Env::NO_PROXY
+      opt
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/sync.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/sync.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/sync.rb	(revision 18425)
@@ -0,0 +1,311 @@
+#
+#   sync.rb - 2 phase lock with counter
+#   	$Release Version: 1.0$
+#   	$Revision: 11708 $
+#   	$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+#   	by Keiju ISHITSUKA(keiju@ishitsuka.com)
+#
+# --
+#  Sync_m, Synchronizer_m
+#  Usage:
+#   obj.extend(Sync_m)
+#   or
+#   class Foo
+#	include Sync_m
+#	:
+#   end
+#
+#   Sync_m#sync_mode
+#   Sync_m#sync_locked?, locked?
+#   Sync_m#sync_shared?, shared?
+#   Sync_m#sync_exclusive?, sync_exclusive?
+#   Sync_m#sync_try_lock, try_lock
+#   Sync_m#sync_lock, lock
+#   Sync_m#sync_unlock, unlock
+#
+#   Sync, Synchronicer:
+#	include Sync_m
+#   Usage:
+#   sync = Sync.new
+#
+#   Sync#mode
+#   Sync#locked?
+#   Sync#shared?
+#   Sync#exclusive?
+#   Sync#try_lock(mode) -- mode = :EX, :SH, :UN
+#   Sync#lock(mode)     -- mode = :EX, :SH, :UN
+#   Sync#unlock
+#   Sync#synchronize(mode) {...}
+#   
+#
+
+unless defined? Thread
+  fail "Thread not available for this ruby interpreter"
+end
+
+module Sync_m
+  RCS_ID='-$Header$-'
+  
+  # lock mode
+  UN = :UN
+  SH = :SH
+  EX = :EX
+  
+  # exceptions
+  class Err < StandardError
+    def Err.Fail(*opt)
+      fail self, sprintf(self::Message, *opt)
+    end
+    
+    class UnknownLocker < Err
+      Message = "Thread(%s) not locked."
+      def UnknownLocker.Fail(th)
+	super(th.inspect)
+      end
+    end
+    
+    class LockModeFailer < Err
+      Message = "Unknown lock mode(%s)"
+      def LockModeFailer.Fail(mode)
+	if mode.id2name
+	  mode = id2name
+	end
+	super(mode)
+      end
+    end
+  end
+  
+  def Sync_m.define_aliases(cl)
+    cl.module_eval %q{
+      alias locked? sync_locked?
+      alias shared? sync_shared?
+      alias exclusive? sync_exclusive?
+      alias lock sync_lock
+      alias unlock sync_unlock
+      alias try_lock sync_try_lock
+      alias synchronize sync_synchronize
+    }
+  end
+  
+  def Sync_m.append_features(cl)
+    super
+    unless cl.instance_of?(Module)
+      # do nothing for Modules
+      # make aliases and include the proper module.
+      define_aliases(cl)
+    end
+  end
+  
+  def Sync_m.extend_object(obj)
+    super
+    obj.sync_extended
+  end
+
+  def sync_extended
+    unless (defined? locked? and
+	    defined? shared? and
+	    defined? exclusive? and
+	    defined? lock and
+	    defined? unlock and
+	    defined? try_lock and
+	    defined? synchronize)
+      Sync_m.define_aliases(class<<self;self;end)
+    end
+    sync_initialize
+  end
+
+  # accessing
+  def sync_locked?
+    sync_mode != UN
+  end
+  
+  def sync_shared?
+    sync_mode == SH
+  end
+  
+  def sync_exclusive?
+    sync_mode == EX
+  end
+  
+  # locking methods.
+  def sync_try_lock(mode = EX)
+    return unlock if sync_mode == UN
+    
+    Thread.critical = true
+    ret = sync_try_lock_sub(sync_mode)
+    Thread.critical = false
+    ret
+  end
+  
+  def sync_lock(m = EX)
+    return unlock if m == UN
+
+    until (Thread.critical = true; sync_try_lock_sub(m))
+      if sync_sh_locker[Thread.current]
+	sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]]
+	sync_sh_locker.delete(Thread.current)
+      else
+	sync_waiting.push Thread.current
+      end
+      Thread.stop
+    end
+    Thread.critical = false
+    self
+  end
+  
+  def sync_unlock(m = EX)
+    Thread.critical = true
+    if sync_mode == UN
+      Thread.critical = false
+      Err::UnknownLocker.Fail(Thread.current)
+    end
+    
+    m = sync_mode if m == EX and sync_mode == SH
+    
+    runnable = false
+    case m
+    when UN
+      Thread.critical = false
+      Err::UnknownLocker.Fail(Thread.current)
+      
+    when EX
+      if sync_ex_locker == Thread.current
+	if (self.sync_ex_count = sync_ex_count - 1) == 0
+	  self.sync_ex_locker = nil
+	  if sync_sh_locker.include?(Thread.current)
+	    self.sync_mode = SH
+	  else
+	    self.sync_mode = UN
+	  end
+	  runnable = true
+	end
+      else
+	Err::UnknownLocker.Fail(Thread.current)
+      end
+      
+    when SH
+      if (count = sync_sh_locker[Thread.current]).nil?
+	Err::UnknownLocker.Fail(Thread.current)
+      else
+	if (sync_sh_locker[Thread.current] = count - 1) == 0 
+	  sync_sh_locker.delete(Thread.current)
+	  if sync_sh_locker.empty? and sync_ex_count == 0
+	    self.sync_mode = UN
+	    runnable = true
+	  end
+	end
+      end
+    end
+    
+    if runnable
+      if sync_upgrade_waiting.size > 0
+	for k, v in sync_upgrade_waiting
+	  sync_sh_locker[k] = v
+	end
+	wait = sync_upgrade_waiting
+	self.sync_upgrade_waiting = []
+	Thread.critical = false
+	
+	for w, v in wait
+	  w.run
+	end
+      else
+	wait = sync_waiting
+	self.sync_waiting = []
+	Thread.critical = false
+	for w in wait
+	  w.run
+	end
+      end
+    end
+    
+    Thread.critical = false
+    self
+  end
+  
+  def sync_synchronize(mode = EX)
+    begin
+      sync_lock(mode)
+      yield
+    ensure
+      sync_unlock
+    end
+  end
+
+  attr :sync_mode, true
+    
+  attr :sync_waiting, true
+  attr :sync_upgrade_waiting, true
+  attr :sync_sh_locker, true
+  attr :sync_ex_locker, true
+  attr :sync_ex_count, true
+    
+  private
+
+  def sync_initialize
+    @sync_mode = UN
+    @sync_waiting = []
+    @sync_upgrade_waiting = []
+    @sync_sh_locker = Hash.new
+    @sync_ex_locker = nil
+    @sync_ex_count = 0
+  end
+
+  def initialize(*args)
+    sync_initialize
+    super
+  end
+    
+  def sync_try_lock_sub(m)
+    case m
+    when SH
+      case sync_mode
+      when UN
+	self.sync_mode = m
+	sync_sh_locker[Thread.current] = 1
+	ret = true
+      when SH
+	count = 0 unless count = sync_sh_locker[Thread.current]
+	sync_sh_locker[Thread.current] = count + 1
+	ret = true
+      when EX
+	# in EX mode, lock will upgrade to EX lock
+	if sync_ex_locker == Thread.current
+	  self.sync_ex_count = sync_ex_count + 1
+	  ret = true
+	else
+	  ret = false
+	end
+      end
+    when EX
+      if sync_mode == UN or
+	sync_mode == SH && sync_sh_locker.size == 1 && sync_sh_locker.include?(Thread.current) 
+	self.sync_mode = m
+	self.sync_ex_locker = Thread.current
+	self.sync_ex_count = 1
+	ret = true
+      elsif sync_mode == EX && sync_ex_locker == Thread.current
+	self.sync_ex_count = sync_ex_count + 1
+	ret = true
+      else
+	ret = false
+      end
+    else
+      Thread.critical = false
+      Err::LockModeFailer.Fail mode
+    end
+    return ret
+  end
+end
+Synchronizer_m = Sync_m
+
+class Sync
+  #Sync_m.extend_class self
+  include Sync_m
+    
+  def initialize
+    super
+  end
+    
+end
+Synchronizer = Sync
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tempfile.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tempfile.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tempfile.rb	(revision 18425)
@@ -0,0 +1,193 @@
+#
+# tempfile - manipulates temporary files
+#
+# $Id: tempfile.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+
+require 'delegate'
+require 'tmpdir'
+
+# A class for managing temporary files.  This library is written to be
+# thread safe.
+class Tempfile < DelegateClass(File)
+  MAX_TRY = 10
+  @@cleanlist = []
+
+  # Creates a temporary file of mode 0600 in the temporary directory
+  # whose name is basename.pid.n and opens with mode "w+".  A Tempfile
+  # object works just like a File object.
+  #
+  # If tmpdir is omitted, the temporary directory is determined by
+  # Dir::tmpdir provided by 'tmpdir.rb'.
+  # When $SAFE > 0 and the given tmpdir is tainted, it uses
+  # /tmp. (Note that ENV values are tainted by default)
+  def initialize(basename, tmpdir=Dir::tmpdir)
+    if $SAFE > 0 and tmpdir.tainted?
+      tmpdir = '/tmp'
+    end
+
+    lock = nil
+    n = failure = 0
+    
+    begin
+      Thread.critical = true
+
+      begin
+	tmpname = File.join(tmpdir, make_tmpname(basename, n))
+	lock = tmpname + '.lock'
+	n += 1
+      end while @@cleanlist.include?(tmpname) or
+	File.exist?(lock) or File.exist?(tmpname)
+
+      Dir.mkdir(lock)
+    rescue
+      failure += 1
+      retry if failure < MAX_TRY
+      raise "cannot generate tempfile `%s'" % tmpname
+    ensure
+      Thread.critical = false
+    end
+
+    @data = [tmpname]
+    @clean_proc = Tempfile.callback(@data)
+    ObjectSpace.define_finalizer(self, @clean_proc)
+
+    @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)
+    @tmpname = tmpname
+    @@cleanlist << @tmpname
+    @data[1] = @tmpfile
+    @data[2] = @@cleanlist
+
+    super(@tmpfile)
+
+    # Now we have all the File/IO methods defined, you must not
+    # carelessly put bare puts(), etc. after this.
+
+    Dir.rmdir(lock)
+  end
+
+  def make_tmpname(basename, n)
+    sprintf('%s.%d.%d', basename, $$, n)
+  end
+  private :make_tmpname
+
+  # Opens or reopens the file with mode "r+".
+  def open
+    @tmpfile.close if @tmpfile
+    @tmpfile = File.open(@tmpname, 'r+')
+    @data[1] = @tmpfile
+    __setobj__(@tmpfile)
+  end
+
+  def _close	# :nodoc:
+    @tmpfile.close if @tmpfile
+    @data[1] = @tmpfile = nil
+  end    
+  protected :_close
+
+  # Closes the file.  If the optional flag is true, unlinks the file
+  # after closing.
+  #
+  # If you don't explicitly unlink the temporary file, the removal
+  # will be delayed until the object is finalized.
+  def close(unlink_now=false)
+    if unlink_now
+      close!
+    else
+      _close
+    end
+  end
+
+  # Closes and unlinks the file.
+  def close!
+    _close
+    @clean_proc.call
+    ObjectSpace.undefine_finalizer(self)
+  end
+
+  # Unlinks the file.  On UNIX-like systems, it is often a good idea
+  # to unlink a temporary file immediately after creating and opening
+  # it, because it leaves other programs zero chance to access the
+  # file.
+  def unlink
+    # keep this order for thread safeness
+    begin
+      File.unlink(@tmpname) if File.exist?(@tmpname)
+      @@cleanlist.delete(@tmpname)
+      @data = @tmpname = nil
+      ObjectSpace.undefine_finalizer(self)
+    rescue Errno::EACCES
+      # may not be able to unlink on Windows; just ignore
+    end
+  end
+  alias delete unlink
+
+  # Returns the full path name of the temporary file.
+  def path
+    @tmpname
+  end
+
+  # Returns the size of the temporary file.  As a side effect, the IO
+  # buffer is flushed before determining the size.
+  def size
+    if @tmpfile
+      @tmpfile.flush
+      @tmpfile.stat.size
+    else
+      0
+    end
+  end
+  alias length size
+
+  class << self
+    def callback(data)	# :nodoc:
+      pid = $$
+      lambda{
+	if pid == $$ 
+	  path, tmpfile, cleanlist = *data
+
+	  print "removing ", path, "..." if $DEBUG
+
+	  tmpfile.close if tmpfile
+
+	  # keep this order for thread safeness
+	  File.unlink(path) if File.exist?(path)
+	  cleanlist.delete(path) if cleanlist
+
+	  print "done\n" if $DEBUG
+	end
+      }
+    end
+
+    # If no block is given, this is a synonym for new().
+    #
+    # If a block is given, it will be passed tempfile as an argument,
+    # and the tempfile will automatically be closed when the block
+    # terminates.  In this case, open() returns nil.
+    def open(*args)
+      tempfile = new(*args)
+
+      if block_given?
+	begin
+	  yield(tempfile)
+	ensure
+	  tempfile.close
+	end
+
+	nil
+      else
+	tempfile
+      end
+    end
+  end
+end
+
+if __FILE__ == $0
+#  $DEBUG = true
+  f = Tempfile.new("foo")
+  f.print("foo\n")
+  f.close
+  f.open
+  p f.gets # => "foo\n"
+  f.close!
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit.rb	(revision 18425)
@@ -0,0 +1,280 @@
+require 'test/unit/testcase'
+require 'test/unit/autorunner'
+
+module Test # :nodoc:
+  #
+  # = Test::Unit - Ruby Unit Testing Framework
+  # 
+  # == Introduction
+  # 
+  # Unit testing is making waves all over the place, largely due to the
+  # fact that it is a core practice of XP. While XP is great, unit testing
+  # has been around for a long time and has always been a good idea. One
+  # of the keys to good unit testing, though, is not just writing tests,
+  # but having tests. What's the difference? Well, if you just _write_ a
+  # test and throw it away, you have no guarantee that something won't
+  # change later which breaks your code. If, on the other hand, you _have_
+  # tests (obviously you have to write them first), and run them as often
+  # as possible, you slowly build up a wall of things that cannot break
+  # without you immediately knowing about it. This is when unit testing
+  # hits its peak usefulness.
+  # 
+  # Enter Test::Unit, a framework for unit testing in Ruby, helping you to
+  # design, debug and evaluate your code by making it easy to write and
+  # have tests for it.
+  # 
+  # 
+  # == Notes
+  # 
+  # Test::Unit has grown out of and superceded Lapidary.
+  # 
+  # 
+  # == Feedback
+  # 
+  # I like (and do my best to practice) XP, so I value early releases,
+  # user feedback, and clean, simple, expressive code. There is always
+  # room for improvement in everything I do, and Test::Unit is no
+  # exception. Please, let me know what you think of Test::Unit as it
+  # stands, and what you'd like to see expanded/changed/improved/etc. If
+  # you find a bug, let me know ASAP; one good way to let me know what the
+  # bug is is to submit a new test that catches it :-) Also, I'd love to
+  # hear about any successes you have with Test::Unit, and any
+  # documentation you might add will be greatly appreciated. My contact
+  # info is below.
+  # 
+  # 
+  # == Contact Information
+  # 
+  # A lot of discussion happens about Ruby in general on the ruby-talk
+  # mailing list (http://www.ruby-lang.org/en/ml.html), and you can ask
+  # any questions you might have there. I monitor the list, as do many
+  # other helpful Rubyists, and you're sure to get a quick answer. Of
+  # course, you're also welcome to email me (Nathaniel Talbott) directly
+  # at mailto:testunit@talbott.ws, and I'll do my best to help you out.
+  # 
+  # 
+  # == Credits
+  # 
+  # I'd like to thank...
+  # 
+  # Matz, for a great language!
+  # 
+  # Masaki Suketa, for his work on RubyUnit, which filled a vital need in
+  # the Ruby world for a very long time. I'm also grateful for his help in
+  # polishing Test::Unit and getting the RubyUnit compatibility layer
+  # right. His graciousness in allowing Test::Unit to supercede RubyUnit
+  # continues to be a challenge to me to be more willing to defer my own
+  # rights.
+  # 
+  # Ken McKinlay, for his interest and work on unit testing, and for his
+  # willingness to dialog about it. He was also a great help in pointing
+  # out some of the holes in the RubyUnit compatibility layer.
+  # 
+  # Dave Thomas, for the original idea that led to the extremely simple
+  # "require 'test/unit'", plus his code to improve it even more by
+  # allowing the selection of tests from the command-line. Also, without
+  # RDoc, the documentation for Test::Unit would stink a lot more than it
+  # does now.
+  # 
+  # Everyone who's helped out with bug reports, feature ideas,
+  # encouragement to continue, etc. It's a real privilege to be a part of
+  # the Ruby community.
+  # 
+  # The guys at RoleModel Software, for putting up with me repeating, "But
+  # this would be so much easier in Ruby!" whenever we're coding in Java.
+  # 
+  # My Creator, for giving me life, and giving it more abundantly.
+  # 
+  # 
+  # == License
+  # 
+  # Test::Unit is copyright (c) 2000-2003 Nathaniel Talbott. It is free
+  # software, and is distributed under the Ruby license. See the COPYING
+  # file in the standard Ruby distribution for details.
+  # 
+  # 
+  # == Warranty
+  # 
+  # This software is provided "as is" and without any express or
+  # implied warranties, including, without limitation, the implied
+  # warranties of merchantibility and fitness for a particular
+  # purpose.
+  # 
+  # 
+  # == Author
+  # 
+  # Nathaniel Talbott.
+  # Copyright (c) 2000-2003, Nathaniel Talbott
+  #
+  # ----
+  #
+  # = Usage
+  #
+  # The general idea behind unit testing is that you write a _test_
+  # _method_ that makes certain _assertions_ about your code, working
+  # against a _test_ _fixture_. A bunch of these _test_ _methods_ are
+  # bundled up into a _test_ _suite_ and can be run any time the
+  # developer wants. The results of a run are gathered in a _test_
+  # _result_ and displayed to the user through some UI. So, lets break
+  # this down and see how Test::Unit provides each of these necessary
+  # pieces.
+  #
+  #
+  # == Assertions
+  #
+  # These are the heart of the framework. Think of an assertion as a
+  # statement of expected outcome, i.e. "I assert that x should be equal
+  # to y". If, when the assertion is executed, it turns out to be
+  # correct, nothing happens, and life is good. If, on the other hand,
+  # your assertion turns out to be false, an error is propagated with
+  # pertinent information so that you can go back and make your
+  # assertion succeed, and, once again, life is good. For an explanation
+  # of the current assertions, see Test::Unit::Assertions.
+  #
+  #
+  # == Test Method & Test Fixture
+  #
+  # Obviously, these assertions have to be called within a context that
+  # knows about them and can do something meaningful with their
+  # pass/fail value. Also, it's handy to collect a bunch of related
+  # tests, each test represented by a method, into a common test class
+  # that knows how to run them. The tests will be in a separate class
+  # from the code they're testing for a couple of reasons. First of all,
+  # it allows your code to stay uncluttered with test code, making it
+  # easier to maintain. Second, it allows the tests to be stripped out
+  # for deployment, since they're really there for you, the developer,
+  # and your users don't need them. Third, and most importantly, it
+  # allows you to set up a common test fixture for your tests to run
+  # against.
+  #
+  # What's a test fixture? Well, tests do not live in a vacuum; rather,
+  # they're run against the code they are testing. Often, a collection
+  # of tests will run against a common set of data, also called a
+  # fixture. If they're all bundled into the same test class, they can
+  # all share the setting up and tearing down of that data, eliminating
+  # unnecessary duplication and making it much easier to add related
+  # tests.
+  #
+  # Test::Unit::TestCase wraps up a collection of test methods together
+  # and allows you to easily set up and tear down the same test fixture
+  # for each test. This is done by overriding #setup and/or #teardown,
+  # which will be called before and after each test method that is
+  # run. The TestCase also knows how to collect the results of your
+  # assertions into a Test::Unit::TestResult, which can then be reported
+  # back to you... but I'm getting ahead of myself. To write a test,
+  # follow these steps:
+  #
+  # * Make sure Test::Unit is in your library path.
+  # * require 'test/unit' in your test script.
+  # * Create a class that subclasses Test::Unit::TestCase.
+  # * Add a method that begins with "test" to your class.
+  # * Make assertions in your test method.
+  # * Optionally define #setup and/or #teardown to set up and/or tear
+  #   down your common test fixture.
+  # * You can now run your test as you would any other Ruby
+  #   script... try it and see!
+  #
+  # A really simple test might look like this (#setup and #teardown are
+  # commented out to indicate that they are completely optional):
+  #
+  #     require 'test/unit'
+  #     
+  #     class TC_MyTest < Test::Unit::TestCase
+  #       # def setup
+  #       # end
+  #     
+  #       # def teardown
+  #       # end
+  #     
+  #       def test_fail
+  #         assert(false, 'Assertion was false.')
+  #       end
+  #     end
+  #
+  #
+  # == Test Runners
+  #
+  # So, now you have this great test class, but you still need a way to
+  # run it and view any failures that occur during the run. This is
+  # where Test::Unit::UI::Console::TestRunner (and others, such as
+  # Test::Unit::UI::GTK::TestRunner) comes into play. The console test
+  # runner is automatically invoked for you if you require 'test/unit'
+  # and simply run the file. To use another runner, or to manually
+  # invoke a runner, simply call its run class method and pass in an
+  # object that responds to the suite message with a
+  # Test::Unit::TestSuite. This can be as simple as passing in your
+  # TestCase class (which has a class suite method). It might look
+  # something like this:
+  #
+  #    require 'test/unit/ui/console/testrunner'
+  #    Test::Unit::UI::Console::TestRunner.run(TC_MyTest)
+  #
+  #
+  # == Test Suite
+  #
+  # As more and more unit tests accumulate for a given project, it
+  # becomes a real drag running them one at a time, and it also
+  # introduces the potential to overlook a failing test because you
+  # forget to run it. Suddenly it becomes very handy that the
+  # TestRunners can take any object that returns a Test::Unit::TestSuite
+  # in response to a suite method. The TestSuite can, in turn, contain
+  # other TestSuites or individual tests (typically created by a
+  # TestCase). In other words, you can easily wrap up a group of
+  # TestCases and TestSuites like this:
+  #
+  #  require 'test/unit/testsuite'
+  #  require 'tc_myfirsttests'
+  #  require 'tc_moretestsbyme'
+  #  require 'ts_anothersetoftests'
+  #
+  #  class TS_MyTests
+  #    def self.suite
+  #      suite = Test::Unit::TestSuite.new
+  #      suite << TC_MyFirstTests.suite
+  #      suite << TC_MoreTestsByMe.suite
+  #      suite << TS_AnotherSetOfTests.suite
+  #      return suite
+  #    end
+  #  end
+  #  Test::Unit::UI::Console::TestRunner.run(TS_MyTests)
+  #
+  # Now, this is a bit cumbersome, so Test::Unit does a little bit more
+  # for you, by wrapping these up automatically when you require
+  # 'test/unit'. What does this mean? It means you could write the above
+  # test case like this instead:
+  #
+  #  require 'test/unit'
+  #  require 'tc_myfirsttests'
+  #  require 'tc_moretestsbyme'
+  #  require 'ts_anothersetoftests'
+  #
+  # Test::Unit is smart enough to find all the test cases existing in
+  # the ObjectSpace and wrap them up into a suite for you. It then runs
+  # the dynamic suite using the console TestRunner.
+  #
+  #
+  # == Questions?
+  #
+  # I'd really like to get feedback from all levels of Ruby
+  # practitioners about typos, grammatical errors, unclear statements,
+  # missing points, etc., in this document (or any other).
+  #
+
+  module Unit
+    # If set to false Test::Unit will not automatically run at exit.
+    def self.run=(flag)
+      @run = flag
+    end
+
+    # Automatically run tests at exit?
+    def self.run?
+      @run ||= false
+    end
+  end
+end
+
+at_exit do
+  unless $! || Test::Unit.run?
+    exit Test::Unit::AutoRunner.run
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/assertionfailederror.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/assertionfailederror.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/assertionfailederror.rb	(revision 18425)
@@ -0,0 +1,14 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+module Test
+  module Unit
+
+    # Thrown by Test::Unit::Assertions when an assertion fails.
+    class AssertionFailedError < StandardError
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/assertions.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/assertions.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/assertions.rb	(revision 18425)
@@ -0,0 +1,622 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/assertionfailederror'
+require 'test/unit/util/backtracefilter'
+
+module Test
+  module Unit
+
+    ##
+    # Test::Unit::Assertions contains the standard Test::Unit assertions.
+    # Assertions is included in Test::Unit::TestCase.
+    #
+    # To include it in your own code and use its functionality, you simply
+    # need to rescue Test::Unit::AssertionFailedError. Additionally you may
+    # override add_assertion to get notified whenever an assertion is made.
+    #
+    # Notes:
+    # * The message to each assertion, if given, will be propagated with the
+    #   failure.
+    # * It is easy to add your own assertions based on assert_block().
+    #
+    # = Example Custom Assertion
+    #
+    #   def deny(boolean, message = nil)
+    #     message = build_message message, '<?> is not false or nil.', boolean
+    #     assert_block message do
+    #       not boolean
+    #     end
+    #   end
+
+    module Assertions
+
+      ##
+      # The assertion upon which all other assertions are based. Passes if the
+      # block yields true.
+      #
+      # Example:
+      #   assert_block "Couldn't do the thing" do
+      #     do_the_thing
+      #   end
+
+      public
+      def assert_block(message="assert_block failed.") # :yields: 
+        _wrap_assertion do
+          if (! yield)
+            raise AssertionFailedError.new(message.to_s)
+          end
+        end
+      end
+
+      ##
+      # Asserts that +boolean+ is not false or nil.
+      #
+      # Example:
+      #   assert [1, 2].include?(5)
+
+      public
+      def assert(boolean, message=nil)
+        _wrap_assertion do
+          assert_block("assert should not be called with a block.") { !block_given? }
+          assert_block(build_message(message, "<?> is not true.", boolean)) { boolean }
+        end
+      end
+
+      ##
+      # Passes if +expected+ == +actual.
+      #
+      # Note that the ordering of arguments is important, since a helpful
+      # error message is generated when this one fails that tells you the
+      # values of expected and actual.
+      #
+      # Example:
+      #   assert_equal 'MY STRING', 'my string'.upcase
+
+      public
+      def assert_equal(expected, actual, message=nil)
+        full_message = build_message(message, <<EOT, expected, actual)
+<?> expected but was
+<?>.
+EOT
+        assert_block(full_message) { expected == actual }
+      end
+
+      private
+      def _check_exception_class(args) # :nodoc:
+        args.partition do |klass|
+          next if klass.instance_of?(Module)
+          assert(Exception >= klass, "Should expect a class of exception, #{klass}")
+          true
+        end
+      end
+
+      private
+      def _expected_exception?(actual_exception, exceptions, modules) # :nodoc:
+        exceptions.include?(actual_exception.class) or
+          modules.any? {|mod| actual_exception.is_a?(mod)}
+      end
+
+      ##
+      # Passes if the block raises one of the given exceptions.
+      #
+      # Example:
+      #   assert_raise RuntimeError, LoadError do
+      #     raise 'Boom!!!'
+      #   end
+
+      public
+      def assert_raise(*args)
+        _wrap_assertion do
+          if Module === args.last
+            message = ""
+          else
+            message = args.pop
+          end
+          exceptions, modules = _check_exception_class(args)
+          expected = args.size == 1 ? args.first : args
+          actual_exception = nil
+          full_message = build_message(message, "<?> exception expected but none was thrown.", expected)
+          assert_block(full_message) do
+            begin
+              yield
+            rescue Exception => actual_exception
+              break
+            end
+            false
+          end
+          full_message = build_message(message, "<?> exception expected but was\n?", expected, actual_exception)
+          assert_block(full_message) {_expected_exception?(actual_exception, exceptions, modules)}
+          actual_exception
+        end
+      end
+
+      ##
+      # Alias of assert_raise.
+      #
+      # Will be deprecated in 1.9, and removed in 2.0.
+
+      public
+      def assert_raises(*args, &block)
+        assert_raise(*args, &block)
+      end
+
+      ##
+      # Passes if +object+ .instance_of? +klass+
+      #
+      # Example:
+      #   assert_instance_of String, 'foo'
+
+      public
+      def assert_instance_of(klass, object, message="")
+        _wrap_assertion do
+          assert_equal(Class, klass.class, "assert_instance_of takes a Class as its first argument")
+          full_message = build_message(message, <<EOT, object, klass, object.class)
+<?> expected to be an instance of
+<?> but was
+<?>.
+EOT
+          assert_block(full_message){object.instance_of?(klass)}
+        end
+      end
+
+      ##
+      # Passes if +object+ is nil.
+      #
+      # Example:
+      #   assert_nil [1, 2].uniq!
+
+      public
+      def assert_nil(object, message="")
+        assert_equal(nil, object, message)
+      end
+
+      ##
+      # Passes if +object+ .kind_of? +klass+
+      #
+      # Example:
+      #   assert_kind_of Object, 'foo'
+
+      public
+      def assert_kind_of(klass, object, message="")
+        _wrap_assertion do
+          assert(klass.kind_of?(Module), "The first parameter to assert_kind_of should be a kind_of Module.")
+          full_message = build_message(message, "<?>\nexpected to be kind_of\\?\n<?> but was\n<?>.", object, klass, object.class)
+          assert_block(full_message){object.kind_of?(klass)}
+        end
+      end
+
+      ##
+      # Passes if +object+ .respond_to? +method+
+      #
+      # Example:
+      #   assert_respond_to 'bugbear', :slice
+
+      public
+      def assert_respond_to(object, method, message="")
+        _wrap_assertion do
+          full_message = build_message(nil, "<?>\ngiven as the method name argument to #assert_respond_to must be a Symbol or #respond_to\\?(:to_str).", method)
+
+          assert_block(full_message) do
+            method.kind_of?(Symbol) || method.respond_to?(:to_str)
+          end
+          full_message = build_message(message, <<EOT, object, object.class, method)
+<?>
+of type <?>
+expected to respond_to\\?<?>.
+EOT
+          assert_block(full_message) { object.respond_to?(method) }
+        end
+      end
+
+      ##
+      # Passes if +string+ =~ +pattern+.
+      #
+      # Example:
+      #   assert_match(/\d+/, 'five, 6, seven')
+
+      public
+      def assert_match(pattern, string, message="")
+        _wrap_assertion do
+          pattern = case(pattern)
+            when String
+              Regexp.new(Regexp.escape(pattern))
+            else
+              pattern
+          end
+          full_message = build_message(message, "<?> expected to be =~\n<?>.", string, pattern)
+          assert_block(full_message) { string =~ pattern }
+        end
+      end
+
+      ##
+      # Passes if +actual+ .equal? +expected+ (i.e. they are the same
+      # instance).
+      #
+      # Example:
+      #   o = Object.new
+      #   assert_same o, o
+
+      public
+      def assert_same(expected, actual, message="")
+        full_message = build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__)
+<?>
+with id <?> expected to be equal\\? to
+<?>
+with id <?>.
+EOT
+        assert_block(full_message) { actual.equal?(expected) }
+      end
+
+      ##
+      # Compares the +object1+ with +object2+ using +operator+.
+      #
+      # Passes if object1.__send__(operator, object2) is true.
+      #
+      # Example:
+      #   assert_operator 5, :>=, 4
+
+      public
+      def assert_operator(object1, operator, object2, message="")
+        _wrap_assertion do
+          full_message = build_message(nil, "<?>\ngiven as the operator for #assert_operator must be a Symbol or #respond_to\\?(:to_str).", operator)
+          assert_block(full_message){operator.kind_of?(Symbol) || operator.respond_to?(:to_str)}
+          full_message = build_message(message, <<EOT, object1, AssertionMessage.literal(operator), object2)
+<?> expected to be
+?
+<?>.
+EOT
+          assert_block(full_message) { object1.__send__(operator, object2) }
+        end
+      end
+
+      ##
+      # Passes if block does not raise an exception.
+      #
+      # Example:
+      #   assert_nothing_raised do
+      #     [1, 2].uniq
+      #   end
+
+      public
+      def assert_nothing_raised(*args)
+        _wrap_assertion do
+          if Module === args.last
+            message = ""
+          else
+            message = args.pop
+          end
+          exceptions, modules = _check_exception_class(args)
+          begin
+            yield
+          rescue Exception => e
+            if ((args.empty? && !e.instance_of?(AssertionFailedError)) ||
+                _expected_exception?(e, exceptions, modules))
+              assert_block(build_message(message, "Exception raised:\n?", e)){false}
+            else
+              raise
+            end
+          end
+          nil
+        end
+      end
+
+      ##
+      # Flunk always fails.
+      #
+      # Example:
+      #   flunk 'Not done testing yet.'
+
+      public
+      def flunk(message="Flunked")
+        assert_block(build_message(message)){false}
+      end
+
+      ##
+      # Passes if ! +actual+ .equal? +expected+
+      #
+      # Example:
+      #   assert_not_same Object.new, Object.new
+
+      public
+      def assert_not_same(expected, actual, message="")
+        full_message = build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__)
+<?>
+with id <?> expected to not be equal\\? to
+<?>
+with id <?>.
+EOT
+        assert_block(full_message) { !actual.equal?(expected) }
+      end
+
+      ##
+      # Passes if +expected+ != +actual+
+      #
+      # Example:
+      #   assert_not_equal 'some string', 5
+
+      public
+      def assert_not_equal(expected, actual, message="")
+        full_message = build_message(message, "<?> expected to be != to\n<?>.", expected, actual)
+        assert_block(full_message) { expected != actual }
+      end
+
+      ##
+      # Passes if ! +object+ .nil?
+      #
+      # Example:
+      #   assert_not_nil '1 two 3'.sub!(/two/, '2')
+
+      public
+      def assert_not_nil(object, message="")
+        full_message = build_message(message, "<?> expected to not be nil.", object)
+        assert_block(full_message){!object.nil?}
+      end
+
+      ##
+      # Passes if +regexp+ !~ +string+ 
+      #
+      # Example:
+      #   assert_no_match(/two/, 'one 2 three')
+
+      public
+      def assert_no_match(regexp, string, message="")
+        _wrap_assertion do
+          assert_instance_of(Regexp, regexp, "The first argument to assert_no_match should be a Regexp.")
+          full_message = build_message(message, "<?> expected to not match\n<?>.", regexp, string)
+          assert_block(full_message) { regexp !~ string }
+        end
+      end
+
+      UncaughtThrow = {NameError => /^uncaught throw \`(.+)\'$/,
+                       ThreadError => /^uncaught throw \`(.+)\' in thread /} #`
+
+      ##
+      # Passes if the block throws +expected_symbol+
+      #
+      # Example:
+      #   assert_throws :done do
+      #     throw :done
+      #   end
+
+      public
+      def assert_throws(expected_symbol, message="", &proc)
+        _wrap_assertion do
+          assert_instance_of(Symbol, expected_symbol, "assert_throws expects the symbol that should be thrown for its first argument")
+          assert_block("Should have passed a block to assert_throws."){block_given?}
+          caught = true
+          begin
+            catch(expected_symbol) do
+              proc.call
+              caught = false
+            end
+            full_message = build_message(message, "<?> should have been thrown.", expected_symbol)
+            assert_block(full_message){caught}
+          rescue NameError, ThreadError => error
+            if UncaughtThrow[error.class] !~ error.message
+              raise error
+            end
+            full_message = build_message(message, "<?> expected to be thrown but\n<?> was thrown.", expected_symbol, $1.intern)
+            flunk(full_message)
+          end
+        end
+      end
+
+      ##
+      # Passes if block does not throw anything.
+      #
+      # Example:
+      #  assert_nothing_thrown do
+      #    [1, 2].uniq
+      #  end
+
+      public
+      def assert_nothing_thrown(message="", &proc)
+        _wrap_assertion do
+          assert(block_given?, "Should have passed a block to assert_nothing_thrown")
+          begin
+            proc.call
+          rescue NameError, ThreadError => error
+            if UncaughtThrow[error.class] !~ error.message
+              raise error
+            end
+            full_message = build_message(message, "<?> was thrown when nothing was expected", $1.intern)
+            flunk(full_message)
+          end
+          assert(true, "Expected nothing to be thrown")
+        end
+      end
+
+      ##
+      # Passes if +expected_float+ and +actual_float+ are equal
+      # within +delta+ tolerance.
+      #
+      # Example:
+      #   assert_in_delta 0.05, (50000.0 / 10**6), 0.00001
+
+      public
+      def assert_in_delta(expected_float, actual_float, delta, message="")
+        _wrap_assertion do
+          {expected_float => "first float", actual_float => "second float", delta => "delta"}.each do |float, name|
+            assert_respond_to(float, :to_f, "The arguments must respond to to_f; the #{name} did not")
+          end
+          assert_operator(delta, :>=, 0.0, "The delta should not be negative")
+          full_message = build_message(message, <<EOT, expected_float, actual_float, delta)
+<?> and
+<?> expected to be within
+<?> of each other.
+EOT
+          assert_block(full_message) { (expected_float.to_f - actual_float.to_f).abs <= delta.to_f }
+        end
+      end
+
+      ##
+      # Passes if the method send returns a true value.
+      #
+      # +send_array+ is composed of:
+      # * A receiver
+      # * A method
+      # * Arguments to the method
+      #
+      # Example:
+      #   assert_send [[1, 2], :include?, 4]
+
+      public
+      def assert_send(send_array, message="")
+        _wrap_assertion do
+          assert_instance_of(Array, send_array, "assert_send requires an array of send information")
+          assert(send_array.size >= 2, "assert_send requires at least a receiver and a message name")
+          full_message = build_message(message, <<EOT, send_array[0], AssertionMessage.literal(send_array[1].to_s), send_array[2..-1])
+<?> expected to respond to
+<?(?)> with a true value.
+EOT
+          assert_block(full_message) { send_array[0].__send__(send_array[1], *send_array[2..-1]) }
+        end
+      end
+
+      ##
+      # Builds a failure message.  +head+ is added before the +template+ and
+      # +arguments+ replaces the '?'s positionally in the template.
+
+      public
+      def build_message(head, template=nil, *arguments)
+        template &&= template.chomp
+        return AssertionMessage.new(head, template, arguments)
+      end
+
+      private
+      def _wrap_assertion
+        @_assertion_wrapped ||= false
+        unless (@_assertion_wrapped)
+          @_assertion_wrapped = true
+          begin
+            add_assertion
+            return yield
+          ensure
+            @_assertion_wrapped = false
+          end
+        else
+          return yield
+        end
+      end
+      
+      ##
+      # Called whenever an assertion is made.  Define this in classes that
+      # include Test::Unit::Assertions to record assertion counts.
+
+      private
+      def add_assertion
+      end
+
+      ##
+      # Select whether or not to use the pretty-printer. If this option is set
+      # to false before any assertions are made, pp.rb will not be required.
+
+      public
+      def self.use_pp=(value)
+        AssertionMessage.use_pp = value
+      end
+      
+      # :stopdoc:
+
+      class AssertionMessage
+        @use_pp = true
+        class << self
+          attr_accessor :use_pp
+        end
+
+        class Literal
+          def initialize(value)
+            @value = value
+          end
+          
+          def inspect
+            @value.to_s
+          end
+        end
+
+        class Template
+          def self.create(string)
+            parts = (string ? string.scan(/(?=[^\\])\?|(?:\\\?|[^\?])+/m) : [])
+            self.new(parts)
+          end
+
+          attr_reader :count
+
+          def initialize(parts)
+            @parts = parts
+            @count = parts.find_all{|e| e == '?'}.size
+          end
+
+          def result(parameters)
+            raise "The number of parameters does not match the number of substitutions." if(parameters.size != count)
+            params = parameters.dup
+            @parts.collect{|e| e == '?' ? params.shift : e.gsub(/\\\?/m, '?')}.join('')
+          end
+        end
+
+        def self.literal(value)
+          Literal.new(value)
+        end
+
+        include Util::BacktraceFilter
+
+        def initialize(head, template_string, parameters)
+          @head = head
+          @template_string = template_string
+          @parameters = parameters
+        end
+
+        def convert(object)
+          case object
+            when Exception
+              <<EOM.chop
+Class: <#{convert(object.class)}>
+Message: <#{convert(object.message)}>
+---Backtrace---
+#{filter_backtrace(object.backtrace).join("\n")}
+---------------
+EOM
+            else
+              if(self.class.use_pp)
+                begin
+                  require 'pp'
+                rescue LoadError
+                  self.class.use_pp = false
+                  return object.inspect
+                end unless(defined?(PP))
+                PP.pp(object, '').chomp
+              else
+                object.inspect
+              end
+          end
+        end
+
+        def template
+          @template ||= Template.create(@template_string)
+        end
+
+        def add_period(string)
+          (string =~ /\.\Z/ ? string : string + '.')
+        end
+
+        def to_s
+          message_parts = []
+          if (@head)
+            head = @head.to_s 
+            unless(head.empty?)
+              message_parts << add_period(head)
+            end
+          end
+          tail = template.result(@parameters.collect{|e| convert(e)})
+          message_parts << tail unless(tail.empty?)
+          message_parts.join("\n")
+        end
+      end
+
+      # :startdoc:
+
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/autorunner.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/autorunner.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/autorunner.rb	(revision 18425)
@@ -0,0 +1,220 @@
+require 'test/unit'
+require 'test/unit/ui/testrunnerutilities'
+require 'optparse'
+
+module Test
+  module Unit
+    class AutoRunner
+      def self.run(force_standalone=false, default_dir=nil, argv=ARGV, &block)
+        r = new(force_standalone || standalone?, &block)
+        r.base = default_dir
+        r.process_args(argv)
+        r.run
+      end
+      
+      def self.standalone?
+        return false unless("-e" == $0)
+        ObjectSpace.each_object(Class) do |klass|
+          return false if(klass < TestCase)
+        end
+        true
+      end
+
+      RUNNERS = {
+        :console => proc do |r|
+          require 'test/unit/ui/console/testrunner'
+          Test::Unit::UI::Console::TestRunner
+        end,
+        :gtk => proc do |r|
+          require 'test/unit/ui/gtk/testrunner'
+          Test::Unit::UI::GTK::TestRunner
+        end,
+        :gtk2 => proc do |r|
+          require 'test/unit/ui/gtk2/testrunner'
+          Test::Unit::UI::GTK2::TestRunner
+        end,
+        :fox => proc do |r|
+          require 'test/unit/ui/fox/testrunner'
+          Test::Unit::UI::Fox::TestRunner
+        end,
+        :tk => proc do |r|
+          require 'test/unit/ui/tk/testrunner'
+          Test::Unit::UI::Tk::TestRunner
+        end,
+      }
+
+      OUTPUT_LEVELS = [
+        [:silent, UI::SILENT],
+        [:progress, UI::PROGRESS_ONLY],
+        [:normal, UI::NORMAL],
+        [:verbose, UI::VERBOSE],
+      ]
+
+      COLLECTORS = {
+        :objectspace => proc do |r|
+          require 'test/unit/collector/objectspace'
+          c = Collector::ObjectSpace.new
+          c.filter = r.filters
+          c.collect($0.sub(/\.rb\Z/, ''))
+        end,
+        :dir => proc do |r|
+          require 'test/unit/collector/dir'
+          c = Collector::Dir.new
+          c.filter = r.filters
+          c.pattern.concat(r.pattern) if(r.pattern)
+          c.exclude.concat(r.exclude) if(r.exclude)
+          c.base = r.base
+          $:.push(r.base) if r.base
+          c.collect(*(r.to_run.empty? ? ['.'] : r.to_run))
+        end,
+      }
+
+      attr_reader :suite
+      attr_accessor :output_level, :filters, :to_run, :pattern, :exclude, :base, :workdir
+      attr_writer :runner, :collector
+
+      def initialize(standalone)
+        Unit.run = true
+        @standalone = standalone
+        @runner = RUNNERS[:console]
+        @collector = COLLECTORS[(standalone ? :dir : :objectspace)]
+        @filters = []
+        @to_run = []
+        @output_level = UI::NORMAL
+        @workdir = nil
+        yield(self) if(block_given?)
+      end
+
+      def process_args(args = ARGV)
+        begin
+          options.order!(args) {|arg| @to_run << arg}
+        rescue OptionParser::ParseError => e
+          puts e
+          puts options
+          $! = nil
+          abort
+        else
+          @filters << proc{false} unless(@filters.empty?)
+        end
+        not @to_run.empty?
+      end
+
+      def options
+        @options ||= OptionParser.new do |o|
+          o.banner = "Test::Unit automatic runner."
+          o.banner << "\nUsage: #{$0} [options] [-- untouched arguments]"
+
+          o.on
+          o.on('-r', '--runner=RUNNER', RUNNERS,
+               "Use the given RUNNER.",
+               "(" + keyword_display(RUNNERS) + ")") do |r|
+            @runner = r
+          end
+
+          if(@standalone)
+            o.on('-b', '--basedir=DIR', "Base directory of test suites.") do |b|
+              @base = b
+            end
+
+            o.on('-w', '--workdir=DIR', "Working directory to run tests.") do |w|
+              @workdir = w
+            end
+
+            o.on('-a', '--add=TORUN', Array,
+                 "Add TORUN to the list of things to run;",
+                 "can be a file or a directory.") do |a|
+              @to_run.concat(a)
+            end
+
+            @pattern = []
+            o.on('-p', '--pattern=PATTERN', Regexp,
+                 "Match files to collect against PATTERN.") do |e|
+              @pattern << e
+            end
+
+            @exclude = []
+            o.on('-x', '--exclude=PATTERN', Regexp,
+                 "Ignore files to collect against PATTERN.") do |e|
+              @exclude << e
+            end
+          end
+
+          o.on('-n', '--name=NAME', String,
+               "Runs tests matching NAME.",
+               "(patterns may be used).") do |n|
+            n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
+            case n
+            when Regexp
+              @filters << proc{|t| n =~ t.method_name ? true : nil}
+            else
+              @filters << proc{|t| n == t.method_name ? true : nil}
+            end
+          end
+
+          o.on('-t', '--testcase=TESTCASE', String,
+               "Runs tests in TestCases matching TESTCASE.",
+               "(patterns may be used).") do |n|
+            n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
+            case n
+            when Regexp
+              @filters << proc{|t| n =~ t.class.name ? true : nil}
+            else
+              @filters << proc{|t| n == t.class.name ? true : nil}
+            end
+          end
+
+          o.on('-I', "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]",
+               "Appends directory list to $LOAD_PATH.") do |dirs|
+            $LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
+          end
+
+          o.on('-v', '--verbose=[LEVEL]', OUTPUT_LEVELS,
+               "Set the output level (default is verbose).",
+               "(" + keyword_display(OUTPUT_LEVELS) + ")") do |l|
+            @output_level = l || UI::VERBOSE
+          end
+
+          o.on('--',
+               "Stop processing options so that the",
+               "remaining options will be passed to the",
+               "test."){o.terminate}
+
+          o.on('-h', '--help', 'Display this help.'){puts o; exit}
+
+          o.on_tail
+          o.on_tail('Deprecated options:')
+
+          o.on_tail('--console', 'Console runner (use --runner).') do
+            warn("Deprecated option (--console).")
+            @runner = RUNNERS[:console]
+          end
+
+          o.on_tail('--gtk', 'GTK runner (use --runner).') do
+            warn("Deprecated option (--gtk).")
+            @runner = RUNNERS[:gtk]
+          end
+
+          o.on_tail('--fox', 'Fox runner (use --runner).') do
+            warn("Deprecated option (--fox).")
+            @runner = RUNNERS[:fox]
+          end
+
+          o.on_tail
+        end
+      end
+
+      def keyword_display(array)
+        list = array.collect {|e, *| e.to_s}
+        Array === array or list.sort!
+        list.collect {|e| e.sub(/^(.)([A-Za-z]+)(?=\w*$)/, '\\1[\\2]')}.join(", ")
+      end
+
+      def run
+        @suite = @collector[self]
+        result = @runner[self] or return false
+        Dir.chdir(@workdir) if @workdir
+        result.run(@suite, @output_level).passed?
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/collector.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/collector.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/collector.rb	(revision 18425)
@@ -0,0 +1,43 @@
+module Test
+  module Unit
+    module Collector
+      def initialize
+        @filters = []
+      end
+
+      def filter=(filters)
+        @filters = case(filters)
+          when Proc
+            [filters]
+          when Array
+            filters
+        end
+      end
+
+      def add_suite(destination, suite)
+        to_delete = suite.tests.find_all{|t| !include?(t)}
+        to_delete.each{|t| suite.delete(t)}
+        destination << suite unless(suite.size == 0)
+      end
+
+      def include?(test)
+        return true if(@filters.empty?)
+        @filters.each do |filter|
+          result = filter[test]
+          if(result.nil?)
+            next
+          elsif(!result)
+            return false
+          else
+            return true
+          end
+        end
+        true
+      end
+
+      def sort(suites)
+        suites.sort_by{|s| s.name}
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/collector/dir.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/collector/dir.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/collector/dir.rb	(revision 18425)
@@ -0,0 +1,107 @@
+require 'test/unit/testsuite'
+require 'test/unit/collector'
+
+module Test
+  module Unit
+    module Collector
+      class Dir
+        include Collector
+
+        attr_reader :pattern, :exclude
+        attr_accessor :base
+
+        def initialize(dir=::Dir, file=::File, object_space=::ObjectSpace, req=nil)
+          super()
+          @dir = dir
+          @file = file
+          @object_space = object_space
+          @req = req
+          @pattern = [/\btest_.*\.rb\Z/m]
+          @exclude = []
+        end
+
+        def collect(*from)
+          basedir = @base
+          $:.push(basedir) if basedir
+          if(from.empty?)
+            recursive_collect('.', find_test_cases)
+          elsif(from.size == 1)
+            recursive_collect(from.first, find_test_cases)
+          else
+            suites = []
+            from.each do |f|
+              suite = recursive_collect(f, find_test_cases)
+              suites << suite unless(suite.tests.empty?)
+            end
+            suite = TestSuite.new("[#{from.join(', ')}]")
+            sort(suites).each{|s| suite << s}
+            suite
+          end
+        ensure
+          $:.delete_at($:.rindex(basedir)) if basedir
+        end
+
+        def find_test_cases(ignore=[])
+          cases = []
+          @object_space.each_object(Class) do |c|
+            cases << c if(c < TestCase && !ignore.include?(c))
+          end
+          ignore.concat(cases)
+          cases
+        end
+
+        def recursive_collect(name, already_gathered)
+          sub_suites = []
+          path = realdir(name)
+          if @file.directory?(path)
+	    dir_name = name unless name == '.'
+            @dir.entries(path).each do |e|
+              next if(e == '.' || e == '..')
+              e_name = dir_name ? @file.join(dir_name, e) : e
+              if @file.directory?(realdir(e_name))
+                next if /\ACVS\z/ =~ e
+                sub_suite = recursive_collect(e_name, already_gathered)
+                sub_suites << sub_suite unless(sub_suite.empty?)
+              else
+                next if /~\z/ =~ e_name or /\A\.\#/ =~ e
+                if @pattern and !@pattern.empty?
+                  next unless @pattern.any? {|pat| pat =~ e_name}
+                end
+                if @exclude and !@exclude.empty?
+                  next if @exclude.any? {|pat| pat =~ e_name}
+                end
+                collect_file(e_name, sub_suites, already_gathered)
+              end
+            end
+          else
+            collect_file(name, sub_suites, already_gathered)
+          end
+          suite = TestSuite.new(@file.basename(name))
+          sort(sub_suites).each{|s| suite << s}
+          suite
+        end
+
+        def collect_file(name, suites, already_gathered)
+          dir = @file.dirname(@file.expand_path(name, @base))
+          $:.unshift(dir)
+          if(@req)
+            @req.require(name)
+          else
+            require(name)
+          end
+          find_test_cases(already_gathered).each{|t| add_suite(suites, t.suite)}
+        ensure
+          $:.delete_at($:.rindex(dir)) if(dir)
+        end
+
+	def realdir(path)
+	  if @base
+	    @file.join(@base, path)
+	  else
+	    path
+	  end
+	end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/collector/objectspace.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/collector/objectspace.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/collector/objectspace.rb	(revision 18425)
@@ -0,0 +1,34 @@
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/collector'
+
+module Test
+  module Unit
+    module Collector
+      class ObjectSpace
+        include Collector
+        
+        NAME = 'collected from the ObjectSpace'
+        
+        def initialize(source=::ObjectSpace)
+          super()
+          @source = source
+        end
+        
+        def collect(name=NAME)
+          suite = TestSuite.new(name)
+          sub_suites = []
+          @source.each_object(Class) do |klass|
+            if(Test::Unit::TestCase > klass)
+              add_suite(sub_suites, klass.suite)
+            end
+          end
+          sort(sub_suites).each{|s| suite << s}
+          suite
+        end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/error.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/error.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/error.rb	(revision 18425)
@@ -0,0 +1,56 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/util/backtracefilter'
+
+module Test
+  module Unit
+
+    # Encapsulates an error in a test. Created by
+    # Test::Unit::TestCase when it rescues an exception thrown
+    # during the processing of a test.
+    class Error
+      include Util::BacktraceFilter
+
+      attr_reader(:test_name, :exception)
+
+      SINGLE_CHARACTER = 'E'
+
+      # Creates a new Error with the given test_name and
+      # exception.
+      def initialize(test_name, exception)
+        @test_name = test_name
+        @exception = exception
+      end
+
+      # Returns a single character representation of an error.
+      def single_character_display
+        SINGLE_CHARACTER
+      end
+
+      # Returns the message associated with the error.
+      def message
+        "#{@exception.class.name}: #{@exception.message}"
+      end
+
+      # Returns a brief version of the error description.
+      def short_display
+        "#@test_name: #{message.split("\n")[0]}"
+      end
+
+      # Returns a verbose version of the error description.
+      def long_display
+        backtrace = filter_backtrace(@exception.backtrace).join("\n    ")
+        "Error:\n#@test_name:\n#{message}\n    #{backtrace}"
+      end
+
+      # Overridden to return long_display.
+      def to_s
+        long_display
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/failure.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/failure.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/failure.rb	(revision 18425)
@@ -0,0 +1,51 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+module Test
+  module Unit
+
+    # Encapsulates a test failure. Created by Test::Unit::TestCase
+    # when an assertion fails.
+    class Failure
+      attr_reader :test_name, :location, :message
+      
+      SINGLE_CHARACTER = 'F'
+
+      # Creates a new Failure with the given location and
+      # message.
+      def initialize(test_name, location, message)
+        @test_name = test_name
+        @location = location
+        @message = message
+      end
+      
+      # Returns a single character representation of a failure.
+      def single_character_display
+        SINGLE_CHARACTER
+      end
+
+      # Returns a brief version of the error description.
+      def short_display
+        "#@test_name: #{@message.split("\n")[0]}"
+      end
+
+      # Returns a verbose version of the error description.
+      def long_display
+        location_display = if(location.size == 1)
+          location[0].sub(/\A(.+:\d+).*/, ' [\\1]')
+        else
+          "\n    [#{location.join("\n     ")}]"
+        end
+        "Failure:\n#@test_name#{location_display}:\n#@message"
+      end
+
+      # Overridden to return long_display.
+      def to_s
+        long_display
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/testcase.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/testcase.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/testcase.rb	(revision 18425)
@@ -0,0 +1,160 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/assertions'
+require 'test/unit/failure'
+require 'test/unit/error'
+require 'test/unit/testsuite'
+require 'test/unit/assertionfailederror'
+require 'test/unit/util/backtracefilter'
+
+module Test
+  module Unit
+
+    # Ties everything together. If you subclass and add your own
+    # test methods, it takes care of making them into tests and
+    # wrapping those tests into a suite. It also does the
+    # nitty-gritty of actually running an individual test and
+    # collecting its results into a Test::Unit::TestResult object.
+    class TestCase
+      include Assertions
+      include Util::BacktraceFilter
+      
+      attr_reader :method_name
+      
+      STARTED = name + "::STARTED"
+      FINISHED = name + "::FINISHED"
+
+      ##
+      # These exceptions are not caught by #run.
+
+      PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, Interrupt,
+                                SystemExit]
+
+      # Creates a new instance of the fixture for running the
+      # test represented by test_method_name.
+      def initialize(test_method_name)
+        unless(respond_to?(test_method_name) and
+               (method(test_method_name).arity == 0 ||
+                method(test_method_name).arity == -1))
+          throw :invalid_test
+        end
+        @method_name = test_method_name
+        @test_passed = true
+      end
+
+      # Rolls up all of the test* methods in the fixture into
+      # one suite, creating a new instance of the fixture for
+      # each method.
+      def self.suite
+        method_names = public_instance_methods(true)
+        tests = method_names.delete_if {|method_name| method_name !~ /^test./}
+        suite = TestSuite.new(name)
+        tests.sort.each do
+          |test|
+          catch(:invalid_test) do
+            suite << new(test)
+          end
+        end
+        if (suite.empty?)
+          catch(:invalid_test) do
+            suite << new("default_test")
+          end
+        end
+        return suite
+      end
+
+      # Runs the individual test method represented by this
+      # instance of the fixture, collecting statistics, failures
+      # and errors in result.
+      def run(result)
+        yield(STARTED, name)
+        @_result = result
+        begin
+          setup
+          __send__(@method_name)
+        rescue AssertionFailedError => e
+          add_failure(e.message, e.backtrace)
+        rescue Exception
+          raise if PASSTHROUGH_EXCEPTIONS.include? $!.class
+          add_error($!)
+        ensure
+          begin
+            teardown
+          rescue AssertionFailedError => e
+            add_failure(e.message, e.backtrace)
+          rescue Exception
+            raise if PASSTHROUGH_EXCEPTIONS.include? $!.class
+            add_error($!)
+          end
+        end
+        result.add_run
+        yield(FINISHED, name)
+      end
+
+      # Called before every test method runs. Can be used
+      # to set up fixture information.
+      def setup
+      end
+
+      # Called after every test method runs. Can be used to tear
+      # down fixture information.
+      def teardown
+      end
+      
+      def default_test
+        flunk("No tests were specified")
+      end
+
+      # Returns whether this individual test passed or
+      # not. Primarily for use in teardown so that artifacts
+      # can be left behind if the test fails.
+      def passed?
+        return @test_passed
+      end
+      private :passed?
+
+      def size
+        1
+      end
+
+      def add_assertion
+        @_result.add_assertion
+      end
+      private :add_assertion
+
+      def add_failure(message, all_locations=caller())
+        @test_passed = false
+        @_result.add_failure(Failure.new(name, filter_backtrace(all_locations), message))
+      end
+      private :add_failure
+
+      def add_error(exception)
+        @test_passed = false
+        @_result.add_error(Error.new(name, exception))
+      end
+      private :add_error
+
+      # Returns a human-readable name for the specific test that
+      # this instance of TestCase represents.
+      def name
+        "#{@method_name}(#{self.class.name})"
+      end
+
+      # Overridden to return #name.
+      def to_s
+        name
+      end
+      
+      # It's handy to be able to compare TestCase instances.
+      def ==(other)
+        return false unless(other.kind_of?(self.class))
+        return false unless(@method_name == other.method_name)
+        self.class == other.class
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/testresult.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/testresult.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/testresult.rb	(revision 18425)
@@ -0,0 +1,80 @@
+#--
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/util/observable'
+
+module Test
+  module Unit
+
+    # Collects Test::Unit::Failure and Test::Unit::Error so that
+    # they can be displayed to the user. To this end, observers
+    # can be added to it, allowing the dynamic updating of, say, a
+    # UI.
+    class TestResult
+      include Util::Observable
+
+      CHANGED = "CHANGED"
+      FAULT = "FAULT"
+
+      attr_reader(:run_count, :assertion_count)
+
+      # Constructs a new, empty TestResult.
+      def initialize
+        @run_count, @assertion_count = 0, 0
+        @failures, @errors = Array.new, Array.new
+      end
+
+      # Records a test run.
+      def add_run
+        @run_count += 1
+        notify_listeners(CHANGED, self)
+      end
+
+      # Records a Test::Unit::Failure.
+      def add_failure(failure)
+        @failures << failure
+        notify_listeners(FAULT, failure)
+        notify_listeners(CHANGED, self)
+      end
+
+      # Records a Test::Unit::Error.
+      def add_error(error)
+        @errors << error
+        notify_listeners(FAULT, error)
+        notify_listeners(CHANGED, self)
+      end
+
+      # Records an individual assertion.
+      def add_assertion
+        @assertion_count += 1
+        notify_listeners(CHANGED, self)
+      end
+
+      # Returns a string contain the recorded runs, assertions,
+      # failures and errors in this TestResult.
+      def to_s
+        "#{run_count} tests, #{assertion_count} assertions, #{failure_count} failures, #{error_count} errors"
+      end
+
+      # Returns whether or not this TestResult represents
+      # successful completion.
+      def passed?
+        return @failures.empty? && @errors.empty?
+      end
+
+      # Returns the number of failures this TestResult has
+      # recorded.
+      def failure_count
+        return @failures.size
+      end
+
+      # Returns the number of errors this TestResult has
+      # recorded.
+      def error_count
+        return @errors.size
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/testsuite.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/testsuite.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/testsuite.rb	(revision 18425)
@@ -0,0 +1,76 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+module Test
+  module Unit
+
+    # A collection of tests which can be #run.
+    #
+    # Note: It is easy to confuse a TestSuite instance with
+    # something that has a static suite method; I know because _I_
+    # have trouble keeping them straight. Think of something that
+    # has a suite method as simply providing a way to get a
+    # meaningful TestSuite instance.
+    class TestSuite
+      attr_reader :name, :tests
+      
+      STARTED = name + "::STARTED"
+      FINISHED = name + "::FINISHED"
+
+      # Creates a new TestSuite with the given name.
+      def initialize(name="Unnamed TestSuite")
+        @name = name
+        @tests = []
+      end
+
+      # Runs the tests and/or suites contained in this
+      # TestSuite.
+      def run(result, &progress_block)
+        yield(STARTED, name)
+        @tests.each do |test|
+          test.run(result, &progress_block)
+        end
+        yield(FINISHED, name)
+      end
+
+      # Adds the test to the suite.
+      def <<(test)
+        @tests << test
+        self
+      end
+
+      def delete(test)
+        @tests.delete(test)
+      end
+
+      # Retuns the rolled up number of tests in this suite;
+      # i.e. if the suite contains other suites, it counts the
+      # tests within those suites, not the suites themselves.
+      def size
+        total_size = 0
+        @tests.each { |test| total_size += test.size }
+        total_size
+      end
+      
+      def empty?
+        tests.empty?
+      end
+
+      # Overridden to return the name given the suite at
+      # creation.
+      def to_s
+        @name
+      end
+      
+      # It's handy to be able to compare TestSuite instances.
+      def ==(other)
+        return false unless(other.kind_of?(self.class))
+        return false unless(@name == other.name)
+        @tests == other.tests
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/console/testrunner.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/console/testrunner.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/console/testrunner.rb	(revision 18425)
@@ -0,0 +1,127 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/ui/testrunnermediator'
+require 'test/unit/ui/testrunnerutilities'
+
+module Test
+  module Unit
+    module UI
+      module Console
+
+        # Runs a Test::Unit::TestSuite on the console.
+        class TestRunner
+          extend TestRunnerUtilities
+
+          # Creates a new TestRunner for running the passed
+          # suite. If quiet_mode is true, the output while
+          # running is limited to progress dots, errors and
+          # failures, and the final result. io specifies
+          # where runner output should go to; defaults to
+          # STDOUT.
+          def initialize(suite, output_level=NORMAL, io=STDOUT)
+            if (suite.respond_to?(:suite))
+              @suite = suite.suite
+            else
+              @suite = suite
+            end
+            @output_level = output_level
+            @io = io
+            @already_outputted = false
+            @faults = []
+          end
+
+          # Begins the test run.
+          def start
+            setup_mediator
+            attach_to_mediator
+            return start_mediator
+          end
+
+          private
+          def setup_mediator
+            @mediator = create_mediator(@suite)
+            suite_name = @suite.to_s
+            if ( @suite.kind_of?(Module) )
+              suite_name = @suite.name
+            end
+            output("Loaded suite #{suite_name}")
+          end
+          
+          def create_mediator(suite)
+            return TestRunnerMediator.new(suite)
+          end
+          
+          def attach_to_mediator
+            @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
+            @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
+            @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
+            @mediator.add_listener(TestCase::STARTED, &method(:test_started))
+            @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
+          end
+          
+          def start_mediator
+            return @mediator.run_suite
+          end
+          
+          def add_fault(fault)
+            @faults << fault
+            output_single(fault.single_character_display, PROGRESS_ONLY)
+            @already_outputted = true
+          end
+          
+          def started(result)
+            @result = result
+            output("Started")
+          end
+          
+          def finished(elapsed_time)
+            nl
+            output("Finished in #{elapsed_time} seconds.")
+            @faults.each_with_index do |fault, index|
+              nl
+              output("%3d) %s" % [index + 1, fault.long_display])
+            end
+            nl
+            output(@result)
+          end
+          
+          def test_started(name)
+            output_single(name + ": ", VERBOSE)
+          end
+          
+          def test_finished(name)
+            output_single(".", PROGRESS_ONLY) unless (@already_outputted)
+            nl(VERBOSE)
+            @already_outputted = false
+          end
+          
+          def nl(level=NORMAL)
+            output("", level)
+          end
+          
+          def output(something, level=NORMAL)
+            @io.puts(something) if (output?(level))
+            @io.flush
+          end
+          
+          def output_single(something, level=NORMAL)
+            @io.write(something) if (output?(level))
+            @io.flush
+          end
+          
+          def output?(level)
+            level <= @output_level
+          end
+        end
+      end
+    end
+  end
+end
+
+if __FILE__ == $0
+  Test::Unit::UI::Console::TestRunner.start_command_line_test
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/fox/testrunner.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/fox/testrunner.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/fox/testrunner.rb	(revision 18425)
@@ -0,0 +1,268 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'fox'
+require 'test/unit/ui/testrunnermediator'
+require 'test/unit/ui/testrunnerutilities'
+
+include Fox
+
+module Test
+  module Unit
+    module UI
+      module Fox
+
+        # Runs a Test::Unit::TestSuite in a Fox UI. Obviously,
+        # this one requires you to have Fox
+        # (http://www.fox-toolkit.org/fox.html) and the Ruby
+        # Fox extension (http://fxruby.sourceforge.net/)
+        # installed.
+        class TestRunner
+
+          extend TestRunnerUtilities
+          
+          RED_STYLE = FXRGBA(0xFF,0,0,0xFF) #0xFF000000
+          GREEN_STYLE = FXRGBA(0,0xFF,0,0xFF) #0x00FF0000
+
+          # Creates a new TestRunner for running the passed
+          # suite.
+          def initialize(suite, output_level = NORMAL)
+            if (suite.respond_to?(:suite))
+              @suite = suite.suite
+            else
+              @suite = suite
+            end
+
+            @result = nil
+            @red = false
+          end
+  
+          # Begins the test run.
+          def start
+            setup_ui
+            setup_mediator
+            attach_to_mediator
+            start_ui
+            @result
+          end
+
+          def setup_mediator
+            @mediator = TestRunnerMediator.new(@suite)
+            suite_name = @suite.to_s
+            if ( @suite.kind_of?(Module) )
+              suite_name = @suite.name
+            end
+            @suite_name_entry.text = suite_name
+          end
+          
+          def attach_to_mediator
+            @mediator.add_listener(TestRunnerMediator::RESET, &method(:reset_ui))
+            @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
+            @mediator.add_listener(TestResult::CHANGED, &method(:result_changed))
+            @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
+            @mediator.add_listener(TestCase::STARTED, &method(:test_started))
+            @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
+          end
+  
+          def start_ui
+            @application.create
+            @window.show(PLACEMENT_SCREEN)
+            @application.addTimeout(1) do
+              @mediator.run_suite
+            end
+            @application.run
+          end
+          
+          def stop
+            @application.exit(0)
+          end
+          
+          def reset_ui(count)
+            @test_progress_bar.barColor = GREEN_STYLE
+            @test_progress_bar.total = count
+            @test_progress_bar.progress = 0
+            @red = false
+  
+            @test_count_label.text = "0"
+            @assertion_count_label.text = "0"
+            @failure_count_label.text = "0"
+            @error_count_label.text = "0"
+  
+            @fault_list.clearItems
+          end
+          
+          def add_fault(fault)
+            if ( ! @red )
+              @test_progress_bar.barColor = RED_STYLE
+              @red = true
+            end
+            item = FaultListItem.new(fault)
+            @fault_list.appendItem(item)
+          end
+          
+          def show_fault(fault)
+            raw_show_fault(fault.long_display)
+          end
+          
+          def raw_show_fault(string)
+            @detail_text.setText(string)
+          end
+          
+          def clear_fault
+            raw_show_fault("")
+          end
+          
+          def result_changed(result)
+            @test_progress_bar.progress = result.run_count
+  
+            @test_count_label.text = result.run_count.to_s
+            @assertion_count_label.text = result.assertion_count.to_s
+            @failure_count_label.text = result.failure_count.to_s
+            @error_count_label.text = result.error_count.to_s
+
+             # repaint now!
+             @info_panel.repaint
+             @application.flush
+          end
+          
+          def started(result)
+            @result = result
+            output_status("Started...")
+          end
+          
+          def test_started(test_name)
+            output_status("Running #{test_name}...")
+          end
+          
+          def finished(elapsed_time)
+            output_status("Finished in #{elapsed_time} seconds")
+          end
+          
+          def output_status(string)
+            @status_entry.text = string
+            @status_entry.repaint
+          end
+  
+          def setup_ui
+            @application = create_application
+            create_tooltip(@application)
+
+            @window = create_window(@application)
+            
+            @status_entry = create_entry(@window)
+            
+            main_panel = create_main_panel(@window)
+            
+            suite_panel = create_suite_panel(main_panel)
+            create_label(suite_panel, "Suite:")
+            @suite_name_entry = create_entry(suite_panel)
+            create_button(suite_panel, "&Run\tRun the current suite", proc { @mediator.run_suite })
+            
+            @test_progress_bar = create_progress_bar(main_panel)
+            
+            @info_panel = create_info_panel(main_panel)
+            create_label(@info_panel, "Tests:")
+            @test_count_label = create_label(@info_panel, "0")
+            create_label(@info_panel, "Assertions:")
+            @assertion_count_label = create_label(@info_panel, "0")
+            create_label(@info_panel, "Failures:")
+            @failure_count_label = create_label(@info_panel, "0")
+            create_label(@info_panel, "Errors:")
+            @error_count_label = create_label(@info_panel, "0")
+            
+            list_panel = create_list_panel(main_panel)
+            @fault_list = create_fault_list(list_panel)
+            
+            detail_panel = create_detail_panel(main_panel)
+            @detail_text = create_text(detail_panel)
+          end
+          
+          def create_application
+            app = FXApp.new("TestRunner", "Test::Unit")
+            app.init([])
+            app
+          end
+          
+          def create_window(app)
+            FXMainWindow.new(app, "Test::Unit TestRunner", nil, nil, DECOR_ALL, 0, 0, 450)
+          end
+          
+          def create_tooltip(app)
+            FXTooltip.new(app)
+          end
+  
+          def create_main_panel(parent)
+            panel = FXVerticalFrame.new(parent, LAYOUT_FILL_X | LAYOUT_FILL_Y)
+            panel.vSpacing = 10
+            panel
+          end
+  
+          def create_suite_panel(parent)
+            FXHorizontalFrame.new(parent, LAYOUT_SIDE_LEFT | LAYOUT_FILL_X)
+          end
+          
+          def create_button(parent, text, action)
+            FXButton.new(parent, text).connect(SEL_COMMAND, &action)
+          end
+          
+          def create_progress_bar(parent)
+            FXProgressBar.new(parent, nil, 0, PROGRESSBAR_NORMAL | LAYOUT_FILL_X)
+          end
+          
+          def create_info_panel(parent)
+            FXMatrix.new(parent, 1, MATRIX_BY_ROWS | LAYOUT_FILL_X)
+          end
+          
+          def create_label(parent, text)
+            FXLabel.new(parent, text, nil, JUSTIFY_CENTER_X | LAYOUT_FILL_COLUMN)
+          end
+          
+          def create_list_panel(parent)
+            FXHorizontalFrame.new(parent, LAYOUT_FILL_X | FRAME_SUNKEN | FRAME_THICK)
+          end
+          
+          def create_fault_list(parent)
+            list = FXList.new(parent, 10, nil, 0, LIST_SINGLESELECT | LAYOUT_FILL_X) #, 0, 0, 0, 150)
+            list.connect(SEL_COMMAND) do |sender, sel, ptr|
+              if sender.retrieveItem(sender.currentItem).selected?
+                show_fault(sender.retrieveItem(sender.currentItem).fault)
+              else
+                clear_fault
+              end
+            end
+            list
+          end
+          
+          def create_detail_panel(parent)
+            FXHorizontalFrame.new(parent, LAYOUT_FILL_X | LAYOUT_FILL_Y | FRAME_SUNKEN | FRAME_THICK)
+          end
+          
+          def create_text(parent)
+            FXText.new(parent, nil, 0, TEXT_READONLY | LAYOUT_FILL_X | LAYOUT_FILL_Y)
+          end
+          
+          def create_entry(parent)
+            entry = FXTextField.new(parent, 30, nil, 0, TEXTFIELD_NORMAL | LAYOUT_SIDE_BOTTOM | LAYOUT_FILL_X)
+            entry.disable
+            entry
+          end
+        end
+  
+        class FaultListItem < FXListItem
+          attr_reader(:fault)
+          def initialize(fault)
+            super(fault.short_display)
+            @fault = fault
+          end
+        end
+      end
+    end
+  end
+end
+
+if __FILE__ == $0
+  Test::Unit::UI::Fox::TestRunner.start_command_line_test
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/gtk/testrunner.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/gtk/testrunner.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/gtk/testrunner.rb	(revision 18425)
@@ -0,0 +1,416 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'gtk'
+require 'test/unit/ui/testrunnermediator'
+require 'test/unit/ui/testrunnerutilities'
+
+module Test
+  module Unit
+    module UI
+      module GTK
+
+        # Runs a Test::Unit::TestSuite in a Gtk UI. Obviously,
+        # this one requires you to have Gtk
+        # (http://www.gtk.org/) and the Ruby Gtk extension
+        # (http://ruby-gnome.sourceforge.net/) installed.
+        class TestRunner
+          extend TestRunnerUtilities
+
+          # Creates a new TestRunner for running the passed
+          # suite.
+          def initialize(suite, output_level = NORMAL)
+            if (suite.respond_to?(:suite))
+              @suite = suite.suite
+            else
+              @suite = suite
+            end
+            @result = nil
+
+            @runner = Thread.current
+            @restart_signal = Class.new(Exception)
+            @viewer = Thread.start do
+              @runner.join rescue @runner.run
+              Gtk.main
+            end
+            @viewer.join rescue nil # wait deadlock to handshake
+          end
+
+          # Begins the test run.
+          def start
+            setup_mediator
+            setup_ui
+            attach_to_mediator
+            start_ui
+            @result
+          end
+
+          private
+          def setup_mediator
+            @mediator = TestRunnerMediator.new(@suite)
+            suite_name = @suite.to_s
+            if ( @suite.kind_of?(Module) )
+              suite_name = @suite.name
+            end
+            suite_name_entry.set_text(suite_name)
+          end
+          
+          def attach_to_mediator
+            run_button.signal_connect("clicked", nil, &method(:run_test))
+            @mediator.add_listener(TestRunnerMediator::RESET, &method(:reset_ui))
+            @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
+            @mediator.add_listener(TestResult::CHANGED, &method(:result_changed))
+            @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
+            @mediator.add_listener(TestCase::STARTED, &method(:test_started))
+            @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
+            @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
+          end
+
+          def run_test(*)
+            @runner.raise(@restart_signal)
+          end
+          
+          def start_ui
+            @viewer.run
+            running = false
+            begin
+              loop do
+                if (running ^= true)
+                  run_button.child.text = "Stop"
+                  @mediator.run_suite
+                else
+                  run_button.child.text = "Run"
+                  @viewer.join
+                  break
+                end
+              end
+            rescue @restart_signal
+              retry
+            rescue
+            end
+          end
+          
+          def stop(*)
+            Gtk.main_quit
+          end
+          
+          def reset_ui(count)
+            test_progress_bar.set_style(green_style)
+            test_progress_bar.configure(0, 0, count)
+            @red = false
+  
+            run_count_label.set_text("0")
+            assertion_count_label.set_text("0")
+            failure_count_label.set_text("0")
+            error_count_label.set_text("0")
+  
+            fault_list.remove_items(fault_list.children)
+          end
+          
+          def add_fault(fault)
+            if ( ! @red )
+              test_progress_bar.set_style(red_style)
+              @red = true
+            end
+            item = FaultListItem.new(fault)
+            item.show
+            fault_list.append_items([item])
+          end
+          
+          def show_fault(fault)
+            raw_show_fault(fault.long_display)
+          end
+          
+          def raw_show_fault(string)
+            fault_detail_label.set_text(string)
+            outer_detail_sub_panel.queue_resize
+          end
+          
+          def clear_fault
+            raw_show_fault("")
+          end
+          
+          def result_changed(result)
+            run_count_label.set_text(result.run_count.to_s)
+            assertion_count_label.set_text(result.assertion_count.to_s)
+            failure_count_label.set_text(result.failure_count.to_s)
+            error_count_label.set_text(result.error_count.to_s)
+          end
+          
+          def started(result)
+            @result = result
+            output_status("Started...")
+          end
+          
+          def test_started(test_name)
+            output_status("Running #{test_name}...")
+          end
+          
+          def test_finished(test_name)
+            test_progress_bar.set_value(test_progress_bar.get_value + 1)
+          end
+          
+          def finished(elapsed_time)
+            output_status("Finished in #{elapsed_time} seconds")
+          end
+          
+          def output_status(string)
+            status_entry.set_text(string)
+          end
+  
+          def setup_ui
+            main_window.signal_connect("destroy", nil, &method(:stop))
+            main_window.show_all
+            fault_list.signal_connect("select-child", nil) {
+              | list, item, data |
+              show_fault(item.fault)
+            }
+            fault_list.signal_connect("unselect-child", nil) {
+              clear_fault
+            }
+            @red = false
+          end
+          
+          def main_window
+            lazy_initialize(:main_window) {
+              @main_window = Gtk::Window.new(Gtk::WINDOW_TOPLEVEL)
+              @main_window.set_title("Test::Unit TestRunner")
+              @main_window.set_usize(800, 600)
+              @main_window.set_uposition(20, 20)
+              @main_window.set_policy(true, true, false)
+              @main_window.add(main_panel)
+            }
+          end
+          
+          def main_panel
+            lazy_initialize(:main_panel) {
+              @main_panel = Gtk::VBox.new(false, 0)
+              @main_panel.pack_start(suite_panel, false, false, 0)
+              @main_panel.pack_start(progress_panel, false, false, 0)
+              @main_panel.pack_start(info_panel, false, false, 0)
+              @main_panel.pack_start(list_panel, false, false, 0)
+              @main_panel.pack_start(detail_panel, true, true, 0)
+              @main_panel.pack_start(status_panel, false, false, 0)
+            }
+          end
+          
+          def suite_panel
+            lazy_initialize(:suite_panel) {
+              @suite_panel = Gtk::HBox.new(false, 10)
+              @suite_panel.border_width(10)
+              @suite_panel.pack_start(Gtk::Label.new("Suite:"), false, false, 0)
+              @suite_panel.pack_start(suite_name_entry, true, true, 0)
+              @suite_panel.pack_start(run_button, false, false, 0)
+            }
+          end
+          
+          def suite_name_entry
+            lazy_initialize(:suite_name_entry) {
+              @suite_name_entry = Gtk::Entry.new
+              @suite_name_entry.set_editable(false)
+            }
+          end
+          
+          def run_button
+            lazy_initialize(:run_button) {
+              @run_button = Gtk::Button.new("Run")
+            }
+          end
+          
+          def progress_panel
+            lazy_initialize(:progress_panel) {
+              @progress_panel = Gtk::HBox.new(false, 10)
+              @progress_panel.border_width(10)
+              @progress_panel.pack_start(test_progress_bar, true, true, 0)
+            }
+          end
+          
+          def test_progress_bar
+            lazy_initialize(:test_progress_bar) {
+              @test_progress_bar = EnhancedProgressBar.new
+              @test_progress_bar.set_usize(@test_progress_bar.allocation.width,
+                                           info_panel.size_request.height)
+              @test_progress_bar.set_style(green_style)
+            }
+          end
+          
+          def green_style
+            lazy_initialize(:green_style) {
+              @green_style = Gtk::Style.new
+              @green_style.set_bg(Gtk::STATE_PRELIGHT, 0x0000, 0xFFFF, 0x0000)
+            }
+          end
+          
+          def red_style
+            lazy_initialize(:red_style) {
+              @red_style = Gtk::Style.new
+              @red_style.set_bg(Gtk::STATE_PRELIGHT, 0xFFFF, 0x0000, 0x0000)
+            }
+          end
+          
+          def info_panel
+            lazy_initialize(:info_panel) {
+              @info_panel = Gtk::HBox.new(false, 0)
+              @info_panel.border_width(10)
+              @info_panel.pack_start(Gtk::Label.new("Runs:"), false, false, 0)
+              @info_panel.pack_start(run_count_label, true, false, 0)
+              @info_panel.pack_start(Gtk::Label.new("Assertions:"), false, false, 0)
+              @info_panel.pack_start(assertion_count_label, true, false, 0)
+              @info_panel.pack_start(Gtk::Label.new("Failures:"), false, false, 0)
+              @info_panel.pack_start(failure_count_label, true, false, 0)
+              @info_panel.pack_start(Gtk::Label.new("Errors:"), false, false, 0)
+              @info_panel.pack_start(error_count_label, true, false, 0)
+            }
+          end
+          
+          def run_count_label
+            lazy_initialize(:run_count_label) {
+              @run_count_label = Gtk::Label.new("0")
+              @run_count_label.set_justify(Gtk::JUSTIFY_LEFT)
+            }
+          end
+          
+          def assertion_count_label
+            lazy_initialize(:assertion_count_label) {
+              @assertion_count_label = Gtk::Label.new("0")
+              @assertion_count_label.set_justify(Gtk::JUSTIFY_LEFT)
+            }
+          end
+          
+          def failure_count_label
+            lazy_initialize(:failure_count_label) {
+              @failure_count_label = Gtk::Label.new("0")
+              @failure_count_label.set_justify(Gtk::JUSTIFY_LEFT)
+            }
+          end
+          
+          def error_count_label
+            lazy_initialize(:error_count_label) {
+              @error_count_label = Gtk::Label.new("0")
+              @error_count_label.set_justify(Gtk::JUSTIFY_LEFT)
+            }
+          end
+          
+          def list_panel
+            lazy_initialize(:list_panel) {
+              @list_panel = Gtk::HBox.new
+              @list_panel.border_width(10)
+              @list_panel.pack_start(list_scrolled_window, true, true, 0)
+            }
+          end
+          
+          def list_scrolled_window
+            lazy_initialize(:list_scrolled_window) {
+              @list_scrolled_window = Gtk::ScrolledWindow.new
+              @list_scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
+              @list_scrolled_window.set_usize(@list_scrolled_window.allocation.width, 150)
+              @list_scrolled_window.add_with_viewport(fault_list)
+            }
+          end
+          
+          def fault_list
+            lazy_initialize(:fault_list) {
+              @fault_list = Gtk::List.new
+            }
+          end
+          
+          def detail_panel
+            lazy_initialize(:detail_panel) {
+              @detail_panel = Gtk::HBox.new
+              @detail_panel.border_width(10)
+              @detail_panel.pack_start(detail_scrolled_window, true, true, 0)
+            }
+          end
+          
+          def detail_scrolled_window
+            lazy_initialize(:detail_scrolled_window) {
+              @detail_scrolled_window = Gtk::ScrolledWindow.new
+              @detail_scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
+              @detail_scrolled_window.set_usize(400, @detail_scrolled_window.allocation.height)
+              @detail_scrolled_window.add_with_viewport(outer_detail_sub_panel)
+            }
+          end
+          
+          def outer_detail_sub_panel
+            lazy_initialize(:outer_detail_sub_panel) {
+              @outer_detail_sub_panel = Gtk::VBox.new
+              @outer_detail_sub_panel.pack_start(inner_detail_sub_panel, false, false, 0)
+            }
+          end
+          
+          def inner_detail_sub_panel
+            lazy_initialize(:inner_detail_sub_panel) {
+              @inner_detail_sub_panel = Gtk::HBox.new
+              @inner_detail_sub_panel.pack_start(fault_detail_label, false, false, 0)
+            }
+          end
+          
+          def fault_detail_label
+            lazy_initialize(:fault_detail_label) {
+              @fault_detail_label = EnhancedLabel.new("")
+              style = Gtk::Style.new
+              font = Gdk::Font.font_load("-*-Courier New-medium-r-normal--*-120-*-*-*-*-*-*")
+              begin
+                style.set_font(font)
+              rescue ArgumentError; end
+              @fault_detail_label.set_style(style)
+              @fault_detail_label.set_justify(Gtk::JUSTIFY_LEFT)
+              @fault_detail_label.set_line_wrap(false)
+            }
+          end
+          
+          def status_panel
+            lazy_initialize(:status_panel) {
+              @status_panel = Gtk::HBox.new
+              @status_panel.border_width(10)
+              @status_panel.pack_start(status_entry, true, true, 0)
+            }
+          end
+          
+          def status_entry
+            lazy_initialize(:status_entry) {
+              @status_entry = Gtk::Entry.new
+              @status_entry.set_editable(false)
+            }
+          end
+  
+          def lazy_initialize(symbol)
+            if (!instance_eval("defined?(@#{symbol.to_s})"))
+              yield
+            end
+            return instance_eval("@" + symbol.to_s)
+          end
+        end
+  
+        class EnhancedProgressBar < Gtk::ProgressBar
+          def set_style(style)
+            super
+            hide
+            show
+          end
+        end
+  
+        class EnhancedLabel < Gtk::Label
+          def set_text(text)
+            super(text.gsub(/\n\t/, "\n" + (" " * 4)))
+          end
+        end
+  
+        class FaultListItem < Gtk::ListItem
+          attr_reader(:fault)
+          def initialize(fault)
+            super(fault.short_display)
+            @fault = fault
+          end
+        end
+      end
+    end
+  end
+end
+
+if __FILE__ == $0
+  Test::Unit::UI::GTK::TestRunner.start_command_line_test
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/gtk2/testrunner.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/gtk2/testrunner.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/gtk2/testrunner.rb	(revision 18425)
@@ -0,0 +1,465 @@
+#--
+#
+# Author:: Kenta MURATA.
+# Copyright:: Copyright (c) 2000-2002 Kenta MURATA. All rights reserved.
+# License:: Ruby license.
+
+require "gtk2"
+require "test/unit/ui/testrunnermediator"
+require "test/unit/ui/testrunnerutilities"
+
+module Test
+  module Unit
+    module UI
+      module GTK2
+
+        Gtk.init
+
+        class EnhancedLabel < Gtk::Label
+          def set_text(text)
+            super(text.gsub(/\n\t/, "\n    "))
+          end
+        end
+
+        class FaultList < Gtk::TreeView
+          def initialize
+            @faults = []
+            @model = Gtk::ListStore.new(String, String)
+            super(@model)
+            column = Gtk::TreeViewColumn.new
+            column.visible = false
+            append_column(column)
+            renderer = Gtk::CellRendererText.new
+            column = Gtk::TreeViewColumn.new("Failures", renderer, {:text => 1})
+            append_column(column)
+            selection.mode = Gtk::SELECTION_SINGLE
+            set_rules_hint(true)
+            set_headers_visible(false)
+          end # def initialize
+
+          def add_fault(fault)
+            @faults.push(fault)
+            iter = @model.append
+            iter.set_value(0, (@faults.length - 1).to_s)
+            iter.set_value(1, fault.short_display)
+          end # def add_fault(fault)
+
+          def get_fault(iter)
+            @faults[iter.get_value(0).to_i]
+          end # def get_fault
+
+          def clear
+            model.clear
+          end # def clear
+        end
+
+        class TestRunner
+          extend TestRunnerUtilities
+
+          def lazy_initialize(symbol)
+            if !instance_eval("defined?(@#{symbol})") then
+              yield
+            end
+            return instance_eval("@#{symbol}")
+          end
+          private :lazy_initialize
+
+          def status_entry
+            lazy_initialize(:status_entry) do
+              @status_entry = Gtk::Entry.new
+              @status_entry.editable = false
+            end
+          end
+          private :status_entry
+
+          def status_panel
+            lazy_initialize(:status_panel) do
+              @status_panel = Gtk::HBox.new
+              @status_panel.border_width = 10
+              @status_panel.pack_start(status_entry, true, true, 0)
+            end
+          end
+          private :status_panel
+
+          def fault_detail_label
+            lazy_initialize(:fault_detail_label) do
+              @fault_detail_label = EnhancedLabel.new("")
+#              style = Gtk::Style.new
+#              font = Gdk::Font.
+#               font_load("-*-Courier 10 Pitch-medium-r-normal--*-120-*-*-*-*-*-*")
+#              style.set_font(font)
+#              @fault_detail_label.style = style
+              @fault_detail_label.justify = Gtk::JUSTIFY_LEFT
+              @fault_detail_label.wrap = false
+            end
+          end
+          private :fault_detail_label
+
+          def inner_detail_sub_panel
+            lazy_initialize(:inner_detail_sub_panel) do
+              @inner_detail_sub_panel = Gtk::HBox.new
+              @inner_detail_sub_panel.pack_start(fault_detail_label, false, false, 0)
+            end
+          end
+          private :inner_detail_sub_panel
+
+          def outer_detail_sub_panel
+            lazy_initialize(:outer_detail_sub_panel) do
+              @outer_detail_sub_panel = Gtk::VBox.new
+              @outer_detail_sub_panel.pack_start(inner_detail_sub_panel, false, false, 0)
+            end
+          end
+          private :outer_detail_sub_panel
+
+          def detail_scrolled_window
+            lazy_initialize(:detail_scrolled_window) do
+              @detail_scrolled_window = Gtk::ScrolledWindow.new
+              @detail_scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
+              @detail_scrolled_window.
+                set_size_request(400, @detail_scrolled_window.allocation.height)
+              @detail_scrolled_window.add_with_viewport(outer_detail_sub_panel)
+            end
+          end
+          private :detail_scrolled_window
+
+          def detail_panel
+            lazy_initialize(:detail_panel) do
+              @detail_panel = Gtk::HBox.new
+              @detail_panel.border_width = 10
+              @detail_panel.pack_start(detail_scrolled_window, true, true, 0)
+            end
+          end
+          private :detail_panel
+
+          def fault_list
+            lazy_initialize(:fault_list) do
+              @fault_list = FaultList.new
+            end
+          end
+          private :fault_list
+
+          def list_scrolled_window
+            lazy_initialize(:list_scrolled_window) do
+              @list_scrolled_window = Gtk::ScrolledWindow.new
+              @list_scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
+              @list_scrolled_window.
+                set_size_request(@list_scrolled_window.allocation.width, 150)
+              @list_scrolled_window.add_with_viewport(fault_list)
+            end
+          end
+          private :list_scrolled_window
+
+          def list_panel
+            lazy_initialize(:list_panel) do
+              @list_panel = Gtk::HBox.new
+              @list_panel.border_width = 10
+              @list_panel.pack_start(list_scrolled_window, true, true, 0)
+            end
+          end
+          private :list_panel
+
+          def error_count_label
+            lazy_initialize(:error_count_label) do
+              @error_count_label = Gtk::Label.new("0")
+              @error_count_label.justify = Gtk::JUSTIFY_LEFT
+            end
+          end
+          private :error_count_label
+
+          def failure_count_label
+            lazy_initialize(:failure_count_label) do
+              @failure_count_label = Gtk::Label.new("0")
+              @failure_count_label.justify = Gtk::JUSTIFY_LEFT
+            end
+          end
+          private :failure_count_label
+
+          def assertion_count_label
+            lazy_initialize(:assertion_count_label) do
+              @assertion_count_label = Gtk::Label.new("0")
+              @assertion_count_label.justify = Gtk::JUSTIFY_LEFT
+            end
+          end
+          private :assertion_count_label
+
+          def run_count_label
+            lazy_initialize(:run_count_label) do
+              @run_count_label = Gtk::Label.new("0")
+              @run_count_label.justify = Gtk::JUSTIFY_LEFT
+            end
+          end
+          private :run_count_label
+          
+          def info_panel
+            lazy_initialize(:info_panel) do
+              @info_panel = Gtk::HBox.new(false, 0)
+              @info_panel.border_width = 10
+              @info_panel.pack_start(Gtk::Label.new("Runs:"), false, false, 0)
+              @info_panel.pack_start(run_count_label, true, false, 0)
+              @info_panel.pack_start(Gtk::Label.new("Assertions:"), false, false, 0)
+              @info_panel.pack_start(assertion_count_label, true, false, 0)
+              @info_panel.pack_start(Gtk::Label.new("Failures:"), false, false, 0)
+              @info_panel.pack_start(failure_count_label, true, false, 0)
+              @info_panel.pack_start(Gtk::Label.new("Errors:"), false, false, 0)
+              @info_panel.pack_start(error_count_label, true, false, 0)
+            end
+          end # def info_panel
+          private :info_panel
+
+          def green_style
+            lazy_initialize(:green_style) do
+              @green_style = Gtk::Style.new
+              @green_style.set_bg(Gtk::STATE_PRELIGHT, 0x0000, 0xFFFF, 0x0000)
+            end
+          end # def green_style
+          private :green_style
+          
+          def red_style
+            lazy_initialize(:red_style) do
+              @red_style = Gtk::Style.new
+              @red_style.set_bg(Gtk::STATE_PRELIGHT, 0xFFFF, 0x0000, 0x0000)
+            end
+          end # def red_style
+          private :red_style
+          
+          def test_progress_bar
+            lazy_initialize(:test_progress_bar) {
+              @test_progress_bar = Gtk::ProgressBar.new
+              @test_progress_bar.fraction = 0.0
+              @test_progress_bar.
+                set_size_request(@test_progress_bar.allocation.width,
+                                 info_panel.size_request[1])
+              @test_progress_bar.style = green_style
+            }
+          end # def test_progress_bar
+          private :test_progress_bar
+          
+          def progress_panel
+            lazy_initialize(:progress_panel) do
+              @progress_panel = Gtk::HBox.new(false, 10)
+              @progress_panel.border_width = 10
+              @progress_panel.pack_start(test_progress_bar, true, true, 0)
+            end
+          end # def progress_panel
+
+          def run_button
+            lazy_initialize(:run_button) do
+              @run_button = Gtk::Button.new("Run")
+            end
+          end # def run_button
+
+          def suite_name_entry
+            lazy_initialize(:suite_name_entry) do
+              @suite_name_entry = Gtk::Entry.new
+              @suite_name_entry.editable = false
+            end
+          end # def suite_name_entry
+          private :suite_name_entry
+
+          def suite_panel
+            lazy_initialize(:suite_panel) do
+              @suite_panel = Gtk::HBox.new(false, 10)
+              @suite_panel.border_width = 10
+              @suite_panel.pack_start(Gtk::Label.new("Suite:"), false, false, 0)
+              @suite_panel.pack_start(suite_name_entry, true, true, 0)
+              @suite_panel.pack_start(run_button, false, false, 0)
+            end
+          end # def suite_panel
+          private :suite_panel
+
+          def main_panel
+            lazy_initialize(:main_panel) do
+              @main_panel = Gtk::VBox.new(false, 0)
+              @main_panel.pack_start(suite_panel, false, false, 0)
+              @main_panel.pack_start(progress_panel, false, false, 0)
+              @main_panel.pack_start(info_panel, false, false, 0)
+              @main_panel.pack_start(list_panel, false, false, 0)
+              @main_panel.pack_start(detail_panel, true, true, 0)
+              @main_panel.pack_start(status_panel, false, false, 0)
+            end
+          end # def main_panel
+          private :main_panel
+
+          def main_window
+            lazy_initialize(:main_window) do
+              @main_window = Gtk::Window.new(Gtk::Window::TOPLEVEL)
+              @main_window.set_title("Test::Unit TestRunner")
+              @main_window.set_default_size(800, 600)
+              @main_window.set_resizable(true)
+              @main_window.add(main_panel)
+            end
+          end # def main_window
+          private :main_window
+
+          def setup_ui
+            main_window.signal_connect("destroy", nil) { stop }
+            main_window.show_all
+            fault_list.selection.signal_connect("changed", nil) do
+              |selection, data|
+              if selection.selected then
+                show_fault(fault_list.get_fault(selection.selected))
+              else
+                clear_fault
+              end
+            end
+          end # def setup_ui
+          private :setup_ui
+
+          def output_status(string)
+            status_entry.set_text(string)
+          end # def output_status(string)
+          private :output_status
+
+          def finished(elapsed_time)
+            test_progress_bar.fraction = 1.0
+            output_status("Finished in #{elapsed_time} seconds")
+          end # def finished(elapsed_time)
+          private :finished
+
+          def test_started(test_name)
+            output_status("Running #{test_name}...")
+          end # def test_started(test_name)
+          private :test_started
+
+          def started(result)
+            @result = result
+            output_status("Started...")
+          end # def started(result)
+          private :started
+
+          def test_finished(result)
+            test_progress_bar.fraction += 1.0 / @count
+          end # def test_finished(result)
+
+          def result_changed(result)
+            run_count_label.label = result.run_count.to_s
+            assertion_count_label.label = result.assertion_count.to_s
+            failure_count_label.label = result.failure_count.to_s
+            error_count_label.label = result.error_count.to_s
+          end # def result_changed(result)
+          private :result_changed
+
+          def clear_fault
+            raw_show_fault("")
+          end # def clear_fault
+          private :clear_fault
+
+          def raw_show_fault(string)
+            fault_detail_label.set_text(string)
+            outer_detail_sub_panel.queue_resize
+          end # def raw_show_fault(string)
+          private :raw_show_fault
+
+          def show_fault(fault)
+            raw_show_fault(fault.long_display)
+          end # def show_fault(fault)
+          private :show_fault
+
+          def add_fault(fault)
+            if not @red then
+              test_progress_bar.style = red_style
+              @red = true
+            end
+            fault_list.add_fault(fault)
+          end # def add_fault(fault)
+          private :add_fault
+
+          def reset_ui(count)
+            test_progress_bar.style = green_style
+            test_progress_bar.fraction = 0.0
+            @count = count + 1
+            @red = false
+
+            run_count_label.set_text("0")
+            assertion_count_label.set_text("0")
+            failure_count_label.set_text("0")
+            error_count_label.set_text("0")
+
+            fault_list.clear
+          end # def reset_ui(count)
+          private :reset_ui
+
+          def stop
+            Gtk.main_quit
+          end # def stop
+          private :stop
+
+          def run_test
+            @runner.raise(@restart_signal)
+          end
+          private :run_test
+
+          def start_ui
+            @viewer.run
+            running = false
+            begin
+              loop do
+                if (running ^= true)
+                  run_button.child.text = "Stop"
+                  @mediator.run_suite
+                else
+                  run_button.child.text = "Run"
+                  @viewer.join
+                  break
+                end
+              end
+            rescue @restart_signal
+              retry
+            rescue
+            end
+          end # def start_ui
+          private :start_ui
+
+          def attach_to_mediator
+            run_button.signal_connect("clicked", nil) { run_test }
+            @mediator.add_listener(TestRunnerMediator::RESET, &method(:reset_ui))
+            @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
+            @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
+            @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
+            @mediator.add_listener(TestResult::CHANGED, &method(:result_changed))
+            @mediator.add_listener(TestCase::STARTED, &method(:test_started))
+            @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
+          end # def attach_to_mediator
+          private :attach_to_mediator
+
+          def setup_mediator
+            @mediator = TestRunnerMediator.new(@suite)
+            suite_name = @suite.to_s
+            if @suite.kind_of?(Module) then
+              suite_name = @suite.name
+            end
+            suite_name_entry.set_text(suite_name)
+          end # def setup_mediator
+          private :setup_mediator
+
+          def start
+            setup_mediator
+            setup_ui
+            attach_to_mediator
+            start_ui
+            @result
+          end # def start
+
+          def initialize(suite, output_level = NORMAL)
+            if suite.respond_to?(:suite) then
+              @suite = suite.suite
+            else
+              @suite = suite
+            end
+            @result = nil
+
+            @runner = Thread.current
+            @restart_signal = Class.new(Exception)
+            @viewer = Thread.start do
+              @runner.join rescue @runner.run
+              Gtk.main
+            end
+            @viewer.join rescue nil # wait deadlock to handshake
+          end # def initialize(suite)
+
+        end # class TestRunner
+
+      end # module GTK2
+    end # module UI
+  end # module Unit
+end # module Test
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/testrunnermediator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/testrunnermediator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/testrunnermediator.rb	(revision 18425)
@@ -0,0 +1,68 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit'
+require 'test/unit/util/observable'
+require 'test/unit/testresult'
+
+module Test
+  module Unit
+    module UI
+
+      # Provides an interface to write any given UI against,
+      # hopefully making it easy to write new UIs.
+      class TestRunnerMediator
+        RESET = name + "::RESET"
+        STARTED = name + "::STARTED"
+        FINISHED = name + "::FINISHED"
+        
+        include Util::Observable
+        
+        # Creates a new TestRunnerMediator initialized to run
+        # the passed suite.
+        def initialize(suite)
+          @suite = suite
+        end
+
+        # Runs the suite the TestRunnerMediator was created
+        # with.
+        def run_suite
+          Unit.run = true
+          begin_time = Time.now
+          notify_listeners(RESET, @suite.size)
+          result = create_result
+          notify_listeners(STARTED, result)
+          result_listener = result.add_listener(TestResult::CHANGED) do |updated_result|
+            notify_listeners(TestResult::CHANGED, updated_result)
+          end
+          
+          fault_listener = result.add_listener(TestResult::FAULT) do |fault|
+            notify_listeners(TestResult::FAULT, fault)
+          end
+          
+          @suite.run(result) do |channel, value|
+            notify_listeners(channel, value)
+          end
+          
+          result.remove_listener(TestResult::FAULT, fault_listener)
+          result.remove_listener(TestResult::CHANGED, result_listener)
+          end_time = Time.now
+          elapsed_time = end_time - begin_time
+          notify_listeners(FINISHED, elapsed_time) #"Finished in #{elapsed_time} seconds.")
+          return result
+        end
+
+        private
+        # A factory method to create the result the mediator
+        # should run with. Can be overridden by subclasses if
+        # one wants to use a different result.
+        def create_result
+          return TestResult.new
+        end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/testrunnerutilities.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/testrunnerutilities.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/testrunnerutilities.rb	(revision 18425)
@@ -0,0 +1,46 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+module Test
+  module Unit
+    module UI
+
+      SILENT = 0
+      PROGRESS_ONLY = 1
+      NORMAL = 2
+      VERBOSE = 3
+
+      # Provides some utilities common to most, if not all,
+      # TestRunners.
+      #
+      #--
+      #
+      # Perhaps there ought to be a TestRunner superclass? There
+      # seems to be a decent amount of shared code between test
+      # runners.
+
+      module TestRunnerUtilities
+
+        # Creates a new TestRunner and runs the suite.
+        def run(suite, output_level=NORMAL)
+          return new(suite, output_level).start
+        end
+
+        # Takes care of the ARGV parsing and suite
+        # determination necessary for running one of the
+        # TestRunners from the command line.
+        def start_command_line_test
+          if ARGV.empty?
+            puts "You should supply the name of a test suite file to the runner"
+            exit
+          end
+          require ARGV[0].gsub(/.+::/, '')
+          new(eval(ARGV[0])).start
+        end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/tk/testrunner.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/tk/testrunner.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/tk/testrunner.rb	(revision 18425)
@@ -0,0 +1,260 @@
+#--
+#
+# Original Author:: Nathaniel Talbott.
+# Author:: Kazuhiro NISHIYAMA.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# Copyright:: Copyright (c) 2003 Kazuhiro NISHIYAMA. All rights reserved.
+# License:: Ruby license.
+
+require 'tk'
+require 'test/unit/ui/testrunnermediator'
+require 'test/unit/ui/testrunnerutilities'
+
+module Test
+  module Unit
+    module UI
+      module Tk
+
+        # Runs a Test::Unit::TestSuite in a Tk UI. Obviously,
+        # this one requires you to have Tk
+        # and the Ruby Tk extension installed.
+        class TestRunner
+          extend TestRunnerUtilities
+
+          # Creates a new TestRunner for running the passed
+          # suite.
+          def initialize(suite, output_level = NORMAL)
+            if (suite.respond_to?(:suite))
+              @suite = suite.suite
+            else
+              @suite = suite
+            end
+            @result = nil
+
+            @red = false
+            @fault_detail_list = []
+            @runner = Thread.current
+            @restart_signal = Class.new(Exception)
+            @viewer = Thread.start do
+              @runner.join rescue @runner.run
+              ::Tk.mainloop
+            end
+            @viewer.join rescue nil # wait deadlock to handshake
+          end
+
+          # Begins the test run.
+          def start
+            setup_ui
+            setup_mediator
+            attach_to_mediator
+            start_ui
+            @result
+          end
+
+          private
+          def setup_mediator
+            @mediator = TestRunnerMediator.new(@suite)
+            suite_name = @suite.to_s
+            if ( @suite.kind_of?(Module) )
+              suite_name = @suite.name
+            end
+            @suite_name_entry.value = suite_name
+          end
+
+          def attach_to_mediator
+            @run_button.command(method(:run_test))
+            @fault_list.bind('ButtonPress-1', proc{|y|
+              fault = @fault_detail_list[@fault_list.nearest(y)]
+              if fault
+                show_fault(fault)
+              end
+            }, '%y')
+            @mediator.add_listener(TestRunnerMediator::RESET, &method(:reset_ui))
+            @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
+            @mediator.add_listener(TestResult::CHANGED, &method(:result_changed))
+            @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
+            @mediator.add_listener(TestCase::STARTED, &method(:test_started))
+            @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
+          end
+
+          def run_test
+            @runner.raise(@restart_signal)
+          end
+
+          def start_ui
+            @viewer.run
+            running = false
+            begin
+              loop do
+                if (running ^= true)
+                  @run_button.configure('text'=>'Stop')
+                  @mediator.run_suite
+                else
+                  @run_button.configure('text'=>'Run')
+                  @viewer.join
+                  break
+                end
+              end
+            rescue @restart_signal
+              retry
+            rescue
+            end
+          end
+
+          def stop
+            ::Tk.exit
+          end
+
+          def reset_ui(count)
+            @test_total_count = count.to_f
+            @test_progress_bar.configure('background'=>'green')
+            @test_progress_bar.place('relwidth'=>(count.zero? ? 0 : 0/count))
+            @red = false
+
+            @test_count_label.value = 0
+            @assertion_count_label.value = 0
+            @failure_count_label.value = 0
+            @error_count_label.value = 0
+
+            @fault_list.delete(0, 'end')
+            @fault_detail_list = []
+            clear_fault
+          end
+
+          def add_fault(fault)
+            if ( ! @red )
+              @test_progress_bar.configure('background'=>'red')
+              @red = true
+            end
+            @fault_detail_list.push fault
+            @fault_list.insert('end', fault.short_display)
+          end
+
+          def show_fault(fault)
+            raw_show_fault(fault.long_display)
+          end
+
+          def raw_show_fault(string)
+            @detail_text.value = string
+          end
+
+          def clear_fault
+            raw_show_fault("")
+          end
+
+          def result_changed(result)
+            @test_count_label.value = result.run_count
+            @test_progress_bar.place('relwidth'=>result.run_count/@test_total_count)
+            @assertion_count_label.value = result.assertion_count
+            @failure_count_label.value = result.failure_count
+            @error_count_label.value = result.error_count
+          end
+
+          def started(result)
+            @result = result
+            output_status("Started...")
+          end
+
+          def test_started(test_name)
+            output_status("Running #{test_name}...")
+          end
+
+          def finished(elapsed_time)
+            output_status("Finished in #{elapsed_time} seconds")
+          end
+
+          def output_status(string)
+            @status_entry.value = string
+          end
+
+          def setup_ui
+            @status_entry = TkVariable.new
+            l = TkLabel.new(nil, 'textvariable'=>@status_entry, 'relief'=>'sunken')
+            l.pack('side'=>'bottom', 'fill'=>'x')
+
+            suite_frame = TkFrame.new.pack('fill'=>'x')
+
+            @run_button = TkButton.new(suite_frame, 'text'=>'Run')
+            @run_button.pack('side'=>'right')
+
+            TkLabel.new(suite_frame, 'text'=>'Suite:').pack('side'=>'left')
+            @suite_name_entry = TkVariable.new
+            l = TkLabel.new(suite_frame, 'textvariable'=>@suite_name_entry, 'relief'=>'sunken')
+            l.pack('side'=>'left', 'fill'=>'x', 'expand'=>true)
+
+            f = TkFrame.new(nil, 'relief'=>'sunken', 'borderwidth'=>3, 'height'=>20).pack('fill'=>'x', 'padx'=>1)
+            @test_progress_bar = TkFrame.new(f, 'background'=>'green').place('anchor'=>'nw', 'relwidth'=>0.0, 'relheight'=>1.0)
+
+            info_frame = TkFrame.new.pack('fill'=>'x')
+            @test_count_label = create_count_label(info_frame, 'Tests:')
+            @assertion_count_label = create_count_label(info_frame, 'Assertions:')
+            @failure_count_label = create_count_label(info_frame, 'Failures:')
+            @error_count_label = create_count_label(info_frame, 'Errors:')
+
+	    if (::Tk.info('command', TkPanedWindow::TkCommandNames[0]) != "")
+	      # use panedwindow
+	      paned_frame = TkPanedWindow.new("orient"=>"vertical").pack('fill'=>'both', 'expand'=>true)
+
+	      fault_list_frame = TkFrame.new(paned_frame)
+	      detail_frame = TkFrame.new(paned_frame)
+
+	      paned_frame.add(fault_list_frame, detail_frame)
+	    else
+	      # no panedwindow
+	      paned_frame = nil
+	      fault_list_frame = TkFrame.new.pack('fill'=>'both', 'expand'=>true)
+	      detail_frame = TkFrame.new.pack('fill'=>'both', 'expand'=>true)
+	    end
+
+	    TkGrid.rowconfigure(fault_list_frame, 0, 'weight'=>1, 'minsize'=>0)
+	    TkGrid.columnconfigure(fault_list_frame, 0, 'weight'=>1, 'minsize'=>0)
+
+            fault_scrollbar_y = TkScrollbar.new(fault_list_frame)
+            fault_scrollbar_x = TkScrollbar.new(fault_list_frame)
+            @fault_list = TkListbox.new(fault_list_frame)
+            @fault_list.yscrollbar(fault_scrollbar_y)
+            @fault_list.xscrollbar(fault_scrollbar_x)
+
+	    TkGrid.rowconfigure(detail_frame, 0, 'weight'=>1, 'minsize'=>0)
+	    TkGrid.columnconfigure(detail_frame, 0, 'weight'=>1, 'minsize'=>0)
+
+	    ::Tk.grid(@fault_list, fault_scrollbar_y, 'sticky'=>'news')
+	    ::Tk.grid(fault_scrollbar_x, 'sticky'=>'news')
+
+            detail_scrollbar_y = TkScrollbar.new(detail_frame)
+            detail_scrollbar_x = TkScrollbar.new(detail_frame)
+            @detail_text = TkText.new(detail_frame, 'height'=>10, 'wrap'=>'none') {
+              bindtags(bindtags - [TkText])
+	    }
+	    @detail_text.yscrollbar(detail_scrollbar_y)
+	    @detail_text.xscrollbar(detail_scrollbar_x)
+
+	    ::Tk.grid(@detail_text, detail_scrollbar_y, 'sticky'=>'news')
+	    ::Tk.grid(detail_scrollbar_x, 'sticky'=>'news')
+
+	    # rubber-style pane
+	    if paned_frame
+	      ::Tk.update
+	      @height = paned_frame.winfo_height
+	      paned_frame.bind('Configure', proc{|h|
+		paned_frame.sash_place(0, 0, paned_frame.sash_coord(0)[1] * h / @height)
+		@height = h
+	      }, '%h')
+	    end
+          end
+
+          def create_count_label(parent, label)
+            TkLabel.new(parent, 'text'=>label).pack('side'=>'left', 'expand'=>true)
+            v = TkVariable.new(0)
+            TkLabel.new(parent, 'textvariable'=>v).pack('side'=>'left', 'expand'=>true)
+            v
+          end
+        end
+      end
+    end
+  end
+end
+
+if __FILE__ == $0
+  Test::Unit::UI::Tk::TestRunner.start_command_line_test
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/util/backtracefilter.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/util/backtracefilter.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/util/backtracefilter.rb	(revision 18425)
@@ -0,0 +1,40 @@
+module Test
+  module Unit
+    module Util
+      module BacktraceFilter
+        TESTUNIT_FILE_SEPARATORS = %r{[\\/:]}
+        TESTUNIT_PREFIX = __FILE__.split(TESTUNIT_FILE_SEPARATORS)[0..-3]
+        TESTUNIT_RB_FILE = /\.rb\Z/
+        
+        def filter_backtrace(backtrace, prefix=nil)
+          return ["No backtrace"] unless(backtrace)
+          split_p = if(prefix)
+            prefix.split(TESTUNIT_FILE_SEPARATORS)
+          else
+            TESTUNIT_PREFIX
+          end
+          match = proc do |e|
+            split_e = e.split(TESTUNIT_FILE_SEPARATORS)[0, split_p.size]
+            next false unless(split_e[0..-2] == split_p[0..-2])
+            split_e[-1].sub(TESTUNIT_RB_FILE, '') == split_p[-1]
+          end
+          return backtrace unless(backtrace.detect(&match))
+          found_prefix = false
+          new_backtrace = backtrace.reverse.reject do |e|
+            if(match[e])
+              found_prefix = true
+              true
+            elsif(found_prefix)
+              false
+            else
+              true
+            end
+          end.reverse
+          new_backtrace = (new_backtrace.empty? ? backtrace : new_backtrace)
+          new_backtrace = new_backtrace.reject(&match)
+          new_backtrace.empty? ? backtrace : new_backtrace
+        end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/util/observable.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/util/observable.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/util/observable.rb	(revision 18425)
@@ -0,0 +1,90 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+require 'test/unit/util/procwrapper'
+
+module Test
+  module Unit
+    module Util
+
+      # This is a utility class that allows anything mixing
+      # it in to notify a set of listeners about interesting
+      # events.
+      module Observable
+        # We use this for defaults since nil might mean something
+        NOTHING = "NOTHING/#{__id__}"
+
+        # Adds the passed proc as a listener on the
+        # channel indicated by channel_name. listener_key
+        # is used to remove the listener later; if none is
+        # specified, the proc itself is used.
+        #
+        # Whatever is used as the listener_key is
+        # returned, making it very easy to use the proc
+        # itself as the listener_key:
+        #
+        #  listener = add_listener("Channel") { ... }
+        #  remove_listener("Channel", listener)
+        def add_listener(channel_name, listener_key=NOTHING, &listener) # :yields: value
+          unless(block_given?)
+            raise ArgumentError.new("No callback was passed as a listener")
+          end
+      
+          key = listener_key
+          if (listener_key == NOTHING)
+            listener_key = listener
+            key = ProcWrapper.new(listener)
+          end
+      
+          channels[channel_name] ||= {}
+          channels[channel_name][key] = listener
+          return listener_key
+        end
+
+        # Removes the listener indicated by listener_key
+        # from the channel indicated by
+        # channel_name. Returns the registered proc, or
+        # nil if none was found.
+        def remove_listener(channel_name, listener_key)
+          channel = channels[channel_name]
+          return nil unless (channel)
+          key = listener_key
+          if (listener_key.instance_of?(Proc))
+            key = ProcWrapper.new(listener_key)
+          end
+          if (channel.has_key?(key))
+            return channel.delete(key)
+          end
+          return nil
+        end
+
+        # Calls all the procs registered on the channel
+        # indicated by channel_name. If value is
+        # specified, it is passed in to the procs,
+        # otherwise they are called with no arguments.
+        #
+        #--
+        #
+        # Perhaps this should be private? Would it ever
+        # make sense for an external class to call this
+        # method directly?
+        def notify_listeners(channel_name, *arguments)
+          channel = channels[channel_name]
+          return 0 unless (channel)
+          listeners = channel.values
+          listeners.each { |listener| listener.call(*arguments) }
+          return listeners.size
+        end
+
+        private
+        def channels
+          @channels ||= {}
+          return @channels
+        end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/util/procwrapper.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/util/procwrapper.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/util/procwrapper.rb	(revision 18425)
@@ -0,0 +1,48 @@
+#--
+#
+# Author:: Nathaniel Talbott.
+# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
+# License:: Ruby license.
+
+module Test
+  module Unit
+    module Util
+
+      # Allows the storage of a Proc passed through '&' in a
+      # hash.
+      #
+      # Note: this may be inefficient, since the hash being
+      # used is not necessarily very good. In Observable,
+      # efficiency is not too important, since the hash is
+      # only accessed when adding and removing listeners,
+      # not when notifying.
+
+      class ProcWrapper
+
+        # Creates a new wrapper for a_proc.
+        def initialize(a_proc)
+          @a_proc = a_proc
+          @hash = a_proc.inspect.sub(/^(#<#{a_proc.class}:)/){''}.sub(/(>)$/){''}.hex
+        end
+
+        def hash
+          return @hash
+        end
+
+        def ==(other)
+          case(other)
+            when ProcWrapper
+              return @a_proc == other.to_proc
+            else
+              return super
+          end
+        end
+        alias :eql? :==
+
+        def to_proc
+          return @a_proc
+        end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/thread.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/thread.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/thread.rb	(revision 18425)
@@ -0,0 +1,5 @@
+unless defined? Thread
+  fail "Thread not available for this ruby interpreter"
+end
+
+require 'thread.so'
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/thwait.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/thwait.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/thwait.rb	(revision 18425)
@@ -0,0 +1,169 @@
+#
+#   thwait.rb - thread synchronization class
+#   	$Release Version: 0.9 $
+#   	$Revision: 1.3 $
+#   	$Date: 1998/06/26 03:19:34 $
+#   	by Keiju ISHITSUKA(Nihpon Rational Software Co.,Ltd.)
+#
+# --
+#  feature:
+#  provides synchronization for multiple threads.
+#
+#  class methods:
+#  * ThreadsWait.all_waits(thread1,...)
+#    waits until all of specified threads are terminated.
+#    if a block is supplied for the method, evaluates it for
+#    each thread termination.
+#  * th = ThreadsWait.new(thread1,...)
+#    creates synchronization object, specifying thread(s) to wait.
+#  
+#  methods:
+#  * th.threads
+#    list threads to be synchronized
+#  * th.empty?
+#    is there any thread to be synchronized.
+#  * th.finished?
+#    is there already terminated thread.
+#  * th.join(thread1,...) 
+#    wait for specified thread(s).
+#  * th.join_nowait(threa1,...)
+#    specifies thread(s) to wait.  non-blocking.
+#  * th.next_wait
+#    waits until any of specified threads is terminated.
+#  * th.all_waits
+#    waits until all of specified threads are terminated.
+#    if a block is supplied for the method, evaluates it for
+#    each thread termination.
+#
+
+require "thread.rb"
+require "e2mmap.rb"
+
+#
+# This class watches for termination of multiple threads.  Basic functionality
+# (wait until specified threads have terminated) can be accessed through the
+# class method ThreadsWait::all_waits.  Finer control can be gained using
+# instance methods.
+#
+# Example:
+#
+#   ThreadsWait.all_wait(thr1, thr2, ...) do |t|
+#     STDERR.puts "Thread #{t} has terminated."
+#   end
+#
+class ThreadsWait
+  RCS_ID='-$Id: thwait.rb,v 1.3 1998/06/26 03:19:34 keiju Exp keiju $-'
+  
+  Exception2MessageMapper.extend_to(binding)
+  def_exception("ErrNoWaitingThread", "No threads for waiting.")
+  def_exception("ErrNoFinishedThread", "No finished threads.")
+  
+  #
+  # Waits until all specified threads have terminated.  If a block is provided,
+  # it is executed for each thread termination.
+  #
+  def ThreadsWait.all_waits(*threads) # :yield: thread
+    tw = ThreadsWait.new(*threads)
+    if block_given?
+      tw.all_waits do |th|
+	yield th
+      end
+    else
+      tw.all_waits
+    end
+  end
+  
+  #
+  # Creates a ThreadsWait object, specifying the threads to wait on.
+  # Non-blocking.
+  #
+  def initialize(*threads)
+    @threads = []
+    @wait_queue = Queue.new
+    join_nowait(*threads) unless threads.empty?
+  end
+  
+  # Returns the array of threads in the wait queue.
+  attr :threads
+  
+  #
+  # Returns +true+ if there are no threads to be synchronized.
+  #
+  def empty?
+    @threads.empty?
+  end
+  
+  #
+  # Returns +true+ if any thread has terminated.
+  #
+  def finished?
+    !@wait_queue.empty?
+  end
+  
+  #
+  # Waits for specified threads to terminate.
+  #
+  def join(*threads)
+    join_nowait(*threads)
+    next_wait
+  end
+  
+  #
+  # Specifies the threads that this object will wait for, but does not actually
+  # wait.
+  #
+  def join_nowait(*threads)
+    threads.flatten!
+    @threads.concat threads
+    for th in threads
+      Thread.start(th) do |t|
+	begin
+	  t.join
+	ensure
+	  @wait_queue.push t
+	end
+      end
+    end
+  end
+  
+  #
+  # Waits until any of the specified threads has terminated, and returns the one
+  # that does.
+  #
+  # If there is no thread to wait, raises +ErrNoWaitingThread+.  If +nonblock+
+  # is true, and there is no terminated thread, raises +ErrNoFinishedThread+.
+  #
+  def next_wait(nonblock = nil)
+    ThreadsWait.fail ErrNoWaitingThread if @threads.empty?
+    begin
+      @threads.delete(th = @wait_queue.pop(nonblock))
+      th
+    rescue ThreadError
+      ThreadsWait.fail ErrNoFinishedThread
+    end
+  end
+  
+  #
+  # Waits until all of the specified threads are terminated.  If a block is
+  # supplied for the method, it is executed for each thread termination.
+  #
+  # Raises exceptions in the same manner as +next_wait+.
+  #
+  def all_waits
+    until @threads.empty?
+      th = next_wait
+      yield th if block_given?
+    end
+  end
+end
+
+ThWait = ThreadsWait
+
+
+# Documentation comments:
+#  - Source of documentation is evenly split between Nutshell, existing
+#    comments, and my own rephrasing.
+#  - I'm not particularly confident that the comments are all exactly correct.
+#  - The history, etc., up the top appears in the RDoc output.  Perhaps it would
+#    be better to direct that not to appear, and put something else there
+#    instead.
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/time.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/time.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/time.rb	(revision 18425)
@@ -0,0 +1,797 @@
+
+#
+# == Introduction
+# 
+# This library extends the Time class:
+# * conversion between date string and time object.
+#   * date-time defined by RFC 2822
+#   * HTTP-date defined by RFC 2616
+#   * dateTime defined by XML Schema Part 2: Datatypes (ISO 8601)
+#   * various formats handled by Date._parse (string to time only)
+# 
+# == Design Issues
+# 
+# === Specialized interface
+# 
+# This library provides methods dedicated to special purposes:
+# * RFC 2822, RFC 2616 and XML Schema.
+# * They makes usual life easier.
+# 
+# === Doesn't depend on strftime
+# 
+# This library doesn't use +strftime+.  Especially #rfc2822 doesn't depend
+# on +strftime+ because:
+# 
+# * %a and %b are locale sensitive
+# 
+#   Since they are locale sensitive, they may be replaced to
+#   invalid weekday/month name in some locales.
+#   Since ruby-1.6 doesn't invoke setlocale by default,
+#   the problem doesn't arise until some external library invokes setlocale.
+#   Ruby/GTK is the example of such library.
+# 
+# * %z is not portable
+# 
+#   %z is required to generate zone in date-time of RFC 2822
+#   but it is not portable.
+#
+# == Revision Information
+#
+# $Id$
+#
+
+require 'parsedate'
+
+#
+# Implements the extensions to the Time class that are described in the
+# documentation for the time.rb library.
+#
+class Time
+  class << Time
+
+    ZoneOffset = {
+      'UTC' => 0,
+      # ISO 8601
+      'Z' => 0,
+      # RFC 822
+      'UT' => 0, 'GMT' => 0,
+      'EST' => -5, 'EDT' => -4,
+      'CST' => -6, 'CDT' => -5,
+      'MST' => -7, 'MDT' => -6,
+      'PST' => -8, 'PDT' => -7,
+      # Following definition of military zones is original one.
+      # See RFC 1123 and RFC 2822 for the error in RFC 822.
+      'A' => +1, 'B' => +2, 'C' => +3, 'D' => +4,  'E' => +5,  'F' => +6, 
+      'G' => +7, 'H' => +8, 'I' => +9, 'K' => +10, 'L' => +11, 'M' => +12,
+      'N' => -1, 'O' => -2, 'P' => -3, 'Q' => -4,  'R' => -5,  'S' => -6, 
+      'T' => -7, 'U' => -8, 'V' => -9, 'W' => -10, 'X' => -11, 'Y' => -12,
+    }
+    def zone_offset(zone, year=Time.now.year)
+      off = nil
+      zone = zone.upcase
+      if /\A([+-])(\d\d):?(\d\d)\z/ =~ zone
+        off = ($1 == '-' ? -1 : 1) * ($2.to_i * 60 + $3.to_i) * 60
+      elsif /\A[+-]\d\d\z/ =~ zone
+        off = zone.to_i * 3600
+      elsif ZoneOffset.include?(zone)
+        off = ZoneOffset[zone] * 3600
+      elsif ((t = Time.local(year, 1, 1)).zone.upcase == zone rescue false)
+        off = t.utc_offset
+      elsif ((t = Time.local(year, 7, 1)).zone.upcase == zone rescue false)
+        off = t.utc_offset
+      end
+      off
+    end
+
+    def zone_utc?(zone)
+      # * +0000 means localtime. [RFC 2822]
+      # * GMT is a localtime abbreviation in Europe/London, etc.
+      if /\A(?:-00:00|-0000|-00|UTC|Z|UT)\z/i =~ zone
+        true
+      else
+        false
+      end
+    end
+    private :zone_utc?
+
+    LeapYearMonthDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+    CommonYearMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+    def month_days(y, m)
+      if ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)
+        LeapYearMonthDays[m-1]
+      else
+        CommonYearMonthDays[m-1]
+      end
+    end
+    private :month_days
+
+    def apply_offset(year, mon, day, hour, min, sec, off)
+      if off < 0
+        off = -off
+        off, o = off.divmod(60)
+        if o != 0 then sec += o; o, sec = sec.divmod(60); off += o end
+        off, o = off.divmod(60)
+        if o != 0 then min += o; o, min = min.divmod(60); off += o end
+        off, o = off.divmod(24)
+        if o != 0 then hour += o; o, hour = hour.divmod(24); off += o end
+        if off != 0
+          day += off
+          if month_days(year, mon) < day
+            mon += 1
+            if 12 < mon
+              mon = 1
+              year += 1
+            end
+            day = 1
+          end
+        end
+      elsif 0 < off
+        off, o = off.divmod(60)
+        if o != 0 then sec -= o; o, sec = sec.divmod(60); off -= o end
+        off, o = off.divmod(60)
+        if o != 0 then min -= o; o, min = min.divmod(60); off -= o end
+        off, o = off.divmod(24)
+        if o != 0 then hour -= o; o, hour = hour.divmod(24); off -= o end
+        if off != 0 then
+          day -= off
+          if day < 1
+            mon -= 1
+            if mon < 1
+              year -= 1
+              mon = 12
+            end
+            day = month_days(year, mon)
+          end
+        end
+      end
+      return year, mon, day, hour, min, sec
+    end
+    private :apply_offset
+
+    def make_time(year, mon, day, hour, min, sec, sec_fraction, zone, now)
+      usec = nil
+      usec = (sec_fraction * 1000000).to_i if sec_fraction
+      if now
+        begin
+          break if year; year = now.year
+          break if mon; mon = now.mon
+          break if day; day = now.day
+          break if hour; hour = now.hour
+          break if min; min = now.min
+          break if sec; sec = now.sec
+          break if sec_fraction; usec = now.tv_usec
+        end until true
+      end
+
+      year ||= 1970
+      mon ||= 1
+      day ||= 1
+      hour ||= 0
+      min ||= 0
+      sec ||= 0
+      usec ||= 0
+
+      off = nil
+      off = zone_offset(zone, year) if zone
+
+      if off
+        year, mon, day, hour, min, sec =
+          apply_offset(year, mon, day, hour, min, sec, off)
+        t = Time.utc(year, mon, day, hour, min, sec, usec)
+        t.localtime if !zone_utc?(zone)
+        t
+      else
+        self.local(year, mon, day, hour, min, sec, usec)
+      end
+    end
+    private :make_time
+
+    #
+    # Parses +date+ using Date._parse and converts it to a Time object.
+    #
+    # If a block is given, the year described in +date+ is converted by the
+    # block.  For example:
+    #
+    #     Time.parse(...) {|y| y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y}
+    #
+    # If the upper components of the given time are broken or missing, they are
+    # supplied with those of +now+.  For the lower components, the minimum
+    # values (1 or 0) are assumed if broken or missing.  For example:
+    #
+    #     # Suppose it is "Thu Nov 29 14:33:20 GMT 2001" now and
+    #     # your timezone is GMT:
+    #     Time.parse("16:30")     #=> Thu Nov 29 16:30:00 GMT 2001
+    #     Time.parse("7/23")      #=> Mon Jul 23 00:00:00 GMT 2001
+    #     Time.parse("Aug 31")    #=> Fri Aug 31 00:00:00 GMT 2001
+    #
+    # Since there are numerous conflicts among locally defined timezone
+    # abbreviations all over the world, this method is not made to
+    # understand all of them.  For example, the abbreviation "CST" is
+    # used variously as:
+    #
+    #     -06:00 in America/Chicago,
+    #     -05:00 in America/Havana,
+    #     +08:00 in Asia/Harbin,
+    #     +09:30 in Australia/Darwin,
+    #     +10:30 in Australia/Adelaide,
+    #     etc.
+    #
+    # Based on the fact, this method only understands the timezone
+    # abbreviations described in RFC 822 and the system timezone, in the
+    # order named. (i.e. a definition in RFC 822 overrides the system
+    # timezone definition.)  The system timezone is taken from
+    # <tt>Time.local(year, 1, 1).zone</tt> and
+    # <tt>Time.local(year, 7, 1).zone</tt>.
+    # If the extracted timezone abbreviation does not match any of them,
+    # it is ignored and the given time is regarded as a local time.
+    #
+    # ArgumentError is raised if Date._parse cannot extract information from
+    # +date+ or Time class cannot represent specified date.
+    #
+    # This method can be used as fail-safe for other parsing methods as:
+    #
+    #   Time.rfc2822(date) rescue Time.parse(date)
+    #   Time.httpdate(date) rescue Time.parse(date)
+    #   Time.xmlschema(date) rescue Time.parse(date)
+    #
+    # A failure for Time.parse should be checked, though.
+    #
+    def parse(date, now=Time.now)
+      d = Date._parse(date, false)
+      year = d[:year]
+      year = yield(year) if year && block_given?
+      make_time(year, d[:mon], d[:mday], d[:hour], d[:min], d[:sec], d[:sec_fraction], d[:zone], now)
+    end
+
+    MonthValue = {
+      'JAN' => 1, 'FEB' => 2, 'MAR' => 3, 'APR' => 4, 'MAY' => 5, 'JUN' => 6,
+      'JUL' => 7, 'AUG' => 8, 'SEP' => 9, 'OCT' =>10, 'NOV' =>11, 'DEC' =>12
+    }
+
+    #
+    # Parses +date+ as date-time defined by RFC 2822 and converts it to a Time
+    # object.  The format is identical to the date format defined by RFC 822 and
+    # updated by RFC 1123.
+    #
+    # ArgumentError is raised if +date+ is not compliant with RFC 2822
+    # or Time class cannot represent specified date.
+    #
+    # See #rfc2822 for more information on this format.
+    #
+    def rfc2822(date)
+      if /\A\s*
+          (?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*,\s*)?
+          (\d{1,2})\s+
+          (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+
+          (\d{2,})\s+
+          (\d{2})\s*
+          :\s*(\d{2})\s*
+          (?::\s*(\d{2}))?\s+
+          ([+-]\d{4}|
+           UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[A-IK-Z])/ix =~ date
+        # Since RFC 2822 permit comments, the regexp has no right anchor.
+        day = $1.to_i
+        mon = MonthValue[$2.upcase]
+        year = $3.to_i
+        hour = $4.to_i
+        min = $5.to_i
+        sec = $6 ? $6.to_i : 0
+        zone = $7
+
+        # following year completion is compliant with RFC 2822.
+        year = if year < 50
+                 2000 + year
+               elsif year < 1000
+                 1900 + year
+               else
+                 year
+               end
+
+        year, mon, day, hour, min, sec =
+          apply_offset(year, mon, day, hour, min, sec, zone_offset(zone))
+        t = self.utc(year, mon, day, hour, min, sec)
+        t.localtime if !zone_utc?(zone)
+        t
+      else
+        raise ArgumentError.new("not RFC 2822 compliant date: #{date.inspect}")
+      end
+    end
+    alias rfc822 rfc2822
+
+    #
+    # Parses +date+ as HTTP-date defined by RFC 2616 and converts it to a Time
+    # object.
+    #
+    # ArgumentError is raised if +date+ is not compliant with RFC 2616 or Time
+    # class cannot represent specified date.
+    #
+    # See #httpdate for more information on this format.
+    #
+    def httpdate(date)
+      if /\A\s*
+          (?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\x20
+          (\d{2})\x20
+          (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\x20
+          (\d{4})\x20
+          (\d{2}):(\d{2}):(\d{2})\x20
+          GMT
+          \s*\z/ix =~ date
+        self.rfc2822(date)
+      elsif /\A\s*
+             (?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday),\x20
+             (\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d\d)\x20
+             (\d\d):(\d\d):(\d\d)\x20
+             GMT
+             \s*\z/ix =~ date
+        self.parse(date)
+      elsif /\A\s*
+             (?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\x20
+             (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\x20
+             (\d\d|\x20\d)\x20
+             (\d\d):(\d\d):(\d\d)\x20
+             (\d{4})
+             \s*\z/ix =~ date
+        self.utc($6.to_i, MonthValue[$1.upcase], $2.to_i,
+                 $3.to_i, $4.to_i, $5.to_i)
+      else
+        raise ArgumentError.new("not RFC 2616 compliant date: #{date.inspect}")
+      end
+    end
+
+    #
+    # Parses +date+ as dateTime defined by XML Schema and converts it to a Time
+    # object.  The format is restricted version of the format defined by ISO
+    # 8601.
+    #
+    # ArgumentError is raised if +date+ is not compliant with the format or Time
+    # class cannot represent specified date.
+    #
+    # See #xmlschema for more information on this format.
+    #
+    def xmlschema(date)
+      if /\A\s*
+          (-?\d+)-(\d\d)-(\d\d)
+          T
+          (\d\d):(\d\d):(\d\d)
+          (\.\d*)?
+          (Z|[+-]\d\d:\d\d)?
+          \s*\z/ix =~ date
+        year = $1.to_i
+        mon = $2.to_i
+        day = $3.to_i
+        hour = $4.to_i
+        min = $5.to_i
+        sec = $6.to_i
+        usec = 0
+        usec = $7.to_f * 1000000 if $7
+        if $8
+          zone = $8
+          year, mon, day, hour, min, sec =
+            apply_offset(year, mon, day, hour, min, sec, zone_offset(zone))
+          Time.utc(year, mon, day, hour, min, sec, usec)
+        else
+          Time.local(year, mon, day, hour, min, sec, usec)
+        end
+      else
+        raise ArgumentError.new("invalid date: #{date.inspect}")
+      end
+    end
+    alias iso8601 xmlschema
+  end # class << self
+
+  #
+  # Returns a string which represents the time as date-time defined by RFC 2822:
+  #
+  #   day-of-week, DD month-name CCYY hh:mm:ss zone
+  #
+  # where zone is [+-]hhmm.
+  #
+  # If +self+ is a UTC time, -0000 is used as zone.
+  #
+  def rfc2822
+    sprintf('%s, %02d %s %d %02d:%02d:%02d ',
+      RFC2822_DAY_NAME[wday],
+      day, RFC2822_MONTH_NAME[mon-1], year,
+      hour, min, sec) +
+    if utc?
+      '-0000'
+    else
+      off = utc_offset
+      sign = off < 0 ? '-' : '+'
+      sprintf('%s%02d%02d', sign, *(off.abs / 60).divmod(60))
+    end
+  end
+  alias rfc822 rfc2822
+
+  RFC2822_DAY_NAME = [
+    'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'
+  ]
+  RFC2822_MONTH_NAME = [
+    'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
+  ]
+
+  #
+  # Returns a string which represents the time as rfc1123-date of HTTP-date
+  # defined by RFC 2616: 
+  # 
+  #   day-of-week, DD month-name CCYY hh:mm:ss GMT
+  #
+  # Note that the result is always UTC (GMT).
+  #
+  def httpdate
+    t = dup.utc
+    sprintf('%s, %02d %s %d %02d:%02d:%02d GMT',
+      RFC2822_DAY_NAME[t.wday],
+      t.day, RFC2822_MONTH_NAME[t.mon-1], t.year,
+      t.hour, t.min, t.sec)
+  end
+
+  #
+  # Returns a string which represents the time as dateTime defined by XML
+  # Schema:
+  #
+  #   CCYY-MM-DDThh:mm:ssTZD
+  #   CCYY-MM-DDThh:mm:ss.sssTZD
+  #
+  # where TZD is Z or [+-]hh:mm.
+  #
+  # If self is a UTC time, Z is used as TZD.  [+-]hh:mm is used otherwise.
+  #
+  # +fractional_seconds+ specifies a number of digits of fractional seconds.
+  # Its default value is 0.
+  #
+  def xmlschema(fraction_digits=0)
+    sprintf('%d-%02d-%02dT%02d:%02d:%02d',
+      year, mon, day, hour, min, sec) +
+    if fraction_digits == 0
+      ''
+    elsif fraction_digits <= 6
+      '.' + sprintf('%06d', usec)[0, fraction_digits]
+    else
+      '.' + sprintf('%06d', usec) + '0' * (fraction_digits - 6)
+    end +
+    if utc?
+      'Z'
+    else
+      off = utc_offset
+      sign = off < 0 ? '-' : '+'
+      sprintf('%s%02d:%02d', sign, *(off.abs / 60).divmod(60))
+    end
+  end
+  alias iso8601 xmlschema
+end
+
+if __FILE__ == $0
+  require 'test/unit'
+
+  class TimeExtentionTest < Test::Unit::TestCase # :nodoc:
+    def test_rfc822
+      assert_equal(Time.utc(1976, 8, 26, 14, 30) + 4 * 3600,
+                   Time.rfc2822("26 Aug 76 14:30 EDT"))
+      assert_equal(Time.utc(1976, 8, 27, 9, 32) + 7 * 3600,
+                   Time.rfc2822("27 Aug 76 09:32 PDT"))
+    end
+
+    def test_rfc2822
+      assert_equal(Time.utc(1997, 11, 21, 9, 55, 6) + 6 * 3600,
+                   Time.rfc2822("Fri, 21 Nov 1997 09:55:06 -0600"))
+      assert_equal(Time.utc(2003, 7, 1, 10, 52, 37) - 2 * 3600,
+                   Time.rfc2822("Tue, 1 Jul 2003 10:52:37 +0200"))
+      assert_equal(Time.utc(1997, 11, 21, 10, 1, 10) + 6 * 3600,
+                   Time.rfc2822("Fri, 21 Nov 1997 10:01:10 -0600"))
+      assert_equal(Time.utc(1997, 11, 21, 11, 0, 0) + 6 * 3600,
+                   Time.rfc2822("Fri, 21 Nov 1997 11:00:00 -0600"))
+      assert_equal(Time.utc(1997, 11, 24, 14, 22, 1) + 8 * 3600,
+                   Time.rfc2822("Mon, 24 Nov 1997 14:22:01 -0800"))
+      begin
+        Time.at(-1)
+      rescue ArgumentError
+        # ignore
+      else
+        assert_equal(Time.utc(1969, 2, 13, 23, 32, 54) + 3 * 3600 + 30 * 60,
+                     Time.rfc2822("Thu, 13 Feb 1969 23:32:54 -0330"))
+        assert_equal(Time.utc(1969, 2, 13, 23, 32, 0) + 3 * 3600 + 30 * 60,
+                     Time.rfc2822(" Thu,
+        13
+          Feb
+            1969
+        23:32
+                 -0330 (Newfoundland Time)"))
+      end
+      assert_equal(Time.utc(1997, 11, 21, 9, 55, 6),
+                   Time.rfc2822("21 Nov 97 09:55:06 GMT"))
+      assert_equal(Time.utc(1997, 11, 21, 9, 55, 6) + 6 * 3600,
+                   Time.rfc2822("Fri, 21 Nov 1997 09 :   55  :  06 -0600"))
+      assert_raise(ArgumentError) {
+        # inner comment is not supported.
+        Time.rfc2822("Fri, 21 Nov 1997 09(comment):   55  :  06 -0600")
+      }
+    end
+
+    def test_rfc2616
+      t = Time.utc(1994, 11, 6, 8, 49, 37)
+      assert_equal(t, Time.httpdate("Sun, 06 Nov 1994 08:49:37 GMT"))
+      assert_equal(t, Time.httpdate("Sunday, 06-Nov-94 08:49:37 GMT"))
+      assert_equal(t, Time.httpdate("Sun Nov  6 08:49:37 1994"))
+      assert_equal(Time.utc(1995, 11, 15, 6, 25, 24),
+                   Time.httpdate("Wed, 15 Nov 1995 06:25:24 GMT"))
+      assert_equal(Time.utc(1995, 11, 15, 4, 58, 8),
+                   Time.httpdate("Wed, 15 Nov 1995 04:58:08 GMT"))
+      assert_equal(Time.utc(1994, 11, 15, 8, 12, 31),
+                   Time.httpdate("Tue, 15 Nov 1994 08:12:31 GMT"))
+      assert_equal(Time.utc(1994, 12, 1, 16, 0, 0),
+                   Time.httpdate("Thu, 01 Dec 1994 16:00:00 GMT"))
+      assert_equal(Time.utc(1994, 10, 29, 19, 43, 31),
+                   Time.httpdate("Sat, 29 Oct 1994 19:43:31 GMT"))
+      assert_equal(Time.utc(1994, 11, 15, 12, 45, 26),
+                   Time.httpdate("Tue, 15 Nov 1994 12:45:26 GMT"))
+      assert_equal(Time.utc(1999, 12, 31, 23, 59, 59),
+                   Time.httpdate("Fri, 31 Dec 1999 23:59:59 GMT"))
+    end
+
+    def test_rfc3339
+      t = Time.utc(1985, 4, 12, 23, 20, 50, 520000)
+      s = "1985-04-12T23:20:50.52Z"
+      assert_equal(t, Time.iso8601(s))
+      assert_equal(s, t.iso8601(2))
+
+      t = Time.utc(1996, 12, 20, 0, 39, 57)
+      s = "1996-12-19T16:39:57-08:00"
+      assert_equal(t, Time.iso8601(s))
+      # There is no way to generate time string with arbitrary timezone.
+      s = "1996-12-20T00:39:57Z"
+      assert_equal(t, Time.iso8601(s))
+      assert_equal(s, t.iso8601)
+
+      t = Time.utc(1990, 12, 31, 23, 59, 60)
+      s = "1990-12-31T23:59:60Z"
+      assert_equal(t, Time.iso8601(s))
+      # leap second is representable only if timezone file has it.
+      s = "1990-12-31T15:59:60-08:00"
+      assert_equal(t, Time.iso8601(s))
+
+      begin
+        Time.at(-1)
+      rescue ArgumentError
+        # ignore
+      else
+        t = Time.utc(1937, 1, 1, 11, 40, 27, 870000)
+        s = "1937-01-01T12:00:27.87+00:20"
+        assert_equal(t, Time.iso8601(s))
+      end
+    end
+
+    # http://www.w3.org/TR/xmlschema-2/
+    def test_xmlschema
+      assert_equal(Time.utc(1999, 5, 31, 13, 20, 0) + 5 * 3600,
+                   Time.xmlschema("1999-05-31T13:20:00-05:00"))
+      assert_equal(Time.local(2000, 1, 20, 12, 0, 0),
+                   Time.xmlschema("2000-01-20T12:00:00"))
+      assert_equal(Time.utc(2000, 1, 20, 12, 0, 0),
+                   Time.xmlschema("2000-01-20T12:00:00Z"))
+      assert_equal(Time.utc(2000, 1, 20, 12, 0, 0) - 12 * 3600,
+                   Time.xmlschema("2000-01-20T12:00:00+12:00"))
+      assert_equal(Time.utc(2000, 1, 20, 12, 0, 0) + 13 * 3600,
+                   Time.xmlschema("2000-01-20T12:00:00-13:00"))
+      assert_equal(Time.utc(2000, 3, 4, 23, 0, 0) - 3 * 3600,
+                   Time.xmlschema("2000-03-04T23:00:00+03:00"))
+      assert_equal(Time.utc(2000, 3, 4, 20, 0, 0),
+                   Time.xmlschema("2000-03-04T20:00:00Z"))
+      assert_equal(Time.local(2000, 1, 15, 0, 0, 0),
+                   Time.xmlschema("2000-01-15T00:00:00"))
+      assert_equal(Time.local(2000, 2, 15, 0, 0, 0),
+                   Time.xmlschema("2000-02-15T00:00:00"))
+      assert_equal(Time.local(2000, 1, 15, 12, 0, 0),
+                   Time.xmlschema("2000-01-15T12:00:00"))
+      assert_equal(Time.utc(2000, 1, 16, 12, 0, 0),
+                   Time.xmlschema("2000-01-16T12:00:00Z"))
+      assert_equal(Time.local(2000, 1, 1, 12, 0, 0),
+                   Time.xmlschema("2000-01-01T12:00:00"))
+      assert_equal(Time.utc(1999, 12, 31, 23, 0, 0),
+                   Time.xmlschema("1999-12-31T23:00:00Z"))
+      assert_equal(Time.local(2000, 1, 16, 12, 0, 0),
+                   Time.xmlschema("2000-01-16T12:00:00"))
+      assert_equal(Time.local(2000, 1, 16, 0, 0, 0),
+                   Time.xmlschema("2000-01-16T00:00:00"))
+      assert_equal(Time.utc(2000, 1, 12, 12, 13, 14),
+                   Time.xmlschema("2000-01-12T12:13:14Z"))
+      assert_equal(Time.utc(2001, 4, 17, 19, 23, 17, 300000),
+                   Time.xmlschema("2001-04-17T19:23:17.3Z"))
+    end
+
+    def test_encode_xmlschema
+      t = Time.utc(2001, 4, 17, 19, 23, 17, 300000)
+      assert_equal("2001-04-17T19:23:17Z", t.xmlschema)
+      assert_equal("2001-04-17T19:23:17.3Z", t.xmlschema(1))
+      assert_equal("2001-04-17T19:23:17.300000Z", t.xmlschema(6))
+      assert_equal("2001-04-17T19:23:17.3000000Z", t.xmlschema(7))
+
+      t = Time.utc(2001, 4, 17, 19, 23, 17, 123456)
+      assert_equal("2001-04-17T19:23:17.1234560Z", t.xmlschema(7))
+      assert_equal("2001-04-17T19:23:17.123456Z", t.xmlschema(6))
+      assert_equal("2001-04-17T19:23:17.12345Z", t.xmlschema(5))
+      assert_equal("2001-04-17T19:23:17.1Z", t.xmlschema(1))
+
+      begin
+        Time.at(-1)
+      rescue ArgumentError
+        # ignore
+      else
+        t = Time.utc(1960, 12, 31, 23, 0, 0, 123456)
+        assert_equal("1960-12-31T23:00:00.123456Z", t.xmlschema(6))
+      end
+    end
+
+    def test_completion
+      now = Time.local(2001,11,29,21,26,35)
+      assert_equal(Time.local( 2001,11,29,21,12),
+                   Time.parse("2001/11/29 21:12", now))
+      assert_equal(Time.local( 2001,11,29),
+                   Time.parse("2001/11/29", now))
+      assert_equal(Time.local( 2001,11,29),
+                   Time.parse(     "11/29", now))
+      #assert_equal(Time.local(2001,11,1), Time.parse("Nov", now))
+      assert_equal(Time.local( 2001,11,29,10,22),
+                   Time.parse(           "10:22", now))
+    end
+
+    def test_invalid
+      # They were actually used in some web sites.
+      assert_raise(ArgumentError) { Time.httpdate("1 Dec 2001 10:23:57 GMT") }
+      assert_raise(ArgumentError) { Time.httpdate("Sat, 1 Dec 2001 10:25:42 GMT") }
+      assert_raise(ArgumentError) { Time.httpdate("Sat,  1-Dec-2001 10:53:55 GMT") }
+      assert_raise(ArgumentError) { Time.httpdate("Saturday, 01-Dec-2001 10:15:34 GMT") }
+      assert_raise(ArgumentError) { Time.httpdate("Saturday, 01-Dec-101 11:10:07 GMT") }
+      assert_raise(ArgumentError) { Time.httpdate("Fri, 30 Nov 2001 21:30:00 JST") }
+
+      # They were actually used in some mails.
+      assert_raise(ArgumentError) { Time.rfc2822("01-5-20") }
+      assert_raise(ArgumentError) { Time.rfc2822("7/21/00") }
+      assert_raise(ArgumentError) { Time.rfc2822("2001-8-28") }
+      assert_raise(ArgumentError) { Time.rfc2822("00-5-6 1:13:06") }
+      assert_raise(ArgumentError) { Time.rfc2822("2001-9-27 9:36:49") }
+      assert_raise(ArgumentError) { Time.rfc2822("2000-12-13 11:01:11") }
+      assert_raise(ArgumentError) { Time.rfc2822("2001/10/17 04:29:55") }
+      assert_raise(ArgumentError) { Time.rfc2822("9/4/2001 9:23:19 PM") }
+      assert_raise(ArgumentError) { Time.rfc2822("01 Nov 2001 09:04:31") }
+      assert_raise(ArgumentError) { Time.rfc2822("13 Feb 2001 16:4 GMT") }
+      assert_raise(ArgumentError) { Time.rfc2822("01 Oct 00 5:41:19 PM") }
+      assert_raise(ArgumentError) { Time.rfc2822("2 Jul 00 00:51:37 JST") }
+      assert_raise(ArgumentError) { Time.rfc2822("01 11 2001 06:55:57 -0500") }
+      assert_raise(ArgumentError) { Time.rfc2822("18 \343\366\356\341\370 2000") }
+      assert_raise(ArgumentError) { Time.rfc2822("Fri, Oct 2001  18:53:32") }
+      assert_raise(ArgumentError) { Time.rfc2822("Fri, 2 Nov 2001 03:47:54") }
+      assert_raise(ArgumentError) { Time.rfc2822("Fri, 27 Jul 2001 11.14.14 +0200") }
+      assert_raise(ArgumentError) { Time.rfc2822("Thu, 2 Nov 2000 04:13:53 -600") }
+      assert_raise(ArgumentError) { Time.rfc2822("Wed, 5 Apr 2000 22:57:09 JST") }
+      assert_raise(ArgumentError) { Time.rfc2822("Mon, 11 Sep 2000 19:47:33 00000") }
+      assert_raise(ArgumentError) { Time.rfc2822("Fri, 28 Apr 2000 20:40:47 +-900") }
+      assert_raise(ArgumentError) { Time.rfc2822("Fri, 19 Jan 2001 8:15:36 AM -0500") }
+      assert_raise(ArgumentError) { Time.rfc2822("Thursday, Sep 27 2001 7:42:35 AM EST") }
+      assert_raise(ArgumentError) { Time.rfc2822("3/11/2001 1:31:57 PM Pacific Daylight Time") }
+      assert_raise(ArgumentError) { Time.rfc2822("Mi, 28 Mrz 2001 11:51:36") }
+      assert_raise(ArgumentError) { Time.rfc2822("P, 30 sept 2001 23:03:14") }
+      assert_raise(ArgumentError) { Time.rfc2822("fr, 11 aug 2000 18:39:22") }
+      assert_raise(ArgumentError) { Time.rfc2822("Fr, 21 Sep 2001 17:44:03 -1000") }
+      assert_raise(ArgumentError) { Time.rfc2822("Mo, 18 Jun 2001 19:21:40 -1000") }
+      assert_raise(ArgumentError) { Time.rfc2822("l\366, 12 aug 2000 18:53:20") }
+      assert_raise(ArgumentError) { Time.rfc2822("l\366, 26 maj 2001 00:15:58") }
+      assert_raise(ArgumentError) { Time.rfc2822("Dom, 30 Sep 2001 17:36:30") }
+      assert_raise(ArgumentError) { Time.rfc2822("%&, 31 %2/ 2000 15:44:47 -0500") }
+      assert_raise(ArgumentError) { Time.rfc2822("dom, 26 ago 2001 03:57:07 -0300") }
+      assert_raise(ArgumentError) { Time.rfc2822("ter, 04 set 2001 16:27:58 -0300") }
+      assert_raise(ArgumentError) { Time.rfc2822("Wen, 3 oct 2001 23:17:49 -0400") }
+      assert_raise(ArgumentError) { Time.rfc2822("Wen, 3 oct 2001 23:17:49 -0400") }
+      assert_raise(ArgumentError) { Time.rfc2822("ele, 11 h: 2000 12:42:15 -0500") }
+      assert_raise(ArgumentError) { Time.rfc2822("Tue, 14 Aug 2001 3:55:3 +0200") }
+      assert_raise(ArgumentError) { Time.rfc2822("Fri, 25 Aug 2000 9:3:48 +0800") }
+      assert_raise(ArgumentError) { Time.rfc2822("Fri, 1 Dec 2000 0:57:50 EST") }
+      assert_raise(ArgumentError) { Time.rfc2822("Mon, 7 May 2001 9:39:51 +0200") }
+      assert_raise(ArgumentError) { Time.rfc2822("Wed, 1 Aug 2001 16:9:15 +0200") }
+      assert_raise(ArgumentError) { Time.rfc2822("Wed, 23 Aug 2000 9:17:36 +0800") }
+      assert_raise(ArgumentError) { Time.rfc2822("Fri, 11 Aug 2000 10:4:42 +0800") }
+      assert_raise(ArgumentError) { Time.rfc2822("Sat, 15 Sep 2001 13:22:2 +0300") }
+      assert_raise(ArgumentError) { Time.rfc2822("Wed,16 \276\305\324\302 2001 20:06:25 +0800") }
+      assert_raise(ArgumentError) { Time.rfc2822("Wed,7 \312\256\322\273\324\302 2001 23:47:22 +0800") }
+      assert_raise(ArgumentError) { Time.rfc2822("=?iso-8859-1?Q?(=C5=DA),?= 10   2 2001 23:32:26 +0900 (JST)") }
+      assert_raise(ArgumentError) { Time.rfc2822("\307\341\314\343\332\311, 30 \344\346\335\343\310\321 2001 10:01:06") }
+      assert_raise(ArgumentError) { Time.rfc2822("=?iso-8859-1?Q?(=BF=E5),?= 12  =?iso-8859-1?Q?9=B7=EE?= 2001 14:52:41\n+0900 (JST)") }
+    end
+
+    def test_zone_0000
+      assert_equal(true, Time.parse("2000-01-01T00:00:00Z").utc?)
+      assert_equal(true, Time.parse("2000-01-01T00:00:00-00:00").utc?)
+      assert_equal(false, Time.parse("2000-01-01T00:00:00+00:00").utc?)
+      assert_equal(false, Time.parse("Sat, 01 Jan 2000 00:00:00 GMT").utc?)
+      assert_equal(true, Time.parse("Sat, 01 Jan 2000 00:00:00 -0000").utc?)
+      assert_equal(false, Time.parse("Sat, 01 Jan 2000 00:00:00 +0000").utc?)
+      assert_equal(false, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 GMT").utc?)
+      assert_equal(true, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 -0000").utc?)
+      assert_equal(false, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 +0000").utc?)
+      assert_equal(true, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 UTC").utc?)
+    end
+
+    def test_parse_leap_second
+      t = Time.utc(1998,12,31,23,59,59)
+      assert_equal(t, Time.parse("Thu Dec 31 23:59:59 UTC 1998"))
+      assert_equal(t, Time.parse("Fri Dec 31 23:59:59 -0000 1998"));t.localtime
+      assert_equal(t, Time.parse("Fri Jan  1 08:59:59 +0900 1999"))
+      assert_equal(t, Time.parse("Fri Jan  1 00:59:59 +0100 1999"))
+      assert_equal(t, Time.parse("Fri Dec 31 23:59:59 +0000 1998"))
+      assert_equal(t, Time.parse("Fri Dec 31 22:59:59 -0100 1998"));t.utc
+      t += 1
+      assert_equal(t, Time.parse("Thu Dec 31 23:59:60 UTC 1998"))
+      assert_equal(t, Time.parse("Fri Dec 31 23:59:60 -0000 1998"));t.localtime
+      assert_equal(t, Time.parse("Fri Jan  1 08:59:60 +0900 1999"))
+      assert_equal(t, Time.parse("Fri Jan  1 00:59:60 +0100 1999"))
+      assert_equal(t, Time.parse("Fri Dec 31 23:59:60 +0000 1998"))
+      assert_equal(t, Time.parse("Fri Dec 31 22:59:60 -0100 1998"));t.utc
+      t += 1 if t.sec == 60
+      assert_equal(t, Time.parse("Thu Jan  1 00:00:00 UTC 1999"))
+      assert_equal(t, Time.parse("Fri Jan  1 00:00:00 -0000 1999"));t.localtime
+      assert_equal(t, Time.parse("Fri Jan  1 09:00:00 +0900 1999"))
+      assert_equal(t, Time.parse("Fri Jan  1 01:00:00 +0100 1999"))
+      assert_equal(t, Time.parse("Fri Jan  1 00:00:00 +0000 1999"))
+      assert_equal(t, Time.parse("Fri Dec 31 23:00:00 -0100 1998"))
+    end
+
+    def test_rfc2822_leap_second
+      t = Time.utc(1998,12,31,23,59,59)
+      assert_equal(t, Time.rfc2822("Thu, 31 Dec 1998 23:59:59 UTC"))
+      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 -0000"));t.localtime                                  
+      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 08:59:59 +0900"))
+      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 00:59:59 +0100"))
+      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 +0000"))
+      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:59 -0100"));t.utc                                  
+      t += 1
+      assert_equal(t, Time.rfc2822("Thu, 31 Dec 1998 23:59:60 UTC"))
+      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 -0000"));t.localtime                                  
+      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 08:59:60 +0900"))
+      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 00:59:60 +0100"))
+      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 +0000"))
+      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:60 -0100"));t.utc                                  
+      t += 1 if t.sec == 60
+      assert_equal(t, Time.rfc2822("Thu,  1 Jan 1999 00:00:00 UTC"))
+      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 00:00:00 -0000"));t.localtime                                  
+      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 09:00:00 +0900"))
+      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 01:00:00 +0100"))
+      assert_equal(t, Time.rfc2822("Fri,  1 Jan 1999 00:00:00 +0000"))
+      assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:00:00 -0100"))
+    end
+
+    def test_xmlschema_leap_second
+      t = Time.utc(1998,12,31,23,59,59)
+      assert_equal(t, Time.xmlschema("1998-12-31T23:59:59Z"))
+      assert_equal(t, Time.xmlschema("1998-12-31T23:59:59-00:00"));t.localtime
+      assert_equal(t, Time.xmlschema("1999-01-01T08:59:59+09:00"))
+      assert_equal(t, Time.xmlschema("1999-01-01T00:59:59+01:00"))
+      assert_equal(t, Time.xmlschema("1998-12-31T23:59:59+00:00"))
+      assert_equal(t, Time.xmlschema("1998-12-31T22:59:59-01:00"));t.utc
+      t += 1
+      assert_equal(t, Time.xmlschema("1998-12-31T23:59:60Z"))
+      assert_equal(t, Time.xmlschema("1998-12-31T23:59:60-00:00"));t.localtime
+      assert_equal(t, Time.xmlschema("1999-01-01T08:59:60+09:00"))
+      assert_equal(t, Time.xmlschema("1999-01-01T00:59:60+01:00"))
+      assert_equal(t, Time.xmlschema("1998-12-31T23:59:60+00:00"))
+      assert_equal(t, Time.xmlschema("1998-12-31T22:59:60-01:00"));t.utc
+      t += 1 if t.sec == 60
+      assert_equal(t, Time.xmlschema("1999-01-01T00:00:00Z"))
+      assert_equal(t, Time.xmlschema("1999-01-01T00:00:00-00:00"));t.localtime
+      assert_equal(t, Time.xmlschema("1999-01-01T09:00:00+09:00"))
+      assert_equal(t, Time.xmlschema("1999-01-01T01:00:00+01:00"))
+      assert_equal(t, Time.xmlschema("1999-01-01T00:00:00+00:00"))
+      assert_equal(t, Time.xmlschema("1998-12-31T23:00:00-01:00"))
+    end
+
+    def test_ruby_talk_152866
+      t = Time::xmlschema('2005-08-30T22:48:00-07:00')
+      assert_equal(31, t.day)
+      assert_equal(8, t.mon)
+    end
+
+    def test_parse_fraction
+      assert_equal(500000, Time.parse("2000-01-01T00:00:00.5+00:00").tv_usec)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/timeout.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/timeout.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/timeout.rb	(revision 18425)
@@ -0,0 +1,105 @@
+#--
+# = timeout.rb
+#
+# execution timeout
+#
+# = Copyright
+#
+# Copyright:: (C) 2000  Network Applied Communication Laboratory, Inc.
+# Copyright:: (C) 2000  Information-technology Promotion Agency, Japan
+#
+#++
+#
+# = Description
+#
+# A way of performing a potentially long-running operation in a thread, and
+# terminating it's execution if it hasn't finished within fixed amount of
+# time.
+#
+# Previous versions of timeout didn't use a module for namespace. This version
+# provides both Timeout.timeout, and a backwards-compatible #timeout.
+#
+# = Synopsis
+#
+#   require 'timeout'
+#   status = Timeout::timeout(5) {
+#     # Something that should be interrupted if it takes too much time...
+#   }
+#
+
+module Timeout
+
+  ##
+  # Raised by Timeout#timeout when the block times out.
+
+  class Error<Interrupt
+  end
+
+  ##
+  # Executes the method's block. If the block execution terminates before +sec+
+  # seconds has passed, it returns true. If not, it terminates the execution
+  # and raises +exception+ (which defaults to Timeout::Error).
+  #
+  # Note that this is both a method of module Timeout, so you can 'include
+  # Timeout' into your classes so they have a #timeout method, as well as a
+  # module method, so you can call it directly as Timeout.timeout().
+
+  def timeout(sec, exception=Error)
+    return yield if sec == nil or sec.zero?
+    raise ThreadError, "timeout within critical session" if Thread.critical
+    begin
+      x = Thread.current
+      y = Thread.start {
+        sleep sec
+        x.raise exception, "execution expired" if x.alive?
+      }
+      yield sec
+      #    return true
+    ensure
+      y.kill if y and y.alive?
+    end
+  end
+
+  module_function :timeout
+
+end
+
+##
+# Identical to:
+#
+#   Timeout::timeout(n, e, &block).
+#
+# Defined for backwards compatibility with earlier versions of timeout.rb, see
+# Timeout#timeout.
+
+def timeout(n, e=Timeout::Error, &block) # :nodoc:
+  Timeout::timeout(n, e, &block)
+end
+
+##
+# Another name for Timeout::Error, defined for backwards compatibility with
+# earlier versions of timeout.rb.
+
+TimeoutError = Timeout::Error # :nodoc:
+
+if __FILE__ == $0
+  p timeout(5) {
+    45
+  }
+  p timeout(5, TimeoutError) {
+    45
+  }
+  p timeout(nil) {
+    54
+  }
+  p timeout(0) {
+    54
+  }
+  p timeout(5) {
+    loop {
+      p 10
+      sleep 1
+    }
+  }
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tmpdir.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tmpdir.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tmpdir.rb	(revision 18425)
@@ -0,0 +1,45 @@
+#
+# tmpdir - retrieve temporary directory path
+#
+# $Id: tmpdir.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+
+class Dir
+
+  @@systmpdir = '/tmp'
+
+  begin
+    require 'Win32API'
+    max_pathlen = 260
+    windir = ' '*(max_pathlen+1)
+    begin
+      getdir = Win32API.new('kernel32', 'GetSystemWindowsDirectory', 'PL', 'L')
+    rescue RuntimeError
+      getdir = Win32API.new('kernel32', 'GetWindowsDirectory', 'PL', 'L')
+    end
+    len = getdir.call(windir, windir.size)
+    windir = File.expand_path(windir[0, len])
+    temp = File.join(windir, 'temp')
+    @@systmpdir = temp if File.directory?(temp) and File.writable?(temp)
+  rescue LoadError
+  end
+
+  ##
+  # Returns the operating system's temporary file path.
+
+  def Dir::tmpdir
+    tmp = '.'
+    if $SAFE > 0
+      tmp = @@systmpdir
+    else
+      for dir in [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'],
+	          ENV['USERPROFILE'], @@systmpdir, '/tmp']
+	if dir and File.directory?(dir) and File.writable?(dir)
+	  tmp = dir
+	  break
+	end
+      end
+    end
+    File.expand_path(tmp)
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tracer.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tracer.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tracer.rb	(revision 18425)
@@ -0,0 +1,167 @@
+#
+#   tracer.rb - 
+#   	$Release Version: 0.2$
+#   	$Revision: 1.8 $
+#   	$Date: 1998/05/19 03:42:49 $
+#   	by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#   
+#
+
+#
+# tracer main class
+#
+class Tracer
+  @RCS_ID='-$Id: tracer.rb,v 1.8 1998/05/19 03:42:49 keiju Exp keiju $-'
+
+  @stdout = STDOUT
+  @verbose = false
+  class << self
+    attr :verbose, true
+    alias verbose? verbose
+    attr :stdout, true
+  end
+  
+  EVENT_SYMBOL = {
+    "line" => "-",
+    "call" => ">",
+    "return" => "<",
+    "class" => "C",
+    "end" => "E",
+    "c-call" => ">",
+    "c-return" => "<",
+  }
+  
+  def initialize
+    @threads = Hash.new
+    if defined? Thread.main
+      @threads[Thread.main.object_id] = 0
+    else
+      @threads[Thread.current.object_id] = 0
+    end
+
+    @get_line_procs = {}
+
+    @filters = []
+  end
+  
+  def stdout
+    Tracer.stdout
+  end
+
+  def on
+    if block_given?
+      on
+      begin
+	yield
+      ensure
+	off
+      end
+    else
+      set_trace_func method(:trace_func).to_proc
+      stdout.print "Trace on\n" if Tracer.verbose?
+    end
+  end
+  
+  def off
+    set_trace_func nil
+    stdout.print "Trace off\n" if Tracer.verbose?
+  end
+
+  def add_filter(p = proc)
+    @filters.push p
+  end
+
+  def set_get_line_procs(file, p = proc)
+    @get_line_procs[file] = p
+  end
+  
+  def get_line(file, line)
+    if p = @get_line_procs[file]
+      return p.call(line)
+    end
+
+    unless list = SCRIPT_LINES__[file]
+      begin
+	f = open(file)
+	begin 
+	  SCRIPT_LINES__[file] = list = f.readlines
+	ensure
+	  f.close
+	end
+      rescue
+	SCRIPT_LINES__[file] = list = []
+      end
+    end
+
+    if l = list[line - 1]
+      l
+    else
+      "-\n"
+    end
+  end
+  
+  def get_thread_no
+    if no = @threads[Thread.current.object_id]
+      no
+    else
+      @threads[Thread.current.object_id] = @threads.size
+    end
+  end
+  
+  def trace_func(event, file, line, id, binding, klass, *)
+    return if file == __FILE__
+    
+    for p in @filters
+      return unless p.call event, file, line, id, binding, klass
+    end
+    
+    saved_crit = Thread.critical
+    Thread.critical = true
+    stdout.printf("#%d:%s:%d:%s:%s: %s",
+      get_thread_no,
+      file,
+      line,
+      klass || '',
+      EVENT_SYMBOL[event],
+      get_line(file, line))
+    Thread.critical = saved_crit
+  end
+
+  Single = new
+  def Tracer.on
+    if block_given?
+      Single.on{yield}
+    else
+      Single.on
+    end
+  end
+  
+  def Tracer.off
+    Single.off
+  end
+  
+  def Tracer.set_get_line_procs(file_name, p = proc)
+    Single.set_get_line_procs(file_name, p)
+  end
+
+  def Tracer.add_filter(p = proc)
+    Single.add_filter(p)
+  end
+  
+end
+
+SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
+
+if $0 == __FILE__
+  # direct call
+    
+  $0 = ARGV[0]
+  ARGV.shift
+  Tracer.on
+  require $0
+elsif caller(0).size == 1
+  Tracer.on
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tsort.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tsort.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tsort.rb	(revision 18425)
@@ -0,0 +1,290 @@
+#!/usr/bin/env ruby
+#--
+# tsort.rb - provides a module for topological sorting and strongly connected components.
+#++
+#
+
+#
+# TSort implements topological sorting using Tarjan's algorithm for
+# strongly connected components.
+#
+# TSort is designed to be able to be used with any object which can be
+# interpreted as a directed graph.
+#
+# TSort requires two methods to interpret an object as a graph,
+# tsort_each_node and tsort_each_child.
+#
+# * tsort_each_node is used to iterate for all nodes over a graph.
+# * tsort_each_child is used to iterate for child nodes of a given node.
+#
+# The equality of nodes are defined by eql? and hash since
+# TSort uses Hash internally.
+#
+# == A Simple Example
+#
+# The following example demonstrates how to mix the TSort module into an
+# existing class (in this case, Hash). Here, we're treating each key in
+# the hash as a node in the graph, and so we simply alias the required
+# #tsort_each_node method to Hash's #each_key method. For each key in the
+# hash, the associated value is an array of the node's child nodes. This
+# choice in turn leads to our implementation of the required #tsort_each_child
+# method, which fetches the array of child nodes and then iterates over that
+# array using the user-supplied block.
+#
+#   require 'tsort'
+#   
+#   class Hash
+#     include TSort
+#     alias tsort_each_node each_key
+#     def tsort_each_child(node, &block)
+#       fetch(node).each(&block)
+#     end
+#   end
+#   
+#   {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort
+#   #=> [3, 2, 1, 4]
+#   
+#   {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_components
+#   #=> [[4], [2, 3], [1]]
+#
+# == A More Realistic Example
+#
+# A very simple `make' like tool can be implemented as follows:
+#
+#   require 'tsort'
+#   
+#   class Make
+#     def initialize
+#       @dep = {}
+#       @dep.default = []
+#     end
+#     
+#     def rule(outputs, inputs=[], &block)
+#       triple = [outputs, inputs, block]
+#       outputs.each {|f| @dep[f] = [triple]}
+#       @dep[triple] = inputs
+#     end
+#     
+#     def build(target)
+#       each_strongly_connected_component_from(target) {|ns|
+#         if ns.length != 1
+#           fs = ns.delete_if {|n| Array === n}
+#           raise TSort::Cyclic.new("cyclic dependencies: #{fs.join ', '}")
+#         end
+#         n = ns.first
+#         if Array === n
+#           outputs, inputs, block = n
+#           inputs_time = inputs.map {|f| File.mtime f}.max
+#           begin
+#             outputs_time = outputs.map {|f| File.mtime f}.min
+#           rescue Errno::ENOENT
+#             outputs_time = nil
+#           end
+#           if outputs_time == nil ||
+#              inputs_time != nil && outputs_time <= inputs_time
+#             sleep 1 if inputs_time != nil && inputs_time.to_i == Time.now.to_i
+#             block.call
+#           end
+#         end
+#       }
+#     end
+#     
+#     def tsort_each_child(node, &block)
+#       @dep[node].each(&block)
+#     end
+#     include TSort
+#   end
+#   
+#   def command(arg)
+#     print arg, "\n"
+#     system arg
+#   end
+#   
+#   m = Make.new
+#   m.rule(%w[t1]) { command 'date > t1' }
+#   m.rule(%w[t2]) { command 'date > t2' }
+#   m.rule(%w[t3]) { command 'date > t3' }
+#   m.rule(%w[t4], %w[t1 t3]) { command 'cat t1 t3 > t4' }
+#   m.rule(%w[t5], %w[t4 t2]) { command 'cat t4 t2 > t5' }
+#   m.build('t5')
+#
+# == Bugs
+#
+# * 'tsort.rb' is wrong name because this library uses
+#   Tarjan's algorithm for strongly connected components.
+#   Although 'strongly_connected_components.rb' is correct but too long.
+#
+# == References
+#
+# R. E. Tarjan, "Depth First Search and Linear Graph Algorithms",
+# <em>SIAM Journal on Computing</em>, Vol. 1, No. 2, pp. 146-160, June 1972.
+#
+
+module TSort
+  class Cyclic < StandardError
+  end
+
+  #
+  # Returns a topologically sorted array of nodes.
+  # The array is sorted from children to parents, i.e.
+  # the first element has no child and the last node has no parent.
+  #
+  # If there is a cycle, TSort::Cyclic is raised.
+  #
+  def tsort
+    result = []
+    tsort_each {|element| result << element}
+    result
+  end
+
+  #
+  # The iterator version of the #tsort method.
+  # <tt><em>obj</em>.tsort_each</tt> is similar to <tt><em>obj</em>.tsort.each</tt>, but
+  # modification of _obj_ during the iteration may lead to unexpected results.
+  #
+  # #tsort_each returns +nil+.
+  # If there is a cycle, TSort::Cyclic is raised.
+  #
+  def tsort_each # :yields: node
+    each_strongly_connected_component {|component|
+      if component.size == 1
+        yield component.first
+      else
+        raise Cyclic.new("topological sort failed: #{component.inspect}")
+      end
+    }
+  end
+
+  #
+  # Returns strongly connected components as an array of arrays of nodes.
+  # The array is sorted from children to parents.
+  # Each elements of the array represents a strongly connected component.
+  #
+  def strongly_connected_components
+    result = []
+    each_strongly_connected_component {|component| result << component}
+    result
+  end
+
+  #
+  # The iterator version of the #strongly_connected_components method.
+  # <tt><em>obj</em>.each_strongly_connected_component</tt> is similar to
+  # <tt><em>obj</em>.strongly_connected_components.each</tt>, but
+  # modification of _obj_ during the iteration may lead to unexpected results.
+  #
+  #
+  # #each_strongly_connected_component returns +nil+.
+  #
+  def each_strongly_connected_component # :yields: nodes
+    id_map = {}
+    stack = []
+    tsort_each_node {|node|
+      unless id_map.include? node
+        each_strongly_connected_component_from(node, id_map, stack) {|c|
+          yield c
+        }
+      end
+    }
+    nil
+  end
+
+  #
+  # Iterates over strongly connected component in the subgraph reachable from 
+  # _node_.
+  #
+  # Return value is unspecified.
+  #
+  # #each_strongly_connected_component_from doesn't call #tsort_each_node.
+  #
+  def each_strongly_connected_component_from(node, id_map={}, stack=[]) # :yields: nodes
+    minimum_id = node_id = id_map[node] = id_map.size
+    stack_length = stack.length
+    stack << node
+
+    tsort_each_child(node) {|child|
+      if id_map.include? child
+        child_id = id_map[child]
+        minimum_id = child_id if child_id && child_id < minimum_id
+      else
+        sub_minimum_id =
+          each_strongly_connected_component_from(child, id_map, stack) {|c|
+            yield c
+          }
+        minimum_id = sub_minimum_id if sub_minimum_id < minimum_id
+      end
+    }
+
+    if node_id == minimum_id
+      component = stack.slice!(stack_length .. -1)
+      component.each {|n| id_map[n] = nil}
+      yield component
+    end
+
+    minimum_id
+  end
+
+  #
+  # Should be implemented by a extended class.
+  #
+  # #tsort_each_node is used to iterate for all nodes over a graph.
+  #
+  def tsort_each_node # :yields: node
+    raise NotImplementedError.new
+  end
+
+  #
+  # Should be implemented by a extended class.
+  #
+  # #tsort_each_child is used to iterate for child nodes of _node_.
+  #
+  def tsort_each_child(node) # :yields: child
+    raise NotImplementedError.new
+  end
+end
+
+if __FILE__ == $0
+  require 'test/unit'
+
+  class TSortHash < Hash # :nodoc:
+    include TSort
+    alias tsort_each_node each_key
+    def tsort_each_child(node, &block)
+      fetch(node).each(&block)
+    end
+  end
+
+  class TSortArray < Array # :nodoc:
+    include TSort
+    alias tsort_each_node each_index
+    def tsort_each_child(node, &block)
+      fetch(node).each(&block)
+    end
+  end
+
+  class TSortTest < Test::Unit::TestCase # :nodoc:
+    def test_dag
+      h = TSortHash[{1=>[2, 3], 2=>[3], 3=>[]}]
+      assert_equal([3, 2, 1], h.tsort)
+      assert_equal([[3], [2], [1]], h.strongly_connected_components)
+    end
+
+    def test_cycle
+      h = TSortHash[{1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}]
+      assert_equal([[4], [2, 3], [1]],
+        h.strongly_connected_components.map {|nodes| nodes.sort})
+      assert_raise(TSort::Cyclic) { h.tsort }
+    end
+
+    def test_array
+      a = TSortArray[[1], [0], [0], [2]]
+      assert_equal([[0, 1], [2], [3]],
+        a.strongly_connected_components.map {|nodes| nodes.sort})
+
+      a = TSortArray[[], [0]]
+      assert_equal([[0], [1]],
+        a.strongly_connected_components.map {|nodes| nodes.sort})
+    end
+  end
+
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/un.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/un.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/un.rb	(revision 18425)
@@ -0,0 +1,235 @@
+# 
+# = un.rb
+# 
+# Copyright (c) 2003 WATANABE Hirofumi <eban@ruby-lang.org>
+# 
+# This program is free software.
+# You can distribute/modify this program under the same terms of Ruby.
+# 
+# == Utilities to replace common UNIX commands in Makefiles etc
+#
+# == SYNOPSIS
+#
+#   ruby -run -e cp -- [OPTION] SOURCE DEST
+#   ruby -run -e ln -- [OPTION] TARGET LINK_NAME
+#   ruby -run -e mv -- [OPTION] SOURCE DEST
+#   ruby -run -e rm -- [OPTION] FILE
+#   ruby -run -e mkdir -- [OPTION] DIRS
+#   ruby -run -e rmdir -- [OPTION] DIRS
+#   ruby -run -e install -- [OPTION] SOURCE DEST
+#   ruby -run -e chmod -- [OPTION] OCTAL-MODE FILE
+#   ruby -run -e touch -- [OPTION] FILE
+#   ruby -run -e help [COMMAND]
+
+require "fileutils"
+require "optparse"
+
+module FileUtils
+#  @fileutils_label = ""
+  @fileutils_output = $stdout
+end
+
+def setup(options = "")
+  ARGV.map! do |x|
+    case x
+    when /^-/
+      x.delete "^-#{options}v"
+    when /[*?\[{]/
+      Dir[x]
+    else
+      x
+    end
+  end
+  ARGV.flatten!
+  ARGV.delete_if{|x| x == "-"}
+  opt_hash = {}
+  OptionParser.new do |o|
+    options.scan(/.:?/) do |s|
+      o.on("-" + s.tr(":", " ")) do |val|
+        opt_hash[s.delete(":").intern] = val
+      end
+    end
+    o.on("-v") do opt_hash[:verbose] = true end
+    o.parse!
+  end
+  yield ARGV, opt_hash
+end
+
+##
+# Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY
+#
+#   ruby -run -e cp -- [OPTION] SOURCE DEST
+#
+#   -p		preserve file attributes if possible
+#   -r		copy recursively
+#   -v		verbose
+#
+
+def cp
+  setup("pr") do |argv, options|
+    cmd = "cp"
+    cmd += "_r" if options.delete :r
+    options[:preserve] = true if options.delete :p
+    dest = argv.pop
+    argv = argv[0] if argv.size == 1
+    FileUtils.send cmd, argv, dest, options
+  end
+end
+
+##
+# Create a link to the specified TARGET with LINK_NAME.
+#
+#   ruby -run -e ln -- [OPTION] TARGET LINK_NAME
+#
+#   -s		make symbolic links instead of hard links
+#   -f		remove existing destination files
+#   -v		verbose
+#
+
+def ln
+  setup("sf") do |argv, options|
+    cmd = "ln"
+    cmd += "_s" if options.delete :s
+    options[:force] = true if options.delete :f
+    dest = argv.pop
+    argv = argv[0] if argv.size == 1
+    FileUtils.send cmd, argv, dest, options
+  end
+end
+
+##
+# Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.
+#
+#   ruby -run -e mv -- [OPTION] SOURCE DEST
+#
+#   -v		verbose
+#
+
+def mv
+  setup do |argv, options|
+    dest = argv.pop
+    argv = argv[0] if argv.size == 1
+    FileUtils.mv argv, dest, options
+  end
+end
+
+##
+# Remove the FILE
+#
+#   ruby -run -e rm -- [OPTION] FILE
+#
+#   -f		ignore nonexistent files
+#   -r		remove the contents of directories recursively
+#   -v		verbose
+#
+
+def rm
+  setup("fr") do |argv, options|
+    cmd = "rm"
+    cmd += "_r" if options.delete :r
+    options[:force] = true if options.delete :f
+    FileUtils.send cmd, argv, options
+  end
+end
+
+##
+# Create the DIR, if they do not already exist.
+#
+#   ruby -run -e mkdir -- [OPTION] DIR
+#
+#   -p		no error if existing, make parent directories as needed
+#   -v		verbose
+#
+
+def mkdir
+  setup("p") do |argv, options|
+    cmd = "mkdir"
+    cmd += "_p" if options.delete :p
+    FileUtils.send cmd, argv, options
+  end
+end
+
+##
+# Remove the DIR.
+#
+#   ruby -run -e rmdir -- [OPTION] DIR
+#
+#   -v		verbose
+#
+
+def rmdir
+  setup do |argv, options|
+    FileUtils.rmdir argv, options
+  end
+end
+
+##
+# Copy SOURCE to DEST.
+#
+#   ruby -run -e install -- [OPTION] SOURCE DEST
+#
+#   -p		apply access/modification times of SOURCE files to
+#  		corresponding destination files
+#   -m		set permission mode (as in chmod), instead of 0755
+#   -v		verbose
+#
+
+def install
+  setup("pm:") do |argv, options|
+    options[:mode] = (mode = options.delete :m) ? mode.oct : 0755
+    options[:preserve] = true if options.delete :p
+    dest = argv.pop
+    argv = argv[0] if argv.size == 1
+    FileUtils.install argv, dest, options
+  end
+end
+
+##
+# Change the mode of each FILE to OCTAL-MODE.
+#
+#   ruby -run -e chmod -- [OPTION] OCTAL-MODE FILE
+#
+#   -v		verbose
+#
+
+def chmod
+  setup do |argv, options|
+    mode = argv.shift.oct
+    FileUtils.chmod mode, argv, options
+  end
+end
+
+##
+# Update the access and modification times of each FILE to the current time.
+#
+#   ruby -run -e touch -- [OPTION] FILE
+#
+#   -v		verbose
+#
+
+def touch
+  setup do |argv, options|
+    FileUtils.touch argv, options
+  end
+end
+
+##
+# Display help message.
+#
+#   ruby -run -e help [COMMAND]
+#
+
+def help
+  setup do |argv,|
+    all = argv.empty?
+    open(__FILE__) do |me|
+      while me.gets("##\n")
+	if help = me.gets("\n\n")
+	  if all or argv.delete help[/-e \w+/].sub(/-e /, "")
+	    print help.gsub(/^# ?/, "")
+	  end
+	end
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri.rb	(revision 18425)
@@ -0,0 +1,28 @@
+#
+# URI support for Ruby
+#
+# Author:: Akira Yamada <akira@ruby-lang.org>
+# Documentation:: Akira Yamada <akira@ruby-lang.org>, Dmitry V. Sabanin <sdmitry@lrn.ru>
+# License:: 
+#  Copyright (c) 2001 akira yamada <akira@ruby-lang.org>
+#  You can redistribute it and/or modify it under the same term as Ruby.
+# Revision:: $Id: uri.rb 11708 2007-02-12 23:01:19Z shyouhei $
+# 
+# See URI for documentation
+#
+
+module URI
+  # :stopdoc:
+  VERSION_CODE = '000911'.freeze
+  VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
+  # :startdoc:
+
+end
+
+require 'uri/common'
+require 'uri/generic'
+require 'uri/ftp'
+require 'uri/http'
+require 'uri/https'
+require 'uri/ldap'
+require 'uri/mailto'
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/common.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/common.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/common.rb	(revision 18425)
@@ -0,0 +1,611 @@
+# = uri/common.rb
+#
+# Author:: Akira Yamada <akira@ruby-lang.org>
+# Revision:: $Id: common.rb 11747 2007-02-15 02:41:45Z knu $
+# License:: 
+#   You can redistribute it and/or modify it under the same term as Ruby.
+#
+
+module URI
+  module REGEXP
+    #
+    # Patterns used to parse URI's
+    #
+    module PATTERN
+      # :stopdoc:
+
+      # RFC 2396 (URI Generic Syntax)
+      # RFC 2732 (IPv6 Literal Addresses in URL's)
+      # RFC 2373 (IPv6 Addressing Architecture)
+
+      # alpha         = lowalpha | upalpha
+      ALPHA = "a-zA-Z"
+      # alphanum      = alpha | digit
+      ALNUM = "#{ALPHA}\\d"
+
+      # hex           = digit | "A" | "B" | "C" | "D" | "E" | "F" |
+      #                         "a" | "b" | "c" | "d" | "e" | "f"
+      HEX     = "a-fA-F\\d"
+      # escaped       = "%" hex hex
+      ESCAPED = "%[#{HEX}]{2}"
+      # mark          = "-" | "_" | "." | "!" | "~" | "*" | "'" |
+      #                 "(" | ")"
+      # unreserved    = alphanum | mark
+      UNRESERVED = "-_.!~*'()#{ALNUM}"
+      # reserved      = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
+      #                 "$" | ","
+      # reserved      = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | 
+      #                 "$" | "," | "[" | "]" (RFC 2732)
+      RESERVED = ";/?:@&=+$,\\[\\]"
+
+      # uric          = reserved | unreserved | escaped
+      URIC = "(?:[#{UNRESERVED}#{RESERVED}]|#{ESCAPED})"
+      # uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
+      #                 "&" | "=" | "+" | "$" | ","
+      URIC_NO_SLASH = "(?:[#{UNRESERVED};?:@&=+$,]|#{ESCAPED})"
+      # query         = *uric
+      QUERY = "#{URIC}*"
+      # fragment      = *uric
+      FRAGMENT = "#{URIC}*"
+
+      # domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
+      DOMLABEL = "(?:[#{ALNUM}](?:[-#{ALNUM}]*[#{ALNUM}])?)"
+      # toplabel      = alpha | alpha *( alphanum | "-" ) alphanum
+      TOPLABEL = "(?:[#{ALPHA}](?:[-#{ALNUM}]*[#{ALNUM}])?)"
+      # hostname      = *( domainlabel "." ) toplabel [ "." ]
+      HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?"
+
+      # RFC 2373, APPENDIX B:
+      # IPv6address = hexpart [ ":" IPv4address ]
+      # IPv4address   = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
+      # hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ]
+      # hexseq  = hex4 *( ":" hex4)
+      # hex4    = 1*4HEXDIG
+      #
+      # XXX: This definition has a flaw. "::" + IPv4address must be
+      # allowed too.  Here is a replacement.
+      #
+      # IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
+      IPV4ADDR = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"
+      # hex4     = 1*4HEXDIG
+      HEX4 = "[#{HEX}]{1,4}"
+      # lastpart = hex4 | IPv4address
+      LASTPART = "(?:#{HEX4}|#{IPV4ADDR})"
+      # hexseq1  = *( hex4 ":" ) hex4
+      HEXSEQ1 = "(?:#{HEX4}:)*#{HEX4}"
+      # hexseq2  = *( hex4 ":" ) lastpart
+      HEXSEQ2 = "(?:#{HEX4}:)*#{LASTPART}"
+      # IPv6address = hexseq2 | [ hexseq1 ] "::" [ hexseq2 ]
+      IPV6ADDR = "(?:#{HEXSEQ2}|(?:#{HEXSEQ1})?::(?:#{HEXSEQ2})?)"
+
+      # IPv6prefix  = ( hexseq1 | [ hexseq1 ] "::" [ hexseq1 ] ) "/" 1*2DIGIT
+      # unused
+
+      # ipv6reference = "[" IPv6address "]" (RFC 2732)
+      IPV6REF = "\\[#{IPV6ADDR}\\]"
+
+      # host          = hostname | IPv4address
+      # host          = hostname | IPv4address | IPv6reference (RFC 2732)
+      HOST = "(?:#{HOSTNAME}|#{IPV4ADDR}|#{IPV6REF})"
+      # port          = *digit
+      PORT = '\d*'
+      # hostport      = host [ ":" port ]
+      HOSTPORT = "#{HOST}(?::#{PORT})?"
+
+      # userinfo      = *( unreserved | escaped |
+      #                    ";" | ":" | "&" | "=" | "+" | "$" | "," )
+      USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})*"
+
+      # pchar         = unreserved | escaped |
+      #                 ":" | "@" | "&" | "=" | "+" | "$" | ","
+      PCHAR = "(?:[#{UNRESERVED}:@&=+$,]|#{ESCAPED})"
+      # param         = *pchar
+      PARAM = "#{PCHAR}*"
+      # segment       = *pchar *( ";" param )
+      SEGMENT = "#{PCHAR}*(?:;#{PARAM})*"
+      # path_segments = segment *( "/" segment )
+      PATH_SEGMENTS = "#{SEGMENT}(?:/#{SEGMENT})*"
+
+      # server        = [ [ userinfo "@" ] hostport ]
+      SERVER = "(?:#{USERINFO}@)?#{HOSTPORT}"
+      # reg_name      = 1*( unreserved | escaped | "$" | "," |
+      #                     ";" | ":" | "@" | "&" | "=" | "+" )
+      REG_NAME = "(?:[#{UNRESERVED}$,;+@&=+]|#{ESCAPED})+"
+      # authority     = server | reg_name
+      AUTHORITY = "(?:#{SERVER}|#{REG_NAME})"
+
+      # rel_segment   = 1*( unreserved | escaped |
+      #                     ";" | "@" | "&" | "=" | "+" | "$" | "," )
+      REL_SEGMENT = "(?:[#{UNRESERVED};@&=+$,]|#{ESCAPED})+"
+
+      # scheme        = alpha *( alpha | digit | "+" | "-" | "." )
+      SCHEME = "[#{ALPHA}][-+.#{ALPHA}\\d]*"
+
+      # abs_path      = "/"  path_segments
+      ABS_PATH = "/#{PATH_SEGMENTS}"
+      # rel_path      = rel_segment [ abs_path ]
+      REL_PATH = "#{REL_SEGMENT}(?:#{ABS_PATH})?"
+      # net_path      = "//" authority [ abs_path ]
+      NET_PATH   = "//#{AUTHORITY}(?:#{ABS_PATH})?"
+
+      # hier_part     = ( net_path | abs_path ) [ "?" query ]
+      HIER_PART   = "(?:#{NET_PATH}|#{ABS_PATH})(?:\\?(?:#{QUERY}))?"
+      # opaque_part   = uric_no_slash *uric
+      OPAQUE_PART = "#{URIC_NO_SLASH}#{URIC}*"
+
+      # absoluteURI   = scheme ":" ( hier_part | opaque_part )
+      ABS_URI   = "#{SCHEME}:(?:#{HIER_PART}|#{OPAQUE_PART})"
+      # relativeURI   = ( net_path | abs_path | rel_path ) [ "?" query ]
+      REL_URI = "(?:#{NET_PATH}|#{ABS_PATH}|#{REL_PATH})(?:\\?#{QUERY})?"
+
+      # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+      URI_REF = "(?:#{ABS_URI}|#{REL_URI})?(?:##{FRAGMENT})?"
+
+      # XXX:
+      X_ABS_URI = "
+        (#{PATTERN::SCHEME}):                     (?# 1: scheme)
+        (?:
+           (#{PATTERN::OPAQUE_PART})              (?# 2: opaque)
+        |
+           (?:(?:
+             //(?:
+                 (?:(?:(#{PATTERN::USERINFO})@)?  (?# 3: userinfo)
+                   (?:(#{PATTERN::HOST})(?::(\\d*))?))?(?# 4: host, 5: port)
+               |
+                 (#{PATTERN::REG_NAME})           (?# 6: registry)
+               )
+             |
+             (?!//))                              (?# XXX: '//' is the mark for hostport)
+             (#{PATTERN::ABS_PATH})?              (?# 7: path)
+           )(?:\\?(#{PATTERN::QUERY}))?           (?# 8: query)
+        )
+        (?:\\#(#{PATTERN::FRAGMENT}))?            (?# 9: fragment)
+      "
+      X_REL_URI = "
+        (?:
+          (?:
+            //
+            (?:
+              (?:(#{PATTERN::USERINFO})@)?       (?# 1: userinfo)
+                (#{PATTERN::HOST})?(?::(\\d*))?  (?# 2: host, 3: port)
+            |
+              (#{PATTERN::REG_NAME})             (?# 4: registry)
+            )
+          )
+        |
+          (#{PATTERN::REL_SEGMENT})              (?# 5: rel_segment)
+        )?
+        (#{PATTERN::ABS_PATH})?                  (?# 6: abs_path)
+        (?:\\?(#{PATTERN::QUERY}))?              (?# 7: query)
+        (?:\\#(#{PATTERN::FRAGMENT}))?           (?# 8: fragment)
+      "
+      # :startdoc:
+    end # PATTERN
+
+    # :stopdoc:
+
+    # for URI::split
+    ABS_URI = Regexp.new('^' + PATTERN::X_ABS_URI + '$', #'
+                         Regexp::EXTENDED, 'N').freeze
+    REL_URI = Regexp.new('^' + PATTERN::X_REL_URI + '$', #'
+                         Regexp::EXTENDED, 'N').freeze
+
+    # for URI::extract
+    URI_REF     = Regexp.new(PATTERN::URI_REF, false, 'N').freeze
+    ABS_URI_REF = Regexp.new(PATTERN::X_ABS_URI, Regexp::EXTENDED, 'N').freeze
+    REL_URI_REF = Regexp.new(PATTERN::X_REL_URI, Regexp::EXTENDED, 'N').freeze
+
+    # for URI::escape/unescape
+    ESCAPED = Regexp.new(PATTERN::ESCAPED, false, 'N').freeze
+    UNSAFE  = Regexp.new("[^#{PATTERN::UNRESERVED}#{PATTERN::RESERVED}]",
+                         false, 'N').freeze
+
+    # for Generic#initialize
+    SCHEME   = Regexp.new("^#{PATTERN::SCHEME}$", false, 'N').freeze #"
+    USERINFO = Regexp.new("^#{PATTERN::USERINFO}$", false, 'N').freeze #"
+    HOST     = Regexp.new("^#{PATTERN::HOST}$", false, 'N').freeze #"
+    PORT     = Regexp.new("^#{PATTERN::PORT}$", false, 'N').freeze #"
+    OPAQUE   = Regexp.new("^#{PATTERN::OPAQUE_PART}$", false, 'N').freeze #"
+    REGISTRY = Regexp.new("^#{PATTERN::REG_NAME}$", false, 'N').freeze #"
+    ABS_PATH = Regexp.new("^#{PATTERN::ABS_PATH}$", false, 'N').freeze #"
+    REL_PATH = Regexp.new("^#{PATTERN::REL_PATH}$", false, 'N').freeze #"
+    QUERY    = Regexp.new("^#{PATTERN::QUERY}$", false, 'N').freeze #"
+    FRAGMENT = Regexp.new("^#{PATTERN::FRAGMENT}$", false, 'N').freeze #"
+    # :startdoc:
+  end # REGEXP
+
+  module Util # :nodoc:
+    def make_components_hash(klass, array_hash)
+      tmp = {}
+      if array_hash.kind_of?(Array) &&
+          array_hash.size == klass.component.size - 1
+        klass.component[1..-1].each_index do |i|
+          begin
+            tmp[klass.component[i + 1]] = array_hash[i].clone
+          rescue TypeError
+            tmp[klass.component[i + 1]] = array_hash[i]
+          end
+        end
+
+      elsif array_hash.kind_of?(Hash)
+        array_hash.each do |key, value|
+          begin
+            tmp[key] = value.clone
+          rescue TypeError
+            tmp[key] = value
+          end
+        end
+      else
+        raise ArgumentError, 
+          "expected Array of or Hash of components of #{klass.to_s} (#{klass.component[1..-1].join(', ')})"
+      end
+      tmp[:scheme] = klass.to_s.sub(/\A.*::/, '').downcase
+
+      return tmp
+    end
+    module_function :make_components_hash
+  end
+
+  module Escape
+    include REGEXP
+
+    #
+    # == Synopsis
+    #
+    #   URI.escape(str [, unsafe])
+    #
+    # == Args
+    #
+    # +str+::
+    #   String to replaces in.
+    # +unsafe+::
+    #   Regexp that matches all symbols that must be replaced with codes.
+    #   By default uses <tt>REGEXP::UNSAFE</tt>.
+    #   When this argument is a String, it represents a character set.
+    #
+    # == Description
+    #
+    # Escapes the string, replacing all unsafe characters with codes.
+    #
+    # == Usage
+    #
+    #   require 'uri'
+    #
+    #   enc_uri = URI.escape("http://example.com/?a=\11\15")
+    #   p enc_uri
+    #   # => "http://example.com/?a=%09%0D"
+    #
+    #   p URI.unescape(enc_uri)
+    #   # => "http://example.com/?a=\t\r"
+    #
+    #   p URI.escape("@?@!", "!?")
+    #   # => "@%3F@%21"
+    #
+    def escape(str, unsafe = UNSAFE)
+      unless unsafe.kind_of?(Regexp)
+        # perhaps unsafe is String object
+        unsafe = Regexp.new("[#{Regexp.quote(unsafe)}]", false, 'N')
+      end
+      str.gsub(unsafe) do |us|
+        tmp = ''
+        us.each_byte do |uc|
+          tmp << sprintf('%%%02X', uc)
+        end
+        tmp
+      end
+    end
+    alias encode escape
+    #
+    # == Synopsis
+    #
+    #   URI.unescape(str)
+    #
+    # == Args
+    #
+    # +str+::
+    #   Unescapes the string.
+    #
+    # == Usage
+    #
+    #   require 'uri'
+    #
+    #   enc_uri = URI.escape("http://example.com/?a=\11\15")
+    #   p enc_uri
+    #   # => "http://example.com/?a=%09%0D"
+    #
+    #   p URI.unescape(enc_uri)
+    #   # => "http://example.com/?a=\t\r"
+    #
+    def unescape(str)
+      str.gsub(ESCAPED) do
+        $&[1,2].hex.chr
+      end
+    end
+    alias decode unescape
+  end
+
+  include REGEXP
+  extend Escape
+
+  @@schemes = {}
+  
+  #
+  # Base class for all URI exceptions.
+  #
+  class Error < StandardError; end
+  #
+  # Not a URI.
+  #
+  class InvalidURIError < Error; end
+  #
+  # Not a URI component.
+  #
+  class InvalidComponentError < Error; end
+  #
+  # URI is valid, bad usage is not.
+  #
+  class BadURIError < Error; end
+
+  #
+  # == Synopsis
+  #
+  #   URI::split(uri)
+  #
+  # == Args
+  #
+  # +uri+::
+  #   String with URI.
+  #
+  # == Description
+  #
+  # Splits the string on following parts and returns array with result:
+  #
+  #   * Scheme
+  #   * Userinfo
+  #   * Host
+  #   * Port
+  #   * Registry
+  #   * Path
+  #   * Opaque
+  #   * Query
+  #   * Fragment
+  # 
+  # == Usage
+  #
+  #   require 'uri'
+  #
+  #   p URI.split("http://www.ruby-lang.org/")
+  #   # => ["http", nil, "www.ruby-lang.org", nil, nil, "/", nil, nil, nil]
+  #
+  def self.split(uri)
+    case uri
+    when ''
+      # null uri
+
+    when ABS_URI
+      scheme, opaque, userinfo, host, port, 
+        registry, path, query, fragment = $~[1..-1]
+
+      # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+
+      # absoluteURI   = scheme ":" ( hier_part | opaque_part )
+      # hier_part     = ( net_path | abs_path ) [ "?" query ]
+      # opaque_part   = uric_no_slash *uric
+
+      # abs_path      = "/"  path_segments
+      # net_path      = "//" authority [ abs_path ]
+
+      # authority     = server | reg_name
+      # server        = [ [ userinfo "@" ] hostport ]
+
+      if !scheme
+        raise InvalidURIError, 
+          "bad URI(absolute but no scheme): #{uri}"
+      end
+      if !opaque && (!path && (!host && !registry))
+        raise InvalidURIError,
+          "bad URI(absolute but no path): #{uri}" 
+      end
+
+    when REL_URI
+      scheme = nil
+      opaque = nil
+
+      userinfo, host, port, registry, 
+        rel_segment, abs_path, query, fragment = $~[1..-1]
+      if rel_segment && abs_path
+        path = rel_segment + abs_path
+      elsif rel_segment
+        path = rel_segment
+      elsif abs_path
+        path = abs_path
+      end
+
+      # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+
+      # relativeURI   = ( net_path | abs_path | rel_path ) [ "?" query ]
+
+      # net_path      = "//" authority [ abs_path ]
+      # abs_path      = "/"  path_segments
+      # rel_path      = rel_segment [ abs_path ]
+
+      # authority     = server | reg_name
+      # server        = [ [ userinfo "@" ] hostport ]
+
+    else
+      raise InvalidURIError, "bad URI(is not URI?): #{uri}"
+    end
+
+    path = '' if !path && !opaque # (see RFC2396 Section 5.2)
+    ret = [
+      scheme, 
+      userinfo, host, port,         # X
+      registry,                        # X
+      path,                         # Y
+      opaque,                        # Y
+      query,
+      fragment
+    ]
+    return ret
+  end
+
+  #
+  # == Synopsis
+  #
+  #   URI::parse(uri_str)
+  #
+  # == Args
+  #
+  # +uri_str+::
+  #   String with URI.
+  #
+  # == Description
+  #
+  # Creates one of the URI's subclasses instance from the string.
+  #  
+  # == Raises
+  #
+  # URI::InvalidURIError
+  #   Raised if URI given is not a correct one.
+  #
+  # == Usage
+  #
+  #   require 'uri'
+  #
+  #   uri = URI.parse("http://www.ruby-lang.org/")
+  #   p uri
+  #   # => #<URI::HTTP:0x202281be URL:http://www.ruby-lang.org/>
+  #   p uri.scheme 
+  #   # => "http" 
+  #   p uri.host 
+  #   # => "www.ruby-lang.org" 
+  # 
+  def self.parse(uri)
+    scheme, userinfo, host, port, 
+      registry, path, opaque, query, fragment = self.split(uri)
+
+    if scheme && @@schemes.include?(scheme.upcase)
+      @@schemes[scheme.upcase].new(scheme, userinfo, host, port, 
+                                   registry, path, opaque, query, 
+                                   fragment)
+    else
+      Generic.new(scheme, userinfo, host, port, 
+                  registry, path, opaque, query, 
+                  fragment)
+    end
+  end
+
+  #
+  # == Synopsis
+  #
+  #   URI::join(str[, str, ...])
+  #
+  # == Args
+  #
+  # +str+::
+  #   String(s) to work with
+  #
+  # == Description
+  #
+  # Joins URIs.
+  #
+  # == Usage
+  #
+  #   require 'uri'
+  #
+  #   p URI.join("http://localhost/","main.rbx")
+  #   # => #<URI::HTTP:0x2022ac02 URL:http://localhost/main.rbx>
+  #
+  def self.join(*str)
+    u = self.parse(str[0])
+    str[1 .. -1].each do |x|
+      u = u.merge(x)
+    end
+    u
+  end
+
+  #
+  # == Synopsis
+  #
+  #   URI::extract(str[, schemes][,&blk])
+  #
+  # == Args
+  #
+  # +str+:: 
+  #   String to extract URIs from.
+  # +schemes+::
+  #   Limit URI matching to a specific schemes.
+  #
+  # == Description
+  #
+  # Extracts URIs from a string. If block given, iterates through all matched URIs.
+  # Returns nil if block given or array with matches.
+  #
+  # == Usage
+  #
+  #   require "uri"
+  #
+  #   URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.")
+  #   # => ["http://foo.example.com/bla", "mailto:test@example.com"]
+  #
+  def self.extract(str, schemes = nil, &block)
+    if block_given?
+      str.scan(regexp(schemes)) { yield $& }
+      nil
+    else
+      result = []
+      str.scan(regexp(schemes)) { result.push $& }
+      result
+    end
+  end
+
+  #
+  # == Synopsis
+  #
+  #   URI::regexp([match_schemes])
+  #
+  # == Args
+  #
+  # +match_schemes+:: 
+  #   Array of schemes. If given, resulting regexp matches to URIs
+  #   whose scheme is one of the match_schemes.
+  # 
+  # == Description
+  # Returns a Regexp object which matches to URI-like strings.
+  # The Regexp object returned by this method includes arbitrary
+  # number of capture group (parentheses).  Never rely on it's number.
+  # 
+  # == Usage
+  #
+  #   require 'uri'
+  #
+  #   # extract first URI from html_string
+  #   html_string.slice(URI.regexp)
+  # 
+  #   # remove ftp URIs
+  #   html_string.sub(URI.regexp(['ftp'])
+  # 
+  #   # You should not rely on the number of parentheses
+  #   html_string.scan(URI.regexp) do |*matches|
+  #     p $&
+  #   end
+  #
+  def self.regexp(schemes = nil)
+    unless schemes
+      ABS_URI_REF
+    else
+      /(?=#{Regexp.union(*schemes)}:)#{PATTERN::X_ABS_URI}/xn
+    end
+  end
+
+end
+
+module Kernel
+  # alias for URI.parse.
+  #
+  # This method is introduced at 1.8.2.
+  def URI(uri_str) # :doc:
+    URI.parse(uri_str)
+  end
+  module_function :URI
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/ftp.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/ftp.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/ftp.rb	(revision 18425)
@@ -0,0 +1,148 @@
+#
+# = uri/ftp.rb
+#
+# Author:: Akira Yamada <akira@ruby-lang.org>
+# License:: You can redistribute it and/or modify it under the same term as Ruby.
+# Revision:: $Id: ftp.rb 11757 2007-02-15 11:36:28Z knu $
+#
+
+require 'uri/generic'
+
+module URI
+
+  #
+  # RFC1738 section 3.2.
+  #
+  class FTP < Generic
+    DEFAULT_PORT = 21
+
+    COMPONENT = [
+      :scheme, 
+      :userinfo, :host, :port,
+      :path, :typecode
+    ].freeze
+    #
+    # Typecode is, "a", "i" or "d". 
+    # As for "a" the text, as for "i" binary, 
+    # as for "d" the directory is displayed. 
+    # "A" with the text, as for "i" being binary, 
+    # is because the respective data type was called ASCII and 
+    # IMAGE with the protocol of FTP.
+    #
+    TYPECODE = ['a', 'i', 'd'].freeze
+    TYPECODE_PREFIX = ';type='.freeze
+
+    def self.new2(user, password, host, port, path, 
+                  typecode = nil, arg_check = true)
+      typecode = nil if typecode.size == 0
+      if typecode && !TYPECODE.include?(typecode)
+        raise ArgumentError,
+          "bad typecode is specified: #{typecode}"
+      end
+
+      # do escape
+
+      self.new('ftp',
+               [user, password], 
+               host, port, nil, 
+               typecode ? path + TYPECODE_PREFIX + typecode : path, 
+               nil, nil, nil, arg_check)
+    end
+
+    #
+    # == Description
+    #
+    # Creates a new URI::FTP object from components of URI::FTP with
+    # check.  It is scheme, userinfo, host, port, path and typecode. It
+    # provided by an Array or a Hash. typecode is "a", "i" or "d".
+    #
+    def self.build(args)
+      tmp = Util::make_components_hash(self, args)
+
+      if tmp[:typecode]
+        if tmp[:typecode].size == 1
+          tmp[:typecode] = TYPECODE_PREFIX + tmp[:typecode] 
+        end
+        tmp[:path] << tmp[:typecode]
+      end
+
+      return super(tmp)
+    end
+
+    #
+    # == Description
+    #
+    # Create a new URI::FTP object from ``generic'' components with no
+    # check.
+    #
+    # == Usage
+    #
+    #   require 'uri'
+    #   p ftp = URI.parse("ftp://ftp.ruby-lang.org/pub/ruby/;type=d") 
+    #   # => #<URI::FTP:0x201fad08 URL:ftp://ftp.ruby-lang.org/pub/ruby/;type=d>
+    #   p ftp.typecode
+    #   # => "d"
+    #
+    def initialize(*arg)
+      super(*arg)
+      @typecode = nil
+      tmp = @path.index(TYPECODE_PREFIX)
+      if tmp
+        typecode = @path[tmp + TYPECODE_PREFIX.size..-1]
+        self.set_path(@path[0..tmp - 1])
+        
+        if arg[-1]
+          self.typecode = typecode
+        else
+          self.set_typecode(typecode)
+        end
+      end
+    end
+    attr_reader :typecode
+
+    def check_typecode(v)
+      if TYPECODE.include?(v)
+        return true
+      else
+        raise InvalidComponentError,
+          "bad typecode(expected #{TYPECODE.join(', ')}): #{v}"
+      end
+    end
+    private :check_typecode
+
+    def set_typecode(v)
+      @typecode = v
+    end
+    protected :set_typecode
+
+    def typecode=(typecode)
+      check_typecode(typecode)
+      set_typecode(typecode)
+      typecode
+    end
+
+    def merge(oth) # :nodoc:
+      tmp = super(oth)
+      if self != tmp
+        tmp.set_typecode(oth.typecode)
+      end
+
+      return tmp
+    end
+
+    def to_s
+      save_path = nil
+      if @typecode
+        save_path = @path
+        @path = @path + TYPECODE_PREFIX + @typecode
+      end
+      str = super
+      if @typecode
+        @path = save_path
+      end
+
+      return str
+    end
+  end
+  @@schemes['FTP'] = FTP
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/generic.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/generic.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/generic.rb	(revision 18425)
@@ -0,0 +1,1121 @@
+#
+# = uri/generic.rb
+#
+# Author:: Akira Yamada <akira@ruby-lang.org>
+# License:: You can redistribute it and/or modify it under the same term as Ruby.
+# Revision:: $Id: generic.rb 11751 2007-02-15 07:45:04Z knu $
+#
+
+require 'uri/common'
+
+module URI
+  
+  #
+  # Base class for all URI classes.
+  # Implements generic URI syntax as per RFC 2396.
+  #
+  class Generic
+    include URI
+    include REGEXP
+
+    DEFAULT_PORT = nil
+
+    #
+    # Returns default port
+    #
+    def self.default_port
+      self::DEFAULT_PORT
+    end
+
+    def default_port
+      self.class.default_port
+    end
+
+    COMPONENT = [
+      :scheme, 
+      :userinfo, :host, :port, :registry, 
+      :path, :opaque, 
+      :query, 
+      :fragment
+    ].freeze
+
+    #
+    # Components of the URI in the order.
+    #
+    def self.component
+      self::COMPONENT
+    end
+
+    USE_REGISTRY = false
+
+    #
+    # DOC: FIXME!
+    #
+    def self.use_registry
+      self::USE_REGISTRY
+    end
+
+    #
+    # == Synopsis
+    #
+    # See #new
+    #
+    # == Description
+    #
+    # At first, tries to create a new URI::Generic instance using
+    # URI::Generic::build. But, if exception URI::InvalidComponentError is raised, 
+    # then it URI::Escape.escape all URI components and tries again.
+    #
+    #
+    def self.build2(args)
+      begin
+        return self.build(args)
+      rescue InvalidComponentError
+        if args.kind_of?(Array)
+          return self.build(args.collect{|x| 
+            if x
+              URI.escape(x)
+            else
+              x
+            end
+          })
+        elsif args.kind_of?(Hash)
+          tmp = {}
+          args.each do |key, value|
+            tmp[key] = if value
+                URI.escape(value)
+              else
+                value
+              end
+          end
+          return self.build(tmp)
+        end
+      end
+    end
+
+    #
+    # == Synopsis
+    #
+    # See #new
+    #
+    # == Description
+    #
+    # Creates a new URI::Generic instance from components of URI::Generic
+    # with check.  Components are: scheme, userinfo, host, port, registry, path,
+    # opaque, query and fragment. You can provide arguments either by an Array or a Hash.
+    # See #new for hash keys to use or for order of array items.
+    #
+    def self.build(args)
+      if args.kind_of?(Array) &&
+          args.size == ::URI::Generic::COMPONENT.size
+        tmp = args
+      elsif args.kind_of?(Hash)
+        tmp = ::URI::Generic::COMPONENT.collect do |c|
+          if args.include?(c)
+            args[c]
+          else
+            nil
+          end
+        end
+      else
+        raise ArgumentError, 
+        "expected Array of or Hash of components of #{self.class} (#{self.class.component.join(', ')})"
+      end
+
+      tmp << true
+      return self.new(*tmp)
+    end
+    #
+    # == Args
+    #
+    # +scheme+::
+    #   Protocol scheme, i.e. 'http','ftp','mailto' and so on.
+    # +userinfo+::
+    #   User name and password, i.e. 'sdmitry:bla'
+    # +host+::
+    #   Server host name
+    # +port+::
+    #   Server port
+    # +registry+::
+    #   DOC: FIXME!
+    # +path+::
+    #   Path on server
+    # +opaque+::
+    #   DOC: FIXME!
+    # +query+::
+    #   Query data
+    # +fragment+::
+    #   A part of URI after '#' sign
+    # +arg_check+::
+    #   Check arguments [false by default]
+    #
+    # == Description
+    #
+    # Creates a new URI::Generic instance from ``generic'' components without check.
+    #
+    def initialize(scheme, 
+                   userinfo, host, port, registry, 
+                   path, opaque, 
+                   query, 
+                   fragment,
+                   arg_check = false)
+      @scheme = nil
+      @user = nil
+      @password = nil
+      @host = nil
+      @port = nil
+      @path = nil
+      @query = nil
+      @opaque = nil
+      @registry = nil
+      @fragment = nil
+
+      if arg_check
+        self.scheme = scheme
+        self.userinfo = userinfo
+        self.host = host
+        self.port = port
+        self.path = path
+        self.query = query
+        self.opaque = opaque
+        self.registry = registry
+        self.fragment = fragment
+      else
+        self.set_scheme(scheme)
+        self.set_userinfo(userinfo)
+        self.set_host(host)
+        self.set_port(port)
+        self.set_path(path)
+        self.set_query(query)
+        self.set_opaque(opaque)
+        self.set_registry(registry)
+        self.set_fragment(fragment)
+      end
+      if @registry && !self.class.use_registry
+        raise InvalidURIError, 
+          "the scheme #{@scheme} does not accept registry part: #{@registry} (or bad hostname?)"
+      end
+      
+      @scheme.freeze if @scheme
+      self.set_path('') if !@path && !@opaque # (see RFC2396 Section 5.2)
+      self.set_port(self.default_port) if self.default_port && !@port
+    end
+    attr_reader :scheme
+    attr_reader :host
+    attr_reader :port
+    attr_reader :registry
+    attr_reader :path
+    attr_reader :query
+    attr_reader :opaque
+    attr_reader :fragment
+
+    # replace self by other URI object
+    def replace!(oth)
+      if self.class != oth.class
+        raise ArgumentError, "expected #{self.class} object"
+      end
+
+      component.each do |c|
+        self.__send__("#{c}=", oth.__send__(c))
+      end
+    end
+    private :replace!
+
+    def component
+      self.class.component
+    end
+
+    def check_scheme(v)
+      if v && SCHEME !~ v
+        raise InvalidComponentError,
+          "bad component(expected scheme component): #{v}"
+      end
+
+      return true
+    end
+    private :check_scheme
+
+    def set_scheme(v)
+      @scheme = v
+    end
+    protected :set_scheme
+
+    def scheme=(v)
+      check_scheme(v)
+      set_scheme(v)
+      v
+    end
+
+    def check_userinfo(user, password = nil)
+      if !password
+        user, password = split_userinfo(user)
+      end
+      check_user(user)
+      check_password(password, user)
+
+      return true
+    end
+    private :check_userinfo
+
+    def check_user(v)
+      if @registry || @opaque
+        raise InvalidURIError, 
+          "can not set user with registry or opaque"
+      end
+
+      return v unless v
+
+      if USERINFO !~ v
+        raise InvalidComponentError,
+          "bad component(expected userinfo component or user component): #{v}"
+      end
+
+      return true
+    end
+    private :check_user
+
+    def check_password(v, user = @user)
+      if @registry || @opaque
+        raise InvalidURIError, 
+          "can not set password with registry or opaque"
+      end
+      return v unless v
+
+      if !user
+        raise InvalidURIError,
+          "password component depends user component"
+      end
+
+      if USERINFO !~ v
+        raise InvalidComponentError,
+          "bad component(expected user component): #{v}"
+      end
+
+      return true
+    end
+    private :check_password
+
+    #
+    # Sets userinfo, argument is string like 'name:pass'
+    #
+    def userinfo=(userinfo)
+      if userinfo.nil?
+        return nil
+      end
+      check_userinfo(*userinfo)
+      set_userinfo(*userinfo)
+      # returns userinfo
+    end
+
+    def user=(user)
+      check_user(user)
+      set_user(user)
+      # returns user
+    end
+    
+    def password=(password)
+      check_password(password)
+      set_password(password)
+      # returns password
+    end
+
+    def set_userinfo(user, password = nil)
+      unless password 
+        user, password = split_userinfo(user)
+      end
+      @user     = user
+      @password = password if password
+
+      [@user, @password]
+    end
+    protected :set_userinfo
+
+    def set_user(v)
+      set_userinfo(v, @password)
+      v
+    end
+    protected :set_user
+
+    def set_password(v)
+      @password = v
+      # returns v
+    end
+    protected :set_password
+
+    def split_userinfo(ui)
+      return nil, nil unless ui
+      user, password = ui.split(/:/, 2)
+
+      return user, password
+    end
+    private :split_userinfo
+
+    def escape_userpass(v)
+      v = URI.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/
+    end
+    private :escape_userpass
+
+    def userinfo
+      if @user.nil?
+        nil
+      elsif @password.nil?
+        @user
+      else
+        @user + ':' + @password
+      end
+    end
+
+    def user
+      @user
+    end
+
+    def password
+      @password
+    end
+
+    def check_host(v)
+      return v unless v
+
+      if @registry || @opaque
+        raise InvalidURIError, 
+          "can not set host with registry or opaque"
+      elsif HOST !~ v
+        raise InvalidComponentError,
+          "bad component(expected host component): #{v}"
+      end
+
+      return true
+    end
+    private :check_host
+
+    def set_host(v)
+      @host = v
+    end
+    protected :set_host
+
+    def host=(v)
+      check_host(v)
+      set_host(v)
+      v
+    end
+
+    def check_port(v)
+      return v unless v
+
+      if @registry || @opaque
+        raise InvalidURIError, 
+          "can not set port with registry or opaque"
+      elsif !v.kind_of?(Fixnum) && PORT !~ v
+        raise InvalidComponentError,
+          "bad component(expected port component): #{v}"
+      end
+
+      return true
+    end
+    private :check_port
+
+    def set_port(v)
+      unless !v || v.kind_of?(Fixnum)
+        if v.empty?
+          v = nil
+        else
+          v = v.to_i
+        end
+      end
+      @port = v
+    end
+    protected :set_port
+
+    def port=(v)
+      check_port(v)
+      set_port(v)
+      port
+    end
+
+    def check_registry(v)
+      return v unless v
+
+      # raise if both server and registry are not nil, because:
+      # authority     = server | reg_name
+      # server        = [ [ userinfo "@" ] hostport ]
+      if @host || @port || @user # userinfo = @user + ':' + @password
+        raise InvalidURIError, 
+          "can not set registry with host, port, or userinfo"
+      elsif v && REGISTRY !~ v
+        raise InvalidComponentError,
+          "bad component(expected registry component): #{v}"
+      end
+
+      return true
+    end
+    private :check_registry
+
+    def set_registry(v)
+      @registry = v
+    end
+    protected :set_registry
+
+    def registry=(v)
+      check_registry(v)
+      set_registry(v)
+      v
+    end
+
+    def check_path(v)
+      # raise if both hier and opaque are not nil, because:
+      # absoluteURI   = scheme ":" ( hier_part | opaque_part )
+      # hier_part     = ( net_path | abs_path ) [ "?" query ]
+      if v && @opaque
+        raise InvalidURIError, 
+          "path conflicts with opaque"
+      end
+
+      if @scheme
+        if v && v != '' && ABS_PATH !~ v
+          raise InvalidComponentError, 
+            "bad component(expected absolute path component): #{v}"
+        end
+      else
+        if v && v != '' && ABS_PATH !~ v && REL_PATH !~ v
+          raise InvalidComponentError, 
+            "bad component(expected relative path component): #{v}"
+        end
+      end
+
+      return true
+    end
+    private :check_path
+
+    def set_path(v)
+      @path = v
+    end
+    protected :set_path
+
+    def path=(v)
+      check_path(v)
+      set_path(v)
+      v
+    end
+
+    def check_query(v)
+      return v unless v
+
+      # raise if both hier and opaque are not nil, because:
+      # absoluteURI   = scheme ":" ( hier_part | opaque_part )
+      # hier_part     = ( net_path | abs_path ) [ "?" query ]
+      if @opaque
+        raise InvalidURIError, 
+          "query conflicts with opaque"
+      end
+
+      if v && v != '' && QUERY !~ v
+          raise InvalidComponentError, 
+            "bad component(expected query component): #{v}"
+        end
+
+      return true
+    end
+    private :check_query
+
+    def set_query(v)
+      @query = v
+    end
+    protected :set_query
+
+    def query=(v)
+      check_query(v)
+      set_query(v)
+      v
+    end
+
+    def check_opaque(v)
+      return v unless v
+
+      # raise if both hier and opaque are not nil, because:
+      # absoluteURI   = scheme ":" ( hier_part | opaque_part )
+      # hier_part     = ( net_path | abs_path ) [ "?" query ]
+      if @host || @port || @user || @path  # userinfo = @user + ':' + @password
+        raise InvalidURIError, 
+          "can not set opaque with host, port, userinfo or path"
+      elsif v && OPAQUE !~ v
+        raise InvalidComponentError,
+          "bad component(expected opaque component): #{v}"
+      end
+
+      return true
+    end
+    private :check_opaque
+
+    def set_opaque(v)
+      @opaque = v
+    end
+    protected :set_opaque
+
+    def opaque=(v)
+      check_opaque(v)
+      set_opaque(v)
+      v
+    end
+
+    def check_fragment(v)
+      return v unless v
+
+      if v && v != '' && FRAGMENT !~ v
+        raise InvalidComponentError, 
+          "bad component(expected fragment component): #{v}"
+      end
+
+      return true
+    end
+    private :check_fragment
+
+    def set_fragment(v)
+      @fragment = v
+    end
+    protected :set_fragment
+
+    def fragment=(v)
+      check_fragment(v)
+      set_fragment(v)
+      v
+    end
+
+    #
+    # Checks if URI has a path
+    #
+    def hierarchical?
+      if @path
+        true
+      else
+        false
+      end
+    end
+
+    #
+    # Checks if URI is an absolute one
+    #
+    def absolute?
+      if @scheme
+        true
+      else
+        false
+      end
+    end
+    alias absolute absolute?
+
+    #
+    # Checks if URI is relative
+    #
+    def relative?
+      !absolute?
+    end
+
+    def split_path(path)
+      path.split(%r{/+}, -1)
+    end
+    private :split_path
+
+    def merge_path(base, rel)
+      # RFC2396, Section 5.2, 5)
+      if rel[0] == ?/ #/
+        # RFC2396, Section 5.2, 5)
+        return rel
+
+      else
+        # RFC2396, Section 5.2, 6)
+        base_path = split_path(base)
+        rel_path  = split_path(rel)
+
+        # RFC2396, Section 5.2, 6), a)
+	base_path << '' if base_path.last == '..'
+	while i = base_path.index('..')
+	  base_path.slice!(i - 1, 2)
+        end
+        if base_path.empty?
+          base_path = [''] # keep '/' for root directory
+        else
+	  base_path.pop
+        end
+
+        # RFC2396, Section 5.2, 6), c)
+        # RFC2396, Section 5.2, 6), d)
+        rel_path.push('') if rel_path.last == '.' || rel_path.last == '..'
+        rel_path.delete('.')
+
+        # RFC2396, Section 5.2, 6), e)
+        tmp = []
+        rel_path.each do |x|
+          if x == '..' &&
+              !(tmp.empty? || tmp.last == '..')
+            tmp.pop
+          else
+            tmp << x
+          end
+        end
+
+        add_trailer_slash = true
+        while x = tmp.shift
+          if x == '..' && base_path.size > 1
+            # RFC2396, Section 4
+            # a .. or . in an absolute path has no special meaning
+            base_path.pop
+          else
+            # if x == '..'
+            #   valid absolute (but abnormal) path "/../..."
+            # else
+            #   valid absolute path
+            # end
+            base_path << x
+            tmp.each {|t| base_path << t}
+            add_trailer_slash = false
+            break
+          end
+        end
+        base_path.push('') if add_trailer_slash
+
+        return base_path.join('/')
+      end
+    end
+    private :merge_path
+
+    #
+    # == Args
+    #
+    # +oth+::
+    #    URI or String
+    #
+    # == Description
+    #
+    # Destructive form of #merge
+    #
+    # == Usage
+    #
+    #   require 'uri'
+    #
+    #   uri = URI.parse("http://my.example.com")
+    #   uri.merge!("/main.rbx?page=1")
+    #   p uri
+    #   # =>  #<URI::HTTP:0x2021f3b0 URL:http://my.example.com/main.rbx?page=1>
+    #
+    def merge!(oth)
+      t = merge(oth)
+      if self == t
+        nil
+      else
+        replace!(t)
+        self
+      end
+    end
+
+    #
+    # == Args
+    #
+    # +oth+::
+    #    URI or String
+    #
+    # == Description
+    #
+    # Merges two URI's.
+    #
+    # == Usage
+    #
+    #   require 'uri'
+    #
+    #   uri = URI.parse("http://my.example.com")
+    #   p uri.merge("/main.rbx?page=1")
+    #   # =>  #<URI::HTTP:0x2021f3b0 URL:http://my.example.com/main.rbx?page=1>
+    #
+    def merge(oth)
+      begin
+        base, rel = merge0(oth)
+      rescue
+        raise $!.class, $!.message
+      end
+
+      if base == rel
+        return base
+      end
+
+      authority = rel.userinfo || rel.host || rel.port
+
+      # RFC2396, Section 5.2, 2)
+      if (rel.path.nil? || rel.path.empty?) && !authority && !rel.query
+        base.set_fragment(rel.fragment) if rel.fragment
+        return base
+      end
+
+      base.set_query(nil)
+      base.set_fragment(nil)
+
+      # RFC2396, Section 5.2, 4)
+      if !authority
+        base.set_path(merge_path(base.path, rel.path)) if base.path && rel.path
+      else
+        # RFC2396, Section 5.2, 4)
+        base.set_path(rel.path) if rel.path
+      end
+
+      # RFC2396, Section 5.2, 7)
+      base.set_userinfo(rel.userinfo) if rel.userinfo
+      base.set_host(rel.host)         if rel.host
+      base.set_port(rel.port)         if rel.port
+      base.set_query(rel.query)       if rel.query
+      base.set_fragment(rel.fragment) if rel.fragment
+
+      return base
+    end # merge
+    alias + merge
+
+    # return base and rel.
+    # you can modify `base', but can not `rel'.
+    def merge0(oth)
+      case oth
+      when Generic
+      when String
+        oth = URI.parse(oth)
+      else
+        raise ArgumentError,
+          "bad argument(expected URI object or URI string)"
+      end
+
+      if self.relative? && oth.relative?
+        raise BadURIError, 
+          "both URI are relative"
+      end
+
+      if self.absolute? && oth.absolute?
+        #raise BadURIError, 
+        #  "both URI are absolute"
+        # hmm... should return oth for usability?
+        return oth, oth
+      end
+
+      if self.absolute?
+        return self.dup, oth
+      else
+        return oth, oth
+      end
+    end
+    private :merge0
+
+    def route_from_path(src, dst)
+      # RFC2396, Section 4.2
+      return '' if src == dst
+
+      src_path = split_path(src)
+      dst_path = split_path(dst)
+
+      # hmm... dst has abnormal absolute path, 
+      # like "/./", "/../", "/x/../", ...
+      if dst_path.include?('..') ||
+          dst_path.include?('.')
+        return dst.dup
+      end
+
+      src_path.pop
+
+      # discard same parts
+      while dst_path.first == src_path.first
+        break if dst_path.empty?
+
+        src_path.shift
+        dst_path.shift
+      end
+
+      tmp = dst_path.join('/')
+
+      # calculate
+      if src_path.empty?
+        if tmp.empty?
+          return './'
+        elsif dst_path.first.include?(':') # (see RFC2396 Section 5)
+          return './' + tmp
+        else
+          return tmp
+        end
+      end
+
+      return '../' * src_path.size + tmp
+    end
+    private :route_from_path
+
+    def route_from0(oth)
+      case oth
+      when Generic
+      when String
+        oth = URI.parse(oth)
+      else
+        raise ArgumentError,
+          "bad argument(expected URI object or URI string)"
+      end
+
+      if self.relative?
+        raise BadURIError, 
+          "relative URI: #{self}"
+      end
+      if oth.relative?
+        raise BadURIError, 
+          "relative URI: #{oth}"
+      end
+
+      if self.scheme != oth.scheme
+        return self, self.dup
+      end
+      rel = URI::Generic.new(nil, # it is relative URI
+                             self.userinfo, self.host, self.port, 
+                             self.registry, self.path, self.opaque,
+                             self.query, self.fragment)
+
+      if rel.userinfo != oth.userinfo ||
+          rel.host.to_s.downcase != oth.host.to_s.downcase ||
+          rel.port != oth.port
+	if self.userinfo.nil? && self.host.nil?
+	  return self, self.dup
+	end
+        rel.set_port(nil) if rel.port == oth.default_port
+        return rel, rel
+      end
+      rel.set_userinfo(nil)
+      rel.set_host(nil)
+      rel.set_port(nil)
+
+      if rel.path && rel.path == oth.path
+        rel.set_path('')
+        rel.set_query(nil) if rel.query == oth.query
+        return rel, rel
+      elsif rel.opaque && rel.opaque == oth.opaque
+        rel.set_opaque('')
+        rel.set_query(nil) if rel.query == oth.query
+        return rel, rel
+      end
+
+      # you can modify `rel', but can not `oth'.
+      return oth, rel
+    end
+    private :route_from0
+    #
+    # == Args
+    #
+    # +oth+::
+    #    URI or String
+    #
+    # == Description
+    #
+    # Calculates relative path from oth to self
+    #
+    # == Usage
+    #
+    #   require 'uri'
+    #
+    #   uri = URI.parse('http://my.example.com/main.rbx?page=1')
+    #   p uri.route_from('http://my.example.com')
+    #   #=> #<URI::Generic:0x20218858 URL:/main.rbx?page=1>
+    #
+    def route_from(oth)
+      # you can modify `rel', but can not `oth'.
+      begin
+        oth, rel = route_from0(oth)
+      rescue
+        raise $!.class, $!.message
+      end
+      if oth == rel
+        return rel
+      end
+
+      rel.set_path(route_from_path(oth.path, self.path))
+      if rel.path == './' && self.query
+        # "./?foo" -> "?foo"
+        rel.set_path('')
+      end
+
+      return rel
+    end
+
+    alias - route_from
+
+    #
+    # == Args
+    #
+    # +oth+::
+    #    URI or String
+    #
+    # == Description
+    #
+    # Calculates relative path to oth from self
+    #
+    # == Usage
+    #
+    #   require 'uri'
+    #
+    #   uri = URI.parse('http://my.example.com')
+    #   p uri.route_to('http://my.example.com/main.rbx?page=1')
+    #   #=> #<URI::Generic:0x2020c2f6 URL:/main.rbx?page=1>
+    #    
+    def route_to(oth)
+      case oth
+      when Generic
+      when String
+        oth = URI.parse(oth)
+      else
+        raise ArgumentError,
+          "bad argument(expected URI object or URI string)"
+      end
+
+      oth.route_from(self)
+    end
+
+    #
+    # Returns normalized URI
+    # 
+    def normalize
+      uri = dup
+      uri.normalize!
+      uri
+    end
+
+    #
+    # Destructive version of #normalize
+    #
+    def normalize!
+      if path && path == ''
+        set_path('/')
+      end
+      if host && host != host.downcase
+        set_host(self.host.downcase)
+      end        
+    end
+
+    def path_query
+      str = @path
+      if @query
+        str += '?' + @query
+      end
+      str
+    end
+    private :path_query
+
+    #
+    # Constructs String from URI
+    # 
+    def to_s
+      str = ''
+      if @scheme
+        str << @scheme
+        str << ':'
+      end
+
+      if @opaque
+        str << @opaque
+
+      else
+        if @registry
+          str << @registry
+        else
+          if @host
+            str << '//'
+          end
+          if self.userinfo
+            str << self.userinfo
+            str << '@'
+          end
+          if @host
+            str << @host
+          end
+          if @port && @port != self.default_port
+            str << ':'
+            str << @port.to_s
+          end
+        end
+
+        str << path_query
+      end
+
+      if @fragment
+        str << '#'
+        str << @fragment
+      end
+
+      str
+    end
+
+    #
+    # Compares to URI's
+    #
+    def ==(oth)
+      if self.class == oth.class
+        self.normalize.component_ary == oth.normalize.component_ary
+      else
+        false
+      end
+    end
+
+    def hash
+      self.component_ary.hash
+    end
+
+    def eql?(oth)
+      self.component_ary.eql?(oth.component_ary)
+    end
+
+=begin
+
+--- URI::Generic#===(oth)
+
+=end
+#    def ===(oth)
+#      raise NotImplementedError
+#    end
+
+=begin
+=end
+    def component_ary
+      component.collect do |x|
+        self.send(x)
+      end
+    end
+    protected :component_ary
+
+    # == Args
+    #
+    # +components+::
+    #    Multiple Symbol arguments defined in URI::HTTP
+    #
+    # == Description
+    #
+    # Selects specified components from URI
+    #
+    # == Usage
+    #
+    #   require 'uri'
+    #
+    #   uri = URI.parse('http://myuser:mypass@my.example.com/test.rbx')
+    #   p uri.select(:userinfo, :host, :path)
+    #   # => ["myuser:mypass", "my.example.com", "/test.rbx"]
+    #
+    def select(*components)
+      components.collect do |c|
+        if component.include?(c)
+          self.send(c)
+        else
+          raise ArgumentError, 
+            "expected of components of #{self.class} (#{self.class.component.join(', ')})"
+        end
+      end
+    end
+
+    def inspect
+      sprintf("#<%s:%#0x URL:%s>", self.class.to_s, self.object_id, self.to_s)
+    end
+
+    def coerce(oth)
+      case oth
+      when String
+        oth = URI.parse(oth)
+      else
+        super
+      end
+
+      return oth, self
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/http.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/http.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/http.rb	(revision 18425)
@@ -0,0 +1,100 @@
+#
+# = uri/http.rb
+#
+# Author:: Akira Yamada <akira@ruby-lang.org>
+# License:: You can redistribute it and/or modify it under the same term as Ruby.
+# Revision:: $Id: http.rb 11747 2007-02-15 02:41:45Z knu $
+#
+
+require 'uri/generic'
+
+module URI
+
+  #
+  # The syntax of HTTP URIs is defined in RFC1738 section 3.3.
+  #
+  # Note that the Ruby URI library allows HTTP URLs containing usernames and
+  # passwords. This is not legal as per the RFC, but used to be 
+  # supported in Internet Explorer 5 and 6, before the MS04-004 security 
+  # update. See <URL:http://support.microsoft.com/kb/834489>.
+  #
+  class HTTP < Generic
+    DEFAULT_PORT = 80
+
+    COMPONENT = [
+      :scheme, 
+      :userinfo, :host, :port, 
+      :path, 
+      :query, 
+      :fragment
+    ].freeze
+
+    #
+    # == Description
+    #
+    # Create a new URI::HTTP object from components, with syntax checking.
+    #
+    # The components accepted are userinfo, host, port, path, query and
+    # fragment.
+    #
+    # The components should be provided either as an Array, or as a Hash 
+    # with keys formed by preceding the component names with a colon. 
+    #
+    # If an Array is used, the components must be passed in the order
+    # [userinfo, host, port, path, query, fragment].
+    #
+    # Example:
+    #
+    #     newuri = URI::HTTP.build({:host => 'www.example.com', 
+    #       :path> => '/foo/bar'})
+    #
+    #     newuri = URI::HTTP.build([nil, "www.example.com", nil, "/path", 
+    #       "query", 'fragment'])
+    #
+    # Currently, if passed userinfo components this method generates 
+    # invalid HTTP URIs as per RFC 1738.
+    #
+    def self.build(args)
+      tmp = Util::make_components_hash(self, args)
+      return super(tmp)
+    end
+
+    #
+    # == Description
+    #
+    # Create a new URI::HTTP object from generic URI components as per
+    # RFC 2396. No HTTP-specific syntax checking (as per RFC 1738) is 
+    # performed.
+    #
+    # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, 
+    # +opaque+, +query+ and +fragment+, in that order.
+    #
+    # Example:
+    #
+    #     uri = URI::HTTP.new(['http', nil, "www.example.com", nil, "/path",
+    #       "query", 'fragment'])
+    #
+    def initialize(*arg)
+      super(*arg)
+    end
+
+    #
+    # == Description
+    #
+    # Returns the full path for an HTTP request, as required by Net::HTTP::Get.
+    #
+    # If the URI contains a query, the full path is URI#path + '?' + URI#query.
+    # Otherwise, the path is simply URI#path.
+    #
+    def request_uri
+      r = path_query
+      if r[0] != ?/
+        r = '/' + r
+      end
+
+      r
+    end
+  end
+
+  @@schemes['HTTP'] = HTTP
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/https.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/https.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/https.rb	(revision 18425)
@@ -0,0 +1,20 @@
+#
+# = uri/https.rb
+#
+# Author:: Akira Yamada <akira@ruby-lang.org>
+# License:: You can redistribute it and/or modify it under the same term as Ruby.
+# Revision:: $Id: https.rb 11747 2007-02-15 02:41:45Z knu $
+#
+
+require 'uri/http'
+
+module URI
+
+  # The default port for HTTPS URIs is 443, and the scheme is 'https:' rather
+  # than 'http:'. Other than that, HTTPS URIs are identical to HTTP URIs;
+  # see URI::HTTP.
+  class HTTPS < HTTP
+    DEFAULT_PORT = 443
+  end
+  @@schemes['HTTPS'] = HTTPS
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/ldap.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/ldap.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/ldap.rb	(revision 18425)
@@ -0,0 +1,190 @@
+#
+# = uri/ldap.rb
+#
+# Author:: 
+#  Takaaki Tateishi <ttate@jaist.ac.jp>
+#  Akira Yamada <akira@ruby-lang.org>
+# License:: 
+#   URI::LDAP is copyrighted free software by Takaaki Tateishi and Akira Yamada.
+#   You can redistribute it and/or modify it under the same term as Ruby.
+# Revision:: $Id: ldap.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+
+require 'uri/generic'
+
+module URI
+
+  #
+  # LDAP URI SCHEMA (described in RFC2255)
+  # ldap://<host>/<dn>[?<attrs>[?<scope>[?<filter>[?<extensions>]]]]
+  #
+  class LDAP < Generic
+
+    DEFAULT_PORT = 389
+    
+    COMPONENT = [
+      :scheme,
+      :host, :port,
+      :dn,
+      :attributes,
+      :scope,
+      :filter,
+      :extensions,
+    ].freeze
+
+    SCOPE = [
+      SCOPE_ONE = 'one',
+      SCOPE_SUB = 'sub',
+      SCOPE_BASE = 'base',
+    ].freeze
+
+    def self.build(args)
+      tmp = Util::make_components_hash(self, args)
+
+      if tmp[:dn]
+        tmp[:path] = tmp[:dn]
+      end
+
+      query = []
+      [:extensions, :filter, :scope, :attributes].collect do |x|
+        next if !tmp[x] && query.size == 0
+        query.unshift(tmp[x])
+      end
+
+      tmp[:query] = query.join('?')
+
+      return super(tmp)
+    end
+
+    def initialize(*arg)
+      super(*arg)
+
+      if @fragment
+        raise InvalidURIError, 'bad LDAP URL'
+      end
+
+      parse_dn
+      parse_query
+    end
+
+    def parse_dn
+      @dn = @path[1..-1]
+    end
+    private :parse_dn
+
+    def parse_query
+      @attributes = nil
+      @scope      = nil
+      @filter     = nil
+      @extensions = nil
+
+      if @query
+        attrs, scope, filter, extensions = @query.split('?')
+
+        @attributes = attrs if attrs && attrs.size > 0
+        @scope      = scope if scope && scope.size > 0
+        @filter     = filter if filter && filter.size > 0
+        @extensions = extensions if extensions && extensions.size > 0
+      end
+    end
+    private :parse_query
+
+    def build_path_query
+      @path = '/' + @dn
+
+      query = []
+      [@extensions, @filter, @scope, @attributes].each do |x|
+        next if !x && query.size == 0
+        query.unshift(x)
+      end
+      @query = query.join('?')
+    end
+    private :build_path_query
+
+    def dn
+      @dn
+    end
+
+    def set_dn(val)
+      @dn = val
+      build_path_query
+      @dn
+    end
+    protected :set_dn
+
+    def dn=(val)
+      set_dn(val)
+      val
+    end
+
+    def attributes
+      @attributes
+    end
+
+    def set_attributes(val)
+      @attributes = val
+      build_path_query
+      @attributes
+    end
+    protected :set_attributes
+
+    def attributes=(val)
+      set_attributes(val)
+      val
+    end
+
+    def scope
+      @scope
+    end
+
+    def set_scope(val)
+      @scope = val
+      build_path_query
+      @scope
+    end
+    protected :set_scope
+
+    def scope=(val)
+      set_scope(val)
+      val
+    end
+
+    def filter
+      @filter
+    end
+
+    def set_filter(val)
+      @filter = val
+      build_path_query
+      @filter
+    end
+    protected :set_filter
+
+    def filter=(val)
+      set_filter(val)
+      val
+    end
+
+    def extensions
+      @extensions
+    end
+
+    def set_extensions(val)
+      @extensions = val
+      build_path_query
+      @extensions
+    end
+    protected :set_extensions
+
+    def extensions=(val)
+      set_extensions(val)
+      val
+    end
+
+    def hierarchical?
+      false
+    end
+  end
+
+  @@schemes['LDAP'] = LDAP
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/mailto.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/mailto.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/uri/mailto.rb	(revision 18425)
@@ -0,0 +1,266 @@
+#
+# = uri/mailto.rb
+#
+# Author:: Akira Yamada <akira@ruby-lang.org>
+# License:: You can redistribute it and/or modify it under the same term as Ruby.
+# Revision:: $Id: mailto.rb 11747 2007-02-15 02:41:45Z knu $
+#
+
+require 'uri/generic'
+
+module URI
+
+  #
+  # RFC2368, The mailto URL scheme
+  #
+  class MailTo < Generic
+    include REGEXP
+
+    DEFAULT_PORT = nil
+
+    COMPONENT = [ :scheme, :to, :headers ].freeze
+
+    # :stopdoc:
+    #  "hname" and "hvalue" are encodings of an RFC 822 header name and
+    #  value, respectively. As with "to", all URL reserved characters must
+    #  be encoded.
+    #
+    #  "#mailbox" is as specified in RFC 822 [RFC822]. This means that it
+    #  consists of zero or more comma-separated mail addresses, possibly
+    #  including "phrase" and "comment" components. Note that all URL
+    #  reserved characters in "to" must be encoded: in particular,
+    #  parentheses, commas, and the percent sign ("%"), which commonly occur
+    #  in the "mailbox" syntax.
+    #
+    #  Within mailto URLs, the characters "?", "=", "&" are reserved.
+
+    # hname      =  *urlc
+    # hvalue     =  *urlc
+    # header     =  hname "=" hvalue
+    HEADER_PATTERN = "(?:[^?=&]*=[^?=&]*)".freeze
+    HEADER_REGEXP  = Regexp.new(HEADER_PATTERN, 'N').freeze
+    # headers    =  "?" header *( "&" header )
+    # to         =  #mailbox
+    # mailtoURL  =  "mailto:" [ to ] [ headers ]
+    MAILBOX_PATTERN = "(?:#{PATTERN::ESCAPED}|[^(),%?=&])".freeze
+    MAILTO_REGEXP = Regexp.new(" # :nodoc:
+      \\A
+      (#{MAILBOX_PATTERN}*?)                          (?# 1: to)
+      (?:
+        \\?
+        (#{HEADER_PATTERN}(?:\\&#{HEADER_PATTERN})*)  (?# 2: headers)
+      )?
+      (?:
+        \\#
+        (#{PATTERN::FRAGMENT})                        (?# 3: fragment)
+      )?
+      \\z
+    ", Regexp::EXTENDED, 'N').freeze
+    # :startdoc:
+
+    #
+    # == Description
+    #
+    # Creates a new URI::MailTo object from components, with syntax checking.
+    #
+    # Components can be provided as an Array or Hash. If an Array is used,
+    # the components must be supplied as [to, headers].
+    #
+    # If a Hash is used, the keys are the component names preceded by colons.
+    #
+    # The headers can be supplied as a pre-encoded string, such as 
+    # "subject=subscribe&cc=address", or as an Array of Arrays like
+    # [['subject', 'subscribe'], ['cc', 'address']]
+    #
+    # Examples:
+    # 
+    #    require 'uri'
+    #    
+    #    m1 = URI::MailTo.build(['joe@example.com', 'subject=Ruby'])
+    #    puts m1.to_s  ->  mailto:joe@example.com?subject=Ruby
+    #    
+    #    m2 = URI::MailTo.build(['john@example.com', [['Subject', 'Ruby'], ['Cc', 'jack@example.com']]])
+    #    puts m2.to_s  ->  mailto:john@example.com?Subject=Ruby&Cc=jack@example.com
+    #    
+    #    m3 = URI::MailTo.build({:to => 'listman@example.com', :headers => [['subject', 'subscribe']]})
+    #    puts m3.to_s  ->  mailto:listman@example.com?subject=subscribe
+    #
+    def self.build(args)
+      tmp = Util::make_components_hash(self, args)
+
+      if tmp[:to]
+        tmp[:opaque] = tmp[:to]
+      else
+        tmp[:opaque] = ''
+      end
+
+      if tmp[:headers]
+        tmp[:opaque] << '?'
+
+        if tmp[:headers].kind_of?(Array)
+          tmp[:opaque] << tmp[:headers].collect { |x|
+            if x.kind_of?(Array)
+              x[0] + '=' + x[1..-1].to_s
+            else
+              x.to_s
+            end
+          }.join('&')
+
+        elsif tmp[:headers].kind_of?(Hash)
+          tmp[:opaque] << tmp[:headers].collect { |h,v|
+            h + '=' + v
+          }.join('&')
+
+        else
+          tmp[:opaque] << tmp[:headers].to_s
+        end
+      end
+
+      return super(tmp)
+    end
+
+    #
+    # == Description
+    #
+    # Creates a new URI::MailTo object from generic URL components with
+    # no syntax checking.
+    #
+    # This method is usually called from URI::parse, which checks
+    # the validity of each component.
+    #
+    def initialize(*arg)
+      super(*arg)
+
+      @to = nil
+      @headers = []
+
+      if MAILTO_REGEXP =~ @opaque
+         if arg[-1]
+          self.to = $1
+          self.headers = $2
+        else
+          set_to($1)
+          set_headers($2)
+        end
+
+      else
+        raise InvalidComponentError,
+          "unrecognised opaque part for mailtoURL: #{@opaque}"
+      end
+    end
+
+    # The primary e-mail address of the URL, as a String
+    attr_reader :to
+
+    # E-mail headers set by the URL, as an Array of Arrays
+    attr_reader :headers
+
+    def check_to(v)
+      return true unless v
+      return true if v.size == 0
+
+      if OPAQUE !~ v || /\A#{MAILBOX_PATTERN}*\z/o !~ v
+        raise InvalidComponentError,
+          "bad component(expected opaque component): #{v}"
+      end
+
+      return true
+    end
+    private :check_to
+
+    def set_to(v)
+      @to = v
+    end
+    protected :set_to
+
+    def to=(v)
+      check_to(v)
+      set_to(v)
+      v
+    end
+
+    def check_headers(v)
+      return true unless v
+      return true if v.size == 0
+
+      if OPAQUE !~ v || 
+          /\A(#{HEADER_PATTERN}(?:\&#{HEADER_PATTERN})*)\z/o !~ v
+        raise InvalidComponentError,
+          "bad component(expected opaque component): #{v}"
+      end
+
+      return true
+    end
+    private :check_headers
+
+    def set_headers(v)
+      @headers = []
+      if v
+        v.scan(HEADER_REGEXP) do |x|
+          @headers << x.split(/=/o, 2)
+        end
+      end
+    end
+    protected :set_headers
+
+    def headers=(v)
+      check_headers(v)
+      set_headers(v)
+      v
+    end
+
+    def to_s
+      @scheme + ':' + 
+        if @to 
+          @to
+        else
+          ''
+        end + 
+        if @headers.size > 0
+          '?' + @headers.collect{|x| x.join('=')}.join('&')
+        else
+          ''
+        end +
+        if @fragment
+          '#' + @fragment
+        else
+          ''
+        end
+    end
+    
+    # Returns the RFC822 e-mail text equivalent of the URL, as a String.
+    #
+    # Example:
+    #
+    #   require 'uri'
+    #
+    #   uri = URI.parse("mailto:ruby-list@ruby-lang.org?Subject=subscribe&cc=myaddr")
+    #   uri.to_mailtext
+    #   # => "To: ruby-list@ruby-lang.org\nSubject: subscribe\nCc: myaddr\n\n\n"
+    #
+    def to_mailtext
+      to = URI::unescape(@to)
+      head = ''
+      body = ''
+      @headers.each do |x|
+        case x[0]
+        when 'body'
+          body = URI::unescape(x[1])
+        when 'to'
+          to << ', ' + URI::unescape(x[1])
+        else
+          head << URI::unescape(x[0]).capitalize + ': ' +
+            URI::unescape(x[1])  + "\n"
+        end
+      end
+
+      return "To: #{to}
+#{head}
+#{body}
+"
+    end
+    alias to_rfc822text to_mailtext
+  end
+
+  @@schemes['MAILTO'] = MailTo
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/weakref.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/weakref.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/weakref.rb	(revision 18425)
@@ -0,0 +1,100 @@
+require "delegate"
+
+# WeakRef is a class to represent a reference to an object that is not seen by
+# the tracing phase of the garbage collector.  This allows the referenced
+# object to be garbage collected as if nothing is referring to it. Because
+# WeakRef delegates method calls to the referenced object, it may be used in
+# place of that object, i.e. it is of the same duck type.
+#
+# Usage:
+#
+#   foo = Object.new
+#   foo = Object.new
+#   p foo.to_s			# original's class
+#   foo = WeakRef.new(foo)
+#   p foo.to_s			# should be same class
+#   ObjectSpace.garbage_collect
+#   p foo.to_s			# should raise exception (recycled)
+class WeakRef<Delegator
+
+  # RefError is raised if an object cannot be referenced by a WeakRef.
+  class RefError<StandardError
+  end
+
+  @@id_map =  {}                # obj -> [ref,...]
+  @@id_rev_map =  {}            # ref -> obj
+  @@final = lambda{|id|
+    __old_status = Thread.critical
+    Thread.critical = true
+    begin
+      rids = @@id_map[id]
+      if rids
+	for rid in rids
+	  @@id_rev_map.delete(rid)
+	end
+	@@id_map.delete(id)
+      end
+      rid = @@id_rev_map[id]
+      if rid
+	@@id_rev_map.delete(id)
+	@@id_map[rid].delete(id)
+	@@id_map.delete(rid) if @@id_map[rid].empty?
+      end
+    ensure
+      Thread.critical = __old_status
+    end
+  }
+
+  # Create a new WeakRef from +orig+.
+  def initialize(orig)
+    super
+    __setobj__(orig)
+  end
+
+  # Return the object this WeakRef references. Raises RefError if the object
+  # has been garbage collected.  The object returned is the object to which
+  # method calls are delegated (see Delegator).
+  def __getobj__
+    unless @@id_rev_map[self.__id__] == @__id
+      raise RefError, "Illegal Reference - probably recycled", caller(2)
+    end
+    begin
+      ObjectSpace._id2ref(@__id)
+    rescue RangeError
+      raise RefError, "Illegal Reference - probably recycled", caller(2)
+    end
+  end
+
+  def __setobj__(obj)
+    @__id = obj.__id__
+    __old_status = Thread.critical
+    begin
+      Thread.critical = true
+      unless @@id_rev_map.key?(self)
+        ObjectSpace.define_finalizer obj, @@final
+        ObjectSpace.define_finalizer self, @@final
+      end
+      @@id_map[@__id] = [] unless @@id_map[@__id]
+    ensure
+      Thread.critical = __old_status
+    end
+    @@id_map[@__id].push self.__id__
+    @@id_rev_map[self.__id__] = @__id
+  end
+
+  # Returns true if the referenced object still exists, and false if it has
+  # been garbage collected.
+  def weakref_alive?
+    @@id_rev_map[self.__id__] == @__id
+  end
+end
+
+if __FILE__ == $0
+  require 'thread'
+  foo = Object.new
+  p foo.to_s			# original's class
+  foo = WeakRef.new(foo)
+  p foo.to_s			# should be same class
+  ObjectSpace.garbage_collect
+  p foo.to_s			# should raise exception (recycled)
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick.rb	(revision 18425)
@@ -0,0 +1,29 @@
+#
+# WEBrick -- WEB server toolkit.
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: webrick.rb,v 1.12 2002/10/01 17:16:31 gotoyuzo Exp $
+
+require 'webrick/compat.rb'
+
+require 'webrick/version.rb'
+require 'webrick/config.rb'
+require 'webrick/log.rb'
+require 'webrick/server.rb'
+require 'webrick/utils.rb'
+require 'webrick/accesslog'
+
+require 'webrick/htmlutils.rb'
+require 'webrick/httputils.rb'
+require 'webrick/cookie.rb'
+require 'webrick/httpversion.rb'
+require 'webrick/httpstatus.rb'
+require 'webrick/httprequest.rb'
+require 'webrick/httpresponse.rb'
+require 'webrick/httpserver.rb'
+require 'webrick/httpservlet.rb'
+require 'webrick/httpauth.rb'
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/accesslog.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/accesslog.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/accesslog.rb	(revision 18425)
@@ -0,0 +1,67 @@
+#
+# accesslog.rb -- Access log handling utilities
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2002 keita yamaguchi
+# Copyright (c) 2002 Internet Programming with Ruby writers
+#
+# $IPR: accesslog.rb,v 1.1 2002/10/01 17:16:32 gotoyuzo Exp $
+
+module WEBrick
+  module AccessLog
+    class AccessLogError < StandardError; end
+
+    CLF_TIME_FORMAT     = "[%d/%b/%Y:%H:%M:%S %Z]"
+    COMMON_LOG_FORMAT   = "%h %l %u %t \"%r\" %s %b"
+    CLF                 = COMMON_LOG_FORMAT
+    REFERER_LOG_FORMAT  = "%{Referer}i -> %U"
+    AGENT_LOG_FORMAT    = "%{User-Agent}i"
+    COMBINED_LOG_FORMAT = "#{CLF} \"%{Referer}i\" \"%{User-agent}i\""
+
+    module_function
+
+    # This format specification is a subset of mod_log_config of Apache.
+    #   http://httpd.apache.org/docs/mod/mod_log_config.html#formats
+    def setup_params(config, req, res)
+      params = Hash.new("")
+      params["a"] = req.peeraddr[3]
+      params["b"] = res.sent_size
+      params["e"] = ENV
+      params["f"] = res.filename || ""
+      params["h"] = req.peeraddr[2]
+      params["i"] = req
+      params["l"] = "-"
+      params["m"] = req.request_method
+      params["n"] = req.attributes
+      params["o"] = res
+      params["p"] = req.port
+      params["q"] = req.query_string
+      params["r"] = req.request_line.sub(/\x0d?\x0a\z/o, '')
+      params["s"] = res.status       # won't support "%>s"
+      params["t"] = req.request_time
+      params["T"] = Time.now - req.request_time
+      params["u"] = req.user || "-"
+      params["U"] = req.unparsed_uri
+      params["v"] = config[:ServerName]
+      params
+    end
+
+    def format(format_string, params)
+      format_string.gsub(/\%(?:\{(.*?)\})?>?([a-zA-Z%])/){
+         param, spec = $1, $2
+         case spec[0]
+         when ?e, ?i, ?n, ?o
+           raise AccessLogError,
+             "parameter is required for \"#{spec}\"" unless param
+           params[spec][param] || "-"
+         when ?t
+           params[spec].strftime(param || CLF_TIME_FORMAT)
+         when ?%
+           "%"
+         else
+           params[spec]
+         end
+      }
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/cgi.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/cgi.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/cgi.rb	(revision 18425)
@@ -0,0 +1,257 @@
+#
+# cgi.rb -- Yet another CGI library
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $Id: cgi.rb 11708 2007-02-12 23:01:19Z shyouhei $
+
+require "webrick/httprequest"
+require "webrick/httpresponse"
+require "webrick/config"
+require "stringio"
+
+module WEBrick
+  class CGI
+    CGIError = Class.new(StandardError)
+
+    attr_reader :config, :logger
+
+    def initialize(*args)
+      if defined?(MOD_RUBY)
+        unless ENV.has_key?("GATEWAY_INTERFACE")
+          Apache.request.setup_cgi_env
+        end
+      end
+      if %r{HTTP/(\d+\.\d+)} =~ ENV["SERVER_PROTOCOL"]
+        httpv = $1
+      end
+      @config = WEBrick::Config::HTTP.dup.update(
+        :ServerSoftware => ENV["SERVER_SOFTWARE"] || "null",
+        :HTTPVersion    => HTTPVersion.new(httpv || "1.0"),
+        :RunOnCGI       => true,   # to detect if it runs on CGI.
+        :NPH            => false   # set true to run as NPH script.
+      )
+      if config = args.shift
+        @config.update(config)
+      end
+      @config[:Logger] ||= WEBrick::BasicLog.new($stderr)
+      @logger = @config[:Logger]
+      @options = args
+    end
+
+    def [](key)
+      @config[key]
+    end
+
+    def start(env=ENV, stdin=$stdin, stdout=$stdout)
+      sock = WEBrick::CGI::Socket.new(@config, env, stdin, stdout)
+      req = HTTPRequest.new(@config)
+      res = HTTPResponse.new(@config)
+      unless @config[:NPH] or defined?(MOD_RUBY)
+        def res.setup_header
+          unless @header["status"]
+            phrase = HTTPStatus::reason_phrase(@status)
+            @header["status"] = "#{@status} #{phrase}"
+          end
+          super
+        end
+        def res.status_line
+          ""
+        end
+      end
+
+      begin
+        req.parse(sock)
+        req.script_name = (env["SCRIPT_NAME"] || File.expand_path($0)).dup
+        req.path_info = (env["PATH_INFO"] || "").dup
+        req.query_string = env["QUERY_STRING"]
+        req.user = env["REMOTE_USER"]
+        res.request_method = req.request_method
+        res.request_uri = req.request_uri
+        res.request_http_version = req.http_version
+        res.keep_alive = req.keep_alive?
+        self.service(req, res)
+      rescue HTTPStatus::Error => ex
+        res.set_error(ex)
+      rescue HTTPStatus::Status => ex
+        res.status = ex.code
+      rescue Exception => ex 
+        @logger.error(ex)
+        res.set_error(ex, true)
+      ensure
+        req.fixup
+        if defined?(MOD_RUBY)
+          res.setup_header
+          Apache.request.status_line = "#{res.status} #{res.reason_phrase}"
+          Apache.request.status = res.status
+          table = Apache.request.headers_out
+          res.header.each{|key, val|
+            case key
+            when /^content-encoding$/i
+              Apache::request.content_encoding = val
+            when /^content-type$/i
+              Apache::request.content_type = val
+            else
+              table[key] = val.to_s
+            end
+          }
+          res.cookies.each{|cookie|
+            table.add("Set-Cookie", cookie.to_s)
+          }
+          Apache.request.send_http_header
+          res.send_body(sock)
+        else
+          res.send_response(sock)
+        end
+      end
+    end
+
+    def service(req, res)
+      method_name = "do_" + req.request_method.gsub(/-/, "_")
+      if respond_to?(method_name)
+        __send__(method_name, req, res)
+      else
+        raise HTTPStatus::MethodNotAllowed,
+              "unsupported method `#{req.request_method}'."
+      end
+    end
+
+    class Socket
+      include Enumerable
+
+      private
+  
+      def initialize(config, env, stdin, stdout)
+        @config = config
+        @env = env
+        @header_part = StringIO.new
+        @body_part = stdin
+        @out_port = stdout
+        @out_port.binmode
+  
+        @server_addr = @env["SERVER_ADDR"] || "0.0.0.0"
+        @server_name = @env["SERVER_NAME"]
+        @server_port = @env["SERVER_PORT"]
+        @remote_addr = @env["REMOTE_ADDR"]
+        @remote_host = @env["REMOTE_HOST"] || @remote_addr
+        @remote_port = @env["REMOTE_PORT"] || 0
+
+        begin
+          @header_part << request_line << CRLF
+          setup_header
+          @header_part << CRLF
+          @header_part.rewind
+        rescue Exception => ex
+          raise CGIError, "invalid CGI environment"
+        end
+      end
+
+      def request_line
+        meth = @env["REQUEST_METHOD"] || "GET"
+        unless url = @env["REQUEST_URI"]
+          url = (@env["SCRIPT_NAME"] || File.expand_path($0)).dup
+          url << @env["PATH_INFO"].to_s
+          url = WEBrick::HTTPUtils.escape_path(url)
+          if query_string = @env["QUERY_STRING"]
+            unless query_string.empty?
+              url << "?" << query_string
+            end
+          end
+        end
+        # we cannot get real HTTP version of client ;)
+        httpv = @config[:HTTPVersion]
+        return "#{meth} #{url} HTTP/#{httpv}"
+      end
+  
+      def setup_header
+        add_header("CONTENT_TYPE", "Content-Type")
+        add_header("CONTENT_LENGTH", "Content-length")
+        @env.each_key{|name|
+          if /^HTTP_(.*)/ =~ name
+            add_header(name, $1.gsub(/_/, "-"))
+          end
+        }
+      end
+  
+      def add_header(envname, hdrname)
+        if value = @env[envname]
+          unless value.empty?
+            @header_part << hdrname << ": " << value << CRLF
+          end
+        end
+      end
+
+      def input
+        @header_part.eof? ? @body_part : @header_part
+      end
+  
+      public
+  
+      def peeraddr
+        [nil, @remote_port, @remote_host, @remote_addr]
+      end
+  
+      def addr
+        [nil, @server_port, @server_name, @server_addr]
+      end
+  
+      def gets(eol=LF)
+        input.gets(eol)
+      end
+  
+      def read(size=nil)
+        input.read(size)
+      end
+
+      def each
+        input.each{|line| yield(line) }
+      end
+  
+      def <<(data)
+        @out_port << data
+      end
+
+      def cert
+        return nil unless defined?(OpenSSL)
+        if pem = @env["SSL_SERVER_CERT"]
+          OpenSSL::X509::Certificate.new(pem) unless pem.empty?
+        end
+      end
+
+      def peer_cert
+        return nil unless defined?(OpenSSL)
+        if pem = @env["SSL_CLIENT_CERT"]
+          OpenSSL::X509::Certificate.new(pem) unless pem.empty?
+        end
+      end
+
+      def peer_cert_chain
+        return nil unless defined?(OpenSSL)
+        if @env["SSL_CLIENT_CERT_CHAIN_0"]
+          keys = @env.keys
+          certs = keys.sort.collect{|k|
+            if /^SSL_CLIENT_CERT_CHAIN_\d+$/ =~ k
+              if pem = @env[k]
+                OpenSSL::X509::Certificate.new(pem) unless pem.empty?
+              end
+            end
+          }
+          certs.compact
+        end
+      end
+
+      def cipher
+        return nil unless defined?(OpenSSL)
+        if cipher = @env["SSL_CIPHER"]
+          ret = [ cipher ]
+          ret << @env["SSL_PROTOCOL"]
+          ret << @env["SSL_CIPHER_USEKEYSIZE"]
+          ret << @env["SSL_CIPHER_ALGKEYSIZE"]
+          ret
+        end
+      end
+    end
+  end 
+end  
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/compat.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/compat.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/compat.rb	(revision 18425)
@@ -0,0 +1,15 @@
+#
+# compat.rb -- cross platform compatibility
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2002 GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: compat.rb,v 1.6 2002/10/01 17:16:32 gotoyuzo Exp $
+
+module Errno
+  class EPROTO       < SystemCallError; end
+  class ECONNRESET   < SystemCallError; end
+  class ECONNABORTED < SystemCallError; end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/config.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/config.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/config.rb	(revision 18425)
@@ -0,0 +1,97 @@
+#
+# config.rb -- Default configurations.
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: config.rb,v 1.52 2003/07/22 19:20:42 gotoyuzo Exp $
+
+require 'webrick/version'
+require 'webrick/httpversion'
+require 'webrick/httputils'
+require 'webrick/utils'
+require 'webrick/log'
+
+module WEBrick
+  module Config
+    LIBDIR = File::dirname(__FILE__)
+
+    # for GenericServer
+    General = {
+      :ServerName     => Utils::getservername,
+      :BindAddress    => nil,   # "0.0.0.0" or "::" or nil
+      :Port           => nil,   # users MUST specifiy this!!
+      :MaxClients     => 100,   # maximum number of the concurrent connections
+      :ServerType     => nil,   # default: WEBrick::SimpleServer
+      :Logger         => nil,   # default: WEBrick::Log.new
+      :ServerSoftware => "WEBrick/#{WEBrick::VERSION} " +
+                         "(Ruby/#{RUBY_VERSION}/#{RUBY_RELEASE_DATE})",
+      :TempDir        => ENV['TMPDIR']||ENV['TMP']||ENV['TEMP']||'/tmp',
+      :DoNotListen    => false,
+      :StartCallback  => nil,
+      :StopCallback   => nil,
+      :AcceptCallback => nil,
+    }
+
+    # for HTTPServer, HTTPRequest, HTTPResponse ...
+    HTTP = General.dup.update(
+      :Port           => 80,
+      :RequestTimeout => 30,
+      :HTTPVersion    => HTTPVersion.new("1.1"),
+      :AccessLog      => nil,
+      :MimeTypes      => HTTPUtils::DefaultMimeTypes,
+      :DirectoryIndex => ["index.html","index.htm","index.cgi","index.rhtml"],
+      :DocumentRoot   => nil,
+      :DocumentRootOptions => { :FancyIndexing => true },
+      :RequestHandler => nil,
+      :RequestCallback => nil,  # alias of :RequestHandler
+      :ServerAlias    => nil,
+
+      # for HTTPProxyServer
+      :ProxyAuthProc  => nil,
+      :ProxyContentHandler => nil,
+      :ProxyVia       => true,
+      :ProxyTimeout   => true,
+      :ProxyURI       => nil,
+
+      :CGIInterpreter => nil,
+      :CGIPathEnv     => nil,
+
+      # workaround: if Request-URIs contain 8bit chars,
+      # they should be escaped before calling of URI::parse().
+      :Escape8bitURI  => false
+    )
+
+    FileHandler = {
+      :NondisclosureName => [".ht*", "*~"],
+      :FancyIndexing     => false,
+      :HandlerTable      => {},
+      :HandlerCallback   => nil,
+      :DirectoryCallback => nil,
+      :FileCallback      => nil,
+      :UserDir           => nil,  # e.g. "public_html"
+      :AcceptableLanguages => []  # ["en", "ja", ... ]
+    }
+
+    BasicAuth = {
+      :AutoReloadUserDB     => true,
+    }
+
+    DigestAuth = {
+      :Algorithm            => 'MD5-sess', # or 'MD5' 
+      :Domain               => nil,        # an array includes domain names.
+      :Qop                  => [ 'auth' ], # 'auth' or 'auth-int' or both.
+      :UseOpaque            => true,
+      :UseNextNonce         => false,
+      :CheckNc              => false,
+      :UseAuthenticationInfoHeader => true,
+      :AutoReloadUserDB     => true,
+      :NonceExpirePeriod    => 30*60,
+      :NonceExpireDelta     => 60,
+      :InternetExplorerHack => true,
+      :OperaHack            => true,
+    }
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/cookie.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/cookie.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/cookie.rb	(revision 18425)
@@ -0,0 +1,110 @@
+#
+# cookie.rb -- Cookie class
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: cookie.rb,v 1.16 2002/09/21 12:23:35 gotoyuzo Exp $
+
+require 'time'
+require 'webrick/httputils'
+
+module WEBrick
+  class Cookie
+
+    attr_reader :name
+    attr_accessor :value, :version
+    attr_accessor :domain, :path, :secure
+    attr_accessor :comment, :max_age
+    #attr_accessor :comment_url, :discard, :port
+
+    def initialize(name, value)
+      @name = name
+      @value = value
+      @version = 0     # Netscape Cookie
+
+      @domain = @path = @secure = @comment = @max_age =
+      @expires = @comment_url = @discard = @port = nil
+    end
+
+    def expires=(t)
+      @expires = t && (t.is_a?(Time) ? t.httpdate : t.to_s)
+    end
+
+    def expires
+      @expires && Time.parse(@expires)
+    end
+
+    def to_s
+      ret = ""
+      ret << @name << "=" << @value
+      ret << "; " << "Version=" << @version.to_s if @version > 0
+      ret << "; " << "Domain="  << @domain  if @domain
+      ret << "; " << "Expires=" << @expires if @expires
+      ret << "; " << "Max-Age=" << @max_age.to_s if @max_age
+      ret << "; " << "Comment=" << @comment if @comment
+      ret << "; " << "Path="    << @path if @path
+      ret << "; " << "Secure"   if @secure
+      ret
+    end
+
+    # Cookie::parse()
+    #   It parses Cookie field sent from the user agent.
+    def self.parse(str)
+      if str
+        ret = []
+        cookie = nil
+        ver = 0
+        str.split(/[;,]\s+/).each{|x|
+          key, val = x.split(/=/,2)
+          val = val ? HTTPUtils::dequote(val) : ""
+          case key
+          when "$Version"; ver = val.to_i
+          when "$Path";    cookie.path = val
+          when "$Domain";  cookie.domain = val
+          when "$Port";    cookie.port = val
+          else
+            ret << cookie if cookie
+            cookie = self.new(key, val)
+            cookie.version = ver
+          end
+        }
+        ret << cookie if cookie
+        ret
+      end
+    end
+
+    def self.parse_set_cookie(str)
+      cookie_elem = str.split(/;/)
+      first_elem = cookie_elem.shift
+      first_elem.strip!
+      key, value = first_elem.split(/=/, 2)
+      cookie = new(key, HTTPUtils.dequote(value))
+      cookie_elem.each{|pair|
+        pair.strip!
+        key, value = pair.split(/=/, 2)
+        if value
+          value = HTTPUtils.dequote(value.strip)
+        end
+        case key.downcase
+        when "domain"  then cookie.domain  = value
+        when "path"    then cookie.path    = value
+        when "expires" then cookie.expires = value
+        when "max-age" then cookie.max_age = Integer(value)
+        when "comment" then cookie.comment = value
+        when "version" then cookie.version = Integer(value)
+        when "secure"  then cookie.secure = true
+        end
+      }
+      return cookie
+    end
+
+    def self.parse_set_cookies(str)
+      return str.split(/,(?=[^;,]*=)|,$/).collect{|c|
+        parse_set_cookie(c)
+      }
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/htmlutils.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/htmlutils.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/htmlutils.rb	(revision 18425)
@@ -0,0 +1,25 @@
+#
+# htmlutils.rb -- HTMLUtils Module
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: htmlutils.rb,v 1.7 2002/09/21 12:23:35 gotoyuzo Exp $
+
+module WEBrick
+  module HTMLUtils
+
+    def escape(string)
+      str = string ? string.dup : ""
+      str.gsub!(/&/n, '&amp;')
+      str.gsub!(/\"/n, '&quot;')
+      str.gsub!(/>/n, '&gt;')
+      str.gsub!(/</n, '&lt;')
+      str
+    end
+    module_function :escape
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth.rb	(revision 18425)
@@ -0,0 +1,45 @@
+#
+# httpauth.rb -- HTTP access authentication
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: httpauth.rb,v 1.14 2003/07/22 19:20:42 gotoyuzo Exp $
+
+require 'webrick/httpauth/basicauth'
+require 'webrick/httpauth/digestauth'
+require 'webrick/httpauth/htpasswd'
+require 'webrick/httpauth/htdigest'
+require 'webrick/httpauth/htgroup'
+
+module WEBrick
+  module HTTPAuth
+    module_function
+
+    def _basic_auth(req, res, realm, req_field, res_field, err_type, block)
+      user = pass = nil
+      if /^Basic\s+(.*)/o =~ req[req_field]
+        userpass = $1
+        user, pass = userpass.unpack("m*")[0].split(":", 2)
+      end
+      if block.call(user, pass)
+        req.user = user
+        return
+      end
+      res[res_field] = "Basic realm=\"#{realm}\""
+      raise err_type
+    end
+
+    def basic_auth(req, res, realm, &block)
+      _basic_auth(req, res, realm, "Authorization", "WWW-Authenticate",
+                  HTTPStatus::Unauthorized, block)
+    end
+
+    def proxy_basic_auth(req, res, realm, &block)
+      _basic_auth(req, res, realm, "Proxy-Authorization", "Proxy-Authenticate",
+                  HTTPStatus::ProxyAuthenticationRequired, block)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/authenticator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/authenticator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/authenticator.rb	(revision 18425)
@@ -0,0 +1,79 @@
+#
+# httpauth/authenticator.rb -- Authenticator mix-in module.
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: authenticator.rb,v 1.3 2003/02/20 07:15:47 gotoyuzo Exp $
+
+module WEBrick
+  module HTTPAuth
+    module Authenticator
+      RequestField      = "Authorization"
+      ResponseField     = "WWW-Authenticate"
+      ResponseInfoField = "Authentication-Info"
+      AuthException     = HTTPStatus::Unauthorized
+      AuthScheme        = nil # must override by the derived class
+
+      attr_reader :realm, :userdb, :logger
+
+      private
+
+      def check_init(config)
+        [:UserDB, :Realm].each{|sym|
+          unless config[sym]
+            raise ArgumentError, "Argument #{sym.inspect} missing."
+          end
+        } 
+        @realm     = config[:Realm]
+        @userdb    = config[:UserDB]
+        @logger    = config[:Logger] || Log::new($stderr)
+        @reload_db = config[:AutoReloadUserDB]
+        @request_field   = self::class::RequestField
+        @response_field  = self::class::ResponseField
+        @resp_info_field = self::class::ResponseInfoField
+        @auth_exception  = self::class::AuthException
+        @auth_scheme     = self::class::AuthScheme
+      end
+
+      def check_scheme(req)
+        unless credentials = req[@request_field]
+          error("no credentials in the request.")
+          return nil 
+        end  
+        unless match = /^#{@auth_scheme}\s+/.match(credentials)
+          error("invalid scheme in %s.", credentials)
+          info("%s: %s", @request_field, credentials) if $DEBUG
+          return nil
+        end
+        return match.post_match
+      end
+
+      def log(meth, fmt, *args)
+        msg = format("%s %s: ", @auth_scheme, @realm)
+        msg << fmt % args
+        @logger.send(meth, msg)
+      end
+
+      def error(fmt, *args)
+        if @logger.error?
+          log(:error, fmt, *args)
+        end
+      end                             
+
+      def info(fmt, *args)
+        if @logger.info?
+          log(:info, fmt, *args)
+        end
+      end
+    end
+
+    module ProxyAuthenticator
+      RequestField  = "Proxy-Authorization"
+      ResponseField = "Proxy-Authenticate"
+      InfoField     = "Proxy-Authentication-Info"
+      AuthException = HTTPStatus::ProxyAuthenticationRequired
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/basicauth.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/basicauth.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/basicauth.rb	(revision 18425)
@@ -0,0 +1,65 @@
+#
+# httpauth/basicauth.rb -- HTTP basic access authentication
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: basicauth.rb,v 1.5 2003/02/20 07:15:47 gotoyuzo Exp $
+
+require 'webrick/config'
+require 'webrick/httpstatus'
+require 'webrick/httpauth/authenticator'
+
+module WEBrick
+  module HTTPAuth
+    class BasicAuth
+      include Authenticator
+
+      AuthScheme = "Basic"
+
+      def self.make_passwd(realm, user, pass)
+        pass ||= ""
+        pass.crypt(Utils::random_string(2))
+      end
+
+      attr_reader :realm, :userdb, :logger
+
+      def initialize(config, default=Config::BasicAuth)
+        check_init(config)
+        @config = default.dup.update(config)
+      end
+
+      def authenticate(req, res)
+        unless basic_credentials = check_scheme(req)
+          challenge(req, res)
+        end
+        userid, password = basic_credentials.unpack("m*")[0].split(":", 2) 
+        password ||= ""
+        if userid.empty?
+          error("user id was not given.")
+          challenge(req, res)
+        end
+        unless encpass = @userdb.get_passwd(@realm, userid, @reload_db)
+          error("%s: the user is not allowed.", userid)
+          challenge(req, res)
+        end
+        if password.crypt(encpass) != encpass
+          error("%s: password unmatch.", userid)
+          challenge(req, res)
+        end
+        info("%s: authentication succeeded.", userid)
+        req.user = userid
+      end
+
+      def challenge(req, res)
+        res[@response_field] = "#{@auth_scheme} realm=\"#{@realm}\""
+        raise @auth_exception
+      end
+    end
+
+    class ProxyBasicAuth < BasicAuth
+      include ProxyAuthenticator
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/digestauth.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/digestauth.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/digestauth.rb	(revision 18425)
@@ -0,0 +1,343 @@
+#
+# httpauth/digestauth.rb -- HTTP digest access authentication
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2003 Internet Programming with Ruby writers.
+# Copyright (c) 2003 H.M.
+#
+# The original implementation is provided by H.M.
+#   URL: http://rwiki.jin.gr.jp/cgi-bin/rw-cgi.rb?cmd=view;name=
+#        %C7%A7%BE%DA%B5%A1%C7%BD%A4%F2%B2%FE%C2%A4%A4%B7%A4%C6%A4%DF%A4%EB
+#
+# $IPR: digestauth.rb,v 1.5 2003/02/20 07:15:47 gotoyuzo Exp $
+
+require 'webrick/config'
+require 'webrick/httpstatus'
+require 'webrick/httpauth/authenticator'
+require 'digest/md5'
+require 'digest/sha1'
+
+module WEBrick
+  module HTTPAuth
+    class DigestAuth
+      include Authenticator
+
+      AuthScheme = "Digest"
+      OpaqueInfo = Struct.new(:time, :nonce, :nc)
+      attr_reader :algorithm, :qop
+
+      def self.make_passwd(realm, user, pass)
+        pass ||= ""
+        Digest::MD5::hexdigest([user, realm, pass].join(":"))
+      end
+
+      def initialize(config, default=Config::DigestAuth)
+        check_init(config)
+        @config                 = default.dup.update(config)
+        @algorithm              = @config[:Algorithm]
+        @domain                 = @config[:Domain]
+        @qop                    = @config[:Qop]
+        @use_opaque             = @config[:UseOpaque]
+        @use_next_nonce         = @config[:UseNextNonce]
+        @check_nc               = @config[:CheckNc]
+        @use_auth_info_header   = @config[:UseAuthenticationInfoHeader]
+        @nonce_expire_period    = @config[:NonceExpirePeriod]
+        @nonce_expire_delta     = @config[:NonceExpireDelta]
+        @internet_explorer_hack = @config[:InternetExplorerHack]
+        @opera_hack             = @config[:OperaHack]
+
+        case @algorithm
+        when 'MD5','MD5-sess'
+          @h = Digest::MD5
+        when 'SHA1','SHA1-sess'  # it is a bonus feature :-)
+          @h = Digest::SHA1
+        else
+          msg = format('Alogrithm "%s" is not supported.', @algorithm)
+          raise ArgumentError.new(msg)
+        end
+
+        @instance_key = hexdigest(self.__id__, Time.now.to_i, Process.pid)
+        @opaques = {}
+        @last_nonce_expire = Time.now
+        @mutex = Mutex.new
+      end
+
+      def authenticate(req, res)
+        unless result = @mutex.synchronize{ _authenticate(req, res) }
+          challenge(req, res)
+        end
+        if result == :nonce_is_stale
+          challenge(req, res, true)
+        end
+        return true
+      end
+
+      def challenge(req, res, stale=false)
+        nonce = generate_next_nonce(req)
+        if @use_opaque
+          opaque = generate_opaque(req)
+          @opaques[opaque].nonce = nonce
+        end
+
+        param = Hash.new
+        param["realm"]  = HTTPUtils::quote(@realm)
+        param["domain"] = HTTPUtils::quote(@domain.to_a.join(" ")) if @domain
+        param["nonce"]  = HTTPUtils::quote(nonce)
+        param["opaque"] = HTTPUtils::quote(opaque) if opaque
+        param["stale"]  = stale.to_s
+        param["algorithm"] = @algorithm
+        param["qop"]    = HTTPUtils::quote(@qop.to_a.join(",")) if @qop
+
+        res[@response_field] =
+          "#{@auth_scheme} " + param.map{|k,v| "#{k}=#{v}" }.join(", ")
+        info("%s: %s", @response_field, res[@response_field]) if $DEBUG
+        raise @auth_exception
+      end
+
+      private
+
+      MustParams = ['username','realm','nonce','uri','response']
+      MustParamsAuth = ['cnonce','nc']
+
+      def _authenticate(req, res)
+        unless digest_credentials = check_scheme(req)
+          return false
+        end
+
+        auth_req = split_param_value(digest_credentials)
+        if auth_req['qop'] == "auth" || auth_req['qop'] == "auth-int"
+          req_params = MustParams + MustParamsAuth
+        else
+          req_params = MustParams
+        end
+        req_params.each{|key|
+          unless auth_req.has_key?(key)
+            error('%s: parameter missing. "%s"', auth_req['username'], key)
+            raise HTTPStatus::BadRequest
+          end
+        }
+
+        if !check_uri(req, auth_req)
+          raise HTTPStatus::BadRequest  
+        end
+
+        if auth_req['realm'] != @realm  
+          error('%s: realm unmatch. "%s" for "%s"',
+                auth_req['username'], auth_req['realm'], @realm)
+          return false
+        end
+
+        auth_req['algorithm'] ||= 'MD5' 
+        if auth_req['algorithm'] != @algorithm &&
+           (@opera_hack && auth_req['algorithm'] != @algorithm.upcase)
+          error('%s: algorithm unmatch. "%s" for "%s"',
+                auth_req['username'], auth_req['algorithm'], @algorithm)
+          return false
+        end
+
+        if (@qop.nil? && auth_req.has_key?('qop')) ||
+           (@qop && (! @qop.member?(auth_req['qop'])))
+          error('%s: the qop is not allowed. "%s"',
+                auth_req['username'], auth_req['qop'])
+          return false
+        end
+
+        password = @userdb.get_passwd(@realm, auth_req['username'], @reload_db)
+        unless password
+          error('%s: the user is not allowd.', auth_req['username'])
+          return false
+        end
+
+        nonce_is_invalid = false
+        if @use_opaque
+          info("@opaque = %s", @opaque.inspect) if $DEBUG
+          if !(opaque = auth_req['opaque'])
+            error('%s: opaque is not given.', auth_req['username'])
+            nonce_is_invalid = true
+          elsif !(opaque_struct = @opaques[opaque])
+            error('%s: invalid opaque is given.', auth_req['username'])
+            nonce_is_invalid = true
+          elsif !check_opaque(opaque_struct, req, auth_req)
+            @opaques.delete(auth_req['opaque'])
+            nonce_is_invalid = true
+          end
+        elsif !check_nonce(req, auth_req)
+          nonce_is_invalid = true
+        end
+
+        if /-sess$/ =~ auth_req['algorithm'] ||
+           (@opera_hack && /-SESS$/ =~ auth_req['algorithm'])
+          ha1 = hexdigest(password, auth_req['nonce'], auth_req['cnonce'])
+        else
+          ha1 = password
+        end
+
+        if auth_req['qop'] == "auth" || auth_req['qop'] == nil
+          ha2 = hexdigest(req.request_method, auth_req['uri'])
+          ha2_res = hexdigest("", auth_req['uri'])
+        elsif auth_req['qop'] == "auth-int"
+          ha2 = hexdigest(req.request_method, auth_req['uri'],
+                          hexdigest(req.body))
+          ha2_res = hexdigest("", auth_req['uri'], hexdigest(res.body))
+        end
+
+        if auth_req['qop'] == "auth" || auth_req['qop'] == "auth-int"
+          param2 = ['nonce', 'nc', 'cnonce', 'qop'].map{|key|
+            auth_req[key]
+          }.join(':')
+          digest     = hexdigest(ha1, param2, ha2)
+          digest_res = hexdigest(ha1, param2, ha2_res)
+        else
+          digest     = hexdigest(ha1, auth_req['nonce'], ha2)
+          digest_res = hexdigest(ha1, auth_req['nonce'], ha2_res)
+        end
+
+        if digest != auth_req['response']
+          error("%s: digest unmatch.", auth_req['username'])
+          return false
+        elsif nonce_is_invalid
+          error('%s: digest is valid, but nonce is not valid.',
+                auth_req['username'])
+          return :nonce_is_stale
+        elsif @use_auth_info_header
+          auth_info = {
+            'nextnonce' => generate_next_nonce(req),
+            'rspauth'   => digest_res
+          }
+          if @use_opaque
+            opaque_struct.time  = req.request_time
+            opaque_struct.nonce = auth_info['nextnonce']
+            opaque_struct.nc    = "%08x" % (auth_req['nc'].hex + 1)
+          end
+          if auth_req['qop'] == "auth" || auth_req['qop'] == "auth-int"
+            ['qop','cnonce','nc'].each{|key|
+              auth_info[key] = auth_req[key]
+            }
+          end
+          res[@resp_info_field] = auth_info.keys.map{|key|
+            if key == 'nc'
+              key + '=' + auth_info[key]
+            else
+              key + "=" + HTTPUtils::quote(auth_info[key])
+            end
+          }.join(', ')
+        end
+        info('%s: authentication scceeded.', auth_req['username'])
+        req.user = auth_req['username']
+        return true
+      end
+
+      def split_param_value(string)
+        ret = {}
+        while string.size != 0
+          case string           
+          when /^\s*([\w\-\.\*\%\!]+)=\s*\"((\\.|[^\"])*)\"\s*,?/
+            key = $1
+            matched = $2
+            string = $'
+            ret[key] = matched.gsub(/\\(.)/, "\\1")
+          when /^\s*([\w\-\.\*\%\!]+)=\s*([^,\"]*),?/
+            key = $1
+            matched = $2
+            string = $'
+            ret[key] = matched.clone
+          when /^s*^,/
+            string = $'
+          else
+            break
+          end
+        end
+        ret
+      end
+
+      def generate_next_nonce(req)
+        now = "%012d" % req.request_time.to_i
+        pk  = hexdigest(now, @instance_key)[0,32]
+        nonce = [now + ":" + pk].pack("m*").chop # it has 60 length of chars.
+        nonce
+      end
+
+      def check_nonce(req, auth_req)
+        username = auth_req['username']
+        nonce = auth_req['nonce']
+
+        pub_time, pk = nonce.unpack("m*")[0].split(":", 2)
+        if (!pub_time || !pk)
+          error("%s: empty nonce is given", username)
+          return false
+        elsif (hexdigest(pub_time, @instance_key)[0,32] != pk)
+          error("%s: invalid private-key: %s for %s",
+                username, hexdigest(pub_time, @instance_key)[0,32], pk)
+          return false
+        end
+
+        diff_time = req.request_time.to_i - pub_time.to_i
+        if (diff_time < 0)
+          error("%s: difference of time-stamp is negative.", username)
+          return false
+        elsif diff_time > @nonce_expire_period
+          error("%s: nonce is expired.", username)
+          return false
+        end
+
+        return true
+      end
+
+      def generate_opaque(req)
+        @mutex.synchronize{
+          now = req.request_time
+          if now - @last_nonce_expire > @nonce_expire_delta
+            @opaques.delete_if{|key,val|
+              (now - val.time) > @nonce_expire_period
+            }
+            @last_nonce_expire = now
+          end
+          begin
+            opaque = Utils::random_string(16)
+          end while @opaques[opaque]
+          @opaques[opaque] = OpaqueInfo.new(now, nil, '00000001')
+          opaque
+        }
+      end
+
+      def check_opaque(opaque_struct, req, auth_req)
+        if (@use_next_nonce && auth_req['nonce'] != opaque_struct.nonce)
+          error('%s: nonce unmatched. "%s" for "%s"',
+                auth_req['username'], auth_req['nonce'], opaque_struct.nonce)
+          return false
+        elsif !check_nonce(req, auth_req)
+          return false
+        end
+        if (@check_nc && auth_req['nc'] != opaque_struct.nc)
+          error('%s: nc unmatched."%s" for "%s"',
+                auth_req['username'], auth_req['nc'], opaque_struct.nc)
+          return false
+        end
+        true
+      end
+
+      def check_uri(req, auth_req)
+        uri = auth_req['uri']
+        if uri != req.request_uri.to_s && uri != req.unparsed_uri &&
+           (@internet_explorer_hack && uri != req.path)
+          error('%s: uri unmatch. "%s" for "%s"', auth_req['username'], 
+                auth_req['uri'], req.request_uri.to_s)
+          return false
+        end
+        true
+      end
+
+      def hexdigest(*args)
+        @h.hexdigest(args.join(":"))
+      end
+    end
+
+    class ProxyDigestAuth < DigestAuth
+      include ProxyAuthenticator
+
+      def check_uri(req, auth_req)
+        return true
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/htdigest.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/htdigest.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/htdigest.rb	(revision 18425)
@@ -0,0 +1,91 @@
+#
+# httpauth/htdigest.rb -- Apache compatible htdigest file
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: htdigest.rb,v 1.4 2003/07/22 19:20:45 gotoyuzo Exp $
+
+require 'webrick/httpauth/userdb'
+require 'webrick/httpauth/digestauth'
+require 'tempfile'
+
+module WEBrick
+  module HTTPAuth
+    class Htdigest
+      include UserDB
+
+      def initialize(path)
+        @path = path
+        @mtime = Time.at(0)
+        @digest = Hash.new
+        @mutex = Mutex::new
+        @auth_type = DigestAuth
+        open(@path,"a").close unless File::exist?(@path)
+        reload
+      end
+
+      def reload
+        mtime = File::mtime(@path)
+        if mtime > @mtime
+          @digest.clear
+          open(@path){|io|
+            while line = io.gets
+              line.chomp!
+              user, realm, pass = line.split(/:/, 3)
+              unless @digest[realm]
+                @digest[realm] = Hash.new
+              end
+              @digest[realm][user] = pass
+            end
+          }
+          @mtime = mtime
+        end
+      end
+
+      def flush(output=nil)
+        output ||= @path
+        tmp = Tempfile.new("htpasswd", File::dirname(output))
+        begin
+          each{|item| tmp.puts(item.join(":")) }
+          tmp.close
+          File::rename(tmp.path, output)
+        rescue
+          tmp.close(true)
+        end
+      end
+
+      def get_passwd(realm, user, reload_db)
+        reload() if reload_db
+        if hash = @digest[realm]
+          hash[user]
+        end
+      end
+
+      def set_passwd(realm, user, pass)
+        @mutex.synchronize{
+          unless @digest[realm]
+            @digest[realm] = Hash.new
+          end
+          @digest[realm][user] = make_passwd(realm, user, pass)
+        }
+      end
+
+      def delete_passwd(realm, user)
+        if hash = @digest[realm]
+          hash.delete(user)
+        end
+      end
+
+      def each
+        @digest.keys.sort.each{|realm|
+          hash = @digest[realm]
+          hash.keys.sort.each{|user|
+            yield([user, realm, hash[user]])
+          }
+        }
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/htgroup.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/htgroup.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/htgroup.rb	(revision 18425)
@@ -0,0 +1,61 @@
+#
+# httpauth/htgroup.rb -- Apache compatible htgroup file
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: htgroup.rb,v 1.1 2003/02/16 22:22:56 gotoyuzo Exp $
+
+require 'tempfile'
+
+module WEBrick
+  module HTTPAuth
+    class Htgroup
+      def initialize(path)
+        @path = path
+        @mtime = Time.at(0)
+        @group = Hash.new
+        open(@path,"a").close unless File::exist?(@path)
+        reload
+      end
+
+      def reload
+        if (mtime = File::mtime(@path)) > @mtime
+          @group.clear
+          open(@path){|io|
+            while line = io.gets
+              line.chomp!
+              group, members = line.split(/:\s*/)
+              @group[group] = members.split(/\s+/)
+            end
+          }
+          @mtime = mtime
+        end
+      end
+
+      def flush(output=nil)
+        output ||= @path
+        tmp = Tempfile.new("htgroup", File::dirname(output))
+        begin
+          @group.keys.sort.each{|group|
+            tmp.puts(format("%s: %s", group, self.members(group).join(" ")))
+          }
+          tmp.close
+          File::rename(tmp.path, output)
+        rescue
+          tmp.close(true)
+        end
+      end
+
+      def members(group)
+        reload
+        @group[group] || []
+      end
+
+      def add(group, members)
+        @group[group] = members(group) | members
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/htpasswd.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/htpasswd.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/htpasswd.rb	(revision 18425)
@@ -0,0 +1,83 @@
+#
+# httpauth/htpasswd -- Apache compatible htpasswd file
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: htpasswd.rb,v 1.4 2003/07/22 19:20:45 gotoyuzo Exp $
+
+require 'webrick/httpauth/userdb'
+require 'webrick/httpauth/basicauth'
+require 'tempfile'
+
+module WEBrick
+  module HTTPAuth
+    class Htpasswd
+      include UserDB
+
+      def initialize(path)
+        @path = path
+        @mtime = Time.at(0)
+        @passwd = Hash.new
+        @auth_type = BasicAuth
+        open(@path,"a").close unless File::exist?(@path)
+        reload
+      end
+
+      def reload
+        mtime = File::mtime(@path)
+        if mtime > @mtime
+          @passwd.clear
+          open(@path){|io|
+            while line = io.gets
+              line.chomp!
+              case line
+              when %r!\A[^:]+:[a-zA-Z0-9./]{13}\z!
+                user, pass = line.split(":")
+              when /:\$/, /:\{SHA\}/
+                raise NotImplementedError,
+                      'MD5, SHA1 .htpasswd file not supported'
+              else
+                raise StandardError, 'bad .htpasswd file'
+              end
+              @passwd[user] = pass
+            end
+          }
+          @mtime = mtime
+        end
+      end
+
+      def flush(output=nil)
+        output ||= @path
+        tmp = Tempfile.new("htpasswd", File::dirname(output))
+        begin
+          each{|item| tmp.puts(item.join(":")) }
+          tmp.close
+          File::rename(tmp.path, output)
+        rescue
+          tmp.close(true)
+        end
+      end
+
+      def get_passwd(realm, user, reload_db)
+        reload() if reload_db
+        @passwd[user]
+      end
+
+      def set_passwd(realm, user, pass)
+        @passwd[user] = make_passwd(realm, user, pass)
+      end
+
+      def delete_passwd(realm, user)
+        @passwd.delete(user)
+      end
+
+      def each
+        @passwd.keys.sort.each{|user|
+          yield([user, @passwd[user]])
+        }
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/userdb.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/userdb.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpauth/userdb.rb	(revision 18425)
@@ -0,0 +1,29 @@
+#
+# httpauth/userdb.rb -- UserDB mix-in module.
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: userdb.rb,v 1.2 2003/02/20 07:15:48 gotoyuzo Exp $
+
+module WEBrick
+  module HTTPAuth
+    module UserDB
+      attr_accessor :auth_type # BasicAuth or DigestAuth
+
+      def make_passwd(realm, user, pass)
+        @auth_type::make_passwd(realm, user, pass)
+      end
+
+      def set_passwd(realm, user, pass)
+        self[user] = pass
+      end                             
+
+      def get_passwd(realm, user, reload_db=false)
+        # reload_db is dummy
+        make_passwd(realm, user, self[user])
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpproxy.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpproxy.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpproxy.rb	(revision 18425)
@@ -0,0 +1,254 @@
+#
+# httpproxy.rb -- HTTPProxy Class
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2002 GOTO Kentaro
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: httpproxy.rb,v 1.18 2003/03/08 18:58:10 gotoyuzo Exp $
+# $kNotwork: straw.rb,v 1.3 2002/02/12 15:13:07 gotoken Exp $
+
+require "webrick/httpserver"
+require "net/http"
+
+Net::HTTP::version_1_2 if RUBY_VERSION < "1.7"
+
+module WEBrick
+  NullReader = Object.new
+  class << NullReader
+    def read(*args)
+      nil
+    end
+    alias gets read
+  end
+
+  class HTTPProxyServer < HTTPServer
+    def initialize(config)
+      super
+      c = @config
+      @via = "#{c[:HTTPVersion]} #{c[:ServerName]}:#{c[:Port]}"
+    end
+
+    def service(req, res)
+      if req.request_method == "CONNECT"
+        proxy_connect(req, res)
+      elsif req.unparsed_uri =~ %r!^http://!
+        proxy_service(req, res)
+      else
+        super(req, res)
+      end
+    end
+
+    def proxy_auth(req, res)
+      if proc = @config[:ProxyAuthProc]
+        proc.call(req, res)
+      end
+      req.header.delete("proxy-authorization")
+    end
+
+    # Some header fields shuold not be transfered.
+    HopByHop = %w( connection keep-alive proxy-authenticate upgrade
+                   proxy-authorization te trailers transfer-encoding )
+    ShouldNotTransfer = %w( set-cookie proxy-connection )
+    def split_field(f) f ? f.split(/,\s+/).collect{|i| i.downcase } : [] end
+
+    def choose_header(src, dst)
+      connections = split_field(src['connection'])
+      src.each{|key, value|
+        key = key.downcase
+        if HopByHop.member?(key)          || # RFC2616: 13.5.1
+           connections.member?(key)       || # RFC2616: 14.10
+           ShouldNotTransfer.member?(key)    # pragmatics
+          @logger.debug("choose_header: `#{key}: #{value}'")
+          next
+        end
+        dst[key] = value
+      }
+    end
+
+    # Net::HTTP is stupid about the multiple header fields.
+    # Here is workaround:
+    def set_cookie(src, dst)
+      if str = src['set-cookie']
+        cookies = []
+        str.split(/,\s*/).each{|token|
+          if /^[^=]+;/o =~ token
+            cookies[-1] << ", " << token
+          elsif /=/o =~ token
+            cookies << token
+          else
+            cookies[-1] << ", " << token
+          end
+        }
+        dst.cookies.replace(cookies)
+      end
+    end
+
+    def set_via(h)
+      if @config[:ProxyVia]
+        if  h['via']
+          h['via'] << ", " << @via
+        else
+          h['via'] = @via
+        end
+      end
+    end
+
+    def proxy_uri(req, res)
+      @config[:ProxyURI]
+    end
+
+    def proxy_service(req, res)
+      # Proxy Authentication
+      proxy_auth(req, res)      
+
+      # Create Request-URI to send to the origin server
+      uri  = req.request_uri
+      path = uri.path.dup
+      path << "?" << uri.query if uri.query
+
+      # Choose header fields to transfer
+      header = Hash.new
+      choose_header(req, header)
+      set_via(header)
+
+      # select upstream proxy server
+      if proxy = proxy_uri(req, res)
+        proxy_host = proxy.host
+        proxy_port = proxy.port
+        if proxy.userinfo
+          credentials = "Basic " + [proxy.userinfo].pack("m*")
+          credentials.chomp!
+          header['proxy-authorization'] = credentials
+        end
+      end
+
+      response = nil
+      begin
+        http = Net::HTTP.new(uri.host, uri.port, proxy_host, proxy_port)
+        http.start{
+          if @config[:ProxyTimeout]
+            ##################################   these issues are 
+            http.open_timeout = 30   # secs  #   necessary (maybe bacause
+            http.read_timeout = 60   # secs  #   Ruby's bug, but why?)
+            ##################################
+          end
+          case req.request_method
+          when "GET"  then response = http.get(path, header)
+          when "POST" then response = http.post(path, req.body || "", header)
+          when "HEAD" then response = http.head(path, header)
+          else
+            raise HTTPStatus::MethodNotAllowed,
+              "unsupported method `#{req.request_method}'."
+          end
+        }
+      rescue => err
+        logger.debug("#{err.class}: #{err.message}")
+        raise HTTPStatus::ServiceUnavailable, err.message
+      end
+  
+      # Persistent connction requirements are mysterious for me.
+      # So I will close the connection in every response.
+      res['proxy-connection'] = "close"
+      res['connection'] = "close"
+
+      # Convert Net::HTTP::HTTPResponse to WEBrick::HTTPProxy
+      res.status = response.code.to_i
+      choose_header(response, res)
+      set_cookie(response, res)
+      set_via(res)
+      res.body = response.body
+
+      # Process contents
+      if handler = @config[:ProxyContentHandler]
+        handler.call(req, res)
+      end
+    end
+
+    def proxy_connect(req, res)
+      # Proxy Authentication
+      proxy_auth(req, res)
+
+      ua = Thread.current[:WEBrickSocket]  # User-Agent
+      raise HTTPStatus::InternalServerError,
+        "[BUG] cannot get socket" unless ua
+
+      host, port = req.unparsed_uri.split(":", 2)
+      # Proxy authentication for upstream proxy server
+      if proxy = proxy_uri(req, res)
+        proxy_request_line = "CONNECT #{host}:#{port} HTTP/1.0"
+        if proxy.userinfo
+          credentials = "Basic " + [proxy.userinfo].pack("m*")
+          credentials.chomp!
+        end
+        host, port = proxy.host, proxy.port
+      end
+
+      begin
+        @logger.debug("CONNECT: upstream proxy is `#{host}:#{port}'.")
+        os = TCPSocket.new(host, port)     # origin server
+
+        if proxy
+          @logger.debug("CONNECT: sending a Request-Line")
+          os << proxy_request_line << CRLF
+          @logger.debug("CONNECT: > #{proxy_request_line}")
+          if credentials
+            @logger.debug("CONNECT: sending a credentials")
+            os << "Proxy-Authorization: " << credentials << CRLF
+          end
+          os << CRLF
+          proxy_status_line = os.gets(LF)
+          @logger.debug("CONNECT: read a Status-Line form the upstream server")
+          @logger.debug("CONNECT: < #{proxy_status_line}")
+          if %r{^HTTP/\d+\.\d+\s+200\s*} =~ proxy_status_line
+            while line = os.gets(LF)
+              break if /\A(#{CRLF}|#{LF})\z/om =~ line
+            end
+          else
+            raise HTTPStatus::BadGateway
+          end
+        end
+        @logger.debug("CONNECT #{host}:#{port}: succeeded")
+        res.status = HTTPStatus::RC_OK
+      rescue => ex
+        @logger.debug("CONNECT #{host}:#{port}: failed `#{ex.message}'")
+        res.set_error(ex)
+        raise HTTPStatus::EOFError
+      ensure
+        if handler = @config[:ProxyContentHandler]
+          handler.call(req, res)
+        end
+        res.send_response(ua)
+        access_log(@config, req, res)
+
+        # Should clear request-line not to send the sesponse twice.
+        # see: HTTPServer#run
+        req.parse(NullReader) rescue nil
+      end
+
+      begin
+        while fds = IO::select([ua, os])
+          if fds[0].member?(ua)
+            buf = ua.sysread(1024);
+            @logger.debug("CONNECT: #{buf.size} byte from User-Agent")
+            os.syswrite(buf)
+          elsif fds[0].member?(os)
+            buf = os.sysread(1024);
+            @logger.debug("CONNECT: #{buf.size} byte from #{host}:#{port}")
+            ua.syswrite(buf)
+          end
+        end
+      rescue => ex
+        os.close
+        @logger.debug("CONNECT #{host}:#{port}: closed")
+      end
+
+      raise HTTPStatus::EOFError
+    end
+
+    def do_OPTIONS(req, res)
+      res['allow'] = "GET,HEAD,POST,OPTIONS,CONNECT"
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httprequest.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httprequest.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httprequest.rb	(revision 18425)
@@ -0,0 +1,365 @@
+#
+# httprequest.rb -- HTTPRequest Class
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: httprequest.rb,v 1.64 2003/07/13 17:18:22 gotoyuzo Exp $
+
+require 'timeout'
+require 'uri'
+
+require 'webrick/httpversion'
+require 'webrick/httpstatus'
+require 'webrick/httputils'
+require 'webrick/cookie'
+
+module WEBrick
+
+  class HTTPRequest
+    BODY_CONTAINABLE_METHODS = [ "POST", "PUT" ]
+    BUFSIZE = 1024*4
+
+    # Request line
+    attr_reader :request_line
+    attr_reader :request_method, :unparsed_uri, :http_version
+
+    # Request-URI
+    attr_reader :request_uri, :host, :port, :path
+    attr_accessor :script_name, :path_info, :query_string
+
+    # Header and entity body
+    attr_reader :raw_header, :header, :cookies
+    attr_reader :accept, :accept_charset
+    attr_reader :accept_encoding, :accept_language
+
+    # Misc
+    attr_accessor :user
+    attr_reader :addr, :peeraddr
+    attr_reader :attributes
+    attr_reader :keep_alive
+    attr_reader :request_time
+
+    def initialize(config)
+      @config = config
+      @logger = config[:Logger]
+
+      @request_line = @request_method =
+        @unparsed_uri = @http_version = nil
+
+      @request_uri = @host = @port = @path = nil
+      @script_name = @path_info = nil
+      @query_string = nil
+      @query = nil
+      @form_data = nil
+
+      @raw_header = Array.new
+      @header = nil
+      @cookies = []
+      @accept = []
+      @accept_charset = []
+      @accept_encoding = []
+      @accept_language = []
+      @body = ""
+
+      @addr = @peeraddr = nil
+      @attributes = {}
+      @user = nil
+      @keep_alive = false
+      @request_time = nil
+
+      @remaining_size = nil
+      @socket = nil
+    end
+
+    def parse(socket=nil)
+      @socket = socket
+      begin
+        @peeraddr = socket.respond_to?(:peeraddr) ? socket.peeraddr : []
+        @addr = socket.respond_to?(:addr) ? socket.addr : []
+      rescue Errno::ENOTCONN
+        raise HTTPStatus::EOFError
+      end
+
+      read_request_line(socket)
+      if @http_version.major > 0
+        read_header(socket)
+        @header['cookie'].each{|cookie|
+          @cookies += Cookie::parse(cookie)
+        }
+        @accept = HTTPUtils.parse_qvalues(self['accept'])
+        @accept_charset = HTTPUtils.parse_qvalues(self['accept-charset'])
+        @accept_encoding = HTTPUtils.parse_qvalues(self['accept-encoding'])
+        @accept_language = HTTPUtils.parse_qvalues(self['accept-language'])
+      end
+      return if @request_method == "CONNECT"
+      return if @unparsed_uri == "*"
+
+      begin
+        @request_uri = parse_uri(@unparsed_uri)
+        @path = HTTPUtils::unescape(@request_uri.path)
+        @path = HTTPUtils::normalize_path(@path)
+        @host = @request_uri.host
+        @port = @request_uri.port
+        @query_string = @request_uri.query
+        @script_name = ""
+        @path_info = @path.dup
+      rescue
+        raise HTTPStatus::BadRequest, "bad URI `#{@unparsed_uri}'."
+      end
+
+      if /close/io =~ self["connection"]
+        @keep_alive = false
+      elsif /keep-alive/io =~ self["connection"]
+        @keep_alive = true
+      elsif @http_version < "1.1"
+        @keep_alive = false
+      else
+        @keep_alive = true
+      end
+    end
+
+    def body(&block)
+      block ||= Proc.new{|chunk| @body << chunk }
+      read_body(@socket, block)
+      @body.empty? ? nil : @body
+    end
+
+    def query
+      unless @query
+        parse_query()
+      end
+      @query
+    end
+
+    def content_length
+      return Integer(self['content-length'])
+    end
+
+    def content_type
+      return self['content-type']
+    end
+
+    def [](header_name)
+      if @header
+        value = @header[header_name.downcase]
+        value.empty? ? nil : value.join(", ")
+      end
+    end
+
+    def each
+      @header.each{|k, v|
+        value = @header[k]
+        yield(k, value.empty? ? nil : value.join(", "))
+      }
+    end
+
+    def keep_alive?
+      @keep_alive
+    end
+
+    def to_s
+      ret = @request_line.dup
+      @raw_header.each{|line| ret << line }
+      ret << CRLF
+      ret << body if body
+      ret
+    end
+
+    def fixup()
+      begin
+        body{|chunk| }   # read remaining body
+      rescue HTTPStatus::Error => ex
+        @logger.error("HTTPRequest#fixup: #{ex.class} occured.")
+        @keep_alive = false
+      rescue => ex
+        @logger.error(ex)
+        @keep_alive = false
+      end
+    end
+
+    def meta_vars
+      # This method provides the metavariables defined by the revision 3
+      # of ``The WWW Common Gateway Interface Version 1.1''.
+      # (http://Web.Golux.Com/coar/cgi/)
+
+      meta = Hash.new
+
+      cl = self["Content-Length"]
+      ct = self["Content-Type"]
+      meta["CONTENT_LENGTH"]    = cl if cl.to_i > 0
+      meta["CONTENT_TYPE"]      = ct.dup if ct
+      meta["GATEWAY_INTERFACE"] = "CGI/1.1"
+      meta["PATH_INFO"]         = @path_info ? @path_info.dup : ""
+     #meta["PATH_TRANSLATED"]   = nil      # no plan to be provided
+      meta["QUERY_STRING"]      = @query_string ? @query_string.dup : ""
+      meta["REMOTE_ADDR"]       = @peeraddr[3]
+      meta["REMOTE_HOST"]       = @peeraddr[2]
+     #meta["REMOTE_IDENT"]      = nil      # no plan to be provided
+      meta["REMOTE_USER"]       = @user
+      meta["REQUEST_METHOD"]    = @request_method.dup
+      meta["REQUEST_URI"]       = @request_uri.to_s
+      meta["SCRIPT_NAME"]       = @script_name.dup
+      meta["SERVER_NAME"]       = @host
+      meta["SERVER_PORT"]       = @port.to_s
+      meta["SERVER_PROTOCOL"]   = "HTTP/" + @config[:HTTPVersion].to_s
+      meta["SERVER_SOFTWARE"]   = @config[:ServerSoftware].dup
+
+      self.each{|key, val|
+        next if /^content-type$/i =~ key
+        next if /^content-length$/i =~ key
+        name = "HTTP_" + key
+        name.gsub!(/-/o, "_")
+        name.upcase!
+        meta[name] = val
+      }
+
+      meta
+    end
+
+    private
+
+    def read_request_line(socket)
+      @request_line = read_line(socket) if socket
+      @request_time = Time.now
+      raise HTTPStatus::EOFError unless @request_line
+      if /^(\S+)\s+(\S+)(?:\s+HTTP\/(\d+\.\d+))?\r?\n/mo =~ @request_line
+        @request_method = $1
+        @unparsed_uri   = $2
+        @http_version   = HTTPVersion.new($3 ? $3 : "0.9")
+      else
+        rl = @request_line.sub(/\x0d?\x0a\z/o, '')
+        raise HTTPStatus::BadRequest, "bad Request-Line `#{rl}'."
+      end
+    end
+
+    def read_header(socket)
+      if socket
+        while line = read_line(socket)
+          break if /\A(#{CRLF}|#{LF})\z/om =~ line
+          @raw_header << line
+        end
+      end
+      begin
+        @header = HTTPUtils::parse_header(@raw_header)
+      rescue => ex
+        raise  HTTPStatus::BadRequest, ex.message
+      end
+    end
+
+    def parse_uri(str, scheme="http")
+      if @config[:Escape8bitURI]
+        str = HTTPUtils::escape8bit(str)
+      end
+      uri = URI::parse(str)
+      return uri if uri.absolute?
+      if self["host"]
+        pattern = /\A(#{URI::REGEXP::PATTERN::HOST})(?::(\d+))?\z/n
+        host, port = *self['host'].scan(pattern)[0]
+      elsif @addr.size > 0
+        host, port = @addr[2], @addr[1]
+      else
+        host, port = @config[:ServerName], @config[:Port]
+      end
+      uri.scheme = scheme
+      uri.host = host
+      uri.port = port ? port.to_i : nil
+      return URI::parse(uri.to_s)
+    end
+
+    def read_body(socket, block)
+      return unless socket
+      if tc = self['transfer-encoding']
+        case tc
+        when /chunked/io then read_chunked(socket, block)
+        else raise HTTPStatus::NotImplemented, "Transfer-Encoding: #{tc}."
+        end
+      elsif self['content-length'] || @remaining_size
+        @remaining_size ||= self['content-length'].to_i
+        while @remaining_size > 0 
+          sz = BUFSIZE < @remaining_size ? BUFSIZE : @remaining_size
+          break unless buf = read_data(socket, sz)
+          @remaining_size -= buf.size
+          block.call(buf)
+        end
+        if @remaining_size > 0 && @socket.eof?
+          raise HTTPStatus::BadRequest, "invalid body size."
+        end
+      elsif BODY_CONTAINABLE_METHODS.member?(@request_method)
+        raise HTTPStatus::LengthRequired
+      end
+      return @body
+    end
+
+    def read_chunk_size(socket)
+      line = read_line(socket)
+      if /^([0-9a-fA-F]+)(?:;(\S+))?/ =~ line
+        chunk_size = $1.hex
+        chunk_ext = $2
+        [ chunk_size, chunk_ext ]
+      else
+        raise HTTPStatus::BadRequest, "bad chunk `#{line}'."
+      end
+    end
+
+    def read_chunked(socket, block)
+      chunk_size, = read_chunk_size(socket)
+      while chunk_size > 0
+        data = ""
+        while data.size < chunk_size
+          tmp = read_data(socket, chunk_size-data.size) # read chunk-data
+          break unless tmp
+          data << tmp
+        end
+        if data.nil? || data.size != chunk_size
+          raise BadRequest, "bad chunk data size."
+        end
+        read_line(socket)                    # skip CRLF
+        block.call(data)
+        chunk_size, = read_chunk_size(socket)
+      end
+      read_header(socket)                    # trailer + CRLF
+      @header.delete("transfer-encoding")
+      @remaining_size = 0
+    end
+
+    def _read_data(io, method, arg)
+      begin
+        timeout(@config[:RequestTimeout]){
+          return io.__send__(method, arg)
+        }
+      rescue Errno::ECONNRESET
+        return nil
+      rescue TimeoutError
+        raise HTTPStatus::RequestTimeout
+      end
+    end
+
+    def read_line(io)
+      _read_data(io, :gets, LF)
+    end
+
+    def read_data(io, size)
+      _read_data(io, :read, size)
+    end
+
+    def parse_query()
+      begin
+        if @request_method == "GET" || @request_method == "HEAD"
+          @query = HTTPUtils::parse_query(@query_string)
+        elsif self['content-type'] =~ /^application\/x-www-form-urlencoded/
+          @query = HTTPUtils::parse_query(body)
+        elsif self['content-type'] =~ /^multipart\/form-data; boundary=(.+)/
+          boundary = HTTPUtils::dequote($1)
+          @query = HTTPUtils::parse_form_data(body, boundary)
+        else
+          @query = Hash.new
+        end
+      rescue => ex
+        raise HTTPStatus::BadRequest, ex.message
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpresponse.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpresponse.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpresponse.rb	(revision 18425)
@@ -0,0 +1,327 @@
+#
+# httpresponse.rb -- HTTPResponse Class
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: httpresponse.rb,v 1.45 2003/07/11 11:02:25 gotoyuzo Exp $
+
+require 'time'
+require 'webrick/httpversion'
+require 'webrick/htmlutils'
+require 'webrick/httputils'
+require 'webrick/httpstatus'
+
+module WEBrick
+  class HTTPResponse
+    BUFSIZE = 1024*4
+
+    attr_reader :http_version, :status, :header
+    attr_reader :cookies
+    attr_accessor :reason_phrase
+    attr_accessor :body
+
+    attr_accessor :request_method, :request_uri, :request_http_version
+    attr_accessor :filename
+    attr_accessor :keep_alive
+    attr_reader :config, :sent_size
+
+    def initialize(config)
+      @config = config
+      @logger = config[:Logger]
+      @header = Hash.new
+      @status = HTTPStatus::RC_OK
+      @reason_phrase = nil
+      @http_version = HTTPVersion::convert(@config[:HTTPVersion])
+      @body = ''
+      @keep_alive = true
+      @cookies = []
+      @request_method = nil
+      @request_uri = nil
+      @request_http_version = @http_version  # temporary
+      @chunked = false
+      @filename = nil
+      @sent_size = 0
+    end
+
+    def status_line
+      "HTTP/#@http_version #@status #@reason_phrase #{CRLF}"
+    end
+
+    def status=(status)
+      @status = status
+      @reason_phrase = HTTPStatus::reason_phrase(status)
+    end
+
+    def [](field)
+      @header[field.downcase]
+    end
+
+    def []=(field, value)
+      @header[field.downcase] = value.to_s
+    end
+
+    def content_length
+      if len = self['content-length']
+        return Integer(len)
+      end
+    end
+
+    def content_length=(len)
+      self['content-length'] = len.to_s
+    end
+
+    def content_type
+      self['content-type']
+    end
+
+    def content_type=(type)
+      self['content-type'] = type
+    end
+
+    def each
+      @header.each{|k, v|  yield(k, v) }
+    end
+
+    def chunked?
+      @chunked
+    end
+
+    def chunked=(val)
+      @chunked = val ? true : false
+    end
+
+    def keep_alive?
+      @keep_alive
+    end
+
+    def send_response(socket)
+      begin
+        setup_header()
+        send_header(socket)
+        send_body(socket)
+      rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ENOTCONN => ex
+        @logger.debug(ex)
+        @keep_alive = false
+      rescue Exception => ex
+        @logger.error(ex)
+        @keep_alive = false
+      end
+    end
+
+    def setup_header()
+      @reason_phrase    ||= HTTPStatus::reason_phrase(@status)
+      @header['server'] ||= @config[:ServerSoftware]
+      @header['date']   ||= Time.now.httpdate
+
+      # HTTP/0.9 features
+      if @request_http_version < "1.0"
+        @http_version = HTTPVersion.new("0.9")
+        @keep_alive = false
+      end
+
+      # HTTP/1.0 features
+      if @request_http_version < "1.1"
+        if chunked?
+          @chunked = false
+          ver = @request_http_version.to_s
+          msg = "chunked is set for an HTTP/#{ver} request. (ignored)"
+          @logger.warn(msg)
+        end
+      end
+
+      # Determin the message length (RFC2616 -- 4.4 Message Length)
+      if @status == 304 || @status == 204 || HTTPStatus::info?(@status)
+        @header.delete('content-length')
+        @body = ""
+      elsif chunked?
+        @header["transfer-encoding"] = "chunked"
+        @header.delete('content-length')
+      elsif %r{^multipart/byteranges} =~ @header['content-type']
+        @header.delete('content-length')
+      elsif @header['content-length'].nil?
+        unless @body.is_a?(IO)
+          @header['content-length'] = @body ? @body.size : 0
+        end
+      end
+
+      # Keep-Alive connection.
+      if @header['connection'] == "close"
+         @keep_alive = false
+      elsif keep_alive?
+        if chunked? || @header['content-length']
+          @header['connection'] = "Keep-Alive"
+        end
+      else
+        @header['connection'] = "close"
+      end
+
+      # Location is a single absoluteURI.
+      if location = @header['location']
+        if @request_uri
+          @header['location'] = @request_uri.merge(location)
+        end
+      end
+    end
+
+    def send_header(socket)
+      if @http_version.major > 0
+        data = status_line()
+        @header.each{|key, value|
+          tmp = key.gsub(/\bwww|^te$|\b\w/){|s| s.upcase }
+          data << "#{tmp}: #{value}" << CRLF
+        }
+        @cookies.each{|cookie|
+          data << "Set-Cookie: " << cookie.to_s << CRLF
+        }
+        data << CRLF
+        _write_data(socket, data)
+      end
+    end
+
+    def send_body(socket)
+      case @body
+      when IO then send_body_io(socket)
+      else send_body_string(socket)
+      end
+    end
+
+    def to_s
+      ret = ""
+      send_response(ret)
+      ret
+    end
+
+    def set_redirect(status, url)
+      @body = "<HTML><A HREF=\"#{url.to_s}\">#{url.to_s}</A>.</HTML>\n"
+      @header['location'] = url.to_s
+      raise status
+    end
+
+    def set_error(ex, backtrace=false)
+      case ex
+      when HTTPStatus::Status 
+        @keep_alive = false if HTTPStatus::error?(ex.code)
+        self.status = ex.code
+      else 
+        @keep_alive = false
+        self.status = HTTPStatus::RC_INTERNAL_SERVER_ERROR
+      end
+      @header['content-type'] = "text/html"
+
+      if respond_to?(:create_error_page)
+        create_error_page()
+        return
+      end
+
+      if @request_uri
+        host, port = @request_uri.host, @request_uri.port
+      else
+        host, port = @config[:ServerName], @config[:Port]
+      end
+
+      @body = ''
+      @body << <<-_end_of_html_
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+  <HEAD><TITLE>#{HTMLUtils::escape(@reason_phrase)}</TITLE></HEAD>
+  <BODY>
+    <H1>#{HTMLUtils::escape(@reason_phrase)}</H1>
+    #{HTMLUtils::escape(ex.message)}
+    <HR>
+      _end_of_html_
+
+      if backtrace && $DEBUG
+        @body << "backtrace of `#{HTMLUtils::escape(ex.class.to_s)}' "
+        @body << "#{HTMLUtils::escape(ex.message)}"
+        @body << "<PRE>"
+        ex.backtrace.each{|line| @body << "\t#{line}\n"}
+        @body << "</PRE><HR>"
+      end
+
+      @body << <<-_end_of_html_
+    <ADDRESS>
+     #{HTMLUtils::escape(@config[:ServerSoftware])} at
+     #{host}:#{port}
+    </ADDRESS>
+  </BODY>
+</HTML>
+      _end_of_html_
+    end
+
+    private
+
+    def send_body_io(socket)
+      begin
+        if @request_method == "HEAD"
+          # do nothing
+        elsif chunked?
+          while buf = @body.read(BUFSIZE)
+            next if buf.empty?
+            data = ""
+            data << format("%x", buf.size) << CRLF
+            data << buf << CRLF
+            _write_data(socket, data)
+            @sent_size += buf.size
+          end
+          _write_data(socket, "0#{CRLF}#{CRLF}")
+        else
+          size = @header['content-length'].to_i
+          _send_file(socket, @body, 0, size)
+          @sent_size = size
+        end
+      ensure
+        @body.close
+      end
+    end
+
+    def send_body_string(socket)
+      if @request_method == "HEAD"
+        # do nothing
+      elsif chunked?
+        remain = body ? @body.size : 0
+        while buf = @body[@sent_size, BUFSIZE]
+          break if buf.empty?
+          data = ""
+          data << format("%x", buf.size) << CRLF
+          data << buf << CRLF
+          _write_data(socket, data)
+          @sent_size += buf.size
+        end
+        _write_data(socket, "0#{CRLF}#{CRLF}")
+      else
+        if @body && @body.size > 0
+          _write_data(socket, @body)
+          @sent_size = @body.size
+        end
+      end
+    end
+
+    def _send_file(output, input, offset, size)
+      while offset > 0
+        sz = BUFSIZE < offset ? BUFSIZE : offset
+        buf = input.read(sz)
+        offset -= buf.size
+      end
+
+      if size == 0
+        while buf = input.read(BUFSIZE)
+          _write_data(output, buf)
+        end
+      else
+        while size > 0
+          sz = BUFSIZE < size ? BUFSIZE : size
+          buf = input.read(sz)
+          _write_data(output, buf)
+          size -= buf.size
+        end
+      end
+    end
+
+    def _write_data(socket, data)
+      socket << data
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/https.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/https.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/https.rb	(revision 18425)
@@ -0,0 +1,63 @@
+#
+# https.rb -- SSL/TLS enhancement for HTTPServer
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2001 GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: https.rb,v 1.15 2003/07/22 19:20:42 gotoyuzo Exp $
+
+require 'webrick/ssl'
+
+module WEBrick
+  module Config
+    HTTP.update(SSL)
+  end
+
+  class HTTPRequest
+    attr_reader :cipher, :server_cert, :client_cert
+
+    alias orig_parse parse
+
+    def parse(socket=nil)
+      if socket.respond_to?(:cert)
+        @server_cert = socket.cert || @config[:SSLCertificate]
+        @client_cert = socket.peer_cert
+        @client_cert_chain = socket.peer_cert_chain
+        @cipher      = socket.cipher
+      end
+      orig_parse(socket)
+    end
+
+    alias orig_parse_uri parse_uri
+
+    def parse_uri(str, scheme="https")
+      if @server_cert
+        return orig_parse_uri(str, scheme)
+      end
+      return orig_parse_uri(str)
+    end
+
+    alias orig_meta_vars meta_vars
+
+    def meta_vars
+      meta = orig_meta_vars
+      if @server_cert
+        meta["HTTPS"] = "on"
+        meta["SSL_SERVER_CERT"] = @server_cert.to_pem
+        meta["SSL_CLIENT_CERT"] = @client_cert ? @client_cert.to_pem : ""
+        if @client_cert_chain
+          @client_cert_chain.each_with_index{|cert, i|
+            meta["SSL_CLIENT_CERT_CHAIN_#{i}"] = cert.to_pem
+          }
+        end
+        meta["SSL_CIPHER"] = @cipher[0]
+        meta["SSL_PROTOCOL"] = @cipher[1]
+        meta["SSL_CIPHER_USEKEYSIZE"] = @cipher[2].to_s
+        meta["SSL_CIPHER_ALGKEYSIZE"] = @cipher[3].to_s
+      end
+      meta
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpserver.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpserver.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpserver.rb	(revision 18425)
@@ -0,0 +1,210 @@
+#
+# httpserver.rb -- HTTPServer Class
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: httpserver.rb,v 1.63 2002/10/01 17:16:32 gotoyuzo Exp $
+
+require 'webrick/server'
+require 'webrick/httputils'
+require 'webrick/httpstatus'
+require 'webrick/httprequest'
+require 'webrick/httpresponse'
+require 'webrick/httpservlet'
+require 'webrick/accesslog'
+
+module WEBrick
+  class HTTPServerError < ServerError; end
+
+  class HTTPServer < ::WEBrick::GenericServer
+    def initialize(config={}, default=Config::HTTP)
+      super
+      @http_version = HTTPVersion::convert(@config[:HTTPVersion])
+
+      @mount_tab = MountTable.new
+      if @config[:DocumentRoot]
+        mount("/", HTTPServlet::FileHandler, @config[:DocumentRoot],
+              @config[:DocumentRootOptions])
+      end
+
+      unless @config[:AccessLog]
+        @config[:AccessLog] = [
+          [ $stderr, AccessLog::COMMON_LOG_FORMAT ],
+          [ $stderr, AccessLog::REFERER_LOG_FORMAT ]
+        ]
+      end
+ 
+      @virtual_hosts = Array.new
+    end
+
+    def run(sock)
+      while true 
+        res = HTTPResponse.new(@config)
+        req = HTTPRequest.new(@config)
+        server = self
+        begin
+          timeout = @config[:RequestTimeout]
+          while timeout > 0
+            break if IO.select([sock], nil, nil, 0.5)
+            timeout = 0 if @status != :Running
+            timeout -= 0.5
+          end
+          raise HTTPStatus::EOFError if timeout <= 0 || sock.eof?
+          req.parse(sock)
+          res.request_method = req.request_method
+          res.request_uri = req.request_uri
+          res.request_http_version = req.http_version
+          res.keep_alive = req.keep_alive?
+          server = lookup_server(req) || self
+          if callback = server[:RequestCallback] || server[:RequestHandler]
+            callback.call(req, res)
+          end
+          server.service(req, res)
+        rescue HTTPStatus::EOFError, HTTPStatus::RequestTimeout => ex
+          res.set_error(ex)
+        rescue HTTPStatus::Error => ex
+          @logger.error(ex.message)
+          res.set_error(ex)
+        rescue HTTPStatus::Status => ex
+          res.status = ex.code
+        rescue StandardError => ex
+          @logger.error(ex)
+          res.set_error(ex, true)
+        ensure
+          if req.request_line
+            req.fixup()
+            res.send_response(sock)
+            server.access_log(@config, req, res)
+          end
+        end
+        break if @http_version < "1.1"
+        break unless req.keep_alive?
+        break unless res.keep_alive?
+      end
+    end
+
+    def service(req, res)
+      if req.unparsed_uri == "*"
+        if req.request_method == "OPTIONS"
+          do_OPTIONS(req, res)
+          raise HTTPStatus::OK
+        end
+        raise HTTPStatus::NotFound, "`#{req.unparsed_uri}' not found."
+      end
+
+      servlet, options, script_name, path_info = search_servlet(req.path)
+      raise HTTPStatus::NotFound, "`#{req.path}' not found." unless servlet
+      req.script_name = script_name
+      req.path_info = path_info
+      si = servlet.get_instance(self, *options)
+      @logger.debug(format("%s is invoked.", si.class.name))
+      si.service(req, res)
+    end
+
+    def do_OPTIONS(req, res)
+      res["allow"] = "GET,HEAD,POST,OPTIONS"
+    end
+
+    def mount(dir, servlet, *options)
+      @logger.debug(sprintf("%s is mounted on %s.", servlet.inspect, dir))
+      @mount_tab[dir] = [ servlet, options ]
+    end
+
+    def mount_proc(dir, proc=nil, &block)
+      proc ||= block
+      raise HTTPServerError, "must pass a proc or block" unless proc
+      mount(dir, HTTPServlet::ProcHandler.new(proc))
+    end
+
+    def unmount(dir)
+      @logger.debug(sprintf("unmount %s.", dir))
+      @mount_tab.delete(dir)
+    end
+    alias umount unmount
+
+    def search_servlet(path)
+      script_name, path_info = @mount_tab.scan(path)
+      servlet, options = @mount_tab[script_name]
+      if servlet
+        [ servlet, options, script_name, path_info ]
+      end
+    end
+
+    def virtual_host(server)
+      @virtual_hosts << server
+      @virtual_hosts = @virtual_hosts.sort_by{|s|
+        num = 0
+        num -= 4 if s[:BindAddress]
+        num -= 2 if s[:Port]
+        num -= 1 if s[:ServerName]
+        num
+      }
+    end
+
+    def lookup_server(req)
+      @virtual_hosts.find{|s|
+        (s[:BindAddress].nil? || req.addr[3] == s[:BindAddress]) &&
+        (s[:Port].nil?        || req.port == s[:Port])           &&
+        ((s[:ServerName].nil?  || req.host == s[:ServerName]) ||
+         (!s[:ServerAlias].nil? && s[:ServerAlias].find{|h| h === req.host}))
+      }
+    end
+
+    def access_log(config, req, res)
+      param = AccessLog::setup_params(config, req, res)
+      @config[:AccessLog].each{|logger, fmt|
+        logger << AccessLog::format(fmt+"\n", param)
+      }
+    end
+
+    class MountTable
+      def initialize
+        @tab = Hash.new
+        compile
+      end
+
+      def [](dir)
+        dir = normalize(dir)
+        @tab[dir]
+      end
+
+      def []=(dir, val)
+        dir = normalize(dir)
+        @tab[dir] = val
+        compile
+        val
+      end
+
+      def delete(dir)
+        dir = normalize(dir)
+        res = @tab.delete(dir)
+        compile
+        res
+      end
+
+      def scan(path)
+        @scanner =~ path
+        [ $&, $' ]
+      end
+
+      private
+
+      def compile
+        k = @tab.keys
+        k.sort!
+        k.reverse!
+        k.collect!{|path| Regexp.escape(path) }
+        @scanner = Regexp.new("^(" + k.join("|") +")(?=/|$)")
+      end
+
+      def normalize(dir)
+        ret = dir ? dir.dup : ""
+        ret.sub!(%r|/+$|, "")
+        ret
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet.rb	(revision 18425)
@@ -0,0 +1,22 @@
+#
+# httpservlet.rb -- HTTPServlet Utility File
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: httpservlet.rb,v 1.21 2003/02/23 12:24:46 gotoyuzo Exp $
+
+require 'webrick/httpservlet/abstract'
+require 'webrick/httpservlet/filehandler'
+require 'webrick/httpservlet/cgihandler'
+require 'webrick/httpservlet/erbhandler'
+require 'webrick/httpservlet/prochandler'
+
+module WEBrick
+  module HTTPServlet
+    FileHandler.add_handler("cgi", CGIHandler)
+    FileHandler.add_handler("rhtml", ERBHandler)
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/abstract.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/abstract.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/abstract.rb	(revision 18425)
@@ -0,0 +1,71 @@
+#
+# httpservlet.rb -- HTTPServlet Module
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: abstract.rb,v 1.24 2003/07/11 11:16:46 gotoyuzo Exp $
+
+require 'thread'
+
+require 'webrick/htmlutils'
+require 'webrick/httputils'
+require 'webrick/httpstatus'
+
+module WEBrick
+  module HTTPServlet
+    class HTTPServletError < StandardError; end
+
+    class AbstractServlet
+      def self.get_instance(config, *options)
+        self.new(config, *options)
+      end
+
+      def initialize(server, *options)
+        @server = @config = server
+        @logger = @server[:Logger]
+        @options = options
+      end
+
+      def service(req, res)
+        method_name = "do_" + req.request_method.gsub(/-/, "_")
+        if respond_to?(method_name)
+          __send__(method_name, req, res)
+        else
+          raise HTTPStatus::MethodNotAllowed,
+                "unsupported method `#{req.request_method}'."
+        end
+      end
+
+      def do_GET(req, res)
+        raise HTTPStatus::NotFound, "not found."
+      end
+
+      def do_HEAD(req, res)
+        do_GET(req, res)
+      end
+
+      def do_OPTIONS(req, res)
+        m = self.methods.grep(/^do_[A-Z]+$/)
+        m.collect!{|i| i.sub(/do_/, "") }
+        m.sort!
+        res["allow"] = m.join(",")
+      end
+
+      private
+
+      def redirect_to_directory_uri(req, res)
+        if req.path[-1] != ?/
+          location = req.path + "/"
+          if req.query_string && req.query_string.size > 0
+            location << "?" << req.query_string
+          end
+          res.set_redirect(HTTPStatus::MovedPermanently, location)
+        end
+      end
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/cgi_runner.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/cgi_runner.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/cgi_runner.rb	(revision 18425)
@@ -0,0 +1,45 @@
+#
+# cgi_runner.rb -- CGI launcher.
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: cgi_runner.rb,v 1.9 2002/09/25 11:33:15 gotoyuzo Exp $
+
+def sysread(io, size)
+  buf = ""
+  while size > 0
+    tmp = io.sysread(size)
+    buf << tmp
+    size -= tmp.size
+  end
+  return buf
+end
+
+STDIN.binmode
+
+buf = ""
+len = sysread(STDIN, 8).to_i
+out = sysread(STDIN, len)
+STDOUT.reopen(open(out, "w"))
+
+len = sysread(STDIN, 8).to_i
+err = sysread(STDIN, len)
+STDERR.reopen(open(err, "w"))
+
+len  = sysread(STDIN, 8).to_i
+dump = sysread(STDIN, len)
+hash = Marshal.restore(dump)
+ENV.keys.each{|name| ENV.delete(name) }
+hash.each{|k, v| ENV[k] = v if v }
+
+dir = File::dirname(ENV["SCRIPT_FILENAME"])
+Dir::chdir dir
+
+if interpreter = ARGV[0]
+  exec(interpreter, ENV["SCRIPT_FILENAME"])
+  # NOTREACHED
+end
+exec ENV["SCRIPT_FILENAME"]
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/cgihandler.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/cgihandler.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/cgihandler.rb	(revision 18425)
@@ -0,0 +1,104 @@
+# 
+# cgihandler.rb -- CGIHandler Class
+#       
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#   
+# $IPR: cgihandler.rb,v 1.27 2003/03/21 19:56:01 gotoyuzo Exp $
+
+require 'rbconfig'
+require 'tempfile'
+require 'webrick/config'
+require 'webrick/httpservlet/abstract'
+
+module WEBrick
+  module HTTPServlet
+
+    class CGIHandler < AbstractServlet
+      Ruby = File::join(::Config::CONFIG['bindir'],
+                        ::Config::CONFIG['ruby_install_name'])
+      Ruby << ::Config::CONFIG['EXEEXT']
+      CGIRunner = "\"#{Ruby}\" \"#{Config::LIBDIR}/httpservlet/cgi_runner.rb\""
+
+      def initialize(server, name)
+        super
+        @script_filename = name
+        @tempdir = server[:TempDir]
+        @cgicmd = "#{CGIRunner} #{server[:CGIInterpreter]}"
+      end
+
+      def do_GET(req, res)
+        data = nil
+        status = -1
+
+        cgi_in = IO::popen(@cgicmd, "wb")
+        cgi_out = Tempfile.new("webrick.cgiout.", @tempdir)
+        cgi_err = Tempfile.new("webrick.cgierr.", @tempdir)
+        begin
+          cgi_in.sync = true
+          meta = req.meta_vars
+          meta["SCRIPT_FILENAME"] = @script_filename
+          meta["PATH"] = @config[:CGIPathEnv]
+          if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
+            meta["SystemRoot"] = ENV["SystemRoot"]
+          end
+          dump = Marshal.dump(meta)
+
+          cgi_in.write("%8d" % cgi_out.path.size)
+          cgi_in.write(cgi_out.path)
+          cgi_in.write("%8d" % cgi_err.path.size)
+          cgi_in.write(cgi_err.path)
+          cgi_in.write("%8d" % dump.size)
+          cgi_in.write(dump)
+
+          if req.body and req.body.size > 0
+            cgi_in.write(req.body)
+          end
+        ensure
+          cgi_in.close
+          status = $?.exitstatus
+          sleep 0.1 if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
+          data = cgi_out.read
+          cgi_out.close(true)
+          if errmsg = cgi_err.read
+            if errmsg.size > 0
+              @logger.error("CGIHandler: #{@script_filename}:\n" + errmsg)
+            end
+          end 
+          cgi_err.close(true)
+        end
+        
+        if status != 0
+          @logger.error("CGIHandler: #{@script_filename} exit with #{status}")
+        end
+
+        data = "" unless data
+        raw_header, body = data.split(/^[\xd\xa]+/on, 2) 
+        raise HTTPStatus::InternalServerError,
+          "Premature end of script headers: #{@script_filename}" if body.nil?
+
+        begin
+          header = HTTPUtils::parse_header(raw_header)
+          if /^(\d+)/ =~ header['status'][0]
+            res.status = $1.to_i
+            header.delete('status')
+          end
+          if header.has_key?('set-cookie')
+            header['set-cookie'].each{|k|
+              res.cookies << Cookie.parse_set_cookie(k)
+            }
+            header.delete('set-cookie')
+          end
+          header.each{|key, val| res[key] = val.join(", ") }
+        rescue => ex
+          raise HTTPStatus::InternalServerError, ex.message
+        end
+        res.body = body
+      end
+      alias do_POST do_GET
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/erbhandler.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/erbhandler.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/erbhandler.rb	(revision 18425)
@@ -0,0 +1,54 @@
+# 
+# erbhandler.rb -- ERBHandler Class
+# 
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+# 
+# $IPR: erbhandler.rb,v 1.25 2003/02/24 19:25:31 gotoyuzo Exp $
+
+require 'webrick/httpservlet/abstract.rb'
+
+require 'erb'
+
+module WEBrick
+  module HTTPServlet
+
+    class ERBHandler < AbstractServlet
+      def initialize(server, name)
+        super
+        @script_filename = name
+      end
+
+      def do_GET(req, res)
+        unless defined?(ERB)
+          @logger.warn "#{self.class}: ERB not defined."
+          raise HTTPStatus::Forbidden, "ERBHandler cannot work."
+        end
+        begin
+          data = open(@script_filename){|io| io.read }
+          res.body = evaluate(ERB.new(data), req, res)
+          res['content-type'] =
+            HTTPUtils::mime_type(@script_filename, @config[:MimeTypes])
+        rescue StandardError => ex
+          raise
+        rescue Exception => ex
+          @logger.error(ex)
+          raise HTTPStatus::InternalServerError, ex.message
+        end
+      end
+
+      alias do_POST do_GET
+
+      private
+      def evaluate(erb, servlet_request, servlet_response)
+        Module.new.module_eval{
+          meta_vars = servlet_request.meta_vars
+          query = servlet_request.query
+          erb.result(binding)
+        }
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/filehandler.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/filehandler.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/filehandler.rb	(revision 18425)
@@ -0,0 +1,398 @@
+#
+# filehandler.rb -- FileHandler Module
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: filehandler.rb,v 1.44 2003/06/07 01:34:51 gotoyuzo Exp $
+
+require 'thread'
+require 'time'
+
+require 'webrick/htmlutils'
+require 'webrick/httputils'
+require 'webrick/httpstatus'
+
+module WEBrick
+  module HTTPServlet
+
+    class DefaultFileHandler < AbstractServlet
+      def initialize(server, local_path)
+        super
+        @local_path = local_path
+      end
+
+      def do_GET(req, res)
+        st = File::stat(@local_path)
+        mtime = st.mtime
+        res['etag'] = sprintf("%x-%x-%x", st.ino, st.size, st.mtime.to_i)
+
+        if not_modified?(req, res, mtime, res['etag'])
+          res.body = ''
+          raise HTTPStatus::NotModified
+        elsif req['range'] 
+          make_partial_content(req, res, @local_path, st.size)
+          raise HTTPStatus::PartialContent
+        else
+          mtype = HTTPUtils::mime_type(@local_path, @config[:MimeTypes])
+          res['content-type'] = mtype
+          res['content-length'] = st.size
+          res['last-modified'] = mtime.httpdate
+          res.body = open(@local_path, "rb")
+        end
+      end
+
+      def not_modified?(req, res, mtime, etag)
+        if ir = req['if-range']
+          begin
+            if Time.httpdate(ir) >= mtime
+              return true
+            end
+          rescue
+            if HTTPUtils::split_header_value(ir).member?(res['etag'])
+              return true
+            end
+          end
+        end
+
+        if (ims = req['if-modified-since']) && Time.parse(ims) >= mtime
+          return true
+        end
+
+        if (inm = req['if-none-match']) &&
+           HTTPUtils::split_header_value(inm).member?(res['etag'])
+          return true
+        end
+
+        return false
+      end
+
+      def make_partial_content(req, res, filename, filesize)
+        mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes])
+        unless ranges = HTTPUtils::parse_range_header(req['range'])
+          raise HTTPStatus::BadRequest,
+            "Unrecognized range-spec: \"#{req['range']}\""
+        end
+        open(filename, "rb"){|io|
+          if ranges.size > 1
+            time = Time.now
+            boundary = "#{time.sec}_#{time.usec}_#{Process::pid}"
+            body = ''
+            ranges.each{|range|
+              first, last = prepare_range(range, filesize)
+              next if first < 0
+              io.pos = first
+              content = io.read(last-first+1)
+              body << "--" << boundary << CRLF
+              body << "Content-Type: #{mtype}" << CRLF
+              body << "Content-Range: #{first}-#{last}/#{filesize}" << CRLF
+              body << CRLF
+              body << content
+              body << CRLF
+            }
+            raise HTTPStatus::RequestRangeNotSatisfiable if body.empty?
+            body << "--" << boundary << "--" << CRLF
+            res["content-type"] = "multipart/byteranges; boundary=#{boundary}"
+            res.body = body
+          elsif range = ranges[0]
+            first, last = prepare_range(range, filesize)
+            raise HTTPStatus::RequestRangeNotSatisfiable if first < 0
+            if last == filesize - 1
+              content = io.dup
+              content.pos = first
+            else
+              io.pos = first
+              content = io.read(last-first+1)
+            end
+            res['content-type'] = mtype
+            res['content-range'] = "#{first}-#{last}/#{filesize}"
+            res['content-length'] = last - first + 1
+            res.body = content
+          else
+            raise HTTPStatus::BadRequest
+          end
+        }
+      end
+
+      def prepare_range(range, filesize)
+        first = range.first < 0 ? filesize + range.first : range.first
+        return -1, -1 if first < 0 || first >= filesize
+        last = range.last < 0 ? filesize + range.last : range.last
+        last = filesize - 1 if last >= filesize
+        return first, last
+      end
+    end
+
+    class FileHandler < AbstractServlet
+      HandlerTable = Hash.new
+
+      def self.add_handler(suffix, handler)
+        HandlerTable[suffix] = handler
+      end
+
+      def self.remove_handler(suffix)
+        HandlerTable.delete(suffix)
+      end
+
+      def initialize(server, root, options={}, default=Config::FileHandler)
+        @config = server.config
+        @logger = @config[:Logger]
+        @root = File.expand_path(root)
+        if options == true || options == false
+          options = { :FancyIndexing => options }
+        end
+        @options = default.dup.update(options)
+      end
+
+      def service(req, res)
+        # if this class is mounted on "/" and /~username is requested.
+        # we're going to override path informations before invoking service.
+        if defined?(Etc) && @options[:UserDir] && req.script_name.empty?
+          if %r|^(/~([^/]+))| =~ req.path_info
+            script_name, user = $1, $2
+            path_info = $'
+            begin
+              passwd = Etc::getpwnam(user)
+              @root = File::join(passwd.dir, @options[:UserDir])
+              req.script_name = script_name
+              req.path_info = path_info
+            rescue
+              @logger.debug "#{self.class}#do_GET: getpwnam(#{user}) failed"
+            end
+          end
+        end
+        super(req, res)
+      end
+
+      def do_GET(req, res)
+        unless exec_handler(req, res)
+          set_dir_list(req, res)
+        end
+      end
+
+      def do_POST(req, res)
+        unless exec_handler(req, res)
+          raise HTTPStatus::NotFound, "`#{req.path}' not found."
+        end
+      end
+
+      def do_OPTIONS(req, res)
+        unless exec_handler(req, res)
+          super(req, res)
+        end
+      end
+
+      # ToDo
+      # RFC2518: HTTP Extensions for Distributed Authoring -- WEBDAV
+      #
+      # PROPFIND PROPPATCH MKCOL DELETE PUT COPY MOVE
+      # LOCK UNLOCK
+
+      # RFC3253: Versioning Extensions to WebDAV
+      #          (Web Distributed Authoring and Versioning)
+      #
+      # VERSION-CONTROL REPORT CHECKOUT CHECK_IN UNCHECKOUT
+      # MKWORKSPACE UPDATE LABEL MERGE ACTIVITY
+
+      private
+
+      def exec_handler(req, res)
+        raise HTTPStatus::NotFound, "`#{req.path}' not found" unless @root
+        if set_filename(req, res)
+          handler = get_handler(req)
+          call_callback(:HandlerCallback, req, res)
+          h = handler.get_instance(@config, res.filename)
+          h.service(req, res)
+          return true
+        end
+        call_callback(:HandlerCallback, req, res)
+        return false
+      end
+
+      def get_handler(req)
+        suffix1 = (/\.(\w+)$/ =~ req.script_name) && $1.downcase
+        suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ req.script_name) && $1.downcase
+        handler_table = @options[:HandlerTable]
+        return handler_table[suffix1] || handler_table[suffix2] ||
+               HandlerTable[suffix1] || HandlerTable[suffix2] ||
+               DefaultFileHandler
+      end
+
+      def set_filename(req, res)
+        res.filename = @root.dup
+        path_info = req.path_info.scan(%r|/[^/]*|)
+
+        path_info.unshift("")  # dummy for checking @root dir
+        while base = path_info.first
+          check_filename(req, res, base)
+          break if base == "/"
+          break unless File.directory?(res.filename + base)
+          shift_path_info(req, res, path_info)
+          call_callback(:DirectoryCallback, req, res)
+        end
+
+        if base = path_info.first
+          check_filename(req, res, base)
+          if base == "/"
+            if file = search_index_file(req, res)
+              shift_path_info(req, res, path_info, file)
+              call_callback(:FileCallback, req, res)
+              return true
+            end
+            shift_path_info(req, res, path_info)
+          elsif file = search_file(req, res, base)
+            shift_path_info(req, res, path_info, file)
+            call_callback(:FileCallback, req, res)
+            return true
+          else
+            raise HTTPStatus::NotFound, "`#{req.path}' not found."
+          end
+        end
+
+        return false
+      end
+
+      def check_filename(req, res, name)
+        @options[:NondisclosureName].each{|pattern|
+          if File.fnmatch("/#{pattern}", name)
+            @logger.warn("the request refers nondisclosure name `#{name}'.")
+            raise HTTPStatus::NotFound, "`#{req.path}' not found."
+          end
+        }
+      end
+
+      def shift_path_info(req, res, path_info, base=nil)
+        tmp = path_info.shift
+        base = base || tmp
+        req.path_info = path_info.join
+        req.script_name << base
+        res.filename << base
+      end
+
+      def search_index_file(req, res)
+        @config[:DirectoryIndex].each{|index|
+          if file = search_file(req, res, "/"+index)
+            return file
+          end
+        }
+        return nil
+      end
+
+      def search_file(req, res, basename)
+        langs = @options[:AcceptableLanguages]
+        path = res.filename + basename
+        if File.file?(path)
+          return basename
+        elsif langs.size > 0
+          req.accept_language.each{|lang|
+            path_with_lang = path + ".#{lang}"
+            if langs.member?(lang) && File.file?(path_with_lang)
+              return basename + ".#{lang}"
+            end
+          }
+          (langs - req.accept_language).each{|lang|
+            path_with_lang = path + ".#{lang}"
+            if File.file?(path_with_lang)
+              return basename + ".#{lang}"
+            end
+          }
+        end
+        return nil
+      end
+
+      def call_callback(callback_name, req, res)
+        if cb = @options[callback_name]
+          cb.call(req, res)
+        end
+      end
+
+      def nondisclosure_name?(name)
+        @options[:NondisclosureName].each{|pattern|
+          if File.fnmatch(pattern, name)
+            return true
+          end
+        }
+        return false
+      end
+
+      def set_dir_list(req, res)
+        redirect_to_directory_uri(req, res)
+        unless @options[:FancyIndexing]
+          raise HTTPStatus::Forbidden, "no access permission to `#{req.path}'"
+        end
+        local_path = res.filename
+        list = Dir::entries(local_path).collect{|name|
+          next if name == "." || name == ".."
+          next if nondisclosure_name?(name)
+          st = (File::stat(local_path + name) rescue nil)
+          if st.nil?
+            [ name, nil, -1 ]
+          elsif st.directory?
+            [ name + "/", st.mtime, -1 ]
+          else
+            [ name, st.mtime, st.size ]
+          end
+        }
+        list.compact!
+
+        if    d0 = req.query["N"]; idx = 0
+        elsif d0 = req.query["M"]; idx = 1
+        elsif d0 = req.query["S"]; idx = 2
+        else  d0 = "A"           ; idx = 0
+        end
+        d1 = (d0 == "A") ? "D" : "A"
+
+        if d0 == "A"
+          list.sort!{|a,b| a[idx] <=> b[idx] }
+        else
+          list.sort!{|a,b| b[idx] <=> a[idx] }
+        end
+
+        res['content-type'] = "text/html"
+
+        res.body = <<-_end_of_html_
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<HTML>
+  <HEAD><TITLE>Index of #{HTMLUtils::escape(req.path)}</TITLE></HEAD>
+  <BODY>
+    <H1>Index of #{HTMLUtils::escape(req.path)}</H1>
+        _end_of_html_
+
+        res.body << "<PRE>\n"
+        res.body << " <A HREF=\"?N=#{d1}\">Name</A>                          "
+        res.body << "<A HREF=\"?M=#{d1}\">Last modified</A>         "
+        res.body << "<A HREF=\"?S=#{d1}\">Size</A>\n"
+        res.body << "<HR>\n"
+       
+        list.unshift [ "..", File::mtime(local_path+".."), -1 ]
+        list.each{ |name, time, size|
+          if name == ".."
+            dname = "Parent Directory"
+          elsif name.size > 25
+            dname = name.sub(/^(.{23})(.*)/){ $1 + ".." }
+          else
+            dname = name
+          end
+          s =  " <A HREF=\"#{HTTPUtils::escape(name)}\">#{dname}</A>"
+          s << " " * (30 - dname.size)
+          s << (time ? time.strftime("%Y/%m/%d %H:%M      ") : " " * 22)
+          s << (size >= 0 ? size.to_s : "-") << "\n"
+          res.body << s
+        }
+        res.body << "</PRE><HR>"
+
+        res.body << <<-_end_of_html_    
+    <ADDRESS>
+     #{HTMLUtils::escape(@config[:ServerSoftware])}<BR>
+     at #{req.host}:#{req.port}
+    </ADDRESS>
+  </BODY>
+</HTML>
+        _end_of_html_
+      end
+
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/prochandler.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/prochandler.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpservlet/prochandler.rb	(revision 18425)
@@ -0,0 +1,33 @@
+# 
+# prochandler.rb -- ProcHandler Class
+#       
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#   
+# $IPR: prochandler.rb,v 1.7 2002/09/21 12:23:42 gotoyuzo Exp $
+
+require 'webrick/httpservlet/abstract.rb'
+
+module WEBrick
+  module HTTPServlet
+
+    class ProcHandler < AbstractServlet
+      def get_instance(server, *options)
+        self
+      end  
+
+      def initialize(proc)
+        @proc = proc
+      end
+
+      def do_GET(request, response)
+        @proc.call(request, response)
+      end
+
+      alias do_POST do_GET
+    end
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpstatus.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpstatus.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpstatus.rb	(revision 18425)
@@ -0,0 +1,126 @@
+#
+# httpstatus.rb -- HTTPStatus Class
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: httpstatus.rb,v 1.11 2003/03/24 20:18:55 gotoyuzo Exp $
+
+module WEBrick
+
+  module HTTPStatus
+
+    class Status      < StandardError; end
+    class Info        < Status; end
+    class Success     < Status; end
+    class Redirect    < Status; end
+    class Error       < Status; end
+    class ClientError < Error; end
+    class ServerError < Error; end
+    
+    class EOFError < StandardError; end
+
+    StatusMessage = {
+      100, 'Continue',
+      101, 'Switching Protocols',
+      200, 'OK',
+      201, 'Created',
+      202, 'Accepted',
+      203, 'Non-Authoritative Information',
+      204, 'No Content',
+      205, 'Reset Content',
+      206, 'Partial Content',
+      300, 'Multiple Choices',
+      301, 'Moved Permanently',
+      302, 'Found',
+      303, 'See Other',
+      304, 'Not Modified',
+      305, 'Use Proxy',
+      307, 'Temporary Redirect',
+      400, 'Bad Request',
+      401, 'Unauthorized',
+      402, 'Payment Required',
+      403, 'Forbidden',
+      404, 'Not Found',
+      405, 'Method Not Allowed',
+      406, 'Not Acceptable',
+      407, 'Proxy Authentication Required',
+      408, 'Request Timeout',
+      409, 'Conflict',
+      410, 'Gone',
+      411, 'Length Required',
+      412, 'Precondition Failed',
+      413, 'Request Entity Too Large',
+      414, 'Request-URI Too Large',
+      415, 'Unsupported Media Type',
+      416, 'Request Range Not Satisfiable',
+      417, 'Expectation Failed',
+      500, 'Internal Server Error',
+      501, 'Not Implemented',
+      502, 'Bad Gateway',
+      503, 'Service Unavailable',
+      504, 'Gateway Timeout',
+      505, 'HTTP Version Not Supported'
+    }
+
+    CodeToError = {}
+
+    StatusMessage.each{|code, message|
+      var_name = message.gsub(/[ \-]/,'_').upcase
+      err_name = message.gsub(/[ \-]/,'')
+
+      case code
+      when 100...200; parent = Info
+      when 200...300; parent = Success
+      when 300...400; parent = Redirect
+      when 400...500; parent = ClientError
+      when 500...600; parent = ServerError
+      end
+
+      eval %-
+        RC_#{var_name} = #{code}
+        class #{err_name} < #{parent}
+          def self.code() RC_#{var_name} end
+          def self.reason_phrase() StatusMessage[code] end
+          def code() self::class::code end 
+          def reason_phrase() self::class::reason_phrase end
+          alias to_i code
+        end
+      -
+
+      CodeToError[code] = const_get(err_name)
+    }
+
+    def reason_phrase(code)
+      StatusMessage[code.to_i]
+    end
+    def info?(code)
+      code.to_i >= 100 and code.to_i < 200
+    end
+    def success?(code)
+      code.to_i >= 200 and code.to_i < 300
+    end
+    def redirect?(code)
+      code.to_i >= 300 and code.to_i < 400
+    end
+    def error?(code)
+      code.to_i >= 400 and code.to_i < 600
+    end
+    def client_error?(code)
+      code.to_i >= 400 and code.to_i < 500
+    end
+    def server_error?(code)
+      code.to_i >= 500 and code.to_i < 600
+    end
+
+    def self.[](code)
+      CodeToError[code]
+    end
+
+    module_function :reason_phrase
+    module_function :info?, :success?, :redirect?, :error?
+    module_function :client_error?, :server_error?
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httputils.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httputils.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httputils.rb	(revision 18425)
@@ -0,0 +1,399 @@
+#
+# httputils.rb -- HTTPUtils Module
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: httputils.rb,v 1.34 2003/06/05 21:34:08 gotoyuzo Exp $
+
+require 'socket'
+require 'tempfile'
+
+module WEBrick
+  CR   = "\x0d"
+  LF   = "\x0a"
+  CRLF = "\x0d\x0a"
+
+  module HTTPUtils
+
+    def normalize_path(path)
+      raise "abnormal path `#{path}'" if path[0] != ?/
+      ret = path.dup
+
+      ret.gsub!(%r{/+}o, '/')                    # //      => /
+      while ret.sub!(%r{/\.(/|\Z)}o, '/'); end   # /.      => /
+      begin                                      # /foo/.. => /foo
+        match = ret.sub!(%r{/([^/]+)/\.\.(/|\Z)}o){
+          if $1 == ".."
+            raise "abnormal path `#{path}'"
+          else
+            "/"
+          end
+        }
+      end while match
+
+      raise "abnormal path `#{path}'" if %r{/\.\.(/|\Z)} =~ ret
+      ret
+    end
+    module_function :normalize_path
+
+    #####
+
+    DefaultMimeTypes = {
+      "ai"    => "application/postscript",
+      "asc"   => "text/plain",
+      "avi"   => "video/x-msvideo",
+      "bin"   => "application/octet-stream",
+      "bmp"   => "image/bmp",
+      "class" => "application/octet-stream",
+      "cer"   => "application/pkix-cert",
+      "crl"   => "application/pkix-crl",
+      "crt"   => "application/x-x509-ca-cert",
+     #"crl"   => "application/x-pkcs7-crl",
+      "css"   => "text/css",
+      "dms"   => "application/octet-stream",
+      "doc"   => "application/msword",
+      "dvi"   => "application/x-dvi",
+      "eps"   => "application/postscript",
+      "etx"   => "text/x-setext",
+      "exe"   => "application/octet-stream",
+      "gif"   => "image/gif",
+      "htm"   => "text/html",
+      "html"  => "text/html",
+      "jpe"   => "image/jpeg",
+      "jpeg"  => "image/jpeg",
+      "jpg"   => "image/jpeg",
+      "lha"   => "application/octet-stream",
+      "lzh"   => "application/octet-stream",
+      "mov"   => "video/quicktime",
+      "mpe"   => "video/mpeg",
+      "mpeg"  => "video/mpeg",
+      "mpg"   => "video/mpeg",
+      "pbm"   => "image/x-portable-bitmap",
+      "pdf"   => "application/pdf",
+      "pgm"   => "image/x-portable-graymap",
+      "png"   => "image/png",
+      "pnm"   => "image/x-portable-anymap",
+      "ppm"   => "image/x-portable-pixmap",
+      "ppt"   => "application/vnd.ms-powerpoint",
+      "ps"    => "application/postscript",
+      "qt"    => "video/quicktime",
+      "ras"   => "image/x-cmu-raster",
+      "rb"    => "text/plain",
+      "rd"    => "text/plain",
+      "rtf"   => "application/rtf",
+      "sgm"   => "text/sgml",
+      "sgml"  => "text/sgml",
+      "tif"   => "image/tiff",
+      "tiff"  => "image/tiff",
+      "txt"   => "text/plain",
+      "xbm"   => "image/x-xbitmap",
+      "xls"   => "application/vnd.ms-excel",
+      "xml"   => "text/xml",
+      "xpm"   => "image/x-xpixmap",
+      "xwd"   => "image/x-xwindowdump",
+      "zip"   => "application/zip",
+    }
+
+    # Load Apache compatible mime.types file.
+    def load_mime_types(file)
+      open(file){ |io|
+        hash = Hash.new
+        io.each{ |line|
+          next if /^#/ =~ line
+          line.chomp!
+          mimetype, ext0 = line.split(/\s+/, 2)
+          next unless ext0   
+          next if ext0.empty?
+          ext0.split(/\s+/).each{ |ext| hash[ext] = mimetype }
+        }
+        hash
+      }
+    end
+    module_function :load_mime_types
+
+    def mime_type(filename, mime_tab)
+      suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase)
+      suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase)
+      mime_tab[suffix1] || mime_tab[suffix2] || "application/octet-stream"
+    end
+    module_function :mime_type
+
+    #####
+
+    def parse_header(raw)
+      header = Hash.new([].freeze)
+      field = nil
+      raw.each{|line|
+        case line
+        when /^([A-Za-z0-9!\#$%&'*+\-.^_`|~]+):\s*(.*?)\s*\z/om
+          field, value = $1, $2
+          field.downcase!
+          header[field] = [] unless header.has_key?(field)
+          header[field] << value
+        when /^\s+(.*?)\s*\z/om
+          value = $1
+          unless field
+            raise "bad header '#{line.inspect}'."
+          end
+          header[field][-1] << " " << value
+        else
+          raise "bad header '#{line.inspect}'."
+        end
+      }
+      header.each{|key, values|
+        values.each{|value|
+          value.strip!
+          value.gsub!(/\s+/, " ")
+        }
+      }
+      header
+    end
+    module_function :parse_header
+
+    def split_header_value(str)
+      str.scan(/((?:"(?:\\.|[^"])+?"|[^",]+)+)
+                (?:,\s*|\Z)/xn).collect{|v| v[0] }
+    end
+    module_function :split_header_value
+
+    def parse_range_header(ranges_specifier)
+      if /^bytes=(.*)/ =~ ranges_specifier
+        byte_range_set = split_header_value($1)
+        byte_range_set.collect{|range_spec|
+          case range_spec
+          when /^(\d+)-(\d+)/ then $1.to_i .. $2.to_i
+          when /^(\d+)-/      then $1.to_i .. -1
+          when /^-(\d+)/      then -($1.to_i) .. -1
+          else return nil
+          end
+        }
+      end
+    end
+    module_function :parse_range_header
+
+    def parse_qvalues(value)
+      tmp = []
+      if value
+        parts = value.split(/,\s*/)
+        parts.each {|part|
+          if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
+            val = m[1]
+            q = (m[2] or 1).to_f
+            tmp.push([val, q])
+          end
+        }
+        tmp = tmp.sort_by{|val, q| -q}
+        tmp.collect!{|val, q| val}
+      end
+      return tmp
+    end
+    module_function :parse_qvalues
+
+    #####
+
+    def dequote(str)
+      ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup
+      ret.gsub!(/\\(.)/, "\\1")
+      ret
+    end
+    module_function :dequote
+
+    def quote(str)
+      '"' << str.gsub(/[\\\"]/o, "\\\1") << '"'
+    end
+    module_function :quote
+
+    #####
+
+    class FormData < String
+      EmptyRawHeader = [].freeze
+      EmptyHeader = {}.freeze
+
+      attr_accessor :name, :filename, :next_data
+      protected :next_data
+
+      def initialize(*args)
+        @name = @filename = @next_data = nil
+        if args.empty?
+          @raw_header = []
+          @header = nil
+          super("")
+        else
+          @raw_header = EmptyRawHeader
+          @header = EmptyHeader 
+          super(args.shift)
+          unless args.empty?
+            @next_data = self.class.new(*args)
+          end
+        end
+      end
+
+      def [](*key)
+        begin
+          @header[key[0].downcase].join(", ")
+        rescue StandardError, NameError
+          super
+        end
+      end
+
+      def <<(str)
+        if @header
+          super
+        elsif str == CRLF
+          @header = HTTPUtils::parse_header(@raw_header)
+          if cd = self['content-disposition']
+            if /\s+name="(.*?)"/ =~ cd then @name = $1 end
+            if /\s+filename="(.*?)"/ =~ cd then @filename = $1 end
+          end
+        else
+          @raw_header << str
+        end
+        self
+      end
+
+      def append_data(data)
+        tmp = self
+        while tmp
+          unless tmp.next_data 
+            tmp.next_data = data
+            break
+          end
+          tmp = tmp.next_data
+        end
+        self
+      end
+
+      def each_data
+        tmp = self
+        while tmp
+          next_data = tmp.next_data
+          yield(tmp)
+          tmp = next_data
+        end
+      end
+
+      def list
+        ret = []
+        each_data{|data|
+          ret << data.to_s
+        }
+        ret
+      end
+
+      alias :to_ary :list
+
+      def to_s
+        String.new(self)
+      end
+    end
+
+    def parse_query(str)
+      query = Hash.new
+      if str
+        str.split(/[&;]/).each{|x|
+          next if x.empty? 
+          key, val = x.split(/=/,2)
+          key = unescape_form(key)
+          val = unescape_form(val.to_s)
+          val = FormData.new(val)
+          val.name = key
+          if query.has_key?(key)
+            query[key].append_data(val)
+            next
+          end
+          query[key] = val
+        }
+      end
+      query
+    end
+    module_function :parse_query
+
+    def parse_form_data(io, boundary)
+      boundary_regexp = /\A--#{boundary}(--)?#{CRLF}\z/
+      form_data = Hash.new
+      return form_data unless io
+      data = nil
+      io.each{|line|
+        if boundary_regexp =~ line
+          if data
+            data.chop!
+            key = data.name
+            if form_data.has_key?(key)
+              form_data[key].append_data(data)
+            else
+              form_data[key] = data 
+            end
+          end
+          data = FormData.new
+          next
+        else
+          if data
+            data << line
+          end
+        end
+      }
+      return form_data
+    end
+    module_function :parse_form_data
+
+    #####
+
+    reserved = ';/?:@&=+$,'
+    num      = '0123456789'
+    lowalpha = 'abcdefghijklmnopqrstuvwxyz'
+    upalpha  = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+    mark     = '-_.!~*\'()'
+    unreserved = num + lowalpha + upalpha + mark
+    control  = (0x0..0x1f).collect{|c| c.chr }.join + "\x7f"
+    space    = " "
+    delims   = '<>#%"'
+    unwise   = '{}|\\^[]`'
+    nonascii = (0x80..0xff).collect{|c| c.chr }.join
+
+    module_function
+
+    def _make_regex(str) /([#{Regexp.escape(str)}])/n end
+    def _make_regex!(str) /([^#{Regexp.escape(str)}])/n end
+    def _escape(str, regex) str.gsub(regex){ "%%%02X" % $1[0] } end
+    def _unescape(str, regex) str.gsub(regex){ $1.hex.chr } end
+
+    UNESCAPED = _make_regex(control+space+delims+unwise+nonascii)
+    UNESCAPED_FORM = _make_regex(reserved+control+delims+unwise+nonascii)
+    NONASCII  = _make_regex(nonascii)
+    ESCAPED   = /%([0-9a-fA-F]{2})/
+    UNESCAPED_PCHAR = _make_regex!(unreserved+":@&=+$,")
+
+    def escape(str)
+      _escape(str, UNESCAPED)
+    end
+
+    def unescape(str)
+      _unescape(str, ESCAPED)
+    end
+
+    def escape_form(str)
+      ret = _escape(str, UNESCAPED_FORM)
+      ret.gsub!(/ /, "+")
+      ret
+    end
+
+    def unescape_form(str)
+      _unescape(str.gsub(/\+/, " "), ESCAPED)
+    end
+
+    def escape_path(str)
+      result = ""
+      str.scan(%r{/([^/]*)}).each{|i|
+        result << "/" << _escape(i[0], UNESCAPED_PCHAR)
+      }
+      return result
+    end
+
+    def escape8bit(str)
+      _escape(str, NONASCII)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpversion.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpversion.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/httpversion.rb	(revision 18425)
@@ -0,0 +1,49 @@
+#
+# HTTPVersion.rb -- presentation of HTTP version
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: httpversion.rb,v 1.5 2002/09/21 12:23:37 gotoyuzo Exp $
+
+module WEBrick
+  class HTTPVersion
+    include Comparable
+
+    attr_accessor :major, :minor
+
+    def self.convert(version)
+      version.is_a?(self) ? version : new(version)
+    end
+
+    def initialize(version)
+      case version
+      when HTTPVersion
+        @major, @minor = version.major, version.minor
+      when String
+        if /^(\d+)\.(\d+)$/ =~ version
+          @major, @minor = $1.to_i, $2.to_i
+        end
+      end
+      if @major.nil? || @minor.nil?
+        raise ArgumentError,
+          format("cannot convert %s into %s", version.class, self.class)
+      end
+    end
+
+    def <=>(other)
+      unless other.is_a?(self.class)
+        other = self.class.new(other)
+      end
+      if (ret = @major <=> other.major) == 0
+        return @minor <=> other.minor
+      end
+      return ret
+    end
+
+    def to_s
+      format("%d.%d", @major, @minor)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/log.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/log.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/log.rb	(revision 18425)
@@ -0,0 +1,88 @@
+#
+# log.rb -- Log Class
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: log.rb,v 1.26 2002/10/06 17:06:10 gotoyuzo Exp $
+
+module WEBrick
+  class BasicLog
+    # log-level constant
+    FATAL, ERROR, WARN, INFO, DEBUG = 1, 2, 3, 4, 5
+
+    attr_accessor :level
+
+    def initialize(log_file=nil, level=nil)
+      @level = level || INFO
+      case log_file
+      when String
+        @log = open(log_file, "a+")
+        @log.sync = true
+        @opened = true
+      when NilClass
+        @log = $stderr
+      else
+        @log = log_file  # requires "<<". (see BasicLog#log)
+      end
+    end
+
+    def close
+      @log.close if @opened
+      @log = nil
+    end
+
+    def log(level, data)
+      if @log && level <= @level
+        data += "\n" if /\n\Z/ !~ data
+        @log << data
+      end
+    end
+
+    def <<(obj)
+      log(INFO, obj.to_s)
+    end
+
+    def fatal(msg) log(FATAL, "FATAL " << format(msg)); end
+    def error(msg) log(ERROR, "ERROR " << format(msg)); end
+    def warn(msg)  log(WARN,  "WARN  " << format(msg)); end
+    def info(msg)  log(INFO,  "INFO  " << format(msg)); end
+    def debug(msg) log(DEBUG, "DEBUG " << format(msg)); end
+
+    def fatal?; @level >= FATAL; end
+    def error?; @level >= ERROR; end
+    def warn?;  @level >= WARN; end
+    def info?;  @level >= INFO; end
+    def debug?; @level >= DEBUG; end
+
+    private
+
+    def format(arg)
+      str = if arg.is_a?(Exception)
+        "#{arg.class}: #{arg.message}\n\t" <<
+        arg.backtrace.join("\n\t") << "\n"
+      elsif arg.respond_to?(:to_str)
+        arg.to_str
+      else
+        arg.inspect
+      end
+    end
+  end
+
+  class Log < BasicLog
+    attr_accessor :time_format 
+
+    def initialize(log_file=nil, level=nil)
+      super(log_file, level)
+      @time_format = "[%Y-%m-%d %H:%M:%S]"
+    end
+
+    def log(level, data)
+      tmp = Time.now.strftime(@time_format)
+      tmp << " " << data
+      super(level, tmp)
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/server.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/server.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/server.rb	(revision 18425)
@@ -0,0 +1,200 @@
+#
+# server.rb -- GenericServer Class
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: server.rb,v 1.62 2003/07/22 19:20:43 gotoyuzo Exp $
+
+require 'thread'
+require 'socket'
+require 'timeout'
+require 'webrick/config'
+require 'webrick/log'
+
+module WEBrick
+
+  class ServerError < StandardError; end
+
+  class SimpleServer
+    def SimpleServer.start
+      yield
+    end
+  end
+
+  class Daemon
+    def Daemon.start
+      exit!(0) if fork
+      Process::setsid
+      exit!(0) if fork
+      Dir::chdir("/")
+      File::umask(0)
+      STDIN.reopen("/dev/null")
+      STDOUT.reopen("/dev/null", "w")
+      STDERR.reopen("/dev/null", "w")
+      yield if block_given?
+    end
+  end
+
+  class GenericServer
+    attr_reader :status, :config, :logger, :tokens, :listeners
+
+    def initialize(config={}, default=Config::General)
+      @config = default.dup.update(config)
+      @status = :Stop
+      @config[:Logger] ||= Log::new
+      @logger = @config[:Logger]
+
+      @tokens = SizedQueue.new(@config[:MaxClients])
+      @config[:MaxClients].times{ @tokens.push(nil) }
+
+      webrickv = WEBrick::VERSION
+      rubyv = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
+      @logger.info("WEBrick #{webrickv}")
+      @logger.info("ruby #{rubyv}")
+
+      @listeners = []
+      unless @config[:DoNotListen]
+        if @config[:Listen]
+          warn(":Listen option is deprecated; use GenericServer#listen")
+        end
+        listen(@config[:BindAddress], @config[:Port])
+        if @config[:Port] == 0
+          @config[:Port] = @listeners[0].addr[1]
+        end
+      end
+    end
+
+    def [](key)
+      @config[key]
+    end
+
+    def listen(address, port)
+      @listeners += Utils::create_listeners(address, port, @logger)
+    end
+
+    def start(&block)
+      raise ServerError, "already started." if @status != :Stop
+      server_type = @config[:ServerType] || SimpleServer
+
+      server_type.start{
+        @logger.info \
+          "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}"
+        call_callback(:StartCallback)
+
+        thgroup = ThreadGroup.new
+        @status = :Running
+        while @status == :Running
+          begin
+            if svrs = IO.select(@listeners, nil, nil, 2.0)
+              svrs[0].each{|svr|
+                @tokens.pop          # blocks while no token is there.
+                if sock = accept_client(svr)
+                  th = start_thread(sock, &block)
+                  th[:WEBrickThread] = true
+                  thgroup.add(th)
+                else
+                  @tokens.push(nil)
+                end
+              }
+            end
+          rescue Errno::EBADF, IOError => ex
+            # if the listening socket was closed in GenericServer#shutdown,
+            # IO::select raise it.
+          rescue Exception => ex
+            msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
+            @logger.error msg
+          end
+        end
+
+        @logger.info "going to shutdown ..."
+        thgroup.list.each{|th| th.join if th[:WEBrickThread] }
+        call_callback(:StopCallback)
+        @logger.info "#{self.class}#start done."
+        @status = :Stop
+      }
+    end
+
+    def stop
+      if @status == :Running
+        @status = :Shutdown
+      end
+    end
+
+    def shutdown
+      stop
+      @listeners.each{|s|
+        if @logger.debug?
+          addr = s.addr
+          @logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})")
+        end
+        s.close
+      }
+      @listeners.clear
+    end
+
+    def run(sock)
+      @logger.fatal "run() must be provided by user."
+    end
+
+    private
+
+    def accept_client(svr)
+      sock = nil
+      begin
+        sock = svr.accept
+        sock.sync = true
+        Utils::set_non_blocking(sock)
+        Utils::set_close_on_exec(sock)
+      rescue Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPROTO => ex
+        # TCP connection was established but RST segment was sent
+        # from peer before calling TCPServer#accept.
+      rescue Exception => ex
+        msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
+        @logger.error msg
+      end
+      return sock
+    end
+
+    def start_thread(sock, &block)
+      Thread.start{
+        begin
+          Thread.current[:WEBrickSocket] = sock
+          begin
+            addr = sock.peeraddr
+            @logger.debug "accept: #{addr[3]}:#{addr[1]}"
+          rescue SocketError
+            @logger.debug "accept: <address unknown>"
+            raise
+          end
+          call_callback(:AcceptCallback, sock)
+          block ? block.call(sock) : run(sock)
+        rescue Errno::ENOTCONN
+          @logger.debug "Errno::ENOTCONN raised"
+        rescue ServerError => ex
+          msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
+          @logger.error msg
+        rescue Exception => ex
+          @logger.error ex
+        ensure
+          @tokens.push(nil)
+          Thread.current[:WEBrickSocket] = nil
+          if addr
+            @logger.debug "close: #{addr[3]}:#{addr[1]}"
+          else
+            @logger.debug "close: <address unknown>"
+          end
+          sock.close
+        end
+      }
+    end
+
+    def call_callback(callback_name, *args)
+      if cb = @config[callback_name]
+        cb.call(*args)
+      end
+    end
+  end    # end of GenericServer
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/ssl.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/ssl.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/ssl.rb	(revision 18425)
@@ -0,0 +1,126 @@
+#
+# ssl.rb -- SSL/TLS enhancement for GenericServer
+#
+# Copyright (c) 2003 GOTOU Yuuzou All rights reserved.
+# 
+# $Id: ssl.rb 11708 2007-02-12 23:01:19Z shyouhei $
+
+require 'webrick'
+require 'openssl'
+
+module WEBrick
+  module Config
+    svrsoft = General[:ServerSoftware]
+    osslv = ::OpenSSL::OPENSSL_VERSION.split[1]
+    SSL = {
+      :ServerSoftware       => "#{svrsoft} OpenSSL/#{osslv}",
+      :SSLEnable            => false,
+      :SSLCertificate       => nil,
+      :SSLPrivateKey        => nil,
+      :SSLClientCA          => nil,
+      :SSLExtraChainCert    => nil,
+      :SSLCACertificateFile => nil,
+      :SSLCACertificatePath => nil,
+      :SSLCertificateStore  => nil,
+      :SSLVerifyClient      => ::OpenSSL::SSL::VERIFY_NONE,
+      :SSLVerifyDepth       => nil,
+      :SSLVerifyCallback    => nil,   # custom verification
+      :SSLTimeout           => nil,
+      :SSLOptions           => nil,
+      :SSLStartImmediately  => true,
+      # Must specify if you use auto generated certificate.
+      :SSLCertName          => nil,
+      :SSLCertComment       => "Generated by Ruby/OpenSSL"
+    }
+    General.update(SSL)
+  end
+
+  module Utils
+    def create_self_signed_cert(bits, cn, comment)
+      rsa = OpenSSL::PKey::RSA.new(bits){|p, n|
+        case p
+        when 0; $stderr.putc "."  # BN_generate_prime
+        when 1; $stderr.putc "+"  # BN_generate_prime
+        when 2; $stderr.putc "*"  # searching good prime,  
+                                  # n = #of try,
+                                  # but also data from BN_generate_prime
+        when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q,
+                                  # but also data from BN_generate_prime
+        else;   $stderr.putc "*"  # BN_generate_prime
+        end
+      }
+      cert = OpenSSL::X509::Certificate.new
+      cert.version = 3
+      cert.serial = 0
+      name = OpenSSL::X509::Name.new(cn)
+      cert.subject = name
+      cert.issuer = name
+      cert.not_before = Time.now
+      cert.not_after = Time.now + (365*24*60*60)
+      cert.public_key = rsa.public_key
+
+      ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
+      ef.issuer_certificate = cert
+      cert.extensions = [
+        ef.create_extension("basicConstraints","CA:FALSE"),
+        ef.create_extension("keyUsage", "keyEncipherment"),
+        ef.create_extension("subjectKeyIdentifier", "hash"),
+        ef.create_extension("extendedKeyUsage", "serverAuth"),
+        ef.create_extension("nsComment", comment),
+      ]
+      aki = ef.create_extension("authorityKeyIdentifier",
+                                "keyid:always,issuer:always")
+      cert.add_extension(aki)
+      cert.sign(rsa, OpenSSL::Digest::SHA1.new)
+
+      return [ cert, rsa ]
+    end
+    module_function :create_self_signed_cert
+  end
+
+  class GenericServer
+    def ssl_context
+      @ssl_context ||= nil
+    end
+
+    def listen(address, port)
+      listeners = Utils::create_listeners(address, port, @logger)
+      if @config[:SSLEnable]
+        unless ssl_context
+          @ssl_context = setup_ssl_context(@config)
+          @logger.info("\n" + @config[:SSLCertificate].to_text) 
+        end
+        listeners.collect!{|svr|
+          ssvr = ::OpenSSL::SSL::SSLServer.new(svr, ssl_context)
+          ssvr.start_immediately = @config[:SSLStartImmediately]
+          ssvr
+        }
+      end
+      @listeners += listeners
+    end
+
+    def setup_ssl_context(config)
+      unless config[:SSLCertificate]
+        cn = config[:SSLCertName]
+        comment = config[:SSLCertComment]
+        cert, key = Utils::create_self_signed_cert(1024, cn, comment)
+        config[:SSLCertificate] = cert
+        config[:SSLPrivateKey] = key
+      end
+      ctx = OpenSSL::SSL::SSLContext.new
+      ctx.key = config[:SSLPrivateKey]
+      ctx.cert = config[:SSLCertificate]
+      ctx.client_ca = config[:SSLClientCA]
+      ctx.extra_chain_cert = config[:SSLExtraChainCert]
+      ctx.ca_file = config[:SSLCACertificateFile]
+      ctx.ca_path = config[:SSLCACertificatePath]
+      ctx.cert_store = config[:SSLCertificateStore]
+      ctx.verify_mode = config[:SSLVerifyClient]
+      ctx.verify_depth = config[:SSLVerifyDepth]
+      ctx.verify_callback = config[:SSLVerifyCallback]
+      ctx.timeout = config[:SSLTimeout]
+      ctx.options = config[:SSLOptions]
+      ctx
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/utils.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/utils.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/utils.rb	(revision 18425)
@@ -0,0 +1,100 @@
+#
+# utils.rb -- Miscellaneous utilities
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: utils.rb,v 1.10 2003/02/16 22:22:54 gotoyuzo Exp $
+
+require 'socket'
+require 'fcntl'
+begin
+  require 'etc'
+rescue LoadError
+  nil
+end
+
+module WEBrick
+  module Utils
+    def set_non_blocking(io)
+      flag = File::NONBLOCK
+      if defined?(Fcntl::F_GETFL)
+        flag |= io.fcntl(Fcntl::F_GETFL)
+      end
+      io.fcntl(Fcntl::F_SETFL, flag)
+    end
+    module_function :set_non_blocking
+
+    def set_close_on_exec(io)
+      if defined?(Fcntl::FD_CLOEXEC)
+        io.fcntl(Fcntl::FD_CLOEXEC, 1)
+      end
+    end
+    module_function :set_close_on_exec
+
+    def su(user)
+      if defined?(Etc)
+        pw = Etc.getpwnam(user)
+        Process::initgroups(user, pw.gid)
+        Process::Sys::setgid(pw.gid)
+        Process::Sys::setuid(pw.uid)
+      else
+        warn("WEBrick::Utils::su doesn't work on this platform")
+      end
+    end
+    module_function :su
+
+    def getservername
+      host = Socket::gethostname
+      begin
+        Socket::gethostbyname(host)[0]
+      rescue
+        host
+      end
+    end
+    module_function :getservername
+
+    def create_listeners(address, port, logger=nil)
+      unless port
+        raise ArgumentError, "must specify port"
+      end
+      res = Socket::getaddrinfo(address, port,
+                                Socket::AF_UNSPEC,   # address family
+                                Socket::SOCK_STREAM, # socket type
+                                0,                   # protocol
+                                Socket::AI_PASSIVE)  # flag
+      last_error = nil
+      sockets = []
+      res.each{|ai|
+        begin
+          logger.debug("TCPServer.new(#{ai[3]}, #{port})") if logger
+          sock = TCPServer.new(ai[3], port)
+          port = sock.addr[1] if port == 0
+          Utils::set_close_on_exec(sock)
+          sockets << sock
+        rescue => ex
+          logger.warn("TCPServer Error: #{ex}") if logger
+          last_error  = ex
+        end
+      }
+      raise last_error if sockets.empty?
+      return sockets
+    end
+    module_function :create_listeners
+
+    RAND_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+                 "0123456789" +
+                 "abcdefghijklmnopqrstuvwxyz" 
+
+    def random_string(len)
+      rand_max = RAND_CHARS.size
+      ret = "" 
+      len.times{ ret << RAND_CHARS[rand(rand_max)] }
+      ret 
+    end
+    module_function :random_string
+
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/version.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/version.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/webrick/version.rb	(revision 18425)
@@ -0,0 +1,13 @@
+#
+# version.rb -- version and release date
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: version.rb,v 1.74 2003/07/22 19:20:43 gotoyuzo Exp $
+
+module WEBrick
+  VERSION      = "1.3.1"
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/binding.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/binding.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/binding.rb	(revision 18425)
@@ -0,0 +1,65 @@
+# WSDL4R - WSDL binding definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'xsd/namedelements'
+
+
+module WSDL
+
+
+class Binding < Info
+  attr_reader :name		# required
+  attr_reader :type		# required
+  attr_reader :operations
+  attr_reader :soapbinding
+
+  def initialize
+    super
+    @name = nil
+    @type = nil
+    @operations = XSD::NamedElements.new
+    @soapbinding = nil
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def parse_element(element)
+    case element
+    when OperationName
+      o = OperationBinding.new
+      @operations << o
+      o
+    when SOAPBindingName
+      o = WSDL::SOAP::Binding.new
+      @soapbinding = o
+      o
+    when DocumentationName
+      o = Documentation.new
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NameAttrName
+      @name = XSD::QName.new(targetnamespace, value.source)
+    when TypeAttrName
+      @type = value
+    else
+      nil
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/data.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/data.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/data.rb	(revision 18425)
@@ -0,0 +1,64 @@
+# WSDL4R - WSDL data definitions.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/qname'
+require 'wsdl/documentation'
+require 'wsdl/definitions'
+require 'wsdl/types'
+require 'wsdl/message'
+require 'wsdl/part'
+require 'wsdl/portType'
+require 'wsdl/operation'
+require 'wsdl/param'
+require 'wsdl/binding'
+require 'wsdl/operationBinding'
+require 'wsdl/service'
+require 'wsdl/port'
+require 'wsdl/import'
+
+
+module WSDL
+
+
+ArrayTypeAttrName = XSD::QName.new(Namespace, 'arrayType')
+BindingName = XSD::QName.new(Namespace, 'binding')
+DefinitionsName = XSD::QName.new(Namespace, 'definitions')
+DocumentationName = XSD::QName.new(Namespace, 'documentation')
+FaultName = XSD::QName.new(Namespace, 'fault')
+ImportName = XSD::QName.new(Namespace, 'import')
+InputName = XSD::QName.new(Namespace, 'input')
+MessageName = XSD::QName.new(Namespace, 'message')
+OperationName = XSD::QName.new(Namespace, 'operation')
+OutputName = XSD::QName.new(Namespace, 'output')
+PartName = XSD::QName.new(Namespace, 'part')
+PortName = XSD::QName.new(Namespace, 'port')
+PortTypeName = XSD::QName.new(Namespace, 'portType')
+ServiceName = XSD::QName.new(Namespace, 'service')
+TypesName = XSD::QName.new(Namespace, 'types')
+
+SchemaName = XSD::QName.new(XSD::Namespace, 'schema')
+
+SOAPAddressName = XSD::QName.new(SOAPBindingNamespace, 'address')
+SOAPBindingName = XSD::QName.new(SOAPBindingNamespace, 'binding')
+SOAPHeaderName = XSD::QName.new(SOAPBindingNamespace, 'header')
+SOAPBodyName = XSD::QName.new(SOAPBindingNamespace, 'body')
+SOAPFaultName = XSD::QName.new(SOAPBindingNamespace, 'fault')
+SOAPOperationName = XSD::QName.new(SOAPBindingNamespace, 'operation')
+
+BindingAttrName = XSD::QName.new(nil, 'binding')
+ElementAttrName = XSD::QName.new(nil, 'element')
+LocationAttrName = XSD::QName.new(nil, 'location')
+MessageAttrName = XSD::QName.new(nil, 'message')
+NameAttrName = XSD::QName.new(nil, 'name')
+NamespaceAttrName = XSD::QName.new(nil, 'namespace')
+ParameterOrderAttrName = XSD::QName.new(nil, 'parameterOrder')
+TargetNamespaceAttrName = XSD::QName.new(nil, 'targetNamespace')
+TypeAttrName = XSD::QName.new(nil, 'type')
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/definitions.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/definitions.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/definitions.rb	(revision 18425)
@@ -0,0 +1,250 @@
+# WSDL4R - WSDL definitions.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'xsd/namedelements'
+
+
+module WSDL
+
+
+class Definitions < Info
+  attr_reader :name
+  attr_reader :targetnamespace
+  attr_reader :imports
+
+  attr_accessor :location
+  attr_reader :importedschema
+
+  def initialize
+    super
+    @name = nil
+    @targetnamespace = nil
+    @location = nil
+    @importedschema = {}
+
+    @types = nil
+    @imports = []
+    @messages = XSD::NamedElements.new
+    @porttypes = XSD::NamedElements.new
+    @bindings = XSD::NamedElements.new
+    @services = XSD::NamedElements.new
+
+    @anontypes = XSD::NamedElements.new
+    @root = self
+  end
+
+  def inspect
+    sprintf("#<%s:0x%x %s>", self.class.name, __id__, @name || '(unnamed)')
+  end
+
+  def targetnamespace=(targetnamespace)
+    @targetnamespace = targetnamespace
+    if @name
+      @name = XSD::QName.new(@targetnamespace, @name.name)
+    end
+  end
+
+  def collect_attributes
+    result = XSD::NamedElements.new
+    if @types
+      @types.schemas.each do |schema|
+	result.concat(schema.collect_attributes)
+      end
+    end
+    @imports.each do |import|
+      result.concat(import.content.collect_attributes)
+    end
+    result
+  end
+
+  def collect_elements
+    result = XSD::NamedElements.new
+    if @types
+      @types.schemas.each do |schema|
+	result.concat(schema.collect_elements)
+      end
+    end
+    @imports.each do |import|
+      result.concat(import.content.collect_elements)
+    end
+    result
+  end
+
+  def collect_complextypes
+    result = @anontypes.dup
+    if @types
+      @types.schemas.each do |schema|
+	result.concat(schema.collect_complextypes)
+      end
+    end
+    @imports.each do |import|
+      result.concat(import.content.collect_complextypes)
+    end
+    result
+  end
+
+  def collect_simpletypes
+    result = XSD::NamedElements.new
+    if @types
+      @types.schemas.each do |schema|
+	result.concat(schema.collect_simpletypes)
+      end
+    end
+    @imports.each do |import|
+      result.concat(import.content.collect_simpletypes)
+    end
+    result
+  end
+
+  # ToDo: simpletype must be accepted...
+  def add_type(complextype)
+    @anontypes << complextype
+  end
+
+  def messages
+    result = @messages.dup
+    @imports.each do |import|
+      result.concat(import.content.messages) if self.class === import.content
+    end
+    result
+  end
+
+  def porttypes
+    result = @porttypes.dup
+    @imports.each do |import|
+      result.concat(import.content.porttypes) if self.class === import.content
+    end
+    result
+  end
+
+  def bindings
+    result = @bindings.dup
+    @imports.each do |import|
+      result.concat(import.content.bindings) if self.class === import.content
+    end
+    result
+  end
+
+  def services
+    result = @services.dup
+    @imports.each do |import|
+      result.concat(import.content.services) if self.class === import.content
+    end
+    result
+  end
+
+  def message(name)
+    message = @messages[name]
+    return message if message
+    @imports.each do |import|
+      message = import.content.message(name) if self.class === import.content
+      return message if message
+    end
+    nil
+  end
+
+  def porttype(name)
+    porttype = @porttypes[name]
+    return porttype if porttype
+    @imports.each do |import|
+      porttype = import.content.porttype(name) if self.class === import.content
+      return porttype if porttype
+    end
+    nil
+  end
+
+  def binding(name)
+    binding = @bindings[name]
+    return binding if binding
+    @imports.each do |import|
+      binding = import.content.binding(name) if self.class === import.content
+      return binding if binding
+    end
+    nil
+  end
+
+  def service(name)
+    service = @services[name]
+    return service if service
+    @imports.each do |import|
+      service = import.content.service(name) if self.class === import.content
+      return service if service
+    end
+    nil
+  end
+
+  def porttype_binding(name)
+    binding = @bindings.find { |item| item.type == name }
+    return binding if binding
+    @imports.each do |import|
+      binding = import.content.porttype_binding(name) if self.class === import.content
+      return binding if binding
+    end
+    nil
+  end
+
+  def parse_element(element)
+    case element
+    when ImportName
+      o = Import.new
+      @imports << o
+      o
+    when TypesName
+      o = Types.new
+      @types = o
+      o
+    when MessageName
+      o = Message.new
+      @messages << o
+      o
+    when PortTypeName
+      o = PortType.new
+      @porttypes << o
+      o
+    when BindingName
+      o = Binding.new
+      @bindings << o
+      o
+    when ServiceName
+      o = Service.new
+      @services << o
+      o
+    when DocumentationName
+      o = Documentation.new
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NameAttrName
+      @name = XSD::QName.new(targetnamespace, value.source)
+    when TargetNamespaceAttrName
+      self.targetnamespace = value.source
+    else
+      nil
+    end
+  end
+
+  def self.parse_element(element)
+    if element == DefinitionsName
+      Definitions.new
+    else
+      nil
+    end
+  end
+
+private
+
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/documentation.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/documentation.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/documentation.rb	(revision 18425)
@@ -0,0 +1,32 @@
+# WSDL4R - WSDL SOAP documentation element.
+# Copyright (C) 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+
+
+class Documentation < Info
+  def initialize
+    super
+  end
+
+  def parse_element(element)
+    # Accepts any element.
+    self
+  end
+
+  def parse_attr(attr, value)
+    # Accepts any attribute.
+    true
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/import.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/import.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/import.rb	(revision 18425)
@@ -0,0 +1,80 @@
+# WSDL4R - WSDL import definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'wsdl/importer'
+
+
+module WSDL
+
+
+class Import < Info
+  attr_reader :namespace
+  attr_reader :location
+  attr_reader :content
+
+  def initialize
+    super
+    @namespace = nil
+    @location = nil
+    @content = nil
+    @web_client = nil
+  end
+
+  def parse_element(element)
+    case element
+    when DocumentationName
+      o = Documentation.new
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NamespaceAttrName
+      @namespace = value.source
+      if @content
+	@content.targetnamespace = @namespace
+      end
+      @namespace
+    when LocationAttrName
+      @location = URI.parse(value.source)
+      if @location.relative? and !parent.location.nil? and
+          !parent.location.relative?
+        @location = parent.location + @location
+      end
+      if root.importedschema.key?(@location)
+        @content = root.importedschema[@location]
+      else
+        root.importedschema[@location] = nil      # placeholder
+        @content = import(@location)
+        if @content.is_a?(Definitions)
+          @content.root = root
+          if @namespace
+            @content.targetnamespace = @namespace
+          end
+        end
+        root.importedschema[@location] = @content
+      end
+      @location
+    else
+      nil
+    end
+  end
+
+private
+
+  def import(location)
+    Importer.import(location, root)
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/importer.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/importer.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/importer.rb	(revision 18425)
@@ -0,0 +1,38 @@
+# WSDL4R - WSDL importer library.
+# Copyright (C) 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/xmlSchema/importer'
+require 'wsdl/parser'
+
+
+module WSDL
+
+
+class Importer < WSDL::XMLSchema::Importer
+  def self.import(location, originalroot = nil)
+    new.import(location, originalroot)
+  end
+
+private
+
+  def parse(content, location, originalroot)
+    opt = {
+      :location => location,
+      :originalroot => originalroot
+    }
+    begin
+      WSDL::Parser.new(opt).parse(content)
+    rescue WSDL::Parser::ParseError
+      super(content, location, originalroot)
+    end
+  end
+
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/info.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/info.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/info.rb	(revision 18425)
@@ -0,0 +1,39 @@
+# WSDL4R - WSDL information base.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+module WSDL
+
+
+class Info
+  attr_accessor :root
+  attr_accessor :parent
+  attr_accessor :id
+
+  def initialize
+    @root = nil
+    @parent = nil
+    @id = nil
+  end
+
+  def inspect
+    if self.respond_to?(:name)
+      sprintf("#<%s:0x%x %s>", self.class.name, __id__, self.name)
+    else
+      sprintf("#<%s:0x%x>", self.class.name, __id__)
+    end
+  end
+
+  def parse_element(element); end	# abstract
+  
+  def parse_attr(attr, value); end	# abstract
+
+  def parse_epilogue; end		# abstract
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/message.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/message.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/message.rb	(revision 18425)
@@ -0,0 +1,54 @@
+# WSDL4R - WSDL message definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+
+
+class Message < Info
+  attr_reader :name	# required
+  attr_reader :parts
+
+  def initialize
+    super
+    @name = nil
+    @parts = []
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def parse_element(element)
+    case element
+    when PartName
+      o = Part.new
+      @parts << o
+      o
+    when DocumentationName
+      o = Documentation.new
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NameAttrName
+      @name = XSD::QName.new(parent.targetnamespace, value.source)
+    else
+      nil
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/operation.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/operation.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/operation.rb	(revision 18425)
@@ -0,0 +1,130 @@
+# WSDL4R - WSDL operation definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+
+
+class Operation < Info
+  class NameInfo
+    attr_reader :op_name
+    attr_reader :optype_name
+    attr_reader :parts
+    def initialize(op_name, optype_name, parts)
+      @op_name = op_name
+      @optype_name = optype_name
+      @parts = parts
+    end
+  end
+
+  attr_reader :name		# required
+  attr_reader :parameter_order	# optional
+  attr_reader :input
+  attr_reader :output
+  attr_reader :fault
+  attr_reader :type		# required
+
+  def initialize
+    super
+    @name = nil
+    @type = nil
+    @parameter_order = nil
+    @input = nil
+    @output = nil
+    @fault = []
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def input_info
+    typename = input.find_message.name
+    NameInfo.new(@name, typename, inputparts)
+  end
+
+  def output_info
+    typename = output.find_message.name
+    NameInfo.new(@name, typename, outputparts)
+  end
+
+  def inputparts
+    sort_parts(input.find_message.parts)
+  end
+
+  def inputname
+    XSD::QName.new(targetnamespace, input.name ? input.name.name : @name.name)
+  end
+
+  def outputparts
+    sort_parts(output.find_message.parts)
+  end
+
+  def outputname
+    XSD::QName.new(targetnamespace,
+      output.name ? output.name.name : @name.name + 'Response')
+  end
+
+  def parse_element(element)
+    case element
+    when InputName
+      o = Param.new
+      @input = o
+      o
+    when OutputName
+      o = Param.new
+      @output = o
+      o
+    when FaultName
+      o = Param.new
+      @fault << o
+      o
+    when DocumentationName
+      o = Documentation.new
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NameAttrName
+      @name = XSD::QName.new(targetnamespace, value.source)
+    when TypeAttrName
+      @type = value
+    when ParameterOrderAttrName
+      @parameter_order = value.source.split(/\s+/)
+    else
+      nil
+    end
+  end
+
+private
+
+  def sort_parts(parts)
+    return parts.dup unless parameter_order
+    result = []
+    parameter_order.each do |orderitem|
+      if (ele = parts.find { |part| part.name == orderitem })
+	result << ele
+      end
+    end
+    if result.length == 0
+      return parts.dup
+    end
+    # result length can be shorter than parts's.
+    # return part must not be a part of the parameterOrder.
+    result
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/operationBinding.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/operationBinding.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/operationBinding.rb	(revision 18425)
@@ -0,0 +1,108 @@
+# WSDL4R - WSDL bound operation definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+
+
+class OperationBinding < Info
+  attr_reader :name		# required
+  attr_reader :input
+  attr_reader :output
+  attr_reader :fault
+  attr_reader :soapoperation
+
+  def initialize
+    super
+    @name = nil
+    @input = nil
+    @output = nil
+    @fault = []
+    @soapoperation = nil
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def porttype
+    root.porttype(parent.type)
+  end
+
+  def find_operation
+    porttype.operations[@name] or raise RuntimeError.new("#{@name} not found")
+  end
+
+  def soapoperation_name
+    if @soapoperation
+      @soapoperation.input_info.op_name
+    else
+      find_operation.name
+    end
+  end
+
+  def soapoperation_style
+    style = nil
+    if @soapoperation
+      style = @soapoperation.operation_style
+    elsif parent.soapbinding
+      style = parent.soapbinding.style
+    else
+      raise TypeError.new("operation style definition not found")
+    end
+    style || :document
+  end
+
+  def soapaction
+    if @soapoperation
+      @soapoperation.soapaction
+    else
+      nil
+    end
+  end
+
+  def parse_element(element)
+    case element
+    when InputName
+      o = Param.new
+      @input = o
+      o
+    when OutputName
+      o = Param.new
+      @output = o
+      o
+    when FaultName
+      o = Param.new
+      @fault << o
+      o
+    when SOAPOperationName
+      o = WSDL::SOAP::Operation.new
+      @soapoperation = o
+      o
+    when DocumentationName
+      o = Documentation.new
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NameAttrName
+      @name = XSD::QName.new(targetnamespace, value.source)
+    else
+      nil
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/param.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/param.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/param.rb	(revision 18425)
@@ -0,0 +1,85 @@
+# WSDL4R - WSDL param definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+
+
+class Param < Info
+  attr_reader :message	# required
+  attr_reader :name	# optional but required for fault.
+  attr_reader :soapbody
+  attr_reader :soapheader
+  attr_reader :soapfault
+
+  def initialize
+    super
+    @message = nil
+    @name = nil
+    @soapbody = nil
+    @soapheader = []
+    @soapfault = nil
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def find_message
+    root.message(@message) or raise RuntimeError.new("#{@message} not found")
+  end
+
+  def soapbody_use
+    if @soapbody
+      @soapbody.use || :literal
+    else
+      raise RuntimeError.new("soap:body not found")
+    end
+  end
+
+  def parse_element(element)
+    case element
+    when SOAPBodyName
+      o = WSDL::SOAP::Body.new
+      @soapbody = o
+      o
+    when SOAPHeaderName
+      o = WSDL::SOAP::Header.new
+      @soapheader << o
+      o
+    when SOAPFaultName
+      o = WSDL::SOAP::Fault.new
+      @soap_fault = o
+      o
+    when DocumentationName
+      o = Documentation.new
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when MessageAttrName
+      if value.namespace.nil?
+        value = XSD::QName.new(targetnamespace, value.source)
+      end
+      @message = value
+    when NameAttrName
+      @name = XSD::QName.new(targetnamespace, value.source)
+    else
+      nil
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/parser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/parser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/parser.rb	(revision 18425)
@@ -0,0 +1,163 @@
+# WSDL4R - WSDL XML Instance parser library.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/qname'
+require 'xsd/ns'
+require 'xsd/charset'
+require 'xsd/datatypes'
+require 'xsd/xmlparser'
+require 'wsdl/wsdl'
+require 'wsdl/data'
+require 'wsdl/xmlSchema/data'
+require 'wsdl/soap/data'
+
+
+module WSDL
+
+
+class Parser
+  include WSDL
+
+  class ParseError < Error; end
+  class FormatDecodeError < ParseError; end
+  class UnknownElementError < FormatDecodeError; end
+  class UnknownAttributeError < FormatDecodeError; end
+  class UnexpectedElementError < FormatDecodeError; end
+  class ElementConstraintError < FormatDecodeError; end
+  class AttributeConstraintError < FormatDecodeError; end
+
+private
+
+  class ParseFrame
+    attr_reader :ns
+    attr_reader :name
+    attr_accessor :node
+
+  private
+
+    def initialize(ns, name, node)
+      @ns = ns
+      @name = name
+      @node = node
+    end
+  end
+
+public
+
+  def initialize(opt = {})
+    @parser = XSD::XMLParser.create_parser(self, opt)
+    @parsestack = nil
+    @lastnode = nil
+    @ignored = {}
+    @location = opt[:location]
+    @originalroot = opt[:originalroot]
+  end
+
+  def parse(string_or_readable)
+    @parsestack = []
+    @lastnode = nil
+    @textbuf = ''
+    @parser.do_parse(string_or_readable)
+    @lastnode
+  end
+
+  def charset
+    @parser.charset
+  end
+
+  def start_element(name, attrs)
+    lastframe = @parsestack.last
+    ns = parent = nil
+    if lastframe
+      ns = lastframe.ns.clone_ns
+      parent = lastframe.node
+    else
+      ns = XSD::NS.new
+      parent = nil
+    end
+    attrs = XSD::XMLParser.filter_ns(ns, attrs)
+    node = decode_tag(ns, name, attrs, parent)
+    @parsestack << ParseFrame.new(ns, name, node)
+  end
+
+  def characters(text)
+    lastframe = @parsestack.last
+    if lastframe
+      # Need not to be cloned because character does not have attr.
+      ns = lastframe.ns
+      decode_text(ns, text)
+    else
+      p text if $DEBUG
+    end
+  end
+
+  def end_element(name)
+    lastframe = @parsestack.pop
+    unless name == lastframe.name
+      raise UnexpectedElementError.new("closing element name '#{name}' does not match with opening element '#{lastframe.name}'")
+    end
+    decode_tag_end(lastframe.ns, lastframe.node)
+    @lastnode = lastframe.node
+  end
+
+private
+
+  def decode_tag(ns, name, attrs, parent)
+    o = nil
+    elename = ns.parse(name)
+    if !parent
+      if elename == DefinitionsName
+	o = Definitions.parse_element(elename)
+        o.location = @location
+      else
+	raise UnknownElementError.new("unknown element: #{elename}")
+      end
+      o.root = @originalroot if @originalroot   # o.root = o otherwise
+    else
+      if elename == XMLSchema::AnnotationName
+        # only the first annotation element is allowed for each xsd element.
+        o = XMLSchema::Annotation.new
+      else
+        o = parent.parse_element(elename)
+      end
+      unless o
+        unless @ignored.key?(elename)
+          warn("ignored element: #{elename}")
+          @ignored[elename] = elename
+        end
+	o = Documentation.new	# which accepts any element.
+      end
+      # node could be a pseudo element.  pseudo element has its own parent.
+      o.root = parent.root
+      o.parent = parent if o.parent.nil?
+    end
+    attrs.each do |key, value|
+      attr_ele = ns.parse(key, true)
+      value_ele = ns.parse(value, true)
+      value_ele.source = value  # for recovery; value may not be a QName
+      unless o.parse_attr(attr_ele, value_ele)
+        unless @ignored.key?(attr_ele)
+          warn("ignored attr: #{attr_ele}")
+          @ignored[attr_ele] = attr_ele
+        end
+      end
+    end
+    o
+  end
+
+  def decode_tag_end(ns, node)
+    node.parse_epilogue
+  end
+
+  def decode_text(ns, text)
+    @textbuf << text
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/part.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/part.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/part.rb	(revision 18425)
@@ -0,0 +1,52 @@
+# WSDL4R - WSDL part definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+
+
+class Part < Info
+  attr_reader :name	# required
+  attr_reader :element	# optional
+  attr_reader :type	# optional
+
+  def initialize
+    super
+    @name = nil
+    @element = nil
+    @type = nil
+  end
+
+  def parse_element(element)
+    case element
+    when DocumentationName
+      o = Documentation.new
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NameAttrName
+      @name = value.source
+    when ElementAttrName
+      @element = value
+    when TypeAttrName
+      @type = value
+    else
+      nil
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/port.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/port.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/port.rb	(revision 18425)
@@ -0,0 +1,84 @@
+# WSDL4R - WSDL port definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+
+
+class Port < Info
+  attr_reader :name		# required
+  attr_reader :binding		# required
+  attr_reader :soap_address
+
+  def initialize
+    super
+    @name = nil
+    @binding = nil
+    @soap_address = nil
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def porttype
+    root.porttype(find_binding.type)
+  end
+
+  def find_binding
+    root.binding(@binding) or raise RuntimeError.new("#{@binding} not found")
+  end
+
+  def inputoperation_map
+    result = {}
+    find_binding.operations.each do |op_bind|
+      op_info = op_bind.soapoperation.input_info
+      result[op_info.op_name] = op_info
+    end
+    result
+  end
+
+  def outputoperation_map
+    result = {}
+    find_binding.operations.each do |op_bind|
+      op_info = op_bind.soapoperation.output_info
+      result[op_info.op_name] = op_info
+    end
+    result
+  end
+
+  def parse_element(element)
+    case element
+    when SOAPAddressName
+      o = WSDL::SOAP::Address.new
+      @soap_address = o
+      o
+    when DocumentationName
+      o = Documentation.new
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NameAttrName
+      @name = XSD::QName.new(targetnamespace, value.source)
+    when BindingAttrName
+      @binding = value
+    else
+      nil
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/portType.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/portType.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/portType.rb	(revision 18425)
@@ -0,0 +1,73 @@
+# WSDL4R - WSDL portType definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'xsd/namedelements'
+
+
+module WSDL
+
+
+class PortType < Info
+  attr_reader :name		# required
+  attr_reader :operations
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def initialize
+    super
+    @name = nil
+    @operations = XSD::NamedElements.new
+  end
+
+  def find_binding
+    root.bindings.find { |item| item.type == @name } or
+      raise RuntimeError.new("#{@name} not found")
+  end
+
+  def locations
+    bind_name = find_binding.name
+    result = []
+    root.services.each do |service|
+      service.ports.each do |port|
+        if port.binding == bind_name
+          result << port.soap_address.location if port.soap_address
+        end
+      end
+    end
+    result
+  end
+
+  def parse_element(element)
+    case element
+    when OperationName
+      o = Operation.new
+      @operations << o
+      o
+    when DocumentationName
+      o = Documentation.new
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NameAttrName
+      @name = XSD::QName.new(targetnamespace, value.source)
+    else
+      nil
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/service.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/service.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/service.rb	(revision 18425)
@@ -0,0 +1,61 @@
+# WSDL4R - WSDL service definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'xsd/namedelements'
+
+
+module WSDL
+
+
+class Service < Info
+  attr_reader :name		# required
+  attr_reader :ports
+  attr_reader :soap_address
+
+  def initialize
+    super
+    @name = nil
+    @ports = XSD::NamedElements.new
+    @soap_address = nil
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def parse_element(element)
+    case element
+    when PortName
+      o = Port.new
+      @ports << o
+      o
+    when SOAPAddressName
+      o = WSDL::SOAP::Address.new
+      @soap_address = o
+      o
+    when DocumentationName
+      o = Documentation.new
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NameAttrName
+      @name = XSD::QName.new(targetnamespace, value.source)
+    else
+      nil
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/address.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/address.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/address.rb	(revision 18425)
@@ -0,0 +1,40 @@
+# WSDL4R - WSDL SOAP address definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module SOAP
+
+
+class Address < Info
+  attr_reader :location
+
+  def initialize
+    super
+    @location = nil
+  end
+
+  def parse_element(element)
+    nil
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when LocationAttrName
+      @location = value.source
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/binding.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/binding.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/binding.rb	(revision 18425)
@@ -0,0 +1,49 @@
+# WSDL4R - WSDL SOAP binding definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module SOAP
+
+
+class Binding < Info
+  attr_reader :style
+  attr_reader :transport
+
+  def initialize
+    super
+    @style = nil
+    @transport = nil
+  end
+
+  def parse_element(element)
+    nil
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when StyleAttrName
+      if ["document", "rpc"].include?(value.source)
+	@style = value.source.intern
+      else
+	raise Parser::AttributeConstraintError.new(
+          "Unexpected value #{ value }.")
+      end
+    when TransportAttrName
+      @transport = value.source
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/body.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/body.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/body.rb	(revision 18425)
@@ -0,0 +1,56 @@
+# WSDL4R - WSDL SOAP body definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module SOAP
+
+
+class Body < Info
+  attr_reader :parts
+  attr_reader :use	# required
+  attr_reader :encodingstyle
+  attr_reader :namespace
+
+  def initialize
+    super
+    @parts = nil
+    @use = nil
+    @encodingstyle = nil
+    @namespace = nil
+  end
+
+  def parse_element(element)
+    nil
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when PartsAttrName
+      @parts = value.source
+    when UseAttrName
+      if ['literal', 'encoded'].include?(value.source)
+        @use = value.source.intern
+      else
+        raise RuntimeError.new("unknown use of soap:body: #{value.source}")
+      end
+    when EncodingStyleAttrName
+      @encodingstyle = value.source
+    when NamespaceAttrName
+      @namespace = value.source
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/cgiStubCreator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/cgiStubCreator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/cgiStubCreator.rb	(revision 18425)
@@ -0,0 +1,76 @@
+# WSDL4R - Creating CGI stub code from WSDL.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'wsdl/soap/mappingRegistryCreator'
+require 'wsdl/soap/methodDefCreator'
+require 'wsdl/soap/classDefCreatorSupport'
+
+
+module WSDL
+module SOAP
+
+
+class CGIStubCreator
+  include ClassDefCreatorSupport
+
+  attr_reader :definitions
+
+  def initialize(definitions)
+    @definitions = definitions
+  end
+
+  def dump(service_name)
+    warn("CGI stub can have only 1 port.  Creating stub for the first port...  Rests are ignored.")
+    port = @definitions.service(service_name).ports[0]
+    dump_porttype(port.porttype.name)
+  end
+
+private
+
+  def dump_porttype(name)
+    class_name = create_class_name(name)
+    methoddef, types = MethodDefCreator.new(@definitions).dump(name)
+    mr_creator = MappingRegistryCreator.new(@definitions)
+    c1 = XSD::CodeGen::ClassDef.new(class_name)
+    c1.def_require("soap/rpc/cgistub")
+    c1.def_require("soap/mapping/registry")
+    c1.def_const("MappingRegistry", "::SOAP::Mapping::Registry.new")
+    c1.def_code(mr_creator.dump(types))
+    c1.def_code <<-EOD
+Methods = [
+#{methoddef.gsub(/^/, "  ")}
+]
+    EOD
+    c2 = XSD::CodeGen::ClassDef.new(class_name + "App",
+      "::SOAP::RPC::CGIStub")
+    c2.def_method("initialize", "*arg") do
+      <<-EOD
+        super(*arg)
+        servant = #{class_name}.new
+        #{class_name}::Methods.each do |definitions|
+          opt = definitions.last
+          if opt[:request_style] == :document
+            @router.add_document_operation(servant, *definitions)
+          else
+            @router.add_rpc_operation(servant, *definitions)
+          end
+        end
+        self.mapping_registry = #{class_name}::MappingRegistry
+        self.level = Logger::Severity::ERROR
+      EOD
+    end
+    c1.dump + "\n" + c2.dump + format(<<-EOD)
+      #{class_name}App.new('app', nil).start
+    EOD
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/classDefCreator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/classDefCreator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/classDefCreator.rb	(revision 18425)
@@ -0,0 +1,314 @@
+# WSDL4R - Creating class definition from WSDL
+# Copyright (C) 2002, 2003, 2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/data'
+require 'wsdl/soap/classDefCreatorSupport'
+require 'xsd/codegen'
+
+
+module WSDL
+module SOAP
+
+
+class ClassDefCreator
+  include ClassDefCreatorSupport
+
+  def initialize(definitions)
+    @elements = definitions.collect_elements
+    @simpletypes = definitions.collect_simpletypes
+    @complextypes = definitions.collect_complextypes
+    @faulttypes = nil
+    if definitions.respond_to?(:collect_faulttypes)
+      @faulttypes = definitions.collect_faulttypes
+    end
+  end
+
+  def dump(type = nil)
+    result = "require 'xsd/qname'\n"
+    if type
+      result = dump_classdef(type.name, type)
+    else
+      str = dump_element
+      unless str.empty?
+        result << "\n" unless result.empty?
+        result << str
+      end
+      str = dump_complextype
+      unless str.empty?
+        result << "\n" unless result.empty?
+        result << str
+      end
+      str = dump_simpletype
+      unless str.empty?
+        result << "\n" unless result.empty?
+        result << str
+      end
+    end
+    result
+  end
+
+private
+
+  def dump_element
+    @elements.collect { |ele|
+      if ele.local_complextype
+        dump_classdef(ele.name, ele.local_complextype,
+          ele.elementform == 'qualified')
+      elsif ele.local_simpletype
+        dump_simpletypedef(ele.name, ele.local_simpletype)
+      else
+        nil
+      end
+    }.compact.join("\n")
+  end
+
+  def dump_simpletype
+    @simpletypes.collect { |type|
+      dump_simpletypedef(type.name, type)
+    }.compact.join("\n")
+  end
+
+  def dump_complextype
+    @complextypes.collect { |type|
+      case type.compoundtype
+      when :TYPE_STRUCT, :TYPE_EMPTY
+        dump_classdef(type.name, type)
+      when :TYPE_ARRAY
+        dump_arraydef(type)
+      when :TYPE_SIMPLE
+        dump_simpleclassdef(type)
+      when :TYPE_MAP
+        # mapped as a general Hash
+        nil
+      else
+        raise RuntimeError.new(
+          "unknown kind of complexContent: #{type.compoundtype}")
+      end
+    }.compact.join("\n")
+  end
+
+  def dump_simpletypedef(qname, simpletype)
+    if !simpletype.restriction or simpletype.restriction.enumeration.empty?
+      return nil
+    end
+    c = XSD::CodeGen::ModuleDef.new(create_class_name(qname))
+    c.comment = "#{qname}"
+    const = {}
+    simpletype.restriction.enumeration.each do |value|
+      constname = safeconstname(value)
+      const[constname] ||= 0
+      if (const[constname] += 1) > 1
+        constname += "_#{const[constname]}"
+      end
+      c.def_const(constname, ndq(value))
+    end
+    c.dump
+  end
+
+  def dump_simpleclassdef(type_or_element)
+    qname = type_or_element.name
+    base = create_class_name(type_or_element.simplecontent.base)
+    c = XSD::CodeGen::ClassDef.new(create_class_name(qname), base)
+    c.comment = "#{qname}"
+    c.dump
+  end
+
+  def dump_classdef(qname, typedef, qualified = false)
+    if @faulttypes and @faulttypes.index(qname)
+      c = XSD::CodeGen::ClassDef.new(create_class_name(qname),
+        '::StandardError')
+    else
+      c = XSD::CodeGen::ClassDef.new(create_class_name(qname))
+    end
+    c.comment = "#{qname}"
+    c.def_classvar('schema_type', ndq(qname.name))
+    c.def_classvar('schema_ns', ndq(qname.namespace))
+    c.def_classvar('schema_qualified', dq('true')) if qualified
+    schema_element = []
+    init_lines = ''
+    params = []
+    typedef.each_element do |element|
+      if element.type == XSD::AnyTypeName
+        type = nil
+      elsif klass = element_basetype(element)
+        type = klass.name
+      elsif element.type
+        type = create_class_name(element.type)
+      else
+        type = nil      # means anyType.
+        # do we define a class for local complexType from it's name?
+        #   type = create_class_name(element.name)
+        # <element>
+        #   <complexType>
+        #     <seq...>
+        #   </complexType>
+        # </element>
+      end
+      name = name_element(element).name
+      attrname = safemethodname?(name) ? name : safemethodname(name)
+      varname = safevarname(name)
+      c.def_attr(attrname, true, varname)
+      init_lines << "@#{varname} = #{varname}\n"
+      if element.map_as_array?
+        params << "#{varname} = []"
+        type << '[]' if type
+      else
+        params << "#{varname} = nil"
+      end
+      # nil means @@schema_ns + varname
+      eleqname =
+        (varname == name && element.name.namespace == qname.namespace) ?
+        nil : element.name
+      schema_element << [varname, eleqname, type]
+    end
+    unless typedef.attributes.empty?
+      define_attribute(c, typedef.attributes)
+      init_lines << "@__xmlattr = {}\n"
+    end
+    c.def_classvar('schema_element',
+      '[' +
+        schema_element.collect { |varname, name, type|
+          '[' +
+            (
+              if name
+                varname.dump + ', [' + ndq(type) + ', ' + dqname(name) + ']'
+              else
+                varname.dump + ', ' + ndq(type)
+              end
+            ) +
+          ']'
+        }.join(', ') +
+      ']'
+    )
+    c.def_method('initialize', *params) do
+      init_lines
+    end
+    c.dump
+  end
+
+  def element_basetype(ele)
+    if klass = basetype_class(ele.type)
+      klass
+    elsif ele.local_simpletype
+      basetype_class(ele.local_simpletype.base)
+    else
+      nil
+    end
+  end
+
+  def attribute_basetype(attr)
+    if klass = basetype_class(attr.type)
+      klass
+    elsif attr.local_simpletype
+      basetype_class(attr.local_simpletype.base)
+    else
+      nil
+    end
+  end
+
+  def basetype_class(type)
+    return nil if type.nil?
+    if simpletype = @simpletypes[type]
+      basetype_mapped_class(simpletype.base)
+    else
+      basetype_mapped_class(type)
+    end
+  end
+
+  def define_attribute(c, attributes)
+    schema_attribute = []
+    attributes.each do |attribute|
+      name = name_attribute(attribute)
+      if klass = attribute_basetype(attribute)
+        type = klass.name
+      else
+        type = nil
+      end
+      methodname = safemethodname('xmlattr_' + name.name)
+      c.def_method(methodname) do <<-__EOD__
+          (@__xmlattr ||= {})[#{dqname(name)}]
+        __EOD__
+      end
+      c.def_method(methodname + '=', 'value') do <<-__EOD__
+          (@__xmlattr ||= {})[#{dqname(name)}] = value
+        __EOD__
+      end
+      schema_attribute << [name, type]
+    end
+    c.def_classvar('schema_attribute',
+      '{' +
+        schema_attribute.collect { |name, type|
+          dqname(name) + ' => ' + ndq(type)
+        }.join(', ') +
+      '}'
+    )
+  end
+
+  def name_element(element)
+    return element.name if element.name 
+    return element.ref if element.ref
+    raise RuntimeError.new("cannot define name of #{element}")
+  end
+
+  def name_attribute(attribute)
+    return attribute.name if attribute.name 
+    return attribute.ref if attribute.ref
+    raise RuntimeError.new("cannot define name of #{attribute}")
+  end
+
+  DEFAULT_ITEM_NAME = XSD::QName.new(nil, 'item')
+
+  def dump_arraydef(complextype)
+    qname = complextype.name
+    c = XSD::CodeGen::ClassDef.new(create_class_name(qname), '::Array')
+    c.comment = "#{qname}"
+    child_type = complextype.child_type
+    c.def_classvar('schema_type', ndq(child_type.name))
+    c.def_classvar('schema_ns', ndq(child_type.namespace))
+    child_element = complextype.find_aryelement
+    schema_element = []
+    if child_type == XSD::AnyTypeName
+      type = nil
+    elsif child_element and (klass = element_basetype(child_element))
+      type = klass.name
+    elsif child_type
+      type = create_class_name(child_type)
+    else
+      type = nil
+    end
+    if child_element
+      if child_element.map_as_array?
+        type << '[]' if type
+      end
+      child_element_name = child_element.name
+    else
+      child_element_name = DEFAULT_ITEM_NAME
+    end
+    schema_element << [child_element_name.name, child_element_name, type]
+    c.def_classvar('schema_element',
+      '[' +
+        schema_element.collect { |varname, name, type|
+          '[' +
+            (
+              if name
+                varname.dump + ', [' + ndq(type) + ', ' + dqname(name) + ']'
+              else
+                varname.dump + ', ' + ndq(type)
+              end
+            ) +
+          ']'
+        }.join(', ') +
+      ']'
+    )
+    c.dump
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/classDefCreatorSupport.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/classDefCreatorSupport.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/classDefCreatorSupport.rb	(revision 18425)
@@ -0,0 +1,126 @@
+# WSDL4R - Creating class code support from WSDL.
+# Copyright (C) 2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'soap/mapping'
+require 'soap/mapping/typeMap'
+require 'xsd/codegen/gensupport'
+
+
+module WSDL
+module SOAP
+
+
+module ClassDefCreatorSupport
+  include XSD::CodeGen::GenSupport
+
+  def create_class_name(qname)
+    if klass = basetype_mapped_class(qname)
+      ::SOAP::Mapping::DefaultRegistry.find_mapped_obj_class(klass).name
+    else
+      safeconstname(qname.name)
+    end
+  end
+
+  def basetype_mapped_class(name)
+    ::SOAP::TypeMap[name]
+  end
+
+  def dump_method_signature(operation)
+    name = operation.name.name
+    input = operation.input
+    output = operation.output
+    fault = operation.fault
+    signature = "#{ name }#{ dump_inputparam(input) }"
+    str = <<__EOD__
+# SYNOPSIS
+#   #{name}#{dump_inputparam(input)}
+#
+# ARGS
+#{dump_inout_type(input).chomp}
+#
+# RETURNS
+#{dump_inout_type(output).chomp}
+#
+__EOD__
+    unless fault.empty?
+      faultstr = (fault.collect { |f| dump_inout_type(f).chomp }).join(', ')
+      str <<<<__EOD__
+# RAISES
+#   #{faultstr}
+#
+__EOD__
+    end
+    str
+  end
+
+  def dq(ele)
+    ele.dump
+  end
+
+  def ndq(ele)
+    ele.nil? ? 'nil' : dq(ele)
+  end
+
+  def sym(ele)
+    ':' + ele
+  end
+
+  def dqname(qname)
+    qname.dump
+  end
+
+private
+
+  def dump_inout_type(param)
+    if param
+      message = param.find_message
+      params = ""
+      message.parts.each do |part|
+        name = safevarname(part.name)
+        if part.type
+          typename = safeconstname(part.type.name)
+          params << add_at("#   #{name}", "#{typename} - #{part.type}\n", 20)
+        elsif part.element
+          typename = safeconstname(part.element.name)
+          params << add_at("#   #{name}", "#{typename} - #{part.element}\n", 20)
+        end
+      end
+      unless params.empty?
+        return params
+      end
+    end
+    "#   N/A\n"
+  end
+
+  def dump_inputparam(input)
+    message = input.find_message
+    params = ""
+    message.parts.each do |part|
+      params << ", " unless params.empty?
+      params << safevarname(part.name)
+    end
+    if params.empty?
+      ""
+    else
+      "(#{ params })"
+    end
+  end
+
+  def add_at(base, str, pos)
+    if base.size >= pos
+      base + ' ' + str
+    else
+      base + ' ' * (pos - base.size) + str
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/clientSkeltonCreator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/clientSkeltonCreator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/clientSkeltonCreator.rb	(revision 18425)
@@ -0,0 +1,78 @@
+# WSDL4R - Creating client skelton code from WSDL.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'wsdl/soap/classDefCreatorSupport'
+
+
+module WSDL
+module SOAP
+
+
+class ClientSkeltonCreator
+  include ClassDefCreatorSupport
+
+  attr_reader :definitions
+
+  def initialize(definitions)
+    @definitions = definitions
+  end
+
+  def dump(service_name)
+    result = ""
+    @definitions.service(service_name).ports.each do |port|
+      result << dump_porttype(port.porttype.name)
+      result << "\n"
+    end
+    result
+  end
+
+private
+
+  def dump_porttype(name)
+    drv_name = create_class_name(name)
+
+    result = ""
+    result << <<__EOD__
+endpoint_url = ARGV.shift
+obj = #{ drv_name }.new(endpoint_url)
+
+# run ruby with -d to see SOAP wiredumps.
+obj.wiredump_dev = STDERR if $DEBUG
+
+__EOD__
+    @definitions.porttype(name).operations.each do |operation|
+      result << dump_method_signature(operation)
+      result << dump_input_init(operation.input) << "\n"
+      result << dump_operation(operation) << "\n\n"
+    end
+    result
+  end
+
+  def dump_operation(operation)
+    name = operation.name
+    input = operation.input
+    "puts obj.#{ safemethodname(name.name) }#{ dump_inputparam(input) }"
+  end
+
+  def dump_input_init(input)
+    result = input.find_message.parts.collect { |part|
+      safevarname(part.name)
+    }.join(" = ")
+    if result.empty?
+      ""
+    else
+      result << " = nil"
+    end
+    result
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/complexType.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/complexType.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/complexType.rb	(revision 18425)
@@ -0,0 +1,161 @@
+# WSDL4R - SOAP complexType definition for WSDL.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/xmlSchema/complexType'
+require 'soap/mapping'
+
+
+module WSDL
+module XMLSchema
+
+
+class ComplexType < Info
+  def compoundtype
+    @compoundtype ||= check_type
+  end
+
+  def check_type
+    if content
+      if attributes.empty? and
+          content.elements.size == 1 and content.elements[0].maxoccurs != '1'
+        if name == ::SOAP::Mapping::MapQName
+          :TYPE_MAP
+        else
+          :TYPE_ARRAY
+        end
+      else
+	:TYPE_STRUCT
+      end
+    elsif complexcontent
+      if complexcontent.base == ::SOAP::ValueArrayName
+        :TYPE_ARRAY
+      else
+        complexcontent.basetype.check_type
+      end
+    elsif simplecontent
+      :TYPE_SIMPLE
+    elsif !attributes.empty?
+      :TYPE_STRUCT
+    else # empty complexType definition (seen in partner.wsdl of salesforce)
+      :TYPE_EMPTY
+    end
+  end
+
+  def child_type(name = nil)
+    case compoundtype
+    when :TYPE_STRUCT
+      if ele = find_element(name)
+        ele.type
+      elsif ele = find_element_by_name(name.name)
+	ele.type
+      end
+    when :TYPE_ARRAY
+      @contenttype ||= content_arytype
+    when :TYPE_MAP
+      item_ele = find_element_by_name("item") or
+        raise RuntimeError.new("'item' element not found in Map definition.")
+      content = item_ele.local_complextype or
+        raise RuntimeError.new("No complexType definition for 'item'.")
+      if ele = content.find_element(name)
+        ele.type
+      elsif ele = content.find_element_by_name(name.name)
+        ele.type
+      end
+    else
+      raise NotImplementedError.new("Unknown kind of complexType.")
+    end
+  end
+
+  def child_defined_complextype(name)
+    ele = nil
+    case compoundtype
+    when :TYPE_STRUCT, :TYPE_MAP
+      unless ele = find_element(name)
+       	if name.namespace.nil?
+  	  ele = find_element_by_name(name.name)
+   	end
+      end
+    when :TYPE_ARRAY
+      if content.elements.size == 1
+	ele = content.elements[0]
+      else
+	raise RuntimeError.new("Assert: must not reach.")
+      end
+    else
+      raise RuntimeError.new("Assert: Not implemented.")
+    end
+    unless ele
+      raise RuntimeError.new("Cannot find #{name} as a children of #{@name}.")
+    end
+    ele.local_complextype
+  end
+
+  def find_arytype
+    unless compoundtype == :TYPE_ARRAY
+      raise RuntimeError.new("Assert: not for array")
+    end
+    if complexcontent
+      complexcontent.attributes.each do |attribute|
+	if attribute.ref == ::SOAP::AttrArrayTypeName
+	  return attribute.arytype
+	end
+      end
+      if check_array_content(complexcontent.content)
+        return element_simpletype(complexcontent.content.elements[0])
+      end
+    elsif check_array_content(content)
+      return element_simpletype(content.elements[0])
+    end
+    raise RuntimeError.new("Assert: Unknown array definition.")
+  end
+
+  def find_aryelement
+    unless compoundtype == :TYPE_ARRAY
+      raise RuntimeError.new("Assert: not for array")
+    end
+    if complexcontent
+      if check_array_content(complexcontent.content)
+        return complexcontent.content.elements[0]
+      end
+    elsif check_array_content(content)
+      return content.elements[0]
+    end
+    nil # use default item name
+  end
+
+private
+
+  def element_simpletype(element)
+    if element.type
+      element.type 
+    elsif element.local_simpletype
+      element.local_simpletype.base
+    else
+      nil
+    end
+  end
+
+  def check_array_content(content)
+    content and content.elements.size == 1 and
+      content.elements[0].maxoccurs != '1'
+  end
+
+  def content_arytype
+    if arytype = find_arytype
+      ns = arytype.namespace
+      name = arytype.name.sub(/\[(?:,)*\]$/, '')
+      XSD::QName.new(ns, name)
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/data.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/data.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/data.rb	(revision 18425)
@@ -0,0 +1,42 @@
+# WSDL4R - WSDL SOAP binding data definitions.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/qname'
+require 'wsdl/soap/definitions'
+require 'wsdl/soap/binding'
+require 'wsdl/soap/operation'
+require 'wsdl/soap/body'
+require 'wsdl/soap/element'
+require 'wsdl/soap/header'
+require 'wsdl/soap/headerfault'
+require 'wsdl/soap/fault'
+require 'wsdl/soap/address'
+require 'wsdl/soap/complexType'
+
+
+module WSDL
+module SOAP
+
+
+HeaderFaultName = XSD::QName.new(SOAPBindingNamespace, 'headerfault')
+
+LocationAttrName = XSD::QName.new(nil, 'location')
+StyleAttrName = XSD::QName.new(nil, 'style')
+TransportAttrName = XSD::QName.new(nil, 'transport')
+UseAttrName = XSD::QName.new(nil, 'use')
+PartsAttrName = XSD::QName.new(nil, 'parts')
+PartAttrName = XSD::QName.new(nil, 'part')
+NameAttrName = XSD::QName.new(nil, 'name')
+MessageAttrName = XSD::QName.new(nil, 'message')
+EncodingStyleAttrName = XSD::QName.new(nil, 'encodingStyle')
+NamespaceAttrName = XSD::QName.new(nil, 'namespace')
+SOAPActionAttrName = XSD::QName.new(nil, 'soapAction')
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/definitions.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/definitions.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/definitions.rb	(revision 18425)
@@ -0,0 +1,149 @@
+# WSDL4R - WSDL additional definitions for SOAP.
+# Copyright (C) 2002-2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'xsd/namedelements'
+require 'soap/mapping'
+
+
+module WSDL
+
+
+class Definitions < Info
+  def self.soap_rpc_complextypes
+    types = XSD::NamedElements.new
+    types << array_complextype
+    types << fault_complextype
+    types << exception_complextype
+    types
+  end
+
+  def self.array_complextype
+    type = XMLSchema::ComplexType.new(::SOAP::ValueArrayName)
+    type.complexcontent = XMLSchema::ComplexContent.new
+    type.complexcontent.base = ::SOAP::ValueArrayName
+    attr = XMLSchema::Attribute.new
+    attr.ref = ::SOAP::AttrArrayTypeName
+    anytype = XSD::AnyTypeName.dup
+    anytype.name += '[]'
+    attr.arytype = anytype
+    type.complexcontent.attributes << attr
+    type
+  end
+
+=begin
+<xs:complexType name="Fault" final="extension">
+  <xs:sequence>
+    <xs:element name="faultcode" type="xs:QName" /> 
+    <xs:element name="faultstring" type="xs:string" /> 
+    <xs:element name="faultactor" type="xs:anyURI" minOccurs="0" /> 
+    <xs:element name="detail" type="tns:detail" minOccurs="0" /> 
+  </xs:sequence>
+</xs:complexType>
+=end
+  def self.fault_complextype
+    type = XMLSchema::ComplexType.new(::SOAP::EleFaultName)
+    faultcode = XMLSchema::Element.new(::SOAP::EleFaultCodeName, XSD::XSDQName::Type)
+    faultstring = XMLSchema::Element.new(::SOAP::EleFaultStringName, XSD::XSDString::Type)
+    faultactor = XMLSchema::Element.new(::SOAP::EleFaultActorName, XSD::XSDAnyURI::Type)
+    faultactor.minoccurs = 0
+    detail = XMLSchema::Element.new(::SOAP::EleFaultDetailName, XSD::AnyTypeName)
+    detail.minoccurs = 0
+    type.all_elements = [faultcode, faultstring, faultactor, detail]
+    type.final = 'extension'
+    type
+  end
+
+  def self.exception_complextype
+    type = XMLSchema::ComplexType.new(XSD::QName.new(
+	::SOAP::Mapping::RubyCustomTypeNamespace, 'SOAPException'))
+    excn_name = XMLSchema::Element.new(XSD::QName.new(nil, 'excn_type_name'), XSD::XSDString::Type)
+    cause = XMLSchema::Element.new(XSD::QName.new(nil, 'cause'), XSD::AnyTypeName)
+    backtrace = XMLSchema::Element.new(XSD::QName.new(nil, 'backtrace'), ::SOAP::ValueArrayName)
+    message = XMLSchema::Element.new(XSD::QName.new(nil, 'message'), XSD::XSDString::Type)
+    type.all_elements = [excn_name, cause, backtrace, message]
+    type
+  end
+
+  def soap_rpc_complextypes(binding)
+    types = rpc_operation_complextypes(binding)
+    types + self.class.soap_rpc_complextypes
+  end
+
+  def collect_faulttypes
+    result = []
+    collect_fault_messages.each do |name|
+      faultparts = message(name).parts
+      if faultparts.size != 1
+	raise RuntimeError.new("expecting fault message to have only 1 part")
+      end
+      if result.index(faultparts[0].type).nil?
+	result << faultparts[0].type
+      end
+    end
+    result
+  end
+
+private
+
+  def collect_fault_messages
+    result = []
+    porttypes.each do |porttype|
+      porttype.operations.each do |operation|
+	operation.fault.each do |fault|
+	  if result.index(fault.message).nil?
+	    result << fault.message
+	  end
+	end
+      end
+    end
+    result
+  end
+
+  def rpc_operation_complextypes(binding)
+    types = XSD::NamedElements.new
+    binding.operations.each do |op_bind|
+      if op_bind_rpc?(op_bind)
+	operation = op_bind.find_operation
+	if op_bind.input
+	  type = XMLSchema::ComplexType.new(op_bind.soapoperation_name)
+	  message = messages[operation.input.message]
+	  type.sequence_elements = elements_from_message(message)
+	  types << type
+	end
+	if op_bind.output
+	  type = XMLSchema::ComplexType.new(operation.outputname)
+	  message = messages[operation.output.message]
+	  type.sequence_elements = elements_from_message(message)
+	  types << type
+	end
+      end
+    end
+    types
+  end
+
+  def op_bind_rpc?(op_bind)
+    op_bind.soapoperation_style == :rpc
+  end
+
+  def elements_from_message(message)
+    message.parts.collect { |part|
+      if part.element
+        collect_elements[part.element]
+      elsif part.name.nil? or part.type.nil?
+	raise RuntimeError.new("part of a message must be an element or typed")
+      else
+        qname = XSD::QName.new(nil, part.name)
+        XMLSchema::Element.new(qname, part.type)
+      end
+    }
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/driverCreator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/driverCreator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/driverCreator.rb	(revision 18425)
@@ -0,0 +1,95 @@
+# WSDL4R - Creating driver code from WSDL.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'wsdl/soap/mappingRegistryCreator'
+require 'wsdl/soap/methodDefCreator'
+require 'wsdl/soap/classDefCreatorSupport'
+require 'xsd/codegen'
+
+
+module WSDL
+module SOAP
+
+
+class DriverCreator
+  include ClassDefCreatorSupport
+
+  attr_reader :definitions
+
+  def initialize(definitions)
+    @definitions = definitions
+  end
+
+  def dump(porttype = nil)
+    if porttype.nil?
+      result = ""
+      @definitions.porttypes.each do |type|
+	result << dump_porttype(type.name)
+	result << "\n"
+      end
+    else
+      result = dump_porttype(porttype)
+    end
+    result
+  end
+
+private
+
+  def dump_porttype(name)
+    class_name = create_class_name(name)
+    methoddef, types = MethodDefCreator.new(@definitions).dump(name)
+    mr_creator = MappingRegistryCreator.new(@definitions)
+    binding = @definitions.bindings.find { |item| item.type == name }
+    return '' unless binding.soapbinding        # not a SOAP binding
+    address = @definitions.porttype(name).locations[0]
+
+    c = XSD::CodeGen::ClassDef.new(class_name, "::SOAP::RPC::Driver")
+    c.def_require("soap/rpc/driver")
+    c.def_const("MappingRegistry", "::SOAP::Mapping::Registry.new")
+    c.def_const("DefaultEndpointUrl", ndq(address))
+    c.def_code(mr_creator.dump(types))
+    c.def_code <<-EOD
+Methods = [
+#{methoddef.gsub(/^/, "  ")}
+]
+    EOD
+    c.def_method("initialize", "endpoint_url = nil") do
+      <<-EOD
+        endpoint_url ||= DefaultEndpointUrl
+        super(endpoint_url, nil)
+        self.mapping_registry = MappingRegistry
+        init_methods
+      EOD
+    end
+    c.def_privatemethod("init_methods") do
+      <<-EOD
+        Methods.each do |definitions|
+          opt = definitions.last
+          if opt[:request_style] == :document
+            add_document_operation(*definitions)
+          else
+            add_rpc_operation(*definitions)
+            qname = definitions[0]
+            name = definitions[2]
+            if qname.name != name and qname.name.capitalize == name.capitalize
+              ::SOAP::Mapping.define_singleton_method(self, qname.name) do |*arg|
+                __send__(name, *arg)
+              end
+            end
+          end
+        end
+      EOD
+    end
+    c.dump
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/element.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/element.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/element.rb	(revision 18425)
@@ -0,0 +1,28 @@
+# WSDL4R - XMLSchema element definition for WSDL.
+# Copyright (C) 2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/xmlSchema/element'
+
+
+module WSDL
+module XMLSchema
+
+
+class Element < Info
+  def map_as_array?
+    maxoccurs != '1'
+  end
+
+  def attributes
+    @local_complextype.attributes
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/fault.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/fault.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/fault.rb	(revision 18425)
@@ -0,0 +1,56 @@
+# WSDL4R - WSDL SOAP body definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module SOAP
+
+
+class Fault < Info
+  attr_reader :name	# required
+  attr_reader :use	# required
+  attr_reader :encodingstyle
+  attr_reader :namespace
+
+  def initialize
+    super
+    @name = nil
+    @use = nil
+    @encodingstyle = nil
+    @namespace = nil
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def parse_element(element)
+    nil
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NameAttrName
+      @name = XSD::QName.new(targetnamespace, value.source)
+    when UseAttrName
+      @use = value.source
+    when EncodingStyleAttrName
+      @encodingstyle = value.source
+    when NamespaceAttrName
+      @namespace = value.source
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/header.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/header.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/header.rb	(revision 18425)
@@ -0,0 +1,86 @@
+# WSDL4R - WSDL SOAP body definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module SOAP
+
+
+class Header < Info
+  attr_reader :headerfault
+
+  attr_reader :message	# required
+  attr_reader :part	# required
+  attr_reader :use	# required
+  attr_reader :encodingstyle
+  attr_reader :namespace
+
+  def initialize
+    super
+    @message = nil
+    @part = nil
+    @use = nil
+    @encodingstyle = nil
+    @namespace = nil
+    @headerfault = nil
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def find_message
+    root.message(@message) or raise RuntimeError.new("#{@message} not found")
+  end
+
+  def find_part
+    find_message.parts.each do |part|
+      if part.name == @part
+	return part
+      end
+    end
+    raise RuntimeError.new("#{@part} not found")
+  end
+
+  def parse_element(element)
+    case element
+    when HeaderFaultName
+      o = WSDL::SOAP::HeaderFault.new
+      @headerfault = o
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when MessageAttrName
+      if value.namespace.nil?
+        value = XSD::QName.new(targetnamespace, value.source)
+      end
+      @message = value
+    when PartAttrName
+      @part = value.source
+    when UseAttrName
+      @use = value.source
+    when EncodingStyleAttrName
+      @encodingstyle = value.source
+    when NamespaceAttrName
+      @namespace = value.source
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/headerfault.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/headerfault.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/headerfault.rb	(revision 18425)
@@ -0,0 +1,56 @@
+# WSDL4R - WSDL SOAP body definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module SOAP
+
+
+class HeaderFault < Info
+  attr_reader :message	# required
+  attr_reader :part	# required
+  attr_reader :use	# required
+  attr_reader :encodingstyle
+  attr_reader :namespace
+
+  def initialize
+    super
+    @message = nil
+    @part = nil
+    @use = nil
+    @encodingstyle = nil
+    @namespace = nil
+  end
+
+  def parse_element(element)
+    nil
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when MessageAttrName
+      @message = value
+    when PartAttrName
+      @part = value.source
+    when UseAttrName
+      @use = value.source
+    when EncodingStyleAttrName
+      @encodingstyle = value.source
+    when NamespaceAttrName
+      @namespace = value.source
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/mappingRegistryCreator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/mappingRegistryCreator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/mappingRegistryCreator.rb	(revision 18425)
@@ -0,0 +1,92 @@
+# WSDL4R - Creating MappingRegistry code from WSDL.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'wsdl/soap/classDefCreatorSupport'
+
+
+module WSDL
+module SOAP
+
+
+class MappingRegistryCreator
+  include ClassDefCreatorSupport
+
+  attr_reader :definitions
+
+  def initialize(definitions)
+    @definitions = definitions
+    @complextypes = @definitions.collect_complextypes
+    @types = nil
+  end
+
+  def dump(types)
+    @types = types
+    map_cache = []
+    map = ""
+    @types.each do |type|
+      if map_cache.index(type).nil?
+	map_cache << type
+	if type.namespace != XSD::Namespace
+	  if typemap = dump_typemap(type)
+            map << typemap
+          end
+	end
+      end
+   end
+    return map
+  end
+
+private
+
+  def dump_typemap(type)
+    if definedtype = @complextypes[type]
+      case definedtype.compoundtype
+      when :TYPE_STRUCT
+        dump_struct_typemap(definedtype)
+      when :TYPE_ARRAY
+        dump_array_typemap(definedtype)
+      when :TYPE_MAP, :TYPE_EMPTY
+        nil
+      else
+        raise NotImplementedError.new("must not reach here")
+      end
+    end
+  end
+
+  def dump_struct_typemap(definedtype)
+    ele = definedtype.name
+    return <<__EOD__
+MappingRegistry.set(
+  #{create_class_name(ele)},
+  ::SOAP::SOAPStruct,
+  ::SOAP::Mapping::Registry::TypedStructFactory,
+  { :type => #{dqname(ele)} }
+)
+__EOD__
+  end
+
+  def dump_array_typemap(definedtype)
+    ele = definedtype.name
+    arytype = definedtype.find_arytype || XSD::AnyTypeName
+    type = XSD::QName.new(arytype.namespace, arytype.name.sub(/\[(?:,)*\]$/, ''))
+    @types << type
+    return <<__EOD__
+MappingRegistry.set(
+  #{create_class_name(ele)},
+  ::SOAP::SOAPArray,
+  ::SOAP::Mapping::Registry::TypedArrayFactory,
+  { :type => #{dqname(type)} }
+)
+__EOD__
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/methodDefCreator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/methodDefCreator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/methodDefCreator.rb	(revision 18425)
@@ -0,0 +1,228 @@
+# WSDL4R - Creating driver code from WSDL.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'wsdl/soap/classDefCreatorSupport'
+require 'soap/rpc/element'
+
+
+module WSDL
+module SOAP
+
+
+class MethodDefCreator
+  include ClassDefCreatorSupport
+
+  attr_reader :definitions
+
+  def initialize(definitions)
+    @definitions = definitions
+    @simpletypes = @definitions.collect_simpletypes
+    @complextypes = @definitions.collect_complextypes
+    @elements = @definitions.collect_elements
+    @types = []
+  end
+
+  def dump(porttype)
+    @types.clear
+    result = ""
+    operations = @definitions.porttype(porttype).operations
+    binding = @definitions.porttype_binding(porttype)
+    operations.each do |operation|
+      op_bind = binding.operations[operation.name]
+      next unless op_bind # no binding is defined
+      next unless op_bind.soapoperation # not a SOAP operation binding
+      result << ",\n" unless result.empty?
+      result << dump_method(operation, op_bind).chomp
+    end
+    return result, @types
+  end
+
+  def collect_rpcparameter(operation)
+    result = operation.inputparts.collect { |part|
+      collect_type(part.type)
+      param_set(::SOAP::RPC::SOAPMethod::IN, part.name, rpcdefinedtype(part))
+    }
+    outparts = operation.outputparts
+    if outparts.size > 0
+      retval = outparts[0]
+      collect_type(retval.type)
+      result << param_set(::SOAP::RPC::SOAPMethod::RETVAL, retval.name,
+        rpcdefinedtype(retval))
+      cdr(outparts).each { |part|
+	collect_type(part.type)
+	result << param_set(::SOAP::RPC::SOAPMethod::OUT, part.name,
+          rpcdefinedtype(part))
+      }
+    end
+    result
+  end
+
+  def collect_documentparameter(operation)
+    param = []
+    operation.inputparts.each do |input|
+      param << param_set(::SOAP::RPC::SOAPMethod::IN, input.name,
+        documentdefinedtype(input), elementqualified(input))
+    end
+    operation.outputparts.each do |output|
+      param << param_set(::SOAP::RPC::SOAPMethod::OUT, output.name,
+        documentdefinedtype(output), elementqualified(output))
+    end
+    param
+  end
+
+private
+
+  def dump_method(operation, binding)
+    name = safemethodname(operation.name.name)
+    name_as = operation.name.name
+    style = binding.soapoperation_style
+    inputuse = binding.input.soapbody_use
+    outputuse = binding.output.soapbody_use
+    namespace = binding.input.soapbody.namespace
+    if style == :rpc
+      qname = XSD::QName.new(namespace, name_as)
+      paramstr = param2str(collect_rpcparameter(operation))
+    else
+      qname = nil
+      paramstr = param2str(collect_documentparameter(operation))
+    end
+    if paramstr.empty?
+      paramstr = '[]'
+    else
+      paramstr = "[ " << paramstr.split(/\r?\n/).join("\n    ") << " ]"
+    end
+    definitions = <<__EOD__
+#{ndq(binding.soapaction)},
+  #{dq(name)},
+  #{paramstr},
+  { :request_style =>  #{sym(style.id2name)}, :request_use =>  #{sym(inputuse.id2name)},
+    :response_style => #{sym(style.id2name)}, :response_use => #{sym(outputuse.id2name)} }
+__EOD__
+    if style == :rpc
+      return <<__EOD__
+[ #{qname.dump},
+  #{definitions}]
+__EOD__
+    else
+      return <<__EOD__
+[ #{definitions}]
+__EOD__
+    end
+  end
+
+  def rpcdefinedtype(part)
+    if mapped = basetype_mapped_class(part.type)
+      ['::' + mapped.name]
+    elsif definedtype = @simpletypes[part.type]
+      ['::' + basetype_mapped_class(definedtype.base).name]
+    elsif definedtype = @elements[part.element]
+      #['::SOAP::SOAPStruct', part.element.namespace, part.element.name]
+      ['nil', part.element.namespace, part.element.name]
+    elsif definedtype = @complextypes[part.type]
+      case definedtype.compoundtype
+      when :TYPE_STRUCT, :TYPE_EMPTY    # ToDo: empty should be treated as void.
+        type = create_class_name(part.type)
+	[type, part.type.namespace, part.type.name]
+      when :TYPE_MAP
+	[Hash.name, part.type.namespace, part.type.name]
+      when :TYPE_ARRAY
+	arytype = definedtype.find_arytype || XSD::AnyTypeName
+	ns = arytype.namespace
+	name = arytype.name.sub(/\[(?:,)*\]$/, '')
+        type = create_class_name(XSD::QName.new(ns, name))
+	[type + '[]', ns, name]
+      else
+	raise NotImplementedError.new("must not reach here")
+      end
+    else
+      raise RuntimeError.new("part: #{part.name} cannot be resolved")
+    end
+  end
+
+  def documentdefinedtype(part)
+    if mapped = basetype_mapped_class(part.type)
+      ['::' + mapped.name, nil, part.name]
+    elsif definedtype = @simpletypes[part.type]
+      ['::' + basetype_mapped_class(definedtype.base).name, nil, part.name]
+    elsif definedtype = @elements[part.element]
+      ['::SOAP::SOAPElement', part.element.namespace, part.element.name]
+    elsif definedtype = @complextypes[part.type]
+      ['::SOAP::SOAPElement', part.type.namespace, part.type.name]
+    else
+      raise RuntimeError.new("part: #{part.name} cannot be resolved")
+    end
+  end
+
+  def elementqualified(part)
+    if mapped = basetype_mapped_class(part.type)
+      false
+    elsif definedtype = @simpletypes[part.type]
+      false
+    elsif definedtype = @elements[part.element]
+      definedtype.elementform == 'qualified'
+    elsif definedtype = @complextypes[part.type]
+      false
+    else
+      raise RuntimeError.new("part: #{part.name} cannot be resolved")
+    end
+  end
+
+  def param_set(io_type, name, type, ele = nil)
+    [io_type, name, type, ele]
+  end
+
+  def collect_type(type)
+    # ignore inline type definition.
+    return if type.nil?
+    return if @types.include?(type)
+    @types << type
+    return unless @complextypes[type]
+    @complextypes[type].each_element do |element|
+      collect_type(element.type)
+    end
+  end
+
+  def param2str(params)
+    params.collect { |param|
+      io, name, type, ele = param
+      unless ele.nil?
+        "[#{dq(io)}, #{dq(name)}, #{type2str(type)}, #{ele2str(ele)}]"
+      else
+        "[#{dq(io)}, #{dq(name)}, #{type2str(type)}]"
+      end
+    }.join(",\n")
+  end
+
+  def type2str(type)
+    if type.size == 1
+      "[#{dq(type[0])}]" 
+    else
+      "[#{dq(type[0])}, #{ndq(type[1])}, #{dq(type[2])}]" 
+    end
+  end
+
+  def ele2str(ele)
+    qualified = ele
+    if qualified
+      "true"
+    else
+      "false"
+    end
+  end
+
+  def cdr(ary)
+    result = ary.dup
+    result.shift
+    result
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/operation.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/operation.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/operation.rb	(revision 18425)
@@ -0,0 +1,122 @@
+# WSDL4R - WSDL SOAP operation definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module SOAP
+
+
+class Operation < Info
+  class OperationInfo
+    attr_reader :style
+    attr_reader :op_name
+    attr_reader :optype_name
+    attr_reader :headerparts
+    attr_reader :bodyparts
+    attr_reader :faultpart
+    attr_reader :soapaction
+    
+    def initialize(style, op_name, optype_name, headerparts, bodyparts, faultpart, soapaction)
+      @style = style
+      @op_name = op_name
+      @optype_name = optype_name
+      @headerparts = headerparts
+      @bodyparts = bodyparts
+      @faultpart = faultpart
+      @soapaction = soapaction
+    end
+  end
+
+  attr_reader :soapaction
+  attr_reader :style
+
+  def initialize
+    super
+    @soapaction = nil
+    @style = nil
+  end
+
+  def parse_element(element)
+    nil
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when StyleAttrName
+      if ["document", "rpc"].include?(value.source)
+	@style = value.source.intern
+      else
+	raise Parser::AttributeConstraintError.new(
+          "Unexpected value #{ value }.")
+      end
+    when SOAPActionAttrName
+      @soapaction = value.source
+    else
+      nil
+    end
+  end
+
+  def input_info
+    name_info = parent.find_operation.input_info
+    param_info(name_info, parent.input)
+  end
+
+  def output_info
+    name_info = parent.find_operation.output_info
+    param_info(name_info, parent.output)
+  end
+
+  def operation_style
+    return @style if @style
+    if parent_binding.soapbinding
+      return parent_binding.soapbinding.style
+    end
+    nil
+  end
+
+private
+
+  def parent_binding
+    parent.parent
+  end
+
+  def param_info(name_info, param)
+    op_name = name_info.op_name
+    optype_name = name_info.optype_name
+
+    soapheader = param.soapheader
+    headerparts = soapheader.collect { |item| item.find_part }
+
+    soapbody = param.soapbody
+    if soapbody.encodingstyle and
+	soapbody.encodingstyle != ::SOAP::EncodingNamespace
+      raise NotImplementedError.new(
+	"EncodingStyle '#{ soapbody.encodingstyle }' not supported.")
+    end
+    if soapbody.namespace
+      op_name = XSD::QName.new(soapbody.namespace, op_name.name)
+    end
+    if soapbody.parts
+      target = soapbody.parts.split(/\s+/)
+      bodyparts = name_info.parts.find_all { |part|
+	target.include?(part.name)
+      }
+    else
+      bodyparts = name_info.parts
+    end
+
+    faultpart = nil
+    OperationInfo.new(operation_style, op_name, optype_name, headerparts, bodyparts, faultpart, parent.soapaction)
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/servantSkeltonCreator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/servantSkeltonCreator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/servantSkeltonCreator.rb	(revision 18425)
@@ -0,0 +1,67 @@
+# WSDL4R - Creating servant skelton code from WSDL.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'wsdl/soap/classDefCreatorSupport'
+require 'xsd/codegen'
+
+
+module WSDL
+module SOAP
+
+
+class ServantSkeltonCreator
+  include ClassDefCreatorSupport
+  include XSD::CodeGen::GenSupport
+
+  attr_reader :definitions
+
+  def initialize(definitions)
+    @definitions = definitions
+  end
+
+  def dump(porttype = nil)
+    if porttype.nil?
+      result = ""
+      @definitions.porttypes.each do |type|
+	result << dump_porttype(type.name)
+	result << "\n"
+      end
+    else
+      result = dump_porttype(porttype)
+    end
+    result
+  end
+
+private
+
+  def dump_porttype(name)
+    class_name = create_class_name(name)
+    c = XSD::CodeGen::ClassDef.new(class_name)
+    operations = @definitions.porttype(name).operations
+    operations.each do |operation|
+      name = safemethodname(operation.name.name)
+      input = operation.input
+      params = input.find_message.parts.collect { |part|
+        safevarname(part.name)
+      }
+      m = XSD::CodeGen::MethodDef.new(name, params) do <<-EOD
+            p [#{params.join(", ")}]
+            raise NotImplementedError.new
+          EOD
+        end
+      m.comment = dump_method_signature(operation)
+      c.add_method(m)
+    end
+    c.dump
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/standaloneServerStubCreator.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/standaloneServerStubCreator.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/standaloneServerStubCreator.rb	(revision 18425)
@@ -0,0 +1,85 @@
+# WSDL4R - Creating standalone server stub code from WSDL.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'wsdl/soap/mappingRegistryCreator'
+require 'wsdl/soap/methodDefCreator'
+require 'wsdl/soap/classDefCreatorSupport'
+
+
+module WSDL
+module SOAP
+
+
+class StandaloneServerStubCreator
+  include ClassDefCreatorSupport
+
+  attr_reader :definitions
+
+  def initialize(definitions)
+    @definitions = definitions
+  end
+
+  def dump(service_name)
+    warn("- Standalone stub can have only 1 port for now.  So creating stub for the first port and rests are ignored.")
+    warn("- Standalone server stub ignores port location defined in WSDL.  Location is http://localhost:10080/ by default.  Generated client from WSDL must be configured to point this endpoint manually.")
+    port = @definitions.service(service_name).ports[0]
+    dump_porttype(port.porttype.name)
+  end
+
+private
+
+  def dump_porttype(name)
+    class_name = create_class_name(name)
+    methoddef, types = MethodDefCreator.new(@definitions).dump(name)
+    mr_creator = MappingRegistryCreator.new(@definitions)
+
+    c1 = XSD::CodeGen::ClassDef.new(class_name)
+    c1.def_require("soap/rpc/standaloneServer")
+    c1.def_require("soap/mapping/registry")
+    c1.def_const("MappingRegistry", "::SOAP::Mapping::Registry.new")
+    c1.def_code(mr_creator.dump(types))
+    c1.def_code <<-EOD
+Methods = [
+#{methoddef.gsub(/^/, "  ")}
+]
+    EOD
+    c2 = XSD::CodeGen::ClassDef.new(class_name + "App",
+      "::SOAP::RPC::StandaloneServer")
+    c2.def_method("initialize", "*arg") do
+      <<-EOD
+        super(*arg)
+        servant = #{class_name}.new
+        #{class_name}::Methods.each do |definitions|
+          opt = definitions.last
+          if opt[:request_style] == :document
+            @router.add_document_operation(servant, *definitions)
+          else
+            @router.add_rpc_operation(servant, *definitions)
+          end
+        end
+        self.mapping_registry = #{class_name}::MappingRegistry
+      EOD
+    end
+    c1.dump + "\n" + c2.dump + format(<<-EOD)
+
+      if $0 == __FILE__
+        # Change listen port.
+        server = #{class_name}App.new('app', nil, '0.0.0.0', 10080)
+        trap(:INT) do
+          server.shutdown
+        end
+        server.start
+      end
+    EOD
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/wsdl2ruby.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/wsdl2ruby.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/soap/wsdl2ruby.rb	(revision 18425)
@@ -0,0 +1,176 @@
+# WSDL4R - WSDL to ruby mapping library.
+# Copyright (C) 2002-2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'logger'
+require 'xsd/qname'
+require 'wsdl/importer'
+require 'wsdl/soap/classDefCreator'
+require 'wsdl/soap/servantSkeltonCreator'
+require 'wsdl/soap/driverCreator'
+require 'wsdl/soap/clientSkeltonCreator'
+require 'wsdl/soap/standaloneServerStubCreator'
+require 'wsdl/soap/cgiStubCreator'
+
+
+module WSDL
+module SOAP
+
+
+class WSDL2Ruby
+  attr_accessor :location
+  attr_reader :opt
+  attr_accessor :logger
+  attr_accessor :basedir
+
+  def run
+    unless @location
+      raise RuntimeError, "WSDL location not given"
+    end
+    @wsdl = import(@location)
+    @name = @wsdl.name ? @wsdl.name.name : 'default'
+    create_file
+  end
+
+private
+
+  def initialize
+    @location = nil
+    @opt = {}
+    @logger = Logger.new(STDERR)
+    @basedir = nil
+    @wsdl = nil
+    @name = nil
+  end
+
+  def create_file
+    create_classdef if @opt.key?('classdef')
+    create_servant_skelton(@opt['servant_skelton']) if @opt.key?('servant_skelton')
+    create_cgi_stub(@opt['cgi_stub']) if @opt.key?('cgi_stub')
+    create_standalone_server_stub(@opt['standalone_server_stub']) if @opt.key?('standalone_server_stub')
+    create_driver(@opt['driver']) if @opt.key?('driver')
+    create_client_skelton(@opt['client_skelton']) if @opt.key?('client_skelton')
+  end
+
+  def create_classdef
+    @logger.info { "Creating class definition." }
+    @classdef_filename = @name + '.rb'
+    check_file(@classdef_filename) or return
+    write_file(@classdef_filename) do |f|
+      f << WSDL::SOAP::ClassDefCreator.new(@wsdl).dump
+    end
+  end
+
+  def create_client_skelton(servicename)
+    @logger.info { "Creating client skelton." }
+    servicename ||= @wsdl.services[0].name.name
+    @client_skelton_filename = servicename + 'Client.rb'
+    check_file(@client_skelton_filename) or return
+    write_file(@client_skelton_filename) do |f|
+      f << shbang << "\n"
+      f << "require '#{@driver_filename}'\n\n" if @driver_filename
+      f << WSDL::SOAP::ClientSkeltonCreator.new(@wsdl).dump(
+	create_name(servicename))
+    end
+  end
+
+  def create_servant_skelton(porttypename)
+    @logger.info { "Creating servant skelton." }
+    @servant_skelton_filename = (porttypename || @name + 'Servant') + '.rb'
+    check_file(@servant_skelton_filename) or return
+    write_file(@servant_skelton_filename) do |f|
+      f << "require '#{@classdef_filename}'\n\n" if @classdef_filename
+      f << WSDL::SOAP::ServantSkeltonCreator.new(@wsdl).dump(
+	create_name(porttypename))
+    end
+  end
+
+  def create_cgi_stub(servicename)
+    @logger.info { "Creating CGI stub." }
+    servicename ||= @wsdl.services[0].name.name
+    @cgi_stubFilename = servicename + '.cgi'
+    check_file(@cgi_stubFilename) or return
+    write_file(@cgi_stubFilename) do |f|
+      f << shbang << "\n"
+      if @servant_skelton_filename
+	f << "require '#{@servant_skelton_filename}'\n\n"
+      end
+      f << WSDL::SOAP::CGIStubCreator.new(@wsdl).dump(create_name(servicename))
+    end
+  end
+
+  def create_standalone_server_stub(servicename)
+    @logger.info { "Creating standalone stub." }
+    servicename ||= @wsdl.services[0].name.name
+    @standalone_server_stub_filename = servicename + '.rb'
+    check_file(@standalone_server_stub_filename) or return
+    write_file(@standalone_server_stub_filename) do |f|
+      f << shbang << "\n"
+      f << "require '#{@servant_skelton_filename}'\n\n" if @servant_skelton_filename
+      f << WSDL::SOAP::StandaloneServerStubCreator.new(@wsdl).dump(
+	create_name(servicename))
+    end
+  end
+
+  def create_driver(porttypename)
+    @logger.info { "Creating driver." }
+    @driver_filename = (porttypename || @name) + 'Driver.rb'
+    check_file(@driver_filename) or return
+    write_file(@driver_filename) do |f|
+      f << "require '#{@classdef_filename}'\n\n" if @classdef_filename
+      f << WSDL::SOAP::DriverCreator.new(@wsdl).dump(
+	create_name(porttypename))
+    end
+  end
+
+  def write_file(filename)
+    if @basedir
+      filename = File.join(basedir, filename)
+    end
+    File.open(filename, "w") do |f|
+      yield f
+    end
+  end
+
+  def check_file(filename)
+    if @basedir
+      filename = File.join(basedir, filename)
+    end
+    if FileTest.exist?(filename)
+      if @opt.key?('force')
+	@logger.warn {
+	  "File '#{filename}' exists but overrides it."
+	}
+	true
+      else
+	@logger.warn {
+	  "File '#{filename}' exists.  #{$0} did not override it."
+	}
+	false
+      end
+    else
+      @logger.info { "Creates file '#{filename}'." }
+      true
+    end
+  end
+
+  def shbang
+    "#!/usr/bin/env ruby"
+  end
+
+  def create_name(name)
+    name ? XSD::QName.new(@wsdl.targetnamespace, name) : nil
+  end
+
+  def import(location)
+    WSDL::Importer.import(location)
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/types.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/types.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/types.rb	(revision 18425)
@@ -0,0 +1,43 @@
+# WSDL4R - WSDL types definition.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+
+
+class Types < Info
+  attr_reader :schemas
+
+  def initialize
+    super
+    @schemas = []
+  end
+
+  def parse_element(element)
+    case element
+    when SchemaName
+      o = XMLSchema::Schema.new
+      @schemas << o
+      o
+    when DocumentationName
+      o = Documentation.new
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    nil
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/wsdl.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/wsdl.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/wsdl.rb	(revision 18425)
@@ -0,0 +1,23 @@
+# WSDL4R - Base definitions.
+# Copyright (C) 2000, 2001, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/qname'
+
+
+module WSDL
+
+
+Version = '0.0.2'
+
+Namespace = 'http://schemas.xmlsoap.org/wsdl/'
+SOAPBindingNamespace ='http://schemas.xmlsoap.org/wsdl/soap/'
+
+class Error < StandardError; end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/all.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/all.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/all.rb	(revision 18425)
@@ -0,0 +1,69 @@
+# WSDL4R - XMLSchema complexType definition for WSDL.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module XMLSchema
+
+
+class All < Info
+  attr_reader :minoccurs
+  attr_reader :maxoccurs
+  attr_reader :elements
+
+  def initialize
+    super()
+    @minoccurs = '1'
+    @maxoccurs = '1'
+    @elements = []
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def elementformdefault
+    parent.elementformdefault
+  end
+
+  def <<(element)
+    @elements << element
+  end
+
+  def parse_element(element)
+    case element
+    when AnyName
+      o = Any.new
+      @elements << o
+      o
+    when ElementName
+      o = Element.new
+      @elements << o
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when MaxOccursAttrName
+      @maxoccurs = value.source
+    when MinOccursAttrName
+      @minoccurs = value.source
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/annotation.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/annotation.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/annotation.rb	(revision 18425)
@@ -0,0 +1,34 @@
+# WSDL4R - WSDL SOAP documentation element.
+# Copyright (C) 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module XMLSchema
+
+
+class Annotation < Info
+  def initialize
+    super
+  end
+
+  def parse_element(element)
+    # Accepts any element.
+    self
+  end
+
+  def parse_attr(attr, value)
+    # Accepts any attribute.
+    true
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/any.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/any.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/any.rb	(revision 18425)
@@ -0,0 +1,56 @@
+# WSDL4R - XMLSchema any definition for WSDL.
+# Copyright (C) 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module XMLSchema
+
+
+class Any < Info
+  attr_accessor :maxoccurs
+  attr_accessor :minoccurs
+  attr_accessor :namespace
+  attr_accessor :process_contents
+
+  def initialize
+    super()
+    @maxoccurs = '1'
+    @minoccurs = '1'
+    @namespace = '##any'
+    @process_contents = 'strict'
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def parse_element(element)
+    nil
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when MaxOccursAttrName
+      @maxoccurs = value.source
+    when MinOccursAttrName
+      @minoccurs = value.source
+    when NamespaceAttrName
+      @namespace = value.source
+    when ProcessContentsAttrName
+      @process_contents = value.source
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/attribute.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/attribute.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/attribute.rb	(revision 18425)
@@ -0,0 +1,127 @@
+# WSDL4R - XMLSchema attribute definition for WSDL.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module XMLSchema
+
+
+class Attribute < Info
+  class << self
+    if RUBY_VERSION > "1.7.0"
+      def attr_reader_ref(symbol)
+        name = symbol.to_s
+        define_method(name) {
+          instance_variable_get("@#{name}") ||
+            (refelement ? refelement.__send__(name) : nil)
+        }
+      end
+    else
+      def attr_reader_ref(symbol)
+        name = symbol.to_s
+        module_eval <<-EOS
+          def #{name}
+            @#{name} || (refelement ? refelement.#{name} : nil)
+          end
+        EOS
+      end
+    end
+  end
+
+  attr_writer :use
+  attr_writer :form
+  attr_writer :name
+  attr_writer :type
+  attr_writer :local_simpletype
+  attr_writer :default
+  attr_writer :fixed
+
+  attr_reader_ref :use
+  attr_reader_ref :form
+  attr_reader_ref :name
+  attr_reader_ref :type
+  attr_reader_ref :local_simpletype
+  attr_reader_ref :default
+  attr_reader_ref :fixed
+
+  attr_accessor :ref
+  attr_accessor :arytype
+
+  def initialize
+    super
+    @use = nil
+    @form = nil
+    @name = nil
+    @type = nil
+    @local_simpletype = nil
+    @default = nil
+    @fixed = nil
+    @ref = nil
+    @refelement = nil
+    @arytype = nil
+  end
+
+  def refelement
+    @refelement ||= root.collect_attributes[@ref]
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def parse_element(element)
+    case element
+    when SimpleTypeName
+      @local_simpletype = SimpleType.new
+      @local_simpletype
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when RefAttrName
+      @ref = value
+    when UseAttrName
+      @use = value.source
+    when FormAttrName
+      @form = value.source
+    when NameAttrName
+      if directelement?
+        @name = XSD::QName.new(targetnamespace, value.source)
+      else
+        @name = XSD::QName.new(nil, value.source)
+      end
+    when TypeAttrName
+      @type = value
+    when DefaultAttrName
+      @default = value.source
+    when FixedAttrName
+      @fixed = value.source
+    when ArrayTypeAttrName
+      @arytype = if value.namespace.nil?
+          XSD::QName.new(XSD::Namespace, value.source)
+        else
+          value
+        end
+    else
+      nil
+    end
+  end
+
+private
+
+  def directelement?
+    parent.is_a?(Schema)
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/choice.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/choice.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/choice.rb	(revision 18425)
@@ -0,0 +1,69 @@
+# WSDL4R - XMLSchema complexType definition for WSDL.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module XMLSchema
+
+
+class Choice < Info
+  attr_reader :minoccurs
+  attr_reader :maxoccurs
+  attr_reader :elements
+
+  def initialize
+    super()
+    @minoccurs = '1'
+    @maxoccurs = '1'
+    @elements = []
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def elementformdefault
+    parent.elementformdefault
+  end
+
+  def <<(element)
+    @elements << element
+  end
+
+  def parse_element(element)
+    case element
+    when AnyName
+      o = Any.new
+      @elements << o
+      o
+    when ElementName
+      o = Element.new
+      @elements << o
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when MaxOccursAttrName
+      @maxoccurs = value.source
+    when MinOccursAttrName
+      @minoccurs = value.source
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/complexContent.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/complexContent.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/complexContent.rb	(revision 18425)
@@ -0,0 +1,92 @@
+# WSDL4R - XMLSchema complexContent definition for WSDL.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'xsd/namedelements'
+
+
+module WSDL
+module XMLSchema
+
+
+class ComplexContent < Info
+  attr_accessor :base
+  attr_reader :derivetype
+  attr_reader :content
+  attr_reader :attributes
+
+  def initialize
+    super
+    @base = nil
+    @derivetype = nil
+    @content = nil
+    @attributes = XSD::NamedElements.new
+    @basetype = nil
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def elementformdefault
+    parent.elementformdefault
+  end
+
+  def basetype
+    @basetype ||= root.collect_complextypes[@base]
+  end
+
+  def parse_element(element)
+    case element
+    when RestrictionName, ExtensionName
+      @derivetype = element.name
+      self
+    when AllName
+      if @derivetype.nil?
+	raise Parser::ElementConstraintError.new("base attr not found.")
+      end
+      @content = All.new
+      @content
+    when SequenceName
+      if @derivetype.nil?
+	raise Parser::ElementConstraintError.new("base attr not found.")
+      end
+      @content = Sequence.new
+      @content
+    when ChoiceName
+      if @derivetype.nil?
+	raise Parser::ElementConstraintError.new("base attr not found.")
+      end
+      @content = Choice.new
+      @content
+    when AttributeName
+      if @derivetype.nil?
+	raise Parser::ElementConstraintError.new("base attr not found.")
+      end
+      o = Attribute.new
+      @attributes << o
+      o
+    end
+  end
+
+  def parse_attr(attr, value)
+    if @derivetype.nil?
+      return nil
+    end
+    case attr
+    when BaseAttrName
+      @base = value
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/complexType.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/complexType.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/complexType.rb	(revision 18425)
@@ -0,0 +1,139 @@
+# WSDL4R - XMLSchema complexType definition for WSDL.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'wsdl/xmlSchema/content'
+require 'wsdl/xmlSchema/element'
+require 'xsd/namedelements'
+
+
+module WSDL
+module XMLSchema
+
+
+class ComplexType < Info
+  attr_accessor :name
+  attr_accessor :complexcontent
+  attr_accessor :simplecontent
+  attr_reader :content
+  attr_accessor :final
+  attr_accessor :mixed
+  attr_reader :attributes
+
+  def initialize(name = nil)
+    super()
+    @name = name
+    @complexcontent = nil
+    @simplecontent = nil
+    @content = nil
+    @final = nil
+    @mixed = false
+    @attributes = XSD::NamedElements.new
+  end
+
+  def targetnamespace
+    # inner elements can be qualified
+    # parent.is_a?(WSDL::XMLSchema::Element) ? nil : parent.targetnamespace
+    parent.targetnamespace
+  end
+
+  def elementformdefault
+    parent.elementformdefault
+  end
+ 
+  AnyAsElement = Element.new(XSD::QName.new(nil, 'any'), XSD::AnyTypeName)
+  def each_element
+    if content
+      content.elements.each do |element|
+        if element.is_a?(Any)
+          yield(AnyAsElement)
+        else
+          yield(element)
+        end
+      end
+    end
+  end
+
+  def find_element(name)
+    if content
+      content.elements.each do |element|
+        if element.is_a?(Any)
+          return AnyAsElement if name == AnyAsElement.name
+        else
+          return element if name == element.name
+        end
+      end
+    end
+    nil
+  end
+
+  def find_element_by_name(name)
+    if content
+      content.elements.each do |element|
+        if element.is_a?(Any)
+          return AnyAsElement if name == AnyAsElement.name.name
+        else
+          return element if name == element.name.name
+        end
+      end
+    end
+    nil
+  end
+
+  def sequence_elements=(elements)
+    @content = Sequence.new
+    elements.each do |element|
+      @content << element
+    end
+  end
+
+  def all_elements=(elements)
+    @content = All.new
+    elements.each do |element|
+      @content << element
+    end
+  end
+
+  def parse_element(element)
+    case element
+    when AllName
+      @content = All.new
+    when SequenceName
+      @content = Sequence.new
+    when ChoiceName
+      @content = Choice.new
+    when ComplexContentName
+      @complexcontent = ComplexContent.new
+    when SimpleContentName
+      @simplecontent = SimpleContent.new
+    when AttributeName
+      o = Attribute.new
+      @attributes << o
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when FinalAttrName
+      @final = value.source
+    when MixedAttrName
+      @mixed = (value.source == 'true')
+    when NameAttrName
+      @name = XSD::QName.new(targetnamespace, value.source)
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/content.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/content.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/content.rb	(revision 18425)
@@ -0,0 +1,96 @@
+# WSDL4R - XMLSchema complexType definition for WSDL.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module XMLSchema
+
+
+class Content < Info
+  attr_accessor :final
+  attr_accessor :mixed
+  attr_accessor :type
+  attr_reader :contents
+  attr_reader :elements
+
+  def initialize
+    super()
+    @final = nil
+    @mixed = false
+    @type = nil
+    @contents = []
+    @elements = []
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def <<(content)
+    @contents << content
+    update_elements
+  end
+
+  def each
+    @contents.each do |content|
+      yield content
+    end
+  end
+
+  def parse_element(element)
+    case element
+    when AllName, SequenceName, ChoiceName
+      o = Content.new
+      o.type = element.name
+      @contents << o
+      o
+    when AnyName
+      o = Any.new
+      @contents << o
+      o
+    when ElementName
+      o = Element.new
+      @contents << o
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when FinalAttrName
+      @final = value.source
+    when MixedAttrName
+      @mixed = (value.source == 'true')
+    else
+      nil
+    end
+  end
+
+  def parse_epilogue
+    update_elements
+  end
+
+private
+
+  def update_elements
+    @elements = []
+    @contents.each do |content|
+      if content.is_a?(Element)
+	@elements << [content.name, content]
+      end
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/data.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/data.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/data.rb	(revision 18425)
@@ -0,0 +1,80 @@
+# WSDL4R - XMLSchema data definitions.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/datatypes'
+require 'wsdl/xmlSchema/annotation'
+require 'wsdl/xmlSchema/schema'
+require 'wsdl/xmlSchema/import'
+require 'wsdl/xmlSchema/include'
+require 'wsdl/xmlSchema/simpleType'
+require 'wsdl/xmlSchema/simpleRestriction'
+require 'wsdl/xmlSchema/simpleExtension'
+require 'wsdl/xmlSchema/complexType'
+require 'wsdl/xmlSchema/complexContent'
+require 'wsdl/xmlSchema/simpleContent'
+require 'wsdl/xmlSchema/any'
+require 'wsdl/xmlSchema/element'
+require 'wsdl/xmlSchema/all'
+require 'wsdl/xmlSchema/choice'
+require 'wsdl/xmlSchema/sequence'
+require 'wsdl/xmlSchema/attribute'
+require 'wsdl/xmlSchema/unique'
+require 'wsdl/xmlSchema/enumeration'
+require 'wsdl/xmlSchema/length'
+require 'wsdl/xmlSchema/pattern'
+
+module WSDL
+module XMLSchema
+
+
+AllName = XSD::QName.new(XSD::Namespace, 'all')
+AnnotationName = XSD::QName.new(XSD::Namespace, 'annotation')
+AnyName = XSD::QName.new(XSD::Namespace, 'any')
+AttributeName = XSD::QName.new(XSD::Namespace, 'attribute')
+ChoiceName = XSD::QName.new(XSD::Namespace, 'choice')
+ComplexContentName = XSD::QName.new(XSD::Namespace, 'complexContent')
+ComplexTypeName = XSD::QName.new(XSD::Namespace, 'complexType')
+ElementName = XSD::QName.new(XSD::Namespace, 'element')
+EnumerationName = XSD::QName.new(XSD::Namespace, 'enumeration')
+ExtensionName = XSD::QName.new(XSD::Namespace, 'extension')
+ImportName = XSD::QName.new(XSD::Namespace, 'import')
+IncludeName = XSD::QName.new(XSD::Namespace, 'include')
+LengthName = XSD::QName.new(XSD::Namespace, 'length')
+PatternName = XSD::QName.new(XSD::Namespace, 'pattern')
+RestrictionName = XSD::QName.new(XSD::Namespace, 'restriction')
+SequenceName = XSD::QName.new(XSD::Namespace, 'sequence')
+SchemaName = XSD::QName.new(XSD::Namespace, 'schema')
+SimpleContentName = XSD::QName.new(XSD::Namespace, 'simpleContent')
+SimpleTypeName = XSD::QName.new(XSD::Namespace, 'simpleType')
+UniqueName = XSD::QName.new(XSD::Namespace, 'unique')
+
+AttributeFormDefaultAttrName = XSD::QName.new(nil, 'attributeFormDefault')
+BaseAttrName = XSD::QName.new(nil, 'base')
+DefaultAttrName = XSD::QName.new(nil, 'default')
+ElementFormDefaultAttrName = XSD::QName.new(nil, 'elementFormDefault')
+FinalAttrName = XSD::QName.new(nil, 'final')
+FixedAttrName = XSD::QName.new(nil, 'fixed')
+FormAttrName = XSD::QName.new(nil, 'form')
+IdAttrName = XSD::QName.new(nil, 'id')
+MaxOccursAttrName = XSD::QName.new(nil, 'maxOccurs')
+MinOccursAttrName = XSD::QName.new(nil, 'minOccurs')
+MixedAttrName = XSD::QName.new(nil, 'mixed')
+NameAttrName = XSD::QName.new(nil, 'name')
+NamespaceAttrName = XSD::QName.new(nil, 'namespace')
+NillableAttrName = XSD::QName.new(nil, 'nillable')
+ProcessContentsAttrName = XSD::QName.new(nil, 'processContents')
+RefAttrName = XSD::QName.new(nil, 'ref')
+SchemaLocationAttrName = XSD::QName.new(nil, 'schemaLocation')
+TargetNamespaceAttrName = XSD::QName.new(nil, 'targetNamespace')
+TypeAttrName = XSD::QName.new(nil, 'type')
+UseAttrName = XSD::QName.new(nil, 'use')
+ValueAttrName = XSD::QName.new(nil, 'value')
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/element.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/element.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/element.rb	(revision 18425)
@@ -0,0 +1,154 @@
+# WSDL4R - XMLSchema element definition for WSDL.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module XMLSchema
+
+
+class Element < Info
+  class << self
+    if RUBY_VERSION > "1.7.0"
+      def attr_reader_ref(symbol)
+        name = symbol.to_s
+        define_method(name) {
+          instance_variable_get("@#{name}") ||
+            (refelement ? refelement.__send__(name) : nil)
+        }
+      end
+    else
+      def attr_reader_ref(symbol)
+        name = symbol.to_s
+        module_eval <<-EOS
+          def #{name}
+            @#{name} || (refelement ? refelement.#{name} : nil)
+          end
+        EOS
+      end
+    end
+  end
+
+  attr_writer :name	# required
+  attr_writer :form
+  attr_writer :type
+  attr_writer :local_simpletype
+  attr_writer :local_complextype
+  attr_writer :constraint
+  attr_writer :maxoccurs
+  attr_writer :minoccurs
+  attr_writer :nillable
+
+  attr_reader_ref :name
+  attr_reader_ref :form
+  attr_reader_ref :type
+  attr_reader_ref :local_simpletype
+  attr_reader_ref :local_complextype
+  attr_reader_ref :constraint
+  attr_reader_ref :maxoccurs
+  attr_reader_ref :minoccurs
+  attr_reader_ref :nillable
+
+  attr_accessor :ref
+
+  def initialize(name = nil, type = nil)
+    super()
+    @name = name
+    @form = nil
+    @type = type
+    @local_simpletype = @local_complextype = nil
+    @constraint = nil
+    @maxoccurs = '1'
+    @minoccurs = '1'
+    @nillable = nil
+    @ref = nil
+    @refelement = nil
+  end
+
+  def refelement
+    @refelement ||= (@ref ? root.collect_elements[@ref] : nil)
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def elementformdefault
+    parent.elementformdefault
+  end
+
+  def elementform
+    self.form.nil? ? parent.elementformdefault : self.form
+  end
+
+  def parse_element(element)
+    case element
+    when SimpleTypeName
+      @local_simpletype = SimpleType.new
+      @local_simpletype
+    when ComplexTypeName
+      @type = nil
+      @local_complextype = ComplexType.new
+      @local_complextype
+    when UniqueName
+      @constraint = Unique.new
+      @constraint
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NameAttrName
+      # namespace may be nil
+      if directelement? or elementform == 'qualified'
+        @name = XSD::QName.new(targetnamespace, value.source)
+      else
+        @name = XSD::QName.new(nil, value.source)
+      end
+    when FormAttrName
+      @form = value.source
+    when TypeAttrName
+      @type = value
+    when RefAttrName
+      @ref = value
+    when MaxOccursAttrName
+      if parent.is_a?(All)
+	if value.source != '1'
+	  raise Parser::AttrConstraintError.new(
+            "cannot parse #{value} for #{attr}")
+	end
+      end
+      @maxoccurs = value.source
+    when MinOccursAttrName
+      if parent.is_a?(All)
+	unless ['0', '1'].include?(value.source)
+	  raise Parser::AttrConstraintError.new(
+            "cannot parse #{value} for #{attr}")
+	end
+      end
+      @minoccurs = value.source
+    when NillableAttrName
+      @nillable = (value.source == 'true')
+    else
+      nil
+    end
+  end
+
+private
+
+  def directelement?
+    parent.is_a?(Schema)
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/enumeration.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/enumeration.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/enumeration.rb	(revision 18425)
@@ -0,0 +1,36 @@
+# WSDL4R - XMLSchema enumeration definition for WSDL.
+# Copyright (C) 2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module XMLSchema
+
+
+class Enumeration < Info
+  def initialize
+    super
+  end
+
+  def parse_element(element)
+    nil
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when ValueAttrName
+      parent.enumeration << value.source
+      value.source
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/import.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/import.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/import.rb	(revision 18425)
@@ -0,0 +1,65 @@
+# WSDL4R - XMLSchema import definition.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'wsdl/xmlSchema/importer'
+
+
+module WSDL
+module XMLSchema
+
+
+class Import < Info
+  attr_reader :namespace
+  attr_reader :schemalocation
+  attr_reader :content
+
+  def initialize
+    super
+    @namespace = nil
+    @schemalocation = nil
+    @content = nil
+  end
+
+  def parse_element(element)
+    nil
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NamespaceAttrName
+      @namespace = value.source
+    when SchemaLocationAttrName
+      @schemalocation = URI.parse(value.source)
+      if @schemalocation.relative? and !parent.location.nil? and
+          !parent.location.relative?
+        @schemalocation = parent.location + @schemalocation
+      end
+      if root.importedschema.key?(@schemalocation)
+        @content = root.importedschema[@schemalocation]
+      else
+        root.importedschema[@schemalocation] = nil      # placeholder
+        @content = import(@schemalocation)
+        root.importedschema[@schemalocation] = @content
+      end
+      @schemalocation
+    else
+      nil
+    end
+  end
+
+private
+
+  def import(location)
+    Importer.import(location, root)
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/importer.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/importer.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/importer.rb	(revision 18425)
@@ -0,0 +1,87 @@
+# WSDL4R - XSD importer library.
+# Copyright (C) 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'soap/httpconfigloader'
+require 'wsdl/xmlSchema/parser'
+
+
+module WSDL
+module XMLSchema
+
+
+class Importer
+  def self.import(location, originalroot = nil)
+    new.import(location, originalroot)
+  end
+
+  def initialize
+    @web_client = nil
+  end
+
+  def import(location, originalroot = nil)
+    unless location.is_a?(URI)
+      location = URI.parse(location)
+    end
+    content = parse(fetch(location), location, originalroot)
+    content.location = location
+    content
+  end
+
+private
+
+  def parse(content, location, originalroot)
+    opt = {
+      :location => location,
+      :originalroot => originalroot
+    }
+    WSDL::XMLSchema::Parser.new(opt).parse(content)
+  end
+
+  def fetch(location)
+    warn("importing: #{location}") if $DEBUG
+    content = nil
+    if location.scheme == 'file' or
+        (location.relative? and FileTest.exist?(location.path))
+      content = File.open(location.path).read
+    elsif location.scheme and location.scheme.size == 1 and
+        FileTest.exist?(location.to_s)
+      # ToDo: remove this ugly workaround for a path with drive letter
+      # (D://foo/bar)
+      content = File.open(location.to_s).read
+    else
+      client = web_client.new(nil, "WSDL4R")
+      client.proxy = ::SOAP::Env::HTTP_PROXY
+      client.no_proxy = ::SOAP::Env::NO_PROXY
+      if opt = ::SOAP::Property.loadproperty(::SOAP::PropertyName)
+        ::SOAP::HTTPConfigLoader.set_options(client,
+          opt["client.protocol.http"])
+      end
+      content = client.get_content(location)
+    end
+    content
+  end
+
+  def web_client
+    @web_client ||= begin
+	require 'http-access2'
+	if HTTPAccess2::VERSION < "2.0"
+	  raise LoadError.new("http-access/2.0 or later is required.")
+	end
+	HTTPAccess2::Client
+      rescue LoadError
+	warn("Loading http-access2 failed.  Net/http is used.") if $DEBUG
+	require 'soap/netHttpClient'
+	::SOAP::NetHttpClient
+      end
+    @web_client
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/include.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/include.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/include.rb	(revision 18425)
@@ -0,0 +1,54 @@
+# WSDL4R - XMLSchema include definition.
+# Copyright (C) 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'wsdl/xmlSchema/importer'
+
+
+module WSDL
+module XMLSchema
+
+
+class Include < Info
+  attr_reader :schemalocation
+  attr_reader :content
+
+  def initialize
+    super
+    @schemalocation = nil
+    @content = nil
+  end
+
+  def parse_element(element)
+    nil
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when SchemaLocationAttrName
+      @schemalocation = URI.parse(value.source)
+      if @schemalocation.relative?
+        @schemalocation = parent.location + @schemalocation
+      end
+      @content = import(@schemalocation)
+      @schemalocation
+    else
+      nil
+    end
+  end
+
+private
+
+  def import(location)
+    Importer.import(location)
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/length.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/length.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/length.rb	(revision 18425)
@@ -0,0 +1,35 @@
+# WSDL4R - XMLSchema length definition for WSDL.
+# Copyright (C) 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module XMLSchema
+
+
+class Length < Info
+  def initialize
+    super
+  end
+
+  def parse_element(element)
+    nil
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when ValueAttrName
+      value.source
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/parser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/parser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/parser.rb	(revision 18425)
@@ -0,0 +1,166 @@
+# WSDL4R - WSDL XML Instance parser library.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/qname'
+require 'xsd/ns'
+require 'xsd/charset'
+require 'xsd/datatypes'
+require 'xsd/xmlparser'
+require 'wsdl/xmlSchema/data'
+
+
+module WSDL
+module XMLSchema
+
+
+class Parser
+  include XSD
+
+  class ParseError < Error; end
+  class FormatDecodeError < ParseError; end
+  class UnknownElementError < FormatDecodeError; end
+  class UnknownAttributeError < FormatDecodeError; end
+  class UnexpectedElementError < FormatDecodeError; end
+  class ElementConstraintError < FormatDecodeError; end
+  class AttributeConstraintError < FormatDecodeError; end
+
+private
+
+  class ParseFrame
+    attr_reader :ns
+    attr_reader :name
+    attr_accessor :node
+
+  private
+
+    def initialize(ns, name, node)
+      @ns = ns
+      @name = name
+      @node = node
+    end
+  end
+
+public
+
+  def initialize(opt = {})
+    @parser = XSD::XMLParser.create_parser(self, opt)
+    @parsestack = nil
+    @lastnode = nil
+    @ignored = {}
+    @location = opt[:location]
+    @originalroot = opt[:originalroot]
+  end
+
+  def parse(string_or_readable)
+    @parsestack = []
+    @lastnode = nil
+    @textbuf = ''
+    @parser.do_parse(string_or_readable)
+    @lastnode
+  end
+
+  def charset
+    @parser.charset
+  end
+
+  def start_element(name, attrs)
+    lastframe = @parsestack.last
+    ns = parent = nil
+    if lastframe
+      ns = lastframe.ns.clone_ns
+      parent = lastframe.node
+    else
+      ns = XSD::NS.new
+      parent = nil
+    end
+    attrs = XSD::XMLParser.filter_ns(ns, attrs)
+    node = decode_tag(ns, name, attrs, parent)
+    @parsestack << ParseFrame.new(ns, name, node)
+  end
+
+  def characters(text)
+    lastframe = @parsestack.last
+    if lastframe
+      # Need not to be cloned because character does not have attr.
+      ns = lastframe.ns
+      decode_text(ns, text)
+    else
+      p text if $DEBUG
+    end
+  end
+
+  def end_element(name)
+    lastframe = @parsestack.pop
+    unless name == lastframe.name
+      raise UnexpectedElementError.new("closing element name '#{name}' does not match with opening element '#{lastframe.name}'")
+    end
+    decode_tag_end(lastframe.ns, lastframe.node)
+    @lastnode = lastframe.node
+  end
+
+private
+
+  def decode_tag(ns, name, attrs, parent)
+    o = nil
+    elename = ns.parse(name)
+    if !parent
+      if elename == SchemaName
+	o = Schema.parse_element(elename)
+        o.location = @location
+      else
+	raise UnknownElementError.new("unknown element: #{elename}")
+      end
+      o.root = @originalroot if @originalroot   # o.root = o otherwise
+    else
+      if elename == AnnotationName
+        # only the first annotation element is allowed for each element.
+        o = Annotation.new
+      else
+        o = parent.parse_element(elename)
+      end
+      unless o
+        unless @ignored.key?(elename)
+          warn("ignored element: #{elename} of #{parent.class}")
+          @ignored[elename] = elename
+        end
+	o = Documentation.new	# which accepts any element.
+      end
+      # node could be a pseudo element.  pseudo element has its own parent.
+      o.root = parent.root
+      o.parent = parent if o.parent.nil?
+    end
+    attrs.each do |key, value|
+      attr_ele = ns.parse(key, true)
+      value_ele = ns.parse(value, true)
+      value_ele.source = value  # for recovery; value may not be a QName
+      if attr_ele == IdAttrName
+	o.id = value_ele
+      else
+        unless o.parse_attr(attr_ele, value_ele)
+          unless @ignored.key?(attr_ele)
+            warn("ignored attr: #{attr_ele}")
+            @ignored[attr_ele] = attr_ele
+          end
+        end
+      end
+    end
+    o
+  end
+
+  def decode_tag_end(ns, node)
+    node.parse_epilogue
+  end
+
+  def decode_text(ns, text)
+    @textbuf << text
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/pattern.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/pattern.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/pattern.rb	(revision 18425)
@@ -0,0 +1,36 @@
+# WSDL4R - XMLSchema pattern definition for WSDL.
+# Copyright (C) 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module XMLSchema
+
+
+class Pattern < Info
+  def initialize
+    super
+  end
+
+  def parse_element(element)
+    nil
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when ValueAttrName
+      parent.pattern = /\A#{value.source}\z/n
+      value.source
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/schema.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/schema.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/schema.rb	(revision 18425)
@@ -0,0 +1,143 @@
+# WSDL4R - XMLSchema schema definition for WSDL.
+# Copyright (C) 2002, 2003-2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'xsd/namedelements'
+
+
+module WSDL
+module XMLSchema
+
+
+class Schema < Info
+  attr_reader :targetnamespace	# required
+  attr_reader :complextypes
+  attr_reader :simpletypes
+  attr_reader :elements
+  attr_reader :attributes
+  attr_reader :imports
+  attr_accessor :attributeformdefault
+  attr_accessor :elementformdefault
+
+  attr_reader :importedschema
+
+  def initialize
+    super
+    @targetnamespace = nil
+    @complextypes = XSD::NamedElements.new
+    @simpletypes = XSD::NamedElements.new
+    @elements = XSD::NamedElements.new
+    @attributes = XSD::NamedElements.new
+    @imports = []
+    @attributeformdefault = "unqualified"
+    @elementformdefault = "unqualified"
+    @importedschema = {}
+    @location = nil
+    @root = self
+  end
+
+  def location
+    @location || (root.nil? ? nil : root.location)
+  end
+
+  def location=(location)
+    @location = location
+  end
+
+  def parse_element(element)
+    case element
+    when ImportName
+      o = Import.new
+      @imports << o
+      o
+    when IncludeName
+      o = Include.new
+      @imports << o
+      o
+    when ComplexTypeName
+      o = ComplexType.new
+      @complextypes << o
+      o
+    when SimpleTypeName
+      o = SimpleType.new
+      @simpletypes << o
+      o
+    when ElementName
+      o = Element.new
+      @elements << o
+      o
+    when AttributeName
+      o = Attribute.new
+      @attributes << o
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when TargetNamespaceAttrName
+      @targetnamespace = value.source
+    when AttributeFormDefaultAttrName
+      @attributeformdefault = value.source
+    when ElementFormDefaultAttrName
+      @elementformdefault = value.source
+    else
+      nil
+    end
+  end
+
+  def collect_attributes
+    result = XSD::NamedElements.new
+    result.concat(@attributes)
+    @imports.each do |import|
+      result.concat(import.content.collect_attributes) if import.content
+    end
+    result
+  end
+
+  def collect_elements
+    result = XSD::NamedElements.new
+    result.concat(@elements)
+    @imports.each do |import|
+      result.concat(import.content.collect_elements) if import.content
+    end
+    result
+  end
+
+  def collect_complextypes
+    result = XSD::NamedElements.new
+    result.concat(@complextypes)
+    @imports.each do |import|
+      result.concat(import.content.collect_complextypes) if import.content
+    end
+    result
+  end
+
+  def collect_simpletypes
+    result = XSD::NamedElements.new
+    result.concat(@simpletypes)
+    @imports.each do |import|
+      result.concat(import.content.collect_simpletypes) if import.content
+    end
+    result
+  end
+
+  def self.parse_element(element)
+    if element == SchemaName
+      Schema.new
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/sequence.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/sequence.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/sequence.rb	(revision 18425)
@@ -0,0 +1,69 @@
+# WSDL4R - XMLSchema complexType definition for WSDL.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module XMLSchema
+
+
+class Sequence < Info
+  attr_reader :minoccurs
+  attr_reader :maxoccurs
+  attr_reader :elements
+
+  def initialize
+    super()
+    @minoccurs = '1'
+    @maxoccurs = '1'
+    @elements = []
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def elementformdefault
+    parent.elementformdefault
+  end
+
+  def <<(element)
+    @elements << element
+  end
+
+  def parse_element(element)
+    case element
+    when AnyName
+      o = Any.new
+      @elements << o
+      o
+    when ElementName
+      o = Element.new
+      @elements << o
+      o
+    else
+      nil
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when MaxOccursAttrName
+      @maxoccurs = value.source
+    when MinOccursAttrName
+      @minoccurs = value.source
+    else
+      nil
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/simpleContent.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/simpleContent.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/simpleContent.rb	(revision 18425)
@@ -0,0 +1,65 @@
+# WSDL4R - XMLSchema simpleContent definition for WSDL.
+# Copyright (C) 2004, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'xsd/namedelements'
+
+
+module WSDL
+module XMLSchema
+
+
+class SimpleContent < Info
+  attr_reader :restriction
+  attr_reader :extension
+
+  def check_lexical_format(value)
+    check(value)
+  end
+
+  def initialize
+    super
+    @restriction = nil
+    @extension = nil
+  end
+
+  def base
+    content.base
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def parse_element(element)
+    case element
+    when RestrictionName
+      @restriction = SimpleRestriction.new
+      @restriction
+    when ExtensionName
+      @extension = SimpleExtension.new
+      @extension
+    end
+  end
+
+private
+
+  def content
+    @restriction || @extension
+  end
+
+  def check(value)
+    unless content.valid?(value)
+      raise XSD::ValueSpaceError.new("#{@name}: cannot accept '#{value}'")
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/simpleExtension.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/simpleExtension.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/simpleExtension.rb	(revision 18425)
@@ -0,0 +1,54 @@
+# WSDL4R - XMLSchema simpleType extension definition for WSDL.
+# Copyright (C) 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'xsd/namedelements'
+
+
+module WSDL
+module XMLSchema
+
+
+class SimpleExtension < Info
+  attr_reader :base
+  attr_reader :attributes
+
+  def initialize
+    super
+    @base = nil
+    @attributes = XSD::NamedElements.new
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+  
+  def valid?(value)
+    true
+  end
+
+  def parse_element(element)
+    case element
+    when AttributeName
+      o = Attribute.new
+      @attributes << o
+      o
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when BaseAttrName
+      @base = value
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/simpleRestriction.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/simpleRestriction.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/simpleRestriction.rb	(revision 18425)
@@ -0,0 +1,73 @@
+# WSDL4R - XMLSchema simpleContent restriction definition for WSDL.
+# Copyright (C) 2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'xsd/namedelements'
+
+
+module WSDL
+module XMLSchema
+
+
+class SimpleRestriction < Info
+  attr_reader :base
+  attr_reader :enumeration
+  attr_accessor :length
+  attr_accessor :pattern
+
+  def initialize
+    super
+    @base = nil
+    @enumeration = []   # NamedElements?
+    @length = nil
+    @pattern = nil
+  end
+  
+  def valid?(value)
+    return false unless check_restriction(value)
+    return false unless check_length(value)
+    return false unless check_pattern(value)
+    true
+  end
+
+  def parse_element(element)
+    case element
+    when EnumerationName
+      Enumeration.new   # just a parsing handler
+    when LengthName
+      Length.new   # just a parsing handler
+    when PatternName
+      Pattern.new   # just a parsing handler
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when BaseAttrName
+      @base = value
+    end
+  end
+
+private
+
+  def check_restriction(value)
+    @enumeration.empty? or @enumeration.include?(value)
+  end
+
+  def check_length(value)
+    @length.nil? or value.size == @length
+  end
+
+  def check_pattern(value)
+    @pattern.nil? or @pattern =~ value
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/simpleType.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/simpleType.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/simpleType.rb	(revision 18425)
@@ -0,0 +1,73 @@
+# WSDL4R - XMLSchema simpleType definition for WSDL.
+# Copyright (C) 2004, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+require 'xsd/namedelements'
+
+
+module WSDL
+module XMLSchema
+
+
+class SimpleType < Info
+  attr_accessor :name
+  attr_reader :restriction
+
+  def check_lexical_format(value)
+    if @restriction
+      check_restriction(value)
+    else
+      raise ArgumentError.new("incomplete simpleType")
+    end
+  end
+
+  def base
+    if @restriction
+      @restriction.base
+    else
+      raise ArgumentError.new("incomplete simpleType")
+    end
+  end
+
+  def initialize(name = nil)
+    super()
+    @name = name
+    @restriction = nil
+  end
+
+  def targetnamespace
+    parent.targetnamespace
+  end
+
+  def parse_element(element)
+    case element
+    when RestrictionName
+      @restriction = SimpleRestriction.new
+      @restriction
+    end
+  end
+
+  def parse_attr(attr, value)
+    case attr
+    when NameAttrName
+      @name = XSD::QName.new(targetnamespace, value.source)
+    end
+  end
+
+private
+
+  def check_restriction(value)
+    unless @restriction.valid?(value)
+      raise XSD::ValueSpaceError.new("#{@name}: cannot accept '#{value}'")
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/unique.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/unique.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/unique.rb	(revision 18425)
@@ -0,0 +1,34 @@
+# WSDL4R - XMLSchema unique element.
+# Copyright (C) 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'wsdl/info'
+
+
+module WSDL
+module XMLSchema
+
+
+class Unique < Info
+  def initialize
+    super
+  end
+
+  def parse_element(element)
+    # Accepts any element.
+    self
+  end
+
+  def parse_attr(attr, value)
+    # Accepts any attribute.
+    true
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/xsd2ruby.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/xsd2ruby.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/wsdl/xmlSchema/xsd2ruby.rb	(revision 18425)
@@ -0,0 +1,107 @@
+# XSD4R - XSD to ruby mapping library.
+# Copyright (C) 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/codegen/gensupport'
+require 'wsdl/xmlSchema/importer'
+require 'wsdl/soap/classDefCreator'
+
+
+module WSDL
+module XMLSchema
+
+
+class XSD2Ruby
+  attr_accessor :location
+  attr_reader :opt
+  attr_accessor :logger
+  attr_accessor :basedir
+
+  def run
+    unless @location
+      raise RuntimeError, "XML Schema location not given"
+    end
+    @xsd = import(@location)
+    @name = create_classname(@xsd)
+    create_file
+  end
+
+private
+
+  def initialize
+    @location = nil
+    @opt = {}
+    @logger = Logger.new(STDERR)
+    @basedir = nil
+    @xsd = nil
+    @name = nil
+  end
+
+  def create_file
+    create_classdef
+  end
+
+  def create_classdef
+    @logger.info { "Creating class definition." }
+    @classdef_filename = @name + '.rb'
+    check_file(@classdef_filename) or return
+    write_file(@classdef_filename) do |f|
+      f << WSDL::SOAP::ClassDefCreator.new(@xsd).dump
+    end
+  end
+
+  def write_file(filename)
+    if @basedir
+      filename = File.join(basedir, filename)
+    end
+    File.open(filename, "w") do |f|
+      yield f
+    end
+  end
+
+  def check_file(filename)
+    if @basedir
+      filename = File.join(basedir, filename)
+    end
+    if FileTest.exist?(filename)
+      if @opt.key?('force')
+	@logger.warn {
+	  "File '#{filename}' exists but overrides it."
+	}
+	true
+      else
+	@logger.warn {
+	  "File '#{filename}' exists.  #{$0} did not override it."
+	}
+	false
+      end
+    else
+      @logger.info { "Creates file '#{filename}'." }
+      true
+    end
+  end
+
+  def create_classname(xsd)
+    name = nil
+    if xsd.targetnamespace
+      name = xsd.targetnamespace.scan(/[a-zA-Z0-9]+$/)[0]
+    end
+    if name.nil?
+      'default'
+    else
+      XSD::CodeGen::GenSupport.safevarname(name)
+    end
+  end
+
+  def import(location)
+    WSDL::XMLSchema::Importer.import(location)
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/base64.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/base64.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/base64.rb	(revision 18425)
@@ -0,0 +1,81 @@
+=begin
+= xmlrpc/base64.rb
+Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
+
+Released under the same term of license as Ruby.
+
+= Classes
+* ((<XMLRPC::Base64>))
+
+= XMLRPC::Base64
+== Description
+This class is necessary for (('xmlrpc4r')) to determine that a string should 
+be transmitted base64-encoded and not as a raw-string. 
+You can use (({XMLRPC::Base64})) on the client and server-side as a 
+parameter and/or return-value.
+
+== Class Methods
+--- XMLRPC::Base64.new( str, state = :dec )
+    Creates a new (({XMLRPC::Base64})) instance with string ((|str|)) as the
+    internal string. When ((|state|)) is (({:dec})) it assumes that the 
+    string ((|str|)) is not in base64 format (perhaps already decoded), 
+    otherwise if ((|state|)) is (({:enc})) it decodes ((|str|)) 
+    and stores it as the internal string.
+    
+--- XMLRPC::Base64.decode( str )
+    Decodes string ((|str|)) with base64 and returns that value.
+
+--- XMLRPC::Base64.encode( str )
+    Encodes string ((|str|)) with base64 and returns that value.
+
+== Instance Methods
+--- XMLRPC::Base64#decoded
+    Returns the internal string decoded.
+
+--- XMLRPC::Base64#encoded
+    Returns the internal string encoded with base64.
+
+=end
+
+module XMLRPC
+
+class Base64
+  
+  def initialize(str, state = :dec)
+    case state
+    when :enc
+      @str = Base64.decode(str)
+    when :dec
+      @str = str
+    else
+      raise ArgumentError, "wrong argument; either :enc or :dec"
+    end
+  end
+  
+  def decoded
+    @str  
+  end
+  
+  def encoded
+    Base64.encode(@str)
+  end
+
+
+  def Base64.decode(str)
+    str.gsub(/\s+/, "").unpack("m")[0]
+  end
+
+  def Base64.encode(str)
+    [str].pack("m")
+  end
+
+end
+
+
+end # module XMLRPC
+
+
+=begin
+= History
+    $Id: base64.rb 11708 2007-02-12 23:01:19Z shyouhei $
+=end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/client.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/client.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/client.rb	(revision 18425)
@@ -0,0 +1,616 @@
+=begin
+= xmlrpc/client.rb
+Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
+
+Released under the same term of license as Ruby.
+
+= Classes
+* ((<XMLRPC::Client>))
+* ((<XMLRPC::Client::Proxy>))
+
+
+= XMLRPC::Client
+== Synopsis
+    require "xmlrpc/client"
+
+    server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80)
+    begin
+      param = server.call("michael.add", 4, 5)
+      puts "4 + 5 = #{param}"
+    rescue XMLRPC::FaultException => e
+      puts "Error:"
+      puts e.faultCode
+      puts e.faultString
+    end
+
+or
+
+    require "xmlrpc/client"
+  
+    server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80)
+    ok, param = server.call2("michael.add", 4, 5)
+    if ok then
+      puts "4 + 5 = #{param}"
+    else
+      puts "Error:"
+      puts param.faultCode
+      puts param.faultString
+    end
+
+== Description
+Class (({XMLRPC::Client})) provides remote procedure calls to a XML-RPC server.
+After setting the connection-parameters with ((<XMLRPC::Client.new>)) which
+creates a new (({XMLRPC::Client})) instance, you can execute a remote procedure 
+by sending the ((<call|XMLRPC::Client#call>)) or ((<call2|XMLRPC::Client#call2>))
+message to this new instance. The given parameters indicate which method to 
+call on the remote-side and of course the parameters for the remote procedure.
+
+== Class Methods
+--- XMLRPC::Client.new( host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil, user=nil, password=nil, use_ssl=false, timeout =nil)
+    Creates an object which represents the remote XML-RPC server on the 
+    given host ((|host|)). If the server is CGI-based, ((|path|)) is the
+    path to the CGI-script, which will be called, otherwise (in the
+    case of a standalone server) ((|path|)) should be (({"/RPC2"})).
+    ((|port|)) is the port on which the XML-RPC server listens.
+    If ((|proxy_host|)) is given, then a proxy server listening at
+    ((|proxy_host|)) is used. ((|proxy_port|)) is the port of the
+    proxy server.
+
+    Default values for ((|host|)), ((|path|)) and ((|port|)) are 'localhost', '/RPC2' and
+    '80' respectively using SSL '443'.
+
+    If ((|user|)) and ((|password|)) are given, each time a request is send, 
+    a Authorization header is send. Currently only Basic Authentification is 
+    implemented no Digest.
+
+    If ((|use_ssl|)) is set to (({true})), comunication over SSL is enabled.
+    Note, that you need the SSL package from RAA installed.
+
+    Parameter ((|timeout|)) is the time to wait for a XML-RPC response, defaults to 30.
+
+--- XMLRPC::Client.new2( uri, proxy=nil, timeout=nil)
+--- XMLRPC::Client.new_from_uri( uri, proxy=nil, timeout=nil)
+:   uri
+    URI specifying protocol (http or https), host, port, path, user and password.
+    Example: https://user:password@host:port/path
+
+:   proxy
+    Is of the form "host:port".
+ 
+:   timeout
+    Defaults to 30. 
+
+--- XMLRPC::Client.new3( hash={} )
+--- XMLRPC::Client.new_from_hash( hash={} )
+    Parameter ((|hash|)) has following case-insensitive keys:
+    * host
+    * path
+    * port
+    * proxy_host
+    * proxy_port
+    * user
+    * password
+    * use_ssl
+    * timeout
+
+    Calls ((<XMLRPC::Client.new>)) with the corresponding values.
+
+== Instance Methods
+--- XMLRPC::Client#call( method, *args )
+    Invokes the method named ((|method|)) with the parameters given by 
+    ((|args|)) on the XML-RPC server.
+    The parameter ((|method|)) is converted into a (({String})) and should 
+    be a valid XML-RPC method-name.  
+    Each parameter of ((|args|)) must be of one of the following types,
+    where (({Hash})), (({Struct})) and (({Array})) can contain any of these listed ((:types:)):
+    * (({Fixnum})), (({Bignum}))
+    * (({TrueClass})), (({FalseClass})) ((({true})), (({false})))
+    * (({String})), (({Symbol}))
+    * (({Float}))
+    * (({Hash})), (({Struct}))
+    * (({Array}))
+    * (({Date})), (({Time})), (({XMLRPC::DateTime}))
+    * (({XMLRPC::Base64})) 
+    * A Ruby object which class includes XMLRPC::Marshallable (only if Config::ENABLE_MARSHALLABLE is (({true}))). 
+      That object is converted into a hash, with one additional key/value pair "___class___" which contains the class name
+      for restoring later that object.
+    
+    The method returns the return-value from the RPC 
+    ((-stands for Remote Procedure Call-)). 
+    The type of the return-value is one of the above shown,
+    only that a (({Bignum})) is only allowed when it fits in 32-bit and
+    that a XML-RPC (('dateTime.iso8601')) type is always returned as
+    a ((<(({XMLRPC::DateTime}))|URL:datetime.html>)) object and 
+    a (({Struct})) is never returned, only a (({Hash})), the same for a (({Symbol})), where
+    always a (({String})) is returned. 
+    A (({XMLRPC::Base64})) is returned as a (({String})) from xmlrpc4r version 1.6.1 on.
+    
+    If the remote procedure returned a fault-structure, then a 
+    (({XMLRPC::FaultException})) exception is raised, which has two accessor-methods
+    (({faultCode})) and (({faultString})) of type (({Integer})) and (({String})).
+
+--- XMLRPC::Client#call2( method, *args )
+    The difference between this method and ((<call|XMLRPC::Client#call>)) is, that
+    this method do ((*not*)) raise a (({XMLRPC::FaultException})) exception.
+    The method returns an array of two values. The first value indicates if 
+    the second value is a return-value ((({true}))) or an object of type
+    (({XMLRPC::FaultException})). 
+    Both are explained in ((<call|XMLRPC::Client#call>)).
+
+    Simple to remember: The "2" in "call2" denotes the number of values it returns.
+
+--- XMLRPC::Client#multicall( *methods )
+    You can use this method to execute several methods on a XMLRPC server which supports
+    the multi-call extension.
+    Example:
+
+      s.multicall(
+        ['michael.add', 3, 4],
+        ['michael.sub', 4, 5]
+      )
+      # => [7, -1]
+
+--- XMLRPC::Client#multicall2( *methods )
+    Same as ((<XMLRPC::Client#multicall>)), but returns like ((<XMLRPC::Client#call2>)) two parameters 
+    instead of raising an (({XMLRPC::FaultException})).
+
+--- XMLRPC::Client#proxy( prefix, *args )
+    Returns an object of class (({XMLRPC::Client::Proxy})), initialized with
+    ((|prefix|)) and ((|args|)). A proxy object returned by this method behaves
+    like ((<XMLRPC::Client#call>)), i.e. a call on that object will raise a
+    (({XMLRPC::FaultException})) when a fault-structure is returned by that call. 
+
+--- XMLRPC::Client#proxy2( prefix, *args )
+    Almost the same like ((<XMLRPC::Client#proxy>)) only that a call on the returned
+    (({XMLRPC::Client::Proxy})) object behaves like ((<XMLRPC::Client#call2>)), i.e.
+    a call on that object will return two parameters. 
+
+
+
+
+--- XMLRPC::Client#call_async(...)
+--- XMLRPC::Client#call2_async(...)
+--- XMLRPC::Client#multicall_async(...)
+--- XMLRPC::Client#multicall2_async(...)
+--- XMLRPC::Client#proxy_async(...)
+--- XMLRPC::Client#proxy2_async(...)
+    In contrast to corresponding methods without "_async", these can be
+    called concurrently and use for each request a new connection, where the 
+    non-asynchronous counterparts use connection-alive (one connection for all requests)
+    if possible. 
+
+    Note, that you have to use Threads to call these methods concurrently. 
+    The following example calls two methods concurrently:
+    
+      Thread.new {
+        p client.call_async("michael.add", 4, 5)
+      }
+ 
+      Thread.new {
+        p client.call_async("michael.div", 7, 9)
+      }
+ 
+
+--- XMLRPC::Client#timeout
+--- XMLRPC::Client#user
+--- XMLRPC::Client#password
+    Return the corresponding attributes.
+
+--- XMLRPC::Client#timeout= (new_timeout)
+--- XMLRPC::Client#user= (new_user)
+--- XMLRPC::Client#password= (new_password)
+    Set the corresponding attributes.
+    
+
+--- XMLRPC::Client#set_writer( writer )
+    Sets the XML writer to use for generating XML output.
+    Should be an instance of a class from module (({XMLRPC::XMLWriter})).
+    If this method is not called, then (({XMLRPC::Config::DEFAULT_WRITER})) is used. 
+
+--- XMLRPC::Client#set_parser( parser )
+    Sets the XML parser to use for parsing XML documents.
+    Should be an instance of a class from module (({XMLRPC::XMLParser})).
+    If this method is not called, then (({XMLRPC::Config::DEFAULT_PARSER})) is used.
+
+--- XMLRPC::Client#cookie
+--- XMLRPC::Client#cookie= (cookieString)
+    Get and set the HTTP Cookie header.
+
+--- XMLRPC::Client#http_header_extra= (additionalHeaders)
+    Set extra HTTP headers that are included in the request.
+
+--- XMLRPC::Client#http_header_extra
+    Access the via ((<XMLRPC::Client#http_header_extra=>)) assigned header. 
+
+--- XMLRPC::Client#http_last_response
+    Returns the (({Net::HTTPResponse})) object of the last RPC.
+
+= XMLRPC::Client::Proxy
+== Synopsis
+    require "xmlrpc/client"
+
+    server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80)
+
+    michael  = server.proxy("michael")
+    michael2 = server.proxy("michael", 4)
+
+    # both calls should return the same value '9'.
+    p michael.add(4,5)
+    p michael2.add(5)
+
+== Description
+Class (({XMLRPC::Client::Proxy})) makes XML-RPC calls look nicer!
+You can call any method onto objects of that class - the object handles 
+(({method_missing})) and will forward the method call to a XML-RPC server.
+Don't use this class directly, but use instead method ((<XMLRPC::Client#proxy>)) or
+((<XMLRPC::Client#proxy2>)).
+
+== Class Methods
+--- XMLRPC::Client::Proxy.new( server, prefix, args=[], meth=:call, delim="." ) 
+    Creates an object which provides (({method_missing})).
+
+    ((|server|)) must be of type (({XMLRPC::Client})), which is the XML-RPC server to be used
+    for a XML-RPC call. ((|prefix|)) and ((|delim|)) will be prepended to the methodname
+    called onto this object. 
+
+    Parameter ((|meth|)) is the method (call, call2, call_async, call2_async) to use for
+    a RPC.
+
+    ((|args|)) are arguments which are automatically given
+    to every XML-RPC call before the arguments provides through (({method_missing})).
+    
+== Instance Methods
+Every method call is forwarded to the XML-RPC server defined in ((<new|XMLRPC::Client::Proxy#new>)).
+    
+Note: Inherited methods from class (({Object})) cannot be used as XML-RPC names, because they get around
+(({method_missing})). 
+          
+
+
+= History
+    $Id: client.rb 11820 2007-02-23 03:47:59Z knu $
+
+=end
+
+
+
+require "xmlrpc/parser"
+require "xmlrpc/create"
+require "xmlrpc/config"
+require "xmlrpc/utils"     # ParserWriterChooseMixin
+require "net/http"
+
+module XMLRPC
+
+  class Client
+   
+    USER_AGENT = "XMLRPC::Client (Ruby #{RUBY_VERSION})"
+
+    include ParserWriterChooseMixin
+    include ParseContentType
+
+
+    # Constructors -------------------------------------------------------------------
+
+    def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil, 
+                   user=nil, password=nil, use_ssl=nil, timeout=nil)
+
+      @http_header_extra = nil
+      @http_last_response = nil 
+      @cookie = nil
+
+      @host       = host || "localhost"
+      @path       = path || "/RPC2"
+      @proxy_host = proxy_host
+      @proxy_port = proxy_port
+      @proxy_host ||= 'localhost' if @proxy_port != nil
+      @proxy_port ||= 8080 if @proxy_host != nil
+      @use_ssl    = use_ssl || false
+      @timeout    = timeout || 30
+
+      if use_ssl
+        require "net/https"
+        @port = port || 443
+      else
+        @port = port || 80
+      end
+
+      @user, @password = user, password
+
+      set_auth
+
+      # convert ports to integers
+      @port = @port.to_i if @port != nil
+      @proxy_port = @proxy_port.to_i if @proxy_port != nil
+
+      # HTTP object for synchronous calls
+      Net::HTTP.version_1_2
+      @http = Net::HTTP.new(@host, @port, @proxy_host, @proxy_port) 
+      @http.use_ssl = @use_ssl if @use_ssl
+      @http.read_timeout = @timeout
+      @http.open_timeout = @timeout
+
+      @parser = nil
+      @create = nil
+    end
+
+
+    class << self
+
+    def new2(uri, proxy=nil, timeout=nil)
+      if match = /^([^:]+):\/\/(([^@]+)@)?([^\/]+)(\/.*)?$/.match(uri)
+        proto = match[1]
+        user, passwd = (match[3] || "").split(":")
+        host, port = match[4].split(":") 
+        path = match[5]
+
+        if proto != "http" and proto != "https"
+          raise "Wrong protocol specified. Only http or https allowed!"
+        end
+
+      else
+        raise "Wrong URI as parameter!"
+      end
+ 
+      proxy_host, proxy_port = (proxy || "").split(":")
+
+      self.new(host, path, port, proxy_host, proxy_port, user, passwd, (proto == "https"), timeout)
+    end
+
+    alias new_from_uri new2
+
+    def new3(hash={})
+
+      # convert all keys into lowercase strings
+      h = {}
+      hash.each { |k,v| h[k.to_s.downcase] = v }
+
+      self.new(h['host'], h['path'], h['port'], h['proxy_host'], h['proxy_port'], h['user'], h['password'],
+               h['use_ssl'], h['timeout'])
+    end
+
+    alias new_from_hash new3
+
+    end
+
+
+    # Attribute Accessors -------------------------------------------------------------------
+
+    # add additional HTTP headers to the request
+    attr_accessor :http_header_extra
+
+    # makes last HTTP response accessible
+    attr_reader :http_last_response
+
+    # Cookie support
+    attr_accessor :cookie
+    
+
+    attr_reader :timeout, :user, :password
+
+    def timeout=(new_timeout)
+      @timeout = new_timeout
+      @http.read_timeout = @timeout
+      @http.open_timeout = @timeout
+    end
+
+    def user=(new_user)
+      @user = new_user
+      set_auth
+    end
+
+    def password=(new_password)
+      @password = new_password
+      set_auth
+    end
+
+    # Call methods --------------------------------------------------------------
+
+    def call(method, *args)
+      ok, param = call2(method, *args) 
+      if ok
+        param
+      else
+        raise param
+      end
+    end 
+
+    def call2(method, *args)
+      request = create().methodCall(method, *args)
+      data = do_rpc(request, false)
+      parser().parseMethodResponse(data)
+    end
+
+    def call_async(method, *args)
+      ok, param = call2_async(method, *args) 
+      if ok
+        param
+      else
+        raise param
+      end
+    end 
+
+    def call2_async(method, *args)
+      request = create().methodCall(method, *args)
+      data = do_rpc(request, true)
+      parser().parseMethodResponse(data)
+    end
+
+
+    # Multicall methods --------------------------------------------------------------
+
+    def multicall(*methods)
+      ok, params = multicall2(*methods)
+      if ok
+        params
+      else
+        raise params
+      end
+    end
+
+    def multicall2(*methods)
+      gen_multicall(methods, false)
+    end
+
+    def multicall_async(*methods)
+      ok, params = multicall2_async(*methods)
+      if ok
+        params
+      else
+        raise params
+      end
+    end
+
+    def multicall2_async(*methods)
+      gen_multicall(methods, true)
+    end
+
+
+    # Proxy generating methods ------------------------------------------
+    
+    def proxy(prefix=nil, *args)
+      Proxy.new(self, prefix, args, :call)
+    end
+
+    def proxy2(prefix=nil, *args)
+      Proxy.new(self, prefix, args, :call2)
+    end
+
+    def proxy_async(prefix=nil, *args)
+      Proxy.new(self, prefix, args, :call_async)
+    end
+
+    def proxy2_async(prefix=nil, *args)
+      Proxy.new(self, prefix, args, :call2_async)
+    end
+
+
+    private # ----------------------------------------------------------
+
+    def set_auth
+      if @user.nil?
+        @auth = nil
+      else
+        a =  "#@user"
+        a << ":#@password" if @password != nil
+        @auth = ("Basic " + [a].pack("m")).chomp
+      end
+    end
+
+    def do_rpc(request, async=false)
+      header = {  
+       "User-Agent"     =>  USER_AGENT,
+       "Content-Type"   => "text/xml; charset=utf-8",
+       "Content-Length" => request.size.to_s, 
+       "Connection"     => (async ? "close" : "keep-alive")
+      }
+
+      header["Cookie"] = @cookie        if @cookie
+      header.update(@http_header_extra) if @http_header_extra
+
+      if @auth != nil
+        # add authorization header
+        header["Authorization"] = @auth
+      end
+ 
+      resp = nil
+      @http_last_response = nil
+
+      if async
+        # use a new HTTP object for each call 
+        Net::HTTP.version_1_2
+        http = Net::HTTP.new(@host, @port, @proxy_host, @proxy_port) 
+        http.use_ssl = @use_ssl if @use_ssl
+        http.read_timeout = @timeout
+        http.open_timeout = @timeout
+        
+        # post request
+        http.start {
+          resp = http.post2(@path, request, header) 
+        }
+      else
+        # reuse the HTTP object for each call => connection alive is possible
+        
+        # post request
+        resp = @http.post2(@path, request, header) 
+      end
+  
+      @http_last_response = resp
+
+      data = resp.body
+
+      if resp.code == "401"
+        # Authorization Required
+        raise "Authorization failed.\nHTTP-Error: #{resp.code} #{resp.message}" 
+      elsif resp.code[0,1] != "2"
+        raise "HTTP-Error: #{resp.code} #{resp.message}" 
+      end
+
+      ct = parse_content_type(resp["Content-Type"]).first
+      if ct != "text/xml"
+        if ct == "text/html"
+          raise "Wrong content-type: \n#{data}"
+        else
+          raise "Wrong content-type"
+        end
+      end
+
+      expected = resp["Content-Length"] || "<unknown>"
+      if data.nil? or data.size == 0 
+        raise "Wrong size. Was #{data.size}, should be #{expected}" 
+      elsif expected != "<unknown>" and expected.to_i != data.size and resp["Transfer-Encoding"].nil?
+        raise "Wrong size. Was #{data.size}, should be #{expected}"
+      end
+
+      c = resp["Set-Cookie"]
+      @cookie = c if c
+
+      return data
+    end
+
+    def gen_multicall(methods=[], async=false)
+      meth = :call2
+      meth = :call2_async if async
+
+      ok, params = self.send(meth, "system.multicall", 
+        methods.collect {|m| {'methodName' => m[0], 'params' => m[1..-1]} }
+      )
+
+      if ok 
+        params = params.collect do |param|
+          if param.is_a? Array
+            param[0]
+          elsif param.is_a? Hash
+            XMLRPC::FaultException.new(param["faultCode"], param["faultString"])
+          else
+            raise "Wrong multicall return value"
+          end 
+        end
+      end
+
+      return ok, params
+    end
+
+
+
+    class Proxy
+
+      def initialize(server, prefix, args=[], meth=:call, delim=".")
+	@server = server
+	@prefix = prefix ? prefix + delim : ""
+	@args   = args 
+        @meth   = meth
+      end
+
+      def method_missing(mid, *args)
+	pre = @prefix + mid.to_s
+	arg = @args + args
+	@server.send(@meth, pre, *arg)
+      end
+
+    end # class Proxy
+
+  end # class Client
+
+end # module XMLRPC
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/config.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/config.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/config.rb	(revision 18425)
@@ -0,0 +1,40 @@
+#
+# $Id: config.rb 11708 2007-02-12 23:01:19Z shyouhei $
+# Configuration file for XML-RPC for Ruby
+#
+
+module XMLRPC
+
+  module Config
+
+    DEFAULT_WRITER = XMLWriter::Simple            # or XMLWriter::XMLParser
+    
+    # available parser:
+    #   * XMLParser::NQXMLTreeParser
+    #   * XMLParser::NQXMLStreamParser
+    #   * XMLParser::XMLTreeParser
+    #   * XMLParser::XMLStreamParser (fastest)
+    #   * XMLParser::REXMLStreamParser
+    #   * XMLParser::XMLScanStreamParser
+    DEFAULT_PARSER = XMLParser::REXMLStreamParser
+
+    # enable <nil/> tag
+    ENABLE_NIL_CREATE    = false
+    ENABLE_NIL_PARSER    = false
+    
+    # allows integers greater than 32-bit if true
+    ENABLE_BIGINT        = false
+
+    # enable marshalling ruby objects which include XMLRPC::Marshallable
+    ENABLE_MARSHALLING   = true 
+
+    # enable multiCall extension by default
+    ENABLE_MULTICALL     = false
+    
+    # enable Introspection extension by default
+    ENABLE_INTROSPECTION = false
+
+  end
+
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/create.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/create.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/create.rb	(revision 18425)
@@ -0,0 +1,290 @@
+#
+# Creates XML-RPC call/response documents
+# 
+# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
+#
+# $Id: create.rb 11820 2007-02-23 03:47:59Z knu $
+#
+
+require "date"
+require "xmlrpc/base64"
+
+module XMLRPC
+
+  module XMLWriter
+
+    class Abstract
+      def ele(name, *children)
+	element(name, nil, *children)
+      end
+
+      def tag(name, txt)
+	element(name, nil, text(txt))
+      end
+    end
+
+
+    class Simple < Abstract
+
+      def document_to_str(doc)
+	doc
+      end
+
+      def document(*params)
+	params.join("")
+      end
+
+      def pi(name, *params)
+	"<?#{name} " + params.join(" ") + " ?>"
+      end
+
+      def element(name, attrs, *children)
+	raise "attributes not yet implemented" unless attrs.nil?
+        if children.empty?
+          "<#{name}/>" 
+        else
+          "<#{name}>" + children.join("") + "</#{name}>"
+        end
+      end
+
+      def text(txt)
+        cleaned = txt.dup
+        cleaned.gsub!(/&/, '&amp;')
+        cleaned.gsub!(/</, '&lt;')
+        cleaned.gsub!(/>/, '&gt;')
+        cleaned
+      end
+
+    end # class Simple
+
+
+    class XMLParser < Abstract
+
+      def initialize
+	require "xmltreebuilder"
+      end
+
+      def document_to_str(doc)
+	doc.to_s
+      end
+
+      def document(*params)
+	XML::SimpleTree::Document.new(*params) 
+      end
+
+      def pi(name, *params)
+	XML::SimpleTree::ProcessingInstruction.new(name, *params)
+      end
+
+      def element(name, attrs, *children)
+	XML::SimpleTree::Element.new(name, attrs, *children)
+      end
+
+      def text(txt)
+	XML::SimpleTree::Text.new(txt)
+      end
+
+    end # class XMLParser
+
+    Classes = [Simple, XMLParser]
+
+    # yields an instance of each installed XML writer
+    def self.each_installed_writer
+      XMLRPC::XMLWriter::Classes.each do |klass|
+        begin
+          yield klass.new
+        rescue LoadError
+        end
+      end
+    end
+
+  end # module XMLWriter
+
+  class Create
+
+    def initialize(xml_writer = nil)
+      @writer = xml_writer || Config::DEFAULT_WRITER.new
+    end
+
+
+    def methodCall(name, *params)
+      name = name.to_s
+
+      if name !~ /[a-zA-Z0-9_.:\/]+/
+	raise ArgumentError, "Wrong XML-RPC method-name"
+      end
+
+      parameter = params.collect do |param|
+	@writer.ele("param", conv2value(param))
+      end
+
+      tree = @writer.document(
+	       @writer.pi("xml", 'version="1.0"'),
+	       @writer.ele("methodCall",   
+		 @writer.tag("methodName", name),
+		 @writer.ele("params", *parameter)    
+	       )
+	     )
+
+      @writer.document_to_str(tree) + "\n"
+    end
+
+
+
+    #
+    # generates a XML-RPC methodResponse document
+    #
+    # if is_ret == false then the params array must
+    # contain only one element, which is a structure
+    # of a fault return-value.
+    # 
+    # if is_ret == true then a normal 
+    # return-value of all the given params is created.
+    #
+    def methodResponse(is_ret, *params)
+
+      if is_ret 
+	resp = params.collect do |param|
+	  @writer.ele("param", conv2value(param))
+	end
+     
+	resp = [@writer.ele("params", *resp)]
+      else
+	if params.size != 1 or params[0] === XMLRPC::FaultException 
+	  raise ArgumentError, "no valid fault-structure given"
+	end
+	resp = @writer.ele("fault", conv2value(params[0].to_h))
+      end
+
+	
+      tree = @writer.document(
+	       @writer.pi("xml", 'version="1.0"'),
+	       @writer.ele("methodResponse", resp) 
+	     )
+
+      @writer.document_to_str(tree) + "\n"
+    end
+
+
+
+    #####################################
+    private
+    #####################################
+
+    #
+    # converts a Ruby object into
+    # a XML-RPC <value> tag
+    #
+    def conv2value(param)
+
+	val = case param
+	when Fixnum 
+	  @writer.tag("i4", param.to_s)
+
+	when Bignum
+          if Config::ENABLE_BIGINT
+            @writer.tag("i4", param.to_s)
+          else
+            if param >= -(2**31) and param <= (2**31-1)
+              @writer.tag("i4", param.to_s)
+            else
+              raise "Bignum is too big! Must be signed 32-bit integer!"
+            end
+          end
+	when TrueClass, FalseClass
+	  @writer.tag("boolean", param ? "1" : "0")
+
+	when String 
+	  @writer.tag("string", param)
+
+	when Symbol 
+	  @writer.tag("string", param.to_s)
+
+        when NilClass
+          if Config::ENABLE_NIL_CREATE
+            @writer.ele("nil")
+          else
+            raise "Wrong type NilClass. Not allowed!"
+          end
+
+	when Float
+	  @writer.tag("double", param.to_s)
+
+	when Struct
+	  h = param.members.collect do |key| 
+	    value = param[key]
+	    @writer.ele("member", 
+	      @writer.tag("name", key.to_s),
+	      conv2value(value) 
+	    )
+	  end
+
+	  @writer.ele("struct", *h) 
+
+	when Hash
+	  # TODO: can a Hash be empty?
+	  
+	  h = param.collect do |key, value|
+	    @writer.ele("member", 
+	      @writer.tag("name", key.to_s),
+	      conv2value(value) 
+	    )
+	  end
+
+	  @writer.ele("struct", *h) 
+
+	when Array
+	  # TODO: can an Array be empty?
+	  a = param.collect {|v| conv2value(v) }
+	  
+	  @writer.ele("array", 
+	    @writer.ele("data", *a)
+	  )
+
+	when Time, Date, ::DateTime
+	  @writer.tag("dateTime.iso8601", param.strftime("%Y%m%dT%H:%M:%S"))  
+
+	when XMLRPC::DateTime
+	  @writer.tag("dateTime.iso8601", 
+	    format("%.4d%02d%02dT%02d:%02d:%02d", *param.to_a))
+   
+	when XMLRPC::Base64
+	  @writer.tag("base64", param.encoded) 
+
+	else 
+          if Config::ENABLE_MARSHALLING and param.class.included_modules.include? XMLRPC::Marshallable
+            # convert Ruby object into Hash
+            ret = {"___class___" => param.class.name}
+            param.instance_variables.each {|v| 
+              name = v[1..-1]
+              val = param.instance_variable_get(v)
+
+              if val.nil?
+                ret[name] = val if Config::ENABLE_NIL_CREATE
+              else
+                ret[name] = val
+              end
+            }
+            return conv2value(ret)
+          else 
+            ok, pa = wrong_type(param)
+            if ok
+              return conv2value(pa)
+            else 
+              raise "Wrong type!"
+            end
+          end
+	end
+	 
+	@writer.ele("value", val)
+    end
+
+    def wrong_type(value)
+      false
+    end
+
+    
+  end # class Create
+
+end # module XMLRPC
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/datetime.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/datetime.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/datetime.rb	(revision 18425)
@@ -0,0 +1,142 @@
+=begin
+= xmlrpc/datetime.rb
+Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
+
+Released under the same term of license as Ruby.
+
+= Classes
+* ((<XMLRPC::DateTime>))
+
+= XMLRPC::DateTime
+== Description
+This class is important to handle XMLRPC (('dateTime.iso8601')) values,
+correcly, because normal UNIX-dates (class (({Date}))) only handle dates 
+from year 1970 on, and class (({Time})) handles dates without the time
+component. (({XMLRPC::DateTime})) is able to store a XMLRPC 
+(('dateTime.iso8601')) value correctly.
+
+== Class Methods
+--- XMLRPC::DateTime.new( year, month, day, hour, min, sec )
+    Creates a new (({XMLRPC::DateTime})) instance with the
+    parameters ((|year|)), ((|month|)), ((|day|)) as date and 
+    ((|hour|)), ((|min|)), ((|sec|)) as time.
+    Raises (({ArgumentError})) if a parameter is out of range, or ((|year|)) is not
+    of type (({Integer})).
+    
+== Instance Methods
+--- XMLRPC::DateTime#year
+--- XMLRPC::DateTime#month
+--- XMLRPC::DateTime#day
+--- XMLRPC::DateTime#hour
+--- XMLRPC::DateTime#min
+--- XMLRPC::DateTime#sec
+    Return the value of the specified date/time component.
+
+--- XMLRPC::DateTime#mon
+    Alias for ((<XMLRPC::DateTime#month>)).
+
+--- XMLRPC::DateTime#year=( value )
+--- XMLRPC::DateTime#month=( value )
+--- XMLRPC::DateTime#day=( value )
+--- XMLRPC::DateTime#hour=( value )
+--- XMLRPC::DateTime#min=( value )
+--- XMLRPC::DateTime#sec=( value )
+    Set ((|value|)) as the new date/time component.
+    Raises (({ArgumentError})) if ((|value|)) is out of range, or in the case
+    of (({XMLRPC::DateTime#year=})) if ((|value|)) is not of type (({Integer})).
+
+--- XMLRPC::DateTime#mon=( value )
+    Alias for ((<XMLRPC::DateTime#month=>)).
+
+--- XMLRPC::DateTime#to_time
+    Return a (({Time})) object of the date/time which (({self})) represents.
+    If the (('year')) is below 1970, this method returns (({nil})), 
+    because (({Time})) cannot handle years below 1970.
+    The used timezone is GMT.
+
+--- XMLRPC::DateTime#to_date
+    Return a (({Date})) object of the date which (({self})) represents.
+    The (({Date})) object do ((*not*)) contain the time component (only date).
+
+--- XMLRPC::DateTime#to_a
+    Returns all date/time components in an array.
+    Returns (({[year, month, day, hour, min, sec]})).
+=end
+
+require "date"
+
+module XMLRPC
+
+class DateTime
+  
+  attr_reader :year, :month, :day, :hour, :min, :sec
+
+  def year= (value)
+    raise ArgumentError, "date/time out of range" unless value.is_a? Integer
+    @year = value
+  end
+
+  def month= (value)
+    raise ArgumentError, "date/time out of range" unless (1..12).include? value
+    @month = value
+  end
+
+  def day= (value)
+    raise ArgumentError, "date/time out of range" unless (1..31).include? value
+    @day = value
+  end
+
+  def hour= (value)
+    raise ArgumentError, "date/time out of range" unless (0..24).include? value
+    @hour = value
+  end
+
+  def min= (value)
+    raise ArgumentError, "date/time out of range" unless (0..59).include? value
+    @min = value
+  end
+
+  def sec= (value)
+    raise ArgumentError, "date/time out of range" unless (0..59).include? value
+    @sec = value
+  end
+
+  alias mon  month
+  alias mon= month= 
+ 
+
+  def initialize(year, month, day, hour, min, sec)
+    self.year, self.month, self.day = year, month, day
+    self.hour, self.min, self.sec   = hour, min, sec
+  end
+ 
+  def to_time
+    if @year >= 1970
+      Time.gm(*to_a)
+    else
+      nil
+    end
+  end
+
+  def to_date
+    Date.new(*to_a[0,3])
+  end
+
+  def to_a
+    [@year, @month, @day, @hour, @min, @sec]
+  end
+
+  def ==(o)
+    Array(self) == Array(o)
+  end
+
+end
+
+
+end # module XMLRPC
+
+
+=begin
+= History
+    $Id: datetime.rb 11708 2007-02-12 23:01:19Z shyouhei $
+=end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/httpserver.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/httpserver.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/httpserver.rb	(revision 18425)
@@ -0,0 +1,178 @@
+#
+# Implements a simple HTTP-server by using John W. Small's (jsmall@laser.net) 
+# ruby-generic-server.
+# 
+# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
+#
+# $Id: httpserver.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+
+
+require "gserver"
+
+class HttpServer < GServer
+
+  ##
+  # handle_obj specifies the object, that receives calls to request_handler
+  # and ip_auth_handler 
+  def initialize(handle_obj, port = 8080, host = DEFAULT_HOST, maxConnections = 4, 
+                 stdlog = $stdout, audit = true, debug = true)
+    @handler = handle_obj
+    super(port, host, maxConnections, stdlog, audit, debug)
+  end
+
+private
+
+  # Constants -----------------------------------------------
+  
+  CRLF        = "\r\n"
+  HTTP_PROTO  = "HTTP/1.0"
+  SERVER_NAME = "HttpServer (Ruby #{RUBY_VERSION})"
+
+  DEFAULT_HEADER = {
+    "Server" => SERVER_NAME
+  }
+
+  ##
+  # Mapping of status code and error message
+  #
+  StatusCodeMapping = {
+    200 => "OK",
+    400 => "Bad Request",
+    403 => "Forbidden",
+    405 => "Method Not Allowed",
+    411 => "Length Required",
+    500 => "Internal Server Error"
+  }
+
+  # Classes -------------------------------------------------
+  
+  class Request
+    attr_reader :data, :header, :method, :path, :proto
+    
+    def initialize(data, method=nil, path=nil, proto=nil)
+      @header, @data = Table.new, data
+      @method, @path, @proto = method, path, proto
+    end
+    
+    def content_length
+      len = @header['Content-Length']
+      return nil if len.nil?
+      return len.to_i 
+    end
+    
+  end
+  
+  class Response
+    attr_reader   :header
+    attr_accessor :body, :status, :status_message
+    
+    def initialize(status=200)
+      @status = status
+      @status_message = nil
+      @header = Table.new
+    end
+  end
+
+
+  ##
+  # a case-insensitive Hash class for HTTP header
+  #
+  class Table
+    include Enumerable
+
+    def initialize(hash={})
+      @hash = hash 
+      update(hash)
+    end
+
+    def [](key)
+      @hash[key.to_s.capitalize]
+    end
+
+    def []=(key, value)
+      @hash[key.to_s.capitalize] = value
+    end
+
+    def update(hash)
+      hash.each {|k,v| self[k] = v}
+      self
+    end
+
+    def each
+      @hash.each {|k,v| yield k.capitalize, v }
+    end
+
+    def writeTo(port)
+      each { |k,v| port << "#{k}: #{v}" << CRLF }
+    end
+  end # class Table
+
+
+  # Helper Methods ------------------------------------------
+
+  def http_header(header=nil)
+    new_header = Table.new(DEFAULT_HEADER)
+    new_header.update(header) unless header.nil? 
+
+    new_header["Connection"] = "close"
+    new_header["Date"]       = http_date(Time.now)
+
+    new_header
+  end
+
+  def http_date( aTime )
+    aTime.gmtime.strftime( "%a, %d %b %Y %H:%M:%S GMT" )
+  end
+
+  def http_resp(status_code, status_message=nil, header=nil, body=nil)
+    status_message ||= StatusCodeMapping[status_code]
+    
+    str = ""
+    str << "#{HTTP_PROTO} #{status_code} #{status_message}" << CRLF
+    http_header(header).writeTo(str)
+    str << CRLF
+    str << body unless body.nil?
+    str
+  end
+
+  # Main Serve Loop -----------------------------------------
+  
+  def serve(io)  
+    # perform IP authentification
+    unless @handler.ip_auth_handler(io)
+      io << http_resp(403, "Forbidden")
+      return
+    end
+
+    # parse first line
+    if io.gets =~ /^(\S+)\s+(\S+)\s+(\S+)/
+      request = Request.new(io, $1, $2, $3)
+    else
+      io << http_resp(400, "Bad Request") 
+      return
+    end
+     
+    # parse HTTP headers
+    while (line=io.gets) !~ /^(\n|\r)/
+      if line =~ /^([\w-]+):\s*(.*)$/
+	request.header[$1] = $2.strip
+      end
+    end
+
+    io.binmode    
+    response = Response.new
+
+    # execute request handler
+    @handler.request_handler(request, response)
+   
+    # write response back to the client
+    io << http_resp(response.status, response.status_message,
+                    response.header, response.body) 
+
+  rescue Exception => e
+    io << http_resp(500, "Internal Server Error")
+  end
+
+end # class HttpServer
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/marshal.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/marshal.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/marshal.rb	(revision 18425)
@@ -0,0 +1,76 @@
+#
+# Marshalling of XML-RPC methodCall and methodResponse
+# 
+# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
+#
+# $Id: marshal.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+
+require "xmlrpc/parser"
+require "xmlrpc/create"
+require "xmlrpc/config"
+require "xmlrpc/utils"
+
+module XMLRPC
+
+  class Marshal
+    include ParserWriterChooseMixin
+
+    # class methods -------------------------------
+   
+    class << self
+
+      def dump_call( methodName, *params )
+        new.dump_call( methodName, *params )
+      end
+
+      def dump_response( param )
+        new.dump_response( param )
+      end
+
+      def load_call( stringOrReadable )
+        new.load_call( stringOrReadable )
+      end
+
+      def load_response( stringOrReadable )
+        new.load_response( stringOrReadable )
+      end
+
+      alias dump dump_response
+      alias load load_response
+
+    end # class self
+
+    # instance methods ----------------------------
+
+    def initialize( parser = nil, writer = nil )
+      set_parser( parser )
+      set_writer( writer )
+    end
+
+    def dump_call( methodName, *params )
+      create.methodCall( methodName, *params )
+    end
+
+    def dump_response( param ) 
+      create.methodResponse( ! param.kind_of?( XMLRPC::FaultException ) , param )
+    end
+
+    ##
+    # returns [ methodname, params ]
+    #
+    def load_call( stringOrReadable )
+      parser.parseMethodCall( stringOrReadable )
+    end
+
+    ##
+    # returns paramOrFault
+    #
+    def load_response( stringOrReadable )
+      parser.parseMethodResponse( stringOrReadable )[1]
+    end
+
+  end # class Marshal
+
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/parser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/parser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/parser.rb	(revision 18425)
@@ -0,0 +1,813 @@
+#
+# Parser for XML-RPC call and response
+# 
+# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
+#
+# $Id: parser.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+
+
+require "date"
+require "xmlrpc/base64"
+require "xmlrpc/datetime"
+
+
+# add some methods to NQXML::Node
+module NQXML
+  class Node
+
+    def removeChild(node)
+      @children.delete(node)
+    end
+    def childNodes
+      @children
+    end
+    def hasChildNodes
+      not @children.empty?
+    end
+    def [] (index)
+      @children[index]
+    end
+
+    def nodeType
+      if @entity.instance_of? NQXML::Text then :TEXT
+      elsif @entity.instance_of? NQXML::Comment then :COMMENT
+      #elsif @entity.instance_of? NQXML::Element then :ELEMENT
+      elsif @entity.instance_of? NQXML::Tag then :ELEMENT
+      else :ELSE
+      end
+    end
+
+    def nodeValue
+      #TODO: error when wrong Entity-type
+      @entity.text
+    end
+    def nodeName
+      #TODO: error when wrong Entity-type
+      @entity.name
+    end
+  end # class Node
+end # module NQXML
+
+module XMLRPC
+
+  class FaultException < StandardError
+    attr_reader :faultCode, :faultString
+
+    alias message faultString
+
+    def initialize(faultCode, faultString)
+      @faultCode   = faultCode
+      @faultString = faultString
+    end
+    
+    # returns a hash
+    def to_h
+      {"faultCode" => @faultCode, "faultString" => @faultString}
+    end
+  end
+
+  module Convert
+    def self.int(str)
+      str.to_i
+    end
+
+    def self.boolean(str)
+      case str
+      when "0" then false
+      when "1" then true
+      else
+        raise "RPC-value of type boolean is wrong" 
+      end
+    end
+
+    def self.double(str)
+      str.to_f
+    end
+
+    def self.dateTime(str)
+      case str
+      when /^(-?\d\d\d\d)-?(\d\d)-?(\d\d)T(\d\d):(\d\d):(\d\d)(?:Z|([+-])(\d\d):?(\d\d))?$/
+        a = [$1, $2, $3, $4, $5, $6].collect{|i| i.to_i}
+        if $7
+          ofs = $8.to_i*3600 + $9.to_i*60
+          ofs = -ofs if $7=='+'
+          utc = Time.utc(a.reverse) + ofs
+          a = [ utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec ]
+        end
+        XMLRPC::DateTime.new(*a)
+      when /^(-?\d\d)-?(\d\d)-?(\d\d)T(\d\d):(\d\d):(\d\d)(Z|([+-]\d\d):(\d\d))?$/
+        a = [$1, $2, $3, $4, $5, $6].collect{|i| i.to_i}
+        if a[0] < 70
+          a[0] += 2000
+        else
+          a[0] += 1900
+        end
+        if $7
+          ofs = $8.to_i*3600 + $9.to_i*60
+          ofs = -ofs if $7=='+'
+          utc = Time.utc(a.reverse) + ofs
+          a = [ utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec ]
+        end
+        XMLRPC::DateTime.new(*a)
+      else
+        raise "wrong dateTime.iso8601 format " + str
+      end
+    end
+
+    def self.base64(str)
+      XMLRPC::Base64.decode(str)
+    end
+
+    def self.struct(hash)
+      # convert to marhalled object
+      klass = hash["___class___"]
+      if klass.nil? or Config::ENABLE_MARSHALLING == false 
+        hash
+      else
+        begin
+          mod = Module
+          klass.split("::").each {|const| mod = mod.const_get(const.strip)}
+
+          obj = mod.allocate
+          
+          hash.delete "___class___"
+          hash.each {|key, value| 
+            obj.instance_variable_set("@#{ key }", value) if key =~ /^([\w_][\w_0-9]*)$/
+          }
+          obj
+        rescue
+          hash
+        end
+      end
+    end
+
+    def self.fault(hash)
+      if hash.kind_of? Hash and hash.size == 2 and 
+        hash.has_key? "faultCode" and hash.has_key? "faultString" and 
+        hash["faultCode"].kind_of? Integer and hash["faultString"].kind_of? String
+
+        XMLRPC::FaultException.new(hash["faultCode"], hash["faultString"]) 
+      else
+        raise "wrong fault-structure: #{hash.inspect}"
+      end
+    end
+
+  end # module Convert
+
+  module XMLParser
+
+    class AbstractTreeParser
+
+      def parseMethodResponse(str)
+	methodResponse_document(createCleanedTree(str))
+      end
+
+      def parseMethodCall(str)
+	methodCall_document(createCleanedTree(str))
+      end
+
+      private
+
+      #
+      # remove all whitespaces but in the tags i4, int, boolean....
+      # and all comments
+      #
+      def removeWhitespacesAndComments(node)
+	remove = []
+	childs = node.childNodes.to_a
+	childs.each do |nd|
+	  case _nodeType(nd)
+	  when :TEXT
+            # TODO: add nil?
+            unless %w(i4 int boolean string double dateTime.iso8601 base64).include? node.nodeName
+
+               if node.nodeName == "value" 
+                 if not node.childNodes.to_a.detect {|n| _nodeType(n) == :ELEMENT}.nil?
+                   remove << nd if nd.nodeValue.strip == "" 
+                 end
+               else
+                 remove << nd if nd.nodeValue.strip == ""
+               end
+	    end
+	  when :COMMENT
+	    remove << nd
+	  else
+	    removeWhitespacesAndComments(nd)
+	  end 
+	end
+
+	remove.each { |i| node.removeChild(i) }
+      end
+
+
+      def nodeMustBe(node, name)
+	cmp = case name
+	when Array 
+	  name.include?(node.nodeName)
+	when String
+	  name == node.nodeName
+	else
+	  raise "error"
+	end  
+
+	if not cmp then
+	  raise "wrong xml-rpc (name)"
+	end
+
+	node
+      end
+
+      #
+      # returns, when successfully the only child-node
+      #
+      def hasOnlyOneChild(node, name=nil)
+	if node.childNodes.to_a.size != 1
+	  raise "wrong xml-rpc (size)"
+	end
+	if name != nil then
+	  nodeMustBe(node.firstChild, name)
+	end
+      end
+
+
+      def assert(b)
+	if not b then
+	  raise "assert-fail" 
+	end
+      end
+
+      # the node `node` has empty string or string
+      def text_zero_one(node)
+	nodes = node.childNodes.to_a.size
+
+	if nodes == 1
+	  text(node.firstChild)
+	elsif nodes == 0
+	  ""
+	else
+	  raise "wrong xml-rpc (size)"
+	end
+      end
+     
+
+      def integer(node)
+	#TODO: check string for float because to_i returnsa
+	#      0 when wrong string
+	 nodeMustBe(node, %w(i4 int))    
+	hasOnlyOneChild(node)
+	
+	Convert.int(text(node.firstChild))
+      end
+
+      def boolean(node)
+	nodeMustBe(node, "boolean")    
+	hasOnlyOneChild(node)
+	
+        Convert.boolean(text(node.firstChild))
+      end
+
+      def v_nil(node)
+        nodeMustBe(node, "nil")
+	assert( node.childNodes.to_a.size == 0 )
+        nil
+      end
+
+      def string(node)
+	nodeMustBe(node, "string")    
+	text_zero_one(node)
+      end
+
+      def double(node)
+	#TODO: check string for float because to_f returnsa
+	#      0.0 when wrong string
+	nodeMustBe(node, "double")    
+	hasOnlyOneChild(node)
+	
+	Convert.double(text(node.firstChild))
+      end
+
+      def dateTime(node)
+	nodeMustBe(node, "dateTime.iso8601")
+	hasOnlyOneChild(node)
+	
+        Convert.dateTime( text(node.firstChild) )
+      end
+
+      def base64(node)
+	nodeMustBe(node, "base64")
+	#hasOnlyOneChild(node)
+	 
+        Convert.base64(text_zero_one(node))
+      end
+
+      def member(node)
+	nodeMustBe(node, "member")
+	assert( node.childNodes.to_a.size == 2 ) 
+
+	[ name(node[0]), value(node[1]) ]
+      end
+
+      def name(node)
+	nodeMustBe(node, "name")
+	#hasOnlyOneChild(node)
+	text_zero_one(node) 
+      end
+
+      def array(node)
+	nodeMustBe(node, "array")
+	hasOnlyOneChild(node, "data") 
+	data(node.firstChild)  
+      end
+
+      def data(node)
+	nodeMustBe(node, "data")
+
+	node.childNodes.to_a.collect do |val|
+	  value(val)
+	end 
+      end
+
+      def param(node)
+	nodeMustBe(node, "param")
+	hasOnlyOneChild(node, "value")
+	value(node.firstChild) 
+      end
+ 
+      def methodResponse(node)
+	nodeMustBe(node, "methodResponse")
+	hasOnlyOneChild(node, %w(params fault))
+	child = node.firstChild
+
+	case child.nodeName
+	when "params"
+	  [ true, params(child,false) ] 
+	when "fault"
+	  [ false, fault(child) ]
+	else
+	  raise "unexpected error"
+	end
+
+      end
+
+      def methodName(node)
+	nodeMustBe(node, "methodName")
+	hasOnlyOneChild(node)
+	text(node.firstChild) 
+      end
+
+      def params(node, call=true)
+	nodeMustBe(node, "params")
+
+	if call 
+	  node.childNodes.to_a.collect do |n|
+	    param(n)
+	  end
+	else # response (only one param)
+	  hasOnlyOneChild(node)
+	  param(node.firstChild)
+	end
+      end
+
+      def fault(node)
+	nodeMustBe(node, "fault")
+	hasOnlyOneChild(node, "value")
+	f = value(node.firstChild) 
+        Convert.fault(f)
+      end
+
+
+
+      # _nodeType is defined in the subclass
+      def text(node)
+	assert( _nodeType(node) == :TEXT )
+	assert( node.hasChildNodes == false )
+	assert( node.nodeValue != nil )
+
+	node.nodeValue.to_s
+      end
+
+      def struct(node)
+	nodeMustBe(node, "struct")    
+
+	hash = {}
+	node.childNodes.to_a.each do |me|
+	  n, v = member(me)  
+	  hash[n] = v
+	end 
+
+        Convert.struct(hash)
+     end
+
+
+      def value(node)
+	nodeMustBe(node, "value")
+	nodes = node.childNodes.to_a.size
+        if nodes == 0 
+          return ""
+        elsif nodes > 1 
+	  raise "wrong xml-rpc (size)"
+        end
+
+	child = node.firstChild
+
+	case _nodeType(child)
+	when :TEXT
+          text_zero_one(node)
+	when :ELEMENT
+	  case child.nodeName
+	  when "i4", "int"        then integer(child)
+	  when "boolean"          then boolean(child)
+	  when "string"           then string(child)
+	  when "double"           then double(child)
+	  when "dateTime.iso8601" then dateTime(child)
+	  when "base64"           then base64(child)
+	  when "struct"           then struct(child)
+	  when "array"            then array(child) 
+          when "nil"              
+            if Config::ENABLE_NIL_PARSER
+              v_nil(child)
+            else
+              raise "wrong/unknown XML-RPC type 'nil'"
+            end
+	  else 
+	    raise "wrong/unknown XML-RPC type"
+	  end
+	else
+	  raise "wrong type of node"
+	end
+
+      end
+
+      def methodCall(node)
+	nodeMustBe(node, "methodCall")
+	assert( (1..2).include?( node.childNodes.to_a.size ) ) 
+	name = methodName(node[0])
+
+	if node.childNodes.to_a.size == 2 then
+	  pa = params(node[1])
+	else # no parameters given
+	  pa = []
+	end
+	[name, pa]
+      end
+
+    end # module TreeParserMixin
+
+    class AbstractStreamParser
+      def parseMethodResponse(str)
+        parser = @parser_class.new
+        parser.parse(str)
+        raise "No valid method response!" if parser.method_name != nil
+        if parser.fault != nil
+          # is a fault structure
+          [false, parser.fault] 
+        else
+          # is a normal return value
+          raise "Missing return value!" if parser.params.size == 0
+          raise "Too many return values. Only one allowed!" if parser.params.size > 1
+          [true, parser.params[0]]
+        end
+      end
+
+      def parseMethodCall(str)
+        parser = @parser_class.new
+        parser.parse(str)
+        raise "No valid method call - missing method name!" if parser.method_name.nil?
+        [parser.method_name, parser.params]
+      end
+    end
+
+    module StreamParserMixin
+      attr_reader :params
+      attr_reader :method_name
+      attr_reader :fault
+
+      def initialize(*a)
+        super(*a)
+        @params = []
+        @values = []
+        @val_stack = []
+
+        @names = []
+        @name = []
+
+        @structs = []
+        @struct = {}
+
+        @method_name = nil
+        @fault = nil
+
+        @data = nil
+      end
+
+      def startElement(name, attrs=[])
+        @data = nil
+        case name
+        when "value"
+          @value = nil
+        when "nil"
+          raise "wrong/unknown XML-RPC type 'nil'" unless Config::ENABLE_NIL_PARSER
+          @value = :nil 
+        when "array"
+          @val_stack << @values
+          @values = []
+        when "struct"
+          @names << @name
+          @name = []
+
+          @structs << @struct
+          @struct = {} 
+        end
+      end
+
+      def endElement(name)
+        @data ||= ""
+        case name
+        when "string"
+          @value = @data
+        when "i4", "int"
+          @value = Convert.int(@data)
+        when "boolean"
+          @value = Convert.boolean(@data)
+        when "double"
+          @value = Convert.double(@data)
+        when "dateTime.iso8601"
+          @value = Convert.dateTime(@data)
+        when "base64"
+          @value = Convert.base64(@data)
+        when "value"
+          @value = @data if @value.nil?
+          @values << (@value == :nil ? nil : @value) 
+        when "array"
+          @value = @values
+          @values = @val_stack.pop
+        when "struct"
+          @value = Convert.struct(@struct)
+
+          @name = @names.pop
+          @struct = @structs.pop
+        when "name"
+          @name[0] = @data 
+        when "member"
+          @struct[@name[0]] = @values.pop 
+
+        when "param"
+          @params << @values[0]
+          @values = []
+
+        when "fault"
+          @fault = Convert.fault(@values[0])
+
+        when "methodName"
+          @method_name = @data 
+        end
+
+        @data = nil
+      end
+
+      def character(data)
+        if @data
+          @data << data
+        else
+          @data = data
+        end
+      end
+
+    end # module StreamParserMixin
+
+    # ---------------------------------------------------------------------------
+    class XMLStreamParser < AbstractStreamParser
+      def initialize
+        require "xmlparser"
+        @parser_class = Class.new(::XMLParser) {
+          include StreamParserMixin
+        }
+      end
+    end # class XMLStreamParser
+    # ---------------------------------------------------------------------------
+    class NQXMLStreamParser < AbstractStreamParser
+      def initialize
+        require "nqxml/streamingparser"
+        @parser_class = XMLRPCParser
+      end
+
+      class XMLRPCParser 
+        include StreamParserMixin
+
+        def parse(str)
+          parser = NQXML::StreamingParser.new(str)
+          parser.each do |ele|
+            case ele
+            when NQXML::Text
+              @data = ele.text
+              #character(ele.text)
+            when NQXML::Tag
+              if ele.isTagEnd
+                endElement(ele.name)
+              else
+                startElement(ele.name, ele.attrs)
+              end
+            end
+          end # do
+        end # method parse
+      end # class XMLRPCParser
+
+    end # class NQXMLStreamParser
+    # ---------------------------------------------------------------------------
+    class XMLTreeParser < AbstractTreeParser
+
+      def initialize
+        require "xmltreebuilder"
+
+        # The new XMLParser library (0.6.2+) uses a slightly different DOM implementation. 
+        # The following code removes the differences between both versions.
+        if defined? XML::DOM::Builder 
+          return if defined? XML::DOM::Node::DOCUMENT # code below has been already executed
+          klass = XML::DOM::Node
+          klass.const_set("DOCUMENT", klass::DOCUMENT_NODE)
+          klass.const_set("TEXT", klass::TEXT_NODE)
+          klass.const_set("COMMENT", klass::COMMENT_NODE)
+          klass.const_set("ELEMENT", klass::ELEMENT_NODE)
+        end
+      end
+
+      private
+
+      def _nodeType(node)
+	tp = node.nodeType
+	if tp == XML::SimpleTree::Node::TEXT then :TEXT
+	elsif tp == XML::SimpleTree::Node::COMMENT then :COMMENT 
+	elsif tp == XML::SimpleTree::Node::ELEMENT then :ELEMENT 
+	else :ELSE
+	end
+      end
+
+
+      def methodResponse_document(node)
+	assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT )
+	hasOnlyOneChild(node, "methodResponse")
+	
+	methodResponse(node.firstChild)
+      end
+
+      def methodCall_document(node)
+	assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT )
+	hasOnlyOneChild(node, "methodCall")
+	
+	methodCall(node.firstChild)
+      end
+
+      def createCleanedTree(str)
+	doc = XML::SimpleTreeBuilder.new.parse(str)
+	doc.documentElement.normalize
+	removeWhitespacesAndComments(doc)
+	doc
+      end
+
+    end # class XMLParser
+    # ---------------------------------------------------------------------------
+    class NQXMLTreeParser < AbstractTreeParser
+
+      def initialize
+        require "nqxml/treeparser"
+      end
+
+      private
+
+      def _nodeType(node)
+	node.nodeType
+      end
+
+      def methodResponse_document(node)
+	methodResponse(node)
+      end
+
+      def methodCall_document(node)
+	methodCall(node)
+      end
+
+      def createCleanedTree(str)
+        doc = ::NQXML::TreeParser.new(str).document.rootNode 
+	removeWhitespacesAndComments(doc)
+	doc
+      end
+
+    end # class NQXMLTreeParser
+    # ---------------------------------------------------------------------------
+    class REXMLStreamParser < AbstractStreamParser
+      def initialize
+        require "rexml/document"
+        @parser_class = StreamListener
+      end
+
+      class StreamListener 
+        include StreamParserMixin
+
+        alias :tag_start :startElement
+        alias :tag_end :endElement
+        alias :text :character
+        alias :cdata :character
+
+        def method_missing(*a)
+          # ignore
+        end
+
+        def parse(str)
+          parser = REXML::Document.parse_stream(str, self)
+       end
+      end 
+
+    end
+    # ---------------------------------------------------------------------------
+    class XMLScanStreamParser < AbstractStreamParser
+      def initialize
+        require "xmlscan/parser"
+        @parser_class = XMLScanParser
+      end
+
+      class XMLScanParser
+        include StreamParserMixin
+
+        Entities = {
+          "lt"   => "<",
+          "gt"   => ">",
+          "amp"  => "&",
+          "quot" => '"',
+          "apos" => "'"
+        }
+
+        def parse(str)
+          parser  = XMLScan::XMLParser.new(self)
+          parser.parse(str)
+        end
+
+        alias :on_stag :startElement
+ 	alias :on_etag :endElement
+
+        def on_stag_end(name); end
+
+        def on_stag_end_empty(name)
+          startElement(name)
+          endElement(name)
+        end
+       
+        def on_chardata(str)
+          character(str)
+        end
+
+        def on_cdata(str)
+          character(str)
+        end
+
+        def on_entityref(ent)
+          str = Entities[ent]
+          if str
+            character(str)
+          else
+            raise "unknown entity"
+          end
+        end
+
+        def on_charref(code)
+          character(code.chr)
+        end
+
+        def on_charref_hex(code)
+          character(code.chr)
+        end
+
+        def method_missing(*a)
+        end
+
+        # TODO: call/implement?
+        # valid_name?
+        # valid_chardata?
+        # valid_char?
+        # parse_error  
+
+      end
+    end
+    # ---------------------------------------------------------------------------
+    XMLParser   = XMLTreeParser
+    NQXMLParser = NQXMLTreeParser
+
+    Classes = [XMLStreamParser, XMLTreeParser, 
+               NQXMLStreamParser, NQXMLTreeParser, 
+               REXMLStreamParser, XMLScanStreamParser]
+
+    # yields an instance of each installed parser
+    def self.each_installed_parser
+      XMLRPC::XMLParser::Classes.each do |klass|
+        begin
+          yield klass.new
+        rescue LoadError
+        end
+      end
+    end
+
+  end # module XMLParser
+
+
+end # module XMLRPC
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/server.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/server.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/server.rb	(revision 18425)
@@ -0,0 +1,780 @@
+=begin
+= xmlrpc/server.rb
+Copyright (C) 2001, 2002, 2003, 2005 by Michael Neumann (mneumann@ntecs.de)
+
+Released under the same term of license as Ruby.
+
+= Classes
+* ((<XMLRPC::BasicServer>))
+* ((<XMLRPC::CGIServer>))
+* ((<XMLRPC::ModRubyServer>))
+* ((<XMLRPC::Server>))
+* ((<XMLRPC::WEBrickServlet>))
+
+= XMLRPC::BasicServer
+== Description
+Is the base class for all XML-RPC server-types (CGI, standalone).
+You can add handler and set a default handler. 
+Do not use this server, as this is/should be an abstract class.
+
+=== How the method to call is found
+The arity (number of accepted arguments) of a handler (method or (({Proc})) object) is 
+compared to the given arguments submitted by the client for a RPC ((-Remote Procedure Call-)). 
+A handler is only called if it accepts the number of arguments, otherwise the search 
+for another handler will go on. When at the end no handler was found, 
+the ((<default_handler|XMLRPC::BasicServer#set_default_handler>)) will be called.
+With this technique it is possible to do overloading by number of parameters, but
+only for (({Proc})) handler, because you cannot define two methods of the same name in
+the same class. 
+
+
+== Class Methods
+--- XMLRPC::BasicServer.new( class_delim="." )
+    Creates a new (({XMLRPC::BasicServer})) instance, which should not be 
+    done, because (({XMLRPC::BasicServer})) is an abstract class. This
+    method should be called from a subclass indirectly by a (({super})) call
+    in the method (({initialize})). The paramter ((|class_delim|)) is used
+    in ((<add_handler|XMLRPC::BasicServer#add_handler>)) when an object is
+    added as handler, to delimit the object-prefix and the method-name.
+
+== Instance Methods
+--- XMLRPC::BasicServer#add_handler( name, signature=nil, help=nil ) { aBlock }
+    Adds ((|aBlock|)) to the list of handlers, with ((|name|)) as the name of the method.
+    Parameters ((|signature|)) and ((|help|)) are used by the Introspection method if specified, 
+    where ((|signature|)) is either an Array containing strings each representing a type of it's 
+    signature (the first is the return value) or an Array of Arrays if the method has multiple 
+    signatures. Value type-names are "int, boolean, double, string, dateTime.iso8601, base64, array, struct".
+
+    Parameter ((|help|)) is a String with informations about how to call this method etc.
+
+    A handler method or code-block can return the types listed at
+    ((<XMLRPC::Client#call|URL:client.html#index:0>)). 
+    When a method fails, it can tell it the client by throwing an 
+    (({XMLRPC::FaultException})) like in this example:
+        s.add_handler("michael.div") do |a,b|
+          if b == 0
+            raise XMLRPC::FaultException.new(1, "division by zero")
+          else
+            a / b 
+          end
+        end 
+    The client gets in the case of (({b==0})) an object back of type
+    (({XMLRPC::FaultException})) that has a ((|faultCode|)) and ((|faultString|))
+    field.
+
+--- XMLRPC::BasicServer#add_handler( prefix, obj )
+    This is the second form of ((<add_handler|XMLRPC::BasicServer#add_handler>)).
+    To add an object write:
+        server.add_handler("michael", MyHandlerClass.new)
+    All public methods of (({MyHandlerClass})) are accessible to
+    the XML-RPC clients by (('michael."name of method"')). This is 
+    where the ((|class_delim|)) in ((<new|XMLRPC::BasicServer.new>)) 
+    has it's role, a XML-RPC method-name is defined by 
+    ((|prefix|)) + ((|class_delim|)) + (('"name of method"')). 
+
+--- XMLRPC::BasicServer#add_handler( interface, obj )
+    This is the third form of ((<add_handler|XMLRPC::BasicServer#add_handler>)).
+
+    Use (({XMLRPC::interface})) to generate an ServiceInterface object, which
+    represents an interface (with signature and help text) for a handler class.
+
+    Parameter ((|interface|)) must be of type (({XMLRPC::ServiceInterface})).
+    Adds all methods of ((|obj|)) which are defined in ((|interface|)) to the
+    server.
+
+    This is the recommended way of adding services to a server!
+
+
+--- XMLRPC::BasicServer#get_default_handler
+    Returns the default-handler, which is called when no handler for
+    a method-name is found.
+    It is a (({Proc})) object or (({nil})).
+
+--- XMLRPC::BasicServer#set_default_handler ( &handler )
+    Sets ((|handler|)) as the default-handler, which is called when 
+    no handler for a method-name is found. ((|handler|)) is a code-block.
+    The default-handler is called with the (XML-RPC) method-name as first argument, and
+    the other arguments are the parameters given by the client-call.
+  
+    If no block is specified the default of (({XMLRPC::BasicServer})) is used, which raises a
+    XMLRPC::FaultException saying "method missing".
+
+
+--- XMLRPC::BasicServer#set_writer( writer )
+    Sets the XML writer to use for generating XML output.
+    Should be an instance of a class from module (({XMLRPC::XMLWriter})).
+    If this method is not called, then (({XMLRPC::Config::DEFAULT_WRITER})) is used. 
+
+--- XMLRPC::BasicServer#set_parser( parser )
+    Sets the XML parser to use for parsing XML documents.
+    Should be an instance of a class from module (({XMLRPC::XMLParser})).
+    If this method is not called, then (({XMLRPC::Config::DEFAULT_PARSER})) is used.
+
+--- XMLRPC::BasicServer#add_introspection
+    Adds the introspection handlers "system.listMethods", "system.methodSignature" and "system.methodHelp", 
+    where only the first one works.
+
+--- XMLRPC::BasicServer#add_multicall
+    Adds the multi-call handler "system.multicall".
+
+--- XMLRPC::BasicServer#get_service_hook
+    Returns the service-hook, which is called on each service request (RPC) unless it's (({nil})).
+
+--- XMLRPC::BasicServer#set_service_hook ( &handler )
+    A service-hook is called for each service request (RPC).
+    You can use a service-hook for example to wrap existing methods and catch exceptions of them or
+    convert values to values recognized by XMLRPC. You can disable it by passing (({nil})) as parameter  
+    ((|handler|)) .
+
+    The service-hook is called with a (({Proc})) object and with the parameters for this (({Proc})).
+    An example:
+
+       server.set_service_hook {|obj, *args|
+         begin
+           ret = obj.call(*args)  # call the original service-method
+           # could convert the return value 
+         resuce
+           # rescue exceptions
+         end
+       }
+
+=end
+
+
+
+require "xmlrpc/parser"
+require "xmlrpc/create"
+require "xmlrpc/config"
+require "xmlrpc/utils"         # ParserWriterChooseMixin
+
+
+
+module XMLRPC
+
+
+class BasicServer
+
+  include ParserWriterChooseMixin
+  include ParseContentType
+
+  ERR_METHOD_MISSING        = 1 
+  ERR_UNCAUGHT_EXCEPTION    = 2
+  ERR_MC_WRONG_PARAM        = 3
+  ERR_MC_MISSING_PARAMS     = 4
+  ERR_MC_MISSING_METHNAME   = 5
+  ERR_MC_RECURSIVE_CALL     = 6
+  ERR_MC_WRONG_PARAM_PARAMS = 7
+  ERR_MC_EXPECTED_STRUCT    = 8
+
+
+  def initialize(class_delim=".")
+    @handler = []
+    @default_handler = nil 
+    @service_hook = nil
+
+    @class_delim = class_delim
+    @create = nil
+    @parser = nil
+
+    add_multicall     if Config::ENABLE_MULTICALL
+    add_introspection if Config::ENABLE_INTROSPECTION
+  end
+
+  def add_handler(prefix, obj_or_signature=nil, help=nil, &block)
+    if block_given?
+      # proc-handler
+      @handler << [prefix, block, obj_or_signature, help]   
+    else
+      if prefix.kind_of? String
+        # class-handler
+        raise ArgumentError, "Expected non-nil value" if obj_or_signature.nil?
+        @handler << [prefix + @class_delim, obj_or_signature]
+      elsif prefix.kind_of? XMLRPC::Service::BasicInterface
+        # class-handler with interface
+        # add all methods
+        @handler += prefix.get_methods(obj_or_signature, @class_delim)
+      else
+        raise ArgumentError, "Wrong type for parameter 'prefix'"
+      end
+    end
+    self
+  end
+
+  def get_service_hook
+    @service_hook
+  end
+
+  def set_service_hook(&handler)
+    @service_hook = handler
+    self
+  end
+ 
+  def get_default_handler
+    @default_handler
+  end
+
+  def set_default_handler (&handler)
+    @default_handler = handler
+    self
+  end  
+
+  def add_multicall
+    add_handler("system.multicall", %w(array array), "Multicall Extension") do |arrStructs|
+      unless arrStructs.is_a? Array 
+        raise XMLRPC::FaultException.new(ERR_MC_WRONG_PARAM, "system.multicall expects an array")
+      end
+
+      arrStructs.collect {|call|
+        if call.is_a? Hash
+          methodName = call["methodName"]
+          params     = call["params"]  
+
+          if params.nil?
+            multicall_fault(ERR_MC_MISSING_PARAMS, "Missing params")
+          elsif methodName.nil?
+            multicall_fault(ERR_MC_MISSING_METHNAME, "Missing methodName")
+          else
+            if methodName == "system.multicall"
+              multicall_fault(ERR_MC_RECURSIVE_CALL, "Recursive system.multicall forbidden")
+            else
+              unless params.is_a? Array
+                multicall_fault(ERR_MC_WRONG_PARAM_PARAMS, "Parameter params have to be an Array")
+              else
+                ok, val = call_method(methodName, *params)
+                if ok
+                  # correct return value
+                  [val]
+                else
+                  # exception
+                  multicall_fault(val.faultCode, val.faultString) 
+                end
+              end
+            end
+          end  
+           
+        else
+          multicall_fault(ERR_MC_EXPECTED_STRUCT, "system.multicall expected struct")
+        end
+      } 
+    end # end add_handler
+    self
+  end
+
+  def add_introspection
+    add_handler("system.listMethods",%w(array), "List methods available on this XML-RPC server") do
+      methods = []
+      @handler.each do |name, obj|
+        if obj.kind_of? Proc
+          methods << name
+        else
+          obj.methods.each {|meth| methods << name + meth}
+        end
+      end
+      methods
+    end
+
+    add_handler("system.methodSignature", %w(array string), "Returns method signature") do |meth|
+      sigs = []
+      @handler.each do |name, obj, sig|
+        if obj.kind_of? Proc and sig != nil and name == meth
+          if sig[0].kind_of? Array
+            # sig contains multiple signatures, e.g. [["array"], ["array", "string"]]
+            sig.each {|s| sigs << s}
+          else
+            # sig is a single signature, e.g. ["array"]
+            sigs << sig 
+          end
+        end
+      end
+      sigs.uniq! || sigs  # remove eventually duplicated signatures
+    end
+
+    add_handler("system.methodHelp", %w(string string), "Returns help on using this method") do |meth|
+      help = nil 
+      @handler.each do |name, obj, sig, hlp|
+        if obj.kind_of? Proc and name == meth 
+          help = hlp
+          break      
+        end
+      end
+      help || ""
+    end
+
+    self
+  end
+
+
+  
+  def process(data)
+    method, params = parser().parseMethodCall(data) 
+    handle(method, *params)
+  end
+ 
+  private # --------------------------------------------------------------
+
+  def multicall_fault(nr, str)
+    {"faultCode" => nr, "faultString" => str}
+  end
+ 
+  #
+  # method dispatch
+  #
+  def dispatch(methodname, *args)
+    for name, obj in @handler
+      if obj.kind_of? Proc
+        next unless methodname == name
+      else
+        next unless methodname =~ /^#{name}(.+)$/
+        next unless obj.respond_to? $1
+        obj = obj.method($1)
+      end
+
+      if check_arity(obj, args.size)
+        if @service_hook.nil?
+          return obj.call(*args) 
+        else
+          return @service_hook.call(obj, *args)
+        end
+      end
+    end 
+ 
+    if @default_handler.nil?
+      raise XMLRPC::FaultException.new(ERR_METHOD_MISSING, "Method #{methodname} missing or wrong number of parameters!")
+    else
+      @default_handler.call(methodname, *args) 
+    end
+  end
+
+
+  #
+  # returns true, if the arity of "obj" matches
+  #
+  def check_arity(obj, n_args)
+    ary = obj.arity
+
+    if ary >= 0
+      n_args == ary
+    else
+      n_args >= (ary+1).abs 
+    end
+  end
+
+
+
+  def call_method(methodname, *args)
+    begin
+      [true, dispatch(methodname, *args)]
+    rescue XMLRPC::FaultException => e  
+      [false, e]  
+    rescue Exception => e
+      [false, XMLRPC::FaultException.new(ERR_UNCAUGHT_EXCEPTION, "Uncaught exception #{e.message} in method #{methodname}")]
+    end
+  end
+
+  #
+  #
+  #
+  def handle(methodname, *args)
+    create().methodResponse(*call_method(methodname, *args))
+  end
+
+
+end
+
+
+=begin
+= XMLRPC::CGIServer
+== Synopsis
+    require "xmlrpc/server"
+ 
+    s = XMLRPC::CGIServer.new     
+
+    s.add_handler("michael.add") do |a,b|
+      a + b
+    end
+
+    s.add_handler("michael.div") do |a,b|
+      if b == 0
+        raise XMLRPC::FaultException.new(1, "division by zero")
+      else
+        a / b 
+      end
+    end 
+
+    s.set_default_handler do |name, *args|
+      raise XMLRPC::FaultException.new(-99, "Method #{name} missing" +
+                                       " or wrong number of parameters!")
+    end
+  
+    s.serve
+
+== Description
+Implements a CGI-based XML-RPC server.
+
+== Superclass
+((<XMLRPC::BasicServer>))
+
+== Class Methods
+--- XMLRPC::CGIServer.new( *a )
+    Creates a new (({XMLRPC::CGIServer})) instance. All parameters given
+    are by-passed to ((<XMLRPC::BasicServer.new>)). You can only create 
+    ((*one*)) (({XMLRPC::CGIServer})) instance, because more than one makes
+    no sense.
+
+== Instance Methods
+--- XMLRPC::CGIServer#serve
+    Call this after you have added all you handlers to the server.
+    This method processes a XML-RPC methodCall and sends the answer
+    back to the client. 
+    Make sure that you don't write to standard-output in a handler, or in
+    any other part of your program, this would case a CGI-based server to fail!
+=end
+
+class CGIServer < BasicServer
+  @@obj = nil
+
+  def CGIServer.new(*a)
+    @@obj = super(*a) if @@obj.nil?
+    @@obj
+  end
+
+  def initialize(*a)
+    super(*a)
+  end
+  
+  def serve
+    catch(:exit_serve) {
+      length = ENV['CONTENT_LENGTH'].to_i
+
+      http_error(405, "Method Not Allowed") unless ENV['REQUEST_METHOD'] == "POST" 
+      http_error(400, "Bad Request")        unless parse_content_type(ENV['CONTENT_TYPE']).first == "text/xml"
+      http_error(411, "Length Required")    unless length > 0 
+
+      # TODO: do we need a call to binmode?
+      $stdin.binmode if $stdin.respond_to? :binmode
+      data = $stdin.read(length)
+
+      http_error(400, "Bad Request")        if data.nil? or data.size != length
+
+      http_write(process(data), "Content-type" => "text/xml; charset=utf-8")
+    }
+  end
+
+
+  private
+
+  def http_error(status, message)
+    err = "#{status} #{message}"
+    msg = <<-"MSGEND" 
+      <html>
+        <head>
+          <title>#{err}</title>
+        </head>
+        <body>
+          <h1>#{err}</h1>
+          <p>Unexpected error occured while processing XML-RPC request!</p>
+        </body>
+      </html>
+    MSGEND
+
+    http_write(msg, "Status" => err, "Content-type" => "text/html")
+    throw :exit_serve # exit from the #serve method
+  end
+
+  def http_write(body, header)
+    h = {}
+    header.each {|key, value| h[key.to_s.capitalize] = value}
+    h['Status']         ||= "200 OK"
+    h['Content-length'] ||= body.size.to_s 
+
+    str = ""
+    h.each {|key, value| str << "#{key}: #{value}\r\n"}
+    str << "\r\n#{body}"
+
+    print str
+  end
+
+end
+
+=begin
+= XMLRPC::ModRubyServer
+== Description
+Implements a XML-RPC server, which works with Apache mod_ruby.
+
+Use it in the same way as CGIServer!
+
+== Superclass
+((<XMLRPC::BasicServer>))
+=end 
+
+class ModRubyServer < BasicServer
+
+  def initialize(*a)
+    @ap = Apache::request
+    super(*a)
+  end
+
+  def serve
+    catch(:exit_serve) {
+      header = {}
+      @ap.headers_in.each {|key, value| header[key.capitalize] = value}
+
+      length = header['Content-length'].to_i
+
+      http_error(405, "Method Not Allowed") unless @ap.request_method  == "POST" 
+      http_error(400, "Bad Request")        unless parse_content_type(header['Content-type']).first == "text/xml"
+      http_error(411, "Length Required")    unless length > 0 
+
+      # TODO: do we need a call to binmode?
+      @ap.binmode
+      data = @ap.read(length)
+
+      http_error(400, "Bad Request")        if data.nil? or data.size != length
+
+      http_write(process(data), 200, "Content-type" => "text/xml; charset=utf-8")
+    }
+  end
+
+
+  private
+
+  def http_error(status, message)
+    err = "#{status} #{message}"
+    msg = <<-"MSGEND" 
+      <html>
+        <head>
+          <title>#{err}</title>
+        </head>
+        <body>
+          <h1>#{err}</h1>
+          <p>Unexpected error occured while processing XML-RPC request!</p>
+        </body>
+      </html>
+    MSGEND
+
+    http_write(msg, status, "Status" => err, "Content-type" => "text/html")
+    throw :exit_serve # exit from the #serve method
+  end
+
+  def http_write(body, status, header)
+    h = {}
+    header.each {|key, value| h[key.to_s.capitalize] = value}
+    h['Status']         ||= "200 OK"
+    h['Content-length'] ||= body.size.to_s 
+
+    h.each {|key, value| @ap.headers_out[key] = value }
+    @ap.content_type = h["Content-type"] 
+    @ap.status = status.to_i 
+    @ap.send_http_header 
+
+    @ap.print body
+  end
+
+end
+
+=begin
+= XMLRPC::Server
+== Synopsis
+    require "xmlrpc/server"
+ 
+    s = XMLRPC::Server.new(8080) 
+
+    s.add_handler("michael.add") do |a,b|
+      a + b
+    end
+
+    s.add_handler("michael.div") do |a,b|
+      if b == 0
+        raise XMLRPC::FaultException.new(1, "division by zero")
+      else
+        a / b 
+      end
+    end 
+
+    s.set_default_handler do |name, *args|
+      raise XMLRPC::FaultException.new(-99, "Method #{name} missing" +
+                                       " or wrong number of parameters!")
+    end
+ 
+    s.serve
+
+== Description
+Implements a standalone XML-RPC server. The method (({serve}))) is left if a SIGHUP is sent to the
+program.
+
+== Superclass
+((<XMLRPC::WEBrickServlet>))
+
+== Class Methods
+--- XMLRPC::Server.new( port=8080, host="127.0.0.1", maxConnections=4, stdlog=$stdout, audit=true, debug=true, *a )
+    Creates a new (({XMLRPC::Server})) instance, which is a XML-RPC server listening on
+    port ((|port|)) and accepts requests for the host ((|host|)), which is by default only the localhost. 
+    The server is not started, to start it you have to call ((<serve|XMLRPC::Server#serve>)).
+
+    Parameters ((|audit|)) and ((|debug|)) are obsolete!
+
+    All additionally given parameters in ((|*a|)) are by-passed to ((<XMLRPC::BasicServer.new>)). 
+    
+== Instance Methods
+--- XMLRPC::Server#serve
+    Call this after you have added all you handlers to the server.
+    This method starts the server to listen for XML-RPC requests and answer them.
+
+--- XMLRPC::Server#shutdown
+    Stops and shuts the server down.
+    
+=end
+
+class WEBrickServlet < BasicServer; end # forward declaration
+
+class Server < WEBrickServlet
+
+  def initialize(port=8080, host="127.0.0.1", maxConnections=4, stdlog=$stdout, audit=true, debug=true, *a)
+    super(*a)
+    require 'webrick'
+    @server = WEBrick::HTTPServer.new(:Port => port, :BindAddress => host, :MaxClients => maxConnections, 
+                                      :Logger => WEBrick::Log.new(stdlog))
+    @server.mount("/", self)
+  end
+  
+  def serve
+    if RUBY_PLATFORM =~ /mingw|mswin32/
+      signal = 1
+    else
+      signal = "HUP"
+    end
+    trap(signal) { @server.shutdown }
+
+    @server.start
+  end
+  
+  def shutdown
+    @server.shutdown
+  end
+ 
+end
+
+=begin
+= XMLRPC::WEBrickServlet
+== Synopsis
+
+    require "webrick"
+    require "xmlrpc/server"
+
+    s = XMLRPC::WEBrickServlet.new
+    s.add_handler("michael.add") do |a,b|
+      a + b
+    end
+
+    s.add_handler("michael.div") do |a,b|
+      if b == 0
+        raise XMLRPC::FaultException.new(1, "division by zero")
+      else
+        a / b 
+      end
+    end 
+
+    s.set_default_handler do |name, *args|
+      raise XMLRPC::FaultException.new(-99, "Method #{name} missing" +
+                                       " or wrong number of parameters!")
+    end
+
+    httpserver = WEBrick::HTTPServer.new(:Port => 8080)    
+    httpserver.mount("/RPC2", s)
+    trap("HUP") { httpserver.shutdown }   # use 1 instead of "HUP" on Windows
+    httpserver.start
+
+== Instance Methods
+
+--- XMLRPC::WEBrickServlet#set_valid_ip( *ip_addr )
+    Specifies the valid IP addresses that are allowed to connect to the server.
+    Each IP is either a (({String})) or a (({Regexp})).
+
+--- XMLRPC::WEBrickServlet#get_valid_ip
+    Return the via method ((<set_valid_ip|XMLRPC::Server#set_valid_ip>)) specified
+    valid IP addresses.
+ 
+== Description
+Implements a servlet for use with WEBrick, a pure Ruby (HTTP-) server framework.
+
+== Superclass
+((<XMLRPC::BasicServer>))
+
+=end
+
+class WEBrickServlet < BasicServer
+  def initialize(*a)
+    super
+    require "webrick/httpstatus"
+    @valid_ip = nil
+  end
+
+  # deprecated from WEBrick/1.2.2. 
+  # but does not break anything.
+  def require_path_info?
+    false 
+  end
+
+  def get_instance(config, *options)
+    # TODO: set config & options
+    self
+  end
+
+  def set_valid_ip(*ip_addr)
+    if ip_addr.size == 1 and ip_addr[0].nil?
+      @valid_ip = nil
+    else
+      @valid_ip = ip_addr
+    end
+  end
+
+  def get_valid_ip
+    @valid_ip
+  end
+
+  def service(request, response)
+
+    if @valid_ip 
+      raise WEBrick::HTTPStatus::Forbidden unless @valid_ip.any? { |ip| request.peeraddr[3] =~ ip }
+    end
+
+    if request.request_method != "POST"
+      raise WEBrick::HTTPStatus::MethodNotAllowed,
+            "unsupported method `#{request.request_method}'."
+    end
+
+    if parse_content_type(request['Content-type']).first != "text/xml" 
+      raise WEBrick::HTTPStatus::BadRequest
+    end 
+
+    length = (request['Content-length'] || 0).to_i
+
+    raise WEBrick::HTTPStatus::LengthRequired unless length > 0
+
+    data = request.body
+
+    if data.nil? or data.size != length
+      raise WEBrick::HTTPStatus::BadRequest
+    end
+
+    resp = process(data)
+    if resp.nil? or resp.size <= 0  
+      raise WEBrick::HTTPStatus::InternalServerError
+    end
+
+    response.status = 200
+    response['Content-Length'] = resp.size
+    response['Content-Type']   = "text/xml; charset=utf-8"
+    response.body = resp 
+  end
+end
+
+
+end # module XMLRPC
+
+
+=begin
+= History
+    $Id: server.rb 11708 2007-02-12 23:01:19Z shyouhei $    
+=end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/utils.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/utils.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xmlrpc/utils.rb	(revision 18425)
@@ -0,0 +1,165 @@
+#
+# Defines ParserWriterChooseMixin, which makes it possible to choose a
+# different XML writer and/or XML parser then the default one.
+# The Mixin is used in client.rb (class Client) and server.rb (class 
+# BasicServer)
+# 
+# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
+#
+# $Id: utils.rb 11708 2007-02-12 23:01:19Z shyouhei $ 
+#
+
+module XMLRPC
+
+  #
+  # This module enables a user-class to be marshalled
+  # by XML-RPC for Ruby into a Hash, with one additional
+  # key/value pair "___class___" => ClassName
+  # 
+  module Marshallable
+  end
+
+
+  module ParserWriterChooseMixin
+
+    def set_writer(writer)
+      @create = Create.new(writer)
+      self
+    end
+
+    def set_parser(parser)
+      @parser = parser
+      self
+    end
+
+    private
+
+    def create
+      # if set_writer was not already called then call it now
+      if @create.nil? then
+	set_writer(Config::DEFAULT_WRITER.new)
+      end
+      @create
+    end
+
+    def parser
+      # if set_parser was not already called then call it now
+      if @parser.nil? then
+	set_parser(Config::DEFAULT_PARSER.new)
+      end
+      @parser
+    end
+
+  end # module ParserWriterChooseMixin
+
+
+  module Service
+
+  #
+  # base class for Service Interface definitions, used
+  # by BasicServer#add_handler
+  #
+
+  class BasicInterface
+    attr_reader :prefix, :methods
+
+    def initialize(prefix)
+      @prefix = prefix
+      @methods = []
+    end
+
+    def add_method(sig, help=nil, meth_name=nil)
+      mname = nil
+      sig = [sig] if sig.kind_of? String
+
+      sig = sig.collect do |s| 
+        name, si = parse_sig(s)
+        raise "Wrong signatures!" if mname != nil and name != mname 
+        mname = name
+        si
+      end
+
+      @methods << [mname, meth_name || mname, sig, help]
+    end
+
+    private # ---------------------------------
+  
+    def parse_sig(sig)
+      # sig is a String
+      if sig =~ /^\s*(\w+)\s+([^(]+)(\(([^)]*)\))?\s*$/
+        params = [$1]
+        name   = $2.strip 
+        $4.split(",").each {|i| params << i.strip} if $4 != nil
+        return name, params
+      else
+        raise "Syntax error in signature"
+      end
+    end
+
+  end # class BasicInterface
+
+  #
+  # class which wraps a Service Interface definition, used
+  # by BasicServer#add_handler
+  #
+  class Interface < BasicInterface
+    def initialize(prefix, &p)
+      raise "No interface specified" if p.nil?
+      super(prefix)
+      instance_eval(&p)
+    end
+
+    def get_methods(obj, delim=".") 
+      prefix = @prefix + delim
+      @methods.collect { |name, meth, sig, help| 
+        [prefix + name, obj.method(meth).to_proc, sig, help] 
+      }
+    end
+
+    private # ---------------------------------
+
+    def meth(*a)
+      add_method(*a)
+    end
+
+  end # class Interface
+
+  class PublicInstanceMethodsInterface < BasicInterface
+    def initialize(prefix)
+      super(prefix)
+    end
+
+    def get_methods(obj, delim=".")
+      prefix = @prefix + delim
+      obj.class.public_instance_methods(false).collect { |name|
+        [prefix + name, obj.method(name).to_proc, nil, nil] 
+      }
+    end
+  end
+
+
+  end # module Service
+
+
+  # 
+  # short-form to create a Service::Interface
+  #
+  def self.interface(prefix, &p)
+    Service::Interface.new(prefix, &p)  
+  end
+
+  # short-cut for creating a PublicInstanceMethodsInterface
+  def self.iPIMethods(prefix)
+    Service::PublicInstanceMethodsInterface.new(prefix) 
+  end
+
+
+  module ParseContentType
+    def parse_content_type(str)
+      a, *b = str.split(";")
+      return a.strip, *b
+    end
+  end
+
+end # module XMLRPC
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/charset.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/charset.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/charset.rb	(revision 18425)
@@ -0,0 +1,187 @@
+# XSD4R - Charset handling library.
+# Copyright (C) 2001, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+module XSD
+
+
+module Charset
+  @internal_encoding = $KCODE
+
+  class XSDError < StandardError; end
+  class CharsetError < XSDError; end
+  class UnknownCharsetError < CharsetError; end
+  class CharsetConversionError < CharsetError; end
+
+public
+
+  ###
+  ## Maps
+  #
+  EncodingConvertMap = {}
+  def Charset.init
+    EncodingConvertMap[['UTF8', 'X_ISO8859_1']] =
+      Proc.new { |str| str.unpack('U*').pack('C*') }
+    EncodingConvertMap[['X_ISO8859_1', 'UTF8']] =
+      Proc.new { |str| str.unpack('C*').pack('U*') }
+    begin
+      require 'xsd/iconvcharset'
+      @internal_encoding = 'UTF8'
+      sjtag = (/(mswin|bccwin|mingw|cygwin|emx)/ =~ RUBY_PLATFORM) ? 'cp932' :
+        'shift_jis'
+      EncodingConvertMap[['UTF8', 'EUC' ]] =
+        Proc.new { |str| IconvCharset.safe_iconv("euc-jp", "utf-8", str) }
+      EncodingConvertMap[['EUC' , 'UTF8']] =
+        Proc.new { |str| IconvCharset.safe_iconv("utf-8", "euc-jp", str) }
+      EncodingConvertMap[['EUC' , 'SJIS']] =
+        Proc.new { |str| IconvCharset.safe_iconv(sjtag, "euc-jp", str) }
+      EncodingConvertMap[['UTF8', 'SJIS']] =
+        Proc.new { |str| IconvCharset.safe_iconv(sjtag, "utf-8", str) }
+      EncodingConvertMap[['SJIS', 'UTF8']] =
+        Proc.new { |str| IconvCharset.safe_iconv("utf-8", sjtag, str) }
+      EncodingConvertMap[['SJIS', 'EUC' ]] =
+        Proc.new { |str| IconvCharset.safe_iconv("euc-jp", sjtag, str) }
+    rescue LoadError
+      begin
+       	require 'nkf'
+	EncodingConvertMap[['EUC' , 'SJIS']] =
+          Proc.new { |str| NKF.nkf('-sXm0', str) }
+	EncodingConvertMap[['SJIS', 'EUC' ]] =
+          Proc.new { |str| NKF.nkf('-eXm0', str) }
+      rescue LoadError
+      end
+  
+      begin
+	require 'uconv'
+	@internal_encoding = 'UTF8'
+	EncodingConvertMap[['UTF8', 'EUC' ]] = Uconv.method(:u8toeuc)
+	EncodingConvertMap[['UTF8', 'SJIS']] = Uconv.method(:u8tosjis)
+	EncodingConvertMap[['EUC' , 'UTF8']] = Uconv.method(:euctou8)
+	EncodingConvertMap[['SJIS', 'UTF8']] = Uconv.method(:sjistou8)
+      rescue LoadError
+      end
+    end
+  end
+  self.init
+
+  CharsetMap = {
+    'NONE' => 'us-ascii',
+    'EUC' => 'euc-jp',
+    'SJIS' => 'shift_jis',
+    'UTF8' => 'utf-8',
+    'X_ISO_8859_1' => 'iso-8859-1',
+    'X_UNKNOWN' => nil,
+  }
+
+
+  ###
+  ## handlers
+  #
+  def Charset.encoding
+    @internal_encoding
+  end
+
+  def Charset.encoding=(encoding)
+    warn("xsd charset is set to #{encoding}") if $DEBUG
+    @internal_encoding = encoding
+  end
+
+  def Charset.xml_encoding_label
+    charset_label(@internal_encoding)
+  end
+
+  def Charset.encoding_to_xml(str, charset)
+    encoding_conv(str, @internal_encoding, charset_str(charset))
+  end
+
+  def Charset.encoding_from_xml(str, charset)
+    encoding_conv(str, charset_str(charset), @internal_encoding)
+  end
+
+  def Charset.encoding_conv(str, enc_from, enc_to)
+    if enc_from == enc_to or enc_from == 'NONE' or enc_to == 'NONE'
+      str
+    elsif converter = EncodingConvertMap[[enc_from, enc_to]]
+      converter.call(str)
+    else
+      raise CharsetConversionError.new(
+	"Converter not found: #{enc_from} -> #{enc_to}")
+    end
+  end
+
+  def Charset.charset_label(encoding)
+    CharsetMap[encoding.upcase]
+  end
+
+  def Charset.charset_str(label)
+    if CharsetMap.respond_to?(:key)
+      CharsetMap.key(label.downcase) || 'X_UNKNOWN'
+    else
+      CharsetMap.index(label.downcase) || 'X_UNKNOWN'
+    end
+  end
+
+  # us_ascii = '[\x00-\x7F]'
+  us_ascii = '[\x9\xa\xd\x20-\x7F]'	# XML 1.0 restricted.
+  USASCIIRegexp = Regexp.new("\\A#{us_ascii}*\\z", nil, "NONE")
+
+  twobytes_euc = '(?:[\x8E\xA1-\xFE][\xA1-\xFE])'
+  threebytes_euc = '(?:\x8F[\xA1-\xFE][\xA1-\xFE])'
+  character_euc = "(?:#{us_ascii}|#{twobytes_euc}|#{threebytes_euc})"
+  EUCRegexp = Regexp.new("\\A#{character_euc}*\\z", nil, "NONE")
+
+  # onebyte_sjis = '[\x00-\x7F\xA1-\xDF]'
+  onebyte_sjis = '[\x9\xa\xd\x20-\x7F\xA1-\xDF]'	# XML 1.0 restricted.
+  twobytes_sjis = '(?:[\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC])'
+  character_sjis = "(?:#{onebyte_sjis}|#{twobytes_sjis})"
+  SJISRegexp = Regexp.new("\\A#{character_sjis}*\\z", nil, "NONE")
+
+  # 0xxxxxxx
+  # 110yyyyy 10xxxxxx
+  twobytes_utf8 = '(?:[\xC0-\xDF][\x80-\xBF])'
+  # 1110zzzz 10yyyyyy 10xxxxxx
+  threebytes_utf8 = '(?:[\xE0-\xEF][\x80-\xBF][\x80-\xBF])'
+  # 11110uuu 10uuuzzz 10yyyyyy 10xxxxxx
+  fourbytes_utf8 = '(?:[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF])'
+  character_utf8 =
+    "(?:#{us_ascii}|#{twobytes_utf8}|#{threebytes_utf8}|#{fourbytes_utf8})"
+  UTF8Regexp = Regexp.new("\\A#{character_utf8}*\\z", nil, "NONE")
+
+  def Charset.is_us_ascii(str)
+    USASCIIRegexp =~ str
+  end
+
+  def Charset.is_utf8(str)
+    UTF8Regexp =~ str
+  end
+
+  def Charset.is_euc(str)
+    EUCRegexp =~ str
+  end
+
+  def Charset.is_sjis(str)
+    SJISRegexp =~ str
+  end
+
+  def Charset.is_ces(str, code = $KCODE)
+    case code
+    when 'NONE'
+      is_us_ascii(str)
+    when 'UTF8'
+      is_utf8(str)
+    when 'EUC'
+      is_euc(str)
+    when 'SJIS'
+      is_sjis(str)
+    else
+      raise UnknownCharsetError.new("Unknown charset: #{code}")
+    end
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen.rb	(revision 18425)
@@ -0,0 +1,12 @@
+# XSD4R - Generating code library
+# Copyright (C) 2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/codegen/gensupport'
+require 'xsd/codegen/moduledef'
+require 'xsd/codegen/classdef'
+require 'xsd/codegen/methoddef'
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/classdef.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/classdef.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/classdef.rb	(revision 18425)
@@ -0,0 +1,203 @@
+# XSD4R - Generating class definition code
+# Copyright (C) 2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/codegen/gensupport'
+require 'xsd/codegen/moduledef'
+require 'xsd/codegen/methoddef'
+
+
+module XSD
+module CodeGen
+
+
+class ClassDef < ModuleDef
+  include GenSupport
+
+  def initialize(name, baseclass = nil)
+    super(name)
+    @baseclass = baseclass
+    @classvar = []
+    @attrdef = []
+  end
+
+  def def_classvar(var, value)
+    var = var.sub(/\A@@/, "")
+    unless safevarname?(var)
+      raise ArgumentError.new("#{var} seems to be unsafe")
+    end
+    @classvar << [var, value]
+  end
+
+  def def_attr(attrname, writable = true, varname = nil)
+    unless safevarname?(varname || attrname)
+      raise ArgumentError.new("#{varname || attrname} seems to be unsafe")
+    end
+    @attrdef << [attrname, writable, varname]
+  end
+
+  def dump
+    buf = ""
+    unless @requirepath.empty?
+      buf << dump_requirepath 
+    end
+    buf << dump_emptyline unless buf.empty?
+    package = @name.split(/::/)[0..-2]
+    buf << dump_package_def(package) unless package.empty?
+    buf << dump_comment if @comment
+    buf << dump_class_def
+    spacer = false
+    unless @classvar.empty?
+      spacer = true
+      buf << dump_classvar
+    end
+    unless @const.empty?
+      buf << dump_emptyline if spacer
+      spacer = true
+      buf << dump_const
+    end
+    unless @code.empty?
+      buf << dump_emptyline if spacer
+      spacer = true
+      buf << dump_code
+    end
+    unless @attrdef.empty?
+      buf << dump_emptyline if spacer
+      spacer = true
+      buf << dump_attributes
+    end
+    unless @methoddef.empty?
+      buf << dump_emptyline if spacer
+      spacer = true
+      buf << dump_methods
+    end
+    buf << dump_class_def_end
+    buf << dump_package_def_end(package) unless package.empty?
+    buf.gsub(/^\s+$/, '')
+  end
+
+private
+
+  def dump_class_def
+    name = @name.to_s.split(/::/)
+    if @baseclass
+      format("class #{name.last} < #{@baseclass}")
+    else
+      format("class #{name.last}")
+    end
+  end
+
+  def dump_class_def_end
+    str = format("end")
+  end
+
+  def dump_classvar
+    dump_static(
+      @classvar.collect { |var, value|
+        %Q(@@#{var.sub(/^@@/, "")} = #{dump_value(value)})
+      }.join("\n")
+    )
+  end
+
+  def dump_attributes
+    str = ""
+    @attrdef.each do |attrname, writable, varname|
+      varname ||= attrname
+      if attrname == varname
+        str << format(dump_accessor(attrname, writable), 2)
+      end
+    end
+    @attrdef.each do |attrname, writable, varname|
+      varname ||= attrname
+      if attrname != varname
+        str << "\n" unless str.empty?
+        str << format(dump_attribute(attrname, writable, varname), 2)
+      end
+    end
+    str
+  end
+
+  def dump_accessor(attrname, writable)
+    if writable
+      "attr_accessor :#{attrname}"
+    else
+      "attr_reader :#{attrname}"
+    end
+  end
+
+  def dump_attribute(attrname, writable, varname)
+    str = nil
+    mr = MethodDef.new(attrname)
+    mr.definition = "@#{varname}"
+    str = mr.dump
+    if writable
+      mw = MethodDef.new(attrname + "=", 'value')
+      mw.definition = "@#{varname} = value"
+      str << "\n" + mw.dump
+    end
+    str
+  end
+end
+
+
+end
+end
+
+
+if __FILE__ == $0
+  require 'xsd/codegen/classdef'
+  include XSD::CodeGen
+  c = ClassDef.new("Foo::Bar::HobbitName", String)
+  c.def_require("foo/bar")
+  c.comment = <<-EOD
+      foo
+    bar
+      baz
+  EOD
+  c.def_const("FOO", 1)
+  c.def_classvar("@@foo", "var".dump)
+  c.def_classvar("baz", "1".dump)
+  c.def_attr("Foo", true, "foo")
+  c.def_attr("bar")
+  c.def_attr("baz", true)
+  c.def_attr("Foo2", true, "foo2")
+  c.def_attr("foo3", false, "foo3")
+  c.def_method("foo") do
+    <<-EOD
+        foo.bar = 1
+\tbaz.each do |ele|
+\t  ele
+        end
+    EOD
+  end
+  c.def_method("baz", "qux") do
+    <<-EOD
+      [1, 2, 3].each do |i|
+        p i
+      end
+    EOD
+  end
+
+  m = MethodDef.new("qux", "quxx", "quxxx") do
+    <<-EOD
+    p quxx + quxxx
+    EOD
+  end
+  m.comment = "hello world\n123"
+  c.add_method(m)
+  c.def_code <<-EOD
+    Foo.new
+    Bar.z
+  EOD
+  c.def_code <<-EOD
+    Foo.new
+    Bar.z
+  EOD
+  c.def_privatemethod("foo", "baz", "*arg", "&block")
+
+  puts c.dump
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/commentdef.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/commentdef.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/commentdef.rb	(revision 18425)
@@ -0,0 +1,34 @@
+# XSD4R - Generating comment definition code
+# Copyright (C) 2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/codegen/gensupport'
+
+
+module XSD
+module CodeGen
+
+
+module CommentDef
+  include GenSupport
+
+  attr_accessor :comment
+
+private
+
+  def dump_comment
+    if /\A#/ =~ @comment
+      format(@comment)
+    else
+      format(@comment).gsub(/^/, '# ')
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/gensupport.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/gensupport.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/gensupport.rb	(revision 18425)
@@ -0,0 +1,166 @@
+# XSD4R - Code generation support
+# Copyright (C) 2004, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+module XSD
+module CodeGen
+
+# from the file 'keywords' in 1.9.
+KEYWORD = {}
+%w(
+__LINE__
+__FILE__
+BEGIN
+END
+alias
+and
+begin
+break
+case
+class
+def
+defined?
+do
+else
+elsif
+end
+ensure
+false
+for
+if
+in
+module
+next
+nil
+not
+or
+redo
+rescue
+retry
+return
+self
+super
+then
+true
+undef
+unless
+until
+when
+while
+yield
+).each { |k| KEYWORD[k] = nil }
+
+module GenSupport
+  def capitalize(target)
+    target.sub(/^([a-z])/) { $1.tr!('[a-z]', '[A-Z]') }
+  end
+  module_function :capitalize
+
+  def uncapitalize(target)
+    target.sub(/^([A-Z])/) { $1.tr!('[A-Z]', '[a-z]') }
+  end
+  module_function :uncapitalize
+
+  def safeconstname(name)
+    safename = name.scan(/[a-zA-Z0-9_]+/).collect { |ele|
+      GenSupport.capitalize(ele)
+    }.join
+    if /^[A-Z]/ !~ safename or keyword?(safename)
+      safename = "C_#{safename}"
+    end
+    safename
+  end
+  module_function :safeconstname
+
+  def safeconstname?(name)
+    /\A[A-Z][a-zA-Z0-9_]*\z/ =~ name and !keyword?(name)
+  end
+  module_function :safeconstname?
+
+  def safemethodname(name)
+    safename = name.scan(/[a-zA-Z0-9_]+/).join('_')
+    safename = uncapitalize(safename)
+    if /^[a-z]/ !~ safename
+      safename = "m_#{safename}"
+    end
+    safename
+  end
+  module_function :safemethodname
+
+  def safemethodname?(name)
+    /\A[a-zA-Z_][a-zA-Z0-9_]*[=!?]?\z/ =~ name
+  end
+  module_function :safemethodname?
+
+  def safevarname(name)
+    safename = uncapitalize(name.scan(/[a-zA-Z0-9_]+/).join('_'))
+    if /^[a-z]/ !~ safename or keyword?(safename)
+      "v_#{safename}"
+    else
+      safename
+    end
+  end
+  module_function :safevarname
+
+  def safevarname?(name)
+    /\A[a-z_][a-zA-Z0-9_]*\z/ =~ name and !keyword?(name)
+  end
+  module_function :safevarname?
+
+  def keyword?(word)
+    KEYWORD.key?(word)
+  end
+  module_function :keyword?
+
+  def format(str, indent = nil)
+    str = trim_eol(str)
+    str = trim_indent(str)
+    if indent
+      str.gsub(/^/, " " * indent)
+    else
+      str
+    end
+  end
+
+private
+
+  def trim_eol(str)
+    str.collect { |line|
+      line.sub(/\r?\n\z/, "") + "\n"
+    }.join
+  end
+
+  def trim_indent(str)
+    indent = nil
+    str = str.collect { |line| untab(line) }.join
+    str.each do |line|
+      head = line.index(/\S/)
+      if !head.nil? and (indent.nil? or head < indent)
+        indent = head
+      end
+    end
+    return str unless indent
+    str.collect { |line|
+      line.sub(/^ {0,#{indent}}/, "")
+    }.join
+  end
+
+  def untab(line, ts = 8)
+    while pos = line.index(/\t/)
+      line = line.sub(/\t/, " " * (ts - (pos % ts)))
+    end
+    line
+  end
+
+  def dump_emptyline
+    "\n"
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/methoddef.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/methoddef.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/methoddef.rb	(revision 18425)
@@ -0,0 +1,63 @@
+# XSD4R - Generating method definition code
+# Copyright (C) 2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/codegen/gensupport'
+require 'xsd/codegen/commentdef'
+
+
+module XSD
+module CodeGen
+
+
+class MethodDef
+  include GenSupport
+  include CommentDef
+
+  attr_accessor :definition
+
+  def initialize(name, *params)
+    unless safemethodname?(name)
+      raise ArgumentError.new("name '#{name}' seems to be unsafe")
+    end
+    @name = name
+    @params = params
+    @comment = nil
+    @definition = yield if block_given?
+  end
+
+  def dump
+    buf = ""
+    buf << dump_comment if @comment
+    buf << dump_method_def
+    buf << dump_definition if @definition and !@definition.empty?
+    buf << dump_method_def_end
+    buf
+  end
+
+private
+
+  def dump_method_def
+    if @params.empty?
+      format("def #{@name}")
+    else
+      format("def #{@name}(#{@params.join(", ")})")
+    end
+  end
+
+  def dump_method_def_end
+    format("end")
+  end
+
+  def dump_definition
+    format(@definition, 2)
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/moduledef.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/moduledef.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/codegen/moduledef.rb	(revision 18425)
@@ -0,0 +1,191 @@
+# XSD4R - Generating module definition code
+# Copyright (C) 2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/codegen/gensupport'
+require 'xsd/codegen/methoddef'
+require 'xsd/codegen/commentdef'
+
+
+module XSD
+module CodeGen
+
+
+class ModuleDef
+  include GenSupport
+  include CommentDef
+
+  def initialize(name)
+    @name = name
+    @comment = nil
+    @const = []
+    @code = []
+    @requirepath = []
+    @methoddef = []
+  end
+
+  def def_require(path)
+    @requirepath << path
+  end
+
+  def def_const(const, value)
+    unless safeconstname?(const)
+      raise ArgumentError.new("#{const} seems to be unsafe")
+    end
+    @const << [const, value]
+  end
+
+  def def_code(code)
+    @code << code
+  end
+
+  def def_method(name, *params)
+    add_method(MethodDef.new(name, *params) { yield if block_given? }, :public)
+  end
+  alias def_publicmethod def_method
+
+  def def_protectedmethod(name, *params)
+    add_method(MethodDef.new(name, *params) { yield if block_given? },
+      :protected)
+  end
+
+  def def_privatemethod(name, *params)
+    add_method(MethodDef.new(name, *params) { yield if block_given? }, :private)
+  end
+
+  def add_method(m, visibility = :public)
+    @methoddef << [visibility, m]
+  end
+
+  def dump
+    buf = ""
+    unless @requirepath.empty?
+      buf << dump_requirepath 
+    end
+    buf << dump_emptyline unless buf.empty?
+    package = @name.split(/::/)[0..-2]
+    buf << dump_package_def(package) unless package.empty?
+    buf << dump_comment if @comment
+    buf << dump_module_def
+    spacer = false
+    unless @const.empty?
+      buf << dump_emptyline if spacer
+      spacer = true
+      buf << dump_const
+    end
+    unless @code.empty?
+      buf << dump_emptyline if spacer
+      spacer = true
+      buf << dump_code
+    end
+    unless @methoddef.empty?
+      buf << dump_emptyline if spacer
+      spacer = true
+      buf << dump_methods
+    end
+    buf << dump_module_def_end
+    buf << dump_package_def_end(package) unless package.empty?
+    buf.gsub(/^\s+$/, '')
+  end
+
+private
+
+  def dump_requirepath
+    format(
+      @requirepath.collect { |path|
+        %Q(require '#{path}')
+      }.join("\n")
+    )
+  end
+
+  def dump_const
+    dump_static(
+      @const.sort.collect { |var, value|
+        %Q(#{var} = #{dump_value(value)})
+      }.join("\n")
+    )
+  end
+
+  def dump_code
+    dump_static(@code.join("\n"))
+  end
+
+  def dump_static(str)
+    format(str, 2)
+  end
+
+  def dump_methods
+    methods = {}
+    @methoddef.each do |visibility, method|
+      (methods[visibility] ||= []) << method
+    end
+    str = ""
+    [:public, :protected, :private].each do |visibility|
+      if methods[visibility]
+        str << "\n" unless str.empty?
+        str << visibility.to_s << "\n\n" unless visibility == :public
+        str << methods[visibility].collect { |m| format(m.dump, 2) }.join("\n")
+      end
+    end
+    str
+  end
+
+  def dump_value(value)
+    if value.respond_to?(:to_src)
+      value.to_src
+    else
+      value
+    end
+  end
+
+  def dump_package_def(package)
+    format(package.collect { |ele| "module #{ele}" }.join("; ")) + "\n\n"
+  end
+
+  def dump_package_def_end(package)
+    "\n\n" + format(package.collect { |ele| "end" }.join("; "))
+  end
+
+  def dump_module_def
+    name = @name.to_s.split(/::/)
+    format("module #{name.last}")
+  end
+
+  def dump_module_def_end
+    format("end")
+  end
+end
+
+
+end
+end
+
+
+if __FILE__ == $0
+  require 'xsd/codegen/moduledef'
+  include XSD::CodeGen
+  m = ModuleDef.new("Foo::Bar::HobbitName")
+  m.def_require("foo/bar")
+  m.def_require("baz")
+  m.comment = <<-EOD
+    foo
+    bar
+    baz
+  EOD
+  m.def_method("foo") do
+    <<-EOD
+      foo.bar = 1
+      baz.each do |ele|
+        ele + 1
+      end
+    EOD
+  end
+  m.def_method("baz", "qux")
+  #m.def_protectedmethod("aaa")
+  m.def_privatemethod("bbb")
+  puts m.dump
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/datatypes.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/datatypes.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/datatypes.rb	(revision 18425)
@@ -0,0 +1,1269 @@
+# XSD4R - XML Schema Datatype implementation.
+# Copyright (C) 2000, 2001, 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/qname'
+require 'xsd/charset'
+require 'uri'
+
+
+###
+## XMLSchamaDatatypes general definitions.
+#
+module XSD
+
+
+Namespace = 'http://www.w3.org/2001/XMLSchema'
+InstanceNamespace = 'http://www.w3.org/2001/XMLSchema-instance'
+
+AttrType = 'type'
+NilValue = 'true'
+
+AnyTypeLiteral = 'anyType'
+AnySimpleTypeLiteral = 'anySimpleType'
+NilLiteral = 'nil'
+StringLiteral = 'string'
+BooleanLiteral = 'boolean'
+DecimalLiteral = 'decimal'
+FloatLiteral = 'float'
+DoubleLiteral = 'double'
+DurationLiteral = 'duration'
+DateTimeLiteral = 'dateTime'
+TimeLiteral = 'time'
+DateLiteral = 'date'
+GYearMonthLiteral = 'gYearMonth'
+GYearLiteral = 'gYear'
+GMonthDayLiteral = 'gMonthDay'
+GDayLiteral = 'gDay'
+GMonthLiteral = 'gMonth'
+HexBinaryLiteral = 'hexBinary'
+Base64BinaryLiteral = 'base64Binary'
+AnyURILiteral = 'anyURI'
+QNameLiteral = 'QName'
+
+NormalizedStringLiteral = 'normalizedString'
+#3.3.2 token
+#3.3.3 language
+#3.3.4 NMTOKEN
+#3.3.5 NMTOKENS
+#3.3.6 Name
+#3.3.7 NCName
+#3.3.8 ID
+#3.3.9 IDREF
+#3.3.10 IDREFS
+#3.3.11 ENTITY
+#3.3.12 ENTITIES
+IntegerLiteral = 'integer'
+NonPositiveIntegerLiteral = 'nonPositiveInteger'
+NegativeIntegerLiteral = 'negativeInteger'
+LongLiteral = 'long'
+IntLiteral = 'int'
+ShortLiteral = 'short'
+ByteLiteral = 'byte'
+NonNegativeIntegerLiteral = 'nonNegativeInteger'
+UnsignedLongLiteral = 'unsignedLong'
+UnsignedIntLiteral = 'unsignedInt'
+UnsignedShortLiteral = 'unsignedShort'
+UnsignedByteLiteral = 'unsignedByte'
+PositiveIntegerLiteral = 'positiveInteger'
+
+AttrTypeName = QName.new(InstanceNamespace, AttrType)
+AttrNilName = QName.new(InstanceNamespace, NilLiteral)
+
+AnyTypeName = QName.new(Namespace, AnyTypeLiteral)
+AnySimpleTypeName = QName.new(Namespace, AnySimpleTypeLiteral)
+
+class Error < StandardError; end
+class ValueSpaceError < Error; end
+
+
+###
+## The base class of all datatypes with Namespace.
+#
+class NSDBase
+  @@types = []
+
+  attr_accessor :type
+
+  def self.inherited(klass)
+    @@types << klass
+  end
+
+  def self.types
+    @@types
+  end
+
+  def initialize
+  end
+
+  def init(type)
+    @type = type
+  end
+end
+
+
+###
+## The base class of XSD datatypes.
+#
+class XSDAnySimpleType < NSDBase
+  include XSD
+  Type = QName.new(Namespace, AnySimpleTypeLiteral)
+
+  # @data represents canonical space (ex. Integer: 123).
+  attr_reader :data
+  # @is_nil represents this data is nil or not.
+  attr_accessor :is_nil
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+  # true or raise
+  def check_lexical_format(value)
+    screen_data(value)
+    true
+  end
+
+  # set accepts a string which follows lexical space (ex. String: "+123"), or
+  # an object which follows canonical space (ex. Integer: 123).
+  def set(value)
+    if value.nil?
+      @is_nil = true
+      @data = nil
+      _set(nil)
+    else
+      @is_nil = false
+      _set(screen_data(value))
+    end
+  end
+
+  # to_s creates a string which follows lexical space (ex. String: "123").
+  def to_s()
+    if @is_nil
+      ""
+    else
+      _to_s
+    end
+  end
+
+private
+
+  def init(type, value)
+    super(type)
+    set(value)
+  end
+
+  # raises ValueSpaceError if check failed
+  def screen_data(value)
+    value
+  end
+
+  def _set(value)
+    @data = value
+  end
+
+  def _to_s
+    @data.to_s
+  end
+end
+
+class XSDNil < XSDAnySimpleType
+  Type = QName.new(Namespace, NilLiteral)
+  Value = 'true'
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+end
+
+
+###
+## Primitive datatypes.
+#
+class XSDString < XSDAnySimpleType
+  Type = QName.new(Namespace, StringLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data(value)
+    unless XSD::Charset.is_ces(value, XSD::Charset.encoding)
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.")
+    end
+    value
+  end
+end
+
+class XSDBoolean < XSDAnySimpleType
+  Type = QName.new(Namespace, BooleanLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data(value)
+    if value.is_a?(String)
+      str = value.strip
+      if str == 'true' || str == '1'
+	true
+      elsif str == 'false' || str == '0'
+	false
+      else
+	raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.")
+      end
+    else
+      value ? true : false
+    end
+  end
+end
+
+class XSDDecimal < XSDAnySimpleType
+  Type = QName.new(Namespace, DecimalLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+  def nonzero?
+    (@number != '0')
+  end
+
+private
+
+  def screen_data(d)
+    if d.is_a?(String)
+      # Integer("00012") => 10 in Ruby.
+      d.sub!(/^([+\-]?)0*(?=\d)/, "\\1")
+    end
+    screen_data_str(d)
+  end
+
+  def screen_data_str(str)
+    /^([+\-]?)(\d*)(?:\.(\d*)?)?$/ =~ str.to_s.strip
+    unless Regexp.last_match
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.")
+    end
+    sign = $1 || '+'
+    int_part = $2
+    frac_part = $3
+    int_part = '0' if int_part.empty?
+    frac_part = frac_part ? frac_part.sub(/0+$/, '') : ''
+    point = - frac_part.size
+    number = int_part + frac_part
+    # normalize
+    if sign == '+'
+      sign = ''
+    elsif sign == '-'
+      if number == '0'
+	sign = ''
+      end
+    end
+    [sign, point, number]
+  end
+
+  def _set(data)
+    if data.nil?
+      @sign = @point = @number = @data = nil
+      return
+    end
+    @sign, @point, @number = data
+    @data = _to_s
+    @data.freeze
+  end
+
+  # 0.0 -> 0; right?
+  def _to_s
+    str = @number.dup
+    if @point.nonzero?
+      str[@number.size + @point, 0] = '.'
+    end
+    @sign + str
+  end
+end
+
+module FloatConstants
+  NaN = 0.0/0.0
+  POSITIVE_INF = +1.0/0.0
+  NEGATIVE_INF = -1.0/0.0
+  POSITIVE_ZERO = +1.0/POSITIVE_INF
+  NEGATIVE_ZERO = -1.0/POSITIVE_INF
+  MIN_POSITIVE_SINGLE = 2.0 ** -149
+end
+
+class XSDFloat < XSDAnySimpleType
+  include FloatConstants
+  Type = QName.new(Namespace, FloatLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data(value)
+    # "NaN".to_f => 0 in some environment.  libc?
+    if value.is_a?(Float)
+      return narrow32bit(value)
+    end
+    str = value.to_s.strip
+    if str == 'NaN'
+      NaN
+    elsif str == 'INF'
+      POSITIVE_INF
+    elsif str == '-INF'
+      NEGATIVE_INF
+    else
+      if /^[+\-\.\deE]+$/ !~ str
+	raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.")
+      end
+      # Float("-1.4E") might fail on some system.
+      str << '0' if /e$/i =~ str
+      begin
+  	return narrow32bit(Float(str))
+      rescue ArgumentError
+  	raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.")
+      end
+    end
+  end
+
+  def _to_s
+    if @data.nan?
+      'NaN'
+    elsif @data.infinite? == 1
+      'INF'
+    elsif @data.infinite? == -1
+      '-INF'
+    else
+      sign = XSDFloat.positive?(@data) ? '+' : '-'
+      sign + sprintf("%.10g", @data.abs).sub(/[eE]([+-])?0+/) { 'e' + $1 }
+    end
+  end
+
+  # Convert to single-precision 32-bit floating point value.
+  def narrow32bit(f)
+    if f.nan? || f.infinite?
+      f
+    elsif f.abs < MIN_POSITIVE_SINGLE
+      XSDFloat.positive?(f) ? POSITIVE_ZERO : NEGATIVE_ZERO
+    else
+      f
+    end
+  end
+
+  def self.positive?(value)
+    (1 / value) > 0.0
+  end
+end
+
+# Ruby's Float is double-precision 64-bit floating point value.
+class XSDDouble < XSDAnySimpleType
+  include FloatConstants
+  Type = QName.new(Namespace, DoubleLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data(value)
+    # "NaN".to_f => 0 in some environment.  libc?
+    if value.is_a?(Float)
+      return value
+    end
+    str = value.to_s.strip
+    if str == 'NaN'
+      NaN
+    elsif str == 'INF'
+      POSITIVE_INF
+    elsif str == '-INF'
+      NEGATIVE_INF
+    else
+      begin
+	return Float(str)
+      rescue ArgumentError
+	# '1.4e' cannot be parsed on some architecture.
+	if /e\z/i =~ str
+	  begin
+	    return Float(str + '0')
+	  rescue ArgumentError
+	    raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.")
+	  end
+	else
+	  raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.")
+	end
+      end
+    end
+  end
+
+  def _to_s
+    if @data.nan?
+      'NaN'
+    elsif @data.infinite? == 1
+      'INF'
+    elsif @data.infinite? == -1
+      '-INF'
+    else
+      sign = (1 / @data > 0.0) ? '+' : '-'
+      sign + sprintf("%.16g", @data.abs).sub(/[eE]([+-])?0+/) { 'e' + $1 }
+    end
+  end
+end
+
+class XSDDuration < XSDAnySimpleType
+  Type = QName.new(Namespace, DurationLiteral)
+
+  attr_accessor :sign
+  attr_accessor :year
+  attr_accessor :month
+  attr_accessor :day
+  attr_accessor :hour
+  attr_accessor :min
+  attr_accessor :sec
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data(value)
+    /^([+\-]?)P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/ =~ value.to_s.strip
+    unless Regexp.last_match
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.")
+    end
+    if ($5 and ((!$2 and !$3 and !$4) or (!$6 and !$7 and !$8)))
+      # Should we allow 'PT5S' here?
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.")
+    end
+    sign = $1
+    year = $2.to_i
+    month = $3.to_i
+    day = $4.to_i
+    hour = $6.to_i
+    min = $7.to_i
+    sec = $8 ? XSDDecimal.new($8) : 0
+    [sign, year, month, day, hour, min, sec]
+  end
+
+  def _set(data)
+    if data.nil?
+      @sign = @year = @month = @day = @hour = @min = @sec = @data = nil
+      return
+    end
+    @sign, @year, @month, @day, @hour, @min, @sec = data
+    @data = _to_s
+    @data.freeze
+  end
+
+  def _to_s
+    str = ''
+    str << @sign if @sign
+    str << 'P'
+    l = ''
+    l << "#{ @year }Y" if @year.nonzero?
+    l << "#{ @month }M" if @month.nonzero?
+    l << "#{ @day }D" if @day.nonzero?
+    r = ''
+    r << "#{ @hour }H" if @hour.nonzero?
+    r << "#{ @min }M" if @min.nonzero?
+    r << "#{ @sec }S" if @sec.nonzero?
+    str << l
+    if l.empty?
+      str << "0D"
+    end
+    unless r.empty?
+      str << "T" << r
+    end
+    str
+  end
+end
+
+
+require 'rational'
+require 'date'
+
+module XSDDateTimeImpl
+  SecInDay = 86400	# 24 * 60 * 60
+
+  def to_obj(klass)
+    if klass == Time
+      to_time
+    elsif klass == Date
+      to_date
+    elsif klass == DateTime
+      to_datetime
+    else
+      nil
+    end
+  end
+
+  def to_time
+    begin
+      if @data.offset * SecInDay == Time.now.utc_offset
+        d = @data
+	usec = (d.sec_fraction * SecInDay * 1000000).round
+        Time.local(d.year, d.month, d.mday, d.hour, d.min, d.sec, usec)
+      else
+        d = @data.newof
+	usec = (d.sec_fraction * SecInDay * 1000000).round
+        Time.gm(d.year, d.month, d.mday, d.hour, d.min, d.sec, usec)
+      end
+    rescue ArgumentError
+      nil
+    end
+  end
+
+  def to_date
+    Date.new0(@data.class.jd_to_ajd(@data.jd, 0, 0), 0, @data.start)
+  end
+
+  def to_datetime
+    data
+  end
+
+  def tz2of(str)
+    /^(?:Z|(?:([+\-])(\d\d):(\d\d))?)$/ =~ str
+    sign = $1
+    hour = $2.to_i
+    min = $3.to_i
+
+    of = case sign
+      when '+'
+	of = +(hour.to_r * 60 + min) / 1440	# 24 * 60
+      when '-'
+	of = -(hour.to_r * 60 + min) / 1440	# 24 * 60
+      else
+	0
+      end
+    of
+  end
+
+  def of2tz(offset)
+    diffmin = offset * 24 * 60
+    if diffmin.zero?
+      'Z'
+    else
+      ((diffmin < 0) ? '-' : '+') << format('%02d:%02d',
+    	(diffmin.abs / 60.0).to_i, (diffmin.abs % 60.0).to_i)
+    end
+  end
+
+  def screen_data(t)
+    # convert t to a DateTime as an internal representation.
+    if t.respond_to?(:to_datetime)      # 1.9 or later
+      t.to_datetime
+    elsif t.is_a?(DateTime)
+      t
+    elsif t.is_a?(Date)
+      t = screen_data_str(t)
+      t <<= 12 if t.year < 0
+      t
+    elsif t.is_a?(Time)
+      jd = DateTime.civil_to_jd(t.year, t.mon, t.mday, DateTime::ITALY)
+      fr = DateTime.time_to_day_fraction(t.hour, t.min, [t.sec, 59].min) +
+        t.usec.to_r / 1000000 / SecInDay
+      of = t.utc_offset.to_r / SecInDay
+      DateTime.new0(DateTime.jd_to_ajd(jd, fr, of), of, DateTime::ITALY)
+    else
+      screen_data_str(t)
+    end
+  end
+
+  def add_tz(s)
+    s + of2tz(@data.offset)
+  end
+end
+
+class XSDDateTime < XSDAnySimpleType
+  include XSDDateTimeImpl
+  Type = QName.new(Namespace, DateTimeLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data_str(t)
+    /^([+\-]?\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d(?:\.(\d*))?)(Z|(?:[+\-]\d\d:\d\d)?)?$/ =~ t.to_s.strip
+    unless Regexp.last_match
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.")
+    end
+    if $1 == '0000'
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.")
+    end
+    year = $1.to_i
+    if year < 0
+      year += 1
+    end
+    mon = $2.to_i
+    mday = $3.to_i
+    hour = $4.to_i
+    min = $5.to_i
+    sec = $6.to_i
+    secfrac = $7
+    zonestr = $8
+    data = DateTime.civil(year, mon, mday, hour, min, sec, tz2of(zonestr))
+    if secfrac
+      diffday = secfrac.to_i.to_r / (10 ** secfrac.size) / SecInDay
+      data += diffday
+      # FYI: new0 and jd_to_rjd are not necessary to use if you don't have
+      # exceptional reason.
+    end
+    [data, secfrac]
+  end
+
+  def _set(data)
+    if data.nil?
+      @data = @secfrac = nil
+      return
+    end
+    @data, @secfrac = data
+  end
+
+  def _to_s
+    year = (@data.year > 0) ? @data.year : @data.year - 1
+    s = format('%.4d-%02d-%02dT%02d:%02d:%02d',
+      year, @data.mon, @data.mday, @data.hour, @data.min, @data.sec)
+    if @data.sec_fraction.nonzero?
+      if @secfrac
+  	s << ".#{ @secfrac }"
+      else
+	s << sprintf("%.16f",
+          (@data.sec_fraction * SecInDay).to_f).sub(/^0/, '').sub(/0*$/, '')
+      end
+    end
+    add_tz(s)
+  end
+end
+
+class XSDTime < XSDAnySimpleType
+  include XSDDateTimeImpl
+  Type = QName.new(Namespace, TimeLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data_str(t)
+    /^(\d\d):(\d\d):(\d\d(?:\.(\d*))?)(Z|(?:([+\-])(\d\d):(\d\d))?)?$/ =~ t.to_s.strip
+    unless Regexp.last_match
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.")
+    end
+    hour = $1.to_i
+    min = $2.to_i
+    sec = $3.to_i
+    secfrac = $4
+    zonestr = $5
+    data = DateTime.civil(1, 1, 1, hour, min, sec, tz2of(zonestr))
+    if secfrac
+      diffday = secfrac.to_i.to_r / (10 ** secfrac.size) / SecInDay
+      data += diffday
+    end
+    [data, secfrac]
+  end
+
+  def _set(data)
+    if data.nil?
+      @data = @secfrac = nil
+      return
+    end
+    @data, @secfrac = data
+  end
+
+  def _to_s
+    s = format('%02d:%02d:%02d', @data.hour, @data.min, @data.sec)
+    if @data.sec_fraction.nonzero?
+      if @secfrac
+  	s << ".#{ @secfrac }"
+      else
+	s << sprintf("%.16f",
+          (@data.sec_fraction * SecInDay).to_f).sub(/^0/, '').sub(/0*$/, '')
+      end
+    end
+    add_tz(s)
+  end
+end
+
+class XSDDate < XSDAnySimpleType
+  include XSDDateTimeImpl
+  Type = QName.new(Namespace, DateLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data_str(t)
+    /^([+\-]?\d{4,})-(\d\d)-(\d\d)(Z|(?:([+\-])(\d\d):(\d\d))?)?$/ =~ t.to_s.strip
+    unless Regexp.last_match
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.")
+    end
+    year = $1.to_i
+    if year < 0
+      year += 1
+    end
+    mon = $2.to_i
+    mday = $3.to_i
+    zonestr = $4
+    DateTime.civil(year, mon, mday, 0, 0, 0, tz2of(zonestr))
+  end
+
+  def _to_s
+    year = (@data.year > 0) ? @data.year : @data.year - 1
+    s = format('%.4d-%02d-%02d', year, @data.mon, @data.mday)
+    add_tz(s)
+  end
+end
+
+class XSDGYearMonth < XSDAnySimpleType
+  include XSDDateTimeImpl
+  Type = QName.new(Namespace, GYearMonthLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data_str(t)
+    /^([+\-]?\d{4,})-(\d\d)(Z|(?:([+\-])(\d\d):(\d\d))?)?$/ =~ t.to_s.strip
+    unless Regexp.last_match
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.")
+    end
+    year = $1.to_i
+    if year < 0
+      year += 1
+    end
+    mon = $2.to_i
+    zonestr = $3
+    DateTime.civil(year, mon, 1, 0, 0, 0, tz2of(zonestr))
+  end
+
+  def _to_s
+    year = (@data.year > 0) ? @data.year : @data.year - 1
+    s = format('%.4d-%02d', year, @data.mon)
+    add_tz(s)
+  end
+end
+
+class XSDGYear < XSDAnySimpleType
+  include XSDDateTimeImpl
+  Type = QName.new(Namespace, GYearLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data_str(t)
+    /^([+\-]?\d{4,})(Z|(?:([+\-])(\d\d):(\d\d))?)?$/ =~ t.to_s.strip
+    unless Regexp.last_match
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.")
+    end
+    year = $1.to_i
+    if year < 0
+      year += 1
+    end
+    zonestr = $2
+    DateTime.civil(year, 1, 1, 0, 0, 0, tz2of(zonestr))
+  end
+
+  def _to_s
+    year = (@data.year > 0) ? @data.year : @data.year - 1
+    s = format('%.4d', year)
+    add_tz(s)
+  end
+end
+
+class XSDGMonthDay < XSDAnySimpleType
+  include XSDDateTimeImpl
+  Type = QName.new(Namespace, GMonthDayLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data_str(t)
+    /^(\d\d)-(\d\d)(Z|(?:[+\-]\d\d:\d\d)?)?$/ =~ t.to_s.strip
+    unless Regexp.last_match
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.")
+    end
+    mon = $1.to_i
+    mday = $2.to_i
+    zonestr = $3
+    DateTime.civil(1, mon, mday, 0, 0, 0, tz2of(zonestr))
+  end
+
+  def _to_s
+    s = format('%02d-%02d', @data.mon, @data.mday)
+    add_tz(s)
+  end
+end
+
+class XSDGDay < XSDAnySimpleType
+  include XSDDateTimeImpl
+  Type = QName.new(Namespace, GDayLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data_str(t)
+    /^(\d\d)(Z|(?:[+\-]\d\d:\d\d)?)?$/ =~ t.to_s.strip
+    unless Regexp.last_match
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.")
+    end
+    mday = $1.to_i
+    zonestr = $2
+    DateTime.civil(1, 1, mday, 0, 0, 0, tz2of(zonestr))
+  end
+
+  def _to_s
+    s = format('%02d', @data.mday)
+    add_tz(s)
+  end
+end
+
+class XSDGMonth < XSDAnySimpleType
+  include XSDDateTimeImpl
+  Type = QName.new(Namespace, GMonthLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data_str(t)
+    /^(\d\d)(Z|(?:[+\-]\d\d:\d\d)?)?$/ =~ t.to_s.strip
+    unless Regexp.last_match
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.")
+    end
+    mon = $1.to_i
+    zonestr = $2
+    DateTime.civil(1, mon, 1, 0, 0, 0, tz2of(zonestr))
+  end
+
+  def _to_s
+    s = format('%02d', @data.mon)
+    add_tz(s)
+  end
+end
+
+class XSDHexBinary < XSDAnySimpleType
+  Type = QName.new(Namespace, HexBinaryLiteral)
+
+  # String in Ruby could be a binary.
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+  def set_encoded(value)
+    if /^[0-9a-fA-F]*$/ !~ value
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.")
+    end
+    @data = String.new(value).strip
+    @is_nil = false
+  end
+
+  def string
+    [@data].pack("H*")
+  end
+
+private
+
+  def screen_data(value)
+    value.unpack("H*")[0].tr('a-f', 'A-F')
+  end
+end
+
+class XSDBase64Binary < XSDAnySimpleType
+  Type = QName.new(Namespace, Base64BinaryLiteral)
+
+  # String in Ruby could be a binary.
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+  def set_encoded(value)
+    if /^[A-Za-z0-9+\/=]*$/ !~ value
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.")
+    end
+    @data = String.new(value).strip
+    @is_nil = false
+  end
+
+  def string
+    @data.unpack("m")[0]
+  end
+
+private
+
+  def screen_data(value)
+    [value].pack("m").strip
+  end
+end
+
+class XSDAnyURI < XSDAnySimpleType
+  Type = QName.new(Namespace, AnyURILiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data(value)
+    begin
+      URI.parse(value.to_s.strip)
+    rescue URI::InvalidURIError
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.")
+    end
+  end
+end
+
+class XSDQName < XSDAnySimpleType
+  Type = QName.new(Namespace, QNameLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data(value)
+    /^(?:([^:]+):)?([^:]+)$/ =~ value.to_s.strip
+    unless Regexp.last_match
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.")
+    end
+    prefix = $1
+    localpart = $2
+    [prefix, localpart]
+  end
+
+  def _set(data)
+    if data.nil?
+      @prefix = @localpart = @data = nil
+      return
+    end
+    @prefix, @localpart = data
+    @data = _to_s
+    @data.freeze
+  end
+
+  def _to_s
+    if @prefix
+      "#{ @prefix }:#{ @localpart }"
+    else
+      "#{ @localpart }"
+    end
+  end
+end
+
+
+###
+## Derived types
+#
+class XSDNormalizedString < XSDString
+  Type = QName.new(Namespace, NormalizedStringLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data(value)
+    if /[\t\r\n]/ =~ value
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.")
+    end
+    super
+  end
+end
+
+class XSDInteger < XSDDecimal
+  Type = QName.new(Namespace, IntegerLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def screen_data_str(str)
+    begin
+      data = Integer(str)
+    rescue ArgumentError
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.")
+    end
+    unless validate(data)
+      raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.")
+    end
+    data
+  end
+
+  def _set(value)
+    @data = value
+  end
+
+  def _to_s()
+    @data.to_s
+  end
+
+  def validate(v)
+    max = maxinclusive
+    min = mininclusive
+    (max.nil? or v <= max) and (min.nil? or v >= min)
+  end
+
+  def maxinclusive
+    nil
+  end
+
+  def mininclusive
+    nil
+  end
+
+  PositiveMinInclusive = 1
+  def positive(v)
+    PositiveMinInclusive <= v
+  end
+end
+
+class XSDNonPositiveInteger < XSDInteger
+  Type = QName.new(Namespace, NonPositiveIntegerLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def maxinclusive
+    0
+  end
+
+  def mininclusive
+    nil
+  end
+end
+
+class XSDNegativeInteger < XSDNonPositiveInteger
+  Type = QName.new(Namespace, NegativeIntegerLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def maxinclusive
+    -1
+  end
+
+  def mininclusive
+    nil
+  end
+end
+
+class XSDLong < XSDInteger
+  Type = QName.new(Namespace, LongLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def maxinclusive
+    +9223372036854775807
+  end
+
+  def mininclusive
+    -9223372036854775808
+  end
+end
+
+class XSDInt < XSDLong
+  Type = QName.new(Namespace, IntLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def maxinclusive
+    +2147483647
+  end
+
+  def mininclusive
+    -2147483648
+  end
+end
+
+class XSDShort < XSDInt
+  Type = QName.new(Namespace, ShortLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def maxinclusive
+    +32767
+  end
+
+  def mininclusive
+    -32768
+  end
+end
+
+class XSDByte < XSDShort
+  Type = QName.new(Namespace, ByteLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def maxinclusive
+    +127
+  end
+
+  def mininclusive
+    -128
+  end
+end
+
+class XSDNonNegativeInteger < XSDInteger
+  Type = QName.new(Namespace, NonNegativeIntegerLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def maxinclusive
+    nil
+  end
+
+  def mininclusive
+    0
+  end
+end
+
+class XSDUnsignedLong < XSDNonNegativeInteger
+  Type = QName.new(Namespace, UnsignedLongLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def maxinclusive
+    +18446744073709551615
+  end
+
+  def mininclusive
+    0
+  end
+end
+
+class XSDUnsignedInt < XSDUnsignedLong
+  Type = QName.new(Namespace, UnsignedIntLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def maxinclusive
+    +4294967295
+  end
+
+  def mininclusive
+    0
+  end
+end
+
+class XSDUnsignedShort < XSDUnsignedInt
+  Type = QName.new(Namespace, UnsignedShortLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def maxinclusive
+    +65535
+  end
+
+  def mininclusive
+    0
+  end
+end
+
+class XSDUnsignedByte < XSDUnsignedShort
+  Type = QName.new(Namespace, UnsignedByteLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def maxinclusive
+    +255
+  end
+
+  def mininclusive
+    0
+  end
+end
+
+class XSDPositiveInteger < XSDNonNegativeInteger
+  Type = QName.new(Namespace, PositiveIntegerLiteral)
+
+  def initialize(value = nil)
+    init(Type, value)
+  end
+
+private
+
+  def maxinclusive
+    nil
+  end
+
+  def mininclusive
+    1
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/datatypes1999.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/datatypes1999.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/datatypes1999.rb	(revision 18425)
@@ -0,0 +1,20 @@
+# XSD4R - XML Schema Datatype 1999 support
+# Copyright (C) 2001, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/datatypes'
+
+
+module XSD
+  Namespace.replace('http://www.w3.org/1999/XMLSchema')
+  InstanceNamespace.replace('http://www.w3.org/1999/XMLSchema-instance')
+  AnyTypeLiteral.replace('ur-type')
+  AnySimpleTypeLiteral.replace('ur-type')
+  NilLiteral.replace('null')
+  NilValue.replace('1')
+  DateTimeLiteral.replace('timeInstant')
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/iconvcharset.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/iconvcharset.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/iconvcharset.rb	(revision 18425)
@@ -0,0 +1,33 @@
+# XSD4R - Charset handling with iconv.
+# Copyright (C) 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'iconv'
+
+
+module XSD
+
+
+class IconvCharset
+  def self.safe_iconv(to, from, str)
+    iconv = Iconv.new(to, from)
+    out = ""
+    begin
+      out << iconv.iconv(str)
+    rescue Iconv::IllegalSequence => e
+      out << e.success
+      ch, str = e.failed.split(//, 2)
+      out << '?'
+      warn("Failed to convert #{ch}")
+      retry
+    end
+    return out
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/mapping.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/mapping.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/mapping.rb	(revision 18425)
@@ -0,0 +1,42 @@
+# XSD4R - XML Mapping for Ruby
+# Copyright (C) 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require "soap/parser"
+require 'soap/encodingstyle/literalHandler'
+require "soap/generator"
+require "soap/mapping"
+require "soap/mapping/wsdlliteralregistry"
+
+
+module XSD
+
+
+module Mapping
+  MappingRegistry = SOAP::Mapping::WSDLLiteralRegistry.new
+  MappingOpt = {:default_encodingstyle => SOAP::LiteralNamespace}
+
+  def self.obj2xml(obj, elename = nil, io = nil)
+    if !elename.nil? and !elename.is_a?(XSD::QName)
+      elename = XSD::QName.new(nil, elename)
+    end
+    elename ||= XSD::QName.new(nil, SOAP::Mapping.name2elename(obj.class.to_s))
+    soap = SOAP::Mapping.obj2soap(obj, MappingRegistry)
+    soap.elename = elename
+    generator = SOAP::SOAPGenerator.new(MappingOpt)
+    generator.generate(soap, io)
+  end
+
+  def self.xml2obj(stream)
+    parser = SOAP::Parser.new(MappingOpt)
+    soap = parser.parse(stream)
+    SOAP::Mapping.soap2obj(soap, MappingRegistry)
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/namedelements.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/namedelements.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/namedelements.rb	(revision 18425)
@@ -0,0 +1,95 @@
+# XSD4R - WSDL named element collection.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+module XSD
+
+
+class NamedElements
+  include Enumerable
+
+  def initialize
+    @elements = []
+    @cache = {}
+  end
+
+  def dup
+    o = NamedElements.new
+    o.elements = @elements.dup
+    o
+  end
+
+  def freeze
+    super
+    @elements.freeze
+    self
+  end
+
+  def empty?
+    size == 0
+  end
+
+  def size
+    @elements.size
+  end
+
+  def [](idx)
+    if idx.is_a?(Numeric)
+      @elements[idx]
+    else
+      @cache[idx] ||= @elements.find { |item| item.name == idx }
+    end
+  end
+
+  def find_name(name)
+    @elements.find { |item| item.name.name == name }
+  end
+
+  def keys
+    collect { |element| element.name }
+  end
+
+  def each
+    @elements.each do |element|
+      yield(element)
+    end
+  end
+
+  def <<(rhs)
+    @elements << rhs
+    self
+  end
+  
+  def delete(rhs)
+    @elements.delete(rhs)
+  end
+
+  def +(rhs)
+    o = NamedElements.new
+    o.elements = @elements + rhs.elements
+    o
+  end
+
+  def concat(rhs)
+    @elements.concat(rhs.elements)
+    self
+  end
+
+  Empty = NamedElements.new.freeze
+
+protected
+
+  def elements=(rhs)
+    @elements = rhs
+  end
+
+  def elements
+    @elements
+  end
+end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/ns.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/ns.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/ns.rb	(revision 18425)
@@ -0,0 +1,140 @@
+# XSD4R - XML Schema Namespace library
+# Copyright (C) 2000-2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/datatypes'
+
+
+module XSD
+
+
+class NS
+  class Assigner
+    def initialize
+      @count = 0
+    end
+
+    def assign(ns)
+      @count += 1
+      "n#{@count}"
+    end
+  end
+
+  attr_reader :default_namespace
+
+  class FormatError < Error; end
+
+public
+
+  def initialize(tag2ns = {})
+    @tag2ns = tag2ns
+    @assigner = nil
+    @ns2tag = {}
+    @tag2ns.each do |tag, ns|
+      @ns2tag[ns] = tag
+    end
+    @default_namespace = nil
+  end
+
+  def assign(ns, tag = nil)
+    if (tag == '')
+      @default_namespace = ns
+      tag
+    else
+      @assigner ||= Assigner.new
+      tag ||= @assigner.assign(ns)
+      @ns2tag[ns] = tag
+      @tag2ns[tag] = ns
+      tag
+    end
+  end
+
+  def assigned?(ns)
+    @default_namespace == ns or @ns2tag.key?(ns)
+  end
+
+  def assigned_tag?(tag)
+    @tag2ns.key?(tag)
+  end
+
+  def clone_ns
+    cloned = NS.new(@tag2ns.dup)
+    cloned.assigner = @assigner
+    cloned.assign(@default_namespace, '') if @default_namespace
+    cloned
+  end
+
+  def name(name)
+    if (name.namespace == @default_namespace)
+      name.name
+    elsif @ns2tag.key?(name.namespace)
+      "#{@ns2tag[name.namespace]}:#{name.name}"
+    else
+      raise FormatError.new("namespace: #{name.namespace} not defined yet")
+    end
+  end
+
+  def compare(ns, name, rhs)
+    if (ns == @default_namespace)
+      return true if (name == rhs)
+    end
+    @tag2ns.each do |assigned_tag, assigned_ns|
+      if assigned_ns == ns && "#{assigned_tag}:#{name}" == rhs
+	return true
+      end
+    end
+    false
+  end
+
+  # $1 and $2 are necessary.
+  ParseRegexp = Regexp.new('^([^:]+)(?::(.+))?$')
+
+  def parse(str, local = false)
+    if ParseRegexp =~ str
+      if (name = $2) and (ns = @tag2ns[$1])
+        return XSD::QName.new(ns, name)
+      end
+    end
+    XSD::QName.new(local ? nil : @default_namespace, str)
+  end
+
+  # For local attribute key parsing
+  #   <foo xmlns="urn:a" xmlns:n1="urn:a" bar="1" n1:baz="2" />
+  #     =>
+  #   {}bar, {urn:a}baz
+  def parse_local(elem)
+    ParseRegexp =~ elem
+    if $2
+      ns = @tag2ns[$1]
+      name = $2
+      if !ns
+	raise FormatError.new("unknown namespace qualifier: #{$1}")
+      end
+    elsif $1
+      ns = nil
+      name = $1
+    else
+      raise FormatError.new("illegal element format: #{elem}")
+    end
+    XSD::QName.new(ns, name)
+  end
+
+  def each_ns
+    @ns2tag.each do |ns, tag|
+      yield(ns, tag)
+    end
+  end
+
+protected
+
+  def assigner=(assigner)
+    @assigner = assigner
+  end
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/qname.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/qname.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/qname.rb	(revision 18425)
@@ -0,0 +1,78 @@
+# XSD4R - XML QName definition.
+# Copyright (C) 2002, 2003, 2004  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+module XSD
+
+
+class QName
+  attr_accessor :namespace
+  attr_accessor :name
+  attr_accessor :source
+
+  def initialize(namespace = nil, name = nil)
+    @namespace = namespace
+    @name = name
+    @source = nil
+  end
+
+  def dup_name(name)
+    XSD::QName.new(@namespace, name)
+  end
+
+  def dump
+    ns = @namespace.nil? ? 'nil' : @namespace.dump
+    name = @name.nil? ? 'nil' : @name.dump
+    "XSD::QName.new(#{ns}, #{name})"
+  end
+
+  def match(rhs)
+    if rhs.namespace and (rhs.namespace != @namespace)
+      return false
+    end
+    if rhs.name and (rhs.name != @name)
+      return false
+    end
+    true
+  end
+
+  def ==(rhs)
+    !rhs.nil? and @namespace == rhs.namespace and @name == rhs.name
+  end
+
+  def ===(rhs)
+    (self == rhs)
+  end
+
+  def eql?(rhs)
+    (self == rhs)
+  end
+
+  def hash
+    @namespace.hash ^ @name.hash
+  end
+  
+  def to_s
+    "{#{ namespace }}#{ name }"
+  end
+
+  def inspect
+    sprintf("#<%s:0x%x %s>", self.class.name, __id__,
+      "{#{ namespace }}#{ name }")
+  end
+
+  NormalizedNameRegexp = /^\{([^}]*)\}(.*)$/
+  def parse(str)
+    NormalizedNameRegexp =~ str
+    self.new($1, $2)
+  end
+
+  EMPTY = QName.new.freeze
+end
+
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser.rb	(revision 18425)
@@ -0,0 +1,61 @@
+# XSD4R - XML Instance parser library.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/xmlparser/parser'
+
+
+module XSD
+
+
+module XMLParser
+  def create_parser(host, opt)
+    XSD::XMLParser::Parser.create_parser(host, opt)
+  end
+  module_function :create_parser
+
+  # $1 is necessary.
+  NSParseRegexp = Regexp.new('^xmlns:?(.*)$')
+
+  def filter_ns(ns, attrs)
+    return attrs if attrs.nil? or attrs.empty?
+    newattrs = {}
+    attrs.each do |key, value|
+      if (NSParseRegexp =~ key)
+	# '' means 'default namespace'.
+	tag = $1 || ''
+	ns.assign(value, tag)
+      else
+	newattrs[key] = value
+      end
+    end
+    newattrs
+  end
+  module_function :filter_ns
+end
+
+
+end
+
+
+# Try to load XML processor.
+loaded = false
+[
+  'xsd/xmlparser/xmlparser',
+  'xsd/xmlparser/xmlscanner',
+  'xsd/xmlparser/rexmlparser',
+].each do |lib|
+  begin
+    require lib
+    loaded = true
+    break
+  rescue LoadError
+  end
+end
+unless loaded
+  raise RuntimeError.new("XML processor module not found.")
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser/parser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser/parser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser/parser.rb	(revision 18425)
@@ -0,0 +1,96 @@
+# XSD4R - XML Instance parser library.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/qname'
+require 'xsd/ns'
+require 'xsd/charset'
+
+
+module XSD
+module XMLParser
+
+
+class Parser
+  class ParseError < Error; end
+  class FormatDecodeError < ParseError; end
+  class UnknownElementError < FormatDecodeError; end
+  class UnknownAttributeError < FormatDecodeError; end
+  class UnexpectedElementError < FormatDecodeError; end
+  class ElementConstraintError < FormatDecodeError; end
+
+  @@parser_factory = nil
+
+  def self.factory
+    @@parser_factory
+  end
+
+  def self.create_parser(host, opt = {})
+    @@parser_factory.new(host, opt)
+  end
+
+  def self.add_factory(factory)
+    if $DEBUG
+      puts "Set #{ factory } as XML processor."
+    end
+    @@parser_factory = factory
+  end
+
+public
+
+  attr_accessor :charset
+
+  def initialize(host, opt = {})
+    @host = host
+    @charset = opt[:charset] || nil
+  end
+
+  def parse(string_or_readable)
+    @textbuf = ''
+    prologue
+    do_parse(string_or_readable)
+    epilogue
+  end
+
+private
+
+  def do_parse(string_or_readable)
+    raise NotImplementError.new(
+      'Method do_parse must be defined in derived class.')
+  end
+
+  def start_element(name, attrs)
+    @host.start_element(name, attrs)
+  end
+
+  def characters(text)
+    @host.characters(text)
+  end
+
+  def end_element(name)
+    @host.end_element(name)
+  end
+
+  def prologue
+  end
+
+  def epilogue
+  end
+
+  def xmldecl_encoding=(charset)
+    if @charset.nil?
+      @charset = charset
+    else
+      # Definition in a stream (like HTTP) has a priority.
+      p "encoding definition: #{ charset } is ignored." if $DEBUG
+    end
+  end
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser/rexmlparser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser/rexmlparser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser/rexmlparser.rb	(revision 18425)
@@ -0,0 +1,54 @@
+# XSD4R - REXMLParser XML parser library.
+# Copyright (C) 2002, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/xmlparser'
+require 'rexml/streamlistener'
+require 'rexml/document'
+
+
+module XSD
+module XMLParser
+
+
+class REXMLParser < XSD::XMLParser::Parser
+  include REXML::StreamListener
+
+  def do_parse(string_or_readable)
+    source = nil
+    source = REXML::SourceFactory.create_from(string_or_readable)
+    source.encoding = charset if charset
+    # Listener passes a String in utf-8.
+    @charset = 'utf-8'
+    REXML::Document.parse_stream(source, self)
+  end
+
+  def epilogue
+  end
+
+  def tag_start(name, attrs)
+    start_element(name, attrs)
+  end
+
+  def tag_end(name)
+    end_element(name)
+  end
+
+  def text(text)
+    characters(text)
+  end
+
+  def xmldecl(version, encoding, standalone)
+    # Version should be checked.
+  end
+
+  add_factory(self)
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser/xmlparser.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser/xmlparser.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser/xmlparser.rb	(revision 18425)
@@ -0,0 +1,50 @@
+# XSD4R - XMLParser XML parser library.
+# Copyright (C) 2001, 2003  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/xmlparser'
+require 'xml/parser'
+
+
+module XSD
+module XMLParser
+
+
+class XMLParser < XSD::XMLParser::Parser
+  class Listener < XML::Parser
+    begin
+      require 'xml/encoding-ja'
+      include XML::Encoding_ja
+    rescue LoadError
+      # uconv may not be installed.
+    end
+  end
+
+  def do_parse(string_or_readable)
+    # XMLParser passes a String in utf-8.
+    @charset = 'utf-8'
+    @parser = Listener.new
+    @parser.parse(string_or_readable) do |type, name, data|
+      case type
+      when XML::Parser::START_ELEM
+	start_element(name, data)
+      when XML::Parser::END_ELEM
+	end_element(name)
+      when XML::Parser::CDATA
+	characters(data)
+      else
+	raise FormatDecodeError.new("Unexpected XML: #{ type }/#{ name }/#{ data }.")
+      end
+    end
+  end
+
+  add_factory(self)
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser/xmlscanner.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser/xmlscanner.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/xsd/xmlparser/xmlscanner.rb	(revision 18425)
@@ -0,0 +1,147 @@
+# XSD4R - XMLScan XML parser library.
+# Copyright (C) 2002, 2003, 2005  NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+
+# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
+# redistribute it and/or modify it under the same terms of Ruby's license;
+# either the dual license version in 2003, or any later version.
+
+
+require 'xsd/xmlparser'
+require 'xmlscan/scanner'
+
+
+module XSD
+module XMLParser
+
+
+class XMLScanner < XSD::XMLParser::Parser
+  include XMLScan::Visitor
+
+  def do_parse(string_or_readable)
+    @attrs = {}
+    @curattr = nil
+    @scanner = XMLScan::XMLScanner.new(self)
+    @scanner.kcode = XSD::Charset.charset_str(charset) if charset
+    @scanner.parse(string_or_readable)
+  end
+
+  def scanner_kcode=(charset)
+    @scanner.kcode = XSD::Charset.charset_str(charset) if charset
+    self.xmldecl_encoding = charset
+  end
+
+  ENTITY_REF_MAP = {
+    'lt' => '<',
+    'gt' => '>',
+    'amp' => '&',
+    'quot' => '"',
+    'apos' => '\''
+  }
+
+  def parse_error(msg)
+    raise ParseError.new(msg)
+  end
+
+  def wellformed_error(msg)
+    raise NotWellFormedError.new(msg)
+  end
+
+  def valid_error(msg)
+    raise NotValidError.new(msg)
+  end
+
+  def warning(msg)
+    p msg if $DEBUG
+  end
+
+  # def on_xmldecl; end
+
+  def on_xmldecl_version(str)
+    # 1.0 expected.
+  end
+
+  def on_xmldecl_encoding(str)
+    self.scanner_kcode = str
+  end
+
+  # def on_xmldecl_standalone(str); end
+
+  # def on_xmldecl_other(name, value); end
+
+  # def on_xmldecl_end; end
+
+  # def on_doctype(root, pubid, sysid); end
+
+  # def on_prolog_space(str); end
+
+  # def on_comment(str); end
+
+  # def on_pi(target, pi); end
+
+  def on_chardata(str)
+    characters(str)
+  end
+
+  # def on_cdata(str); end
+
+  def on_etag(name)
+    end_element(name)
+  end
+
+  def on_entityref(ref)
+    characters(ENTITY_REF_MAP[ref])
+  end
+
+  def on_charref(code)
+    characters([code].pack('U'))
+  end
+
+  def on_charref_hex(code)
+    on_charref(code)
+  end
+
+  # def on_start_document; end
+
+  # def on_end_document; end
+
+  def on_stag(name)
+    @attrs = {}
+  end
+
+  def on_attribute(name)
+    @attrs[name] = @curattr = ''
+  end
+
+  def on_attr_value(str)
+    @curattr << str
+  end
+
+  def on_attr_entityref(ref)
+    @curattr << ENTITY_REF_MAP[ref]
+  end
+
+  def on_attr_charref(code)
+    @curattr << [code].pack('U')
+  end
+
+  def on_attr_charref_hex(code)
+    on_attr_charref(code)
+  end
+
+  # def on_attribute_end(name); end
+
+  def on_stag_end_empty(name)
+    on_stag_end(name)
+    on_etag(name)
+  end
+
+  def on_stag_end(name)
+    start_element(name, @attrs)
+  end
+
+  add_factory(self)
+end
+
+
+end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml.rb	(revision 18425)
@@ -0,0 +1,436 @@
+# -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
+# $Id: yaml.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+# = yaml.rb: top-level module with methods for loading and parsing YAML documents
+#
+# Author:: why the lucky stiff
+# 
+
+require 'stringio'
+require 'yaml/error'
+require 'yaml/syck'
+require 'yaml/tag'
+require 'yaml/stream'
+require 'yaml/constants'
+
+# == YAML
+#
+# YAML(tm) (rhymes with 'camel') is a
+# straightforward machine parsable data serialization format designed for
+# human readability and interaction with scripting languages such as Perl
+# and Python. YAML is optimized for data serialization, formatted
+# dumping, configuration files, log files, Internet messaging and
+# filtering. This specification describes the YAML information model and
+# serialization format. Together with the Unicode standard for characters, it
+# provides all the information necessary to understand YAML Version 1.0
+# and construct computer programs to process it.
+#                         
+# See http://yaml.org/ for more information.  For a quick tutorial, please
+# visit YAML In Five Minutes (http://yaml.kwiki.org/?YamlInFiveMinutes).
+#                              
+# == About This Library
+#                         
+# The YAML 1.0 specification outlines four stages of YAML loading and dumping.
+# This library honors all four of those stages, although data is really only
+# available to you in three stages.
+#     
+# The four stages are: native, representation, serialization, and presentation.
+#     
+# The native stage refers to data which has been loaded completely into Ruby's
+# own types. (See +YAML::load+.)
+#
+# The representation stage means data which has been composed into
+# +YAML::BaseNode+ objects.  In this stage, the document is available as a
+# tree of node objects.  You can perform YPath queries and transformations
+# at this level.  (See +YAML::parse+.)
+#   
+# The serialization stage happens inside the parser.  The YAML parser used in
+# Ruby is called Syck.  Serialized nodes are available in the extension as
+# SyckNode structs.
+#       
+# The presentation stage is the YAML document itself.  This is accessible
+# to you as a string.  (See +YAML::dump+.)
+#   
+# For more information about the various information models, see Chapter
+# 3 of the YAML 1.0 Specification (http://yaml.org/spec/#id2491269).
+#
+# The YAML module provides quick access to the most common loading (YAML::load)
+# and dumping (YAML::dump) tasks.  This module also provides an API for registering
+# global types (YAML::add_domain_type).
+#
+# == Example
+#
+# A simple round-trip (load and dump) of an object.
+#
+#     require "yaml"
+#
+#     test_obj = ["dogs", "cats", "badgers"]
+#
+#     yaml_obj = YAML::dump( test_obj )
+#                         # -> ---
+#                              - dogs
+#                              - cats
+#                              - badgers
+#     ruby_obj = YAML::load( yaml_obj )
+#                         # => ["dogs", "cats", "badgers"]
+#     ruby_obj == test_obj
+#                         # => true
+#
+# To register your custom types with the global resolver, use +add_domain_type+.
+#
+#     YAML::add_domain_type( "your-site.com,2004", "widget" ) do |type, val|
+#         Widget.new( val )
+#     end
+#
+module YAML
+
+    Resolver = YAML::Syck::Resolver
+    DefaultResolver = YAML::Syck::DefaultResolver
+    DefaultResolver.use_types_at( @@tagged_classes )
+    GenericResolver = YAML::Syck::GenericResolver
+    Parser = YAML::Syck::Parser
+    Emitter = YAML::Syck::Emitter
+
+    # Returns a new default parser
+    def YAML.parser; Parser.new.set_resolver( YAML.resolver ); end
+    # Returns a new generic parser
+    def YAML.generic_parser; Parser.new.set_resolver( GenericResolver ); end
+    # Returns the default resolver
+    def YAML.resolver; DefaultResolver; end
+    # Returns a new default emitter
+    def YAML.emitter; Emitter.new.set_resolver( YAML.resolver ); end
+
+	#
+	# Converts _obj_ to YAML and writes the YAML result to _io_.
+    #     
+    #   File.open( 'animals.yaml', 'w' ) do |out|
+    #     YAML.dump( ['badger', 'elephant', 'tiger'], out )
+    #   end
+    #
+    # If no _io_ is provided, a string containing the dumped YAML
+    # is returned.
+	#
+    #   YAML.dump( :locked )
+    #      #=> "--- :locked"
+    #
+	def YAML.dump( obj, io = nil )
+        obj.to_yaml( io || io2 = StringIO.new )
+        io || ( io2.rewind; io2.read )
+	end
+
+	#
+	# Load a document from the current _io_ stream.
+	#
+    #   File.open( 'animals.yaml' ) { |yf| YAML::load( yf ) }
+    #      #=> ['badger', 'elephant', 'tiger']
+    #
+    # Can also load from a string.
+    #
+    #   YAML.load( "--- :locked" )
+    #      #=> :locked
+    #
+	def YAML.load( io )
+		yp = parser.load( io )
+	end
+
+    #
+    # Load a document from the file located at _filepath_.
+    #
+    #   YAML.load_file( 'animals.yaml' )
+    #      #=> ['badger', 'elephant', 'tiger']
+    #
+    def YAML.load_file( filepath )
+        File.open( filepath ) do |f|
+            load( f )
+        end
+    end
+
+	#
+	# Parse the first document from the current _io_ stream
+	#
+    #   File.open( 'animals.yaml' ) { |yf| YAML::load( yf ) }
+    #      #=> #<YAML::Syck::Node:0x82ccce0
+    #           @kind=:seq,
+    #           @value=
+    #            [#<YAML::Syck::Node:0x82ccd94
+    #              @kind=:scalar,
+    #              @type_id="str",
+    #              @value="badger">,
+    #             #<YAML::Syck::Node:0x82ccd58
+    #              @kind=:scalar,
+    #              @type_id="str",
+    #              @value="elephant">,
+    #             #<YAML::Syck::Node:0x82ccd1c
+    #              @kind=:scalar,
+    #              @type_id="str",
+    #              @value="tiger">]>
+    #
+    # Can also load from a string.
+    #
+    #   YAML.parse( "--- :locked" )
+    #      #=> #<YAML::Syck::Node:0x82edddc 
+    #            @type_id="tag:ruby.yaml.org,2002:sym", 
+    #            @value=":locked", @kind=:scalar>
+    #
+	def YAML.parse( io )
+		yp = generic_parser.load( io )
+	end
+
+    #
+    # Parse a document from the file located at _filepath_.
+    #
+    #   YAML.parse_file( 'animals.yaml' )
+    #      #=> #<YAML::Syck::Node:0x82ccce0
+    #           @kind=:seq,
+    #           @value=
+    #            [#<YAML::Syck::Node:0x82ccd94
+    #              @kind=:scalar,
+    #              @type_id="str",
+    #              @value="badger">,
+    #             #<YAML::Syck::Node:0x82ccd58
+    #              @kind=:scalar,
+    #              @type_id="str",
+    #              @value="elephant">,
+    #             #<YAML::Syck::Node:0x82ccd1c
+    #              @kind=:scalar,
+    #              @type_id="str",
+    #              @value="tiger">]>
+    #
+    def YAML.parse_file( filepath )
+        File.open( filepath ) do |f|
+            parse( f )
+        end
+    end
+
+	#
+	# Calls _block_ with each consecutive document in the YAML
+    # stream contained in _io_.
+    #
+    #   File.open( 'many-docs.yaml' ) do |yf|
+    #     YAML.each_document( yf ) do |ydoc|
+    #       ## ydoc contains the single object
+    #       ## from the YAML document
+    #     end
+    #   end
+	#
+	def YAML.each_document( io, &block )
+		yp = parser.load_documents( io, &block )
+    end
+
+	#
+	# Calls _block_ with each consecutive document in the YAML
+    # stream contained in _io_.
+    #
+    #   File.open( 'many-docs.yaml' ) do |yf|
+    #     YAML.load_documents( yf ) do |ydoc|
+    #       ## ydoc contains the single object
+    #       ## from the YAML document
+    #     end
+    #   end
+	#
+	def YAML.load_documents( io, &doc_proc )
+		YAML.each_document( io, &doc_proc )
+    end
+
+	#
+	# Calls _block_ with a tree of +YAML::BaseNodes+, one tree for
+    # each consecutive document in the YAML stream contained in _io_.
+    #
+    #   File.open( 'many-docs.yaml' ) do |yf|
+    #     YAML.each_node( yf ) do |ydoc|
+    #       ## ydoc contains a tree of nodes
+    #       ## from the YAML document
+    #     end
+    #   end
+	#
+	def YAML.each_node( io, &doc_proc )
+		yp = generic_parser.load_documents( io, &doc_proc )
+    end
+
+	#
+	# Calls _block_ with a tree of +YAML::BaseNodes+, one tree for
+    # each consecutive document in the YAML stream contained in _io_.
+    #
+    #   File.open( 'many-docs.yaml' ) do |yf|
+    #     YAML.parse_documents( yf ) do |ydoc|
+    #       ## ydoc contains a tree of nodes
+    #       ## from the YAML document
+    #     end
+    #   end
+	#
+	def YAML.parse_documents( io, &doc_proc )
+		YAML.each_node( io, &doc_proc )
+    end
+
+	#
+	# Loads all documents from the current _io_ stream, 
+    # returning a +YAML::Stream+ object containing all
+    # loaded documents.
+	#
+	def YAML.load_stream( io )
+		d = nil
+		parser.load_documents( io ) do |doc|
+			d = YAML::Stream.new if not d
+			d.add( doc ) 
+        end
+		return d
+	end
+
+	#
+    # Returns a YAML stream containing each of the items in +objs+,
+    # each having their own document.
+    #
+    #   YAML.dump_stream( 0, [], {} )
+    #     #=> --- 0
+    #         --- []
+    #         --- {}
+    #
+	def YAML.dump_stream( *objs )
+		d = YAML::Stream.new
+        objs.each do |doc|
+			d.add( doc ) 
+        end
+        d.emit
+	end
+
+	#
+	# Add a global handler for a YAML domain type.
+	#
+	def YAML.add_domain_type( domain, type_tag, &transfer_proc )
+        resolver.add_type( "tag:#{ domain }:#{ type_tag }", transfer_proc )
+	end
+
+	#
+	# Add a transfer method for a builtin type
+	#
+	def YAML.add_builtin_type( type_tag, &transfer_proc )
+	    resolver.add_type( "tag:yaml.org,2002:#{ type_tag }", transfer_proc )
+	end
+
+	#
+	# Add a transfer method for a builtin type
+	#
+	def YAML.add_ruby_type( type_tag, &transfer_proc )
+	    resolver.add_type( "tag:ruby.yaml.org,2002:#{ type_tag }", transfer_proc )
+	end
+
+	#
+	# Add a private document type
+	#
+	def YAML.add_private_type( type_re, &transfer_proc )
+	    resolver.add_type( "x-private:" + type_re, transfer_proc )
+	end
+
+    #
+    # Detect typing of a string
+    #
+    def YAML.detect_implicit( val )
+        resolver.detect_implicit( val )
+    end
+
+    #
+    # Convert a type_id to a taguri
+    #
+    def YAML.tagurize( val )
+        resolver.tagurize( val )
+    end
+
+    #
+    # Apply a transfer method to a Ruby object
+    #
+    def YAML.transfer( type_id, obj )
+        resolver.transfer( YAML.tagurize( type_id ), obj )
+    end
+
+	#
+	# Apply any implicit a node may qualify for
+	#
+	def YAML.try_implicit( obj )
+		YAML.transfer( YAML.detect_implicit( obj ), obj )
+	end
+
+    #
+    # Method to extract colon-seperated type and class, returning
+    # the type and the constant of the class
+    #
+    def YAML.read_type_class( type, obj_class )
+        scheme, domain, type, tclass = type.split( ':', 4 )
+        tclass.split( "::" ).each { |c| obj_class = obj_class.const_get( c ) } if tclass
+        return [ type, obj_class ]
+    end
+
+    #
+    # Allocate blank object
+    #
+    def YAML.object_maker( obj_class, val )
+        if Hash === val
+            o = obj_class.allocate
+            val.each_pair { |k,v|
+                o.instance_variable_set("@#{k}", v)
+            }
+            o
+        else
+            raise YAML::Error, "Invalid object explicitly tagged !ruby/Object: " + val.inspect
+        end
+    end
+
+	#
+	# Allocate an Emitter if needed
+	#
+	def YAML.quick_emit( oid, opts = {}, &e )
+        out = 
+            if opts.is_a? YAML::Emitter
+                opts
+            else
+                emitter.reset( opts )
+            end
+        out.emit( oid, &e )
+	end
+	
+end
+
+require 'yaml/rubytypes'
+require 'yaml/types'
+
+module Kernel
+    #
+    # ryan:: You know how Kernel.p is a really convenient way to dump ruby
+    #        structures?  The only downside is that it's not as legible as
+    #        YAML.
+    #
+    # _why:: (listening)
+    #
+    # ryan:: I know you don't want to urinate all over your users' namespaces.
+    #        But, on the other hand, convenience of dumping for debugging is,
+    #        IMO, a big YAML use case.
+    #
+    # _why:: Go nuts!  Have a pony parade!
+    #
+    # ryan:: Either way, I certainly will have a pony parade.
+    #
+
+    # Prints any supplied _objects_ out in YAML.  Intended as
+    # a variation on +Kernel::p+.
+    #
+    #   S = Struct.new(:name, :state)
+    #   s = S['dave', 'TX']
+    #   y s
+    #
+    # _produces:_
+    #
+    #   --- !ruby/struct:S 
+    #   name: dave
+    #   state: TX
+    #
+    def y( object, *objects )
+        objects.unshift object
+        puts( if objects.length == 1
+                  YAML::dump( *objects )
+              else
+                  YAML::dump_stream( *objects )
+              end )
+    end
+    private :y
+end
+
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/baseemitter.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/baseemitter.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/baseemitter.rb	(revision 18425)
@@ -0,0 +1,247 @@
+#
+# BaseEmitter
+#
+
+require 'yaml/constants'
+require 'yaml/encoding'
+require 'yaml/error'
+
+module YAML
+
+    module BaseEmitter
+
+        def options( opt = nil )
+            if opt
+                @options[opt] || YAML::DEFAULTS[opt]
+            else
+                @options
+            end
+        end
+
+        def options=( opt )
+            @options = opt
+        end
+
+        #
+        # Emit binary data
+        #
+        def binary_base64( value )
+            self << "!binary "
+            self.node_text( [value].pack("m"), '|' )
+        end
+
+		#
+		# Emit plain, normal flowing text
+		#
+		def node_text( value, block = nil )
+            @seq_map = false
+			valx = value.dup
+            unless block
+            block =
+                if options(:UseBlock)
+                    '|'
+                elsif not options(:UseFold) and valx =~ /\n[ \t]/ and not valx =~ /#{YAML::ESCAPE_CHAR}/
+                    '|'
+                else
+                    '>'
+                end 
+
+                indt = $&.to_i if block =~ /\d+/
+                if valx =~ /(\A\n*[ \t#]|^---\s+)/
+                    indt = options(:Indent) unless indt.to_i > 0
+                    block += indt.to_s
+                end
+
+            block +=
+                if valx =~ /\n\Z\n/
+                    "+"
+                elsif valx =~ /\Z\n/
+                    ""
+                else
+                    "-"
+                end
+            end
+            block += "\n"
+            if block[0] == ?"
+                esc_skip = ( "\t\n" unless valx =~ /^[ \t]/ ) || ""
+                valx = fold( YAML::escape( valx, esc_skip ) + "\"" ).chomp
+                self << '"' + indent_text( valx, indt, false )
+            else
+                if block[0] == ?> 
+                    valx = fold( valx ) 
+                end
+                #p [block, indt]
+                self << block + indent_text( valx, indt )
+            end
+		end
+
+		#
+		# Emit a simple, unqouted string
+		#
+		def simple( value )
+            @seq_map = false
+            self << value.to_s
+		end
+
+		#
+		# Emit double-quoted string
+		#
+		def double( value )
+			"\"#{YAML.escape( value )}\"" 
+		end
+
+		#
+		# Emit single-quoted string
+		#
+		def single( value )
+			"'#{value}'"
+		end
+
+		#
+		# Write a text block with the current indent
+		#
+		def indent_text( text, mod, first_line = true )
+			return "" if text.to_s.empty?
+            spacing = indent( mod )
+            text = text.gsub( /\A([^\n])/, "#{ spacing }\\1" ) if first_line
+			return text.gsub( /\n^([^\n])/, "\n#{spacing}\\1" )
+		end
+
+		#
+		# Write a current indent
+		#
+        def indent( mod = nil )
+            #p [ self.id, level, mod, :INDENT ]
+            if level <= 0
+                mod ||= 0
+            else
+                mod ||= options(:Indent)
+                mod += ( level - 1 ) * options(:Indent)
+            end
+            return " " * mod
+		end
+
+		#
+		# Add indent to the buffer
+		#
+		def indent!
+			self << indent
+		end
+
+		#
+		# Folding paragraphs within a column
+		#
+		def fold( value )
+            value.gsub( /(^[ \t]+.*$)|(\S.{0,#{options(:BestWidth) - 1}})(?:[ \t]+|(\n+(?=[ \t]|\Z))|$)/ ) do |s| 
+                $1 || $2 + ( $3 || "\n" )
+            end
+		end
+
+        #
+        # Quick mapping
+        #
+        def map( type, &e )
+            val = Mapping.new
+            e.call( val )
+			self << "#{type} " if type.length.nonzero?
+
+			#
+			# Empty hashes
+			#
+			if val.length.zero?
+				self << "{}"
+                @seq_map = false
+			else
+                # FIXME
+                # if @buffer.length == 1 and options(:UseHeader) == false and type.length.zero? 
+			    #     @headless = 1 
+                # end
+
+                defkey = @options.delete( :DefaultKey )
+                if defkey
+                    seq_map_shortcut
+                    self << "= : "
+                    defkey.to_yaml( :Emitter => self )
+                end
+
+				#
+				# Emit the key and value
+				#
+                val.each { |v|
+                    seq_map_shortcut
+                    if v[0].is_complex_yaml?
+                        self << "? "
+                    end
+                    v[0].to_yaml( :Emitter => self )
+                    if v[0].is_complex_yaml?
+                        self << "\n"
+                        indent!
+                    end
+                    self << ": " 
+                    v[1].to_yaml( :Emitter => self )
+                }
+			end
+        end
+
+        def seq_map_shortcut
+            # FIXME: seq_map needs to work with the new anchoring system
+            # if @seq_map
+            #     @anchor_extras[@buffer.length - 1] = "\n" + indent
+            #     @seq_map = false
+            # else
+                self << "\n"
+                indent! 
+            # end
+        end
+
+        #
+        # Quick sequence
+        #
+        def seq( type, &e )
+            @seq_map = false
+            val = Sequence.new
+            e.call( val )
+			self << "#{type} " if type.length.nonzero?
+
+			#
+			# Empty arrays
+			#
+			if val.length.zero?
+				self << "[]"
+			else
+                # FIXME
+                # if @buffer.length == 1 and options(:UseHeader) == false and type.length.zero? 
+			    #     @headless = 1 
+                # end
+
+				#
+				# Emit the key and value
+				#
+                val.each { |v|
+                    self << "\n"
+                    indent!
+                    self << "- "
+                    @seq_map = true if v.class == Hash
+                    v.to_yaml( :Emitter => self )
+                }
+			end
+        end
+
+    end
+
+    #
+    # Emitter helper classes
+    #
+    class Mapping < Array
+        def add( k, v )
+            push [k, v]
+        end
+    end
+
+    class Sequence < Array
+        def add( v )
+            push v
+        end
+    end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/basenode.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/basenode.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/basenode.rb	(revision 18425)
@@ -0,0 +1,216 @@
+#
+# YAML::BaseNode class
+#
+require 'yaml/ypath'
+
+module YAML
+
+    #
+    # YAML Generic Model container
+    #
+    module BaseNode
+
+        #
+        # Search for YPath entry and return
+        # qualified nodes.
+        #
+        def select( ypath_str )
+            matches = match_path( ypath_str )
+
+            #
+            # Create a new generic view of the elements selected
+            #
+            if matches
+                result = []
+                matches.each { |m|
+                    result.push m.last
+                }
+                YAML.transfer( 'seq', result )
+            end
+        end
+
+        #
+        # Search for YPath entry and return
+        # transformed nodes.
+        #
+        def select!( ypath_str )
+            matches = match_path( ypath_str )
+
+            #
+            # Create a new generic view of the elements selected
+            #
+            if matches
+                result = []
+                matches.each { |m|
+                    result.push m.last.transform
+                }
+                result
+            end
+        end
+
+        #
+        # Search for YPath entry and return a list of
+        # qualified paths.
+        #
+        def search( ypath_str )
+            matches = match_path( ypath_str )
+
+            if matches
+                matches.collect { |m|
+                    path = []
+                    m.each_index { |i|
+                        path.push m[i] if ( i % 2 ).zero?
+                    }
+                    "/" + path.compact.join( "/" )
+                }
+            end
+        end
+
+        def at( seg )
+            if Hash === @value
+                self[seg]
+            elsif Array === @value and seg =~ /\A\d+\Z/ and @value[seg.to_i]
+                @value[seg.to_i]
+            end
+        end
+
+        #
+        # YPath search returning a complete depth array
+        #
+        def match_path( ypath_str )
+            depth = 0
+            matches = []
+            YPath.each_path( ypath_str ) do |ypath|
+                seg = match_segment( ypath, 0 )
+                matches += seg if seg
+            end
+            matches.uniq
+        end
+
+        #
+        # Search a node for a single YPath segment
+        #
+        def match_segment( ypath, depth )
+            deep_nodes = []
+            seg = ypath.segments[ depth ]
+            if seg == "/"
+                unless String === @value
+                    idx = -1
+                    @value.collect { |v|
+                        idx += 1
+                        if Hash === @value
+                            match_init = [v[0].transform, v[1]]
+                            match_deep = v[1].match_segment( ypath, depth )
+                        else
+                            match_init = [idx, v]
+                            match_deep = v.match_segment( ypath, depth )
+                        end
+                        if match_deep
+                            match_deep.each { |m|
+                                deep_nodes.push( match_init + m )
+                            }
+                        end
+                    }
+                end
+                depth += 1
+                seg = ypath.segments[ depth ]
+            end
+            match_nodes =
+                case seg
+                when "."
+                    [[nil, self]]
+                when ".."
+                    [["..", nil]]
+                when "*"
+                    if @value.is_a? Enumerable
+                        idx = -1
+                        @value.collect { |h|
+                            idx += 1
+                            if Hash === @value
+                                [h[0].transform, h[1]]
+                            else
+                                [idx, h]
+                            end
+                        }
+                    end
+                else
+                    if seg =~ /^"(.*)"$/
+                        seg = $1
+                    elsif seg =~ /^'(.*)'$/
+                        seg = $1
+                    end
+                    if ( v = at( seg ) )
+                        [[ seg, v ]]
+                    end
+                end
+            return deep_nodes unless match_nodes
+            pred = ypath.predicates[ depth ]
+            if pred
+                case pred
+                when /^\.=/
+                    pred = $'   # '
+                    match_nodes.reject! { |n|
+                        n.last.value != pred
+                    }
+                else
+                    match_nodes.reject! { |n|
+                        n.last.at( pred ).nil?
+                    }
+                end
+            end
+            return match_nodes + deep_nodes unless ypath.segments.length > depth + 1
+
+            #puts "DEPTH: #{depth + 1}"
+            deep_nodes = []
+            match_nodes.each { |n|
+                if n[1].is_a? BaseNode
+                    match_deep = n[1].match_segment( ypath, depth + 1 )
+                    if match_deep
+                        match_deep.each { |m|
+                            deep_nodes.push( n + m )
+                        }
+                    end
+                else
+                    deep_nodes = []
+                end
+            }
+            deep_nodes = nil if deep_nodes.length == 0
+            deep_nodes
+        end
+
+        #
+        # We want the node to act like as Hash
+        # if it is.
+        #
+        def []( *key )
+            if Hash === @value
+                v = @value.detect { |k,v| k.transform == key.first }
+                v[1] if v
+            elsif Array === @value
+                @value.[]( *key )
+            end
+        end
+
+        def children
+            if Hash === @value
+                @value.values.collect { |c| c[1] }
+            elsif Array === @value
+                @value
+            end
+        end
+
+        def children_with_index
+            if Hash === @value
+                @value.keys.collect { |i| [self[i], i] }
+            elsif Array === @value
+                i = -1; @value.collect { |v| i += 1; [v, i] }
+            end
+        end
+
+        def emit
+            transform.to_yaml
+        end
+    end
+
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/constants.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/constants.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/constants.rb	(revision 18425)
@@ -0,0 +1,45 @@
+#
+# Constants used throughout the library
+#
+module YAML
+
+	#
+	# Constants
+	#
+	VERSION = '0.60'
+	SUPPORTED_YAML_VERSIONS = ['1.0']
+
+	#
+	# Parser tokens
+	#
+	WORD_CHAR = 'A-Za-z0-9'
+	PRINTABLE_CHAR = '-_A-Za-z0-9!?/()$\'". ' 
+	NOT_PLAIN_CHAR = '\x7f\x0-\x1f\x80-\x9f'
+	ESCAPE_CHAR = '[\\x00-\\x09\\x0b-\\x1f]'
+	INDICATOR_CHAR = '*&!|\\\\^@%{}[]='
+	SPACE_INDICATORS = '-#:,?'
+	RESTRICTED_INDICATORS = '#:,}]'
+	DNS_COMP_RE = "\\w(?:[-\\w]*\\w)?"
+	DNS_NAME_RE = "(?:(?:#{DNS_COMP_RE}\\.)+#{DNS_COMP_RE}|#{DNS_COMP_RE})"
+	ESCAPES = %w{\x00   \x01	\x02	\x03	\x04	\x05	\x06	\a
+			     \x08	\t		\n		\v		\f		\r		\x0e	\x0f
+				 \x10	\x11	\x12	\x13	\x14	\x15	\x16	\x17
+				 \x18	\x19	\x1a	\e		\x1c	\x1d	\x1e	\x1f
+			    }
+	UNESCAPES = {
+				'a' => "\x07", 'b' => "\x08", 't' => "\x09", 
+				'n' => "\x0a", 'v' => "\x0b", 'f' => "\x0c",
+				'r' => "\x0d", 'e' => "\x1b", '\\' => '\\',
+			    }
+
+	#
+	# Default settings
+	#
+	DEFAULTS = {
+		:Indent => 2, :UseHeader => false, :UseVersion => false, :Version => '1.0',
+		:SortKeys => false, :AnchorFormat => 'id%03d', :ExplicitTypes => false,
+		:WidthType => 'absolute', :BestWidth => 80,
+		:UseBlock => false, :UseFold => false, :Encoding => :None
+	}
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/dbm.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/dbm.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/dbm.rb	(revision 18425)
@@ -0,0 +1,111 @@
+require 'yaml'
+require 'dbm'
+#
+# YAML + DBM = YDBM
+# - Same interface as DBM class
+#
+module YAML
+
+class DBM < ::DBM
+    VERSION = "0.1"
+    def []( key )
+        fetch( key )
+    end
+    def []=( key, val )
+        store( key, val )
+    end
+    def fetch( keystr, ifnone = nil )
+        begin
+            val = super( keystr )
+            return YAML::load( val ) if String === val
+        rescue IndexError
+        end
+        if block_given?
+            yield keystr
+        else
+            ifnone
+        end
+    end
+    def index( keystr )
+        super( keystr.to_yaml )
+    end
+    def values_at( *keys )
+        keys.collect { |k| fetch( k ) }
+    end
+    def delete( key )
+        v = super( key )
+        if String === v
+            v = YAML::load( v ) 
+        end
+        v
+    end
+    def delete_if
+        del_keys = keys.dup
+        del_keys.delete_if { |k| yield( k, fetch( k ) ) == false }
+        del_keys.each { |k| delete( k ) } 
+        self
+    end
+    def reject
+        hsh = self.to_hash
+        hsh.reject { |k,v| yield k, v }
+    end
+    def each_pair
+        keys.each { |k| yield k, fetch( k ) }
+        self
+    end
+    def each_value
+        super { |v| yield YAML::load( v ) }
+        self
+    end
+    def values
+        super.collect { |v| YAML::load( v ) }
+    end
+    def has_value?( val )
+        each_value { |v| return true if v == val }
+        return false
+    end
+    def invert
+        h = {}
+        keys.each { |k| h[ self.fetch( k ) ] = k }
+        h
+    end
+    def replace( hsh )
+        clear
+        update( hsh )
+    end
+    def shift
+        a = super
+        a[1] = YAML::load( a[1] ) if a
+        a
+    end
+    def select( *keys )
+        if block_given?
+            self.keys.collect { |k| v = self[k]; [k, v] if yield k, v }.compact
+        else
+            values_at( *keys )
+        end
+    end
+    def store( key, val )
+        super( key, val.to_yaml )
+        val
+    end
+    def update( hsh )
+        hsh.keys.each do |k|
+            self.store( k, hsh.fetch( k ) )
+        end
+        self
+    end
+    def to_a
+        a = []
+        keys.each { |k| a.push [ k, self.fetch( k ) ] }
+        a
+    end
+    def to_hash
+        h = {}
+        keys.each { |k| h[ k ] = self.fetch( k ) }
+        h
+    end
+    alias :each :each_pair
+end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/encoding.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/encoding.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/encoding.rb	(revision 18425)
@@ -0,0 +1,33 @@
+#
+# Handle Unicode-to-Internal conversion
+#
+
+module YAML
+
+	#
+	# Escape the string, condensing common escapes
+	#
+	def YAML.escape( value, skip = "" )
+		value.gsub( /\\/, "\\\\\\" ).
+              gsub( /"/, "\\\"" ).
+              gsub( /([\x00-\x1f])/ ) do |x|
+                 skip[x] || ESCAPES[ x.unpack("C")[0] ]
+             end
+	end
+
+	#
+	# Unescape the condenses escapes
+	#
+	def YAML.unescape( value )
+		value.gsub( /\\(?:([nevfbart\\])|0?x([0-9a-fA-F]{2})|u([0-9a-fA-F]{4}))/ ) { |x| 
+			if $3
+				["#$3".hex ].pack('U*')
+			elsif $2
+				[$2].pack( "H2" ) 
+			else
+				UNESCAPES[$1] 
+			end
+		}
+	end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/error.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/error.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/error.rb	(revision 18425)
@@ -0,0 +1,34 @@
+#
+# Error messages and exception class
+#
+
+module YAML
+
+	#
+	# Error messages
+	#
+
+	ERROR_NO_HEADER_NODE = "With UseHeader=false, the node Array or Hash must have elements"
+	ERROR_NEED_HEADER = "With UseHeader=false, the node must be an Array or Hash"
+	ERROR_BAD_EXPLICIT = "Unsupported explicit transfer: '%s'"
+    ERROR_MANY_EXPLICIT = "More than one explicit transfer"
+	ERROR_MANY_IMPLICIT = "More than one implicit request"
+	ERROR_NO_ANCHOR = "No anchor for alias '%s'"
+	ERROR_BAD_ANCHOR = "Invalid anchor: %s"
+	ERROR_MANY_ANCHOR = "More than one anchor"
+	ERROR_ANCHOR_ALIAS = "Can't define both an anchor and an alias"
+	ERROR_BAD_ALIAS = "Invalid alias: %s"
+	ERROR_MANY_ALIAS = "More than one alias"
+	ERROR_ZERO_INDENT = "Can't use zero as an indentation width"
+	ERROR_UNSUPPORTED_VERSION = "This release of YAML.rb does not support YAML version %s"
+	ERROR_UNSUPPORTED_ENCODING = "Attempt to use unsupported encoding: %s"
+
+	#
+	# YAML Error classes
+	#
+    
+	class Error < StandardError; end
+	class ParseError < Error; end
+    class TypeError < StandardError; end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/loader.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/loader.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/loader.rb	(revision 18425)
@@ -0,0 +1,14 @@
+#
+# YAML::Loader class
+# .. type handling ..
+#
+module YAML
+    class Loader
+        TRANSFER_DOMAINS = {
+            'yaml.org,2002' => {},
+            'ruby.yaml.org,2002' => {}
+        }
+        PRIVATE_TYPES = {}
+        IMPLICIT_TYPES = [ 'null', 'bool', 'time', 'int', 'float' ]
+    end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/rubytypes.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/rubytypes.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/rubytypes.rb	(revision 18425)
@@ -0,0 +1,408 @@
+# -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
+require 'date'
+
+class Class
+	def to_yaml( opts = {} )
+		raise TypeError, "can't dump anonymous class %s" % self.class
+	end
+end
+
+class Object
+    yaml_as "tag:ruby.yaml.org,2002:object"
+    def to_yaml_style; end
+    def to_yaml_properties; instance_variables.sort; end
+	def to_yaml( opts = {} )
+		YAML::quick_emit( object_id, opts ) do |out|
+            out.map( taguri, to_yaml_style ) do |map|
+				to_yaml_properties.each do |m|
+                    map.add( m[1..-1], instance_variable_get( m ) )
+                end
+            end
+        end
+	end
+end
+
+class Hash
+    yaml_as "tag:ruby.yaml.org,2002:hash"
+    yaml_as "tag:yaml.org,2002:map"
+    def yaml_initialize( tag, val )
+        if Array === val
+            update Hash.[]( *val )		# Convert the map to a sequence
+        elsif Hash === val
+            update val
+        else
+            raise YAML::TypeError, "Invalid map explicitly tagged #{ tag }: " + val.inspect
+        end
+    end
+	def to_yaml( opts = {} )
+		YAML::quick_emit( object_id, opts ) do |out|
+            out.map( taguri, to_yaml_style ) do |map|
+                each do |k, v|
+                    map.add( k, v )
+                end
+            end
+        end
+	end
+end
+
+class Struct
+    yaml_as "tag:ruby.yaml.org,2002:struct"
+    def self.yaml_tag_class_name; self.name.gsub( "Struct::", "" ); end
+    def self.yaml_tag_read_class( name ); "Struct::#{ name }"; end
+    def self.yaml_new( klass, tag, val )
+        if Hash === val
+            struct_type = nil
+
+            #
+            # Use existing Struct if it exists
+            #
+            props = {}
+            val.delete_if { |k,v| props[k] = v if k =~ /^@/ }
+            begin
+                struct_name, struct_type = YAML.read_type_class( tag, Struct )
+            rescue NameError
+            end
+            if not struct_type
+                struct_def = [ tag.split( ':', 4 ).last ]
+                struct_type = Struct.new( *struct_def.concat( val.keys.collect { |k| k.intern } ) ) 
+            end
+
+            #
+            # Set the Struct properties
+            #
+            st = YAML::object_maker( struct_type, {} )
+            st.members.each do |m|
+                st.send( "#{m}=", val[m] )
+            end
+            props.each do |k,v|
+                st.instance_variable_set(k, v)
+            end
+            st
+        else
+            raise YAML::TypeError, "Invalid Ruby Struct: " + val.inspect
+        end
+    end
+	def to_yaml( opts = {} )
+		YAML::quick_emit( object_id, opts ) do |out|
+			#
+			# Basic struct is passed as a YAML map
+			#
+            out.map( taguri, to_yaml_style ) do |map|
+				self.members.each do |m|
+                    map.add( m, self[m] )
+                end
+				self.to_yaml_properties.each do |m|
+                    map.add( m, instance_variable_get( m ) )
+                end
+            end
+        end
+	end
+end
+
+class Array
+    yaml_as "tag:ruby.yaml.org,2002:array"
+    yaml_as "tag:yaml.org,2002:seq"
+    def yaml_initialize( tag, val ); concat( val.to_a ); end
+	def to_yaml( opts = {} )
+		YAML::quick_emit( object_id, opts ) do |out|
+            out.seq( taguri, to_yaml_style ) do |seq|
+                each do |x|
+                    seq.add( x )
+                end
+            end
+        end
+	end
+end
+
+class Exception
+    yaml_as "tag:ruby.yaml.org,2002:exception"
+    def Exception.yaml_new( klass, tag, val )
+        o = YAML.object_maker( klass, { 'mesg' => val.delete( 'message' ) } )
+        val.each_pair do |k,v|
+            o.instance_variable_set("@#{k}", v)
+        end
+        o
+    end
+	def to_yaml( opts = {} )
+		YAML::quick_emit( object_id, opts ) do |out|
+            out.map( taguri, to_yaml_style ) do |map|
+                map.add( 'message', message )
+				to_yaml_properties.each do |m|
+                    map.add( m[1..-1], instance_variable_get( m ) )
+                end
+            end
+        end
+	end
+end
+
+class String
+    yaml_as "tag:ruby.yaml.org,2002:string"
+    yaml_as "tag:yaml.org,2002:binary"
+    yaml_as "tag:yaml.org,2002:str"
+    def is_complex_yaml?
+        to_yaml_style or not to_yaml_properties.empty? or self =~ /\n.+/
+    end
+    def is_binary_data?
+        ( self.count( "^ -~", "^\r\n" ) / self.size > 0.3 || self.count( "\x00" ) > 0 ) unless empty?
+    end
+    def String.yaml_new( klass, tag, val )
+        val = val.unpack("m")[0] if tag == "tag:yaml.org,2002:binary"
+        val = { 'str' => val } if String === val
+        if Hash === val
+            s = klass.allocate
+            # Thank you, NaHi
+            String.instance_method(:initialize).
+                  bind(s).
+                  call( val.delete( 'str' ) )
+            val.each { |k,v| s.instance_variable_set( k, v ) }
+            s
+        else
+            raise YAML::TypeError, "Invalid String: " + val.inspect
+        end
+    end
+	def to_yaml( opts = {} )
+		YAML::quick_emit( is_complex_yaml? ? object_id : nil, opts ) do |out|
+            if is_binary_data?
+                out.scalar( "tag:yaml.org,2002:binary", [self].pack("m"), :literal )
+            elsif to_yaml_properties.empty?
+                out.scalar( taguri, self, self =~ /^:/ ? :quote2 : to_yaml_style )
+            else
+                out.map( taguri, to_yaml_style ) do |map|
+                    map.add( 'str', "#{self}" )
+                    to_yaml_properties.each do |m|
+                        map.add( m, instance_variable_get( m ) )
+                    end
+                end
+            end
+        end
+	end
+end
+
+class Symbol
+    yaml_as "tag:ruby.yaml.org,2002:symbol"
+    yaml_as "tag:ruby.yaml.org,2002:sym"
+    def Symbol.yaml_new( klass, tag, val )
+        if String === val
+            val = YAML::load( val ) if val =~ /\A(["']).*\1\z/
+            val.intern
+        else
+            raise YAML::TypeError, "Invalid Symbol: " + val.inspect
+        end
+    end
+	def to_yaml( opts = {} )
+		YAML::quick_emit( nil, opts ) do |out|
+            out.scalar( "tag:yaml.org,2002:str", self.inspect, :plain )
+        end
+	end
+end
+
+class Range
+    yaml_as "tag:ruby.yaml.org,2002:range"
+    def Range.yaml_new( klass, tag, val )
+        inr = %r'(\w+|[+-]?\d+(?:\.\d+)?(?:e[+-]\d+)?|"(?:[^\\"]|\\.)*")'
+        opts = {}
+        if String === val and val =~ /^#{inr}(\.{2,3})#{inr}$/o
+            r1, rdots, r2 = $1, $2, $3
+            opts = {
+                'begin' => YAML.load( "--- #{r1}" ),
+                'end' => YAML.load( "--- #{r2}" ),
+                'excl' => rdots.length == 3
+            }
+            val = {}
+        elsif Hash === val
+            opts['begin'] = val.delete('begin')
+            opts['end'] = val.delete('end')
+            opts['excl'] = val.delete('excl')
+        end
+        if Hash === opts
+            r = YAML::object_maker( klass, {} )
+            # Thank you, NaHi
+            Range.instance_method(:initialize).
+                  bind(r).
+                  call( opts['begin'], opts['end'], opts['excl'] )
+            val.each { |k,v| r.instance_variable_set( k, v ) }
+            r
+        else
+            raise YAML::TypeError, "Invalid Range: " + val.inspect
+        end
+    end
+	def to_yaml( opts = {} )
+		YAML::quick_emit( object_id, opts ) do |out|
+            # if self.begin.is_complex_yaml? or self.begin.respond_to? :to_str or
+            #   self.end.is_complex_yaml? or self.end.respond_to? :to_str or
+            #   not to_yaml_properties.empty?
+                out.map( taguri, to_yaml_style ) do |map|
+                    map.add( 'begin', self.begin )
+                    map.add( 'end', self.end )
+                    map.add( 'excl', self.exclude_end? )
+                    to_yaml_properties.each do |m|
+                        map.add( m, instance_variable_get( m ) )
+                    end
+                end
+            # else
+            #     out.scalar( taguri ) do |sc|
+            #         sc.embed( self.begin )
+            #         sc.concat( self.exclude_end? ? "..." : ".." )
+            #         sc.embed( self.end )
+            #     end
+            # end
+        end
+	end
+end
+
+class Regexp
+    yaml_as "tag:ruby.yaml.org,2002:regexp"
+    def Regexp.yaml_new( klass, tag, val )
+        if String === val and val =~ /^\/(.*)\/([mix]*)$/
+            val = { 'regexp' => $1, 'mods' => $2 }
+        end
+        if Hash === val
+            mods = nil
+            unless val['mods'].to_s.empty?
+                mods = 0x00
+                mods |= Regexp::EXTENDED if val['mods'].include?( 'x' )
+                mods |= Regexp::IGNORECASE if val['mods'].include?( 'i' )
+                mods |= Regexp::MULTILINE if val['mods'].include?( 'm' )
+            end
+            val.delete( 'mods' )
+            r = YAML::object_maker( klass, {} )
+            Regexp.instance_method(:initialize).
+                  bind(r).
+                  call( val.delete( 'regexp' ), mods )
+            val.each { |k,v| r.instance_variable_set( k, v ) }
+            r
+        else
+            raise YAML::TypeError, "Invalid Regular expression: " + val.inspect
+        end
+    end
+	def to_yaml( opts = {} )
+		YAML::quick_emit( nil, opts ) do |out|
+            if to_yaml_properties.empty?
+                out.scalar( taguri, self.inspect, :plain )
+            else
+                out.map( taguri, to_yaml_style ) do |map|
+                    src = self.inspect
+                    if src =~ /\A\/(.*)\/([a-z]*)\Z/
+                        map.add( 'regexp', $1 )
+                        map.add( 'mods', $2 )
+                    else
+		                raise YAML::TypeError, "Invalid Regular expression: " + src
+                    end
+                    to_yaml_properties.each do |m|
+                        map.add( m, instance_variable_get( m ) )
+                    end
+                end
+            end
+        end
+	end
+end
+
+class Time
+    yaml_as "tag:ruby.yaml.org,2002:time"
+    yaml_as "tag:yaml.org,2002:timestamp"
+    def Time.yaml_new( klass, tag, val )
+        if Hash === val
+            t = val.delete( 'at' )
+            val.each { |k,v| t.instance_variable_set( k, v ) }
+            t
+        else
+            raise YAML::TypeError, "Invalid Time: " + val.inspect
+        end
+    end
+	def to_yaml( opts = {} )
+		YAML::quick_emit( object_id, opts ) do |out|
+            tz = "Z"
+            # from the tidy Tobias Peters <t-peters@gmx.de> Thanks!
+            unless self.utc?
+                utc_same_instant = self.dup.utc
+                utc_same_writing = Time.utc(year,month,day,hour,min,sec,usec)
+                difference_to_utc = utc_same_writing - utc_same_instant
+                if (difference_to_utc < 0) 
+                    difference_sign = '-'
+                    absolute_difference = -difference_to_utc
+                else
+                    difference_sign = '+'
+                    absolute_difference = difference_to_utc
+                end
+                difference_minutes = (absolute_difference/60).round
+                tz = "%s%02d:%02d" % [ difference_sign, difference_minutes / 60, difference_minutes % 60]
+            end
+            standard = self.strftime( "%Y-%m-%d %H:%M:%S" )
+            standard += ".%06d" % [usec] if usec.nonzero?
+            standard += " %s" % [tz]
+            if to_yaml_properties.empty?
+                out.scalar( taguri, standard, :plain )
+            else
+                out.map( taguri, to_yaml_style ) do |map|
+                    map.add( 'at', standard )
+                    to_yaml_properties.each do |m|
+                        map.add( m, instance_variable_get( m ) )
+                    end
+                end
+            end
+        end
+	end
+end
+
+class Date
+    yaml_as "tag:yaml.org,2002:timestamp#ymd"
+	def to_yaml( opts = {} )
+		YAML::quick_emit( object_id, opts ) do |out|
+            out.scalar( "tag:yaml.org,2002:timestamp", self.to_s, :plain )
+        end
+	end
+end
+
+class Integer
+    yaml_as "tag:yaml.org,2002:int"
+	def to_yaml( opts = {} )
+		YAML::quick_emit( nil, opts ) do |out|
+            out.scalar( "tag:yaml.org,2002:int", self.to_s, :plain )
+        end
+	end
+end
+
+class Float
+    yaml_as "tag:yaml.org,2002:float"
+	def to_yaml( opts = {} )
+		YAML::quick_emit( nil, opts ) do |out|
+            str = self.to_s
+            if str == "Infinity"
+                str = ".Inf"
+            elsif str == "-Infinity"
+                str = "-.Inf"
+            elsif str == "NaN"
+                str = ".NaN"
+            end
+            out.scalar( "tag:yaml.org,2002:float", str, :plain )
+        end
+	end
+end
+
+class TrueClass
+    yaml_as "tag:yaml.org,2002:bool#yes"
+	def to_yaml( opts = {} )
+		YAML::quick_emit( nil, opts ) do |out|
+            out.scalar( taguri, "true", :plain )
+        end
+	end
+end
+
+class FalseClass
+    yaml_as "tag:yaml.org,2002:bool#no"
+	def to_yaml( opts = {} )
+		YAML::quick_emit( nil, opts ) do |out|
+            out.scalar( taguri, "false", :plain )
+        end
+	end
+end
+
+class NilClass 
+    yaml_as "tag:yaml.org,2002:null"
+	def to_yaml( opts = {} )
+		YAML::quick_emit( nil, opts ) do |out|
+            out.scalar( taguri, "", :plain )
+        end
+	end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/store.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/store.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/store.rb	(revision 18425)
@@ -0,0 +1,29 @@
+#
+# YAML::Store
+#
+require 'yaml'
+require 'pstore'
+
+class YAML::Store < PStore
+  def initialize( *o )
+    @opt = YAML::DEFAULTS.dup
+    if String === o.first
+      super(o.shift)
+    end
+    if o.last.is_a? Hash
+      @opt.update(o.pop)
+    end
+  end
+
+  def dump(table)
+    @table.to_yaml(@opt)
+  end
+
+  def load(content)
+    YAML::load(content)
+  end
+
+  def load_file(file)
+    YAML::load(file)
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/stream.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/stream.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/stream.rb	(revision 18425)
@@ -0,0 +1,40 @@
+module YAML
+
+	#
+	# YAML::Stream -- for emitting many documents
+	#
+	class Stream
+
+		attr_accessor :documents, :options
+
+		def initialize( opts = {} )
+			@options = opts
+			@documents = []
+		end
+		
+        def []( i )
+            @documents[ i ]
+        end
+
+		def add( doc )
+			@documents << doc
+		end
+
+		def edit( doc_num, doc )
+			@documents[ doc_num ] = doc
+		end
+
+		def emit( io = nil )
+            # opts = @options.dup
+			# opts[:UseHeader] = true if @documents.length > 1
+            out = YAML.emitter
+            out.reset( io || io2 = StringIO.new )
+            @documents.each { |v|
+                v.to_yaml( out )
+            }
+            io || ( io2.rewind; io2.read )
+		end
+
+	end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/stringio.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/stringio.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/stringio.rb	(revision 18425)
@@ -0,0 +1,83 @@
+#
+# Limited StringIO if no core lib is available
+#
+begin
+require 'stringio'
+rescue LoadError
+    # StringIO based on code by MoonWolf
+    class StringIO
+        def initialize(string="")
+            @string=string
+            @pos=0
+            @eof=(string.size==0)
+        end
+        def pos
+            @pos
+        end    
+        def eof
+            @eof
+        end
+        alias eof? eof
+        def readline(rs=$/)
+            if @eof
+                raise EOFError
+            else
+                if p = @string[@pos..-1]=~rs
+                    line = @string[@pos,p+1]
+                else
+                    line = @string[@pos..-1]
+                end
+                @pos+=line.size
+                @eof =true if @pos==@string.size
+                $_ = line
+            end
+        end
+        def rewind
+            seek(0,0)
+        end
+        def seek(offset,whence)
+            case whence
+            when 0
+                @pos=offset
+            when 1
+                @pos+=offset
+            when 2
+                @pos=@string.size+offset
+            end
+            @eof=(@pos>=@string.size)
+            0
+        end
+    end
+
+	#
+	# Class method for creating streams
+	#
+	def YAML.make_stream( io )
+        if String === io
+            io = StringIO.new( io )
+        elsif not IO === io
+            raise YAML::Error, "YAML stream must be an IO or String object."
+        end
+        if YAML::unicode
+            def io.readline
+                YAML.utf_to_internal( readline( @ln_sep ), @utf_encoding )
+            end
+            def io.check_unicode
+                @utf_encoding = YAML.sniff_encoding( read( 4 ) )
+                @ln_sep = YAML.enc_separator( @utf_encoding )
+                seek( -4, IO::SEEK_CUR )
+            end
+		    def io.utf_encoding
+		    	@utf_encoding
+		    end
+            io.check_unicode
+        else
+            def io.utf_encoding
+                :None
+            end
+        end
+        io
+	end
+
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/syck.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/syck.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/syck.rb	(revision 18425)
@@ -0,0 +1,19 @@
+#
+# YAML::Syck module
+# .. glues syck and yaml.rb together ..
+#
+require 'syck'
+require 'yaml/basenode'
+
+module YAML
+    module Syck
+
+        #
+        # Mixin BaseNode functionality
+        #
+        class Node
+            include YAML::BaseNode
+        end
+
+    end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/tag.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/tag.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/tag.rb	(revision 18425)
@@ -0,0 +1,91 @@
+# -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
+# $Id: tag.rb 11708 2007-02-12 23:01:19Z shyouhei $
+#
+# = yaml/tag.rb: methods for associating a taguri to a class.
+#
+# Author:: why the lucky stiff
+# 
+module YAML
+    # A dictionary of taguris which map to
+    # Ruby classes.
+    @@tagged_classes = {}
+    
+    # 
+    # Associates a taguri _tag_ with a Ruby class _cls_.  The taguri is used to give types
+    # to classes when loading YAML.  Taguris are of the form:
+    #
+    #   tag:authorityName,date:specific
+    #
+    # The +authorityName+ is a domain name or email address.  The +date+ is the date the type
+    # was issued in YYYY or YYYY-MM or YYYY-MM-DD format.  The +specific+ is a name for
+    # the type being added.
+    # 
+    # For example, built-in YAML types have 'yaml.org' as the +authorityName+ and '2002' as the
+    # +date+.  The +specific+ is simply the name of the type:
+    #
+    #  tag:yaml.org,2002:int
+    #  tag:yaml.org,2002:float
+    #  tag:yaml.org,2002:timestamp
+    #
+    # The domain must be owned by you on the +date+ declared.  If you don't own any domains on the
+    # date you declare the type, you can simply use an e-mail address.
+    #
+    #  tag:why@ruby-lang.org,2004:notes/personal
+    #
+    def YAML.tag_class( tag, cls )
+        if @@tagged_classes.has_key? tag
+            warn "class #{ @@tagged_classes[tag] } held ownership of the #{ tag } tag"
+        end
+        @@tagged_classes[tag] = cls
+    end
+
+    # Returns the complete dictionary of taguris, paired with classes.  The key for
+    # the dictionary is the full taguri.  The value for each key is the class constant
+    # associated to that taguri.
+    #
+    #  YAML.tagged_classes["tag:yaml.org,2002:int"] => Integer
+    #
+    def YAML.tagged_classes
+        @@tagged_classes
+    end
+end
+
+class Module
+    # :stopdoc:
+
+    # Adds a taguri _tag_ to a class, used when dumping or loading the class
+    # in YAML.  See YAML::tag_class for detailed information on typing and
+    # taguris.
+    def yaml_as( tag, sc = true )
+        verbose, $VERBOSE = $VERBOSE, nil
+        class_eval <<-"end;", __FILE__, __LINE__+1
+            attr_writer :taguri
+            def taguri
+                if respond_to? :to_yaml_type
+                    YAML::tagurize( to_yaml_type[1..-1] )
+                else
+                    return @taguri if defined?(@taguri) and @taguri
+                    tag = #{ tag.dump }
+                    if self.class.yaml_tag_subclasses? and self.class != YAML::tagged_classes[tag]
+                        tag = "\#{ tag }:\#{ self.class.yaml_tag_class_name }"
+                    end
+                    tag
+                end
+            end
+            def self.yaml_tag_subclasses?; #{ sc ? 'true' : 'false' }; end
+        end;
+        YAML::tag_class tag, self
+    ensure
+        $VERBOSE = verbose
+    end
+    # Transforms the subclass name into a name suitable for display
+    # in a subclassed tag.
+    def yaml_tag_class_name
+        self.name
+    end
+    # Transforms the subclass name found in the tag into a Ruby
+    # constant name.
+    def yaml_tag_read_class( name )
+        name
+    end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/types.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/types.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/types.rb	(revision 18425)
@@ -0,0 +1,194 @@
+# -*- mode: ruby; ruby-indent-level: 4 -*- vim: sw=4
+#
+# Classes required by the full core typeset
+#
+
+module YAML
+
+    #
+    # Default private type
+    #
+    class PrivateType
+        def self.tag_subclasses?; false; end
+        attr_accessor :type_id, :value
+        verbose, $VERBOSE = $VERBOSE, nil
+        def initialize( type, val )
+            @type_id = type; @value = val
+            @value.taguri = "x-private:#{ @type_id }"
+        end
+        def to_yaml( opts = {} )
+            @value.to_yaml( opts )
+        end
+    ensure
+        $VERBOSE = verbose
+    end
+
+    #
+    # Default domain type
+    #
+    class DomainType
+        def self.tag_subclasses?; false; end
+        attr_accessor :domain, :type_id, :value
+        verbose, $VERBOSE = $VERBOSE, nil
+        def initialize( domain, type, val )
+            @domain = domain; @type_id = type; @value = val
+            @value.taguri = "tag:#{ @domain }:#{ @type_id }"
+        end
+        def to_yaml( opts = {} )
+            @value.to_yaml( opts )
+        end
+    ensure
+        $VERBOSE = verbose
+    end
+
+    #
+    # Unresolved objects
+    #
+    class Object
+        def self.tag_subclasses?; false; end
+        def to_yaml( opts = {} )
+            YAML::quick_emit( object_id, opts ) do |out|
+                out.map( "tag:ruby.yaml.org,2002:object:#{ @class }", to_yaml_style ) do |map|
+                    @ivars.each do |k,v|
+                        map.add( k, v )
+                    end
+                end
+            end
+        end
+    end
+
+    #
+    # YAML Hash class to support comments and defaults
+    #
+    class SpecialHash < ::Hash 
+        attr_accessor :default
+        def inspect
+            self.default.to_s
+        end
+        def to_s
+            self.default.to_s
+        end
+        def update( h )
+            if YAML::SpecialHash === h
+                @default = h.default if h.default
+            end
+            super( h )
+        end
+        def to_yaml( opts = {} )
+            opts[:DefaultKey] = self.default
+            super( opts )
+        end
+    end
+
+    #
+    # Builtin collection: !omap
+    #
+    class Omap < ::Array
+        yaml_as "tag:yaml.org,2002:omap"
+        def yaml_initialize( tag, val )
+            if Array === val
+                val.each do |v|
+                    if Hash === v
+                        concat( v.to_a )		# Convert the map to a sequence
+                    else
+                        raise YAML::Error, "Invalid !omap entry: " + val.inspect
+                    end
+                end
+            else
+                raise YAML::Error, "Invalid !omap: " + val.inspect
+            end
+            self
+        end
+        def self.[]( *vals )
+            o = Omap.new
+            0.step( vals.length - 1, 2 ) do |i|
+                o[vals[i]] = vals[i+1]
+            end
+            o
+        end
+        def []( k )
+            self.assoc( k ).to_a[1]
+        end
+        def []=( k, *rest )
+            val, set = rest.reverse
+            if ( tmp = self.assoc( k ) ) and not set
+                tmp[1] = val
+            else
+                self << [ k, val ] 
+            end
+            val
+        end
+        def has_key?( k )
+            self.assoc( k ) ? true : false
+        end
+        def is_complex_yaml?
+            true
+        end
+        def to_yaml( opts = {} )
+            YAML::quick_emit( self.object_id, opts ) do |out|
+                out.seq( taguri, to_yaml_style ) do |seq|
+                    self.each do |v|
+                        seq.add( Hash[ *v ] )
+                    end
+                end
+            end
+        end
+    end
+
+    #
+    # Builtin collection: !pairs
+    #
+    class Pairs < ::Array
+        yaml_as "tag:yaml.org,2002:pairs"
+        def yaml_initialize( tag, val )
+            if Array === val
+                val.each do |v|
+                    if Hash === v
+                        concat( v.to_a )		# Convert the map to a sequence
+                    else
+                        raise YAML::Error, "Invalid !pairs entry: " + val.inspect
+                    end
+                end
+            else
+                raise YAML::Error, "Invalid !pairs: " + val.inspect
+            end
+            self
+        end
+        def self.[]( *vals )
+            p = Pairs.new
+            0.step( vals.length - 1, 2 ) { |i|
+                p[vals[i]] = vals[i+1]
+            }
+            p
+        end
+        def []( k )
+            self.assoc( k ).to_a
+        end
+        def []=( k, val )
+            self << [ k, val ] 
+            val
+        end
+        def has_key?( k )
+            self.assoc( k ) ? true : false
+        end
+        def is_complex_yaml?
+            true
+        end
+        def to_yaml( opts = {} )
+            YAML::quick_emit( self.object_id, opts ) do |out|
+                out.seq( taguri, to_yaml_style ) do |seq|
+                    self.each do |v|
+                        seq.add( Hash[ *v ] )
+                    end
+                end
+            end
+        end
+    end
+
+    #
+    # Builtin collection: !set
+    #
+    class Set < ::Hash
+        yaml_as "tag:yaml.org,2002:set"
+    end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/yamlnode.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/yamlnode.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/yamlnode.rb	(revision 18425)
@@ -0,0 +1,54 @@
+#
+# YAML::YamlNode class
+#
+require 'yaml/basenode'
+
+module YAML
+
+    #
+    # YAML Generic Model container
+    #
+    class YamlNode
+        include BaseNode
+        attr_accessor :kind, :type_id, :value, :anchor
+        def initialize( t, v )
+            @type_id = t
+            if Hash === v
+                @kind = 'map'
+                @value = {}
+                v.each { |k,v|
+                    @value[ k.transform ] = [ k, v ]
+                }
+            elsif Array === v
+                @kind = 'seq'
+                @value = v
+            elsif String === v
+                @kind = 'scalar'
+                @value = v
+            end
+        end
+
+        #
+        # Transform this node fully into a native type
+        #
+        def transform
+            t = nil
+            if @value.is_a? Hash
+                t = {}
+                @value.each { |k,v|
+                    t[ k ] = v[1].transform
+                }
+            elsif @value.is_a? Array
+                t = []
+                @value.each { |v|
+                    t.push v.transform
+                }
+            else
+                t = @value
+            end
+            YAML.transfer_method( @type_id, t )
+        end
+
+    end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/ypath.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/ypath.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml/ypath.rb	(revision 18425)
@@ -0,0 +1,52 @@
+#
+# YAML::YPath
+#
+
+module YAML
+
+    class YPath
+        attr_accessor :segments, :predicates, :flags
+        def initialize( str )
+            @segments = []
+            @predicates = []
+            @flags = nil
+            while str =~ /^\/?(\/|[^\/\[]+)(?:\[([^\]]+)\])?/
+                @segments.push $1
+                @predicates.push $2
+                str = $'
+            end
+            unless str.to_s.empty?
+                @segments += str.split( "/" )
+            end
+            if @segments.length == 0
+                @segments.push "."
+            end
+        end
+        def YPath.each_path( str )
+            #
+            # Find choices
+            #
+            paths = []
+            str = "(#{ str })"
+            while str.sub!( /\(([^()]+)\)/, "\n#{ paths.length }\n" )
+                paths.push $1.split( '|' )
+            end
+
+            #
+            # Construct all possible paths
+            #
+            all = [ str ]
+            ( paths.length - 1 ).downto( 0 ) do |i|
+                all = all.collect do |a|
+                    paths[i].collect do |p|
+                        a.gsub( /\n#{ i }\n/, p )
+                    end
+                end.flatten.uniq
+            end
+            all.collect do |path|
+                yield YPath.new( path )
+            end
+        end
+    end
+
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv.rb	(revision 18425)
@@ -0,0 +1,1 @@
+require 'flv/stream'
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/amf_string_buffer.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/amf_string_buffer.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/amf_string_buffer.rb	(revision 18425)
@@ -0,0 +1,280 @@
+# Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+class AMFStringBuffer
+  def initialize(str = nil)
+    @buffer = str || ''
+    @pos = 0
+  end
+  
+  def seek(pos)
+    @pos = pos
+  end
+  
+  def read(length)
+    raise EOFError if @pos + length > @buffer.length
+    rt = @buffer[@pos, length]
+    @pos += length
+    rt
+  end
+  
+  def readchar
+    read(1).unpack('C').first
+  end
+  
+  def write(str)
+    if @pos + str.length > @buffer.length
+      @buffer << ' ' * (@pos + str.length - @buffer.length)
+    end
+    @buffer[@pos, str.length] = str
+    @pos += str.length
+  end
+
+  def close
+  end
+  
+  def to_s
+    @buffer
+  end
+
+  def length
+    @buffer.length
+  end
+
+  def eof?
+    @pos == length
+  end
+
+  def pos
+    @pos
+  end
+  
+  def read__AMF_string
+    read(read__UI16)
+  end
+  
+  def read__AMF_double
+    num = read(8).unpack('G').first.to_f
+  end
+
+  def read__AMF_boolean
+    read__UI8 == 1
+  end
+  
+  def read__AMF_mixed_array
+    size = read__UI32 # is not used
+    hash = {}
+    while !eof?
+      key = read__AMF_string
+      break if key.empty? && (type = read__UI8) == 9
+      hash[key] = read__AMF_data(type)
+    end
+    hash
+  end
+
+  def read__AMF_object
+    object = Object.new
+    while !eof?
+      key = read__AMF_string
+      break if key.empty? && (type = read__UI8) == 9
+      object.instance_variable_set( eval(":@#{key}"), read__AMF_data(type) )
+    end
+    object
+  end
+
+  def read__AMF_array
+    size = read__UI32
+    array = []
+    (1..size).step do |pos|  
+      break if eof?
+      array << read__AMF_data
+    end
+    array
+  end
+  
+  def read__AMF_date
+    utc_time = Time.at((read__AMF_double / 1000).to_i)
+    utc_time + (read__SI16 * 60) - Time.now.gmtoff
+  end
+  
+  def read__AMF_data(type = nil)
+    type ||= read__UI8
+    value = case type.to_i
+    when  0
+      read__AMF_double
+    when  1
+      read__AMF_boolean
+    when  2
+      read__AMF_string
+    when  3
+      read__AMF_object
+    when  8
+      read__AMF_mixed_array
+    when 10
+      read__AMF_array
+    when 11
+      read__AMF_date
+    else
+    end
+    return value
+  end
+  
+  def write__AMF_string(str)
+    write__UI8 2
+    write__UI16 str.length
+    write str
+  end
+  
+  def write__AMF_double(value)
+    write__UI8 0
+    write [value].pack('G')
+  end
+
+  def write__AMF_boolean(value)
+    write__UI8 1
+    value = value ? 1 : 0
+    write [value].pack('C')
+  end
+  
+  def write__AMF_date(time)
+    write__UI8 11
+    write [(time.to_f * 1000.0)].pack('G')
+    write__SI16( (Time.now.gmtoff / 60).to_i ) 
+  end
+  
+  def write__AMF_data(object)
+    if object === true || object === false
+      write__AMF_boolean object
+    elsif object.kind_of? Numeric
+      write__AMF_double object
+    elsif object.kind_of? Time
+      write__AMF_date object
+    elsif object.kind_of? Hash
+      write__AMF_mixed_array object
+    elsif object.kind_of? String
+      write__AMF_string object
+    elsif object.kind_of? Array
+      write__AMF_array object
+    else
+      write__AMF_object object
+    end
+  end
+  
+  def write__AMF_key(key)
+    write__UI16 key.length
+    write key
+  end
+  
+  def write__AMF_mixed_array(hash)
+    write__UI8 8
+    write__UI32 hash.length # length will never be read
+    
+    hash.each_pair do |key, value|
+      write__AMF_key key
+      write__AMF_data value
+    end
+    
+    write__UI16 0
+    write__UI8 9
+  end
+
+  def write__AMF_array(array)
+    write__UI8 10
+    write__UI32 array.length
+    
+    array.each do |value|
+      write__AMF_data value
+    end
+  end
+
+  def write__AMF_object(object)
+    write__UI8 3
+    
+    object.instance_variables.each do |variable|
+      write__AMF_key variable.gsub('@', '')
+      write__AMF_data object.instance_variable_get( variable.intern )
+    end
+    
+    write__UI16 0
+    write__UI8 9
+  end
+  
+  # FIXME: This methods are copied from flv_stream.rb. Should get in here per
+  # include? or something like this.
+  def read__UI8
+    readchar
+  end
+  
+  def read__UI16
+    (readchar << 8) + readchar
+  end
+  
+  def read__UI24
+    (readchar << 16) + (readchar << 8) + readchar
+  end
+  
+  def read__UI32
+    (readchar << 24) + (readchar << 16) + (readchar << 8) + readchar
+  end
+  
+  def read__STRING(length)
+    read length
+  end
+    
+  def read__SI16
+    read(2).reverse.unpack('s').first.to_i
+  end
+  
+  def write__UI8(value)
+    write [value].pack('C')
+  end
+  
+  def write__UI16(value)
+    write [(value >> 8) & 0xff].pack('c')
+    write [value & 0xff].pack('c')
+  end
+
+  def write__UI24(value)
+    write [value >> 16].pack('c')
+    write [(value >> 8) & 0xff].pack('c')
+    write [value & 0xff].pack('c')
+  end
+  
+  def write__UI32(value)
+    write [value].pack('N')
+  end
+  
+  def write__SI16(value)
+    write [(value >> 8) & 0xff].pack('c')
+    write [value & 0xff].pack('c')
+  end
+
+  def write__STRING(string)
+    write string
+  end
+  alias_method :<<, :write__STRING
+  
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/audio_tag.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/audio_tag.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/audio_tag.rb	(revision 18425)
@@ -0,0 +1,93 @@
+# Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+module FLV
+  
+  class FLVAudioTag < FLVTag
+
+    UNCOMPRESSED = 0
+    ADPCM = 1
+    MP3 = 2
+    NELLYMOSER8KHZMONO = 5
+    NELLYMOSER = 6
+    
+    MONO = 0
+    STEREO = 1
+
+    attr_reader :sound_format,
+                :sound_rate,
+                :sound_sample_size,
+                :sound_type
+    
+    def after_initialize(new_object)
+      @tag_type = AUDIO
+      read_header
+    end
+
+    def name
+      'Audio Tag'
+    end
+
+    def read_header
+      data_stream = AMFStringBuffer.new(@data)
+      bit_sequence = data_stream.read__STRING(1).unpack('B8').to_s
+      
+      @sound_format = bit2uint(bit_sequence[0,4])
+      @sound_rate = case bit2uint(bit_sequence[4,2])
+      when 0
+        5500
+      when 1
+        11000
+      when 2
+        22000
+      when 3
+        44000
+      end
+      @sound_sample_size = case bit2uint(bit_sequence[6,1])
+      when 0
+        8
+      when 1
+        16
+      end
+      @sound_type = bit2uint(bit_sequence[7,1])
+
+      # Nellymoser 8kHz mono special case
+      if @sound_format == NELLYMOSER8KHZMONO
+        @sound_rate = 8000
+        @sound_type = MONO
+      end
+    end
+
+    def inspect
+      out = super
+      out << "sound_format: #{['Uncompressed', 'ADPCM', 'MP3', nil, nil, 'Nellymoser 8KHz mono', 'Nellymoser'][@sound_format]}"
+      out << "sound_rate: #{@sound_rate}"
+      out << "sound_sample_size: #{@sound_sample_size}"
+      out << "sound_type: #{['Mono', 'Stereo'][@sound_type]}"
+      out
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/core_extensions.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/core_extensions.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/core_extensions.rb	(revision 18425)
@@ -0,0 +1,141 @@
+# Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+class Time
+  alias :to_str :to_s
+  DAY_NAME = [
+    'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'
+  ]
+  MONTH_NAME = [
+    'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
+  ]
+  def to_s
+    sprintf('%s %s %d %02d:%02d:%02d GMT',
+      DAY_NAME[wday],
+      MONTH_NAME[mon-1], day,
+      hour, min, sec, year) +
+      (
+        off = Time.now.gmtoff
+        sign = off < 0 ? '-' : '+'
+        sprintf('%s%02d%02d', sign, *(off.abs / 60).divmod(60))
+      ) +
+      (
+        sprintf(' %d', year)
+      )
+  end
+  def to_iso
+    offset = Time.now.gmtoff
+    strftime("%Y-%m-%dT%H:%m:%S#{sprintf('%s%02d:%02d', (offset < 0 ? '-' : '+'), *(offset.abs / 60).divmod(60))}")
+  end
+end
+
+class Float
+  alias :to_str :to_s
+  def to_s
+     to_f % 1 == 0 ? to_i.to_s : to_str
+  end
+end
+
+class IO
+  def read__UI8(position = nil)
+    seek position unless position.nil?
+    readchar
+  end
+  
+  def read__UI16(position = nil)
+    seek position unless position.nil?
+    (readchar << 8) + readchar
+  end
+  
+  def read__UI24(position = nil)
+    seek position unless position.nil?
+    (readchar << 16) + (readchar << 8) + readchar
+  end
+  
+  def read__UI32(position = nil)
+    seek position unless position.nil?
+    (readchar << 24) + (readchar << 16) + (readchar << 8) + readchar
+  end
+  
+  def read__STRING(length, position = nil)
+    seek position unless position.nil?
+    read length
+  end
+  
+  
+  def write__UI8(value, position = nil)
+    seek position unless position.nil?
+    write [value].pack('C')
+  end
+  
+  def write__UI24(value, position = nil)
+    seek position unless position.nil?
+    write [value >> 16].pack('c')
+    write [(value >> 8) & 0xff].pack('c')
+    write [value & 0xff].pack('c')
+  end
+  
+  def write__UI32(value, position = nil)
+    seek position unless position.nil?
+    write [value].pack('N')
+  end
+  
+  def write__STRING(string, position = nil)
+    seek position unless position.nil?
+    write string
+  end
+end
+
+class ARGFWrapper
+  def readchar
+    ARGF.readchar
+  end
+  
+  def read(length)
+    ARGF.read(length)
+  end
+  
+  def read__UI8
+    readchar
+  end
+  
+  def read__UI16
+    (readchar << 8) + readchar
+  end
+  
+  def read__UI24
+    (readchar << 16) + (readchar << 8) + readchar
+  end
+  
+  def read__UI32
+    (readchar << 24) + (readchar << 16) + (readchar << 8) + readchar
+  end
+  
+  def read__STRING(length)
+    read length
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/meta_tag.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/meta_tag.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/meta_tag.rb	(revision 18425)
@@ -0,0 +1,78 @@
+# Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+require 'flv/amf_string_buffer'
+require 'miyaml'
+
+module FLV
+  
+  class FLVMetaTag < FLVTag
+    
+    attr_accessor :meta_data, :event
+    
+    def after_initialize(new_object)
+      @tag_type = META
+      unless new_object
+        meta_data_stream = AMFStringBuffer.new(@data)
+        @event = meta_data_stream.read__AMF_data
+        @meta_data = meta_data_stream.read__AMF_data
+      else
+        @event = 'onMetaData'
+        @meta_data = {}
+      end
+    end
+
+    def name
+      "Meta Tag (#{@event})"
+    end
+    
+    def add_meta_data(meta_data)
+      return nil if meta_data.nil?
+      @metadata.update meta_data
+    end
+    
+    def data
+      meta_data_stream = AMFStringBuffer.new('')
+      meta_data_stream.write__AMF_string @event
+      meta_data_stream.write__AMF_data @meta_data
+      meta_data_stream.to_s
+    end
+
+    def [](key)
+      @meta_data[key]
+    end
+
+    def []=(key, value)
+      @meta_data[key] = value
+    end
+
+    def inspect
+      out = super
+      out << "event: #{@event}"
+      out << "meta_data:\n  #{MiYAML.dump(@meta_data, :indent => 2, :boundaries => false)}"
+      out
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/stream.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/stream.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/stream.rb	(revision 18425)
@@ -0,0 +1,492 @@
+# Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+require 'flv/core_extensions'
+require 'flv/tag'
+require 'flv/audio_tag'
+require 'flv/video_tag'
+require 'flv/meta_tag'
+
+
+module FLV
+  
+  class FLVError < StandardError; end
+  class FLVTagError < FLVError; end
+  class FLVStreamError < FLVError; end
+  
+  class FLVStream
+    
+    attr_accessor :signatur,
+                  :version,
+                  :type_flags_audio,
+                  :type_flags_video,
+                  :tags,
+                  :stream_log
+    
+    def initialize(in_stream, out_stream = nil, stream_log = false)
+
+      
+      @stream_log = stream_log ? (File.open('stream.log', File::CREAT|File::WRONLY|File::TRUNC) rescue AMFStringBuffer.new) : AMFStringBuffer.new
+      @in_stream = in_stream
+      @out_stream = out_stream || in_stream
+
+      unless eof?
+        begin
+          read_header
+          read_tags
+        rescue Object => e
+          log e
+          raise e
+        ensure
+          @stream_log.close
+        end
+      else
+        @version = 1
+        @type_flags_audio = false
+        @type_flags_video = false
+        @extra_data = ''
+        @tags = []
+      end
+    end
+    
+    
+    # general
+    def add_tags(tags, stick_on_framerate = true, overwrite = true)
+      tags = [tags] unless tags.kind_of? Array
+      
+      tags.each do |tag|
+        
+        # FIXME: Does not really work for video or audio tags, because tags are
+        #        inserted next to same kind. Normally audio and video tags are 
+        #        alternating.
+        if stick_on_framerate && !framerate.nil? &&framerate != 0 && tag.timestamp % (1000 / framerate) != 0
+          raise FLVTagError, "Could not insert tag. Timestamp #{tag.timestamp} does not fit into framerate."
+          next
+        end
+        
+        after_tag = @tags.detect { |_tag| _tag.timestamp >= tag.timestamp }
+        
+        if after_tag.nil?
+          @tags << tag
+          next
+        end
+
+        if tag.timestamp == after_tag.timestamp && tag.class == after_tag.class
+          if tag.kind_of?(FLVMetaTag) && ( ( tag.event != after_tag.event ) || ( tag.event == after_tag.event && !overwrite ) )
+            @tags.insert( @tags.index(after_tag), tag )
+          else
+            @tags[@tags.index(after_tag)] = tag
+          end
+        else
+          @tags.insert( @tags.index(after_tag), tag )
+        end
+          
+        empty_tag_type_cache
+      end
+      
+      @tags
+    end
+
+    def cut(options = [])
+      @tags.delete_if { |tag| tag.timestamp < ( options[:in_point] || 0 ) || tag.timestamp > ( options[:out_point] || tags.last.timestamp ) }
+      if options[:collapse]
+        difference = @tags.first.timestamp
+        @tags.each { |tag| tag.timestamp -= difference }
+      end
+      empty_tag_type_cache
+    end
+
+    def find_nearest_keyframe_video_tag(position)
+      keyframe_video_tags.sort do |tag_a, tag_b|
+        (position - tag_a.timestamp).abs <=> (position - tag_b.timestamp).abs
+      end.first
+    end
+    
+    def add_meta_tag(meta_data = {})
+      meta_tag = FLVMetaTag.new
+      meta_tag.event = 'onMetaData'
+      
+      meta_tag['framerate'] = framerate
+      meta_tag['duration'] = duration
+      meta_tag['lasttimestamp'] = lasttimestamp
+      meta_tag['videosize'] = videosize
+      meta_tag['audiosize'] = audiosize
+      meta_tag['datasize'] = 0 # calculate after tag was added
+      meta_tag['filesize'] = 0 # calculate after tag was added
+      meta_tag['width'] = (width == 0 && on_meta_data_tag) ? on_meta_data_tag.meta_data['width'] : width
+      meta_tag['height'] = (height == 0 && on_meta_data_tag) ? on_meta_data_tag.meta_data['height'] : height
+      meta_tag['videodatarate'] = videodatarate
+      meta_tag['audiodatarate'] = audiodatarate
+      meta_tag['lastkeyframetimestamp'] = lastkeyframetimestamp
+      meta_tag['audiocodecid'] = audiocodecid
+      meta_tag['videocodecid'] = videocodecid
+      meta_tag['audiodelay'] = audiodelay
+      meta_tag['canSeekToEnd'] = canSeekToEnd
+      meta_tag['stereo'] = stereo
+      meta_tag['audiosamplerate'] = audiosamplerate
+      meta_tag['audiosamplesize'] = audiosamplesize
+      meta_tag['cuePoints'] = cue_points
+      meta_tag['keyframes'] = keyframes
+      meta_tag['hasVideo'] = has_video?
+      meta_tag['hasAudio'] = has_audio?
+      meta_tag['hasMetadata'] = true
+      meta_tag['hasCuePoints'] = has_cue_points?
+      meta_tag['hasKeyframes'] = has_keyframes?
+
+      meta_tag.meta_data.merge!(meta_data)
+      
+      add_tags(meta_tag)
+
+      # recalculate values those need meta tag data size or presence
+      meta_tag['keyframes'] = keyframes
+      meta_tag['datasize'] = datasize
+      meta_tag['filesize'] = filesize
+      meta_tag['hasMetadata'] = has_meta_data?
+    end
+    
+    def write
+
+      begin
+        @out_stream.seek( 0 )
+      rescue Object => e
+      end
+      
+      write_header
+      write_tags
+
+      begin
+        @out_stream.truncate( @out_stream.pos )
+      rescue Object => e
+      end
+    end
+    
+    def close
+      @in_stream.close
+      @out_stream.close
+    end
+
+    
+    # views on tags
+
+    def empty_tag_type_cache
+      @video_tags_cache = nil
+      @keyframe_video_tags_cache = nil
+      @audio_tags_cache = nil
+      @meta_tags_cache = nil
+      @on_cue_point_tags_cache = nil
+    end
+    
+    def video_tags
+      @video_tags_cache ||= @tags.find_all { |tag| tag.kind_of? FLVVideoTag }
+    end
+    
+    def keyframe_video_tags
+      @keyframe_video_tags_cache ||= @tags.find_all do |tag|
+        tag.kind_of?(FLVVideoTag) && tag.frame_type == FLVVideoTag::KEYFRAME
+      end
+    end
+    
+    def audio_tags
+      @audio_tags_cache ||= @tags.find_all { |tag| tag.kind_of? FLVAudioTag }
+    end
+    
+    def meta_tags
+      @meta_tags_cache ||= @tags.find_all { |tag| tag.kind_of? FLVMetaTag }
+    end
+    
+    def on_meta_data_tag
+      @tags.find { |tag| tag.kind_of?(FLVMetaTag) && tag.event == 'onMetaData' } # FIXME: Cannot be cached
+    end
+
+    def on_cue_point_tags
+      @on_cue_point_tags_cache ||= @tags.find_all { |tag| tag.kind_of?(FLVMetaTag) && tag.event == 'onCuePoint' } # FIXME: Cannot be cached
+    end
+
+    def has_video?
+      video_tags.size > 0
+    end
+
+    def has_audio?
+      audio_tags.size > 0
+    end
+
+    def has_meta_data?
+      !on_meta_data_tag.nil?
+    end
+    
+    def has_cue_points?
+      on_cue_point_tags.size > 0
+    end
+
+    def has_keyframes?
+      keyframe_video_tags.size > 0
+    end
+    
+    # meta data
+
+    # FIXME: Could be less complicate and run faster
+    def frame_sequence
+      return nil unless has_video?
+      raise(FLVStreamError, 'File has to contain at least 2 video tags to calculate frame sequence') if video_tags.length < 2
+
+      @frame_sequence ||=
+      begin
+        sequences = video_tags.collect do |tag| # find all sequences
+          video_tags[video_tags.index(tag) + 1].timestamp - tag.timestamp unless tag == video_tags.last
+        end.compact
+        
+        uniq_sequences = (sequences.uniq - [0]).sort # remove 0 and try smallest intervall first 
+        
+        sequence_appearances = uniq_sequences.collect { |sequence| sequences.find_all { |_sequence| sequence == _sequence }.size } # count apperance of each sequence
+        
+        uniq_sequences[ sequence_appearances.index( sequence_appearances.max ) ] # return the sequence that appears most
+      end
+    end
+    
+    def framerate
+      return nil unless has_video?
+      frame_sequence == 0 ? 0 : 1000 / frame_sequence
+    end
+    
+    def duration
+      lasttimestamp
+    end
+    
+    def lasttimestamp
+      last_tag = if has_video?
+          video_tags.last
+        elsif has_audio?
+          audio_tags.last
+        else
+          tags.last
+        end
+      last_tag.timestamp.nil? ? 0 : last_tag.timestamp / 1000.0
+    end
+    
+    def lastkeyframetimestamp
+      return nil unless has_video?
+      (keyframe_video_tags.last.nil? || keyframe_video_tags.last.timestamp.nil?) ? 0 : keyframe_video_tags.last.timestamp / 1000.0
+    end
+    
+    def videosize
+      video_tags.inject(0) { |size, tag| size += tag.size }
+    end
+    
+    def audiosize
+      audio_tags.inject(0) { |size, tag| size += tag.size }
+    end
+    
+    def datasize
+      videosize + audiosize + (meta_tags.inject(0) { |size, tag| size += tag.size})
+    end
+    
+    def filesize
+      # header + data + backpointers 
+      @data_offset + datasize + ((@tags.length + 1) * 4)
+    end
+    
+    def width
+      return nil unless has_video?
+      video_tags.first.width || 0
+    end
+    
+    def height
+      return nil unless has_video?
+      video_tags.first.height || 0
+    end
+    
+    def videodatarate
+      data_size = video_tags.inject(0) do |size, tag|
+        size += tag.data_size
+      end
+      return data_size == 0 ? 0 : data_size / duration * 8 / 1000 # kBits/sec
+    end
+    
+    def audiodatarate
+      data_size = audio_tags.inject(0) do |size, tag|
+        size += tag.data_size
+      end
+      return data_size == 0 ? 0 : data_size / duration * 8 / 1000 # kBits/sec
+    end
+
+    def stereo
+      audio_tags.first && audio_tags.first.sound_type == FLVAudioTag::STEREO
+    end
+
+    def audiosamplerate
+      audio_tags.first && audio_tags.first.sound_rate
+    end
+
+    def audiosamplesize
+      audio_tags.first && audio_tags.first.sound_sample_size
+    end
+    
+    def audiocodecid
+      audio_tags.first && audio_tags.first.sound_format
+    end
+
+    def videocodecid
+      return nil unless has_video?
+      video_tags.first.codec_id
+    end
+
+    def audiodelay
+      return 0 unless has_video?
+      video_tags.first.timestamp.nil? ? 0 : video_tags.first.timestamp / 1000.0
+    end
+
+    def canSeekToEnd
+      return true unless has_video?
+      video_tags.last.frame_type == FLVVideoTag::KEYFRAME
+    end
+
+    def keyframes
+      object = Object.new
+      
+      calculate_tag_byte_offsets
+      
+      object.instance_variable_set( :@times, keyframe_video_tags.collect { |video_tag| video_tag.timestamp / 1000.0 } )
+      object.instance_variable_set( :@filepositions, keyframe_video_tags.collect { |video_tag| video_tag.byte_offset } )
+      
+      return object
+    end
+
+    def cue_points
+      on_cue_point_tags.collect { |tag| tag.meta_data }
+    end
+    
+    def <<(tags)
+      add_tags tags, true
+    end
+    
+    private
+      def calculate_tag_byte_offsets
+        @tags.inject(@data_offset + 4) { |offset, tag| tag.byte_offset = offset; offset += 4 + tag.size }
+      end
+    
+      def read_header
+        begin
+          @signature = @in_stream.read__STRING(3)
+          log "File signature: #{@signature}"
+          raise(FLVStreamError, 'IO is not a FLV stream. Wrong signature.') if @signature != 'FLV'
+          
+          @version = @in_stream.read__UI8
+          log "File version: #{@version}"
+          
+          type_flags = @in_stream.read__UI8
+          @type_flags_audio = (type_flags & 4) == 1
+          log "File has audio: #{@type_flags_audio}"
+          
+          @type_flags_video = (type_flags & 1) == 1
+          log "File has video: #{@type_flags_video}"
+          
+          @data_offset = @in_stream.read__UI32
+          log "File header size: #{@data_offset}"
+          
+          @extra_data = @in_stream.read__STRING @data_offset - 9
+          log "File header extra data: #{@extra_data}"
+          
+        rescue IOError => e
+          raise IOError, "IO Error while reading FLV header. #{e.message}", e.backtrace
+        end
+      end
+      
+      def write_header
+        begin
+          @out_stream.write__STRING 'FLV'
+          @out_stream.write__UI8 1
+          type_flags = 0
+          type_flags += 4 if has_audio?
+          type_flags += 1 if has_video?
+          @out_stream.write__UI8 type_flags
+          @out_stream.write__UI32 9 + @extra_data.length
+          @out_stream.write__STRING @extra_data
+        rescue IOError => e
+          raise IOError, "IO Error while writing FLV header. #{e.message}", e.backtrace
+        end
+      end
+      
+      def read_tags
+        @tags ||= []
+        
+        while true
+          break if eof?
+          previous_tag_length = @in_stream.read__UI32
+          log "Previous tag length: #{previous_tag_length}"
+          
+          break if eof?
+          log "Tag number: #{@tags.size + 1}"
+          tag_type = @in_stream.read__UI8
+          log "Tag type: #{FLVTag.type2name(tag_type)}"
+
+          break if eof?
+          case tag_type
+          when FLVTag::AUDIO
+            @tags << FLVAudioTag.new(@in_stream)
+          when FLVTag::VIDEO
+            @tags << FLVVideoTag.new(@in_stream)
+          when FLVTag::META
+            @tags << FLVMetaTag.new(@in_stream)
+          else
+            @tags << FLVTag.new(@in_stream)
+          end
+
+        end
+        
+        if $VERBOSE
+          total_known_tags =
+            audio_tags.size + video_tags.size + meta_tags.size
+          out =  "Read tags: #{audio_tags.size} audio, #{video_tags.size} video,"
+          out << " #{meta_tags.size} meta,"
+          out << " #{@tags.size - total_known_tags} unknown,"
+          out << " #{@tags.size} total\n"
+          puts out
+        end
+      end
+      
+      def write_tags
+        
+        @out_stream.write__UI32 0
+
+        count = 0
+        @tags.each do |tag|
+          tag.serialize @out_stream
+          @out_stream.write__UI32 tag.size
+          count += 1
+          puts "[#{count}]#{tag.inspect}\n" if $VERBOSE
+        end
+
+        puts "Wrote tags: #{count} total" if $VERBOSE
+      end
+
+      def log(msg)
+        @stream_log << msg.to_s + "\n"
+      end
+
+      def eof?
+        @in_stream.eof?
+      end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/tag.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/tag.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/tag.rb	(revision 18425)
@@ -0,0 +1,120 @@
+# Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+require 'flv/core_extensions'
+require 'flv/stream'
+
+
+module FLV
+  
+  class FLVTag
+    
+    AUDIO = 8
+    VIDEO = 9
+    META = 18
+    UNDEFINED = 0
+    
+    attr_accessor :tag_type,
+                  :timestamp,
+                  :byte_offset
+    
+    def initialize(stream = nil)
+      @tag_type = UNDEFINED
+      @byte_offset = nil
+      
+      unless stream.nil?
+        data_size = stream.read__UI24
+        @timestamp = stream.read__UI24
+        stream.read__UI32
+        @data = stream.read(data_size)
+      else
+        @timestamp = 0
+        @data = ''
+      end
+      after_initialize(stream.nil?) if respond_to? :after_initialize
+    end
+    
+    def size
+      # header(11) + body(data_size)
+      11 + data_size
+    end
+
+    def name
+      'Unknown Tag'
+    end
+    
+    def data
+      @data
+    end
+    
+    def data_size
+      data.length
+    end
+    
+    def serialize(stream)
+      stream.write__UI8 tag_type
+      stream.write__UI24 data_size
+      stream.write__UI24 timestamp
+      stream.write__UI32 0
+      stream.write__STRING data
+    end
+
+    def info
+      "#{name}: timestamp #{timestamp}, size #{size}, data size #{data_size}"
+    end
+
+    def inspect
+      out = ["tag: #{self.class}"]
+      out << "timestamp: #{@timestamp}"
+      out << "size: #{size}"
+      out << "data_size: #{data_size}"
+      out
+    end
+
+    def self.type2name(type)
+      case type
+      when AUDIO
+        'audio'
+      when VIDEO
+        'video'
+      when META
+        'meta'
+      when UNDEFINED
+        'undefined'
+      else
+        "unknown(#{type})"
+      end
+    end
+    
+    private
+      def bit2uint(sequence)
+        int = 0
+        sequence.split(//).each_with_index do |character, i|
+          int += 2 ** (sequence.length - i - 1) if character == '1'
+        end
+        int
+      end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/video_tag.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/video_tag.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flv/video_tag.rb	(revision 18425)
@@ -0,0 +1,114 @@
+# Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+require 'flv/amf_string_buffer'
+
+module FLV
+  
+  class FLVVideoTag < FLVTag
+    
+    H263VIDEOPACKET = 2
+    SCREENVIDEOPACKET = 3
+    ON2VP6 = 4
+
+    KEYFRAME = 1
+    INTERFRAME = 2
+    DISPOSABLEINTERFRAME = 3
+
+    attr_reader :frame_type,
+                :codec_id,
+                :width,
+                :height
+    
+    def after_initialize(new_object)
+      @tag_type = VIDEO
+      read_header
+    end
+
+    def name
+      case frame_type
+      when KEYFRAME
+        'Video Tag (Keyframe)'
+      when INTERFRAME
+        'Video Tag (Interframe)'
+      when DISPOSABLEINTERFRAME
+        'Video Tag (disposable Interframe)'
+      else
+        'Video Tag'
+      end
+    end
+
+    def keyframe?
+      frame_type == KEYFRAME
+    end
+
+    def interframe?
+      frame_type == INTERFRAME || frame_type == DISPOSABLEINTERFRAME
+    end
+    
+    def read_header
+      data_stream = AMFStringBuffer.new(@data)
+
+      # the sequence is swaped in the swf-file-format description
+      # frame_type <-> codec_id (description: 1. codec_id, 2. frame_type)
+      codec_id_and_frame_type = data_stream.read__UI8
+      @frame_type = codec_id_and_frame_type >> 4
+      @codec_id = codec_id_and_frame_type & 0xf
+
+      bit_sequence = data_stream.read(9).unpack('B72').to_s
+      
+      if @codec_id == H263VIDEOPACKET
+        @width, @height = case bit2uint bit_sequence[30,3]
+        when 0
+          [bit2uint(bit_sequence[33,8]), bit2uint(bit_sequence[41,8])]
+        when 1
+          [bit2uint(bit_sequence[33,16]), bit2uint(bit_sequence[49,16])]
+        when 2
+          [352, 288]
+        when 3
+          [176, 144]
+        when 4
+          [128, 96]
+        when 5
+          [320, 240]
+        when 6
+          [160, 120]
+        end
+      elsif @codec_id == SCREENVIDEOPACKET
+        @width, @height = bit2uint(bit_sequence[4,12]), bit2uint(bit_sequence[16,12])
+      end
+    end
+
+    def inspect
+      out = super
+      out << "frame_type: #{%w{ Keyframe Interframe DisposableInterframe }[@frame_type]}"
+      out << "codec_id: #{@codec_id}"
+      out << "width: #{@width}"
+      out << "height: #{@height}"
+      out << "data_size: #{data_size}"
+      out
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flvtool2.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flvtool2.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flvtool2.rb	(revision 18425)
@@ -0,0 +1,230 @@
+# Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+require 'flvtool2/version'
+require 'flvtool2/base'
+
+module FLVTool2
+  
+  SHELL_COMMAND_NAME = (RUBY_PLATFORM =~ /win32/) ? 'flvtool2.exe' : 'flvtool2'
+  SWITCHES = %w{ s v r p x c i o k t n l a }
+  COMMANDS = %w{ U C P D A V }
+  
+  def self.parse_arguments
+    options = {}
+    options[:commands] = []
+    options[:metadatacreator] = "inlet media FLVTool2 v#{PROGRAMM_VERSION.join('.')} - http://www.inlet-media.de/flvtool2"
+    options[:metadata] = {}
+    options[:in_path] = nil
+    options[:in_pipe] = false
+    options[:out_path] = nil
+    options[:out_pipe] = false
+    options[:simulate] = false
+    options[:verbose] = false
+    options[:recursive] = false
+    options[:preserve] = false
+    options[:xml] = false
+    options[:compatibility_mode] = false
+    options[:in_point] = nil
+    options[:out_point] = nil
+    options[:keyframe_mode] = false
+    options[:tag_file] = nil
+    options[:tag_number] = nil
+    options[:stream_log] = false
+    options[:collapse] = false
+
+    while (arg = ARGV.shift)
+      case arg
+      when /^-([a-zA-Z0-9]+?):(.+)$/
+        options[:metadata][$1] = $2
+      when /^-([a-zA-Z0-9]+?)#([0-9]+)$/
+        options[:metadata][$1] = $2.to_f
+      when /^-([a-zA-Z0-9]+?)@(\d{4,})-(\d{2,})-(\d{2,}) (\d{2,}):(\d{2,}):(\d{2,})$/
+        options[:metadata][$1] = Time.local($2, $3, $4, $5, $6, $7)
+      when /^-(.+)$/
+        $1.split(//).flatten.each do |switch|  
+          case switch
+          when 's'
+            options[:simulate] = true
+          when 'v'
+            options[:verbose] = true
+          when 'r'
+            options[:recursive] = true
+          when 'p'
+            options[:preserve] = true
+          when 'x'
+            options[:xml] = true
+          when 'c'
+            options[:compatibility_mode] = true
+          when 'i'
+            options[:in_point] = ARGV.shift.to_i
+          when 'o'
+            options[:out_point] = ARGV.shift.to_i
+          when 'k'
+            options[:keyframe_mode] = true
+          when 't'
+            options[:tag_file] = ARGV.shift
+          when 'n'
+            options[:tag_number] = ARGV.shift.to_i
+          when 'l'
+            options[:stream_log] = true
+          when 'a'
+            options[:collapse] = true
+          when 'U'
+            options[:commands] << :update
+          when 'P'
+            options[:commands] << :print
+          when 'C'
+            options[:commands] << :cut
+          when 'D'
+            options[:commands] << :debug
+          when 'A'
+            options[:commands] << :add
+          when 'H'
+            options[:commands] << :help
+          when 'V'
+            options[:commands] << :version
+          end
+        end
+      when /^([^-].*)$/
+        if options[:in_path].nil? 
+          options[:in_path] = $1
+          if options[:in_path].downcase =~ /stdin|pipe/
+            options[:in_pipe] = true
+            options[:in_path] = 'pipe'
+          else
+            options[:in_path] = File.expand_path( options[:in_path] )
+          end
+        else
+          options[:out_path] = $1
+          if options[:out_path].downcase =~ /stdout|pipe/
+            options[:out_pipe] = true
+            options[:out_path] = 'pipe'
+          else
+            options[:out_path] = File.expand_path( options[:out_path] )
+          end
+        end
+      end
+    end
+    
+    return options
+  end
+  
+  def self.validate_options( options )
+    if options[:commands].empty?
+      show_usage
+      exit 0
+    end
+    
+    options[:commands].each do |command|  
+      case command
+      when :print
+        if options[:out_pipe]
+          throw_error "Could not use print command in conjunction with output piping or redirection"
+          exit 1
+        end
+      when :debug
+        if options[:out_pipe]
+          throw_error "Could not use debug command in conjunction with output piping or redirection"
+          exit 1
+        end
+      when :help
+        show_usage
+        exit 0
+      when :version
+        show_version
+        exit 0
+      end
+    end
+    options
+  end
+  
+  def self.execute!(options)
+    if options[:commands].include? :help
+      show_usage
+    else
+      FLVTool2::Base::execute!( options )
+    end
+  end
+
+  def self.show_version
+    puts "FLVTool2 #{version}"
+  end
+  
+  def self.show_usage
+    self.show_version
+    puts "Copyright (c) 2005-2007 Norman Timmler (inlet media e.K., Hamburg, Germany)\n"
+    puts "Get the latest version from http://www.inlet-media.de/flvtool2\n"
+    puts "This program is published under the BSD license.\n"
+    puts "\n"
+    puts "Usage: #{SHELL_COMMAND_NAME} [-#{COMMANDS.sort.join}#{SWITCHES.sort.join}]... [-key:value]... in-path|stdin [out-path|stdout]\n"
+    puts "\n"
+    puts "If out-path is omitted, in-path will be overwritten.\n"
+    puts "In-path can be a single file, or a directory. If in-path is a directory,\n"
+    puts "out-path has to be likewise, or can be omitted. Directory recursion\n"
+    puts "is controlled by the -r switch. You can use stdin and stdout keywords\n"
+    puts "as in- and out-path for piping or redirecting.\n"
+    puts "\n"
+    puts "Chain commands like that: -UP (updates FLV file than prints out meta data)\n"
+    puts "\n"
+    puts "Commands:\n"
+    puts "  -A            Adds tags from -t tags-file\n"
+    puts "  -C            Cuts file using -i inpoint and -o outpoint\n"
+    puts "  -D            Debugs file (writes a lot to stdout)\n"
+    puts "  -H            Helpscreen will be shown\n"
+    puts "  -P            Prints out meta data to stdout\n"
+    puts "  -U            Updates FLV with an onMetaTag event\n"
+    puts "\n"
+    puts "Switches:\n"
+    puts "  -a            Collapse space between cutted regions\n"
+    puts "  -c            Compatibility mode calculates some onMetaTag values different\n"
+    puts "  -key:value    Key-value-pair for onMetaData tag (overwrites generated values)\n"
+    puts "  -i timestamp  Inpoint for cut command in miliseconds\n"
+    puts "  -k            Keyframe mode slides onCuePoint(navigation) tags added by the\n"
+    puts "                add command to nearest keyframe position\n"
+    puts "  -l            Logs FLV stream reading to stream.log in current directory\n"
+    puts "  -n            Number of tag to debug\n"
+    puts "  -o timestamp  Outpoint for cut command in miliseconds\n"
+    puts "  -p            Preserve mode only updates FLVs that have not been processed\n"
+    puts "                before\n"
+    puts "  -r            Recursion for directory processing\n"
+    puts "  -s            Simulation mode never writes FLV data to out-path\n"
+    puts "  -t path       Tagfile (MetaTags written in XML)\n"
+    puts "  -v            Verbose mode\n"
+    puts "  -x            XML mode instead of YAML mode\n"
+    puts "\n"
+    puts "REPORT BUGS at http://projects.inlet-media.de/flvtool2"
+    puts "Powered by Riva VX, http://rivavx.com\n"
+  end
+  
+  def self.throw_error(error)
+    puts "ERROR: #{error}"
+  end
+end
+
+
+FLVTool2::execute!( FLVTool2::validate_options( FLVTool2::parse_arguments ) )
+exit 0
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flvtool2/base.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flvtool2/base.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flvtool2/base.rb	(revision 18425)
@@ -0,0 +1,297 @@
+# Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+require 'flv'
+require 'mixml'
+require 'miyaml'
+
+module FLVTool2
+  
+  module Base
+
+    class << self
+    
+      def execute!(options)
+  
+        options[:commands].each do |command|
+          before_filter = "before_#{command.to_s}".intern
+          send(before_filter, options) if respond_to? before_filter
+        end
+        
+        process_files(options) do |stream, in_path, out_path|
+          write_stream = false
+          options[:commands].each do |command|
+            write_stream = true if send( command, options, stream, in_path, out_path )
+          end
+          stream.write if write_stream && !options[:simulate]
+        end
+  
+        options[:commands].each do |command|
+          after_filter = "after_#{command.to_s}".intern
+          send(after_filter, options) if respond_to? after_filter
+        end
+      end
+  
+  
+      def add(options, stream, in_path, out_path)
+        tag_structures = MiXML.parse( File.open( options[:tag_file], File::RDONLY ) { |file| file.readlines }.join )
+  
+        add_tag = Proc.new do |data|  
+          
+          tag = FLV::FLVMetaTag.new
+  
+          overwrite = ( data['overwrite'] && data['overwrite'].downcase ) == 'true' || false
+          data.delete( 'overwrite' )
+          
+          tag.event = data['event'] || 'event'
+          data.delete( 'event' )
+          
+          tag.timestamp = ( data['timestamp'] && data['timestamp'].to_i ) || 0
+          tag.timestamp = stream.find_nearest_keyframe_video_tag(tag.timestamp).timestamp if options[:keyframe_mode] && data['type'] == 'navigation'
+          data.delete( 'timestamp' )
+          data['time'] = tag.timestamp / 1000
+          
+          tag.meta_data.merge!( data )
+  
+          stream.add_tags( tag, false, overwrite )
+        end
+        
+        tag_structures['tags'].each do |tag_name, value|
+          case tag_name
+          when 'metatag'
+            if value.class == Array
+              value.each { |_value| add_tag.call( _value ) } 
+            else
+              add_tag.call( value )
+            end
+          else
+          end
+        end
+        
+        return true
+      end
+  
+      
+      def debug(options, stream, in_path, out_path)
+  
+        puts "---\n"
+        puts "path: #{in_path}"
+      
+        unless stream.nil?
+          if options[:tag_number]
+            puts "  tag_number: #{options[:tag_number]}"
+            puts "  " + stream.tags[ options[:tag_number] - 1 ].inspect.join( "\n  " )
+          else
+            stream.tags.each_with_index do |tag, index|
+              puts "##{index + 1} #{tag.info}"
+            end
+          end
+        end
+  
+        return false
+      end
+  
+      
+      def cut(options, stream, in_path, out_path)
+  
+        in_point = options[:keyframe_mode] ? stream.find_nearest_keyframe_video_tag(options[:in_point] || 0).timestamp : options[:in_point]
+        stream.cut( :in_point => in_point, :out_point => options[:out_point], :collapse => options[:collapse] )
+  
+        return true
+      end
+  
+      
+      def update(options, stream, in_path, out_path)
+        
+        if ( 
+              options[:preserve] && 
+              ( 
+                !stream.on_meta_data_tag ||
+                ( stream.on_meta_data_tag && stream.on_meta_data_tag.meta_data['metadatacreator'] != options[:metadatacreator] ) 
+              ) 
+           ) || !options[:preserve]
+          
+          add_meta_data_tag( stream, options )
+  
+          return true
+        else
+          puts 'Input file is FLV v1.1 yet. No update necessary.' if options[:verbose]
+          
+          return false
+        end
+      end
+  
+      
+      def before_print(options)
+        puts "<?xml version=\"1.0\"?>\n<fileset>" if options[:xml]
+      end
+      
+      def print(options, stream, in_path, out_path)
+        
+        if options[:xml]
+          puts "  <flv name=\"#{in_path}\">"
+          puts MiXML.dump( stream.on_meta_data_tag && stream.on_meta_data_tag.meta_data, 2 )
+          puts "  </flv>"
+        else
+          puts MiYAML.dump( { in_path => ( stream.on_meta_data_tag && stream.on_meta_data_tag.meta_data ) } )
+        end
+  
+        return false
+      end
+  
+      def object_to_hash(object)
+        object.instance_variables.inject( {} ) do |hash, variable|
+          hash[variable.gsub('@', '')] = object.instance_variable_get( variable.intern )
+          hash
+        end
+      end
+      
+      def after_print(options)
+        puts '</fileset>' if options[:xml]
+      end
+  
+  
+      def add_meta_data_tag(stream, options)
+        # add onLastSecond tag
+        onlastsecond = FLV::FLVMetaTag.new
+        onlastsecond.event = 'onLastSecond'
+        onlastsecond.timestamp = ((stream.duration - 1) * 1000).to_int
+        stream.add_tags(onlastsecond, false) if onlastsecond.timestamp >= 0
+  
+        stream.add_meta_tag({ 'metadatacreator' => options[:metadatacreator], 'metadatadate' => Time.now }.merge(options[:metadata]))
+        unless options[:compatibility_mode]
+          stream.on_meta_data_tag.meta_data['duration'] += (stream.frame_sequence || 0) / 1000.0
+        end
+      end
+  
+  
+  
+      
+      def process_files(options)
+  
+        if options[:in_pipe]
+  
+          unless options[:omit_out] || options[:out_path].nil?
+            create_directories_for_path( options[:out_path] )
+            out_path = options[:out_path]
+          else
+            out_path = nil
+          end
+          
+          begin
+            stream = open_stream( 'pipe', out_path )
+            yield stream, 'pipe', out_path
+            begin
+              stream.close
+            rescue
+            end
+            
+          rescue Exception => e
+            show_exception(e, options)
+          end
+          
+        else
+        
+          if File.directory?( options[:in_path] )
+            pattern = options[:recursive] ? "#{File::SEPARATOR}**#{File::SEPARATOR}*.flv" : "#{File::SEPARATOR}*.flv"
+            file_names = Dir[options[:in_path] + pattern]
+          else
+            file_names = [options[:in_path]]
+          end
+          
+          file_names.each do |in_path|
+  
+            if options[:out_pipe]
+              out_path = 'pipe'
+            else
+              out_path = options[:out_path]
+              unless options[:out_path].nil?
+                out_path = in_path.gsub( options[:in_path], options[:out_path] )
+                create_directories_for_path( out_path )
+              end
+            end
+            
+            begin
+              stream = open_stream( in_path, out_path, options[:stream_log] )
+              yield stream, in_path, out_path
+  
+              begin
+                stream.close
+              rescue
+              end
+              
+            rescue Exception => e
+              show_exception(e, options)
+            end
+          end
+        end
+      end
+  
+      def open_stream(in_path, out_path = nil, stream_log = false)
+        attributes = (RUBY_PLATFORM =~ /win32/) ? File::BINARY : 0
+  
+        if in_path == 'pipe'
+          in_stream = $stdin
+        elsif in_path == out_path || out_path.nil?
+          in_stream = File.open( in_path, File::RDWR|attributes )
+        else
+          in_stream = File.open( in_path, File::RDONLY|attributes )
+        end
+  
+        if out_path == 'pipe' || ( in_path == 'pipe' && out_path.nil? )
+          out_stream = $stdout
+        elsif in_path != out_path && !out_path.nil?
+          out_stream = File.open( out_path, File::CREAT|File::WRONLY|attributes )
+        else
+          out_stream = nil
+        end
+        
+        FLV::FLVStream.new( in_stream, out_stream, stream_log )
+      end
+      
+      def create_directories_for_path(path_to_build)
+        parts = path_to_build.split(File::SEPARATOR)
+        parts.shift #removes '/' or 'c:\'
+        parts.pop # removes filename
+        
+        parts.inject('') do |path, dir|
+          begin
+            path += File::SEPARATOR + dir
+            Dir.mkdir path
+          rescue Object => e
+            raise e unless File.directory?(path)
+          end
+          path
+        end
+      end
+  
+      def show_exception(e, options)
+        puts "ERROR: #{e.message}\nERROR: #{e.backtrace.join("\nERROR: ")}"
+        puts "Skipping file #{options[:in_path]}\n" if options[:verbose]
+      end
+    end
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flvtool2/version.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flvtool2/version.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/flvtool2/version.rb	(revision 18425)
@@ -0,0 +1,10 @@
+module FLVTool2
+
+  PROGRAMM_VERSION = [1, 0, 6]
+  PROGRAMM_VERSION_EXTENSION = ''
+  
+  def self.version
+    "#{PROGRAMM_VERSION.join('.')}#{PROGRAMM_VERSION_EXTENSION}"
+  end  
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/mixml.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/mixml.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/mixml.rb	(revision 18425)
@@ -0,0 +1,119 @@
+# Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+class MiXML
+
+  def self.parse(xml)
+    current = {}
+    xml.scan( /<([!\?].*?)>|<([^\/].*?)>|<\/(.+?)>|([^<>]*)/m ) do |ignore, open_tag, close_tag, cdata|  
+      if open_tag
+        tag_name = open_tag.match( /(\w+)\s?/ )[1]
+        
+        parameters = {}
+        open_tag.scan( /(\w+)=\"(.*?)\"/ ) { |key, value| parameters[key] = value }
+
+        parameters[:parent] = current
+        
+        if current[tag_name].class == Array
+          current[tag_name] << parameters
+          current = current[tag_name].last
+        else
+          if current[tag_name]
+            current[tag_name] = [ current[tag_name], parameters ]
+            current = current[tag_name].last
+          else
+            current[tag_name] = parameters
+            current = current[tag_name]
+          end
+        end
+        
+      elsif close_tag
+        parent = current[:parent]
+        current.delete( :parent )
+        current = parent unless parent.nil?
+      elsif cdata
+        cdata.strip!
+        current[:cdata] = cdata unless cdata.empty?
+      end
+    end
+
+    return normalize_cdata( current )
+  end
+
+  def self.normalize_cdata(branch)
+    if branch.class == Array
+      branch.collect do |item|
+        normalize_cdata( item )
+      end
+    elsif branch.class == Hash && branch[:cdata].nil?
+      branch.inject( {} ) do |hash, key_value|
+        key, value = key_value
+        value = normalize_cdata( value )
+        hash[key] = value
+        hash
+      end
+    else
+      if branch[:cdata] && branch.size == 1
+        branch[:cdata]
+      else
+        branch
+      end
+    end
+  end
+  
+  def self.dump(object, indent = 0)
+    '  ' * indent << dump_object(object, indent).strip
+  end
+  
+  def self.dump_object(object, indent = 0)
+    xml = ''
+    
+    if object.class == Object
+      object = object.instance_variables.inject( {} ) { |hash, var| hash[var.gsub('@', '')] = object.instance_variable_get(var); hash }
+    end
+    
+    case object
+    when Array
+      object.each do |value|
+        xml << indenter(indent) << "<value>" << dump_object( value, indent + 1 ) << "</value>"
+      end
+      xml << indenter(indent - 1)
+    when Hash
+      object.each do |key, value|
+        xml << indenter(indent) << "<#{key}>" << dump_object( value, indent + 1 ) << "</#{key}>"
+      end
+      xml << indenter(indent - 1)
+    else
+      xml << object.to_s
+    end
+    
+    return xml
+  end
+
+  def self.indenter(indent = 0)
+    "\n" << '  ' * indent
+  end
+end
+
Index: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/miyaml.rb
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/miyaml.rb	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/site_ruby/1.8/miyaml.rb	(revision 18425)
@@ -0,0 +1,63 @@
+# Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany)
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+class MiYAML
+
+  def self.dump(object, options = {})
+    options = { :indent => 0, :boundaries => true }.merge( options )
+
+    out = (options[:boundaries] ? "---\n" : '')
+    out << dump_object(object, options[:indent]).strip
+    out << (options[:boundaries] ? "\n...\n" : '')
+    out
+  end
+  
+  def self.dump_object(object, indent = 0)
+    yaml = ''
+    
+    if object.class == Object
+      object = object.instance_variables.inject( {} ) { |hash, var| hash[var.gsub('@', '')] = object.instance_variable_get(var); hash }
+    end
+    
+    case object
+    when Array
+      object.each do |value|
+         yaml << indenter(indent) << '- ' << dump_object( value, indent + 1 )
+      end
+    when Hash
+      object.each do |key, value|
+        yaml << indenter(indent) << "#{key}: " << dump_object( value, indent + 1 )
+      end
+    else
+      yaml << object.to_s
+    end
+    
+    return yaml
+  end
+
+  def self.indenter(indent = 0)
+    "\n" << '  ' * indent
+  end
+end
Index: extensions/gsdl-video/trunk/installed/cmdline/man/man1/a52dec.1
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/man/man1/a52dec.1	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/man/man1/a52dec.1	(revision 18425)
@@ -0,0 +1,46 @@
+.TH a52dec "1" "a52dec"
+.SH NAME
+a52dec \- decode ATSC A/52 audio streams
+.SH SYNOPSIS
+.B a52dec
+[\fI-h\fR] [\fI-s [track]\fR] [\fI-t pid\fR] [\fI-c\fR] [\fI-r\fR] [\fI-o mode\fR] [\fIfile\fR]
+.SH DESCRIPTION
+`a52dec' plays ATSC A/52 audio streams.
+Input is from stdin if no file is given.
+.TP
+\fB\-h\fR
+display help and available audio modes
+.TP
+\fB\-s\fR
+use program stream demultiplexer, track 0-7 or 0x80-0x87
+.TP
+\fB\-t pid\fR
+use transport stream demultiplexer, pid 0x10-0x1ffe
+.TP
+\fB\-c\fR
+use c implementation, disables all accelerations
+.TP
+\fB\-r\fR
+disable dynamic range compression
+.TP
+\fB\-o\fR \fImode\fR
+use audio output driver `mode'.
+.br
+A list of modes is available using the \fB\-h\fR option.
+.SH AUTHORS
+Michel Lespinasse <walken@zoy.org>
+.br
+Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+.br
+And many others on the net.
+.SH "REPORTING BUGS"
+Report bugs to <liba52-devel@lists.sourceforge.net>.
+.SH COPYRIGHT
+Copyright \(co 2000-2002 Michel Lespinasse
+.br
+Copyright \(co 1999-2000 Aaron Holtzman
+.br
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+.BR extract_a52 "(1)"
Index: extensions/gsdl-video/trunk/installed/cmdline/man/man1/extract_a52.1
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/man/man1/extract_a52.1	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/man/man1/extract_a52.1	(revision 18425)
@@ -0,0 +1,35 @@
+.TH extract_a52 "1" "extract_a52"
+.SH NAME
+extract_a52 \- extract ATSC A/52 audio from a MPEG stream.
+.SH SYNOPSIS
+.B extract_a52
+[\fI-h\fR] [\fI-s [track]\fR] [\fI-t pid\fR] [\fIfile\fR]
+.SH DESCRIPTION
+`extract_a52' extracts ATSC A/52 audio from a MPEG stream.
+Input is from stdin if no file is given.
+.TP
+\fB\-h\fR
+display help
+.TP
+\fB\-s track\fR
+set track number (0-7 or 0x80-0x87)
+.TP
+\fB\-t pid\fR
+use transport stream demultiplexer, pid 0x10-0x1ffe
+.SH AUTHORS
+Michel Lespinasse <walken@zoy.org>
+.br
+Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+.br
+And many others on the net.
+.SH "REPORTING BUGS"
+Report bugs to <liba52-devel@lists.sourceforge.net>.
+.SH COPYRIGHT
+Copyright \(co 2000-2002 Michel Lespinasse
+.br
+Copyright \(co 1999-2000 Aaron Holtzman
+.br
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+.BR a52dec "(1)"
Index: extensions/gsdl-video/trunk/installed/cmdline/man/man1/lame.1
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/man/man1/lame.1	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/man/man1/lame.1	(revision 18425)
@@ -0,0 +1,1233 @@
+.TH lame 1 "August 03, 2005" "" "LAME audio compressor"
+.SH NAME
+lame \- create mp3 audio files
+.SH SYNOPSIS
+lame [options] <infile> <outfile>
+.SH DESCRIPTION
+.PP
+LAME is a program which can be used to create compressed audio files.
+(Lame ain't an MP3 encoder).
+These audio files can be played back by popular MP3 players such as
+mpg123 or madplay.
+To read from stdin, use "\-" for <infile>.
+To write to stdout, use a "\-" for <outfile>.
+.SH OPTIONS
+Input options:
+.TP
+.B \-r
+Assume the input file is raw pcm.
+Sampling rate and mono/stereo/jstereo must be specified on the command line.
+Without
+.B \-r,
+LAME will perform several
+.I fseek()'s
+on the input file looking for WAV and AIFF headers.
+.br
+Might not be available on your release. 
+.TP
+.B \-x
+Swap bytes in the input file or output file when using
+.B \-\-decode.
+.br
+For sorting out little endian/big endian type problems.
+If your encodings sounds like static,
+try this first.
+.br
+Without using
+.B \-x,
+LAME will treat input file as native endian.
+.TP
+.BI \-s " sfreq"
+.I sfreq
+= 8/11.025/12/16/22.05/24/32/44.1/48
+
+Required only for raw PCM input files.
+Otherwise it will be determined from the header of the input file.
+
+LAME will automatically resample the input file to one of the supported
+MP3 samplerates if necessary.
+.TP
+.BI \-\-bitwidth " n"
+Input bit width per sample.
+.br
+.I n
+= 8, 16, 24, 32 (default 16)
+
+Required only for raw PCM input files.
+Otherwise it will be determined from the header of the input file.
+.TP
+.BI \-\-signed
+Instructs LAME that the samples from the input are signed (the default).
+
+Required only for raw PCM input files
+and only available if LAME was compiled with libsndfile.
+.TP
+.BI \-\-unsigned
+Instructs LAME that the samples from the input are unsigned.
+
+Required only for raw PCM input files
+and only available if LAME was compiled with libsndfile.
+.TP
+.BI \-\-little-endian
+Instructs LAME that the samples from the input are in little-endian form.
+
+Required only for raw PCM input files
+and only available if LAME was compiled with libsndfile.
+.TP
+.BI \-\-big-endian
+Instructs LAME that the samples from the input are in big-endian form.
+
+Required only for raw PCM input files
+and only available if LAME was compiled with libsndfile.
+.TP
+.B \-\-mp2input
+Assume the input file is a MPEG Layer II (ie MP2) file.
+.br
+If the filename ends in ".mp2" LAME will assume it is a MPEG Layer II file.
+For stdin or Layer II files which do not end in .mp2 you need to use
+this switch. 
+.TP
+.B \-\-mp3input
+Assume the input file is a MP3 file.
+.br
+Useful for downsampling from one mp3 to another.
+As an example,
+it can be useful for streaming through an IceCast server.
+.br
+If the filename ends in ".mp3" LAME will assume it is an MP3.
+For stdin or MP3 files which do not end in .mp3 you need to use this switch. 
+.TP
+.BI \-\-nogap " file1 file2 ..."
+gapless encoding for a set of contiguous files
+.TP
+.BI \-\-nogapout " dir"
+output dir for gapless encoding (must precede \-\-nogap)
+
+.PP
+Operational options:
+.TP
+.BI \-m  " mode"
+.I mode
+= s, j, f, d, m
+
+Joint-stereo is the default mode for stereo files with VBR when
+.B \-V
+is more than 4 or fixed bitrates of 160kbs or less.
+At higher fixed bitrates or higher VBR settings,
+the default is stereo. 
+
+.B (s)tereo 
+.br
+In this mode,
+the encoder makes no use of potentially existing correlations between
+the two input channels.
+It can,
+however,
+negotiate the bit demand between both channel,
+i.e. give one channel more bits if the other contains silence or needs
+less bits because of a lower complexity.
+
+.B (j)oint stereo
+.br
+In this mode,
+the encoder will make use of a correlation between both channels.
+The signal will be matrixed into a sum ("mid"),
+computed by L+R,
+and difference ("side") signal,
+computed by L\-R,
+and more bits are allocated to the mid channel.
+This will effectively increase the bandwidth if the signal does not
+have too much stereo separation,
+thus giving a significant gain in encoding quality.
+
+Using mid/side stereo inappropriately can result in audible
+compression artifacts.
+To much switching between mid/side and regular stereo can also
+sound bad.
+To determine when to switch to mid/side stereo,
+LAME uses a much more sophisticated algorithm than that described
+in the ISO documentation, and thus is safe to use in joint
+stereo mode.
+
+.B (f)orced joint stereo 
+.br
+This mode will force MS joint stereo on all frames.
+It is slightly faster than joint stereo,
+but it should be used only if you are sure that every frame of the
+input file has very little stereo separation.
+
+.B (d)ual channels
+.br
+In this mode,
+the 2 channels will be totally independently encoded.
+Each channel will have exactly half of the bitrate.
+This mode is designed for applications like dual languages
+encoding (for example: English in one channel and French in the other).
+Using this encoding mode for regular stereo files will result in a
+lower quality encoding.
+
+.B (m)ono
+.br
+The input will be encoded as a mono signal.
+If it was a stereo signal,
+it will be downsampled to mono.
+The downmix is calculated as the sum of the left and right channel,
+attenuated by 6 dB.
+.TP
+.B \-a
+Mix the stereo input file to mono and encode as mono.
+.br
+The downmix is calculated as the sum of the left and right channel,
+attenuated by 6 dB. 
+
+This option is only needed in the case of raw PCM stereo input
+(because LAME cannot determine the number of channels in the input file).
+To encode a stereo PCM input file as mono,
+use
+.B lame \-m
+.I s
+.B \-a.
+
+For WAV and AIFF input files,
+using
+.B \-m
+will always produce a mono .mp3 file from both mono and stereo input. 
+.TP
+.B \-d
+Allows the left and right channels to use different block size types. 
+.TP
+.B \-\-freeformat
+Produces a free format bitstream.
+With this option,
+you can use
+.B \-b
+with any bitrate higher than 8 kbps.
+
+However,
+even if an mp3 decoder is required to support free bitrates at
+least up to 320 kbps,
+many players are unable to deal with it.
+
+Tests have shown that the following decoders support free format:
+.br
+.B FreeAmp
+up to 440 kbps
+.br
+.B in_mpg123
+up to 560 kbps
+.br
+.B l3dec
+up to 310 kbps
+.br
+.B LAME
+up to 560 kbps
+.br
+.B MAD
+up to 640 kbps
+.TP
+.B \-\-decode
+Uses LAME for decoding to a wav file.
+The input file can be any input type supported by encoding,
+including layer II files.
+LAME uses a bugfixed version of mpglib for decoding.
+
+If
+.B \-t
+is used (disable wav header),
+LAME will output raw pcm in native endian format.
+You can use
+.B \-x
+to swap bytes order.
+
+This option is not usable if the MP3 decoder was
+.B explicitly
+disabled in the build of LAME.
+.TP
+.BI \-t
+Disable writing of the INFO Tag on encoding.
+.br
+This tag in embedded in frame 0 of the MP3 file.
+It includes some information about the encoding options of the file,
+and in VBR it lets VBR aware players correctly seek and compute
+playing times of VBR files.
+
+When
+.B \-\-decode
+is specified (decode to WAV),
+this flag will disable writing of the WAV header.
+The output will be raw pcm,
+native endian format.
+Use
+.B \-x
+to swap bytes.
+.TP
+.BI \-\-comp " arg"
+Instead of choosing bitrate,
+using this option,
+user can choose compression ratio to achieve.
+.TP
+.BI \-\-scale " n"
+.PD 0
+.TP
+.BI \-\-scale\-l " n"
+.TP
+.BI \-\-scale\-r " n"
+Scales input (every channel, only left channel or only right channel) by
+.I n.
+This just multiplies the PCM data (after it has been converted to floating
+point) by
+.I n. 
+
+.I n
+> 1: increase volume
+.br
+.I n
+= 1: no effect
+.br
+.I n
+< 1: reduce volume
+
+Use with care,
+since most MP3 decoders will truncate data which decodes to values
+greater than 32768.
+.PD
+.TP
+.B \-\-replaygain\-fast
+Compute ReplayGain fast but slightly inaccurately.
+
+This computes "Radio" ReplayGain on the input data stream after
+user\(hyspecified volume\(hyscaling and/or resampling.
+
+The ReplayGain analysis does
+.I not
+affect the content of a compressed data stream itself,
+it is a value stored in the header of a sound file.
+Information on the purpose of ReplayGain and the algorithms used is
+available from
+.B http://www.replaygain.org/.
+
+Only the "RadioGain" Replaygain value is computed,
+it is stored in the LAME tag.
+The analysis is performed with the reference
+volume equal to 89dB.
+Note: the reference volume has been changed from 83dB on transition from
+version 3.95 to 3.95.1.
+
+This switch is enabled by default.
+
+See also:
+.B \-\-replaygain\-accurate, \-\-noreplaygain
+.TP
+.B \-\-replaygain\-accurate
+Compute ReplayGain more accurately and find the peak sample.
+
+This enables decoding on the fly, computes "Radio" ReplayGain on the
+decoded data stream,
+finds the peak sample of the decoded data stream and stores it in the file.
+ 
+The ReplayGain analysis does
+.I not
+affect the content of a compressed data stream itself,
+it is a value stored in the header of a sound file.
+Information on the purpose of ReplayGain and the algorithms used is
+available from
+.B http://www.replaygain.org/.
+
+ 
+By default, LAME performs ReplayGain analysis on the input data
+(after the user\(hyspecified volume scaling).
+This behavior might give slightly inaccurate results
+because the data on the output of a lossy compression/decompression sequence
+differs from the initial input data.
+When
+.B \-\-replaygain-accurate
+is specified the mp3 stream gets decoded on the fly and the analysis is
+performed on the decoded data stream.
+Although theoretically this method gives more accurate results,
+it has several disadvantages:
+.RS 8
+.IP "*" 4
+tests have shown that the difference between the ReplayGain values computed
+on the input data and decoded data is usually not greater than 0.5dB,
+although the minimum volume difference the human ear can perceive is
+about 1.0dB
+.IP "*" 4
+decoding on the fly significantly slows down the encoding process
+.RE
+.RS 7
+
+The apparent advantage is that:
+.RE
+.RS 8
+.IP "*" 4
+with
+.B \-\-replaygain-accurate
+the real peak sample is determined and stored in the file.
+The knowledge of the peak sample can be useful to decoders (players)
+to prevent a negative effect called 'clipping' that introduces distortion
+into the sound.
+.RE
+.RS 7
+ 
+Only the "RadioGain" ReplayGain value is computed,
+it is stored in the LAME tag.
+The analysis is performed with the reference
+volume equal to 89dB.
+Note: the reference volume has been changed from 83dB on transition from
+version 3.95 to 3.95.1.
+ 
+This option is not usable if the MP3 decoder was
+.B explicitly
+disabled in the build of LAME.
+(Note: if LAME is compiled without the MP3 decoder,
+ReplayGain analysis is performed on the input data after user-specified
+volume scaling).
+ 
+See also:
+.B \-\-replaygain-fast, \-\-noreplaygain \-\-clipdetect
+.RE
+.TP
+.B \-\-noreplaygain
+Disable ReplayGain analysis.
+
+By default ReplayGain analysis is enabled. This switch disables it.
+
+See also:
+.B \-\-replaygain-fast, \-\-replaygain-accurate
+.TP
+.B \-\-clipdetect
+Clipping detection.
+
+Enable
+.B \-\-replaygain-accurate
+and print a message whether clipping occurs and how far in dB the waveform
+is from full scale.
+  
+This option is not usable if the MP3 decoder was
+.B explicitly
+disabled in the build of LAME.
+
+See also:
+.B \-\-replaygain-accurate
+.TP
+.B \-\-preset " [fast] type | [cbr] kbps"
+Use one of the built-in presets.
+
+Have a look at the PRESETS section below.
+
+.B Warning:
+with the current version fast presets might result in too high bitrate
+compared to regular presets.
+
+.B \-\-preset help
+gives more infos about the the used options in these presets.
+.TP
+.B \-\-alt-preset " [fast] type | [cbr] kbps"
+Use one of the built-in  presets.
+
+This option is deprecated and offers the same as the
+.B \-\-preset
+option above. Do not use it anymore, it will go away in a later version.
+.TP
+.B \-\-r3mix
+Uses r3mix VBR preset.
+.br
+See http://www.r3mix.net/ for more details. 
+.TP
+.B \-\-noasm " type"
+Disable specific assembly optimizations (
+.B mmx
+/
+.B 3dnow
+/
+.B sse
+).
+Quality will not increase, only speed will be reduced.
+If you have problems running Lame on a Cyrix/Via processor,
+disabling mmx optimizations might solve your problem.
+
+.PP
+Verbosity:
+.TP
+.BI \-\-disptime " n"
+Set the delay in seconds between two display updates. 
+.TP
+.B \-\-nohist
+By default,
+LAME will display a bitrate histogram while producing VBR mp3 files.
+This will disable that feature.
+.br
+Histogram display might not be available on your release. 
+.TP
+.B -S
+.PD 0
+.TP
+.B \-\-silent
+.TP
+.B \-\-quiet
+Do not print anything on the screen.
+.PD
+.TP
+.B \-\-verbose
+Print a lot of information on the screen.
+.TP
+.B \-\-help
+Display a list of available options.
+
+.PP
+Noise shaping & psycho acoustic algorithms:
+.TP
+.BI -q " qual"
+0 <=
+.I qual
+<= 9
+
+Bitrate is of course the main influence on quality.
+The higher the bitrate,
+the higher the quality.
+But for a given bitrate,
+we have a choice of algorithms to determine the best scalefactors
+and Huffman encoding (noise shaping).
+
+.B -q 0:
+.br
+use slowest & best possible version of all algorithms.
+.B -q 0
+and
+.B -q 1
+are slow and may not produce significantly higher quality.
+
+.B -q 2:
+.br
+recommended.
+Same as
+.B -h.
+
+.B -q 5:
+.br
+default value.
+Good speed,
+reasonable quality.
+
+.B -q 7:
+.br
+same as
+.B -f.
+Very fast,
+ok quality.
+Psycho acoustics are used for pre-echo & M/S,
+but no noise shaping is done.
+
+.B -q 9:
+.br
+disables almost all algorithms including psy-model.
+Poor quality.
+.TP
+.B -h
+Use some quality improvements.
+Encoding will be slower,
+but the result will be of higher quality.
+The behavior is the same as the
+.B -q 2
+switch.
+.br
+This switch is always enabled when using VBR. 
+.TP
+.B -f
+This switch forces the encoder to use a faster encoding mode,
+but with a lower quality.
+The behavior is the same as the
+.B -q 7
+switch.
+
+Noise shaping will be disabled,
+but psycho acoustics will still be computed for bit allocation
+and pre-echo detection. 
+
+.PP
+CBR (constant bitrate, the default) options:
+.TP
+.BI -b  " n"
+For MPEG1 (sampling frequencies of 32, 44.1 and 48 kHz)
+.br
+.I n
+= 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
+
+For MPEG2 (sampling frequencies of 16, 22.05 and 24 kHz)
+.br
+.I n
+= 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160
+
+Default is 128 for MPEG1 and 64 for MPEG2. 
+.TP
+.BI \-\-cbr
+enforce use of constant bitrate
+
+.PP
+ABR (average bitrate) options:
+.TP
+.BI \-\-abr " n"
+Turns on encoding with a targeted average bitrate of n kbits,
+allowing to use frames of different sizes.
+The allowed range of
+.I n
+is 8 - 310,
+you can use any integer value within that range.
+
+It can be combined with the
+.B -b
+and
+.B -B
+switches like:
+.B lame \-\-abr
+.I 123
+.B -b
+.I 64
+.B -B
+.I 192 a.wav a.mp3
+which would limit the allowed frame sizes between 64 and 192 kbits.
+
+The use of
+.B -B
+is NOT RECOMMENDED.
+A 128 kbps CBR bitstream,
+because of the bit reservoir,
+can actually have frames which use as many bits as a 320 kbps frame.
+VBR modes minimize the use of the bit reservoir,
+and thus need to allow 320 kbps frames to get the same flexibility
+as CBR streams. 
+
+.PP
+VBR (variable bitrate) options:
+.TP
+.B -v
+use variable bitrate
+.B (\-\-vbr-old)
+.TP
+.B \-\-vbr-old
+Invokes the oldest,
+most tested VBR algorithm.
+It produces very good quality files,
+though is not very fast.
+This has,
+up through v3.89,
+been considered the "workhorse" VBR algorithm.
+.TP
+.B \-\-vbr-new
+Invokes the newest VBR algorithm.
+During the development of version 3.90,
+considerable tuning was done on this algorithm,
+and it is now considered to be on par with the original
+.B \-\-vbr-old. 
+It has the added advantage of being very fast (over twice as fast as
+.B \-\-vbr-old).
+.TP
+.BI -V " n"
+0 <=
+.I n
+<= 9
+.br
+Enable VBR (Variable BitRate) and specifies the value of VBR quality
+(default = 4).
+0 = highest quality.
+
+.PP
+ABR and VBR options:
+.TP
+.BI -b " bitrate"
+For MPEG1 (sampling frequencies of 32, 44.1 and 48 kHz)
+.br
+.I n
+= 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
+
+For MPEG2 (sampling frequencies of 16, 22.05 and 24 kHz)
+.br
+.I n
+= 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160
+
+Specifies the minimum bitrate to be used.
+However,
+in order to avoid wasted space,
+the smallest frame size available will be used during silences. 
+.TP
+.BI -B " bitrate"
+For MPEG1 (sampling frequencies of 32, 44.1 and 48 kHz)
+.br
+.I n
+= 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
+
+For MPEG2 (sampling frequencies of 16, 22.05 and 24 kHz)
+.br
+.I n
+= 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160
+
+Specifies the maximum allowed bitrate.
+
+Note: If you own an mp3 hardware player build upon a MAS 3503 chip,
+you must set maximum bitrate to no more than 224 kpbs. 
+.TP
+.B -F
+Strictly enforce the
+.B -b
+option.
+.br
+This is mainly for use with hardware players that do not support low
+bitrate mp3.
+
+Without this option,
+the minimum bitrate will be ignored for passages of analog silence,
+i.e. when the music level is below the absolute threshold of
+human hearing (ATH). 
+
+.PP
+ATH related:
+.TP
+.B \-\-noath
+Disable any use of the ATH (absolute threshold of hearing) for masking.
+Normally,
+humans are unable to hear any sound below this threshold. 
+.TP
+.B \-\-athshort
+Ignore psychoacoustic model for short blocks,
+use ATH only. 
+.TP
+.B \-\-athonly
+This option causes LAME to ignore the output of the psy-model and only
+use masking from the ATH (absolute threshold of hearing).
+Might be useful at very high bitrates or for testing the ATH. 
+.TP
+.BI \-\-athtype " shape"
+The Absolute Threshold of Hearing is the minimum threshold under which
+humans are unable to hear any sound.
+.br
+In the past,
+LAME was using ATH shape 0 which is the Painter & Spanias formula.
+Tests have shown that this formula is innacurate for the
+13 - 22 kHz area,
+leading to audible artifacts in some cases.
+.br
+Shape 1 was thus implemented,
+which is over sensitive,
+leading to very high bitrates.
+.br
+Shape 2 formula was accurately modelized from real data in order to
+reach optimal quality while not wasting bitrate.
+In CBR and ABR modes,
+LAME uses ATH shape 2 by default,
+VBR selects one depending on the specified parameter to the
+.B -V
+option.
+.TP
+.BI \-\-athlower " n"
+Lower the ATH (absolute threshold of hearing) by
+.I n
+dB.
+.br
+Normally,
+humans are unable to hear any sound below this threshold,
+but for music recorded at very low level this option might be useful.
+.TP
+.BI \-\-athaa-type " n"
+ATH auto adjust types 1 - 3,
+else no adjustment
+.TP
+.BI \-\-athaa-sensitivity " x"
+activation offset in -/+ dB for ATH auto-adjustment
+
+.PP
+PSY related:
+.TP
+.B \-\-short
+Let LAME use short blocks when appropriate.
+It is the default setting.
+.TP
+.B \-\-noshort
+Encode all frames using long blocks only.
+This could increase quality when encoding at very low bitrates,
+but can produce serious pre-echo artefacts. 
+.TP
+.B \-\-allshort
+Use only short blocks,
+no long ones. 
+.TP
+.BI \-\-cwlimit " freq"
+Compute tonality up to
+.I freq
+(in kHz).
+Default setting is 8.8717.
+.TP
+.B \-\-notemp
+Do not make use of the temporal masking effect. 
+.TP
+.B \-\-nspsytune
+Experimental PSY tunings by Naoki Shibata
+.TP
+.B \-\-nssafejoint
+M/S switching criterion
+.TP
+.BI \-\-nsmsfix " arg"
+M/S switching tuning [effective 0-3.5]
+.TP
+.BI \-\-ns-bass " x"
+Adjust masking for sfbs  0 -  6 (long)  0 -  5 (short)
+.TP
+.BI \-\-ns-alto " x"
+Adjust masking for sfbs  7 - 13 (long)  6 - 10 (short)
+.TP
+.BI \-\-ns-treble " x"
+Adjust masking for sfbs 14 - 21 (long) 11 - 12 (short)
+.TP
+.BI \-\-ns-sfb21 " x"
+Change ns-treble by x dB for sfb21
+
+.PP
+Experimental options:
+.TP
+.BI -X " n"
+0 <=
+.I n
+<= 7
+
+When LAME searches for a "good" quantization,
+it has to compare the actual one with the best one found so far. 
+The comparison says which one is better,
+the best so far or the actual.
+The
+.B -X
+parameter selects between different approaches to make this decision,
+.B -X0
+being the default mode:
+
+.B -X0 
+.br
+The criterions are (in order of importance):
+.br
+* less distorted scalefactor bands
+.br
+* the sum of noise over the thresholds is lower
+.br
+* the total noise is lower
+
+.B -X1
+.br
+The actual is better if the maximum noise over all scalefactor bands is
+less than the best so far.
+
+.B -X2
+.br
+The actual is better if the total sum of noise is lower than the best so
+far.
+
+.B -X3
+.br
+The actual is better if the total sum of noise is lower than the best so
+far and the maximum noise over all scalefactor bands is less than the
+best so far plus 2dB.
+
+.B -X4
+.br
+Not yet documented.
+
+.B -X5
+.br
+The criterions are (in order of importance):
+.br
+* the sum of noise over the thresholds is lower 
+.br
+* the total sum of noise is lower
+
+.B -X6 
+.br
+The criterions are (in order of importance):
+.br
+* the sum of noise over the thresholds is lower
+.br
+* the maximum noise over all scalefactor bands is lower
+.br
+* the total sum of noise is lower
+
+.B -X7 
+.br
+The criterions are:
+.br
+* less distorted scalefactor bands
+.br
+or
+.br
+* the sum of noise over the thresholds is lower 
+.TP
+.B -Y
+lets LAME ignore noise in sfb21, like in CBR
+.TP
+.B -Z
+toggles the scalefac feature on
+
+.PP
+MP3 header/stream options:
+.TP
+.BI -e " emp"
+.I emp
+= n, 5, c
+
+n = (none, default)
+.br
+5 = 0/15 microseconds
+.br
+c = citt j.17
+
+All this does is set a flag in the bitstream.
+If you have a PCM input file where one of the above types of
+(obsolete) emphasis has been applied,
+you can set this flag in LAME.
+Then the mp3 decoder should de-emphasize the output during playback,
+although most decoders ignore this flag.
+
+A better solution would be to apply the de-emphasis with a standalone
+utility before encoding,
+and then encode without
+.B -e. 
+.TP
+.B -c
+Mark the encoded file as being copyrighted.
+.TP
+.B -o
+Mark the encoded file as being a copy. 
+.TP
+.B -p
+Turn on CRC error protection.
+.br
+It will add a cyclic redundancy check (CRC) code in each frame,
+allowing to detect transmission errors that could occur on the
+MP3 stream.
+However,
+it takes 16 bits per frame that would otherwise be used for encoding,
+and then will slightly reduce the sound quality. 
+.TP
+.B \-\-nores
+Disable the bit reservoir.
+Each frame will then become independent from previous ones,
+but the quality will be lower. 
+.TP
+.B \-\-strictly-enforce-ISO
+With this option,
+LAME will enforce the 7680 bit limitation on total frame size.
+.br
+This results in many wasted bits for high bitrate encodings but will
+ensure strict ISO compatibility.
+This compatibility might be important for hardware players.
+
+.PP
+Filter options:
+.TP
+.B -k
+Tells the encoder to use full bandwidth and to disable all filters.
+By default,
+the encoder uses some highpass filtering at low bitrates,
+in order to keep a good quality by giving more bits to more important
+frequencies.
+.br
+Increasing the bandwidth from the default setting might produce
+ringing artefacts at low bitrates.
+Use with care! 
+.TP
+.BI \-\-lowpass " freq"
+Set a lowpass filtering frequency in kHz.
+Frequencies above the specified one will be cutoff. 
+.TP
+.BI \-\-lowpass-width " freq"
+Set the width of the lowpass filter.
+The default value is 15% of the lowpass frequency. 
+.TP
+.BI \-\-highpass " freq"
+Set an highpass filtering frequency in kHz.
+Frequencies below the specified one will be cutoff. 
+.TP
+.BI \-\-highpass-width " freq"
+Set the width of the highpass filter in kHz.
+The default value is 15% of the highpass frequency.
+.TP
+.BI \-\-resample " sfreq"
+.I sfreq
+= 8, 11.025, 12, 16, 22.05, 24, 32, 44.1, 48
+.br
+Select output sampling frequency (only supported for encoding).
+.br
+If not specified,
+LAME will automatically resample the input when using high compression ratios.
+
+.PP
+ID3 tag options:
+.TP
+.BI \-\-tt " title"
+audio/song title (max 30 chars for version 1 tag)
+.TP
+.BI \-\-ta " artist"
+audio/song artist (max 30 chars for version 1 tag)
+.TP
+.BI \-\-tl " album"
+audio/song album (max 30 chars for version 1 tag)
+.TP
+.BI \-\-ty " year"
+audio/song year of issue (1 to 9999)
+.TP
+.BI \-\-tc " comment"
+user-defined text (max 30 chars for v1 tag, 28 for v1.1)
+.TP
+.BI \-\-tn " track"
+audio/song track number (1 to 255, creates v1.1 tag)
+.TP
+.BI \-\-tg " genre"
+audio/song genre (name or number in list)
+.TP
+.B \-\-add-id3v2
+force addition of version 2 tag
+.TP
+.B \-\-id3v1-only
+add only a version 1 tag
+.TP
+.B \-\-id3v2-only
+add only a version 2 tag
+.TP
+.B \-\-space-id3v1
+pad version 1 tag with spaces instead of nulls
+.TP
+.B \-\-pad-id3v2
+pad version 2 tag with extra 128 bytes
+.TP
+.B \-\-genre-list
+print alphabetically sorted ID3 genre list and exit
+.TP
+.B \-\-ignore-tag-errors
+ignore errors in values passed for tags, use defaults in case an error occurs
+
+.PP
+Analysis options:
+.TP
+.B \-g
+run graphical analysis on <infile>.
+<infile> can also be a .mp3 file.
+(This feature is a compile time option.
+Your binary may for speed reasons be compiled without this.)
+
+.SH ID3 TAGS
+LAME is able to embed ID3 v1,
+v1.1 or v2 tags inside the encoded MP3 file.
+This allows to have some useful information about the music track
+included inside the file.
+Those data can be read by most MP3 players.
+
+Lame will smartly choose which tags to use.
+It will add ID3 v2 tags only if the input comments won't fit in v1
+or v1.1 tags,
+i.e. if they are more than 30 characters.
+In this case,
+both v1 and v2 tags will be added,
+to ensure reading of tags by MP3 players which are unable to read ID3 v2 tags.
+
+.SH ENCODING MODES
+LAME is able to encode your music using one of its 3 encoding modes:
+constant bitrate (CBR), average bitrate (ABR) and variable bitrate (VBR).
+.TP
+.B Constant Bitrate (CBR)
+This is the default encoding mode,
+and also the most basic.
+In this mode,
+the bitrate will be the same for the whole file.
+It means that each part of your mp3 file will be using the same
+number of bits.
+The musical passage being a difficult one to encode or an easy one,
+the encoder will use the same bitrate,
+so the quality of your mp3 is variable.
+Complex parts will be of a lower quality than the easiest ones.
+The main advantage is that the final files size won't change and
+can be accurately predicted.
+.TP
+.B Average Bitrate (ABR)
+In this mode,
+you choose the encoder will maintain an average bitrate while using
+higher bitrates for the parts of your music that need more bits.
+The result will be of higher quality than CBR encoding but the
+average file size will remain predictable,
+so this mode is highly recommended over CBR.
+This encoding mode is similar to what is referred as vbr in AAC or
+Liquid Audio (2 other compression technologies).
+.TP
+.B Variable bitrate (VBR)
+In this mode,
+you choose the desired quality on a scale from 9 (lowest
+quality/biggest distortion) to 0 (highest quality/lowest distortion).
+Then encoder tries to maintain the given quality in the whole file by
+choosing the optimal number of bits to spend for each part of your music.
+The main advantage is that you are able to specify the quality level that
+you want to reach,
+but the inconvenient is that the final file size is totally unpredictable.
+
+.SH PRESETS
+The
+.B \-\-preset
+switches are designed to provide the highest possible quality.
+
+They have for the most part been subject to and tuned via rigorous double blind
+listening tests to verify and achieve this objective.
+
+These are continually updated to coincide with the latest developments that
+occur and as a result should provide you with nearly the best quality
+currently possible from LAME.
+
+To activate these presets:
+.PP
+For VBR modes (generally highest quality):
+.TP
+.B \-\-preset medium
+This preset should provide near transparency to most people on most music.
+.TP
+.B \-\-preset standard
+This preset should generally be transparent to most people on most music and
+is already quite high in quality.
+.TP
+.B \-\-preset extreme
+If you have extremely good hearing and similar equipment,
+this preset will generally provide slightly higher quality than the
+.B standard
+mode.
+.PP
+For CBR 320kbps (highest quality possible from the
+.B \-\-preset
+switches):
+.TP
+.B \-\-preset insane
+This preset will usually be overkill for most people and most situations,
+but if you must have the absolute highest quality with no regard to filesize,
+this is the way to go.
+.PP
+For ABR modes (high quality per given bitrate but not as high as VBR):
+.TP
+.B \-\-preset " kbps"
+Using this preset will usually give you good quality at a specified bitrate.
+Depending on the bitrate entered,
+this preset will determine the optimal settings for that particular situation.
+While this approach works,
+it is not nearly as flexible as VBR,
+and usually will not attain the same level of quality as VBR at higher bitrates.
+.PP
+The following options are also available for the corresponding profiles:
+.PP
+.B fast standard|extreme|insane
+.br
+.B cbr " kbps"
+.PP
+.TP
+.B fast
+Enables the new fast VBR for a particular profile.
+The disadvantage to the speed switch is that often times the bitrate will be
+slightly higher than with the normal mode and quality may be slightly lower also.
+.TP
+.B cbr
+If you use the ABR mode (read above) with a significant bitrate such as 80,
+96,
+112,
+128,
+160,
+192,
+224,
+256,
+320,
+you can use the
+.B cbr
+option to force CBR mode encoding instead of the standard ABR mode.
+ABR does provide higher quality but CBR may be useful in situations such as when
+streaming an MP3 over the Internet may be important.
+
+
+.SH EXAMPLES
+.LP
+Fixed bit rate jstereo 128kbs encoding:
+.IP
+.B lame
+.I sample.wav sample.mp3
+
+.LP
+Fixed bit rate jstereo 128 kbps encoding, highest quality (recommended):
+.IP
+.B lame \-h
+.I sample.wav sample.mp3
+
+.LP
+Fixed bit rate jstereo 112 kbps encoding:
+.IP
+.B lame \-b
+.I 112 sample.wav sample.mp3
+
+.LP
+To disable joint stereo encoding (slightly faster,
+but less quality at bitrates <= 128 kbps):
+.IP
+.B lame \-m
+.I s sample.wav sample.mp3
+
+.LP
+Fast encode,
+low quality (no psycho-acoustics):
+.IP
+.B lame \-f
+.I sample.wav sample.mp3
+
+.LP
+Variable bitrate (use \-V n to adjust quality/filesize):
+.IP
+.B lame \-h \-V
+.I 6 sample.wav sample.mp3
+
+.LP
+Streaming mono 22.05 kHz raw pcm, 24 kbps output:
+.IP
+.B cat
+.I inputfile
+.B | lame \-r \-m
+.I m
+.B \-b
+.I 24
+.B \-s
+.I 22.05 \- \-
+.B >
+.I output
+
+.LP
+Streaming mono 44.1 kHz raw pcm,
+with downsampling to 22.05 kHz:
+.IP
+.B cat
+.I inputfile
+.B | lame \-r \-m
+.I m
+.B \-b
+.I 24
+.B \-\-resample
+.I 22.05 \- \-
+.B >
+.I output
+
+.LP
+Encode with the
+.B fast standard
+preset:
+.IP
+.B lame \-\-preset fast standard
+.I sample.wav sample.mp3
+
+.SH BUGS
+.PP
+Probably there are some.
+.SH SEE ALSO
+.BR mpg123 (1) ,
+.BR madplay (1) ,
+.BR sox (1)
+.SH AUTHORS
+.nf
+LAME originally developed by Mike Cheng and now maintained by
+Mark Taylor.  GPSYCHO psycho-acoustic model by Mark Taylor.
+(http://www.mp3dev.org/).
+mpglib by Michael Hipp
+Manual page by William Schelter, Nils Faerber, Alexander Leidinger.
+Small fixes on the manual page by Rogerio Brito.
+.f
Index: extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/basic.html
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/basic.html	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/basic.html	(revision 18425)
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+<HEAD>
+<TITLE>Basic command line switch reference</TITLE>
+<META NAME="description" CONTENT="Command line switch reference">
+<META NAME="keywords" CONTENT="lame">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso_8859_1">
+<LINK REL="STYLESHEET" HREF="lame.css">
+</HEAD>
+<BODY TEXT=#000000
+        BGCOLOR=#F9FBFB LINK=#006666 VLINK=#4C4C4C
+        ALINK=#995500>
+<H1>Basic command line switch reference</H1>
+<br>
+Only the most usual switches are described here. However those should be sufficient 
+for the vast majority of users. 
+<P> 
+<TABLE CELLPADDING=3 BORDER="1">
+  <TR VALIGN="TOP"> 
+    <TD ALIGN="LEFT" nowrap><b>switch</b></TD>
+    <TD ALIGN="LEFT" nowrap><b>parameter</b></TD>
+  </TR>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-abr">--abr</a></kbd></td>
+    <td align="LEFT" nowrap>average bitrate encoding</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#b">-b</a></kbd></td>
+    <td align="LEFT" nowrap>bitrate (8...320)</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-decode">--decode</a></kbd></td>
+    <td align="LEFT" nowrap>decoding only</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#f">-f</a></kbd></td>
+    <td align="LEFT" nowrap> fast mode</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#h">-h</a></kbd></td>
+    <td align="LEFT" nowrap>high quality</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-help">--help</a></kbd></td>
+    <td align="LEFT" nowrap> help</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#m">-m m</a></kbd></td>
+    <td align="LEFT" nowrap>mono mode</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#V">-V</a></kbd></td>
+    <td align="LEFT" nowrap>VBR quality setting (0...9)</td>
+  </tr>
+</TABLE>
+<BR>
+<dl> 
+  <dt><strong>* <kbd>--abr n</kbd><a name="-abr">&nbsp;&nbsp;&nbsp;&nbsp;average 
+    bitrate encoding</a></strong> 
+</dl>
+<dl> 
+  <dd>Turns on encoding with a targeted average bitrate of n kbits, allowing to 
+    use frames of different sizes. The allowed range of n is 8-320, you can use 
+    any integer value within that range. 
+  <dt><br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+</dl>
+<dl> 
+  <dt><strong>* <kbd>-b n</kbd><a name="b">&nbsp;&nbsp;&nbsp;&nbsp;bitrate</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd>For MPEG1 (sampling frequencies of 32, 44.1 and 48 kHz)<br>
+    n = 32,40,48,56,64,80,96,112,128,160,192,224,256,320<br>
+    <br>
+    For MPEG2 (sampling frequencies of 16, 22.05 and 24 kHz)<br>
+    n = 8,16,24,32,40,48,56,64,80,96,112,128,144,160<br>
+    <br>
+    Default is 128 kbs for MPEG1 and 80 kbs for MPEG2. 
+  <dt><br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+</dl>
+<dl> 
+  <dt><strong>* <kbd>--decode</kbd><a name="-decode">&nbsp;&nbsp;&nbsp;&nbsp;decoding 
+    only</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>Uses LAME for decoding to a WAV file. The input file can be any input type 
+    supported by encoding, including layer I,II,III (MP3). 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-f</kbd><a name="f">&nbsp;&nbsp;&nbsp;&nbsp;fast mode</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd> This switch forces the encoder to use a faster encoding mode, but with 
+    a lower quality. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-h</kbd><a name="h">&nbsp;&nbsp;&nbsp;&nbsp;high quality</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd> Use some quality improvements. Encoding will be slower, but the result 
+    will be of higher quality.<br>
+    This switch is always enabled when using VBR. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--help</kbd><a name="-help">&nbsp;&nbsp;&nbsp;&nbsp;help</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd> Display a list of all available options. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-m m</kbd><a name="m">&nbsp;&nbsp;&nbsp;&nbsp;mono 
+    mode</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>The input will be encoded as a mono signal. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-V 0...9</kbd><a name="V">&nbsp;&nbsp;&nbsp;&nbsp;VBR quality 
+    setting</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Enable VBR (Variable BitRate) and specifies the value of VBR quality.<br>
+    default=4<br>
+    0=highest quality. 
+</dl>
+</BODY>
+</HTML>
Index: extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/contributors.html
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/contributors.html	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/contributors.html	(revision 18425)
@@ -0,0 +1,165 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!-- saved from url=(0051)http://internet.roadrunner.com/~mt/mp3/history.html -->
+<HTML><HEAD><TITLE>Contributors</TITLE>
+<META content="text/html; charset=iso-8859-1" http-equiv=Content-Type>
+<META content="MSHTML 5.00.2014.210" name=GENERATOR><link rel="stylesheet" href="lame.css"></HEAD>
+<BODY aLink=#bbbbbb bgColor=#ffffff link=#888888 text=#000000 vLink=#555555>
+<CENTER>
+  <H1>Contributors</H1>
+</CENTER>
+<HR>
+<H4>The following people contributed to the LAME development:</H4>
+<p> Lauri Ahonen<br>
+  Sakari Ailus<br>
+  Tero Auvinen<br>
+  Michal Bacik<br>
+  Alex Ballegooy<br>
+  Wilfried Behne<br>
+  Bob Bell<br>
+  Simon Blandford<br>
+  Segher Boessenkool<br>
+  Florian Bome<br>
+  Lionel Bonnet<br>
+  Gabriel Bouvigne<br>
+  Rog&eacute;rio Theodoro de Brito<br>
+  Erik de Castro Lopo<br>
+  David Chandler<br>
+  Michael Cheng<br>
+  John Dahlstrom<br>
+  Goran Dokic<br>
+  James Droppo<br>
+  Sergey Dubov<br>
+  Dominique Duvivier<br>
+  John Edwards<br>
+  Alvaro Martinez Echevarria<br>
+  Joakim Enerstam<br>
+  Albert Faber<br>
+  Nils Faerber<br>
+  Sami Farin<br>
+  Mikhail M. Fedotov<br>
+  Joseph Fourier<br>
+  Jani Frilander<br>
+  Richard Gorton<br>
+  Casper Gripenberg<br>
+  Steffan Haeuser<br>
+  Jeremy Hall<br>
+  Paul Hartman<br>
+  John Hayward-Warburton<br>
+  Peder Hedlund <br>
+  Robert Hegemann<br>
+  Mathew Hendry<br>
+  Magnus Holmgren <br>
+  Ben "Jacobs"<br>
+  Tamito Kajiyama<br>
+  Ti Kan <br>
+  Mo Katz<br>
+  Iwasa Kazmi<br>
+  Ralf Kempkens <br>
+  Frank Klemm<br>
+  Aleksander Korzynski<br>
+  Joachim Kuebart <br>
+  Leonid Kulakov<br>
+  Dmitry Kutsanov<br>
+  Jarmo Laakkonen <br>
+  An van Lam<br>
+  Juha Laukala<br>
+  Greg Lehey <br>
+  Felix von Leitner<br>
+  Rafael Luebbert<br>
+  Macik<br>
+  Lars Magne Ingebrigtsen<br>
+  Scott Manley<br>
+  Vladimir Marek<br>
+  Goran Markovic<br>
+  Sergey A. Maslyakov<br>
+  Chris Matrakidis<br>
+  Greg Maxwell<br>
+  Scott Miller<br>
+  Darin Morrison<br>
+  Tomasz Motylewski<br>
+  Kimmo Mustonen <br>
+  Dan Nelson<br>
+  Anton Oleynikov<br>
+  Mike Oliphant<br>
+  Andr&eacute; Osterhues<br>
+  Johannes Overmann<br>
+  Gian-Carlo Pascutto<br>
+  Jan Peman<br>
+  Jan Rafaj<br>
+  Gertjan van Ratingen<br>
+  Miguel Revilla Rodriguez<br>
+  Shawn Riley<br>
+  Tim Ruddick<br>
+  Ingo Saitz<br>
+  Conrad Sanderson<br>
+  Sergey Sapelin<br>
+  William Schelter<br>
+  Justin Schoeman<br>
+  Naoki Shibata<br>
+  Sigbjørn Skjæret<br>
+  Nathan Slingerland<br>
+  Patrick De Smet<br>
+  Acy Stapp<br>
+  Mark Stephens<br>
+  Alexander Stumpf <br>
+  Stephane Tavenard<br>
+  Mark Taylor<br>
+  Mikhail Teterin <br>
+  Brad Threatt<br>
+  Takehiro Tominaga<br>
+  Warren Toomey<br>
+  Atro Tossavainen <br>
+  Roel Van Den Berghe<br>
+  Christopher Wise<br>
+  Martin Weghofer<br>
+  William Welch<br>
+  Gerhard Wesp<br>
+  Alfred Weyers<br>
+  Ethan Yeo<br>
+  Chuck Zenkus </p>
+<p>&nbsp;</p>
+<h4>Original ISO contributors:</h4>
+<p>Bill Aspromonte<br>
+  Shaun Astarabadi<br>
+  R. Bittner<br>
+  Karlheinz Brandenburg<br>
+  W. Joseph Carter<br>
+  Jack Chang<br>
+  Mike Coleman<br>
+  Johnathan Devine<br>
+  Ernst Eberlein<br>
+  Dan Ellis<br>
+  Peter Farrett<br>
+  Jean-Georges Fritsch<br>
+  Vlad Fruchter<br>
+  Hendrik Fuchs<br>
+  Bernhard Grill<br>
+  Amit Gulati<br>
+  Munsi Haque<br>
+  Chuck Hsiao<br>
+  Toshiyuki Ishino<br>
+  Masahiro Iwadare<br>
+  Earl Jennings<br>
+  James Johnston<br>
+  Leon v.d. Kerkhof<br>
+  Don Lee<br>
+  Mike Li<br>
+  Yu-Tang Lin<br>
+  Soren Neilsen<br>
+  Simao F. Campos Neto<br>
+  Mark Paley<br>
+  Davis Pan<br>
+  Tan Ah Peng<br>
+  Kevin Peterson<br>
+  Juan Pineda<br>
+  Ernst F. Schroeder<br>
+  Peter Siebert<br>
+  Jens Spille<br>
+  John Stewart<br>
+  Sam Stewart<br>
+  Al Tabayoyon<br>
+  Kathy Wang<br>
+  Franz-Otto Witte<br>
+  Douglas Wong</p>
+</BODY>
+</HTML>
Index: extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/examples.html
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/examples.html	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/examples.html	(revision 18425)
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+   <META NAME="description" CONTENT="Some examples">
+   <META NAME="keywords" CONTENT="lame">
+   <META NAME="resource-type" CONTENT="document">
+   <META NAME="distribution" CONTENT="global">
+   <META NAME="GENERATOR" CONTENT="Mozilla/4.08 [en] (X11; I; Linux 2.0.36 i686) [Netscape]">
+   <TITLE>Some command line examples</TITLE>
+<LINK REL="STYLESHEET" HREF="lame.css">
+</HEAD>
+<BODY TEXT="#000000" BGCOLOR="#F9FBFB" LINK="#006666" VLINK="#4C4C4C" ALINK="#995500">
+<H1><FONT FACE="Helvetica">Some command line examples</FONT></H1>
+<UL>
+  <LI> Fixed bit rate 128kbps encoding:<br>
+    <kbd>lame sample.wav sample.mp3</kbd><br>
+    <br>
+  </LI>
+  <LI> Fixed bit rate jstereo 128kbps encoding, high quality (recommended):<br>
+    <kbd>lame -h sample.wav sample.mp3</kbd><br>
+    <br>
+  </LI>
+  <LI> Average bit rate 112kbps encoding:<br>
+    <kbd>lame --abr 112 sample.wav sample.mp3</kbd><br>
+    <br>
+  </LI>
+  <LI>Fast encode, low quality (no psycho-acoustics):<br>
+    <kbd>lame -f sample.wav sample.mp3<br>
+    <br>
+    </kbd></LI>
+  <LI>Variable bitrate (use -V n to adjust quality/filesize):<br>
+    <kbd>lame -h -V 6 sample.wav sample.mp3<br>
+    <br>
+    </kbd></LI>
+  <LI>Streaming mono 22.05 kHz raw pcm, 24 kbps output:<br>
+    <kbd>cat inputfile | lame -r -m m -b 24 -s 22.05 -- > output<br>
+    <br>
+    </kbd></LI>
+  <LI>Streaming mono 44.1 kHz raw pcm, with downsampling to 22.05 kHz:<br>
+    <kbd>cat inputfile | lame -r -m m -b 24 --resample 22.05 -- > output</kbd></LI>
+</UL>
+</BODY>
+</HTML>
Index: extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/history.html
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/history.html	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/history.html	(revision 18425)
@@ -0,0 +1,1513 @@
+<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+<meta http-equiv="Content-Type"
+ content="text/html; charset=iso-8859-1">
+<meta name="GENERATOR"
+ content="Mozilla/4.7 [en] (X11; I; Linux 2.2.12-20 i686) [Netscape]">
+<meta http-equiv="content-type"
+ content="text/html; charset=ISO-8859-1">
+<title>LAME Changelog</title>
+</head>
+<body text="#000000" bgcolor="#ffffff" link="#888888" vlink="#555555"
+ alink="#bbbbbb">
+<center>
+  <h1> History</h1>
+</center>
+Starting with LAME 3.0: <br>
+<font color="#ff0000">red = features and bug fixes which affect quality</font> 
+<br>
+<font color="#3366ff">blue = features and bug fixes which affect speed</font> 
+<br>
+black = usability, portability, other 
+<hr>
+<h3>LAME 3.97&nbsp; &nbsp;September 24 2006</h3>
+<ul>
+  <li>3.97 beta 3 becomes 3.97 
+  </li>
+</ul>
+<br>
+<h3>LAME 3.97 beta 3&nbsp; &nbsp;August 19 2006</h3>
+<ul>
+  <li>Gabriel Bouvigne: 
+    <ul>
+      <li><font color="#ff0000">Workaround against a short blocks detection issue</font></li>
+    </ul>
+  </li>
+</ul>
+<br>
+<h3>LAME 3.97 beta 2&nbsp; &nbsp;November 26 2005</h3>
+<ul>
+  <li>Gabriel Bouvigne: 
+    <ul>
+      <li>Fixed an initialization error when input is not using a standard sampling frequency</li>
+      <li>Fixed a possible assertion failure in very low bitrate encoding</li>
+      <li><font color="#ff0000">Slight change regarding ATH adjustment with V5</font></li>
+      <li><font color="#ff0000">Reinstated bit reservoir for 320kbps CBR</font></li>
+      <li><font color="#3366ff">ReplayGain analysis should now be faster when encountering silent parts</font></li>
+    </ul>
+  </li>
+  <li>Takehiro Tominaga: 
+    <ul>
+      <li>Fixed a possible link problem of assembly code</li>
+    </ul>
+  </li>
+</ul>
+<br>
+<h3>LAME 3.97 beta 1&nbsp; &nbsp;September 12 2005</h3>
+<ul>
+  <li>Takehiro Tominaga: 
+    <ul>
+      <li>Fixed an out of array access in mp3rtp
+      <li><font color="#ff0000">Fixed a quality setting in DLL</font></li>
+      <li>Fixed display when using --silent</li>
+    </ul>
+  </li>
+  <li>Vitaly Ivanov: 
+    <ul>
+      <li>Updated DirectShow interface</li>
+    </ul>
+  </li>
+  <li>Robert Hegemann: 
+    <ul>
+      <li><font color="#ff0000">Fixed an out of array access</font></li>
+      <li><font color="#ff0000">Fixed some small rounding problem in vbr-new quantization routines</font></li>
+      <li><font color="#ff0000">Fixed a bug in vbr-new regarding high frequencies (sfb21) when using -Y</font></li>
+      <li><font color="#ff0000">Fixed a few bugs in vbr-new when using -Y</font></li>
+      <li><font color="#ff0000">Updated scalefactors allocation scheme in vbr-new</font></li>
+      <li>Fixed mingw32 configure problems</li>
+      <li>Resolved some compiler warnings</li>
+      <li>Updated command-line visualisation</li>
+    </ul>
+  </li>
+  <li>Gabriel Bouvigne: 
+    <ul>
+      <li>Changed some FLOAT8 to FLOAT</li>
+      <li>Added project files for VC7</li>
+      <li><font color="#ff0000">Reworked -q1 and -q0</font></li>
+      <li><font color="#ff0000">Updated presets</font></li>
+      <li><font color="#ff0000">Fixed an error in ISO quantization on systems not using the IEEE754 hack</font></li>
+      <li><font color="#3366ff">Faster quantization</font></li>
+      <li><font color="#3366ff">SSE version of init_xrpow</font></li>
+    </ul>
+  </li>
+  <li>Rogério Brito: 
+    <ul>
+      <li>Updated Debian packaging</li>
+      <li>Documentation work</li>
+    </ul>
+  </li>
+  <li>Chris Miller: 
+    <ul>
+      <li>Support for x64 platform SDK in makefile.msvc</li>
+    </ul>
+  </li>
+</ul>
+<br>
+<h3>LAME 3.96.1 &nbsp; &nbsp;July 25 2004</h3>
+<ul>
+  <li>Robert Hegemann: 
+    <ul>
+      <li><font color="#ff0000">Fixed a rare bug in vbr-new (could lead to crashes or data corruption)</font></li>
+    </ul>
+  </li>
+  <li>Gabriel Bouvigne: 
+    <ul>
+      <li>some fixes in ACM codec</li>
+      <li>fixed padding when encoding to 320kbps</li>
+      <li><font color="#ff0000">fixed block size selection for mid and side channels</font></li>
+    </ul>
+  </li>
+</ul>
+<br>
+<h3>LAME 3.96 &nbsp; &nbsp;April 11 2004</h3>
+<ul>
+  <li>Gabriel Bouvigne:
+  <ul>
+    <li><font color="#ff0000">new quantization selection mode (used in ABR/CBR)</font></li>
+    <li><font color="#ff0000">set sfscale for ABR/CBR up to 160kbps</font></li>
+</ul>
+</li>
+</ul>
+<br>
+<h3>LAME 3.96 beta 2 &nbsp; &nbsp;March 28 2004</h3>
+<ul>
+  <li>Takehiro Tominaga:
+  <ul>
+    <li><font color="#3366ff">removed unnecessary integer convertion in resampling</font></li>
+</ul></li>
+  <li>Robert Hegemann:
+  <ul>
+    <li><font color="#ff0000">reworked scalefactor allocation in vbr-new</font></li>
+    <li>fixed a freeformat decoding problem</li>
+</ul>
+  <li>Gabriel Bouvigne:
+  <ul>
+    <li><font color="#ff0000">updated minimal bitrate for V1 and V2</font></li>
+</ul>
+</li>
+  <li>Aleksander Korzynski:
+  <ul>
+    <li>added ability to disable ReplayGain analysis</li>
+</ul>
+</li>
+</ul>
+<br>
+<h3>LAME 3.96 beta &nbsp; &nbsp;March 7 2004</h3>
+<ul>
+  <li>Takehiro Tominaga:
+  <ul>
+    <li>fixed decoding issue</li>
+</ul></li>
+  <li>Aleksander Korzynski:
+  <ul>
+    <li>changed internal ReplayGain handling</li>
+    <li>fixed some issues when ReplayGain is used with resampling</li>
+</ul>
+</li>
+  <li>Robert Hegemann:
+  <ul>
+    <li>added standard ISO quantization for vbr-new, used at lower quality settings</li>
+    <li><font color="#3366ff">faster count_bits for vbr-new</font></li>
+    <li><font color="#3366ff">faster find_scalefac_ave function for vbr-new</font></li>
+    <li><font color="#ff0000">fixed an out of array access in psychoacoustic models;
+        this bug could make some psy calculations worthless and sometimes let lame crash</font></li>
+    <li><font color="#ff0000">fixed an error on silent scalefactor bands;
+        this bug resulted in huffman data overrun problems while decoding,
+        resulting in audible glitches</font></li>
+    <li>fixed a freeformat decoding bug</li> 
+</ul>
+  <li>Gabriel Bouvigne:
+  <ul>
+    <li><font color="#ff0000">adjusted short block thresholds</font></li>
+    <li>fixed some array addressing bugs</li>
+    <li>made ReplayGain analysis reentrant</li>
+</ul>
+</li>
+  <li>David Chandler: fixed a crash in quantize_xrpow
+</li>
+  <li>Michal Bacik: fixed a crash when using 8kHz
+</li>
+  <li>Goran Markovic: fixed some decoding bugs
+</li>
+  <li>John Edwards: fixed a too small buffer in ReplayGain code</li>
+</ul>
+<br>
+<h3>LAME 3.95.1 &nbsp; &nbsp;January 12 2004</h3>
+<ul>
+  <li>Gabriel Bouvigne:
+  <ul>
+    <li>fixed a crash when using vbr-new</li>
+    <li>changed ReplayGain reference level to 89dB</li>
+</ul></li>
+</ul>
+<br>
+<h3>LAME 3.95 &nbsp; &nbsp;January 11 2004</h3>
+<ul>
+  <li>Gabriel Bouvigne:
+  <ul>
+    <li><font color="#ff0000">fixed lowpass values when using vbr with mono files</font></li>
+    <li><font color="#3366ff">faster quantization loops</font></li>
+    <li><font color="#3366ff">faster count_bits</font></li>
+    <li>fixed a buffer requirement error in ACM codec</li>
+  </ul></li>
+  <li>Takehiro TOMINAGA:
+  <ul>
+    <li>fixed mpglib and other decoding support code to prevent the crash when invalid mp3 input</li>
+  </ul></li>
+  <li>removed Layer I decoding support</li>
+  <li><font color="#3366ff">use FastLog and IEEE 754 hack on PowerPC too (approx. 10 percent faster)</font></li>
+</ul>
+<br>
+<h3>LAME 3.94 beta December 15 2003</h3>
+<ul>
+  <li>Takehiro Tominaga: 
+    <ul>
+      <li><font color="#ff0000">fixed block switching of nspsytune</font></li>
+      <li><font color="#ff0000">best huffman divide in the inner loop.</font> 
+        This should improve the quality, but PAINFULLY slow. So it is not enabled 
+        by default. Use -q0 to use it.</li>
+      <li>Changed -q option mapping. "-q2" until version 3.93 is now "-q3".</li>
+      <li><font color="#ff0000">saving bits by better scalefactor storing</font></li>
+      <li>removed Vorbis support</li>
+      <li><font color="#ff0000">substep quantization.</font>This should help breaking 
+        the SFB21 bloating problem</li>
+      <li><font color="#ff0000">made psychoacoustic model aware of ATH adjustements</font></li>
+      <li><font color="#ff0000">use ATH value as short block masking lower limit</font></li>
+      <li><font color="#ff0000">several fixes in psychoacoustic model</font></li>
+      <li>more robust decoding</li>
+    </ul></li>
+  <li>Mark Taylor / Gabriel Bouvigne: fixed issues in VBR header</li>
+  <li>Mark Taylor: workaround against some hardware decoder defficiencies</li>
+  <li>Aleksander Korzynski: ability to compute the "Radio" ReplayGain and detect clipping 
+    on the fly. The ReplayGain value is stored in the Lame tag.</li>
+  <li>Gabriel Bouvigne:
+  <ul>
+    <li><font color="#ff0000">work on presets</font></li>
+    <li><font color="#ff0000">use presets by default for cbr/abr</font></li>
+    <li><font color="#ff0000">use presets by default for vbr</font></li>
+    <li><font color="#ff0000">analog silence detection in partitionned sfb21</font></li>
+    <li><font color="#3366ff">do not compute noise in upper 0 part of the spectrum</font></li>
+    <li><font color="#3366ff">only compute noise in modified scalefactor bands</font></li>
+  </ul></li>
+  <li>Guillaume Lessard:
+  <ul>
+    <li>nogap related changes</li>
+  </ul></li>
+  <li>Alexander Leidinger:
+  <ul>
+    <li>prevent closing the input fd prematurely if the input is a named pipe</li>
+  </ul></li>
+</ul>
+<br>
+<h3>LAME 3.93.1 &nbsp; &nbsp;December 1 2002</h3>
+<ul>
+  <li>Gabriel Bouvigne: 
+    <ul>
+      <li>preset medium added to the dll interface</li>
+      <li><font color="#ff0000">fix for abr/cbr presets</font></li>
+      <li><font color="#ff0000">fix -q0 switch</font></li>
+    </ul>
+  </li>
+  <li>Alexander Leidinger: fix link problem on systems where socket() resides 
+    in libsocket</li>
+</ul>
+<br>
+<h3>LAME 3.93 &nbsp; &nbsp;November 16 2002</h3>
+<ul>
+  <li>Takehiro Tominaga: 
+    <ul>
+      <li><font color="#ff0000">bit allocation for pre-echo control improved for 
+        single channel encodings</font></li>
+      <li><font color="#ff0000">substep noise shaping</font></li>
+      <li><font color="#3366ff">optimizations by changing data structure</font></li>
+      <li><font color="#ff0000">noise shaping model 2 fix</font></li>
+      <li><font color="#3366ff">nspsytune FIR filter clean up</font></li>
+      <li><font color="#ff0000">fix small psymodel bugs(DC current estimation, 
+        preecho detection of non-VBR mode, and nspsymode initialization)</font></li>
+      <li>portability fixes for Tru64 UNIX</li>
+    </ul>
+  </li>
+  <li>Albert Faber: some fixes in the DLL</li>
+  <li>Simon Blandford: fixes for channel scaling in mono mode</li>
+  <li><font color="#3366ff">Dominique Duvivier: some optimizations and a faster 
+    log10 function</font></li>
+  <li>Mark Taylor: 
+    <ul>
+      <li>some tag related fixes in the direct show filter and in the ACM codec</li>
+      <li><font color="#3366ff">fixed a mono encoding bug found by Justin Schoeman</font></li>
+      <li>calc_noise bug fix</li>
+      <li>other fixes</li>
+    </ul>
+  </li>
+  <li>Alexander Leidinger: 
+    <ul>
+      <li>update to autoconf 2.53, rewrite some configure tests</li>
+      <li>Akos Maroy: determine gcc version even with gcc 3.1</li>
+      <li>Andrew Bachmann: compile shared libs on BeOS (and perhaps other arches)</li>
+      <li>ultrasparc switches for gcc 3.1</li>
+      <li>fixes for SunOS 4.x</li>
+      <li>fixes for 64bit arches</li>
+      <li>CFLAGS fix for IRIX</li>
+      <li>don't override CFLAGS if exptopt isn't requested</li>
+    </ul>
+  </li>
+  <li>Robert Hegeman: 
+    <ul>
+      <li><font color="#3366ff">some fixes</font></li>
+      <li><font color="#ff0000">some fixes for VBR</font></li>
+    </ul>
+  </li>
+  <li>Gabriel Bouvigne: 
+    <ul>
+      <li>--noasm switch. Might help Cyrix/Via users</li>
+      <li><font color="#ff0000">presets and alt-presets merged</font></li>
+    </ul>
+  </li>
+</ul>
+<br>
+<h3>LAME 3.92 &nbsp; &nbsp;April 14 2002</h3>
+<ul>
+  <li><font color="#ff0000">Alexander Leidinger:&nbsp; add non linear psymodel 
+    (compile time option, disabled by default)</font>, workaround a bug in gcc 
+    3.0.3 (compiler options, based upon suggestions from various people, see archives 
+    and changelog for more)</li>
+  <li>Steve Lhomme:&nbsp; ACM wrapper (MS-Windows codec)</li>
+  <li><font color="#3366ff">Steve Lhomme:&nbsp; less memory copying on stereo 
+    (interleaved) input</font></li>
+  <li> <font color="#ff0000">Takehiro Tominaga: Inter-channel masking, enables 
+    with --interch x option</font></li>
+  <li> For buggy versions of gcc compiler (2.96*), back off on some of the advanced 
+    compiler options<br>
+  </li>
+</ul>
+<br>
+<h3>LAME 3.91 &nbsp; &nbsp;December 29 2001</h3>
+<ul>
+  <li><font color="#ff0000">Darin Morrison:&nbsp; Bugfix for --alt-preset (for 
+    content with low volume, clean vocals), only important for the "fast standard" 
+    preset</font>
+  </li>
+  <li>Alexander Leidinger:
+    <ul>
+      <li>add some missing files to the distribution</li>
+      <li>add --alt-preset to the man page</li>
+    </ul>
+  </li>
+</ul>
+<br>
+<h3>LAME 3.90 &nbsp; &nbsp;December 21 2001</h3>
+<ul>
+  <li><font color="#ff0000">Many small improvements and bug fixes not added to 
+    history</font></li>
+  <li><font color="#ff0000">John Dahlstrom:&nbsp; more fine tuning on the auto 
+    adjustment of the ATH</font></li>
+  <li><font color="#3366ff">Robert Hegemann:&nbsp; small speed and quality improvements 
+    for the old VBR code (--vbr-old).</font> </li>
+  <li><font color="#ff0000">Robert Hegemann:&nbsp; some short block bug fixes</font> 
+  </li>
+  <li><font color="#ff0000">Robert Hegemann:&nbsp; Big improvements to --vbr-mtrh, 
+    now encodes much more frequencies over 16khz</font> </li>
+  <li><font color="#ff0000">Robert Hegemann:&nbsp; --vbr-new code disabled (outdated 
+    and lower quality) and replaced with --vbr-mtrh (Both --vbr-new and --vbr-mtrh 
+    now default to mtrh)</font> </li>
+  <li>Robert Hegemann:&nbsp; reordering of --longhelp to give more information, 
+    --extrahelp dropped </li>
+  <li>Darin Morrison:&nbsp; Totally revamped and extremely high quality unified 
+    preset system and other general quality improvements now available with --alt-presets: 
+    <ul>
+      <li> <font color="#ff0000">some improvements to psychoacoustics (vast improvements 
+        over default L.A.M.E. modes) when --alt-preset is used including:</font></li>
+      <ul>
+        <li> <font color="#ff0000">Improved tuning of short block usage.</font></li>
+        <li> <font color="#ff0000">Improved quantization selection usage (the 
+          -X modes), now adapts between appropriate modes on the fly. Also helps 
+          on "dropout" problems and with pre-echo cases.</font></li>
+        <li> <font color="#ff0000">Improved joint stereo usage. Thresholds are 
+          better tuned now and fix some "dropout" problems L.A.M.E. suffers from 
+          on clips like serioustrouble.</font></li>
+        <li> <font color="#ff0000">Improved noise shaping usage. Now switches 
+          between noise shaping modes on the fly (toggles -Z on and off when appropriate) 
+          which allows lower bitrates but without the quality compromise.</font></li>
+        <li> <font color="#ff0000">Clips vastly improved over default L.A.M.E. 
+          modes (vbr/cbr/abr, including --r3mix): castanets, florida_seq, death2, 
+          fatboy, spahm, gbtinc, ravebase, short, florida_seq, hihat, bassdrum, 
+          2nd_vent_clip, serioustrouble, bloodline, and others. No degraded clips 
+          known.</font></li>
+        <li> VBR bitrates are now more "stable" with less fluctuation -- not dipping 
+          too low on some music and not increasing too high unnecessarily on other 
+          music. "--alt-preset standard" provides bitrates roughly within the 
+          range of 180-220kbps, often averaging close to 192kbps.</li>
+      </ul>
+      <li> --alt-presets replace the --dm-presets and "metal" preset is removed 
+        and replaced with generic abr and cbr presets.</li>
+      <li> --alt-preset extreme (note the 'e') replaces xtreme to help eliminate 
+        some confusion</li>
+      <li> --alt-preset vbr modes now have a fast option which offers almost no 
+        compromise in speed.</li>
+      <li> --alt-preset standard (and "fast standard") are now much lower in bitrate, 
+        matching --r3mix with an overall average, though offering higher quality 
+        especially on difficult test samples.</li>
+      <li> --alt-presets are no longer just "presets" as in a collection of switches, 
+        instead they are now quality "modes" because of special code level tunings 
+        (those mentioned above).</li>
+      <li> Use --alt-preset help for more information.</li>
+    </ul>
+  </li>
+  <li>Roel VdB: more tuning on the --r3mix preset </li>
+  <li>Jon Dee, Roel VdB:&nbsp; INFO tag</li>
+  <li>Alexander Leidinger, mp3gain@hotmail.com:&nbsp; added --scale-l and --scale-r 
+    to scale stereo channels independantly </li>
+  <li>Takehiro Tominaga:&nbsp; <font color="#ff0000">new noise shaping mode, offering 
+    more "cutting edge" shaping according to masking, enabled via -q0</font> </li>
+  <li>Mark Taylor:&nbsp; More work on --nogap </li>
+  <li>Gabriel Bouvigne:&nbsp; Small changes to abr code for more accurate final 
+    bitrate </li>
+  <li>Gabriel Bouvigne, mp3gain@hotmail.com:&nbsp; Preliminary <a
+ href="http://www.replaygain.org"> ReplayGain</a> analysis code added (not functional 
+    yet) </li>
+  <li>Gabriel Bouvigne, Alexander Leidinger:&nbsp; Documentation updates </li>
+  <li>John Dahlstrom, DSPguru@math.com:&nbsp; floating point interface function 
+    in the Windows DLL</li>
+</ul>
+<br>
+<h3>LAME 3.89beta&nbsp; &nbsp;July 5 2001</h3>
+<ul>
+  <li> John Stewart:&nbsp; long filename support for Win9x/NT.</li>
+  <li> Takehiro Tominaga:&nbsp; LAME can calculate the CRC of VBR header, so now 
+    "lame -pv" works fine.</li>
+  <li><font color="#ff0000">Robert Hegemann:&nbsp; Improvements of the new VBR 
+    code (--vbr-mtrh).</font></li>
+  <li><font color="#3366ff">Robert Hegemann: New VBR code (--vbr-mtrh) is now 
+    defaulted to get more feedback. The VBR speed is now on par with CBR. We will 
+    use the old VBR code in the release.</font></li>
+  <li><font color="#ff0000">Gabriel Bouvigne: Change of the maximum frame size 
+    limit. LAME should now be more friendly with hardware players.</font></li>
+  <li>Gabriel Bouvigne: Size of VBR is now more balanced according to the -V value.</li>
+  <li>Alexander Leidinger: Finished the implementation of the set/get functions.</li>
+  <li>John Dahlstrom: LAME now handles 24bits input</li>
+  <li>Mark Taylor: bugs in lame --decode causing truncation of mp3 file fixed</li>
+  <li>Mark Taylor: preliminary --nogap support</li>
+  <li>"Final" API completed: shared library safe! &nbsp;This API is frozen and 
+    should be backwords compatiable with future versions of libmp3lame.so, but 
+    we will continue to add new functionality. &nbsp;<br>
+  </li>
+</ul>
+<h3> LAME 3.88beta&nbsp;&nbsp; March 25 2001</h3>
+<ul>
+  <li> <font color="#ff0000">A lot of work that was never added to the History!</font></li>
+  <li> <font color="#ff0000">Frank Klemm and Gabriel Bouvigne:&nbsp; New ATH formula.&nbsp; 
+    Big improvement for high bitrate encodings.</font></li>
+  <li> <font color="#ff0000">Takehiro Tominaga: Temporal masking</font></li>
+  <li> <font color="#ff0000">Gabriel Bouvigne/Mark Taylor: auto adjustment of 
+    ATH</font></li>
+  <li> <font color="#ff0000">Robert Hegemann:&nbsp; Better outer_loop stopping 
+    criterion.&nbsp; Enabled with -q2 or better.</font></li>
+  <li> <font color="#ff0000">Robert Hegemann/Naoki Shibata:&nbsp; slow/carefull 
+    noise shaping.&nbsp; -q3..9:&nbsp; amplify all distorted bands.&nbsp; -q2: 
+    amplify distorted bands within 50%.&nbsp; -q1-0:&nbsp; amplify only most distorted 
+    band at each iteration.</font></li>
+  <li> <font color="#ff0000">Takehiro Tominaga: Interframe, shortblock temporal 
+    masking.</font></li>
+  <li> Takehiro Tominaga:&nbsp; LAME restructured into a shared library and front 
+    end application.&nbsp; Slight changes to the API. More changes are coming 
+    to turn LAME into a true shared library (right now you have to recompile if 
+    you upgrade the library :-(</li>
+  <li> <font color="#000000">Naoki Shibata:</font></li>
+  <ul>
+    <li> <font color="#ff0000">improvements to psychoacoustics</font><font
+ color="#000000"> (--nspsytune)</font></li>
+    <li> <font color="#ff0000">BUG in long block pre echo control fixed </font><font color="#000000"> 
+      (some out of range array access in M/S psychoacoustics)</font></li>
+  </ul>
+  <li> <font color="#000000">Ralf Kempkens:&nbsp;&nbsp;&nbsp; Visual Basic Script 
+    for lame, suggested to put it on your Windows Desktop and you can drag'n'drop 
+    Waves to encode on it.</font></li>
+  <li> <font color="#000000">Alexander Stumpf:&nbsp;&nbsp;&nbsp; improved lame.bat 
+    for 4Dos users</font></li>
+  <li> <font color="#000000">Mark Taylor: Several bugs fixed in the resampling 
+    code.</font></li>
+  <li> <font color="#000000">Frank Klemm, Robert Hegemann:&nbsp;&nbsp;&nbsp; added 
+    assembler code for CPU feature detection on runtime (MMX, 3DNow, SIMD)</font></li>
+  <li> <font color="#3366ff">Takehiro Tominaga: 3DNow FFT code.</font></li>
+  <li> <font color="#000000">Florian Bome, Alexander Leidinger:&nbsp;&nbsp;&nbsp; 
+    more work on configure stuff</font></li>
+  <li> <font color="#000000">Alexander Leidinger:&nbsp;&nbsp; automake/libtool 
+    generated Makefiles and TONS of other work.</font></li>
+  <li> <font color="#000000">Alexander Leidinger:&nbsp;&nbsp; Much work towards 
+    shared library style API.</font></li>
+  <li> <font color="#000000">Anonymous: New more efficient RTP code.</font></li>
+  <li> <font color="#ff0000">Mark Taylor: psycho-acoustic data now computed for 
+    all scalefactor bands (up to 24 kHz)</font></li>
+  <li> <font color="#ff0000">Mark Taylor, Takehiro Tominaga: All ISO table data 
+    replaced by formulas - should improve MPEG2.5 results for which we never had 
+    correct table data.</font></li>
+</ul>
+<h3> LAME 3.87alpha&nbsp; September 25 2000</h3>
+<ul>
+  <li> Mark Taylor:&nbsp; Bug fixed in LAME/mpglib error recovery when encountering 
+    a corrupt&nbsp; MP3 frame during *decoding*.</li>
+  <li> Albert Faber:&nbsp; added LayerI+II decoding support</li>
+  <li> <font color="#000000">Frank Klemm:&nbsp; added improved CRC calculation</font></li>
+  <li> <font color="#000000">Frank Klemm: substantial code cleanup/improvements</font></li>
+  <li> Robert Hegemann:&nbsp; Bug fixes</li>
+  <ul>
+    <li> <font color="#ff0000">in huffman_init</font>, could lead to segmentation 
+      faults (only in rare cases, most likely at lower sample rates)</li>
+    <li> <font color="#ff0000">M/S switching at lower sample rates</font> (the 
+      fact there is no 2nd granule was ignored)</li>
+  </ul>
+  <li> <font color="#3366ff">Robert Hegemann:&nbsp; speed up in&nbsp; VBR</font></li>
+  <li> Jarmo Laakkonen:&nbsp; Amiga/GCC settings for Makefile.unix.</li>
+  <li> Magnus Holmgren:&nbsp; README and Makefile for (free) Borland C++&nbsp; 
+    compiler. Will also compile lame_enc.dll, but this is untested.</li>
+  <li> Florian Bome:&nbsp;&nbsp; LAME finally has a&nbsp; ./configure script!!</li>
+</ul>
+<h3> LAME 3.86beta&nbsp; August 6 2000</h3>
+<ul>
+  <li> Christopher Wise:&nbsp; A makefile for DJGPP, the DOS version of gcc.&nbsp; 
+    Now most windows users should be able to compile LAME with minimal effort.</li>
+  <li> <font color="#ff0000">Robert Hegemann:&nbsp; old VBR:&nbsp;&nbsp; fixed 
+    some bugs and Takehiro's scalefac_scale feature (not yet on by&nbsp; default.)&nbsp; 
+    older LAME versions did not allow to spent more than 2500 bits of 4095 possible 
+    bits to a granule per channel, now fixed.</font></li>
+  <li> Robert Hegemann:&nbsp; new VBR:&nbsp;&nbsp; analog silence treatment like 
+    in old VBR</li>
+  <li> William Welch:&nbsp; Improved options for Linux/Alpha gcc and ccc compilers 
+    in Makefile.</li>
+  <li> Mathew Hendry:&nbsp; setting appropriate CRC bit for additional Xing-VBR 
+    tagging frame</li>
+  <li> Don Melton:&nbsp; added ID3 version 2 TAG support</li>
+  <li> <font color="#000000">John Dahlstrom: fixed bug allowing timing information 
+    (for status in command line encoder) to overflow.</font></li>
+  <li> <font color="#000000">Tamito KAJIYAMA, Fixed several bugs in the LAME/Vorbis 
+    interface.</font></li>
+  <li> <font color="#000000">Mark Taylor:&nbsp; lame --decode will recognize <a href="http://albumid.cjb.net">Album 
+    ID tags</a></font></li>
+  <li> <font color="#ff0000">Naoki Shibata:&nbsp; Additive masking and other improvements 
+    to psycho acoustics.&nbsp; (not yet on by default)</font></li>
+</ul>
+<h3> LAME 3.85beta&nbsp;&nbsp; July 3 2000</h3>
+<ul>
+  <li> <font color="#ff0000">Takehiro Tominaga:&nbsp; mid/side stereo demasking 
+    thresholds updated.</font></li>
+  <li> Takehiro Tominaga: New short block MDCT coefficient data structure.&nbsp; 
+    Should allow for future speed improvements.</li>
+  <li> Robert Hegemann:&nbsp; fixed bug in old VBR routine, the --noath mode messed 
+    up the VBR routine resulting in very large files</li>
+  <li> Robert Hegemann: found bugs in some sections when using 32 bit floating 
+    point.&nbsp; Default is now back to 64bit floating point.</li>
+  <li> <font color="#ff0000">Takehiro Tominaga:&nbsp; Modified PE formula to use 
+    ATH.</font></li>
+  <li> <font color="#000000">S.T.L.:&nbsp; README.DJGPP - instructions for compiling 
+    LAME with DJGPP, the dos version of gcc.</font></li>
+</ul>
+<h3> LAME 3.84beta&nbsp; June 30&nbsp; 2000</h3>
+<ul>
+  <li> Mark Weinstein:&nbsp; .wav file output (with --decode option) was writing 
+    the wrong filesize in the .wav file.&nbsp; Now fixed.</li>
+  <li> Mark Taylor:&nbsp; (optional) Vorbis support, both encoding and decoding.&nbsp; 
+    LAME can now produce .ogg files, or even re-encode your entire .ogg collection 
+    into mp3.&nbsp;&nbsp; (Just kidding: it is always a bad idea to convert from 
+    one lossy format to another)</li>
+  <li> ?: Bug fixed causing VBR to crash under windows.&nbsp;&nbsp; (pretab[] 
+    array overflow)</li>
+  <li> Sergey Sapelin: Another bug found in the mpg123 MPEG2 tables.&nbsp; Now 
+    fixed for the mpg123 based decoder in LAME.</li>
+  <li> Marco Remondini:&nbsp; VBR histogram works in win32.&nbsp; compile with 
+    -DBRHIST -DNOTERMCAP</li>
+  <li> <font color="#ff0000">Takehiro Tominaga:&nbsp; LAME CBR will now use scalefac_scale 
+    to expand the dynamic range of the scalefactors.</font></li>
+  <li> <font color="#000000">Iwasa Kazmi:&nbsp; Library improvements:&nbsp; exit()'s, 
+    printf, fprintf's are being replaced by interceptable macros.</font></li>
+</ul>
+<h3> LAME 3.83beta&nbsp; May 19&nbsp; 2000</h3>
+<ul>
+  <li> <font color="#ff0000">Mark Taylor:&nbsp; Bug in buffering routines:&nbsp; 
+    in some cases, could cause MDCT&nbsp; to read past end of buffer.&nbsp; Rare 
+    in MPEG2, even more rare for MPEG1, but potentially serious!</font></li>
+  <li> Mark Taylor:&nbsp; MDCT/polyphase filterbank was not being "primed" properly.&nbsp; 
+    Does not effect output unless you set the encoder delay lower than the default 
+    of 576 samples.</li>
+  <li> <font color="#ff0000">Mark Taylor:&nbsp; "vdbj" and "Caster"&nbsp; found 
+    several VBR bugs (now fixed):&nbsp;&nbsp; 1.&nbsp; Analog silence detection 
+    only checked frequencies up to 16 kHz.&nbsp; 2.&nbsp; VBR mode could still 
+    somehow avoid -F mode.&nbsp; 3.&nbsp; VBR mode would ignore noise above 16 
+    kHz (scalefactor band 22), Now calc_noise1 will compute the noise in this 
+    band when in VBR mode.&nbsp; Not calculated in CBR&nbsp; mode since CBR algorithm 
+    has no way of using this information.</font></li>
+  <li> Mark Taylor:&nbsp; scalefactor band 22 info (masking(=ATH),&nbsp; noise 
+    and energy) now displayed in frame analyzer.</li>
+  <li> <font color="#ff0000">VBR code ATH tuning was disabled by accident in 3.81, 
+    now fixed.</font></li>
+  <li> <font color="#000000">Mark Taylor:&nbsp; lame --decode will produce .wav 
+    files.&nbsp; (oops - size is off by a factor of 4)</font></li>
+</ul>
+<h3> LAME 3.82beta&nbsp;&nbsp; May 11 2000</h3>
+<ul>
+  <li> Robert Hegemann:&nbsp; Fixed bug in high bitrate joint stereo encodings.</li>
+  <li> <font color="#3366ff">Naoki Shibata:&nbsp; new long block MDCT routine</font></li>
+</ul>
+<h3> LAME 3.81beta&nbsp; May 8 2000</h3>
+<ul>
+  <li> all ISO code removed!</li>
+  <li> <font color="#3366ff">Takehiro Tominaga and Naoki Shibata:&nbsp; new window 
+    subband routines.</font></li>
+  <li> <font color="#000000">Naoki Shibata:&nbsp; Bug fix in mpglib (decoding) 
+    lib:&nbsp; in some cases, MDCT coefficients from previous granule was incorrectly 
+    used for the next granule.</font></li>
+  <li> <font color="#ff0000">ISO 7680 bit buffer limitation removed.&nbsp; It 
+    can be reactivated with "--strictly-enforce-ISO"&nbsp; Please report any trouble 
+    with high bitrates.</font></li>
+</ul>
+<h3> LAME 3.80beta&nbsp; May 6 2000</h3>
+<ul>
+  <li> <font color="#ff0000">Takehiro Tominaga:&nbsp; more efficient and faster 
+    huffman encoding!</font></li>
+  <li> <font color="#ff0000">Takehiro Tominaga and Mark Taylor:&nbsp; much improved 
+    short block compression!</font></li>
+  <li> <font color="#000000">Tomasz Motylewski and Mark Taylor:&nbsp; MPEG2.5 
+    now supported!</font></li>
+  <li> <font color="#000000">Mark Taylor: incorporated Takehiro's bitstream.c!&nbsp; 
+    bitstream.c used by default, but old ISO bitstream code can also be used.</font></li>
+  <li> <font color="#ff0000">Scott&nbsp; Manley and Mark Taylor:&nbsp; good resampling 
+    routine finaly in LAME.&nbsp; uses a 19 point FIR filter with Blackman window.&nbsp; 
+    Very slow for non integer resampling ratios.</font></li>
+  <li> <font color="#000000">Iwasa Kazmi:&nbsp; fixed SIGBUS error:&nbsp; VBR 
+    and id3 tags were using data after it was free()'d.</font></li>
+  <li> <font color="#ff0000">Robert Hegemann:&nbsp; Improved VBR tuning.&nbsp; 
+    #define RH_QUALITY_CONTROL and #RH_SIDE_VBR now the defaults.</font></li>
+  <li> <font color="#000000">Robert Hegemann:&nbsp;&nbsp; LAME version string 
+    now added to ancillary data.</font></li>
+  <li> Kimmo Mustonen:&nbsp; VBR histogram support for Amiga.</li>
+  <li> Casper Gripenberg:&nbsp; VBR stats (but not histogram) for DOS verson.</li>
+  <li> Robert Hegemann:&nbsp; rare VBR overflow bug fixed.</li>
+  <li> Zack:&nbsp; -F option strictly enforces the VBR min bitrate.&nbsp; Without 
+    -F, LAME will ignore the minimum bitrate when encoding analog silence.</li>
+  <li> Shawn Riley:&nbsp; User can now specify a compression ratio (--comp &lt;arg&gt;) 
+    instead of a bit rate.&nbsp; Default settings based on a compression ratio 
+    of 11.0</li>
+  <li> Mark Taylor:&nbsp; free format bitstreams can be created with --freeformat, 
+    and specify any integer bitrate from 8 to 320kbs with -b.</li>
+  <li> Mark Taylor: lame be used as a decoder (output raw pcm only):&nbsp; lame 
+    --decode input.mp3 output.pcm</li>
+</ul>
+<h3> LAME 3.70&nbsp;&nbsp; April 6 2000</h3>
+<ul>
+  <li> "LAME 3.69beta" becomes LAME 3.70 "stable"</li>
+</ul>
+<h3> LAME 3.69beta&nbsp;&nbsp; April 6 2000</h3>
+<ul>
+  <li> "spahm":&nbsp; default mode selection bug fixed.&nbsp; In some cases, lame 
+    was defaulting to regular stereo instead of jstereo when the user did not 
+    specify a mode.</li>
+</ul>
+<h3> LAME 3.68beta&nbsp; April 4 2000</h3>
+<ul>
+  <li> Mark Taylor: mono encoding bug in DLL fixed.</li>
+  <li> Ingo Saitz: bug in --cwlimit argument parsing fixed.</li>
+  <li> <font color="#ff0000">Scott Manly: bug in 4-point resample code fixed.</font></li>
+</ul>
+<h3> LAME 3.67beta&nbsp; March 27 2000</h3>
+<ul>
+  <li> <font color="#ff0000">Robert Hegemann:&nbsp; jstereo now enabled for MPEG2 
+    encodings</font></li>
+  <li> Mark Taylor: old M/S stereo mode which used L/R maskings has been removed.</li>
+  <li> Mark Taylor: Xing MPEG2 VBR headers now working.</li>
+  <li> <font color="#ff0000">Mark Taylor:&nbsp; When quantized coefficients are 
+    all 0 in a band, set scalefactors to 0 also to save a few bits.</font></li>
+  <li> <font color="#000000">Ingo Saitz:&nbsp; Problems with framesize calculation 
+    when using -f fast-math option fixed.</font></li>
+</ul>
+<h3> LAME 3.66beta March 21 2000</h3>
+<ul>
+  <li> Bug fixes in BladeEnc DLL, possible click in last mp3 frame, VBR historgram 
+    display, byteswapping option, ASM quantize routines work for both float and 
+    double.</li>
+</ul>
+<h3> LAME 3.65beta&nbsp;&nbsp; March 17 2000</h3>
+<ul>
+  <li> Enabled ASM version of quantize_xrpow() - accidently disabled in lame3.64.</li>
+</ul>
+<h3> LAME 3.64beta&nbsp; March 16 2000</h3>
+<ul>
+  <li> Don Melton:&nbsp; id3v1.1 tags &amp; id3 bugfixes</li>
+  <li> <font color="#ff0000">Gabriel Bouvigne:&nbsp; L/R matching block type fix</font></li>
+  <li> <font color="#ff0000">Bug fixed which was allowing quantized values to 
+    exceed the maximum when not using -h</font></li>
+  <li> <font color="#3366ff">Mark Taylor: Fitlers based on polyphase filterbank.&nbsp; 
+    should be slightly better since the responce is independent of the blocktype, 
+    and they are slightly faster.</font></li>
+  <li> Mark Taylor: API:&nbsp; the API changed slightly - and this should be the 
+    final version. There is a new routine: lame_encode_buffer() which takes an 
+    arbritray sized input buffer, resamples &amp; filters if necessary, encodes, 
+    and returns the mp3buffer.&nbsp; There are also several new #defines, so it 
+    is possible to compile a simple encoding library with no decoding or file 
+    I/O or command line parsing.&nbsp; see the file API for details.</li>
+  <li> Mark Taylor: MSVC stuff:&nbsp; lame.exe (with and without the frame analyzer) 
+    and the CDex lame_enc.dll</li>
+  <br>
+  should compile under MSVC.&nbsp; The MSVC5 project files may need some tweaking.&nbsp; 
+  In particular, <br>
+  you need to make sure LAMEPARSE, LAMESNDFILE and HAVEMPGLIB <br>
+  are defined.&nbsp; (and HAVEGTK for the GTK stuff). 
+</ul>
+<h3> LAME 3.63beta&nbsp; February 20&nbsp; 2000</h3>
+<ul>
+  <li> Robert Hegemann:&nbsp; FPE with -h fixed?</li>
+  <li> Mathey Hendry:&nbsp; FPE error catching for Cygwin, FPE fix for vbr mode 
+    and output to /dev/null</li>
+  <li> Jeremy Hall:&nbsp; Fixed problems with input files where the number of 
+    samples is not known.</li>
+  <li> <font color="#3366ff">Mathew Hendry:&nbsp; ASM quantize_xrpow() for GNU 
+    i386</font></li>
+  <li> <font color="#3366ff">Wilfried Behne&nbsp; quantize_xrpow ()for PowerPC 
+    and non-ASM</font></li>
+  <li> <font color="#3366ff">Takehiro Tominaga:&nbsp; GOGO FFTs&nbsp; (not yet 
+    used?)</font></li>
+  <br>
+  &nbsp; 
+</ul>
+<h3> LAME 3.62beta&nbsp;&nbsp; February 9 2000</h3>
+<ul>
+  <li> <font color="#000000">Iwasa Kazmi:&nbsp; frame analyzer short block display 
+    of single subblocks (press 1,2&nbsp; or 3)</font></li>
+  <li> <font color="#000000">Ingo Saitz:&nbsp; --help option added, with output 
+    to stdout</font></li>
+  <li> <font color="#ff0000">Alfred Weyers: short block AAC spreading function 
+    bug fixed</font></li>
+  <li> <font color="#3366ff">Takehiro Tominaga:&nbsp; new scalefac data structure 
+    - improves performance!</font></li>
+  <li> <font color="#ff0000">Lionel Bonnet:&nbsp; Bug fixed in MPEG2 scalefactor 
+    routine: scalefactors were being severly limited.</font></li>
+  <li> <font color="#3366ff">Takehiro Tominaga:&nbsp; faster FFT routines from.&nbsp; 
+    These routines are also compatible with the GOGO routines, in case someone 
+    is interested in porting them back to LAME.</font></li>
+  <li> <font color="#3366ff">Sigbj&oslash;rn Skj&aelig;ret, Takehiro Tominaga:&nbsp; 
+    faster pow() code.</font></li>
+  <li> <font color="#ff0000">Joachim Kuebart:&nbsp; Found some unitialized variables 
+    that were effecting quality for encodings which did not use the -h option 
+    (now fixed).</font></li>
+  <li> Mark Taylor: More modularization work.&nbsp;&nbsp; It is now possible to 
+    use LAME as a library where you can set the encoding parameters directly and 
+    do your own file i/o.&nbsp;&nbsp; The calling program is now it's own mp3 
+    output.&nbsp; For an example of the LAME API, see main.c, or mp3rtp.c or mp3x.c.&nbsp; 
+    These can all be compiled as stand alone programs which link with libmp3lame.a.</li>
+  <li> Felix vos Leitner:&nbsp; mp3rtp fixes.&nbsp; mp3rtp is a standalone program 
+    which will encode and stream with RTP.</li>
+  <li> Robert Hegemann:&nbsp; Information written to stderr displaying exactly 
+    which type of lowpass filter (if any) is being used.</li>
+  <li> Iwasa Kazmi:&nbsp; mpglib (the mpg123 decoder) scsfi decoding fixes.</li>
+  <li> Takehiro Tominaga:&nbsp; More mpglib scsfi decoding fixes.</li>
+</ul>
+<h3> LAME 3.61beta&nbsp; January 14 2000</h3>
+<ul>
+  <li> <font color="#ff0000">Mark Taylor: Fixed bug with lowpass filters when 
+    using VBR with a 64kbs or lower min bitrate setting.</font></li>
+  <li> <font color="#ff0000">Takehiro Tominaga:&nbsp; more efficient huffman encoding 
+    splitting.</font></li>
+</ul>
+<h3> LAME 3.60beta&nbsp;&nbsp; January 9 2000</h3>
+<ul>
+  <li> Mark Taylor: Distribution now comes with self test.&nbsp; Needs work to 
+    be automated, see 'make test' in Makefile.</li>
+  <li> <font color="#ff0000">Mark Taylor: AAC spreading function now the default</font></li>
+  <li> Gabriel Bouvigne: updated HTML docs</li>
+  <li> Felix von Leitner: compute correct file length from Xing header (if present) 
+    when input file is a mp3 file</li>
+  <li> Felix von Leitner: mp3rtp (standalone) program now included.&nbsp; Not 
+    yet tested.&nbsp; mp3rtp ip:port:ttl&nbsp; &lt;infile&gt;&nbsp;&nbsp; /dev/null 
+    will stream directly to ip:port using&nbsp; RTP.</li>
+  <br>
+  &nbsp; 
+</ul>
+<h3> LAME 3.59beta&nbsp; January 4 2000</h3>
+<ul>
+  <li> Takehiro Tominaga:&nbsp; --noath option.&nbsp; Disables ATH maskings.</li>
+  <li> Gabriel Bouvigne:&nbsp; updated HTML docs.</li>
+  <li> Iwasa Kazmi:&nbsp; makefile fixes</li>
+  <li> Mark Taylor:&nbsp; Fixed bug where first frame of data was always overwritten 
+    with 0's.&nbsp; Thanks to 'gol'</li>
+  <li> <font color="#ff0000">Mark Taylor:&nbsp; bug fixes in mid/side masking 
+    ratios (thanks to Menno Bakker)</font></li>
+  <li> Mark Taylor:&nbsp; replaced norm_l, norm_s table data with formulas.</li>
+</ul>
+<h3> LAME 3.58beta&nbsp; December 13 1999</h3>
+<ul>
+  <li> <font color="#ff0000">Segher Boessenkool:&nbsp; More accurate quantization 
+    procedure!&nbsp; Enabled with -h.</font></li>
+  <li> <font color="#3366ff">Mathew Hendry, Acy Stapp and Takehiro Tominaga: ASM 
+    optimizations for quantize_xrpow and quantize_xrpow_ISO.</font></li>
+  <li> Chuck Zenkus:&nbsp; "encoder inside" logo on web page</li>
+  <li> Mark Taylor:&nbsp;&nbsp; a couple people have asked for this.&nbsp;&nbsp; 
+    Allow LAME to overide VBR_min_bitrate if analog_silence detected.&nbsp;&nbsp; 
+    Analog_silence defined a la Robert:&nbsp;&nbsp; energy&nbsp; &lt; ATH.</li>
+  <li> An Van Lam: Valid bitrates were being printed for layer 2, not layer 3!</li>
+  <li> Ethan Yeo:&nbsp; Makefile.MSVC updated</li>
+  <li> Mark Stephens:&nbsp; updated all MSVC project files</li>
+  <li> Robert Hegemann:&nbsp; lowpass and highpass filters can be enabled with 
+    --lowpass, --highpass</li>
+  <li> <font color="#ff0000">Mark Taylor:&nbsp; MS switching is now smoother: 
+    ms_ratio average over 4 granules</font></li>
+  <li> <font color="#ff0000">Takehiro Tominaga:&nbsp; Scalefactor pre-emphasis 
+    fixed (and now turned back on)</font></li>
+  <li> <font color="#ff0000">Takehiro Tominaga:&nbsp; Bug in M/S maskings:&nbsp; 
+    switch to turn on stereo demasking code was buggy.</font></li>
+</ul>
+<h3> LAME 3.57beta&nbsp; November 22 1999</h3>
+<ul>
+  <li> Sigbj&oslash;rn Skj&aelig;ret, patch to allow encoding from 8bit input 
+    files when using LIBSNDFILE</li>
+  <li> Mark Taylor: Automatic downsampling to nearest valid samplerate.</li>
+  <li> Mark Taylor: Scalefactor bands demarked on MDCT plot in frameanalyzer</li>
+  <li> Mark Taylor: Scalefactor preemphasis disabled for now.&nbsp;&nbsp; The 
+    algorithm was often doing more harm than good.</li>
+</ul>
+<h3> LAME 3.56beta&nbsp; November 19 1999</h3>
+<ul>
+  <li> Kimmo Mustonen: portabilty code cleanup.</li>
+  <li> Vladimir Marek: id3 genre patch.</li>
+  <li> Conrad Sanderson: new applypatch script.</li>
+  <li> Mark Taylor: Initial window type now "STOP_TYPE" to reduce initial attenuation.&nbsp; 
+    This is needed because the new encoder delay is so short.&nbsp; With a NORM_TYPE, 
+    the first 240 samples would be attenuated.</li>
+  <li> Mark Taylor: Padding at end of file now adjusted (hopefully!) to produce 
+    as little padding as possible while still guarantee all input samples are 
+    encoded.</li>
+  <li> <font color="#ff0000">Takehiro Tominaga:&nbsp; Reduced shortblock extra 
+    bit allocation formulas by 10% since new huffman coding is at least 10% more 
+    efficient.</font></li>
+</ul>
+<h3> LAME 3.55beta&nbsp; November 11 1999</h3>
+<ul>
+  <li> Albert Faber:&nbsp; updated BladeEnc.dll</li>
+  <li> Mark Taylor: Simple lowpass filter added to linear downsampling routine.</li>
+  <li> Nils Faerber: updated man page.</li>
+  <li> Mark Taylor: All floating point variables are delcared FLOAT or&nbsp; FLOAT8.&nbsp; 
+    Change the definition of FLOAT8 in machine.h to run at 32bit preceision.</li>
+  <li> Mark Taylor: Bug (introduced in 3.54beta) in stereo-&gt;mono downsampling 
+    fixed.</li>
+</ul>
+<h3> LAME 3.54beta&nbsp; November 8 1999</h3>
+<ul>
+  <li> Mark Taylor: Encoder delay is now 48 samples.&nbsp; Can be adjusted to 
+    1160 to sync with FhG (see ENCDELAY in encoder.h)&nbsp; This is kind of amazing, 
+    since if Takehiro put his MDCT/filterbank routine in a decoder, we could have 
+    a total&nbsp; delay of only 96 samples.</li>
+  <li> <font color="#ff0000">Mark Taylor: More inconstancies found and fixed in 
+    MPEG2 tables.</font></li>
+  <li> Mark Taylor: Resampling from an MP3 input file now works.&nbsp; But we 
+    still dont have a lowpass filter so dont expect good results.</li>
+</ul>
+<h3> LAME 3.53beta&nbsp; November 8 1999</h3>
+<ul>
+  <li> <font color="#3366ff">Takehiro Tominaga:&nbsp; Fixed MPEG2 problem in new 
+    MDCT routines.&nbsp; Takehiro's combined filterbank/MDCT routine is now the 
+    default.&nbsp; Removes all buffering from psymodel.c and the filterbanks/MDCT 
+    routines.</font></li>
+</ul>
+<h3> LAME 3.52beta&nbsp; November 8 1999</h3>
+<ul>
+  <li> By permission of copyright holders of all GPL code in LAME,&nbsp; all GPL 
+    code is now released under a modified version of the LGPL (see the README 
+    file)</li>
+  <li> By popular demand, all C++ comments changed to C style comments</li>
+  <li> Mark Taylor: Linear resampling now works.&nbsp; Use --resample to set an 
+    output samplerate different from the input samplerate.&nbsp; (doesn't seem 
+    to work with mp3 input files, and there is no lowpass filter, so dont expect 
+    good results just yet)</li>
+  <li> <font color="#3366ff">Takehiro Tominaga:&nbsp; Faster Huffman encoding 
+    routines</font></li>
+</ul>
+<font color="#3366ff">The following changes are disabled because of MPEG2 problems.&nbsp; 
+But to try them, set MDCTDELAY=48 in encoder.h, instead of MDCTDELAY=528.:</font> 
+<ul>
+  <li> <font color="#3366ff">Takehiro Tominaga:&nbsp; New MDCT routines with shorter 
+    delay (48 samples instead of 528) and even faster than the old routines.</font></li>
+  <li> <font color="#3366ff">Takehiro Tominaga:&nbsp; Removed extra buffering 
+    in psymodel.c</font></li>
+</ul>
+<h3> LAME 3.51&nbsp; November 7 1999</h3>
+<ul>
+  <li> Takehiro Tominaga: Bug in quantize.c absolute threshold of hearing calculation 
+    for non-44.1 kHz input files.</li>
+</ul>
+<h3> LAME 3.50&nbsp; November 1 1999</h3>
+<ul>
+  <li> LAME 3.37beta becomes official LAME 3.50 release</li>
+</ul>
+<h3> LAME 3.37beta&nbsp; November 1 1999</h3>
+<ul>
+  <li> <font color="#ff0000">Lionel Bonnet:&nbsp; Found severe bug in MPEG2 Short 
+    block SNR.</font></li>
+  <li> Sergey Sapelin:&nbsp; VBR Toc improvement.</li>
+  <li> Sergey Dubov: fskip() routine</li>
+  <li> Conrad Sanderson: replacement for filterbank.c.&nbsp;&nbsp; Not much faster 
+    but amazingly simpler.</li>
+</ul>
+<h3> LAME 3.36beta&nbsp; October 25 1999</h3>
+<ul>
+  <li> Albert Faber:&nbsp; more MSVC and BladeDLL updates</li>
+  <li> Kimmo Mustonen:&nbsp; Much code cleanup and Amiga updates</li>
+  <li> Anton Oleynikov: Borland C updates</li>
+  <li> Mark Taylor: More stdin fixes:&nbsp; For some reason, forward fseek()'s 
+    would fail when used on pipes even though it is okay with redirection from 
+    "&lt;". So I changed all the forward fseek()'s to use fread().&nbsp; This 
+    should improve stdin support for wav/aiff files.&nbsp; If you know the input 
+    file is raw pcm, you can still use the '-r' option to avoid *all* seeking 
+    of any kind.</li>
+  <br>
+  &nbsp; 
+</ul>
+<h3> LAME 3.35beta&nbsp; October 21 1999</h3>
+<ul>
+  <li> <font color="#ff0000">Leonid Kulakov:&nbsp; Serious bug in MPEG2 scalefactor 
+    band tables fixed.</font></li>
+  <li> Portability patches from:&nbsp; Anton Oleynikov, Sigbj&oslash;rn Skj&aelig;ret, 
+    Mathew Hendry, Richard Gorton</li>
+  <li> Alfred Weyers: compiler options, updated timestatus.</li>
+  <li> Albert Faber:&nbsp; BladeDll and other updates (new machine.h).</li>
+  <li> Monty:&nbsp; updated Makefile to fix gcc inline math bug.</li>
+  <br>
+  &nbsp; 
+</ul>
+<h3> LAME 3.34beta&nbsp; October 12 1999</h3>
+<ul>
+  <li> <font color="#ff0000">Mark Taylor: Bug fixed:&nbsp; minimum bitrate in 
+    VBR mode could be ignored for a few frames.</font></li>
+  <li> <font color="#ff0000">Mark Taylor: New (minor) VBR tunings.</font></li>
+  <li> Tim Ruddick: New wav/aiff header parsing routines.&nbsp; Better parsing 
+    and fewer fseek()'s.</li>
+  <li> Anton Oleynikov:&nbsp; patches to work with Borland C</li>
+  <li> <font color="#ff0000">Gabriel Bouvigne:&nbsp; Experimental voice option 
+    enabled with --voice</font></li>
+</ul>
+<h3> LAME 3.33beta&nbsp; October 11 1999</h3>
+<ul>
+  <li> <font color="#ff0000">Robert Hegemann: RH VBR mode now the default and 
+    only VBR mode.&nbsp; The new code will always quantize to 0 distortion and 
+    the quality is increased by reducing the masking from the psy-model.&nbsp; 
+    -X0 is still the default for now.</font></li>
+  <li> <font color="#ff0000">Robert Hegemann: new -X5 mode</font></li>
+  <li> Mathew Hendry: New timing code, removes the need for HAVETIMES</li>
+  <li> <font color="#3366ff">Mathew Hendry:&nbsp; assembler quantize_xrpow for 
+    Windows</font></li>
+  <li> Iwasa Kazmi:&nbsp; stdin/stdout patch for Windows</li>
+  <li> Mark Taylor: New option: "--athonly" will ignore the psy-model output and 
+    use only the absolute threshold of hearing for the masking.</li>
+  <br>
+  &nbsp; 
+</ul>
+<h3> LAME 3.32beta&nbsp; October 8 1999</h3>
+<ul>
+  <li> <font color="#3366ff">Takehiro Tominaga:&nbsp; faster long block spreading 
+    function convolution for non 44.1 kHz sampling frequencies, and faster short 
+    block spreading function convolution for all sampling frequencies.</font></li>
+  <li> <font color="#ff0000">Takehiro Tominaga:&nbsp; Completly rewritten huffman 
+    table selection and count_bits().&nbsp; More efficient table selection results 
+    in many more bits per frame.</font></li>
+  <li> <font color="#ff0000">Takehiro Tominaga:&nbsp; More efficient scalefac 
+    compress setting.</font></li>
+  <li> <font color="#3366ff">Mike Cheng: new calc_noise2()</font></li>
+  <li> Alfred Weyers: patch for timestatus() seconds rollover</li>
+  <br>
+  &nbsp; 
+</ul>
+<h3> LAME 3.31beta&nbsp; September 28 1999</h3>
+<ul>
+  <li> Albert Faber:&nbsp; updated his BladeDLL code.&nbsp; This allows LAME to 
+    be compiled into a BladeEnc compatiable .dll.</li>
+  <li> <font color="#3366ff">Mike Cheng: faster l3psycho_ener() routine.</font></li>
+  <li> Sigbj&oslash;rn Skj&aelig;ret: more code cleanup.</li>
+</ul>
+<h3> LAME&nbsp; 3.30beta&nbsp; September 27 1999</h3>
+<ul>
+  <li> Conrad Sanderson:&nbsp; ID3 tag code added (type 'lame' for instructions)</li>
+  <li> new mdct.c from Mike Cheng (no faster, but much cleaner code)</li>
+  <li> Mathew Hendry: Microsoft nmake makefile and a couple other changes for 
+    MSVC</li>
+  <li> More modulization work:&nbsp; One input sound file interface handles mp3's, 
+    uncompressed audio, with or without LIBSNDFILE.&nbsp; Fixes (hopefully) a 
+    bunch of file I/O bugs introduced in 3.29 (Mark Taylor)</li>
+  <li> LAME will now print valid samplerate/bitrate combinations (Mark Taylor)</li>
+  <li> stdin/stdout fix for OS/2 (Paul Hartman)</li>
+  <li> For mp3 input files, totalframes estimated based on filesize and first 
+    frame bitrate. (Mark Taylor)</li>
+  <li> Updated all functions with new style prototypes.&nbsp; (Sigbj&oslash;rn 
+    Skj&aelig;ret)</li>
+  <br>
+  &nbsp; 
+</ul>
+<h3> LAME 3.29beta&nbsp; September 21 1999</h3>
+<ul>
+  <li> <font color="#ff0000">Bug in bigv_bitcount fixed.&nbsp; Loop.c was overestimating 
+    the number of bits needed, resulting in wasted bits every frame.&nbsp; (Leonid 
+    A. Kulakov)</font></li>
+  <li> <font color="#ff0000">Bug in *_choose_table() fixed&nbsp;&nbsp; These routines 
+    would not sellect the optimal Huffman table in some cases.&nbsp;&nbsp; (Leonid 
+    A. Kulakov)</font></li>
+  <li> <font color="#ff0000">Tuning of ATH normalization (macik)</font></li>
+  <li> Removed unused variables and fixed function prototypes (Sigbj&oslash;rn 
+    Skj&aelig;ret)</li>
+  <li> Sami Farin sent a&nbsp; .wav&nbsp; file that&nbsp; LAME built in support 
+    choked on.&nbsp;&nbsp; I added a slightly more sophisticated wav header parsing 
+    to handle this, but if you have trouble, use libsndfile.</li>
+  <li> Resampling hooks and options added.&nbsp; Buffering and resampling routines 
+    need to be written.</li>
+  <li> LAME will now take an mp3 file as input.&nbsp; When resampling code is 
+    working, LAME will be able to (for example) convert a high bitrate stereo 
+    mp3 to a low bitrate mono mp3 for streaming.</li>
+</ul>
+<h3> LAME 3.28beta&nbsp; September 15 1999</h3>
+<ul>
+  <li> <font color="#ff0000">Serious bug fixed in high frequency MDCT coefficients.&nbsp; 
+    Huffman coding was reversing the order of the count1 block quadruples.&nbsp;&nbsp; 
+    (Leonid A. Kulakov)</font></li>
+  <li> nint() problems under Tru64 unix fixed and preprocessor variable HAVE_NINT 
+    removed.&nbsp; (Bob Bell)</li>
+  <li> Compiler warning fixes and code cleanup&nbsp;&nbsp; (Sigbj&oslash;rn Skj&aelig;ret, 
+    Lionel Bonnet)</li>
+  <li> USAGE file now includes suggestions for downsampling.&nbsp; For low bitrate 
+    encodings, proper downsampling can give dramatically better results.&nbsp; 
+    (John Hayward-Warburton)</li>
+</ul>
+<h3> LAME 3.27beta&nbsp; September 12 1999</h3>
+<ul>
+  <li> Several bugs in encode.c and l3bitstream.c fixed by Lionel Bonnet.</li>
+  <li> Bugs in new VBR (#define RH) formula for mono input file and mid/side encoding 
+    fixed.</li>
+</ul>
+<h3> LAME 3.26beta&nbsp; September 10 1999</h3>
+<ul>
+  <li> The "-m m" option (mono .mp3 file) will automatically mix left and right 
+    channels if the input file is stereo.&nbsp; (Alfred Weyers)</li>
+  <li> <font color="#ff0000">New quant_compare algorithm (method for deciding 
+    which of two quantizations is better) enabled with -X4 (Greg Maxwell)</font></li>
+  <li> <font color="#ff0000">New mid/side VBR bit allocation formula.&nbsp; Mid 
+    channel bits are set by the quality requirements, and then the side channel 
+    uses a reduced number of bits (in a proportion coming from the fixed bitrate 
+    code).&nbsp; This might not be optimal, but it should be pretty good and no 
+    one knows what the optimal solution should be.&nbsp; (Greg Maxwell)</font></li>
+  <li> <font color="#ff0000">New VBR (#define RH) tunings based on detailed listening 
+    tests by Macik and Greg Maxwell.</font></li>
+  <li> Sigbj&oslash;rn Skj&aelig;ret fixed several compiler warnings (which turned 
+    out to be potential bugs)</li>
+  <li> Takehiro Tominaga fixed a low bitrate bug in reduce_side()</li>
+  <li> Alfred Weyers fixed some buffer overflows.</li>
+  <li> <font color="#ff0000">New ATH (absolute threshold of hearing) formula replaces 
+    buggy ISO code, and adds&nbsp; analog silence treatment&nbsp; (removal of 
+    coefficients below below ATH).&nbsp;&nbsp; These are turned on by default 
+    but have not been fully tested.&nbsp; (Robert Hegemann)</font></li>
+  <li> <font color="#ff0000">Bug in short block spreading function fixed.&nbsp; 
+    (Robert Hegemann)</font></li>
+</ul>
+<h3> LAME 3.25beta&nbsp; August 22 1999</h3>
+<ul>
+  <li> Sigbj&oslash;rn Skj&aelig;ret fixed a zero byte malloc call.&nbsp; This 
+    bug&nbsp; was introduced in 3.24 and causes problems on non Linux systems.</li>
+  <li> Bit allocation routines would sometimes allocate more than 4095 bits to 
+    one channel of one granule.&nbsp; A couple of people reported problems that 
+    might be caused by this, especially at higher bitrates.</li>
+  <li> Nils Faerber updated the man page and fixed many of the compiler warnings.</li>
+  <br>
+  &nbsp; 
+</ul>
+<h3> LAME 3.24beta&nbsp;&nbsp; August 15 1999</h3>
+<ul>
+  <li> This release contains the following new code (for developers) which is 
+    disabled by default:</li>
+  <li> Robert Hegemann:&nbsp; Completely overhauled VBR code.&nbsp; Now computes 
+    exact number of bits required for the given qualty and then quantized with 
+    the appropriate bitrate.</li>
+  <li> Several new quantization quality measures.</li>
+</ul>
+<h3> LAME 3.23beta&nbsp; August 8 1999</h3>
+<ul>
+  <li> Very nice continuously updated VBR histogram display from Iwasa Kazmi.&nbsp; 
+    (disabled with --nohist).</li>
+  <li> More modulerization work.&nbsp; The encoding engine can now be compiled 
+    into libmp3lame, but the interface is awkward.</li>
+  <li> <font color="#ff0000">Bug fixed in FFT Hann window formula (Leonid A. Kulakov).</font></li>
+  <li> New LAME logo on the download page.&nbsp; Created by Chris Michalisles.</li>
+  <li> <font color="#ff0000">Several VBR algorithm improvements from Robert Hegemann.&nbsp; 
+    New quantization noise metrics and VBR quality measure takes into account 
+    mid/side encoding.&nbsp; Should produce smaller files with the same quality, 
+    especially when using jstereo.</font></li>
+</ul>
+<h3> LAME 3.22beta&nbsp; July 27 1999</h3>
+<ul>
+  <li> Downsampling (stereo to mono) bug with MPEG2 fixed.&nbsp; (Mike Oliphant)</li>
+  <li> Downsampling now merges L &amp; R channels - before it only took the L 
+    channel.</li>
+  <li> More modularization and code cleanup from Albert Faber and myself.</li>
+  <li> Input filesize limit removed for raw pcm input files.&nbsp; For other file 
+    types, LAME will still only read the first 2^32 samples, (27 hours of playing 
+    time at 44.1 kHz).</li>
+  <br>
+  &nbsp; 
+</ul>
+<h3> LAME 3.21beta&nbsp; July 26 1999</h3>
+<ul>
+  <li> <font color="#ff0000">Correct Mid/Side masking thresholds for JSTEREO mode!&nbsp; 
+    This is enabled with -h.&nbsp; It&nbsp; makes LAME about 20% slower since 
+    it computes psycho-acoustics for L,R Mid and Side channels.</font></li>
+  <li> <font color="#ff0000">"Analog silence" threshold added.&nbsp; Keeps VBR 
+    from upping the bitrate during very quite passages.&nbsp; (Robert.Hegemann)</font></li>
+  <li> <font color="#ff0000">New VBR quality setting from Robert Hegemann.&nbsp; 
+    It is based on the idea that distortion at lower bit rates sounds worse than 
+    at higher bitrates, and so the allowed distortion (VBR quality setting) is 
+    proportional to the bitrate.&nbsp; Because of this, default minimum bitrate 
+    is now 32kbs.</font></li>
+  <li> <font color="#ff0000">Expermental subblock gain code enabled with -Z.</font></li>
+  <li> New "-r" option for raw pcm input files.&nbsp; With -r, LAME will not do 
+    any fseek()'s or look for wav and aiff headers on the input file.</li>
+  <li> Bug fixes in mp3x (frame analyzer) for viewing frames near end of the file.</li>
+  <li> Bug fixed to allow setting the sampling rate of raw pcm input files.</li>
+</ul>
+<h3> LAME 3.20beta&nbsp; July 19 1999</h3>
+<ul>
+  <li> Bug in get_audio.c fixed.&nbsp; Libsndfile wrappers would not compile (Miguel 
+    Revilla&nbsp; Rodriguez)</li>
+  <li> Nils Faerber found some unitialized variables and some wierd extranous 
+    computations in filter_subband, now fixed.&nbsp; This was causing seg faults 
+    on some machines.</li>
+  <br>
+  &nbsp; 
+</ul>
+<h3> LAME 3.19beta&nbsp; July 18 1999</h3>
+<ul>
+  <li> <font color="#ff0000">Oops!&nbsp; Robert Hegemann immediatly found a bug 
+    in the new&nbsp; (old -Z option) quantization code.&nbsp; calc_noise1 was 
+    not returning tot_noise, so non ms-stereo frames were buggy.</font></li>
+  <br>
+  &nbsp; 
+</ul>
+<h3> LAME 3.18beta&nbsp; July 17 1999</h3>
+<ul>
+  <li> <font color="#ff0000">Many psycho-acoustic bug fixes.&nbsp; Dan Nelson 
+    discovered a bug in MPEG2: For short blocks, the code assumes 42 partition 
+    bands.&nbsp; MPEG1 sometimes has less, MPEG2 can have more.&nbsp; In MPEG1, 
+    this bug would not have effected the output if your compiler initializes static 
+    variables to 0 on creation.&nbsp; In MPEG2 it leads to array out-of-bounds 
+    access errors. Finally, there was a related bug in MPEG1/MPEG2, short &amp; 
+    long blocks where the energy above 16 kHz was all added to partition band 
+    0. (the lowest frequeny partition band!)</font></li>
+  <li> <font color="#ff0000">The -Z option (Gabriel Bouvigne's idea of using total 
+    quantization noise to choose between two quantizations with the same value 
+    of "over") is now the default.&nbsp; I believe this helps remove the trilling 
+    sound in Jan's testsignal4.wav.&nbsp; The quality of testsignal2.wav and testsignal4.wav 
+    are now better than Xing and getting closer to FhG.</font></li>
+  <li> Bug fixes in frame &amp; sample count for downsampling mode. (ben "jacobs")</li>
+  <li> Patches to improve modulization.&nbsp; (ben "jacobs")</li>
+</ul>
+<h3> LAME 3.17beta&nbsp; July 11 1999</h3>
+<ul>
+  <li> substantial code cleanup towards goal of making LAME more modular.</li>
+</ul>
+<h3> LAME 3.16beta&nbsp; July 11 1999</h3>
+<ul>
+  <li> <font color="#ff0000">New tunings of window switching, and better bit allocation 
+    based on pe.&nbsp; (Jan Rafaj.&nbsp; improves both testsignal2.wav and testsignal4.wav).</font></li>
+  <li> <font color="#ff0000">Bug in mid/side quantization when side channel was 
+    zero fixed.&nbsp; (Albert Faber)</font></li>
+  <li> Removed some extranous computations in l3psy.c (Robert Hegemann)</li>
+  <li> More detailed timing status info, including hours display. (Sakari Ailus) 
+    and percentage indicator (Conrad Sanderson).</li>
+  <li> <font color="#3366ff">Window_subband and calc_noise1,calc_noise2 speedups.&nbsp; 
+    Quantize_xrpow speedup should be significant on non GNU/intel systems. (Mike 
+    Cheng)</font></li>
+  <li> <font color="#3366ff">Better initial guess for VBR bitrate.&nbsp; Should 
+    speed up VBR encoding.&nbsp; (Gabriel Bouvigne)</font></li>
+  <li> More advanced .wav header parsing.&nbsp; fixes bugs involving click in 
+    first frame. (Robert.Hegemann)</li>
+  <li> Correct filesize and total frame computation when using LIBSNDFILE (ben 
+    "jacobs")</li>
+  <li> Click in last frame (buffering problem) when using libsndfile fixed.</li>
+  <li> Audio I/O code overhauled.&nbsp; There is now a uniform audio i/o interface 
+    to libsndfile or the LAME built in wav/aiff routines.&nbsp; All audio i/o 
+    code localized to get_audio.c.</li>
+  <br>
+  &nbsp; 
+</ul>
+<h3> LAME 3.15beta</h3>
+<ul>
+  <li> times()/clock() problem fixed for non-unix OS.&nbsp; (Ben "Jacobs")</li>
+  <li> Fixed uninitialized pe[] when using fast mode.&nbsp; (Ben "Jacobs")</li>
+</ul>
+<h3> LAME 3.13&nbsp; June 24 1999</h3>
+<ul>
+  <li> Patches for BeOS from Gertjan van Ratingen.</li>
+  <li> Makefile info for OS/2 Warp 4.0&nbsp; (from dink.org).</li>
+  <li> Status display now based on wall clock time, not cpu time.</li>
+  <li> mem_alloc no longer allocates twice as much memory as needed (Jan Peman).</li>
+</ul>
+<h3> 3.12pre9</h3>
+<ul>
+  <li> Updated BLADEDLL code to handle recent changes (Albert Faber).</li>
+  <li> Bug fixed in parsing options when not using GTK (Albert Faber).</li>
+  <li> <font color="#ff0000">MPEG2 Layer III psycho acoustics now working.</font></li>
+  <li> <font color="#3366ff">Improved huffman encoding Chris Matrakidis. (10% 
+    faster).&nbsp; I dont know how he finds these improvements!&nbsp; LAME with 
+    full quality now encodes faster than real time on my PII 266.</font></li>
+  <li> Fixed time display when encoding takes more than 60 minutes.</li>
+</ul>
+<h3> 3.12pre8</h3>
+<ul>
+  <li> <font color="#ff0000">New <a href="gpsycho/ms_stereo.html">mid/side stereo</a> 
+    criterion.&nbsp; LAME will use mid/side stereo only when the difference between 
+    L &amp; R masking thresholds (averaged over all scalefactors) is less then 
+    5db.&nbsp; In several test samples it does a very good job mimicking the FhG 
+    encoder.</font></li>
+  <li> <font color="#ff0000">Bug in mid/side stereo fixed:&nbsp; independent variation 
+    of mid &amp; side channel scalefactors disabled.&nbsp; Because of the way 
+    outer_loop is currently coded, when encoding mid/side coefficietns using left/right 
+    thresholds, you have to vary the scalefactors simultaneously.</font></li>
+  <li> <font color="#ff0000">Bug in side/mid energy ratio calculation fixed. (Thanks 
+    to Robert Hegemann)</font></li>
+  <li> Default mode is stereo (not jstereo) if bitrate is chosen as 192kbs or 
+    higher.&nbsp; Tero Auvinen first pointed out that FhG seems to think at 160kbs, 
+    their encoder is so good it doesn't need jstereo tricks. Since LAME is not 
+    as good as FhG, I am going to claim that 192kbs LAME is so good it doens't 
+    need jstereo tricks, and thus it is disabled by default.</li>
+  <li> WAV header parsing for big-endian machines, and automatic detection of 
+    big-endian machines.&nbsp; (Thanks to&nbsp; Sigbj&oslash;rn Skj&aelig;ret).</li>
+  <li> added 56 sample delay to sync LAME with FhG.</li>
+  <li> MP3x (frame analyzer) can now handle MPEG2 streams.</li>
+</ul>
+<h3> 3.12pre7</h3>
+<ul>
+  <li> MPEG2 layer III now working!&nbsp; lower bit rates (down to 8kbs) and 3 
+    more sampling frequencies:&nbsp; 16000, 22050, 24000Hz. Quality is poor - 
+    the psy-model does not yet work with these sampling frequencies.</li>
+  <li> Fixed "ERROR: outer_loop(): huff_bits &lt; 0." bug when using VBR.</li>
+  <li> bash and sh scripts to run LAME on multiple files now included.&nbsp; (from 
+    Robert Hegemann and Gerhard Wesp respectively)</li>
+  <li> bug fix in encoding times for longer files from&nbsp; (Alvaro Martinez 
+    Echevarria)</li>
+  <li> yet another segfault in the frame analyzer fixed.</li>
+  <li> ISO psy-model/bit allocation routines removed.&nbsp; This allowed makeframe() 
+    to be made much simpler, and most of the complicated buffering is now gone. 
+    Eventually I would like the encoding engine to be a stand alone library.</li>
+</ul>
+<h3> 3.12pre6</h3>
+<ul>
+  <li> <font color="#ff0000">Better VBR tuning.&nbsp; Find minimum bitrate with 
+    distortion less than the allows maximum.&nbsp; A minimum bit rate is imposed 
+    on frames with short blocks (where the measured distortion can not be trusted).&nbsp;&nbsp; 
+    A minimum frame bitrate can be specified with -b, default=64kbs.</font></li>
+  <li> <a href="http://www.zip.com.au/%7Eerikd/libsndfile">LIBSNDFILE</a> support.&nbsp; 
+    With libsndfile, LAME can encode almost all sound formats.&nbsp; Albert Faber 
+    did the work for this, including getting libsndfile running under win32.</li>
+  <li> CRC checksum now working!&nbsp;&nbsp; (Thanks to Johannes Overmann )</li>
+  <li> frame analyzer will now work with mono .mp3 files</li>
+  <li> <font color="#3366ff">more code tweeks from Jan Peman.</font></li>
+  <li> <font color="#3366ff">Compaq-Alpha(Linux) fixes and speedups from Nils 
+    Faerber.</font></li>
+  <li> <font color="#3366ff">Faster bin_search_StepSize from Juha Laukala.</font></li>
+  <li> <font color="#3366ff">Faster quantize() from Mike Cheng</font></li>
+  <li> <font color="#3366ff">Faster quantize_xrpow() from Chris Matrakidis.&nbsp; 
+    xrpow_flag removed since this option is now on by default.</font></li>
+  <li> Fixed .wav header parsing from Nils Faerber.</li>
+  <li> Xing VBR frame info header code from Albert Faber.&nbsp;&nbsp; "Xing" and 
+    "LAME 3.12" embedded in first frame.</li>
+  <li> <font color="#ff0000">Bug in VBR bit allocation based on "over" value fixed.</font></li>
+</ul>
+<h3> LAME 3.11&nbsp; June 3 1999</h3>
+<ul>
+  <li> Almost all warnings (-Wall) now fixed!&nbsp; (Thanks to Jan Peman)</li>
+  <li> More coding improvements from Gabriel Bouvigne and Warren Toomey.</li>
+  <li> <font color="#ff0000">VBR&nbsp; (variable bit rate).&nbsp;&nbsp; Increases 
+    bit rate for short blocks and for frames where the number of bands containing 
+    audible distortion is greater than a given value.&nbsp; Much tuning needs 
+    to be done.</font></li>
+  <li> Patch to remove all atan() calls from James Droppo.</li>
+
+</ul>
+<h3> LAME 3.10 May 30 1999</h3>
+<ul>
+  <li> <font color="#3366ff">Fast mode (-f)&nbsp; disables psycho-acoustic model 
+    for real time encoding on older machines.&nbsp; Thanks to Lauri Ahonen who 
+    first sent a patch for this.</font></li>
+  <li> <font color="#ff0000">New bit reservoir usage scheme to accommodate the 
+    new pre-echo detection formulas.</font></li>
+  <li> <font color="#ff0000">Tuning of AWS and ENER_AWS pre-echo formulas by Gabriel 
+    Bouvigne and myself.&nbsp; They work great!&nbsp; now on by default.</font></li>
+  <li> In jstereo, force blocktypes for left &amp; right channels to be identical.&nbsp; 
+    FhG seems to do this.&nbsp; It can be disabled with "-d".</li>
+  <li> Patches to compile MP3x under win32 (Thanks to Albert Faber).</li>
+  <li> <font color="#3366ff">bin_serach_stepsize limited to a quantizationStepSize 
+    of&nbsp; -210 through 45.</font></li>
+  <li> <font color="#ff0000">outer_loop()&nbsp; will now vary Mid &amp; Side scalefactors 
+    independently.&nbsp; Can lead to better quantizations, but it is slower (twice 
+    as many quantizations to look at).&nbsp; Running with "-m f" does not need 
+    this and will run at the old speed</font></li>
+  <li> <font color="#ff0000">Bug in inner_loop would allow quantizations larger 
+    than allowed.&nbsp; (introduced in lame3.04, now fixed.)</font></li>
+  <li> Updated HTML documentation from Gabriel Bouvigne.</li>
+  <li> Unix&nbsp; man page from William Schelter.</li>
+  <li> <font color="#ff0000">numlines[] bug fixed.&nbsp; (Thanks to Rafael Luebbert, 
+    MPecker author).</font></li>
+  <li> <font color="#3366ff">Quantization speed improvements from Chirs Matrakidis.</font></li>
+  <li> <font color="#ff0000">When comparing quantizations with the same number 
+    of bands with audible distortion, use the one with the largest scalefactors, 
+    not the first one outer_loop happened to find.</font></li>
+  <li> Improved defination of best quantization when using -f (fast mode).</li>
+  <li> subblock code now working.&nbsp; But no algorithm to choose subblock gains 
+    yet.</li>
+  <li> Linux now segfaults on floating point exceptions.&nbsp; Should prevent 
+    me from releasing binaries that crash on other operating systems.</li>
+</ul>
+<h3> LAME 3.04 May 22 1999</h3>
+<ul>
+  <li>Preliminary documentation from Gabriel Bouvigne.</li>
+  <li> <font color="#3366ff">I wouldn't have thought it was possible, but now 
+    there are even more speed improvements from Chris Matrakidis!&nbsp; Removed 
+    one FFT when using joint stereo, and many improvements in loop.c.</font></li>
+  <li> "Fake" ms_stereo mode renamed "Force" ms_stereo since it forces mid/side 
+    stereo on all frames.&nbsp; For some music this is said to be a problem, but 
+    for most music mode is probably better than the default jstereo because it 
+    uses specialized mid/side channel masking thresholds.</li>
+  <li> Small bugs in Force ms_stereo mode fixed.</li>
+  <li> Compaq Alpha fixes from Nathan Slingerland.</li>
+  <li> <font color="#ff0000">Some new experimental pre-echo detection formulas 
+    in l3psy.c (#ifdef AWS and #ifdef ENER_AWS, both off by default.&nbsp; Thanks 
+    to Gabriel Bouvigne and Andre Osterhues)</font></li>
+  <li> Several bugs in the syncing of data displayed by mp3x (the frame analyzer) 
+    were fixed.</li>
+  <li> highq (-h) option added.&nbsp; This turns on things (just one so far) that 
+    should sound better but slow down LAME.</li>
+</ul>
+<h3>LAME 3.03 May 18 1999 </h3>
+<ul>
+  <li> <font color="#3366ff">Faster (20%) &amp; cleaner FFT (Thanks to Chris Matrakidis&nbsp; 
+    http://www.geocities.com/ResearchTriangle/8869/fft_summary.html)</font></li>
+  <li> mods so it works with VC++ (Thanks to Gabriel Bouvigne, www.mp3tech.org)</li>
+  <li> MP3s marked "original" by default&nbsp; (Thanks to Gabriel Bouvigne, www.mp3tech.org)</li>
+  <li> Can now be compiled into a BladeEnc compatible .DLL&nbsp;&nbsp; (Thanks 
+    to&nbsp; Albert Faber, CDex author)</li>
+  <li> Patches for "silent mode" and stdin/stdout&nbsp; (Thanks to Lars Magne 
+    Ingebrigtsen)</li>
+  <li> <font color="#ff0000">Fixed rare bug: if a long_block is sandwiched between 
+    two short_blocks, it must be changed to a short_block, but the short_block 
+    ratios have not been computed in l3psy.c.&nbsp; Now always compute short_block 
+    ratios just in case.</font></li>
+  <li> <font color="#ff0000">Fixed bug with initial quantize step size when many 
+    coefficients are zero.&nbsp; (Thanks to Martin Weghofer).</font></li>
+  <li> Bug fixed in MP3x display of audible distortion.</li>
+  <li> improved status display (Thanks to Lauri Ahonen).</li>
+</ul>
+<h3> LAME 3.02 May 12 1999</h3>
+<ul>
+  <li> <font color="#ff0000">encoder could use ms_stereo even if channel 0 and 
+    1 block types were different.&nbsp; (Thanks to Jan Rafaj)</font></li>
+  <li> <font color="#ff0000">added -k option to disable the 16 kHz cutoff at 128kbs.&nbsp; 
+    This cutoff is never used at higher bitrates. (Thanks to Jan Rafaj)</font></li>
+  <li> <font color="#ff0000">modified pe bit allocation formula to make sense 
+    at bit rates other than 128kbs.</font></li>
+  <li> fixed l3_xmin initialization problem which showed up under FreeBSD.&nbsp; 
+    (Thanks to Warren Toomey)</li>
+</ul>
+<h3><b>LAME 3.01 May 11 1999</b> </h3>
+<ul>
+  <li> max_name_size increased to 300&nbsp; (Thanks to Mike Oliphant)</li>
+  <li> patch to allow seeks on input file (Thanks to Scott Manley)</li>
+  <li> fixes for mono modes (Thanks to everyone who pointed this out)</li>
+  <li> overflow in calc_noise2 fixed</li>
+  <li> bit reservoir overflow when encoding lots of frames with all zeros&nbsp; 
+    (Thanks to Jani Frilander)</li>
+</ul>
+<h3><br>
+  <b>LAME 3.0 May 10 1999</b> </h3>
+<ul>
+  <li><font color="#ff0000">added GPSYCHO (developed by Mark Taylor)</font></li>
+  <li> <font color="#000000">added MP3x (developed by Mark Taylor)</font></li>
+  <li> LAME now maintained by Mark Taylor</li>
+</ul>
+<b>November 8 1998</b> 
+<ul>
+  <li> Version 2.1f released</li>
+  <li> 50% faster filter_subband() routine in encode.c contributed by James Droppo</li>
+</ul>
+<b>November 2 1998</b> 
+<ul>
+  <li> Version 2.1e released.</li>
+  <li> New command line switch <b>-a</b> auto-resamples a stereo input file to 
+    mono.</li>
+  <li> New command line switch <b>-r</b> resamples from 44.1 kHz to 32 kHz [this 
+    switch doesn't work really well. Very tinny sounding output files. Has to 
+    do with the way I do the resampling probably]</li>
+  <li> Both of these were put into the ISO code in the encode.c file, and are 
+    simply different ways of filling the input buffers from a file.</li>
+</ul>
+<b>October 31 1998</b> 
+<ul>
+  <li> Version 2.1d released</li>
+  <li> Fixed memory alloc in musicin.c (for l3_sb_sample)</li>
+  <li> Added new command line switch (-x) to force swapping of byte order</li>
+  <li> Cleaned up memory routines in l3psy.c. All the mem_alloc() and free() routines 
+    where changed so that it was only done <i>once</i> and not every single time 
+    the routine was called.</li>
+  <li> Added a compile time switch -DTIMER that includes all timing info. It's 
+    a switch for the time being until some other people have tested on their system. 
+    Timing code has a tendency to do different things on different platforms.</li>
+</ul>
+<b>October 18 1998</b> 
+<ul>
+  <li> Version 2.1b released.</li>
+  <li> Fixed up bug: all PCM files were being read as WAV.</li>
+  <li> Played with the mem_alloc routine to fix crash under amigaos (just allocating 
+    twice as much memory as needed). Might see if we can totally do without this 
+    routine. Individual malloc()s where they are needed instead</li>
+  <li> Put Jan Peman's quality switch back in. This reduces quality via the '-q&nbsp;<int>' 
+    switch. Fun speedup which is mostly harmless if you're not concerned with 
+    quality.</int></li>
+  <li> Compiling with amiga-gcc works fine</li>
+</ul>
+<b>October 16 1998</b> 
+<ul>
+  <li> Version 2.1a released. User input/output has been cleaned up a bit. WAV 
+    file reading is there in a very rudimentary sense ie the program will recognize 
+    the header and skip it, but not read it. The WAV file is assumed to be 16bit 
+    stereo 44.1 kHz.</li>
+</ul>
+<b>October 6 1998</b> 
+<ul>
+  <li> Version 2.1 released with all tables now incorporated into the exe. Thanks 
+    to <b>Lars Magne Ingebrigtseni</b>(larsi@ifi.uio.no)</li>
+</ul>
+<b>October 4 1998</b>In response to some concerns about the quality of the encoder, 
+I have rebuilt the encoder from scratch and carefully compared output at all stages 
+with the output of the unmodified ISO encoder. <a
+ href="http://www.uq.net.au/%7Ezzmcheng/lame/download.html"> Version2.0</a> of 
+LAME is built from the ISO source code (dist10), and incorporates modifications 
+from myself and the 8hz effort. The output file from LAME v2.0 is <i>identical</i> 
+to the output of the ISO encoder for my test file.Since I do not have heaps of 
+time, I left the ISO AIFF file reader in the code, and did not incorporate a WAV 
+file reader.Added section on <a
+ href="http://www.uq.net.au/%7Ezzmcheng/lame/quality.html"> quality</a><b> October 
+1 1998</b> 
+<ul>
+  <li> Updated web page and released LAME v1.0</li>
+</ul>
+<b>Up to September 1998</b> 
+<ul>
+  Working on the 8hz source code... 
+  <ul>
+    <li> Patched the <a href="http://www.8hz.com/">8hz</a> source code</li>
+    <li> 45% faster than original source (on my freebsd p166).</li>
+    <ul>
+      <li> m1 - sped up the mdct.c and quantize() functions [MDCTD, MDCTD2, LOOPD]</li>
+      <li> m2 - sped up the filter_subband routine using <b>Stephane Tavenard</b> 
+        's work from musicin [FILTST]</li>
+      <li> m2 - minor cleanup of window_subband [WINDST2]</li>
+      <li> m2 - Cleaned up a few bits in l3psy.c. Replaced a sparse matrix multiply 
+        with a hand configured unrolling [PSYD]</li>
+      <li> m3 - (amiga only) Added in the asm FFT for m68k (based on sources from 
+        <b>Henryk Richter</b> and <b>Stephane Tavenard</b>)</li>
+      <li> m4 - raw pcm support back in</li>
+      <li> m5 - put in a byte-ordering switch for raw PCM reading (just in case)</li>
+      <li> m6 - reworked the whole fft.c file. fft now 10-15% faster.</li>
+      <li> m7 - totally new fft routine. exploits fact that this is a real-&gt;complex 
+        fft. About twice as fast as previous fastest fft (in m6). (C fft routine 
+        is faster than the asm one on an m68k!)</li>
+      <li> m8</li>
+      <ul>
+        <li> - Now encodes from stdin. Use '-' as the input filename. Thanks to 
+          <b>Brad Threatt</b></li>
+        <li> - Worked out that the 1024point FFT only ever uses the first 6 phi 
+          values, and the first 465 energy values. Saves a bunch of calculations.</li>
+        <li> - Added a speed-up/quality switch. Speed is increased but quality 
+          is decreased <i>slightly</i>. My ears are bad enough not to be able 
+          to notice the difference in quality at low settings :). Setting '-q 
+          1' improves speed by about 10%. '-q 100' improves speed by about 26%. 
+          Enoding of my test track goes from 111s (at default '-q 0') to 82s (at 
+          -q 100). Thanks to <b> Jan Peman</b> for this tip.</li>
+      </ul>
+      <li> m9 - fixed an error in l3psy.c. numlines[] is overwritten with incorrect 
+        data. Added a new variable numlines_s[] to fix this. Thanks again to <b>Jan 
+        Peman</b>.</li>
+      <li> m10 - Down to 106 seconds by selecting a few more compiler options. 
+        Also added a pow20() function in l3loop.c to speed up (ever so slightly) 
+        calls to pow(2.0, x)</li>
+      <li> m11</li>
+      <ul>
+        <li> No speedups. Just cleaned up some bits of the code.</li>
+        <li> Changed K&amp;R prototyping to 'normal' format. Thanks to <b>Steffan 
+          Haeuser</b> for his help here.</li>
+        <li> Changed some C++ style comments to normal C comments in huffman.c</li>
+        <li> Removed the #warning from psy_data.h (it was getting annoying!)</li>
+        <li> Removed reference in bitstream.c to malloc.h. Is there a system left 
+          where malloc.h hasn't been superceded by stdlib.h?</li>
+      </ul>
+      <li> In Progess:</li>
+      <ul>
+        <li> my PSYD hack for the spreading functions is only valid for 44.1 kHz 
+          - Should really put in a "if freq = 44.1 kHz" switch for it. Someone 
+          might want to extend the speedup for 48 and 32 kHz.</li>
+        <li> Putting in Jan Peman's quantanf_init speedup.</li>
+      </ul>
+    </ul>
+  </ul>
+</ul>
+</body>
+</html>
Index: extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/id3.html
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/id3.html	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/id3.html	(revision 18425)
@@ -0,0 +1,257 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+<HEAD>
+<TITLE>ID3 tags</TITLE>
+<META NAME="description" CONTENT="Command line switch reference">
+<META NAME="keywords" CONTENT="lame">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso_8859_1">
+<LINK REL="STYLESHEET" HREF="lame.css">
+</HEAD>
+<BODY TEXT=#000000
+        BGCOLOR=#F9FBFB LINK=#006666 VLINK=#4C4C4C
+        ALINK=#995500>
+<H1>ID3 tags</H1>
+<p>&nbsp;</p>
+<p>LAME is able to embed ID3 v1, v1.1 or v2 tags inside the encoded MP3 file. 
+  This allows to have some usefull information about the music track included 
+  inside the file. Those data can be read by most MP3 players.<br>
+  <br>
+  Lame will smartly choose wich tags to use. It will add ID3 v2 tags only if the 
+  input comments won't fint in v1 or v1.1 tags, ie if they are more than 30 characters. 
+  In this case, both v1 and v2 tags will be added, to ensure reading of tags by 
+  MP3 players wich are unable to read ID3 v2 tags.</p>
+<P> 
+<TABLE CELLPADDING=3 BORDER="1">
+  <TR VALIGN="TOP"> 
+    <TD ALIGN="LEFT" nowrap><b>ID3 comments switches</b></TD>
+    <TD ALIGN="LEFT" nowrap><b>parameters</b></TD>
+  </TR>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--tt "title"</kbd></td>
+    <td align="LEFT" nowrap>title of song</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--ta "artist"</kbd></td>
+    <td align="LEFT" nowrap>artist who did the song</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--tl "album"</kbd></td>
+    <td align="LEFT" nowrap>album where it came from</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--ty "year"</kbd></td>
+    <td align="LEFT" nowrap>year in which the song/album was made</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--tc "comment"</kbd></td>
+    <td align="LEFT" nowrap>additional info</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--tn "track"</kbd></td>
+    <td align="LEFT" nowrap>track number of the song on the CD (1 to 255, creates 
+      an ID3 v 1.1 tag)</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--tg "genre"</kbd></td>
+    <td align="LEFT" nowrap> genre of song (name or number)</td>
+  </tr>
+</table>
+<br>
+<br>
+<TABLE CELLPADDING=3 BORDER="1">
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><b>ID3 behaviour switches</b></td>
+    <td align="LEFT" nowrap>&nbsp; </td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--add-id3v2</kbd></td>
+    <td align="LEFT" nowrap> force addition of version 2 tag</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--id3v1-only</kbd></td>
+    <td align="LEFT" nowrap> add only a version 1 tag</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--id3v2-only</kbd></td>
+    <td align="LEFT" nowrap> add only a version 2 tag</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--space-id3v1</kbd></td>
+    <td align="LEFT" nowrap> pad version 1 tags with spaces instead of nulls</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--pad-id3v2</kbd></td>
+    <td align="LEFT" nowrap> pad version 2 tags with extra 128 bytes</td>
+  </tr>
+  <tr valign="TOP">
+    <td align="LEFT" nowrap><kbd>--ignore-tag-errors</kbd></td>
+    <td align="LEFT" nowrap> ignore errors in values passed for tags, use defaults in case an error occours</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd>--genre-list</kbd></td>
+    <td align="LEFT" nowrap> print alphabetically sorted ID3 genre list and exit</td>
+  </tr>
+</TABLE>
+<p><br>
+  The following genres are supported:<br>
+  <br>
+</p>
+<table width="80%" border="0">
+  <tr valign="top" align="left"> 
+    <td>00 - Blues<br>
+      01 - Classic Rock<br>
+      02 - Country<br>
+      03 - Dance<br>
+      04 - Disco<br>
+      05 - Funk<br>
+      06 - Grunge<br>
+      07 - Hip-Hop<br>
+      08 - Jazz<br>
+      09 - Metal<br>
+      10 - New Age<br>
+      11 - Oldies<br>
+      12 - Other<br>
+      13 - Pop<br>
+      14 - R&B<br>
+      15 - Rap<br>
+      16 - Reggae<br>
+      17 - Rock<br>
+      18 - Techno<br>
+      19 - Industrial<br>
+      20 - Alternative<br>
+      21 - Ska<br>
+      22 - Death Metal<br>
+      23 - Pranks<br>
+      24 - Soundtrack<br>
+      25 - Euro-Techno<br>
+      26 - Ambient<br>
+      27 - Trip-Hop<br>
+      28 - Vocal<br>
+      29 - Jazz+Funk<br>
+      30 - Fusion<br>
+      31 - Trance<br>
+      32 - Classical<br>
+      33 - Instrumental<br>
+      34 - Acid<br>
+      35 - House<br>
+      36 - Game<br>
+      37 - Sound Clip<br>
+      38 - Gospel<br>
+      39 - Noise<br>
+      40 - Alternative Rock<br>
+      41 - Bass<br>
+      43 - Punk<br>
+      44 - Space<br>
+      45 - Meditative<br>
+      46 - Instrumental Pop<br>
+      47 - Instrumental Rock<br>
+      48 - Ethnic<br>
+      49 - Gothic<br>
+      50 - Darkwave<br>
+      51 - Techno-Industrial<br>
+      52 - Electronic<br>
+      53 - Pop-Folk<br>
+      54 - Eurodance<br>
+      55 - Dream<br>
+      56 - Southern Rock<br>
+      57 - Comedy<br>
+      58 - Cult<br>
+      59 - Gangsta<br>
+      60 - Top 40<br>
+      61 - Christian Rap<br>
+      62 - Pop/Funk<br>
+      63 - Jungle<br>
+      64 - Native US<br>
+      65 - Cabaret<br>
+      66 - New Wave<br>
+      67 - Psychadelic<br>
+      68 - Rave<br>
+      69 - Showtunes<br>
+      70 - Trailer<br>
+      71 - Lo-Fi<br>
+      72 - Tribal<br>
+      73 - Acid Punk<br>
+      74 - Acid Jazz<br>
+      75 - Polka<br>
+      76 - Retro<br>
+      77 - Musical<br>
+      78 - Rock & Roll<br>
+      79 - Hard Rock<br>
+      80 - Folk<br>
+      81 - Folk-Rock<br>
+      82 - National Folk<br>
+      83 - Swing<br>
+      84 - Fast Fusion<br>
+      85 - Bebob<br>
+      86 - Latin<br>
+      87 - Revival<br>
+      88 - Celtic<br>
+      89 - Bluegrass<br>
+      90 - Avantgarde<br>
+      91 - Gothic Rock<br>
+      92 - Progressive Rock<br>
+      93 - Psychedelic Rock<br>
+      94 - Symphonic Rock<br>
+      95 - Slow Rock<br>
+      96 - Big Band<br>
+      97 - Chorus<br>
+      98 - Easy Listening<br>
+      99 - Acoustic </td>
+    <td>100 - Humour<br>
+      101 - Speech<br>
+      102 - Chanson<br>
+      103 - Opera<br>
+      104 - Chamber Music<br>
+      105 - Sonata<br>
+      106 - Symphony<br>
+      107 - Booty Bass<br>
+      108 - Primus<br>
+      109 - Porn Groove<br>
+      110 - Satire<br>
+      111 - Slow Jam<br>
+      112 - Club<br>
+      113 - Tango<br>
+      114 - Samba<br>
+      115 - Folklore<br>
+      116 - Ballad<br>
+      117 - Power Ballad<br>
+      118 - Rhytmic Soul<br>
+      119 - Freestyle<br>
+      120 - Duet<br>
+      121 - Punk Rock<br>
+      122 - Drum Solo<br>
+      123 - Acapella<br>
+      124 - Euro-House<br>
+      125 - Dance Hall<br>
+      126 - Goa<br>
+      127 - Drum & Bass<br>
+      128 - Club-House<br>
+      129 - Hardcore<br>
+      130 - Terror<br>
+      131 - Indie<br>
+      132 - BritPop<br>
+      133 - Negerpunk<br>
+      134 - Polsk Punk<br>
+      135 - Beat<br>
+      136 - Christian Gangsta<br>
+      137 - Heavy Metal<br>
+      138 - Black Metal<br>
+      139 - Crossover<br>
+      140 - Contemporary C<br>
+      141 - Christian Rock<br>
+      142 - Merengue<br>
+      143 - Salsa<br>
+      144 - Thrash Metal<br>
+      145 - Anime<br>
+      146 - JPop<br>
+      147 - SynthPop</td>
+  </tr>
+</table>
+<p><br>
+  <br>
+  <br>
+</p>
+</BODY>
+</HTML>
Index: extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/index.html
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/index.html	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/index.html	(revision 18425)
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+<HEAD>
+<TITLE>LAME V3 Next Generation High-End MPEG Layer III Encoding</TITLE>
+<META NAME="description" CONTENT="LAME V3 Next Generation High-End MPEG Layer III Encoding">
+<META NAME="keywords" CONTENT="lame">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso_8859_1">
+<LINK REL="STYLESHEET" HREF="lame.css">
+</HEAD>
+<BODY TEXT=#000000
+        BGCOLOR=#F9FBFB LINK=#006666 VLINK=#4C4C4C
+        ALINK=#995500>
+<FONT FACE = Helvetica > 
+<P> 
+<H1 ALIGN="CENTER"><FONT SIZE="+4"><i><font face="Arial, Helvetica, sans-serif">LAME</font></i><font face="Arial, Helvetica, sans-serif"> 
+  V3.97<BR>
+  </font></FONT> 
+  <P><font size="+4" face="Arial, Helvetica, sans-serif"> <BR>
+    </font> <font face="Arial, Helvetica, sans-serif"><BIG>L<font color="#3366FF">ame</font> 
+    A<font color="#3366FF">in't an</font> M<font color="#3366FF">P3</font> E<font color="#3366FF">ncoder</font></BIG></font> 
+  <P><BIG> <BR>
+    </BIG> 
+</H1>
+<P ALIGN="CENTER"><STRONG>Open Source Project <BR>
+  <A HREF="http://www.mp3dev.org">http://www.mp3dev.org</A> </STRONG></P>
+<P ALIGN="LEFT"></P>
+<P> 
+<DIV ALIGN="LEFT"> 
+  <P> 
+</DIV>
+<BR>
+<HR>
+<br>
+<LI><A HREF="node6.html#SECTION00310000000000000000"> Introduction</A> 
+  <UL>
+    <LI><A HREF="node6.html#SECTION00311000000000000000"> The purpose of audio 
+      compression</A> 
+    <LI><A HREF="node6.html#SECTION00312000000000000000"> The two parts of audio 
+      compression</A> 
+    <LI><A HREF="node6.html#SECTION00313000000000000000"> Compression ratios, 
+      bitrate and quality</A> 
+  </UL>
+<LI><A HREF="examples.html"> Some command line examples</A> 
+<LI><A HREF="modes.html"> CBR, ABR and VBR: the 3 encoding modes</A> 
+<LI><a href="presets.html">Built-in presets</a> 
+<LI><a href="basic.html">Basic command line switch reference</a> 
+<LI><a href="switchs.html">Full command line switch reference</a> 
+<LI><a href="id3.html">ID3 tags</a> 
+<LI><a href="history.html">History</a> 
+<LI><a href="contributors.html">Contributors</a><BR>
+</font> 
+</BODY>
+</HTML>
Index: extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/lame.css
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/lame.css	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/lame.css	(revision 18425)
@@ -0,0 +1,24 @@
+BODY {
+        font-family: Arial, Helvetica, sans-serif;
+        position: absolute;
+        padding-left: 1cm;
+        margin-left: 1cm;
+     }
+
+h1, h2, h3 {
+        margin-left: -1cm; text-align: left
+        }
+
+TABLE { text-align: left; font-family: Arial, Helvetica, sans-serif;}
+TH {background-color: #C0C0C0}
+TD {font-family: Arial, Helvetica, sans-serif;}
+
+SMALL.TINY		{ font-size : xx-small }
+SMALL.SCRIPTSIZE	{ font-size : xx-small }
+SMALL.FOOTNOTESIZE	{ font-size : x-small  }
+SMALL.SMALL		{ font-size : small    }
+BIG.LARGE		{ font-size : large    }
+BIG.XLARGE		{ font-size : x-large  }
+BIG.XXLARGE		{ font-size : xx-large }
+BIG.HUGE		{ font-size : xx-large }
+BIG.XHUGE		{ font-size : xx-large }
Index: extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/modes.html
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/modes.html	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/modes.html	(revision 18425)
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+<HEAD>
+<TITLE>Encoding modes</TITLE>
+<META NAME="description" CONTENT="Command line switch reference">
+<META NAME="keywords" CONTENT="lame">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso_8859_1">
+<LINK REL="STYLESHEET" HREF="lame.css">
+</HEAD>
+<BODY TEXT=#000000
+        BGCOLOR=#F9FBFB LINK=#006666 VLINK=#4C4C4C
+        ALINK=#995500>
+<H1>CBR/ABR/VBR: the 3 encoding modes</H1>
+<p>&nbsp;</p>
+<p>LAME is able to encode your music using one of its 3 encoding modes: constant 
+  bitrate (CBR), average bitrate (ABR) and variable bitrate (VBR).<br>
+  <br>
+  <br>
+</p>
+<h2>Constant Bitrate (CBR)</h2>
+<p>This is the default encoding mode, and also the most basic. In this mode, the 
+  bitrate will be the same for the whole file. It means that each part of your 
+  mp3 file will be using the same number of bits. The musical passage beeing a 
+  difficult one to encode or an easy one, the encoder will use the same bitrate, 
+  so the quality of your mp3 is variable. Complex parts will be of a lower quality 
+  than the easiest ones. The main advantage is that the final files size won't 
+  change and can be accurately predicted.<br>
+  <br>
+</p>
+<h2>Average Bitrate (ABR)</h2>
+<p>In this mode, you choose a target bitrate and the encoder will try to constantly 
+  maintain an average bitrate while using higher bitrates for the parts of your 
+  music that need more bits. The result will be of higher quality than CBR encoding 
+  while the average file size will remain predictible, so this mode is highly 
+  recommended over CBR.<br>
+  <br>
+</p>
+<h2>Variable bitrate (VBR)</h2>
+<p>In this mode, you choose the desired quality on a scale going from 9 (lowest 
+  quality/highest distortion) to 0 (highest quality/lowest distortion). Then encoder 
+  tries to maintain the given quality in the whole file by choosing the optimal 
+  number of bits to spend for each part of your music. The main advantage is that 
+  you are able to specify the quality level that you want to reach, but the inconvenient 
+  is that the final file size is totally unpredictible.</p>
+</BODY>
+</HTML>
Index: extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/node6.html
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/node6.html	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/node6.html	(revision 18425)
@@ -0,0 +1,132 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+<HEAD>
+<TITLE>Introduction</TITLE>
+<META NAME="description" CONTENT="Introduction">
+<META NAME="keywords" CONTENT="lame">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso_8859_1">
+<LINK REL="STYLESHEET" HREF="lame.css">
+</HEAD>
+<BODY TEXT=#000000
+        BGCOLOR=#F9FBFB LINK=#006666 VLINK=#4C4C4C
+        ALINK=#995500>
+<FONT FACE = Helvetica ><strong>Subsections</strong>
+<UL>
+  <LI><A 
+ HREF="node6.html#SECTION00311000000000000000"> The purpose of audio compression</A> 
+  <LI><A 
+ HREF="node6.html#SECTION00312000000000000000"> The two parts of audio compression</A> 
+  <LI><A 
+ HREF="node6.html#SECTION00313000000000000000"> Compression ratios, bitrate and 
+    quality</A> 
+</UL>
+
+<HR>
+<H1><A NAME="SECTION00310000000000000000"> Introduction</A> </H1>
+There is a lot of confusion surrounding the terms <I>audio compression</I>, <I>audio 
+encoding</I>, and <I>audio decoding</I>. This section will give you an overview 
+what audio coding (another one of these terms...) is all about. 
+<P> 
+<H2><A NAME="SECTION00311000000000000000"> The purpose of audio compression</A> 
+</H2>
+<P> Up to the advent of audio compression, high-quality digital audio data took 
+  a lot of hard disk space to store. Let us go through a short example. 
+<P> You want to, say, sample your favorite 1-minute song and store it on your 
+  harddisk. Because you want CD quality, you sample at 44.1 kHz, stereo, 
+  with 16 bits per sample. 
+<P> 44100 Hz means that you have 44100 values per second coming in from your sound 
+  card (or input file). Multiply that by two because you have two channels. Multiply 
+  by another factor of two because you have two bytes per value (that's what 16 
+  bit means). The song will take up <NOBR>44100 samples/s &middot; 2 channels 
+  &middot; 2 bytes/sample &middot; 60 s/min ~ 10 MBytes</NOBR> of storage space 
+  on your harddisk. 
+<P> If you wanted to download that over the internet, given an average 56k&nbsp;modem 
+  connected at 44k (which is a typical case), it would take you (at least) <NOBR>10000000 
+  bytes &middot; 8 bits/byte / (44000 bits/s) &middot; / (60 s/min) ~ 30 minutes</NOBR> 
+<DIV ALIGN="CENTER"> <B>Just to download one minute of music!</B> </DIV>
+<P> Digital audio coding, which - in this context - is synonymously called digital 
+  audio compression as well, is the art of minimizing storage space (or channel 
+  bandwidth) requirements for audio data. Modern perceptual audio coding techniques 
+  (like MPEG Layer III) exploit the properties of the human ear (the perception 
+  of sound) to achieve a size reduction by a factor of 11 with little or no perceptible 
+  loss of quality. 
+<P> Therefore, such schemes are the key technology for high quality low bit-rate 
+  applications, like soundtracks for CD-ROM games, solid-state sound memories, 
+  Internet audio, digital audio broadcasting systems, and the like. 
+<P> 
+<H2><A NAME="SECTION00312000000000000000"> The two parts of audio compression</A> 
+</H2>
+<P> Audio compression really consists of two parts. The first part, called <I>encoding</I>, 
+  transforms the digital audio data that resides, say, in a WAVE file, into a 
+  highly compressed form called <I>bitstream</I>. To play the bitstream on your 
+  soundcard, you need the second part, called <I>decoding</I>. Decoding takes 
+  the bitstream and re-expands it to a WAVE file. 
+<P> The program that effects the first part is called an audio <I>encoder</I>. 
+  <i>LAME</i> is such an encoder . The program that does the second part is called 
+  an audio <I>decoder</I>. One well-known MPEG&nbsp;Layer III decoder is <tt>Xmms</tt>, 
+  another <TT>mpg123</TT>. Both can be found on <A NAME="tex2html1"
+ HREF="http://www.mp3-tech.org">ww.mp3-tech.org</A> . 
+<H2><A NAME="SECTION00313000000000000000"> Compression ratios, bitrate and quality</A> 
+</H2>
+<P> It has not been explicitly mentioned up to now: What you end up with after 
+  encoding and decoding is not the same sound file anymore: All superflous information 
+  has been squeezed out, so to say. It is not the same <I>file</I>, but it will 
+  <I>sound</I> the same - more or less, depending on how much compression had 
+  been performed on it. 
+<P> Generally speaking, the lower the compression ratio achieved, the better the 
+  sound quality will be in the end - and <I>vice versa</I>. Table <A HREF="node6.html#table-soundq">1.1</A> 
+  gives you an overview about quality achievable. 
+<P> Because compression ratio is a somewhat unwieldy measure, experts use the 
+  term <I>bitrate</I> when speaking of the strength of compression. Bitrate denotes 
+  the average number of bits that one second of audio data will take up in your 
+  compressed bitstream. Usually the units used will be kbps, which is <SUP>kbits</SUP>/<SUB>s</SUB>, 
+  or 1000&nbsp;<SUP>bits</SUP>/<SUB>s</SUB>. To calculate the number of bytes 
+  per second of audio data, simply divide the number of bits per second by eight. 
+<P> <BR>
+<DIV ALIGN="CENTER"><A NAME="table-soundq">&#160;</A> <A NAME="95">&#160;</A> 
+  <TABLE CELLPADDING=3 BORDER="1" width="512" height="225">
+    <CAPTION><STRONG>Table 1.1:</STRONG> Bitrate versus sound quality</CAPTION>
+    <TR VALIGN="TOP"> 
+      <TD ALIGN="RIGHT" nowrap width="115">Bitrate</TD>
+      <TD ALIGN="RIGHT" nowrap width="67">Bandwidth</TD>
+      <TD ALIGN="LEFT" nowrap width="246">Quality comparable to or better than</TD>
+    </TR>
+    <TR VALIGN="TOP"> 
+      <TD ALIGN="RIGHT" nowrap width="115">16 kbps</TD>
+      <TD ALIGN="RIGHT" nowrap width="67">4.5 kHz</TD>
+      <TD ALIGN="LEFT" nowrap width="246">shortwave radio</TD>
+    </TR>
+    <TR VALIGN="TOP"> 
+      <TD ALIGN="RIGHT" nowrap width="115">32 kbps</TD>
+      <TD ALIGN="RIGHT" nowrap width="67">7.5 kHz</TD>
+      <TD ALIGN="LEFT" nowrap width="246">AM radio</TD>
+    </TR>
+    <TR VALIGN="TOP"> 
+      <TD ALIGN="RIGHT" nowrap width="115">96 kbps</TD>
+      <TD ALIGN="RIGHT" nowrap width="67">11 kHz</TD>
+      <TD ALIGN="LEFT" nowrap width="246">FM radio</TD>
+    </TR>
+    <tr valign="TOP"> 
+      <td align="RIGHT" nowrap width="115">128 kbps</td>
+      <td align="RIGHT" nowrap width="67">16 kHz</td>
+      <td align="LEFT" nowrap width="246">near CD</td>
+    </tr>
+    <tr valign="TOP"> 
+      <td align="RIGHT" nowrap width="115">160-180 kbps <br>
+        (variable bitrate)</td>
+      <td align="RIGHT" nowrap width="67">20 kHz</td>
+      <td align="LEFT" nowrap width="246">perceptual transparency</td>
+    </tr>
+    <TR VALIGN="TOP"> 
+      <TD ALIGN="RIGHT" nowrap width="115">256 kbps</TD>
+      <TD ALIGN="RIGHT" nowrap width="67">22 kHz</TD>
+      <TD ALIGN="LEFT" nowrap width="246">studio</TD>
+    </TR>
+  </TABLE>
+</DIV>
+<BR>
+</font> 
+</BODY>
+</HTML>
Index: extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/presets.html
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/presets.html	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/presets.html	(revision 18425)
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+<HEAD>
+<TITLE>Presets</TITLE>
+<META NAME="description" CONTENT="Command line switch reference">
+<META NAME="keywords" CONTENT="lame">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso_8859_1">
+<LINK REL="STYLESHEET" HREF="lame.css">
+</HEAD>
+<BODY TEXT=#000000
+        BGCOLOR=#F9FBFB LINK=#006666 VLINK=#4C4C4C
+        ALINK=#995500>
+<H1>Built-in presets</H1>
+<p>&nbsp;</p>
+<p>Lame features some built-in presets. Those presets are designed to provide 
+  the highest possible quality.<br>
+  They have for the most part been subject to and tuned via rigorous listening 
+  tests to verify and achieve this objective. These are continually updated to 
+  coincide with the latest developments that occur and as a result should provide 
+  you with nearly the best quality currently possible from LAME.</p>
+<p><br>
+  If your goal is quality, these presets are highly recommended over any custom 
+  set of parameters you might use. To activate presets, you should use:<br>
+  <tt>lame --preset preset_name</tt><br>
+  <br>
+  <br>
+</p>
+<h2>VBR modes</h2>
+<h3>--preset medium</h3>
+<p>This preset should provide near transparency to most people on most music.<br>
+  The resulting bitrate should be in the 150-180kbps range, according to music 
+  complexity.</p>
+<h3>--preset standard</h3>
+<p>This preset should generally be transparent to most people on most music and 
+  is already quite high in quality.<br>
+  The resulting bitrate should be in the 170-210kbps range, according to music 
+  complexity.</p>
+<h3>--preset extreme</h3>
+<p>If you have extremely good hearing and similar equipment, this preset will 
+  provide slightly higher quality than the &quot;standard&quot; mode.<br>
+  The resulting bitrate should be in the 200-240kbps range, according to music 
+  complexity.</p>
+<p>Any of those VBR presets can also be used in fast mode, using the new vbr algorithm. 
+  This mode is faster, but its quality could be a little lower. To enable the 
+  fast mode, use:<br>
+  <tt>lame --preset fast preset_name</tt></p>
+<p>&nbsp;</p>
+<h2>CBR 320kbps</h2>
+<h3>--preset insane</h3>
+<p>This preset will usually be overkill for most people and most situations, but 
+  if you must have the absolute highest quality with no regard to filesize, this 
+  is the way to go. This preset is the highest preset quality available.</p>
+<p>&nbsp;</p>
+<h2>ABR modes</h2>
+<h3>--preset &lt;kbps&gt;</h3>
+<p>Using this preset will usually give you good quality at a specified bitrate. 
+  Depending on the bitrate entered, this preset will determine the optimal settings 
+  for that particular situation.<br>
+  While this approach works, it is not nearly as flexible as VBR, and usually 
+  will not reach the same quality level as VBR at higher bitrates.<br>
+  If you need CBR encoding, those presets can also be used in CBR mode by using:<br>
+  <tt>lame --preset cbr &lt;kbps&gt;</tt></p>
+</BODY>
+</HTML>
Index: extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/switchs.html
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/switchs.html	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/share/doc/lame/html/switchs.html	(revision 18425)
@@ -0,0 +1,1340 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+<HEAD>
+<TITLE>Full command line switch reference</TITLE>
+<META NAME="description" CONTENT="Command line switch reference">
+<META NAME="keywords" CONTENT="lame">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso_8859_1">
+<LINK REL="STYLESHEET" HREF="lame.css">
+</HEAD>
+<BODY TEXT=#000000
+        BGCOLOR=#F9FBFB LINK=#006666 VLINK=#4C4C4C
+        ALINK=#995500>
+<H1>Full command line switch reference</H1>
+<P> <font size="-1">note: Options which could exist without being documented 
+  here are considered as experimental ones. Such experimental options should usually 
+  not be used.</font> 
+<P> 
+<TABLE CELLPADDING=3 BORDER="1">
+  <TR VALIGN="TOP"> 
+    <TD ALIGN="LEFT" nowrap><b>switch</b></TD>
+    <TD ALIGN="LEFT" nowrap><b>parameter</b></TD>
+  </TR>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#a">-a</a></kbd></td>
+    <td align="LEFT" nowrap>downmix stereo file to mono</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-abr">--abr</a></kbd></td>
+    <td align="LEFT" nowrap>average bitrate encoding</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-allshort">--allshort</a></kbd></td>
+    <td align="LEFT" nowrap>use short blocks only</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-athlower">--athlower</a></kbd></td>
+    <td align="LEFT" nowrap>lower the ATH</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-athonly">--athonly</a></kbd></td>
+    <td align="LEFT" nowrap>ATH only</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-athshort">--athshort</a></kbd></td>
+    <td align="LEFT" nowrap>ATH only for short blocks</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-athtype">--athtype</a></kbd></td>
+    <td align="LEFT" nowrap>select ATH type</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#b">-b</a></kbd></td>
+    <td align="LEFT" nowrap>bitrate (8...320)</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#Bmax">-B</a></kbd></td>
+    <td align="LEFT" nowrap>max VBR/ABR bitrate (8...320)</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-bitwidth">--bitwidth</a></kbd></td>
+    <td align="LEFT" nowrap>input bit width</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#c">-c</a></kbd></td>
+    <td align="LEFT" nowrap>copyright</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-cbr">--cbr</a></kbd></td>
+    <td align="LEFT" nowrap>enforce use of constant bitrate</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-clipdetect">--clipdetect</a></kbd></td>
+    <td align="LEFT" nowrap>clipping detection</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-comp">--comp</a></kbd></td>
+    <td align="LEFT" nowrap>choose compression ratio</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-cwlimit">--cwlimit</a></kbd></td>
+    <td align="LEFT" nowrap>tonality limit</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#d">-d</a></kbd></td>
+    <td align="LEFT" nowrap>block type control</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-decode">--decode</a></kbd></td>
+    <td align="LEFT" nowrap>decoding only</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-disptime">--disptime</a></kbd></td>
+    <td align="LEFT" nowrap>time between display updates</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#e">-e</a></kbd></td>
+    <td align="LEFT" nowrap>de-emphasis (<b>n</b>, 5, c)</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#f">-f</a></kbd></td>
+    <td align="LEFT" nowrap> fast mode</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#FF">-F</a></kbd></td>
+    <td align="LEFT" nowrap> strictly enforce the -b option</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-freeformat">--freeformat</a></kbd></td>
+    <td align="LEFT" nowrap> free format bitstream</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#h">-h</a></kbd></td>
+    <td align="LEFT" nowrap>high quality</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-help">--help</a></kbd></td>
+    <td align="LEFT" nowrap> help</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-highpass">--highpass</a></kbd></td>
+    <td align="LEFT" nowrap> highpass filtering frequency in kHz</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-highpass">--highpass-width</a></kbd></td>
+    <td align="LEFT" nowrap> width of highpass filtering in kHz</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#k">-k</a></kbd></td>
+    <td align="LEFT" nowrap> full bandwidth</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-lowpass">--lowpass</a></kbd></td>
+    <td align="LEFT" nowrap> lowpass filtering frequency in kHz</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-lowpass-width">--lowpass-width</a></kbd></td>
+    <td align="LEFT" nowrap> width of lowpass filtering in kHz</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#m">-m</a></kbd></td>
+    <td align="LEFT" nowrap>stereo mode (s, <b>j</b>, f, m)</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-mp1input">--mp1input</a></kbd></td>
+    <td align="LEFT" nowrap>MPEG Layer I input file</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-mp2input">--mp2input</a></kbd></td>
+    <td align="LEFT" nowrap>MPEG Layer II input file</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-mp3input">--mp3input</a></kbd></td>
+    <td align="LEFT" nowrap>MPEG Layer III input file</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-noath">--noath</a></kbd></td>
+    <td align="LEFT" nowrap>disable ATH</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-noasm">--noasm</a></kbd></td>
+    <td align="LEFT" nowrap>disable assembly optimizations (mmx/3dnow/sse)</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-nohist">--nohist</a></kbd></td>
+    <td align="LEFT" nowrap>disable histogram display</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-noreplaygain">--noreplaygain</a></kbd></td>
+    <td align="LEFT" nowrap>disable ReplayGain analysis</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-nores">--nores</a></kbd></td>
+    <td align="LEFT" nowrap>disable bit reservoir</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-noshort">--noshort</a></kbd></td>
+    <td align="LEFT" nowrap>disable short blocks frames</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-notemp">--notemp</a></kbd></td>
+    <td align="LEFT" nowrap>disable temporal masking</td>
+  </tr>
+  <TR VALIGN="TOP"> 
+    <TD ALIGN="LEFT" nowrap><kbd><a href="#o">-o</a></kbd></TD>
+    <TD ALIGN="LEFT" nowrap>non-original</TD>
+  </TR>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#p">-p</a></kbd></td>
+    <td align="LEFT" nowrap>error protection</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-preset">--preset</a></kbd></td>
+    <td align="LEFT" nowrap>use built-in preset</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-priority">--priority</a></kbd></td>
+    <td align="LEFT" nowrap>OS/2 process priority control</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#q">-q</a></kbd></td>
+    <td align="LEFT" nowrap>algorithm quality selection</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-silent">--quiet</a></kbd></td>
+    <td align="LEFT" nowrap>silent operation</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#r">-r</a></kbd></td>
+    <td align="LEFT" nowrap>input file is raw PCM</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-replaygain-accurate">--replaygain-accurate</a></kbd></td>
+    <td align="LEFT" nowrap>compute ReplayGain more accurately and find the peak sample</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-replaygain-fast">--replaygain-fast</a></kbd></td>
+    <td align="LEFT" nowrap>compute ReplayGain fast but slightly inaccurately (default)</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-resample">--resample</a></kbd></td>
+    <td align="LEFT" nowrap>output sampling frequency in kHz (encoding only)</td>
+  </tr>
+  <TR VALIGN="TOP"> 
+    <TD ALIGN="LEFT" nowrap><kbd><a href="#s">-s</a></kbd></TD>
+    <TD ALIGN="LEFT" nowrap>sampling frequency in kHz</TD>
+  </TR>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-silent">-S</a></kbd></td>
+    <td align="LEFT" nowrap>silent operation</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-scale">--scale</a></kbd></td>
+    <td align="LEFT" nowrap>scale input</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-scale-l">--scale-l</a></kbd></td>
+    <td align="LEFT" nowrap>scale input channel 0 (left)</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-scale-r">--scale-r</a></kbd></td>
+    <td align="LEFT" nowrap>scale input channel 1 (right)</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-short">--short</a></kbd></td>
+    <td align="LEFT" nowrap>use short blocks</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-silent">--silent</a></kbd></td>
+    <td align="LEFT" nowrap>silent operation</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-strictly-enforce-ISO">--strictly-enforce-ISO</a></kbd></td>
+    <td align="LEFT" nowrap>strict ISO compliance</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#t">-t</a></kbd></td>
+    <td align="LEFT" nowrap>disable INFO/WAV header</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#V">-V</a></kbd></td>
+    <td align="LEFT" nowrap>VBR quality setting (0...9)</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-vbr-new">--vbr-new</a></kbd></td>
+    <td align="LEFT" nowrap>new VBR mode</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-vbr-old">--vbr-old</a></kbd></td>
+    <td align="LEFT" nowrap>older VBR mode</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#-verbose">--verbose</a></kbd></td>
+    <td align="LEFT" nowrap>verbosity</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#x">-x</a></kbd></td>
+    <td align="LEFT" nowrap>swapbytes</td>
+  </tr>
+  <tr valign="TOP"> 
+    <td align="LEFT" nowrap><kbd><a href="#Xquant">-X</a></kbd></td>
+    <td align="LEFT" nowrap>change quality measure</td>
+  </tr>
+</TABLE>
+<BR>
+<dl> 
+  <dt><strong>* <kbd>-a</kbd><a name="a">&nbsp;&nbsp;&nbsp;&nbsp;downmix&#160;</a></strong> 
+  <dd>Mix the stereo input file to mono and encode as mono.<br>
+    The downmix is calculated as the sum of the left and right channel, attenuated 
+    by 6 dB. <br>
+    <br>
+    This option is only needed in the case of raw PCM stereo input (because LAME 
+    cannot determine the number of channels in the input file).<br>
+    To encode a stereo PCM input file as mono, use "lame -m s -a".<br>
+    <br>
+    For WAV and AIFF input files, using "-m m" will always produce a mono .mp3 
+    file from both mono and stereo input. 
+  <dt><br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+</dl>
+<dl> 
+  <dt><strong>* <kbd>--abr n</kbd><a name="-abr">&nbsp;&nbsp;&nbsp;&nbsp;average 
+    bitrate encoding</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>Turns on encoding with a targeted average bitrate of n kbits, allowing to 
+    use frames of different sizes. The allowed range of n is 8-310, you can use 
+    any integer value within that range.<br>
+    <br>
+    It can be combined with the -b and -B switches like:<br>
+    lame --abr 123 -b 64 -B 192 a.wav a.mp3<br>
+    which would limit the allowed frame sizes between 64 and 192 kbits. <br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+</dl>
+<dl> 
+  <dt><strong>* <kbd>--allshort</kbd><a name="-allshort">&nbsp;&nbsp;&nbsp;&nbsp;use 
+    short blocks only</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>Use only short blocks, no long ones. 
+</dl>
+<dl> 
+  <dd>&nbsp; 
+  <dt><br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+</dl>
+<dl> 
+  <dt><strong>* <kbd>--athlower n</kbd><a name="-athlower">&nbsp;&nbsp;&nbsp;&nbsp;lower 
+    the ATH</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>Lower the ATH (absolute threshold of hearing) by n dB.<br>
+    Normally, humans are unable to hear any sound below this threshold, but for 
+    music recorded at very low level this option might be useful.
+</dl>
+<dl> 
+  <dd>&nbsp; 
+  <dt><br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+</dl>
+<dl> 
+  <dt><strong>* <kbd>--athonly</kbd><a name="-athonly">&nbsp;&nbsp;&nbsp;&nbsp;ATH 
+    only</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>This option causes LAME to ignore the output of the psy-model and only use 
+    masking from the ATH (absolute threshold of hearing). Might be useful at very 
+    high bitrates or for testing the ATH. 
+</dl>
+<dl> 
+  <dd>&nbsp; 
+  <dt><br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+</dl>
+<dl> 
+  <dt><strong>* <kbd>--athshort</kbd><a name="-athshort">&nbsp;&nbsp;&nbsp;&nbsp;ATH 
+    only for short blocks</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>Ignore psychoacoustic model for short blocks, use ATH only. 
+</dl>
+<dl> 
+  <dd>&nbsp; 
+  <dt><br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+</dl>
+<dl> 
+  <dt><strong>* <kbd>--athtype 0/1/2</kbd><a name="-athtype">&nbsp;&nbsp;&nbsp;&nbsp;select 
+    ATH type</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>The Absolute Threshold of Hearing is the minimum threshold under which humans 
+    are unable to hear any sound. In the past, LAME was using ATH shape 0 which 
+    is the Painter & Spanias formula. Tests have shown that this formula is innacurate 
+    for the 13-22 kHz area, leading to audible artifacts in some cases. Shape 1 
+    was thus implemented, which is over sensitive, leading to very high bitrates. 
+    Shape 2 formula was accurately modelized from real data in order to real optimal 
+    quality while not wasting bitrate. In CBR and ABR modes, LAME uses ATH shape 
+    2 by default. <br>
+    <br>
+    In VBR mode, LAME is adapting its shape according to the 
+    -V value, going gradually from the 0 shape at -V9 up to shape 2 at -V0.
+</dl>
+<dl> 
+  <dd>&nbsp; 
+  <dt><br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+</dl>
+<dl> 
+  <dt><strong>* <kbd>-b n</kbd><a name="b">&nbsp;&nbsp;&nbsp;&nbsp;bitrate</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd>For MPEG1 (sampling frequencies of 32, 44.1 and 48 kHz)<br>
+    n = 32,40,48,56,64,80,96,112,128,160,192,224,256,320<br>
+    <br>
+    For MPEG2 (sampling frequencies of 16, 22.05 and 24 kHz)<br>
+    n = 8,16,24,32,40,48,56,64,80,96,112,128,144,160<br>
+    <br>
+    Default is 128 kbps for MPEG1 and 64 kbps for MPEG2. <br>
+    <br>
+    When used with variable bitrate encoding (VBR), -b specifies the minimum bitrate 
+    to be used. However, in order to avoid wasted space, the smallest frame size 
+    available will be used during silences. 
+  <dt><br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+</dl>
+<dl> 
+  <dt><strong>* <kbd>-B n</kbd><a name="Bmax">&nbsp;&nbsp;&nbsp;&nbsp;maximum 
+    VBR/ABR bitrate&nbsp;</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>For MPEG1 (sampling frequencies of 32, 44.1 and 48 kHz)<br>
+    n = 32,40,48,56,64,80,96,112,128,160,192,224,256,320<br>
+    <br>
+    For MPEG2 (sampling frequencies of 16, 22.05 and 24 kHz)<br>
+    n = 8,16,24,32,40,48,56,64,80,96,112,128,144,160<br>
+    <br>
+    Specifies the maximum allowed bitrate when using VBR/ABR <br>
+    <br>
+    The use of -B is NOT RECOMMENDED. A 128kbps CBR bitstream, because of the bit reservoir, 
+    can actually have frames which use as many bits as a 320kbps frame. VBR modes 
+    minimize the use of the bit reservoir, and thus need to allow 320kbps frames 
+    to get the same flexibility as CBR streams.<br>
+    <br>
+    <i>note: If you own an mp3 hardware player build upon a MAS 3503 chip, you 
+    must set maximum bitrate to no more than 224 kpbs.</i> <br>
+</dl>
+<dl> 
+  <dt><strong>* <kbd>--bitwidth 8/16/24/32</kbd><a name="-bitwidth">&nbsp;&nbsp;&nbsp;&nbsp;input 
+    bit width&nbsp;</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> Required only for raw PCM input files. Otherwise it will be determined 
+    from the header of the input file. <br>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--clipdetect</kbd><a name="-clipdetect">&nbsp;&nbsp;&nbsp;&nbsp;clipping detection</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd>
+    Enable --replaygain-accurate and print a message whether clipping 
+    occurs and how far in dB the waveform is from full scale.<br>
+    <br>
+    This option is not usable if the MP3 decoder was <b>explicitly</b>
+    disabled in the build of LAME.<br>
+    <br>
+    See also: <a href="#-replaygain-accurate">--replaygain-accurate</a>
+  <dt><br>
+    <br>
+    <hr width="50%" noshade align="center">
+    <br>
+  <dt><strong>* <kbd>--cbr</kbd><a name="-cbr">
+    &nbsp;&nbsp;&nbsp;&nbsp;enforce use of constant bitrate</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd>This switch enforces the use of constant bitrate encoding. 
+  <dt><br>
+    <br>
+    <hr width="50%" noshade align="center">
+    <br>
+  <dt><strong>* <kbd>--cbr</kbd><a name="-cbr">
+    &nbsp;&nbsp;&nbsp;&nbsp;enforce use of constant bitrate</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd>This switch enforces the use of constant bitrate encoding. 
+  <dt><br>
+    <br>
+    <hr width="50%" noshade align="center">
+    <br>
+  <dt><strong>* <kbd>--comp</kbd><a name="-comp">&nbsp;&nbsp;&nbsp;&nbsp;choose 
+    compression ratio</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>Instead of choosing bitrate, using this option, user can choose compression 
+    ratio to achieve. 
+  <dt><br>
+    <br>
+    <hr width="50%" noshade align="center">
+    <br>
+  <dt><strong>* <kbd>--cwlimit n</kbd><a name="-cwlimit">&nbsp;&nbsp;&nbsp;tonality 
+    limit</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>Compute tonality up to freq (in kHz). Default setting is 8.8717. 
+  <dt><br>
+    <br>
+    <hr width="50%" noshade align="center">
+    <br>
+  <dt><strong>* <kbd>-d</kbd><a name="d">&nbsp;&nbsp;&nbsp;&nbsp;block type control</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd>Allows the left and right channels to use different block size types. 
+  <dt><br>
+    <br>
+    <hr width="50%" noshade align="center">
+    <br>
+  <dt><strong>* <kbd>--decode</kbd><a name="-decode">&nbsp;&nbsp;&nbsp;&nbsp;decoding 
+    only</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>Uses LAME for decoding to a WAV file. The input file can be any input type 
+    supported by encoding, including layer I,II,III (MP3) and OGG files. In case 
+    of MPEG files, LAME uses a bugfixed version of mpglib for decoding.<br>
+    <br>
+    If -t is used (disable WAV header), Lame will output raw PCM in native endian 
+    format. You can use -x to swap bytes order. <br>
+    <br>
+    This option is not usable if the MP3 decoder was <b>explicitly</b>
+    disabled in the build of LAME.
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--disptime n</kbd><a name="-disptime">&nbsp;&nbsp;&nbsp;&nbsp;time 
+    between display updates</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>Set the delay in seconds between two display updates. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-e n/5/c</kbd><a name="e">&nbsp;&nbsp;&nbsp;&nbsp;de-emphasis</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd> <br>
+    n = (none, default)<br>
+    5 = 0/15 microseconds<br>
+    c = citt j.17<br>
+    <br>
+    All this does is set a flag in the bitstream. If you have a PCM input file 
+    where one of the above types of (obsolete) emphasis has been applied, you 
+    can set this flag in LAME. Then the mp3 decoder should de-emphasize the output 
+    during playback, although most decoders ignore this flag.<br>
+    <br>
+    A better solution would be to apply the de-emphasis with a standalone utility 
+    before encoding, and then encode without -e. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-f</kbd><a name="f">&nbsp;&nbsp;&nbsp;&nbsp;fast mode</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd> This switch forces the encoder to use a faster encoding mode, but with 
+    a lower quality. The behaviour is the same as the -q7 switch.<br>
+    <br>
+    Noise shaping will be disabled, but psycho acoustics will still be computed 
+    for bit allocation and pre-echo detection. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-F</kbd><a name="FF">&nbsp;&nbsp;&nbsp;strictly enforce the 
+    -b option</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> This is mainly for use with hardware players that do not support low bitrate 
+    mp3.<br>
+    <br>
+    Without this option, the minimum bitrate will be ignored for passages of analog 
+    silence, ie when the music level is below the absolute threshold of human 
+    hearing (ATH). 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--freeformat</kbd><a name="-freeformat">&nbsp;&nbsp;&nbsp;&nbsp;free 
+    format bitstream</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> Produces a free format bitstream. With this option, you can use -b with 
+    any bitrate higher than 8 kbps.<br>
+    <br>
+    However, even if an mp3 decoder is required to support free bitrates at least 
+    up to 320 kbps, many players are unable to deal with it.<br>
+    <br>
+    Tests have shown that the following decoders support free format:<br>
+    <br>
+    FreeAmp up to 440 kbps<br>
+    in_mpg123 up to 560 kbps<br>
+    l3dec up to 310 kbps<br>
+    LAME up to 560 kbps<br>
+    MAD up to 640 kbps<br>
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-h</kbd><a name="h">&nbsp;&nbsp;&nbsp;&nbsp;high quality</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd> Use some quality improvements. Encoding will be slower, but the result 
+    will be of higher quality. The behaviour is the same as the -q2 switch.<br>
+    This switch is always enabled when using VBR. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--help</kbd><a name="-help">&nbsp;&nbsp;&nbsp;&nbsp;help</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd> Display a list of all available options. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--highpass</kbd><a name="-highpass">&nbsp;&nbsp;&nbsp;&nbsp;highpass 
+    filtering frequency in kHz</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> Set an highpass filtering frequency. Frequencies below the specified one 
+    will be cutoff. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--highpass-width</kbd><a name="-highpass-width">&nbsp;&nbsp;&nbsp;&nbsp;width 
+    of highpass filtering in kHz</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> Set the width of the highpass filter. The default value is 15% of the highpass 
+    frequency. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-k</kbd><a name="k">&nbsp;&nbsp;&nbsp;&nbsp;full bandwidth</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd> Tells the encoder to use full bandwidth and to disable all filters. By 
+    default, the encoder uses some lowpass filtering at lower bitrates, in order 
+    to keep a good quality by giving more bits to more important frequencies.<br>
+    Increasing the bandwidth from the default setting might produce ringing artefacts 
+    at low bitrates. Use with care! 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--lowpass</kbd><a name="-lowpass">&nbsp;&nbsp;&nbsp;&nbsp;lowpass 
+    filtering frequency in kHz</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Set a lowpass filtering frequency. Frequencies above the specified one 
+    will be cutoff. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--lowpass-width</kbd><a name="-lowpass-width">&nbsp;&nbsp;&nbsp;&nbsp;width 
+    of lowpass filtering in kHz</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Set the width of the lowpass filter. The default value is 15% of the lowpass 
+    frequency. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-m s/<b>j/</b>f/d/m</kbd><a name="m">&nbsp;&nbsp;&nbsp;&nbsp;stereo 
+    mode</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> Joint-stereo is the default mode for input files featuring two channels.. 
+    <b><i><br>
+    <br>
+    stereo</i></b> <br>
+    In this mode, the encoder makes no use of potentially existing correlations 
+    between the two input channels. It can, however, negotiate the bit demand 
+    between both channel, i.e. give one channel more bits if the other contains 
+    silence or needs less bits because of a lower complexity.<br>
+    <br>
+    <i><b>joint stereo</b></i><br>
+    In this mode, the encoder will make use of correlation between both channels. 
+    The signal will be matrixed into a sum ("mid"), computed by L+R, and difference 
+    ("side") signal, computed by L-R, and more bits are allocated to the mid channel.<br>
+    This will effectively increase the bandwidth if the signal does not have too 
+    much stereo separation, thus giving a significant gain in encoding quality. 
+    In joint stereo, the encoder can select between Left/Right and Mid/Side representation 
+    on a frame basis.<br>
+    <br>
+    Using mid/side stereo inappropriately can result in audible compression artifacts. 
+    To much switching between mid/side and regular stereo can also sound bad. 
+    To determine when to switch to mid/side stereo, LAME uses a much more sophisticated 
+    algorithm than that described in the ISO documentation, and thus is safe to 
+    use in joint stereo mode.<br>
+    <br>
+    <b><i>forced joint stereo </i></b><br>
+    This mode will force MS joint stereo on all frames. It's slightly faster than 
+    joint stereo, but it should be used only if you are sure that every frame 
+    of the input file has very little stereo separation.<br>
+    <br>
+    <b><i>dual channels </i></b><br>
+    In this mode, the 2 channels will be totally independently encoded. Each 
+    channel will have exactly half of the bitrate. This mode is designed for applications 
+    like dual languages encoding (ex: English in one channel and French in the 
+    other). Using this encoding mode for regular stereo files will result in a 
+    lower quality encoding.<br>
+    <br>
+    <b><i>mono</i></b><br>
+    The input will be encoded as a mono signal. If it was a stereo signal, it 
+    will be downsampled to mono. The downmix is calculated as the sum of the left 
+    and right channel, attenuated by 6 dB. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--mp1input</kbd><a name="-mp1input">&nbsp;&nbsp;&nbsp;&nbsp;MPEG 
+    Layer I input file</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> Assume the input file is a MPEG Layer I file.<br>
+    If the filename ends in ".mp1" or &quot;.mpg&quot; LAME will assume it is 
+    a MPEG Layer I file. For stdin or Layer I files which do not end in .mp1 or .mpg 
+    you need to use this switch. 
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--mp2input</kbd><a name="-mp2input">&nbsp;&nbsp;&nbsp;&nbsp;MPEG 
+    Layer II input file</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> Assume the input file is a MPEG Layer II (ie MP2) file.<br>
+    If the filename ends in ".mp2" LAME will assume it is a MPEG Layer II file. For 
+    stdin or Layer II files which do not end in .mp2 you need to use this switch. 
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--mp3input</kbd><a name="-mp3input">&nbsp;&nbsp;&nbsp;&nbsp;MPEG 
+    Layer III input file</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> Assume the input file is a MP3 file. Useful for downsampling from one 
+    mp3 to another. As an example, it can be useful for streaming through an 
+    IceCast server.<br>
+    If the filename ends in ".mp3" LAME will assume it is an MP3 file. For stdin or 
+    MP3 files which do not end in .mp3 you need to use this switch. 
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--noath</kbd><a name="-noath">&nbsp;&nbsp;&nbsp;&nbsp;disable 
+    ATH</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> Disable any use of the ATH (absolute threshold of hearing) for masking. 
+    Normally, humans are unable to hear any sound below this threshold. 
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--noasm mmx/3dnow/sse</kbd><a name="-noasm">
+   &nbsp;&nbsp;&nbsp;&nbsp;disable assembly optimizations</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>Disable specific assembly optimizations. Quality will not increase, only
+      speed will be reduced. If you have problems running Lame on a Cyrix/Via
+      processor, disabling mmx optimizations might solve your problem.
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--nohist</kbd><a name="-nohist">&nbsp;&nbsp;&nbsp;&nbsp;disable 
+    histogram display</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> By default, LAME will display a bitrate histogram while producing VBR mp3 
+    files. This will disable that feature.<br>
+    Histogram display might not be available on your release. 
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--noreplaygain</kbd><a name="-noreplaygain">&nbsp;&nbsp;&nbsp;&nbsp;disable 
+    ReplayGain analysis</a></strong></dt>
+</dl>
+<dl> 
+  <dd> By default ReplayGain analysis is enabled. This switch disables it.<br>
+  <br>
+    See also: <a href="#-replaygain-accurate">--replaygain-accurate</a>,
+    <a href="#-replaygain-fast">--replaygain-fast</a>
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--nores</kbd><a name="-nores">&nbsp;&nbsp;&nbsp;&nbsp;disable 
+    bit reservoir</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Disable the bit reservoir. Each frame will then become independent from 
+    previous ones, but the quality will be lower. 
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--noshort</kbd><a name="-noshort">&nbsp;&nbsp;&nbsp;&nbsp;disable 
+    short blocks frames</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Encode all frames using long blocks only. This could increase quality when 
+    encoding at very low bitrates, but can produce serious pre-echo artefacts. 
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--notemp</kbd><a name="-notemp">&nbsp;&nbsp;&nbsp;&nbsp;disable 
+    temporal masking</a></strong></dt>
+</dl>
+<dl> 
+  <dd>Don't make use of the temporal masking effect. 
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-o</kbd><a name="o">&nbsp;&nbsp;&nbsp;&nbsp;non-original</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd> Mark the encoded file as being a copy. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-p</kbd><a name="p">&nbsp;&nbsp;&nbsp;&nbsp;error protection</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Turn on CRC error protection.<br>
+    It will add a cyclic redundancy check (CRC) code in each frame, allowing to 
+    detect transmission errors that could occur on the MP3 stream. However, it 
+    takes 16 bits per frame that would otherwise be used for encoding, and then 
+    will slightly reduce the sound quality. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--preset presetName</kbd> <a name="-preset">&nbsp;&nbsp;&nbsp;&nbsp;use 
+    built-in preset</a></strong></dt>
+</dl>
+<dd> Use one of the built-in presets (standard, fast standard, extreme, fast extreme, insane, or the abr/cbr modes).
+<br>
+<dd>   "--preset help" gives more information about the usage possibilities for these presets. 
+<dt><br>
+  <br>
+<hr width="50%" noshade align="center">
+<br>
+<dl> </dl>
+<dt><strong>* <kbd>--priority 0...4</kbd><a name="-priority">&nbsp;&nbsp;&nbsp;&nbsp;OS/2 
+  process priority control</a></strong> </dt>
+<dl> 
+  <dd> With this option, LAME will run with a different process priority under 
+    IBM OS/2.<br>
+    This will greatly improve system responsiveness, since OS/2 will have more 
+    free time to properly update the screen and poll the keyboard/mouse. It should 
+    make quite a difference overall, especially on slower machines. LAME's performance 
+    impact should be minimal.<br>
+    <br>
+  <dd><b>0 (Low priority)</b><br>
+    Priority 0 assumes "IDLE" class, with delta 0.<br>
+    LAME will have the lowest priority possible, and the encoding may be suspended 
+    very frequently by user interaction.<br>
+    <br>
+  <dd><b>1 (Medium priority)</b><br>
+    Priority 1 assumes "IDLE" class, with delta +31.<br>
+    LAME won't interfere at all with what you're doing.<br>
+    Recommended if you have a slower machine. <br>
+    <br>
+  <dd><b>2 (Regular priority)</b><br>
+    Priority 2 assumes "REGULAR" class, with delta -31.<br>
+    LAME won't interfere with your activity. It'll run just like a regular process, 
+    but will spare just a bit of idle time for the system. Recommended for most 
+    users. <br>
+    <br>
+  <dd><b>3 (High priority)</b><br>
+    Priority 3 assumes "REGULAR" class, with delta 0.<br>
+    LAME will run with a priority a bit higher than a normal process. <br>
+    Good if you're just running LAME by itself or with moderate user interaction.<br>
+    <br>
+  <dd><b>4 (Maximum priority)</b><br>
+    Priority 4 assumes "REGULAR" class, with delta +31.<br>
+    LAME will run with a very high priority, and may interfere with the machine 
+    response.<br>
+    Recommended if you only intend to run LAME by itself, or if you have a fast 
+    processor. <br>
+    <br>
+    <br>
+    Priority 1 or 2 is recommended for most users. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-q 0..9</kbd><a name="q">&nbsp;&nbsp;&nbsp;&nbsp;algorithm 
+    quality selection</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Bitrate is of course the main influence on quality. The higher the bitrate, 
+    the higher the quality. But for a given bitrate, we have a choice of algorithms 
+    to determine the best scalefactors and Huffman encoding (noise shaping).<br>
+    <br>
+    -q 0: use slowest &amp; best possible version of all algorithms. -q 0 and -q 1 
+    are slow and may not produce significantly higher quality.<br>
+    <br>
+    -q 2: recommended. Same as -h.<br>
+    <br>
+    -q 5: default value. Good speed, reasonable quality.<br>
+    <br>
+    -q 7: same as -f. Very fast, ok quality. (psycho acoustics are used for pre-echo 
+    &amp; M/S, but no noise shaping is done.<br>
+    <br>
+    -q 9: disables almost all algorithms including psy-model. poor quality. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-r</kbd><a name="r">&nbsp;&nbsp;&nbsp;&nbsp;input file is 
+    raw PCM</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Assume the input file is raw PCM. Sampling rate and mono/stereo/jstereo 
+    must be specified on the command line. Without -r, LAME will perform several 
+    fseek()'s on the input file looking for WAV and AIFF headers.<br>
+    Might not be available on your release. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--replaygain-accurate</kbd><a name="-replaygain-accurate">&nbsp;&nbsp;&nbsp;&nbsp;compute
+   ReplayGain more accurately and find the peak sample</a></strong></dt>
+</dl>
+<dl> 
+  <dd>
+    Enable decoding on the fly. Compute "Radio" ReplayGain on the decoded 
+    data stream. Find the peak sample of the decoded data stream and store 
+    it in the file.<br>
+    <br>    
+    ReplayGain analysis does <i>not</i> affect the content of a 
+    compressed data stream itself, it is a value stored in the header 
+    of a sound file. Information on the purpose of ReplayGain and the
+    algorithms used is available from 
+    <a href="http://www.replaygain.org/">http://www.replaygain.org/</a><br>
+    <br>
+    By default, LAME performs ReplayGain analysis on the input data 
+    (after the user-specified volume scaling). This
+    behavior might give slightly inaccurate results because the data on 
+    the output of a lossy compression/decompression sequence differs from 
+    the initial input data. When --replaygain-accurate is specified the
+    mp3 stream gets decoded on the fly and the analysis is performed on the
+    decoded data stream. Although theoretically this method gives more 
+    accurate results, it has several disadvantages:
+    <ul>
+      <li> tests have shown that the difference between the ReplayGain values 
+        computed on the input data and decoded data is usually no greater 
+        than 0.5dB, although the minimum volume difference the human ear 
+        can perceive is about 1.0dB
+      </li>
+      <li> decoding on the fly significantly slows down the encoding process
+      </li>
+    </ul>
+    The apparent advantage is that:
+    <ul>
+      <li> with --replaygain-accurate the peak sample is determined and 
+        stored in the file. The knowledge of the peak sample can be useful
+        to decoders (players) to prevent a negative effect called 'clipping'
+        that introduces distortion into sound.
+      </li>
+    </ul>    
+    <br>
+    Only the "RadioGain" ReplayGain value is computed. It is stored in the 
+    LAME tag. The analysis is  performed with the reference volume equal
+    to 89dB. Note: the reference volume has been changed from 83dB on 
+    transition from version 3.95 to 3.95.1.<br>
+    <br>
+    This option is not usable if the MP3 decoder was <b>explicitly</b>
+    disabled in the build of LAME. (Note: if LAME is compiled without the 
+    MP3 decoder, ReplayGain analysis is performed on the input data after
+    user-specified volume scaling).<br>
+    <br>
+    See also: <a href="#-replaygain-fast">--replaygain-fast</a>, 
+    <a href="#-noreplaygain">--noreplaygain</a>, <a href="#-clipdetect">--clipdetect</a>
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--replaygain-fast</kbd><a name="-replaygain-fast">&nbsp;&nbsp;&nbsp;&nbsp;compute
+   ReplayGain fast but slightly inaccurately (default)</a></strong></dt>
+</dl>
+<dl> 
+  <dd>
+    Compute "Radio" ReplayGain on the input data stream after user-specified 
+    volume scaling and/or resampling.<br>
+    <br>    
+    ReplayGain analysis does <i>not</i> affect the content of a 
+    compressed data stream itself, it is a value stored in the header 
+    of a sound file. Information on the purpose of ReplayGain and the
+    algorithms used is available from 
+    <a href="http://www.replaygain.org/">http://www.replaygain.org/</a><br>
+    <br>
+    Only the "RadioGain" ReplayGain value is computed. It is stored in the 
+    LAME tag. The analysis is  performed with the reference volume equal
+    to 89dB. Note: the reference volume has been changed from 83dB on 
+    transition from version 3.95 to 3.95.1.<br>
+    <br>
+    This switch is enabled by default.<br>
+    <br>
+    See also: <a href="#-replaygain-accurate">--replaygain-accurate</a>, 
+    <a href="#-noreplaygain">--noreplaygain</a>
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--resample 8/11.025/12/16/22.05/24/32/44.1/48</kbd><a name="-resample">&nbsp;&nbsp;&nbsp;&nbsp;output 
+    sampling frequency in kHz</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Select output sampling frequency (for encoding only). <br>
+    If not specified, LAME will automatically resample the input when using high 
+    compression ratios. 
+  <dt><br>
+  </dt>
+</dl>
+<dl> 
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-s 8/11.025/12/16/22.05/24/32/44.1/48</kbd><a name="s">&nbsp;&nbsp;&nbsp;&nbsp;sampling 
+    frequency</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> Required only for raw PCM input files. Otherwise it will be determined 
+    from the header of the input file.<br>
+    <br>
+    LAME will automatically resample the input file to one of the supported MP3 
+    samplerates if necessary. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-S / --silent / --quiet</kbd><a name="-silent">&nbsp;&nbsp;&nbsp;&nbsp;silent 
+    operation</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> Don't print progress report. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--scale n</kbd><a name="-scale">&nbsp;&nbsp;&nbsp;&nbsp;scales 
+    input by n</a></strong> </dt>
+  <dt><strong>* <kbd>--scale-l n</kbd><a name="-scale-l">&nbsp;&nbsp;&nbsp;&nbsp;scales 
+    input channel 0 (left) by n</a></strong> </dt>
+  <dt><strong>* <kbd>--scale-r n</kbd><a name="-scale-r">&nbsp;&nbsp;&nbsp;&nbsp;scales 
+    input channel 1 (right) by n</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>Scales input by n. This just multiplies the PCM data (after it has been 
+    converted to floating point) by n. <br>
+    <br>
+    n > 1: increase volume<br>
+    n = 1: no effect<br>
+    n < 1: reduce volume<br>
+    <br>
+    Use with care, since most MP3 decoders will truncate data which decodes to 
+    values greater than 32768. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--short</kbd><a name="-short">&nbsp;&nbsp;&nbsp;&nbsp;use 
+    short blocks</a></strong> </dt>
+</dl>
+<dl> 
+  <dd>Let LAME use short blocks when appropriate. It is the default setting. 
+</dl>
+<dl> 
+  <dd>&nbsp; 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--strictly-enforce-ISO</kbd><a name="-strictly-enforce-ISO">&nbsp;&nbsp;&nbsp;&nbsp;strict 
+    ISO compliance</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> With this option, LAME will enforce the 7680 bit limitation on total frame 
+    size.<br>
+    This results in many wasted bits for high bitrate encodings but will ensure 
+    strict ISO compatibility. This compatibility might be important for hardware 
+    players. 
+</dl>
+<dl> 
+  <dd>&nbsp; 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-t</kbd><a name="t">&nbsp;&nbsp;&nbsp;&nbsp;disable INFO/WAV 
+    header </a></strong></dt>
+</dl>
+<dl> 
+  <dd> Disable writing of the INFO Tag on encoding.<br>
+    This tag in embedded in frame 0 of the MP3 file. It includes some information 
+    about the encoding options of the file, and in VBR it lets VBR aware players 
+    correctly seek and compute playing times of VBR files.<br>
+    <br>
+    When '--decode' is specified (decode to WAV), this flag will disable writing 
+    of the WAV header. The output will be raw PCM, native endian format. Use -x 
+    to swap bytes. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-V 0...9</kbd><a name="V">&nbsp;&nbsp;&nbsp;&nbsp;VBR quality 
+    setting</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Enable VBR (Variable BitRate) and specifies the value of VBR quality.<br>
+    default=4<br>
+    0=highest quality. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--vbr-new</kbd><a name="-vbr-new">&nbsp;&nbsp;&nbsp;&nbsp;new 
+    VBR mode</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Invokes the newest VBR algorithm. During the development of version 3.90, 
+    considerable tuning was done on this algorithm, and it is now considered to 
+    be on par with the original --vbr-old. <br>
+    It has the added advantage of being very fast (over twice as fast as --vbr-old). 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--vbr-old</kbd><a name="-vbr-old">&nbsp;&nbsp;&nbsp;&nbsp;older 
+    VBR mode</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Invokes the oldest, most tested VBR algorithm. It produces very good quality 
+    files, though is not very fast. This has, up through v3.89, been considered 
+    the "workhorse" VBR algorithm. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>--verbose</kbd><a name="-verbose">&nbsp;&nbsp;&nbsp;&nbsp;verbosity</a></strong></dt>
+</dl>
+<dl> 
+  <dd> Print a lot of information on screen. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-x</kbd><a name="x">&nbsp;&nbsp;&nbsp;&nbsp;swapbytes</a></strong> 
+  </dt>
+</dl>
+<dl> 
+  <dd> Swap bytes in the input file or output file when using --decode.<br>
+    For sorting out little endian/big endian type problems. If your encodings 
+    sounds like static, try this first. 
+  <dt><br>
+    <br>
+  </dt>
+  <hr width="50%" noshade align="center">
+  <br>
+  <dl> </dl>
+  <dt><strong>* <kbd>-X 0...7</kbd><a name="Xquant">&nbsp;&nbsp;&nbsp;&nbsp;change 
+    quality measure</a></strong> </dt>
+</dl>
+<dl> 
+  <dd> When LAME searches for a "good" quantization, it has to compare the actual 
+    one with the best one found so far. The comparison says which one is better, 
+    the best so far or the actual. The -X parameter selects between different 
+    approaches to make this decision, -X0 being the default mode:<br>
+    <br>
+    <b>-X0 </b><br>
+    The criterions are (in order of importance):<br>
+    * less distorted scalefactor bands<br>
+    * the sum of noise over the thresholds is lower<br>
+    * the total noise is lower<br>
+    <br>
+    <b>-X1</b><br>
+    The actual is better if the maximum noise over all scalefactor bands is less 
+    than the best so far .<br>
+    <br>
+    <b>-X2</b><br>
+    The actual is better if the total sum of noise is lower than the best so far.<br>
+    <br>
+    <b>-X3</b><br>
+    The actual is better if the total sum of noise is lower than the best so far 
+    and the maximum noise over all scalefactor bands is less than the best so 
+    far plus 2db.<br>
+    <br>
+    <b>-X4</b> <br>
+    Not yet documented.<br>
+    <br>
+    <b>-X5</b><br>
+    The criterions are (in order of importance):<br>
+    * the sum of noise over the thresholds is lower <br>
+    * the total sum of noise is lower<br>
+    <br>
+    <b>-X6</b> <br>
+    The criterions are (in order of importance):<br>
+    * the sum of noise over the thresholds is lower<br>
+    * the maximum noise over all scalefactor bands is lower<br>
+    * the total sum of noise is lower<br>
+    <br>
+    <b>-X7</b> <br>
+    The criterions are:<br>
+    * less distorted scalefactor bands<br>
+    or<br>
+    * the sum of noise over the thresholds is lower 
+</dl>
+</BODY>
+</HTML>
Index: extensions/gsdl-video/trunk/installed/cmdline/share/man/man1/ruby.1
===================================================================
--- extensions/gsdl-video/trunk/installed/cmdline/share/man/man1/ruby.1	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/cmdline/share/man/man1/ruby.1	(revision 18425)
@@ -0,0 +1,351 @@
+.\"Ruby is copyrighted by Yukihiro Matsumoto <matz@netlab.jp>.
+.Dd December 31, 2002
+.Dt RUBY(1) "" "Ruby Programmers Reference Guide"
+.\".Dt RUBY 1
+.Os UNIX
+.Sh NAME
+.Nm ruby
+.Nd Interpreted object-oriented scripting language
+.Sh SYNOPSIS
+.Nm
+.Op Fl -copyright
+.Op Fl -version
+.Op Fl Sacdlnpswvy
+.Op Fl 0 Ns Op Ar octal
+.Op Fl C Ar directory
+.Op Fl F Ar pattern
+.Op Fl I Ar directory
+.Op Fl K Ar c
+.Op Fl T Ns Op Ar level
+.Op Fl e Ar command
+.Op Fl i Ns Op Ar extension
+.Op Fl r Ar library
+.Op Fl x Ns Op Ar directory
+.Op Fl -
+.Op Ar program_file
+.Op Ar argument ...
+.Sh DESCRIPTION
+Ruby is an interpreted scripting language for quick and easy
+object-oriented programming.  It has many features to process text
+files and to do system management tasks (as in Perl).  It is simple,
+straight-forward, and extensible.
+.Pp
+If you want a language for easy object-oriented programming, or you
+don't like the Perl ugliness, or you do like the concept of LISP, but
+don't like too much parentheses, Ruby may be the language of your
+choice.
+.Sh FEATURES
+Ruby's features are as follows:
+.Bl -tag -width 6n
+.It Sy "Interpretive"
+Ruby is an interpreted language, so you don't have to recompile
+programs written in Ruby to execute them.
+.Pp
+.It Sy "Variables have no type (dynamic typing)"
+Variables in Ruby can contain data of any type.  You don't have to
+worry about variable typing.  Consequently, it has a weaker compile
+time check.
+.Pp
+.It Sy "No declaration needed"
+You can use variables in your Ruby programs without any declarations.
+Variable names denote their scope, local, global, instance, etc.
+.Pp
+.It Sy "Simple syntax"
+Ruby has a simple syntax influenced slightly from Eiffel.
+.Pp
+.It Sy "No user-level memory management"
+Ruby has automatic memory management.  Objects no longer referenced
+from anywhere are automatically collected by the garbage collector
+built into the interpreter.
+.Pp
+.It Sy "Everything is an object"
+Ruby is the purely object-oriented language, and was so since its
+creation.  Even such basic data as integers are seen as objects.
+.Pp
+.It Sy "Class, inheritance, and methods"
+Of course, as an object-oriented language, Ruby has such basic
+features like classes, inheritance, and methods.
+.Pp
+.It Sy "Singleton methods"
+Ruby has the ability to define methods for certain objects.  For
+example, you can define a press-button action for certain widget by
+defining a singleton method for the button.  Or, you can make up your
+own prototype based object system using singleton methods, if you want
+to.
+.Pp
+.It Sy "Mix-in by modules"
+Ruby intentionally does not have the multiple inheritance as it is a
+source of confusion.  Instead, Ruby has the ability to share
+implementations across the inheritance tree.  This is often called
+.Sq Mix-in .
+.Pp
+.It Sy "Iterators"
+Ruby has iterators for loop abstraction.
+.Pp
+.It Sy "Closures"
+In Ruby, you can objectify the procedure.
+.Pp
+.It Sy "Text processing and regular expression"
+Ruby has a bunch of text processing features like in Perl.
+.Pp
+.It Sy "Bignums"
+With built-in bignums, you can for example calculate factorial(400).
+.Pp
+.It Sy "Exception handling"
+As in Java(tm).
+.Pp
+.It Sy "Direct access to the OS"
+Ruby can use most
+.Ux
+system calls, often used in system programming.
+.Pp
+.It Sy "Dynamic loading"
+On most
+.Ux
+systems, you can load object files into the Ruby interpreter
+on-the-fly.
+.El
+.Pp
+.Sh OPTIONS
+Ruby interpreter accepts following command-line options (switches).
+They are quite similar to those of
+.Xr perl 1 .
+.Bl -tag -width "1234567890123" -compact
+.Pp
+.It Fl -copyright
+Prints the copyright notice.
+.Pp
+.It Fl -version
+Prints the version of Ruby interpreter.
+.Pp
+.It Fl 0 Ns Op Ar octal
+(The digit
+.Dq zero . )
+Specifies the input record separator
+.Pf ( Li "$/" )
+as an octal number. If no digit is given, the null character is taken
+as the separator.  Other switches may follow the digits.
+.Fl 00
+turns Ruby into paragraph mode.
+.Fl 0777
+makes Ruby read whole file at once as a single string since there is
+no legal character with that value.
+.Pp
+.It Fl C Ar directory
+Causes Ruby to switch to the directory.
+.Pp
+.It Fl F Ar pattern
+Specifies input field separator
+.Pf ( Li "$;" ) .
+.Pp
+.It Fl I Ar directory
+Used to tell Ruby where to load the library scripts.  Directory path
+will be added to the load-path variable
+.Pf ( Li "$:" ) .
+.Pp
+.It Fl K Ar kcode
+Specifies KANJI (Japanese) encoding.
+.Pp
+.It Fl S
+Makes Ruby use the
+.Ev PATH
+environment variable to search for script, unless if its name begins
+with a slash.  This is used to emulate
+.Li #!
+on machines that don't support it, in the following manner:
+.Bd -literal -offset indent
+#! /usr/local/bin/ruby
+# This line makes the next one a comment in Ruby \e
+  exec /usr/local/bin/ruby -S $0 $*
+.Ed
+.Pp
+.It Fl T Ns Op Ar level
+Turns on taint checks at the specified level (default 1).
+.Pp
+.It Fl a
+Turns on auto-split mode when used with
+.Fl n
+or
+.Fl p .
+In auto-split mode, Ruby executes
+.Dl $F = $_.split
+at beginning of each loop.
+.Pp
+.It Fl c
+Causes Ruby to check the syntax of the script and exit without
+executing. If there are no syntax errors, Ruby will print
+.Dq Syntax OK
+to the standard output.
+.Pp
+.It Fl d
+.It Fl -debug
+Turns on debug mode.
+.Li "$DEBUG"
+will be set to true.
+.Pp
+.It Fl e Ar command
+Specifies script from command-line while telling Ruby not to search
+the rest of arguments for a script file name.
+.Pp
+.It Fl h
+.It Fl -help
+Prints a summary of the options.
+.Pp
+.It Fl i Ar extension
+Specifies in-place-edit mode.  The extension, if specified, is added
+to old file name to make a backup copy.  For example:
+.Bd -literal -offset indent
+% echo matz > /tmp/junk
+% cat /tmp/junk
+matz
+% ruby -p -i.bak -e '$_.upcase!' /tmp/junk
+% cat /tmp/junk
+MATZ
+% cat /tmp/junk.bak
+matz
+.Ed
+.Pp
+.It Fl l
+(The lowercase letter
+.Dq ell . )
+Enables automatic line-ending processing, which means to firstly set
+.Li "$\e"
+to the value of
+.Li "$/" ,
+and secondly chops every line read using
+.Li chop! .
+.Pp
+.It Fl n
+Causes Ruby to assume the following loop around your script, which
+makes it iterate over file name arguments somewhat like
+.Nm sed
+.Fl n
+or
+.Nm awk .
+.Bd -literal -offset indent
+while gets
+  ...
+end
+.Ed
+.Pp
+.It Fl p
+Acts mostly same as -n switch, but print the value of variable
+.Li "$_"
+at the each end of the loop.  For example:
+.Bd -literal -offset indent
+% echo matz | ruby -p -e '$_.tr! "a-z", "A-Z"'
+MATZ
+.Ed
+.Pp
+.It Fl r Ar library
+Causes Ruby to load the library using require.  It is useful when using
+.Fl n
+or
+.Fl p .
+.Pp
+.It Fl s
+Enables some switch parsing for switches after script name but before
+any file name arguments (or before a
+.Fl - ) .
+Any switches found there are removed from
+.Li ARGV
+and set the corresponding variable in the script.  For example:
+.Bd -literal -offset indent
+#! /usr/local/bin/ruby -s
+# prints "true" if invoked with `-xyz' switch.
+print "true\en" if $xyz
+.Ed
+.Pp
+On some systems
+.Li "$0"
+does not always contain the full pathname, so you need the
+.Fl S
+switch to tell Ruby to search for the script if necessary.  To handle
+embedded spaces or such.  A better construct than
+.Li "$*"
+would be
+.Li ${1+"$@"} ,
+but it does not work if the script is being interpreted by
+.Xr csh 1 .
+.Pp
+.It Fl v
+.It Fl -verbose
+Enables verbose mode.  Ruby will print its version at the beginning,
+and set the variable
+.Li "$VERBOSE"
+to true.  Some methods print extra messages if this variable is true.
+If this switch is given, and no other switches are present, Ruby quits
+after printing its version.
+.Pp
+.It Fl w
+Enables verbose mode without printing version message at the
+beginning.  It sets the
+.Li "$VERBOSE"
+variable to true.
+.Pp
+.It Fl x Ns Op Ar directory
+Tells Ruby that the script is embedded in a message.  Leading garbage
+will be discarded until the first that starts with
+.Dq #!
+and contains the string,
+.Dq ruby .
+Any meaningful switches on that line will applied.  The end of script
+must be specified with either
+.Li EOF ,
+.Li "^D" ( Li "control-D" ) ,
+.Li "^Z" ( Li "control-Z" ) ,
+or reserved word
+.Li __END__ .
+If the directory name is specified, Ruby will switch to that directory
+before executing script.
+.Pp
+.It Fl y
+.It Fl -yydebug
+Turns on compiler debug mode.  Ruby will print a bunch of internal
+state messages during compiling scripts.  You don't have to specify
+this switch, unless you are going to debug the Ruby interpreter.
+.El
+.Pp
+.Sh ENVIRONMENT
+.Bl -tag -width "RUBYLIB_PREFIX" -compact
+.It Ev RUBYLIB
+A colon-separated list of directories that are added to Ruby's
+library load path
+.Pf ( Li "$:" ) . Directories from this environment variable are searched
+before the standard load path is searched.
+.Pp
+e.g.:
+.Dl RUBYLIB="$HOME/lib/ruby:$HOME/lib/rubyext"
+.Pp
+.It Ev RUBYOPT
+Additional Ruby options.
+.Pp
+e.g.
+.Dl RUBYOPT="-w -Ke"
+.Pp
+.It Ev RUBYPATH
+A colon-separated list of directories that Ruby searches for
+Ruby programs when the
+.Fl S
+flag is specified.  This variable precedes the
+.Ev PATH
+environment variable.
+.Pp
+.It Ev RUBYSHELL
+The path to the system shell command.  This environment variable is
+enabled for only mswin32, mingw32, and OS/2 platforms.  If this
+variable is not defined, Ruby refers to
+.Ev COMSPEC .
+.Pp
+.It Ev PATH
+Ruby refers to the
+.Ev PATH
+environment variable on calling Kernel#system.
+.Pp
+.It Ev RUBYLIB_PREFIX
+This variable is obsolete.
+.El
+.Pp
+.Sh AUTHORS
+Ruby is designed and implemented by
+.An Yukihiro Matsumoto Aq matz@netlab.jp .
Index: extensions/gsdl-video/trunk/installed/server/conf/lighttpd.conf
===================================================================
--- extensions/gsdl-video/trunk/installed/server/conf/lighttpd.conf	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/server/conf/lighttpd.conf	(revision 18425)
@@ -0,0 +1,327 @@
+# lighttpd configuration file
+#
+# use it as a base for lighttpd 1.0.0 and above
+#
+# $Id: lighttpd.conf,v 1.7 2004/11/03 22:26:05 weigon Exp $
+
+############ Options you really have to take care of ####################
+
+## modules to load
+# at least mod_access and mod_accesslog should be loaded
+# all other module should only be loaded if really neccesary
+# - saves some time
+# - saves memory
+server.modules              = (
+#                               "mod_rewrite",
+#                               "mod_redirect",
+#                               "mod_alias",
+                                "mod_access",
+				"mod_flv_streaming",
+#                               "mod_cml",
+#                               "mod_trigger_b4_dl",
+#                               "mod_auth",
+#                               "mod_status",
+#                               "mod_setenv",
+#                               "mod_fastcgi",
+#                               "mod_proxy",
+#                               "mod_simple_vhost",
+#                               "mod_evhost",
+#                               "mod_userdir",
+                                "mod_cgi",
+#                               "mod_compress",
+#                               "mod_ssi",
+#                               "mod_usertrack",
+#                               "mod_expire",
+#                               "mod_secdownload",
+#                               "mod_rrdtool",
+                                "mod_accesslog" )
+
+
+## a static document-root, for virtual-hosting take look at the
+## server.virtual-* options
+server.document-root        = "/research/code/gsdl-video-import/trunk/installed/server/htdocs/"
+
+## where to send error-messages to
+server.errorlog             = "/research/code/gsdl-video-import/trunk/installed/server/logs/error.log"
+
+# files to check for if .../ is requested
+index-file.names            = ( "index.php", "index.html",
+                                "index.htm", "default.htm" )
+
+## set the event-handler (read the performance section in the manual)
+# server.event-handler = "freebsd-kqueue" # needed on OS X
+
+# mimetype mapping
+mimetype.assign             = (
+  ".pdf"          =>      "application/pdf",
+  ".sig"          =>      "application/pgp-signature",
+  ".spl"          =>      "application/futuresplash",
+  ".class"        =>      "application/octet-stream",
+  ".ps"           =>      "application/postscript",
+  ".torrent"      =>      "application/x-bittorrent",
+  ".dvi"          =>      "application/x-dvi",
+  ".gz"           =>      "application/x-gzip",
+  ".pac"          =>      "application/x-ns-proxy-autoconfig",
+  ".swf"          =>      "application/x-shockwave-flash",
+  ".tar.gz"       =>      "application/x-tgz",
+  ".tgz"          =>      "application/x-tgz",
+  ".tar"          =>      "application/x-tar",
+  ".zip"          =>      "application/zip",
+  ".mp3"          =>      "audio/mpeg",
+  ".m3u"          =>      "audio/x-mpegurl",
+  ".wma"          =>      "audio/x-ms-wma",
+  ".wax"          =>      "audio/x-ms-wax",
+  ".ogg"          =>      "application/ogg",
+  ".wav"          =>      "audio/x-wav",
+  ".gif"          =>      "image/gif",
+  ".jpg"          =>      "image/jpeg",
+  ".jpeg"         =>      "image/jpeg",
+  ".png"          =>      "image/png",
+  ".xbm"          =>      "image/x-xbitmap",
+  ".xpm"          =>      "image/x-xpixmap",
+  ".xwd"          =>      "image/x-xwindowdump",
+  ".css"          =>      "text/css",
+  ".html"         =>      "text/html",
+  ".htm"          =>      "text/html",
+  ".js"           =>      "text/javascript",
+  ".asc"          =>      "text/plain",
+  ".c"            =>      "text/plain",
+  ".cpp"          =>      "text/plain",
+  ".log"          =>      "text/plain",
+  ".conf"         =>      "text/plain",
+  ".text"         =>      "text/plain",
+  ".txt"          =>      "text/plain",
+  ".dtd"          =>      "text/xml",
+  ".xml"          =>      "text/xml",
+  ".mpeg"         =>      "video/mpeg",
+  ".mpg"          =>      "video/mpeg",
+  ".mov"          =>      "video/quicktime",
+  ".qt"           =>      "video/quicktime",
+  ".avi"          =>      "video/x-msvideo",
+  ".asf"          =>      "video/x-ms-asf",
+  ".asx"          =>      "video/x-ms-asf",
+  ".wmv"          =>      "video/x-ms-wmv",
+  ".bz2"          =>      "application/x-bzip",
+  ".tbz"          =>      "application/x-bzip-compressed-tar",
+  ".tar.bz2"      =>      "application/x-bzip-compressed-tar"
+ )
+
+# Use the "Content-Type" extended attribute to obtain mime type if possible
+#mimetype.use-xattr        = "enable"
+
+
+## send a different Server: header
+## be nice and keep it at lighttpd
+# server.tag                 = "lighttpd"
+
+#### accesslog module
+accesslog.filename          = "/research/code/gsdl-video-import/trunk/installed/server/logs/access.log"
+
+## deny access the file-extensions
+#
+# ~    is for backupfiles from vi, emacs, joe, ...
+# .inc is often used for code includes which should in general not be part
+#      of the document-root
+url.access-deny             = ( "~", ".inc" )
+
+#!!!!!
+#$HTTP["url"] =~ "\.pdf$" {
+#  server.range-requests = "disable"
+#}
+
+##
+# which extensions should not be handle via static-file transfer
+#
+# .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi
+static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
+
+######### Options that are good to be but not neccesary to be changed #######
+
+## bind to port (default: 80)
+server.port                = 8081
+
+## bind to localhost (default: all interfaces)
+#server.bind                = "grisu.home.kneschke.de"
+
+## error-handler for status 404
+#server.error-handler-404   = "/error-handler.html"
+#server.error-handler-404   = "/error-handler.php"
+
+## to help the rc.scripts
+#server.pid-file            = "/var/run/lighttpd.pid"
+
+
+flv-streaming.extensions = ( ".flv" )
+
+###### virtual hosts
+##
+##  If you want name-based virtual hosting add the next three settings and load
+##  mod_simple_vhost
+##
+## document-root =
+##   virtual-server-root + virtual-server-default-host + virtual-server-docroot
+## or
+##   virtual-server-root + http-host + virtual-server-docroot
+##
+#simple-vhost.server-root   = "/home/weigon/wwwroot/servers/"
+#simple-vhost.default-host  = "grisu.home.kneschke.de"
+#simple-vhost.document-root = "/pages/"
+
+
+##
+## Format: <errorfile-prefix><status-code>.html
+## -> ..../status-404.html for 'File not found'
+#server.errorfile-prefix    = "/home/weigon/projects/lighttpd/doc/status-"
+
+## virtual directory listings
+dir-listing.activate       = "enable"
+
+## enable debugging
+#debug.log-request-header   = "enable"
+#debug.log-response-header  = "enable"
+#debug.log-request-handling = "enable"
+#debug.log-file-not-found   = "enable"
+
+### only root can use these options
+#
+# chroot() to directory (default: no chroot() )
+#server.chroot              = "/"
+
+## change uid to <uid> (default: don't care)
+#server.username            = "wwwrun"
+
+## change uid to <uid> (default: don't care)
+#server.groupname           = "wwwrun"
+
+#### compress module
+#compress.cache-dir         = "/research/code/gsdl-video-import/trunk/installed/server/cache/compress/"
+#compress.filetype          = ("text/plain", "text/html")
+
+#### proxy module
+## read proxy.txt for more info
+#proxy.server               = ( ".php" =>
+#                               ( "localhost" =>
+#                                 (
+#                                   "host" => "192.168.0.101",
+#                                   "port" => 80
+#                                 )
+#                               )
+#                             )
+
+#### fastcgi module
+## read fastcgi.txt for more info
+## for PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini
+#fastcgi.server             = ( ".php" =>
+#                               ( "localhost" =>
+#                                 (
+#                                   "socket" => "/tmp/php-fastcgi.socket",
+#                                   "bin-path" => "/usr/local/bin/php"
+#                                 )
+#                               )
+#                            )
+
+#### CGI module
+cgi.assign                 = ( ".pl"  => "/usr/bin/perl",
+                               ".cgi" => "/usr/bin/perl" )
+
+
+#### SSL engine
+#ssl.engine                 = "enable"
+#ssl.pemfile                = "server.pem"
+
+#### status module
+#status.status-url          = "/server-status"
+#status.config-url          = "/server-config"
+
+#### auth module
+## read authentication.txt for more info
+#auth.backend               = "plain"
+#auth.backend.plain.userfile = "lighttpd.user"
+#auth.backend.plain.groupfile = "lighttpd.group"
+
+#auth.backend.ldap.hostname = "localhost"
+#auth.backend.ldap.base-dn  = "dc=my-domain,dc=com"
+#auth.backend.ldap.filter   = "(uid=$)"
+
+#auth.require               = ( "/server-status" =>
+#                               (
+#                                 "method"  => "digest",
+#                                 "realm"   => "download archiv",
+#                                 "require" => "user=jan"
+#                               ),
+#                               "/server-config" =>
+#                               (
+#                                 "method"  => "digest",
+#                                 "realm"   => "download archiv",
+#                                 "require" => "valid-user"
+#                               )
+#                             )
+
+#### url handling modules (rewrite, redirect, access)
+#url.rewrite                = ( "^/$"             => "/server-status" )
+#url.redirect               = ( "^/wishlist/(.+)" => "http://www.123.org/$1" )
+#### both rewrite/redirect support back reference to regex conditional using %n
+#$HTTP["host"] =~ "^www\.(.*)" {
+#  url.redirect            = ( "^/(.*)" => "http://%1/$1" )
+#}
+
+#
+# define a pattern for the host url finding
+# %% => % sign
+# %0 => domain name + tld
+# %1 => tld
+# %2 => domain name without tld
+# %3 => subdomain 1 name
+# %4 => subdomain 2 name
+#
+#evhost.path-pattern        = "/home/storage/dev/www/%3/htdocs/"
+
+#### expire module
+#expire.url                 = ( "/buggy/" => "access 2 hours", "/asdhas/" => "access plus 1 seconds 2 minutes")
+
+#### ssi
+#ssi.extension              = ( ".shtml" )
+
+#### rrdtool
+#rrdtool.binary             = "/usr/bin/rrdtool"
+#rrdtool.db-name            = "/var/www/lighttpd.rrd"
+
+#### setenv
+#setenv.add-request-header  = ( "TRAV_ENV" => "mysql://user@host/db" )
+#setenv.add-response-header = ( "X-Secret-Message" => "42" )
+
+## for mod_trigger_b4_dl
+# trigger-before-download.gdbm-filename = "/home/weigon/testbase/trigger.db"
+# trigger-before-download.memcache-hosts = ( "127.0.0.1:11211" )
+# trigger-before-download.trigger-url = "^/trigger/"
+# trigger-before-download.download-url = "^/download/"
+# trigger-before-download.deny-url = "http://127.0.0.1/index.html"
+# trigger-before-download.trigger-timeout = 10
+
+## for mod_cml
+## don't forget to add index.cml to server.indexfiles
+# cml.extension               = ".cml"
+# cml.memcache-hosts          = ( "127.0.0.1:11211" )
+
+#### variable usage:
+## variable name without "." is auto prefixed by "var." and becomes "var.bar"
+#bar = 1
+#var.mystring = "foo"
+
+## integer add
+#bar += 1
+## string concat, with integer cast as string, result: "www.foo1.com"
+#server.name = "www." + mystring + var.bar + ".com"
+## array merge
+#index-file.names = (foo + ".php") + index-file.names
+#index-file.names += (foo + ".php")
+
+#### include
+#include /etc/lighttpd/lighttpd-inc.conf
+## same as above if you run: "lighttpd -f /etc/lighttpd/lighttpd.conf"
+#include "lighttpd-inc.conf"
+
+#### include_shell
+#include_shell "echo var.a=1"
+## the above is same as:
+#var.a=1
Index: extensions/gsdl-video/trunk/installed/server/htdocs/gsdl
===================================================================
--- extensions/gsdl-video/trunk/installed/server/htdocs/gsdl	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/server/htdocs/gsdl	(revision 18425)
@@ -0,0 +1,1 @@
+link /research/code/gsdl-svn
Index: extensions/gsdl-video/trunk/installed/server/htdocs/index.html
===================================================================
--- extensions/gsdl-video/trunk/installed/server/htdocs/index.html	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/server/htdocs/index.html	(revision 18425)
@@ -0,0 +1,13 @@
+<html>
+  <head>
+    <title>Greenstone Video Streaming Server</title>
+  </head>
+
+  <body>
+    <h3>Greenstone Video Streaming Server</h3>
+
+    <p>You are running the lighthtppd server with flash streaming enabled.</p>
+
+  </body>
+
+</html>
Index: extensions/gsdl-video/trunk/installed/server/share/man/man1/lighttpd.1
===================================================================
--- extensions/gsdl-video/trunk/installed/server/share/man/man1/lighttpd.1	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/server/share/man/man1/lighttpd.1	(revision 18425)
@@ -0,0 +1,18 @@
+.TH LIGHTTPD 1 2003-12-21
+.SH NAME
+lighttpd - a fast, secure and flexible webserver
+.SH SYNOPSIS
+lighttpd -D -f <configfile>
+.SH DESCRIPTION
+.SH FILES
+/etc/lighttpd/lighttpd.conf
+.SH CONFORMING TO
+HTTP/1.0
+HTTP/1.0
+HTTP-Authentification - Basic, Digest
+FastCGI
+CGI/1.1
+.SH SEE ALSO
+spawn-fcgi(1)
+.SH AUTHOR
+jan@kneschke.de
Index: extensions/gsdl-video/trunk/installed/server/share/man/man1/spawn-fcgi.1
===================================================================
--- extensions/gsdl-video/trunk/installed/server/share/man/man1/spawn-fcgi.1	(revision 18425)
+++ extensions/gsdl-video/trunk/installed/server/share/man/man1/spawn-fcgi.1	(revision 18425)
@@ -0,0 +1,13 @@
+.TH SPAWNFCGI 1 2003-12-21
+.SH NAME
+spawn-fcgi \- spawning FastCGI processes
+.SH SYNOPSIS
+spawn-fcgi -f <fastcgi-binary> [-p <port> | -s <socket>] [-C <num-of-php-procs>] [-c <chroot-dir>] [-u <username>] [-g <groupname>]
+spawn-fcgi -v
+spawn-fcgi -h
+.SH DESCRIPTION
+spawn-fcgi is used to spawn remote FastCGI processes.
+.SH SEE ALSO
+lighttpd(1)
+.SH AUTHOR
+jan@kneschke.de
Index: extensions/gsdl-video/trunk/lib/cascade-lib.bash
===================================================================
--- extensions/gsdl-video/trunk/lib/cascade-lib.bash	(revision 18425)
+++ extensions/gsdl-video/trunk/lib/cascade-lib.bash	(revision 18425)
@@ -0,0 +1,181 @@
+
+run_untar()
+{
+  local package=$1
+  local version=$2
+  local ext=$3
+
+  tar_args="";
+
+  if [ $ext = ".tar.gz" ] ; then
+    tar_args="xvzf"
+  elif [ $ext = ".tgz" ] ; then
+    tar_args="xvzf"
+  elif [ $ext = ".tar.bz2" ] ; then
+    tar_args="xvjf"
+  elif [ $ext = ".tar.bz" ] ; then
+    tar_args="xvjf"
+  elif [ $ext = ".tar" ] ; then
+    tar_args="xvf"
+  else 
+    echo "Warning: Unrecognized extension: $ext"
+    echo "Assuming tarred, gzipped file"
+    tar_args="xvjf"
+  fi
+
+
+  echo tar $tar_args $package$version$ext 
+  tar $tar_args $package$version$ext
+
+  if [ $? != 0 ] ; then
+    echo "      Error encountered running *untar* stage of $progname"
+    exit 1
+  fi
+}
+
+opt_run_tarclean()
+{
+  local type=$1
+  local package=$2
+  local version=$3
+
+  if [ $type = "1" ] ; then
+
+    local dir=$package$version
+    if [ -d $dir ] ; then
+      echo /bin/rm -rf $dir
+      /bin/rm -rf $dir
+
+      if [ $? != 0 ] ; then
+        echo "      Error encountered running *tarclean* stage of $progname"
+        exit 1
+      fi
+    else 
+      echo "Unable to find directory $dir"
+    fi
+  fi
+}
+
+opt_run_untar()
+{
+  local force_untar=$1
+  local auto_untar=$2
+  local package=$3
+  local version=$4
+
+  local ext="";
+
+  if [ ! -z "$5" ] ; then
+    ext=$5
+  else 
+    ext=".tar.gz"
+  fi
+
+  if [ $force_untar = "1" ] ; then
+    run_untar $package $version $ext
+  elif [ $auto_config = "1" ] ; then
+    if [ -d $package$version ] ; then
+      echo "Found untarred version of $package$version$ext => no need to untar"
+    else
+      run_untar $package $version $ext
+    fi
+  fi
+}
+
+
+opt_run_configure()
+{
+  local force_config=$1
+  local auto_config=$2
+  local package=$3
+  local version=$4
+  local prefix=$5
+  local opt_args="";
+
+  if [ ! -z "$6" ] ; then
+    opt_args=$6
+  fi
+
+  if [ $force_config = "1" ] ; then
+    echo "[pushd $package$version]"
+    ( cd $package$version ; \
+      echo ./configure --prefix="$prefix" $opt_args ; \
+      ./configure --prefix="$prefix" $opt_args )
+    if [ $? != 0 ] ; then
+        echo "      Error encountered running *configure* stage of $progname"
+        exit 1
+    fi
+    echo "[popd]"
+  else
+    if [ $auto_config = "1" ] ; then
+      echo "Found top-level for ${progname%.*} => no need to run ./configure"
+    fi
+  fi
+}
+
+
+opt_run_make()
+{
+  local type=$1
+  local package=$2
+  local version=$3
+  local opt_target=""
+
+  if [ ! -z "$4" ] ; then
+    opt_target=$4
+  fi
+
+  if [ $type = "1" ] ; then
+    ( cd $package$version ; \
+      make $opt_target)
+
+    if [ $? != 0 ] ; then
+        echo "      Error encountered running *make $target* stage of $progname"
+        exit 1
+    fi
+  fi
+}
+
+
+
+force_untar=0
+auto_untar=0
+
+force_config=0
+auto_config=0
+
+compile=0
+install=0
+clean=0
+distclean=0
+tarclean=0
+
+if [ $# -gt 0 ] ; then
+  for cmd in $* ; do
+    echo $cmd
+    if   [ $cmd = "untar" ] ;     then force_untar=1
+    elif [ $cmd = "configure" ] ; then force_config=1
+    elif [ $cmd = "compile" ]   ; then compile=1
+    elif [ $cmd = "install" ]   ; then install=1  
+    elif [ $cmd = "clean" ]     ; then clean=1  
+    elif [ $cmd = "distclean" ] ; then distclean=1
+    elif [ $cmd = "tarclean" ] ;  then tarclean=1
+    fi
+  done
+else
+  # defaults
+  auto_untar=1
+  auto_config=1
+  compile=1
+  install=1
+  clean=0
+  distclean=0
+  tarclean=0
+fi
+
+if [ $auto_config = "1" ] ; then
+  if [ ! -e $package$version/Makefile ] ; then
+    force_config=1
+  fi
+fi
+
Index: extensions/gsdl-video/trunk/packages/CASCADE-MAKE.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/CASCADE-MAKE.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/CASCADE-MAKE.sh	(revision 18425)
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+dirlist="cmdline server"
+if [ -e devel ] ; then
+  dirlist="$dirlist devel"
+fi
+
+for d in $dirlist ; do
+  echo "  Running $d/CASCADE-MAKE.sh $*"
+
+  (cd $d; ./CASCADE-MAKE.sh $*)
+
+  if [ $? != 0 ] ; then
+    echo "  Error encountered running $d/CASCADE-MAKE.sh"
+    exit 1
+  fi
+done
+
Index: extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE.sh	(revision 18425)
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+
+for d in A52DEC LAME FAAC FAAD2 FFMPEG RUBY FLVTOOL2 LIBJPEG ; do
+  echo "    Running CASCADE-MAKE/$d.sh $*"
+
+  ./CASCADE-MAKE/$d.sh $*
+
+  if [ $? != 0 ] ; then
+    echo "  Error encountered running CASCADE-MAKE/$d.sh"
+    exit 1
+  fi
+done
Index: extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/A52DEC.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/A52DEC.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/A52DEC.sh	(revision 18425)
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+package=a52dec
+version=-0.7.4
+
+progname=$0
+
+source ../../bin/script/test-setup.bash
+source ../../lib/cascade-lib.bash
+
+prefix=$GEXTVIDEO_INSTALLED/cmdline
+
+
+opt_run_untar $force_untar $auto_untar $package $version
+opt_run_configure $force_config $auto_config $package $version "$prefix"
+
+opt_run_make $compile   $package $version
+opt_run_make $install   $package $version "install"
+opt_run_make $clean     $package $version "clean"
+opt_run_make $distclean $package $version "distclean"
+
+opt_run_tarclean $tarclean $package $version
+
+
Index: extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FAAC.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FAAC.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FAAC.sh	(revision 18425)
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+package=faac
+version=-1.26
+
+progname=$0
+
+source ../../bin/script/test-setup.bash
+source ../../lib/cascade-lib.bash
+
+prefix=$GEXTVIDEO_INSTALLED/cmdline
+
+
+if [ $force_configure ] ; then
+  echo "*****"
+  echo "Assuming you have untarred faac-1.25.tar.gz and run 'dos2unix' on *.in"
+  echo "*****"
+  sleep 3
+fi
+
+opt_run_untar $force_untar $auto_untar $package $version
+if [ -d $package ] ; then
+  echo "Moving $package -> $package$version"
+  /bin/mv $package $package$version
+fi
+
+
+# Need own customized configure
+if [ $force_config = "1" ] ; then
+  echo "[pushd $package$version]"
+  ( cd $package$version ; \
+    ./bootstrap
+    echo ./configure --prefix=$prefix --with-mp4v2 ; \
+    ./configure --prefix=$prefix --with-mp4v2 )
+  if [ $? != 0 ] ; then
+      echo "      Error encountered running *configure* stage of $progname"
+      exit 1
+  fi
+  echo "[popd]"
+else
+  if [ $auto_config = "1" ] ; then
+    echo "Found top-level for ${progname%.*} => no need to run ./configure"
+  fi
+fi
+
+
+#opt_run_configure $force_config $auto_config $package $version "$prefix" \
+#        --with-mp4v2
+
+opt_run_make $compile   $package $version
+opt_run_make $install   $package $version "install"
+opt_run_make $clean     $package $version "clean"
+opt_run_make $distclean $package $version "distclean"
+
+opt_run_tarclean $tarclean $package $version
+
+
+
Index: extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FAAD2.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FAAD2.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FAAD2.sh	(revision 18425)
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+package=faad2
+version=-2.6.1
+
+progname=$0
+
+source ../../bin/script/test-setup.bash
+source ../../lib/cascade-lib.bash
+
+prefix=$GEXTVIDEO_INSTALLED/cmdline
+
+
+opt_run_untar $force_untar $auto_untar $package $version
+if [ -d $package ] ; then
+  echo "Moving $package -> $package$version"
+  /bin/mv $package $package$version
+fi
+
+
+# Need own customized configure
+if [ $force_config = "1" ] ; then
+  echo "[pushd $package$version]"
+  ( cd $package$version ; \
+    autoreconf -vif
+    echo ./configure --prefix=$prefix --with-mp4v2 ; \
+    ./configure --prefix=$prefix --with-mp4v2 )
+  if [ $? != 0 ] ; then
+      echo "      Error encountered running *configure* stage of $progname"
+      exit 1
+  fi
+  echo "[popd]"
+else
+  if [ $auto_config = "1" ] ; then
+    echo "Found top-level for ${progname%.*} => no need to run ./configure"
+  fi
+fi
+
+opt_run_make $compile   $package $version
+opt_run_make $install   $package $version "install"
+opt_run_make $clean     $package $version "clean"
+opt_run_make $distclean $package $version "distclean"
+
+opt_run_tarclean $tarclean $package $version
+
+
+
Index: extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FFKEYFRAME.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FFKEYFRAME.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FFKEYFRAME.sh	(revision 18425)
@@ -0,0 +1,57 @@
+#!/bin/bash
+
+package=ffkeyframe
+version=-0.1
+
+progname=$0
+
+source ../../bin/script/test-setup.bash
+source ../../lib/cascade-lib.bash
+
+prefix=$GEXTVIDEO_INSTALLED/cmdline
+
+opt_run_untar $force_untar $auto_untar $package $version
+
+### opt_run_configure $force_config $auto_config $package $version "$prefix"
+
+### opt_run_make $compile   $package $version
+### opt_run_make $install   $package $version "install"
+
+
+
+
+
+#( cd ffkeyframe ; \
+#  ./configure --prefix=$GEXTVIDEO_INSTALLED/cmdline --enable-shared --enable-static --enable-swscaler --enable-libmp3lame --enable-liba52 --enable-gpl --enable-libogg --enable-libvorbis --enable-libfaac --enable-libfaad --extra-ldflags=-L$GEXTVIDEO_INSTALLED/cmdline/lib/ --extra-cflags=-I$GEXTVIDEO_INSTALLED/cmdline/include )
+#
+#if [ $? != 0 ] ; then
+#    echo "      Error encountered running *configure* stage of $progname"
+#    exit 1
+#fi
+
+if [ $compile = "1" ] ; then
+  ( cd $package$version ; \
+    make -I ../ffmpeg-jul21-2007 allhive)
+
+  if [ $? != 0 ] ; then
+      echo "      Error encountered running *make* stage of $progname"
+      exit 1
+  fi
+fi
+
+
+if [ $install = "1" ] ; then
+  ( cd $package$version ; \
+    make -I ../ffmpeg-jul21-2007 install-hive )
+
+  if [ $? != 0 ] ; then
+      echo "      Error encountered running *install* stage of $progname"
+      exit 1
+  fi
+fi
+
+
+opt_run_make $clean     $package $version "hiveclean"
+opt_run_make $distclean $package $version "hivedistclean"
+
+opt_run_tarclean $tarclean $package $version
Index: extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FFMPEG.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FFMPEG.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FFMPEG.sh	(revision 18425)
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+package=ffmpeg
+
+# If changing this version number, don't forget to update FFKEYFRAME.sh
+version=-jul21-2007
+
+
+
+progname=$0
+
+source ../../bin/script/test-setup.bash
+source ../../lib/cascade-lib.bash
+
+prefix=$GEXTVIDEO_INSTALLED/cmdline
+
+opt_run_untar $force_untar $auto_untar $package $version
+if [ -d $package ] ; then
+  echo "Moving $package -> $package$version"
+  /bin/mv $package $package$version
+fi
+
+opt_run_configure $force_config $auto_config $package $version "$prefix" \
+     "--enable-shared --enable-static --enable-swscaler \
+      --enable-libmp3lame --enable-liba52 --enable-gpl \
+      --enable-libogg --enable-libvorbis \
+      --enable-libfaac --enable-libfaad \
+      --extra-ldflags=-L$prefix/lib/ \
+      --extra-cflags=-I$prefix/include"
+
+
+opt_run_make $compile   $package $version
+opt_run_make $install   $package $version "install"
+opt_run_make $clean     $package $version "clean"
+opt_run_make $distclean $package $version "distclean"
+
+opt_run_tarclean $tarclean $package $version
+
+
Index: extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FLVTOOL2.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FLVTOOL2.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/FLVTOOL2.sh	(revision 18425)
@@ -0,0 +1,96 @@
+#!/bin/bash
+
+package=flvtool2
+version=-1.0.6
+
+progname=$0
+
+source ../../bin/script/test-setup.bash
+source ../../lib/cascade-lib.bash
+
+prefix=$GEXTVIDEO_INSTALLED/cmdline
+
+
+opt_run_untar $force_untar $auto_untar $package $version ".tgz"
+
+
+
+if [ -d $package$version ] ; then
+  echo "****"
+  echo "* Always (for now) have it run configure stage for ruby"
+  echo "****"
+
+
+  ( echo "[pushd $package$version]"a ; \
+    cd $package$version ; \
+    ruby setup.rb config --prefix=$prefix )
+
+    if [ $? != 0 ] ; then
+        echo "      Error encountered running *config* stage of $progname"
+        exit 1
+    fi
+    echo "[popd]"
+fi
+
+
+if [ $compile = "1" ] ; then
+  ( echo "[pushd $package$version]" ; \
+    cd $package$version ; \
+    ruby setup.rb setup )
+
+  if [ $? != 0 ] ; then
+      echo "      Error encountered running *setup/compile* stage of $progname"
+      exit 1
+  fi
+  echo "[popd]"
+
+fi
+
+
+if [ $install = "1" ] ; then
+  ( echo "[pushd $package$version]" ; \
+    cd $package$version ; \
+    ruby setup.rb install )
+
+  if [ $? != 0 ] ; then
+      echo "      Error encountered running *install* stage of $progname"
+      exit 1
+  fi
+  echo "[popd]"
+fi
+
+# What are the equivalent calls for clean and distclean ???
+
+#opt_run_make $clean     $package $version "clean"
+
+# Does this make any sense?
+if [ $clean = "XXX" ] ; then
+  ( echo "[pushd $package$version]" ; \
+    cd $package$version ; \
+    ruby setup.rb clean )
+
+  if [ $? != 0 ] ; then
+      echo "      Error encountered running *install* stage of $progname"
+      exit 1
+  fi
+  echo "[popd]"
+fi
+
+
+#opt_run_make $distclean $package $version "distclean"
+
+# Does this make any sense???
+
+if [ $distclean = "XXX" ] ; then
+  ( echo "[pushd $package$version]" ; \
+    cd $package$version ; \
+    ruby setup.rb distclean )
+
+  if [ $? != 0 ] ; then
+      echo "      Error encountered running *install* stage of $progname"
+      exit 1
+  fi
+  echo "[popd]"
+fi
+
+opt_run_tarclean $tarclean $package $version
Index: extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/LAME.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/LAME.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/LAME.sh	(revision 18425)
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+package=lame
+version=-3.97
+
+progname=$0
+
+source ../../bin/script/test-setup.bash
+source ../../lib/cascade-lib.bash
+
+prefix=$GEXTVIDEO_INSTALLED/cmdline
+
+opt_run_untar $force_untar $auto_untar $package $version
+opt_run_configure $force_config $auto_config $package $version "$prefix"
+
+opt_run_make $compile   $package $version
+opt_run_make $install   $package $version "install"
+opt_run_make $clean     $package $version "clean"
+opt_run_make $distclean $package $version "distclean"
+
+opt_run_tarclean $tarclean $package $version
+
+
+
Index: extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/LIBJPEG.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/LIBJPEG.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/LIBJPEG.sh	(revision 18425)
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+package=jpeg
+version=-6b
+
+progname=$0
+
+source ../../bin/script/test-setup.bash
+source ../../lib/cascade-lib.bash
+
+prefix=$GEXTVIDEO_INSTALLED/cmdline
+
+
+opt_run_untar $force_untar $auto_untar $package $version
+opt_run_configure $force_config $auto_config $package $version "$prefix" \
+        --enable-static
+
+opt_run_make $compile   $package $version
+opt_run_make $install   $package $version "install-lib"
+opt_run_make $clean     $package $version "clean"
+opt_run_make $distclean $package $version "distclean"
+
+opt_run_tarclean $tarclean $package $version
+
Index: extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/RUBY.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/RUBY.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/cmdline/CASCADE-MAKE/RUBY.sh	(revision 18425)
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+package=ruby
+version=-1.8.6
+
+progname=$0
+
+source ../../bin/script/test-setup.bash
+source ../../lib/cascade-lib.bash
+
+prefix=$GEXTVIDEO_INSTALLED/cmdline
+
+opt_run_untar $force_untar $auto_untar $package $version
+opt_run_configure $force_config $auto_config $package $version "$prefix"
+
+opt_run_make $compile   $package $version
+opt_run_make $install   $package $version "install"
+opt_run_make $clean     $package $version "clean"
+opt_run_make $distclean $package $version "distclean"
+
+opt_run_tarclean $tarclean $package $version
+
Index: extensions/gsdl-video/trunk/packages/cmdline/jpeg-6b.tar.gz
===================================================================
--- extensions/gsdl-video/trunk/packages/cmdline/jpeg-6b.tar.gz	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/cmdline/jpeg-6b.tar.gz	(revision 18425)
@@ -0,0 +1,1 @@
+link jpegsrc.v6b.tar.gz
Index: extensions/gsdl-video/trunk/packages/server/CASCADE-MAKE.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/server/CASCADE-MAKE.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/server/CASCADE-MAKE.sh	(revision 18425)
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+
+for d in LIGHTTPD GSLIGHTTPD ; do
+  echo "    Running CASCADE-MAKE/$d.sh $*"
+
+  ./CASCADE-MAKE/$d.sh $*
+
+  if [ $? != 0 ] ; then
+    echo "  Error encountered running CASCADE-MAKE/$d.sh"
+    exit 1
+  fi
+done
Index: extensions/gsdl-video/trunk/packages/server/CASCADE-MAKE/GSLIGHTTPD.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/server/CASCADE-MAKE/GSLIGHTTPD.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/server/CASCADE-MAKE/GSLIGHTTPD.sh	(revision 18425)
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+progname=$0
+
+source ../../bin/script/test-setup.bash
+source ../../lib/cascade-lib.bash
+
+prefix=$GEXTVIDEO_INSTALLED/server
+
+
+# Ensure that the necessary directories exist within the 'installed' area
+
+
+for d in logs htdocs conf ; do
+  if [ ! -e $prefix/$d ] ; then
+    echo "Creating $prefix/$d"
+    mkdir $prefix/$d
+  fi
+done
+
+# Install necessary config files to work with Greenstone
+
+gsvidinstalled=$prefix
+
+( cd gslighttpd ; \
+  cat lighttpd.conf.in \
+  | sed "s%@GSVIDINSTALLED@%$gsvidinstalled%g" \
+  > $prefix/conf/lighttpd.conf )
+
+if [ $? != 0 ] ; then
+    echo "      Error encountered running *customise install* stage of GSLIGHTTPD.sh"
+    exit 1
+fi
+
+
+( cd gslighttpd ; \
+  /bin/cp index.html $prefix/htdocs/. )
+
+if [ $? != 0 ] ; then
+    echo "      Error encountered running *customise install* stage of GSLIGHTTPD.sh"
+    exit 1
+fi
+
Index: extensions/gsdl-video/trunk/packages/server/CASCADE-MAKE/LIGHTTPD.sh
===================================================================
--- extensions/gsdl-video/trunk/packages/server/CASCADE-MAKE/LIGHTTPD.sh	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/server/CASCADE-MAKE/LIGHTTPD.sh	(revision 18425)
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+package=lighttpd
+version=-1.4.15
+
+progname=$0
+
+source ../../bin/script/test-setup.bash
+source ../../lib/cascade-lib.bash
+
+prefix=$GEXTVIDEO_INSTALLED/server
+
+
+opt_run_untar $force_untar $auto_untar $package $version
+opt_run_configure $force_config $auto_config $package $version "$prefix"
+
+opt_run_make $compile   $package $version
+opt_run_make $install   $package $version "install"
+opt_run_make $clean     $package $version "clean"
+opt_run_make $distclean $package $version "distclean"
+
+opt_run_tarclean $tarclean $package $version
Index: extensions/gsdl-video/trunk/packages/server/gslighttpd/index.html
===================================================================
--- extensions/gsdl-video/trunk/packages/server/gslighttpd/index.html	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/server/gslighttpd/index.html	(revision 18425)
@@ -0,0 +1,13 @@
+<html>
+  <head>
+    <title>Greenstone Video Streaming Server</title>
+  </head>
+
+  <body>
+    <h3>Greenstone Video Streaming Server</h3>
+
+    <p>You are running the lighthtppd server with flash streaming enabled.</p>
+
+  </body>
+
+</html>
Index: extensions/gsdl-video/trunk/packages/server/gslighttpd/lighttpd.conf.in
===================================================================
--- extensions/gsdl-video/trunk/packages/server/gslighttpd/lighttpd.conf.in	(revision 18425)
+++ extensions/gsdl-video/trunk/packages/server/gslighttpd/lighttpd.conf.in	(revision 18425)
@@ -0,0 +1,327 @@
+# lighttpd configuration file
+#
+# use it as a base for lighttpd 1.0.0 and above
+#
+# $Id: lighttpd.conf,v 1.7 2004/11/03 22:26:05 weigon Exp $
+
+############ Options you really have to take care of ####################
+
+## modules to load
+# at least mod_access and mod_accesslog should be loaded
+# all other module should only be loaded if really neccesary
+# - saves some time
+# - saves memory
+server.modules              = (
+#                               "mod_rewrite",
+#                               "mod_redirect",
+#                               "mod_alias",
+                                "mod_access",
+				"mod_flv_streaming",
+#                               "mod_cml",
+#                               "mod_trigger_b4_dl",
+#                               "mod_auth",
+#                               "mod_status",
+#                               "mod_setenv",
+#                               "mod_fastcgi",
+#                               "mod_proxy",
+#                               "mod_simple_vhost",
+#                               "mod_evhost",
+#                               "mod_userdir",
+                                "mod_cgi",
+#                               "mod_compress",
+#                               "mod_ssi",
+#                               "mod_usertrack",
+#                               "mod_expire",
+#                               "mod_secdownload",
+#                               "mod_rrdtool",
+                                "mod_accesslog" )
+
+
+## a static document-root, for virtual-hosting take look at the
+## server.virtual-* options
+server.document-root        = "@GSVIDINSTALLED@/htdocs/"
+
+## where to send error-messages to
+server.errorlog             = "@GSVIDINSTALLED@/logs/error.log"
+
+# files to check for if .../ is requested
+index-file.names            = ( "index.php", "index.html",
+                                "index.htm", "default.htm" )
+
+## set the event-handler (read the performance section in the manual)
+# server.event-handler = "freebsd-kqueue" # needed on OS X
+
+# mimetype mapping
+mimetype.assign             = (
+  ".pdf"          =>      "application/pdf",
+  ".sig"          =>      "application/pgp-signature",
+  ".spl"          =>      "application/futuresplash",
+  ".class"        =>      "application/octet-stream",
+  ".ps"           =>      "application/postscript",
+  ".torrent"      =>      "application/x-bittorrent",
+  ".dvi"          =>      "application/x-dvi",
+  ".gz"           =>      "application/x-gzip",
+  ".pac"          =>      "application/x-ns-proxy-autoconfig",
+  ".swf"          =>      "application/x-shockwave-flash",
+  ".tar.gz"       =>      "application/x-tgz",
+  ".tgz"          =>      "application/x-tgz",
+  ".tar"          =>      "application/x-tar",
+  ".zip"          =>      "application/zip",
+  ".mp3"          =>      "audio/mpeg",
+  ".m3u"          =>      "audio/x-mpegurl",
+  ".wma"          =>      "audio/x-ms-wma",
+  ".wax"          =>      "audio/x-ms-wax",
+  ".ogg"          =>      "application/ogg",
+  ".wav"          =>      "audio/x-wav",
+  ".gif"          =>      "image/gif",
+  ".jpg"          =>      "image/jpeg",
+  ".jpeg"         =>      "image/jpeg",
+  ".png"          =>      "image/png",
+  ".xbm"          =>      "image/x-xbitmap",
+  ".xpm"          =>      "image/x-xpixmap",
+  ".xwd"          =>      "image/x-xwindowdump",
+  ".css"          =>      "text/css",
+  ".html"         =>      "text/html",
+  ".htm"          =>      "text/html",
+  ".js"           =>      "text/javascript",
+  ".asc"          =>      "text/plain",
+  ".c"            =>      "text/plain",
+  ".cpp"          =>      "text/plain",
+  ".log"          =>      "text/plain",
+  ".conf"         =>      "text/plain",
+  ".text"         =>      "text/plain",
+  ".txt"          =>      "text/plain",
+  ".dtd"          =>      "text/xml",
+  ".xml"          =>      "text/xml",
+  ".mpeg"         =>      "video/mpeg",
+  ".mpg"          =>      "video/mpeg",
+  ".mov"          =>      "video/quicktime",
+  ".qt"           =>      "video/quicktime",
+  ".avi"          =>      "video/x-msvideo",
+  ".asf"          =>      "video/x-ms-asf",
+  ".asx"          =>      "video/x-ms-asf",
+  ".wmv"          =>      "video/x-ms-wmv",
+  ".bz2"          =>      "application/x-bzip",
+  ".tbz"          =>      "application/x-bzip-compressed-tar",
+  ".tar.bz2"      =>      "application/x-bzip-compressed-tar"
+ )
+
+# Use the "Content-Type" extended attribute to obtain mime type if possible
+#mimetype.use-xattr        = "enable"
+
+
+## send a different Server: header
+## be nice and keep it at lighttpd
+# server.tag                 = "lighttpd"
+
+#### accesslog module
+accesslog.filename          = "@GSVIDINSTALLED@/logs/access.log"
+
+## deny access the file-extensions
+#
+# ~    is for backupfiles from vi, emacs, joe, ...
+# .inc is often used for code includes which should in general not be part
+#      of the document-root
+url.access-deny             = ( "~", ".inc" )
+
+#!!!!!
+#$HTTP["url"] =~ "\.pdf$" {
+#  server.range-requests = "disable"
+#}
+
+##
+# which extensions should not be handle via static-file transfer
+#
+# .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi
+static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
+
+######### Options that are good to be but not neccesary to be changed #######
+
+## bind to port (default: 80)
+server.port                = 8081
+
+## bind to localhost (default: all interfaces)
+#server.bind                = "grisu.home.kneschke.de"
+
+## error-handler for status 404
+#server.error-handler-404   = "/error-handler.html"
+#server.error-handler-404   = "/error-handler.php"
+
+## to help the rc.scripts
+#server.pid-file            = "/var/run/lighttpd.pid"
+
+
+flv-streaming.extensions = ( ".flv" )
+
+###### virtual hosts
+##
+##  If you want name-based virtual hosting add the next three settings and load
+##  mod_simple_vhost
+##
+## document-root =
+##   virtual-server-root + virtual-server-default-host + virtual-server-docroot
+## or
+##   virtual-server-root + http-host + virtual-server-docroot
+##
+#simple-vhost.server-root   = "/home/weigon/wwwroot/servers/"
+#simple-vhost.default-host  = "grisu.home.kneschke.de"
+#simple-vhost.document-root = "/pages/"
+
+
+##
+## Format: <errorfile-prefix><status-code>.html
+## -> ..../status-404.html for 'File not found'
+#server.errorfile-prefix    = "/home/weigon/projects/lighttpd/doc/status-"
+
+## virtual directory listings
+dir-listing.activate       = "enable"
+
+## enable debugging
+#debug.log-request-header   = "enable"
+#debug.log-response-header  = "enable"
+#debug.log-request-handling = "enable"
+#debug.log-file-not-found   = "enable"
+
+### only root can use these options
+#
+# chroot() to directory (default: no chroot() )
+#server.chroot              = "/"
+
+## change uid to <uid> (default: don't care)
+#server.username            = "wwwrun"
+
+## change uid to <uid> (default: don't care)
+#server.groupname           = "wwwrun"
+
+#### compress module
+#compress.cache-dir         = "@GSVIDINSTALLED@/cache/compress/"
+#compress.filetype          = ("text/plain", "text/html")
+
+#### proxy module
+## read proxy.txt for more info
+#proxy.server               = ( ".php" =>
+#                               ( "localhost" =>
+#                                 (
+#                                   "host" => "192.168.0.101",
+#                                   "port" => 80
+#                                 )
+#                               )
+#                             )
+
+#### fastcgi module
+## read fastcgi.txt for more info
+## for PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini
+#fastcgi.server             = ( ".php" =>
+#                               ( "localhost" =>
+#                                 (
+#                                   "socket" => "/tmp/php-fastcgi.socket",
+#                                   "bin-path" => "/usr/local/bin/php"
+#                                 )
+#                               )
+#                            )
+
+#### CGI module
+cgi.assign                 = ( ".pl"  => "/usr/bin/perl",
+                               ".cgi" => "/usr/bin/perl" )
+
+
+#### SSL engine
+#ssl.engine                 = "enable"
+#ssl.pemfile                = "server.pem"
+
+#### status module
+#status.status-url          = "/server-status"
+#status.config-url          = "/server-config"
+
+#### auth module
+## read authentication.txt for more info
+#auth.backend               = "plain"
+#auth.backend.plain.userfile = "lighttpd.user"
+#auth.backend.plain.groupfile = "lighttpd.group"
+
+#auth.backend.ldap.hostname = "localhost"
+#auth.backend.ldap.base-dn  = "dc=my-domain,dc=com"
+#auth.backend.ldap.filter   = "(uid=$)"
+
+#auth.require               = ( "/server-status" =>
+#                               (
+#                                 "method"  => "digest",
+#                                 "realm"   => "download archiv",
+#                                 "require" => "user=jan"
+#                               ),
+#                               "/server-config" =>
+#                               (
+#                                 "method"  => "digest",
+#                                 "realm"   => "download archiv",
+#                                 "require" => "valid-user"
+#                               )
+#                             )
+
+#### url handling modules (rewrite, redirect, access)
+#url.rewrite                = ( "^/$"             => "/server-status" )
+#url.redirect               = ( "^/wishlist/(.+)" => "http://www.123.org/$1" )
+#### both rewrite/redirect support back reference to regex conditional using %n
+#$HTTP["host"] =~ "^www\.(.*)" {
+#  url.redirect            = ( "^/(.*)" => "http://%1/$1" )
+#}
+
+#
+# define a pattern for the host url finding
+# %% => % sign
+# %0 => domain name + tld
+# %1 => tld
+# %2 => domain name without tld
+# %3 => subdomain 1 name
+# %4 => subdomain 2 name
+#
+#evhost.path-pattern        = "/home/storage/dev/www/%3/htdocs/"
+
+#### expire module
+#expire.url                 = ( "/buggy/" => "access 2 hours", "/asdhas/" => "access plus 1 seconds 2 minutes")
+
+#### ssi
+#ssi.extension              = ( ".shtml" )
+
+#### rrdtool
+#rrdtool.binary             = "/usr/bin/rrdtool"
+#rrdtool.db-name            = "/var/www/lighttpd.rrd"
+
+#### setenv
+#setenv.add-request-header  = ( "TRAV_ENV" => "mysql://user@host/db" )
+#setenv.add-response-header = ( "X-Secret-Message" => "42" )
+
+## for mod_trigger_b4_dl
+# trigger-before-download.gdbm-filename = "/home/weigon/testbase/trigger.db"
+# trigger-before-download.memcache-hosts = ( "127.0.0.1:11211" )
+# trigger-before-download.trigger-url = "^/trigger/"
+# trigger-before-download.download-url = "^/download/"
+# trigger-before-download.deny-url = "http://127.0.0.1/index.html"
+# trigger-before-download.trigger-timeout = 10
+
+## for mod_cml
+## don't forget to add index.cml to server.indexfiles
+# cml.extension               = ".cml"
+# cml.memcache-hosts          = ( "127.0.0.1:11211" )
+
+#### variable usage:
+## variable name without "." is auto prefixed by "var." and becomes "var.bar"
+#bar = 1
+#var.mystring = "foo"
+
+## integer add
+#bar += 1
+## string concat, with integer cast as string, result: "www.foo1.com"
+#server.name = "www." + mystring + var.bar + ".com"
+## array merge
+#index-file.names = (foo + ".php") + index-file.names
+#index-file.names += (foo + ".php")
+
+#### include
+#include /etc/lighttpd/lighttpd-inc.conf
+## same as above if you run: "lighttpd -f /etc/lighttpd/lighttpd.conf"
+#include "lighttpd-inc.conf"
+
+#### include_shell
+#include_shell "echo var.a=1"
+## the above is same as:
+#var.a=1
Index: extensions/gsdl-video/trunk/perllib/plugins/TimedHTMLPlugin.pm
===================================================================
--- extensions/gsdl-video/trunk/perllib/plugins/TimedHTMLPlugin.pm	(revision 18425)
+++ extensions/gsdl-video/trunk/perllib/plugins/TimedHTMLPlugin.pm	(revision 18425)
@@ -0,0 +1,964 @@
+###########################################################################
+#
+# TimedHTMLPlug.pm -- 
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# 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.
+#
+###########################################################################
+
+
+package TimedHTMLPlugin;
+
+use videoconvert;
+
+use HTMLPlugin;
+
+sub BEGIN {
+    @TimedHTMLPlugin::ISA = ('HTMLPlugin');
+}
+
+use strict; # every perl program should have this!
+no strict 'refs'; # make an exception so we can use variables as filehandles
+
+my $arguments =
+    [ 
+      { 'name' => "video_excerpt_duration",
+	'desc' => "{VideoPlug.video_excerpt_duration}",
+	'type' => "string",
+	'reqd' => "no" }
+      ];
+
+
+
+
+my $options = { 'name'     => "TimedHTMLPlugin",
+		'desc'     => "{TimedHTMLPlugin.desc}",
+		'abstract' => "no",
+		'inherits' => "yes",
+	        'args'     => $arguments };
+
+
+sub new {
+    my ($class) = shift (@_);
+    my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
+    push(@$pluginlist, $class);
+    
+    if(defined $arguments){ push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});}
+    if(defined $options) { push(@{$hashArgOptLists->{"OptList"}},$options)};
+   
+
+    my $self = (defined $hashArgOptLists) 
+	? new HTMLPlugin($pluginlist,$inputargs,$hashArgOptLists)
+	: new HTMLPlugin($pluginlist,$inputargs);
+    
+    my $collect_dir = $ENV{'GSDLCOLLECTDIR'};
+
+    my $collect_bin = &util::filename_cat($collect_dir,"bin");
+    my $collect_script = &util::filename_cat($collect_bin,"script");
+    
+    $ENV{'PATH'} .= ":" if (defined $ENV{'PATH'});
+    $ENV{'PATH'} .= "$collect_bin:$collect_script";
+
+    return bless $self, $class;
+}
+
+sub html_to_text
+{
+    my ($self, $text) = @_;
+
+    $text =~ s/<\/?[^>]*>//g;
+
+    $text =~ s/&nbsp;/ /g;
+
+    $text =~ s/\s+/ /gs;
+    $text =~ s/^\s+//;
+    $text =~ s/\s+$//;
+
+    return $text;
+}
+
+
+sub extract_metadata_table
+{
+    my ($self, $textref) = @_;
+
+    my $metatable_store = {};
+
+    my $metatable_re = "<table([^>]*)>(.*?<p class=\"?Metadata\"?>.*?)<\\/table>";
+
+    if ($$textref =~ m/$metatable_re/gsi) {
+	my $metatable_attr = $1;
+	my $metatable_body = $2;
+
+	my @tr_list = ($metatable_body =~ m/(<tr[^>]*>.*?<\/tr>)/gsi);
+
+	my @filtered_tr_list = ();
+
+	foreach my $tr (@tr_list) {
+
+	    my $in_filtered_tr = 1;
+
+	    my @td_list = ($tr =~ m/<td[^>]*>(.*?)<\/td>/gsi);
+	    my $td_list_num = scalar(@td_list);
+	    
+	    if ($td_list_num == 2) {
+		my $meta_name  = $self->html_to_text($td_list[0]);
+		my $meta_value = $self->html_to_text($td_list[1]);
+		
+		$meta_name =~ s/\s*//g;
+		
+
+		if ($meta_value =~ m/^(\s*|\?+)$/) {
+		    $in_filtered_tr = 0;
+		}
+		else {
+		    my $meta_name_label = $meta_name;
+		    $meta_name_label =~ s/\s+//g;
+
+		    $metatable_store->{$meta_name_label} = $meta_value;
+
+		    if ($meta_name_label =~ m/^GS\./) {
+			# even though we want to store this as metadata, we
+			# don't want this going into table presented at top of document
+			$in_filtered_tr = 0; 
+		    }
+
+		}
+	    }
+	    else {
+		print STDERR "Warning: Metadata table does not consist of two cells (metadata name : metadata value)\n";
+		print STDERR "         Skipping\n";
+	    }
+
+
+	    if ($in_filtered_tr) {
+		push(@filtered_tr_list,$tr);
+	    }
+	}
+
+	my $filtered_tr_block = join("\n",@filtered_tr_list);
+	my $filtered_table = "<table$metatable_attr>$filtered_tr_block</table>";
+
+
+	### my $metatable_re = "<table[^>]*>.*?<p class=\"?Metadata\"?>.*?<\\/table>";
+
+###	print STDERR "*** filtered table = $filtered_table\n";
+
+	$$textref =~ s/$metatable_re/$filtered_table/si;
+	
+    }
+
+    return $metatable_store;
+
+}
+
+
+
+
+
+my $only_num = 0;
+my $only_limit = 100;
+
+sub hms_to_secs
+{
+    my $self = shift @_;
+    my ($hh,$mm,$ss) = @_;
+
+    return $hh*3600 + $mm*60 + $ss;
+}
+
+
+
+sub timed_event
+{
+    my $self = shift (@_);
+
+    my ($front, $tape, $hh, $mm, $ss, $back) = @_;
+
+    my $time_encoded = "$hh:$mm:$ss";
+    my $time_encoded_file = "$hh$mm$ss";
+
+    my $time_pos = $self->{'time_pos'};
+    my $time_num = scalar(@{$self->{'time_seq'}});
+
+    my $videoconvert = $self->{'videoconvert'};
+
+    # excerpt from tim_pos -> time_pos + 2;
+    my $adv_time_pos = $time_pos+2;
+    $adv_time_pos = $time_num-1 if ($adv_time_pos>=$time_num);
+
+    my $adv_time_elem = $self->{'time_seq'}->[$adv_time_pos];
+
+#    print STDERR "*** ", substr($adv_time_elem,0,800), "\n";
+
+    my ($atape,$ah,$am,$as) = ($adv_time_elem =~ m/(T\d+:) ?(\d\d):(\d\d):(\d\d)(?:\:\d\d)?/);
+
+    my $excerpt_len = undef;
+    my $time_in_secs     = $self->hms_to_secs($hh,$mm,$ss);
+
+    if (!defined $tape) {
+	if (defined $self->{'ptape'}) {
+	    $tape = $self->{'ptape'};
+	}
+	else {
+	    print STDERR "Warning: First time offset does not define tape side\n";
+	    print STDERR "         Defaulting to 1\n";
+	    $tape = "T1:";
+	}
+    }
+
+    if (!defined $atape) {
+	$atape = "T1";
+    }
+
+#    print STDERR "**** atape = $atape\n";
+#    print STDERR "*** tape = $tape\n";
+
+    if ($atape eq $tape) {
+	my $adv_time_in_secs = $self->hms_to_secs($ah,$am,$as);
+
+	$excerpt_len = $adv_time_in_secs - $time_in_secs;
+    }
+
+    my $collect_dir = $ENV{'GSDLCOLLECTDIR'};
+
+    my $media_type = $self->{'media_type'};
+    my $media_dir  = $self->{'media_dir'};
+    my $media_root = $self->{'media_root'};
+
+    my $media_base_dir = $self->{'media_base_dir'};
+
+    my $mp3_html;    
+    my $avi_html;
+
+    my $tape_num = "1";
+
+    if (defined $media_type) {
+
+	my $src_file;
+	my $src_filename;
+
+	if ($media_type eq "video") {
+	    $src_file = "$media_root\_01_$tape_num.VOB";
+	    $src_filename 
+		= &util::filename_cat($media_base_dir, $src_file);
+	}
+	elsif ($media_type =~ m/^audio$/) {
+	    $src_file = "$media_root\_Tape$tape_num.mp3";
+	    $src_filename 
+		= &util::filename_cat($media_base_dir, $src_file);
+	}
+	else {
+	    print STDERR "Warning: Unrecognised media type: $media_type\n";
+	}
+
+
+	if ($media_type eq "video") {
+
+	    # video excerpt
+
+	    my $encoded_file = "$media_dir\_$time_encoded_file.avi";
+
+	    my $ve_filename 
+		= &util::filename_cat($collect_dir,"media","video_excerpt",$encoded_file);
+
+	    if ($only_num < $only_limit) {
+		if (! -e $ve_filename) {
+		    # my $args = "-vcodec mpeg2video";
+		    my $args = "-vcodec msmpeg4";
+		    
+		    my $ve_cmd = "gsmpeg.sh -v 1 -i $src_filename $args -ss $time_encoded ";
+		    
+		    if (defined $excerpt_len) {
+			$ve_cmd .= "-t $excerpt_len ";
+		    }
+		    
+		    $ve_cmd .= $ve_filename;
+		    
+##		    print STDERR "$ve_cmd\n";
+		    
+##		    `$ve_cmd`;
+		}
+		    
+##		my $avi_url = "http://mcgonagall.cs.waikato.ac.nz:8201/gsdl/collect/hauraki2/media/video_excerpt/$media_dir\_$time_encoded_file.avi";
+		my $avi_url = "_httpprefix_/collect/hauraki2/media/video_excerpt/$media_dir\_$time_encoded_file.avi";
+		
+##		$avi_html = "<a class=\"mm\" href=\"$avi_url\"><img border=1 src=\"_httpcimages_\/video5.gif\"></a>";
+		
+		
+		## my $stream_url = "_httpstreamserver_/$local_root.asf";
+##		my $stream_url = "http://mcgonagall.cs.waikato.ac.nz:8090/$local_root.avi";
+##		$avi_html .= "<a class=\"mm\" href=\"$stream_url\">Stream</a>";
+
+
+		## $avi_html .= "<a class=\"mm\" href=\"_httpcurrentdocumentwithvplayer_\"><img border=1 src=\"_httpcimages_\/video5.gif\"></a>";
+
+		$avi_html .= "<a class=\"mm\" href=\"javascript:videoplayerseek($hh,$mm,$ss)\"><img border=1 src=\"_httpcimages_\/video5.gif\"></a>";
+
+		# save 'time-stamp' as metadata???
+		
+
+
+	    }
+	    else {
+		$avi_html = "<img src=\"_httpcimages_\/video5.gif\">";
+	    }
+	}
+
+	if ($media_type =~ m/^(video|audio)$/) {
+
+	    # audio excerpt
+#	    my $encoded_file = "$media_dir\_$time_encoded_file.mp3";
+
+#	    ## my $src_file = "$media_root\_Tape$tape_num.avi";
+
+#	    #my $src_filename 
+#	    #	= &util::filename_cat($collect_dir,"media",$media_type ,$media_dir, $src_file);
+
+#	    my $ae_filename 
+#		= &util::filename_cat($collect_dir,"media","audio_excerpt",$encoded_file);
+
+
+	    if ($only_num < $only_limit) {
+
+		$excerpt_len = 120 if (!defined $excerpt_len); #######
+
+		my ($ae_cmd,$omp3_filename,$omp3_file) 
+		    = $videoconvert->audio_excerpt_cmd($src_filename,
+						       $hh,$mm,$ss,$excerpt_len);
+		
+		my $ae_options = { @{$videoconvert->{'ffmpeg_monitor'}},
+				   'message_prefix' => "Audio Excerpt",
+				   'message' => "Generating audio excerpt: $omp3_file" }; 
+		
+		my ($ae_regenerated,$ae_result,$ae_had_error)
+		    = $videoconvert->run_cached_general_cmd($ae_cmd,$omp3_filename,$ae_options);
+
+		push(@{$self->{'mp3_excerpts'}}, { 'omp3_file' => $omp3_file, 'omp3_filename' => $omp3_filename} );
+
+	    }
+
+
+
+
+	    #    if (! -e $ae_filename) {
+	    if ($only_num < $only_limit) {
+#		if (! -e $ae_filename) {
+		    
+#		    my $args = "-acodec mp3";
+		    
+#		    ## my $src_filename = "media/video/mirth/VTS_01_1.avi";
+#		    my $ae_cmd = "gsmpeg.sh -v 1 -i $src_filename $args -ss $time_encoded ";
+		    
+#		    if (defined $excerpt_len) {
+#			$ae_cmd .= "-t $excerpt_len ";
+#		    }
+		    
+#		    $ae_cmd .= $ae_filename;
+		    		    		    
+##		    print STDERR "$ae_cmd\n";
+		    
+##		    `$ae_cmd`;
+#		}
+		
+		
+##		my $mp3_url = "http://mcgonagall.cs.waikato.ac.nz:8201/gsdl/collect/hauraki2/media/audio_excerpt/$media_dir\_$time_encoded_file.mp3";
+#		my $mp3_url = "_httpprefix_/collect/hauraki2/media/audio_excerpt/$media_dir\_$time_encoded_file.mp3";
+	
+		my ($voa_root) = ($src_file =~ m/^(.*)\..*?$/);
+	
+		my $mp3_url = "javascript:audioexcerptplay('$voa_root','$hh','$mm','$ss')";
+
+#		my $mp3_url = "_httpcollection_/index/assoc/{If}{[assocfilepath],[assocfilepath],[parent(Top):assocfilepath]}/$media_dir\_$time_encoded_file.mp3";
+
+		$mp3_html = "<a class=\"mm\" href=\"$mp3_url\"><img border=1 src=\"_httpcimages_\/audio2.gif\"></a>";
+
+#		my $baseexcerpt_url = "_httpcollection_/index/assoc/{If}{[assocfilepath],[assocfilepath],[parent(Top):assocfilepath]}";
+		
+#####		$doc_obj->add_metadata ($section, "audioexcerpturl",$mp3_url);
+		
+		
+	    }
+	    else {
+		$mp3_html = "<img src=\"_httpcimages_\/audio2.gif\">";
+		
+	    }
+	}
+    }
+    else {
+	print STDERR "Warning: no media type defined.\n";
+    }
+
+
+    $only_num++;
+
+    $self->{'time_pos'}++;
+
+    my $table = "<table width=\"100%\" cellspacing=\"1\" cellpadding=\"0\"><tr valign=\"middle\">";
+    $table .= "<td>$avi_html</td>" if (defined $avi_html);
+    $table .= "<td>$mp3_html</td>";
+    $table .= "<td>$time_encoded</td>";
+    $table .= "</tr></table>";
+
+    # my $line = "$front$avi_html&nbsp;$mp3_html&nbsp;$time_encoded$back";
+
+    my $line = "$front$table$back";
+
+    # Remember tape prefix for next call
+    $self->{'ptape'} = $tape;
+
+    return $line;
+}
+
+
+sub hyperlink_timing_info
+{
+    my ($self, $textref) = @_;
+
+    my $media_type = $self->{'media_type'};
+    my $media_dir  = $self->{'media_dir'};
+    my $media_root = $self->{'media_root'};
+
+    my $front_re = "<p class=Timing><span\\s+.*?>";
+    my $tape_re  = "T\\d+:";
+    my $tt_re = "\\d\\d";
+    my $back_re = ".*?<\\/span>";
+
+    my $time_match_re = "$front_re$tt_re:$tt_re:$tt_re$back_re(?:\:$tt_re)?";
+    # my $time_sub_re   = "($front_re)($tape_re)? ?($tt_re):($tt_re):($tt_re)(?:\:$tt_re)?($back_re)";
+
+    my $tape_match_re   = "$front_re($tape_re)? ?$tt_re:$tt_re:$tt_re(?:\:$tt_re)?$back_re";
+    my $tape_sub_re   = "($front_re)($tt_re):($tt_re):($tt_re)(?:\:$tt_re)?($back_re)";
+
+
+
+    my @time_seq = ($$textref =~ m/$time_match_re/sgi);
+
+    # artifically add tape information into all time indexes
+    my $extrapolate_tape = "";
+    my $num_seq = scalar(@time_seq);
+    for (my $i=0; $i<$num_seq; $i++) {
+	my ($curr_tape) = ($time_seq[$i] =~ m/$tape_match_re/sgi);
+	if (!defined $curr_tape) {
+	    $time_seq[$i] =~ s/$tape_sub_re/$1$extrapolate_tape$2:$3:$4$5/sgi;
+	}
+	else {
+	    if ($curr_tape ne $extrapolate_tape) {
+		$extrapolate_tape = $curr_tape;
+	    }
+	}
+    }
+
+
+    $self->{'time_seq'} = \@time_seq;
+    $self->{'time_pos'} = 0;
+
+    $$textref =~ s/(<p class=Timing><span\s+.*?>)(T\d+:)? ?(\d\d):(\d\d):(\d\d)(?:\:\d\d)?.*?(<\/span>)/$self->timed_event($1,$2,$3,$4,$5,$6)/sgie;
+
+
+    # knock out any div tags as they interfere with document broken up into sections
+    $$textref =~ s/<\/?div.*?>//gi;
+
+    # Embedded word style infomation is lost by HTMLPlug => make Question
+    # style use HTML italics
+
+    $$textref =~ s/<p class=\"Question\">(.*?)<\/p>/<p><i>$1<\/i><\/p>/gsi;
+
+}
+
+
+
+sub store_block_files
+{
+    my $self =shift (@_);
+    my ($filename_full_path, $block_hash) = @_;
+
+    # Would be better if this were tied to particular HTML docs that
+    # this plugin has processed.
+
+    # For now block all files native to DVD format
+
+    if (($filename_full_path =~ m/\.(IFO|BUP)$/)        # block info and backup-info data
+	|| ($filename_full_path =~ m/VIDEO_TS\..*?$/)   # block top-level files
+	|| ($filename_full_path =~ m/VTS_\d\d_\d\.VOB$/) # 
+	) {
+	
+	$block_hash->{'file_blocks'}->{$filename_full_path} = 1;
+    }
+}
+
+sub read_block {
+    my $self = shift (@_);  
+  
+    my ($pluginfo, $base_dir, $file, $metadata, $processor, $maxdocs, $total_count, $gli) = @_;
+
+    print STDERR "***** TimedHTMLPlugin read_block\n";
+
+    my $filename = $file;
+    $filename = &util::filename_cat ($base_dir, $file) if $base_dir =~ /\w/;
+
+    if (($filename =~ m/\.(IFO|BUP)$/)        # block info and backup-info data
+	|| ($filename =~ m/VIDEO_TS\..*?$/)   # block top-level files
+	|| ($filename =~ m/VTS_\d\d_\d\.VOB$/) # 
+	) {
+	$self->{'num_blocked'} ++;
+	return (0,undef); # blocked
+    }
+
+
+#####	|| ($filename =~ m/VTS_\d\d_0\.VOB$/) # block menu item for this track
+
+
+    if (defined $self->{'file_blocks'}->{$filename} && $self->{'file_blocks'}->{$filename} == 1){
+	$self->{'num_blocked'} ++;
+	return (0,undef); # blocked
+    }
+
+
+    if (defined $self->{'re_file_block'}) {
+	my $re_file_blocks = $self->{'re_file_block'};
+	foreach my $re_file_block (@$re_file_blocks) {
+###	    print STDERR "**** re file block: $filename =~ m $re_file_block\n";
+	    if ($filename =~ m/$re_file_block/) {
+###		print STDERR "*** blocking $filename\n";
+
+		$self->{'num_blocked'} ++;
+		return (0,undef); # blocked
+	    }
+	}
+    }
+
+
+    return $self->SUPER::read_block(@_);
+
+}
+
+
+sub read_file {
+    my $self = shift @_;
+    my ($filename, $encoding, $language, $textref) = @_;
+
+    $only_num = 0;
+
+    $self->SUPER::read_file(@_);
+
+    my $metatable_store = $self->extract_metadata_table($textref);
+    $self->{'metatable_store'} = $metatable_store;
+
+    my ($root, $dirname, $suffix)
+        = &File::Basename::fileparse($filename, "\\.[^\\.]+\$");
+    
+    # media defaults
+    my $media_type = undef;
+    my $media_dir  = $root;
+    ## my $media_root = "VTS_%02d_%02d";
+    my $media_root = "VTS";
+
+    if (defined $metatable_store->{'GS.Media'}) {
+	$media_type = $metatable_store->{'GS.Media'};
+	$media_type = lc($media_type);
+    }
+    if (defined $metatable_store->{'GS.MediaDirectory'}) {
+	$media_dir = $metatable_store->{'GS.MediaDirectory'};
+    }
+    if (defined $metatable_store->{'GS.MediaRoot'}) {
+	$media_root = $metatable_store->{'GS.MediaRoot'};
+    }
+
+    $self->{'media_type'} = $media_type;
+    $self->{'media_dir'}  = $media_dir;
+    $self->{'media_root'} = $media_root;
+
+    my $media_base_dir = &util::filename_cat($dirname,$media_dir);
+    $self->{'media_base_dir'} = $media_base_dir;
+
+    $self->{'vob_duration_info'} = &videoconvert::vob_durations($media_base_dir,"1",$self->{'outhandle'});
+
+##    $self->hyperlink_timing_info($textref);
+
+    # Convert entities to their UTF8 equivalents
+    $$textref =~ s/&(lt|gt|amp|quot|nbsp);/&z$1;/go;
+    $$textref =~ s/&([^;]+);/&ghtml::getcharequiv($1,1)/gseo;
+    $$textref =~ s/&z(lt|gt|amp|quot|nbsp);/&$1;/go;
+}
+
+
+sub streamable_video
+{
+    my $self = shift (@_);
+
+    my ($base_dir,$filename,$doc_obj,$section) = @_;
+
+    my $outhandle = $self->{'outhandle'};
+    my $verbosity = $self->{'verbosity'};
+
+    my $media_base_dir = $self->{'media_base_dir'};
+
+    #---
+    # Determine size of input video
+
+    my $collect_dir = $ENV{'GSDLCOLLECTDIR'};
+
+    my $media_type = $self->{'media_type'};
+    my $media_dir  = $self->{'media_dir'};
+    my $media_root = $self->{'media_root'};
+
+    my $tape_num = "1";
+
+    my $src_file;
+    my $src_filename;
+
+    if ($media_type eq "video") {
+	$src_file = "$media_root\_01_$tape_num.VOB";
+	$src_filename 
+	    = &util::filename_cat($media_base_dir, $src_file);
+    }
+    elsif ($media_type =~ m/^audio$/) {
+	$src_file = "$media_root\_Tape$tape_num.mp3";
+	$src_filename 
+	    = &util::filename_cat($media_base_dir, $src_file);
+    }
+    else {
+	print STDERR "Warning: Unrecognised media type: $media_type\n";
+    }
+
+    if (-e $src_filename) {
+	$self->{'file_blocks'}->{$src_filename} = 1;
+
+	my $re_file_block = $src_filename;
+	$re_file_block =~ s/_01_$tape_num.VOB$/_\\d+_\\d+.VOB\$/;
+	
+	
+	push(@{$self->{'re_file_block'}},$re_file_block);
+    }
+
+    my ($video_type, $video_width, $video_height, $video_duration, $video_size,
+	$vcodec,$vfps,$atype,$afreq,$achan,$arate) 
+	= &videoconvert::identify($src_filename, $outhandle, $verbosity);
+
+    if ($vfps eq "unknown") {
+	print $outhandle "Unknown framerate, defaulting to 25 frames per second.\n";
+	$vfps = 25;
+    }
+
+###    print STDERR "*** video duration = $video_duration\n";
+    my ($dur_hour,$dur_min,$dur_sec) 
+	= ($video_duration =~ m/(\d+):(\d+):(\d+\.\d+)/);
+    my $total_dur_secs = $dur_hour*3600 + $dur_min*60 + $dur_sec;
+
+    $self->{'video-fps'} = $vfps;
+    $self->{'num-total-frames'} = $total_dur_secs * $vfps;
+
+
+    # shorten duration prcessed for experimentation purposes
+    my $exp_duration = undef;
+
+    my $video_excerpt_duration = $self->{'video_excerpt_duration'};
+
+    print STDERR "**** video duration (secs) = $total_dur_secs\n";
+
+
+    if ((defined $video_excerpt_duration) && ($video_excerpt_duration ne "")) {
+	$exp_duration = $video_excerpt_duration;
+	my ($hh,$mm,$ss,$ms) = ($exp_duration =~ m/^(\d\d):(\d\d):(\d\d)\.?(\d\d)?/);
+	my $excerpt_dur_in_secs = $hh * 3600 + $mm * 60 + $ss;
+
+	if ($excerpt_dur_in_secs < $total_dur_secs) {
+	    $self->{'num-total-frames'} = $excerpt_dur_in_secs * $vfps; # override calculation for full length duration
+	}
+	else {
+	    # clip is already shorter than requested video excerpt duration
+	    # set exp_duration back to undefined
+	    $exp_duration = undef;
+	}
+    }
+
+    print $outhandle "TimedHTMLPlug: Preparing video files associated with $filename for HTMLPlug\n";
+
+    if (defined $exp_duration)
+    {
+	print $outhandle "Only encoding first $exp_duration of video.\n";
+	$self->{'exp_duration'} = $exp_duration;
+    }
+
+    
+    my $videoconvert 
+	= new videoconvert($base_dir,$src_filename,$verbosity,$outhandle,$exp_duration);
+    $self->{'videoconvert'} = $videoconvert;
+
+    #---
+    # Generate the Flash FLV format for streaming purposes
+
+    my $streaming_bitrate = "256k"; # used to be 192k
+    my $streaming_size    = "360"; # used to be 352 (CIF?)
+    my $streaming_achan   = "1";
+    my $streaming_arate   = "44100";
+    my $streaming_quality = "high";
+
+    #---
+    # Convert video to flash
+    #---
+    my ($stream_cmd,$oflash_filename,$oflash_file) 
+	= $videoconvert->stream_cmd($src_filename,
+				    $video_width,$video_height,
+				    $streaming_quality, $streaming_bitrate, $streaming_size,
+				    $streaming_achan, $streaming_arate);
+
+    my $streamable_options = { @{$videoconvert->{'ffmpeg_monitor'}},
+			       'message_prefix' => "Stream",
+			       'message' => "Generating streamable video: $oflash_file" }; 
+
+    my ($streamable_regenerated,$streamable_result,$streamable_had_error)
+	= $videoconvert->run_cached_general_cmd($stream_cmd,$oflash_filename,$streamable_options);
+
+    $self->{'streamable_regenerated'} = $streamable_regenerated;
+
+    if (!$streamable_had_error) {
+	#---
+	# Make video seekable
+	#---
+	my ($streamseekable_cmd,$ostreamseekable_filename) = $videoconvert->streamseekable_cmd($oflash_filename);
+	
+	my $streamseekable_options = { @{$videoconvert->{'flvtool2_monitor'}},
+				       'message_prefix' => "Stream Seekable",
+				       'message' => "Reprocessing video stream to be seekable by timeline: $oflash_file" }; 
+
+	if ($streamable_regenerated) {
+	    $videoconvert->run_general_cmd($streamseekable_cmd,$streamseekable_options);
+	}
+
+	my $streamable_url = $oflash_file;
+##	$streamable_url =~ s/ /%20/g;
+
+	$doc_obj->add_metadata ($section, "streamablevideo", $streamable_url);
+	$doc_obj->associate_file($oflash_filename,$oflash_file,"video/flash",
+				 $section);
+    }
+
+    #
+    # FlowPlayer.swf       height+22 pixels
+    # FlowPlayerBlack.swf  height+16 pixels
+    # FlowPlayerThermo.swf height+16 pixels
+    # FlowPlayerWhite.swf  height+26 pixels
+    $doc_obj->add_metadata ($section, "flashwidth",    $video_width);
+    $doc_obj->add_metadata ($section, "flashheight",   $video_height + 22 + 100);
+    
+    my $base_url = "_httpstreamserverprefix_/collect/[collection]/index/assoc/{If}{[assocfilepath],[assocfilepath],[parent(Top):assocfilepath]}/";
+
+    $doc_obj->add_metadata ($section, "baseurl",$base_url);
+    
+    $self->{'oflash_file'} = $oflash_file;
+    $self->{'oflash_filename'} = $oflash_filename;
+
+}
+
+
+
+sub add_cuepoints
+{
+    my ($self) = shift @_;
+    my ($doc_obj) = @_;
+
+    my $section = $doc_obj->get_top_section();
+    my $chapters = $doc_obj->get_children($section);
+
+
+    # open file
+    my $output_dir = $self->{'videoconvert'}->{'cached_dir'};
+    my $cue_filename = &util::filename_cat($output_dir,"on_cue.xml");
+
+    open(CUEOUT,">$cue_filename")
+	|| die "Unable to open $cue_filename: $!\n";
+    print CUEOUT "<tags>\n";
+
+
+    my $cc = 0;
+
+    foreach my $chap (@$chapters)
+    {
+	$cc++;
+
+	my $chap_text = $doc_obj->get_text($chap);
+
+	my @cuepoints 
+	    = ($chap_text =~ m/<p class=Timing><span\s+.*?>(?:T\d+:)? ?(\d\d:\d\d:\d\d)(?:\:\d\d)?/gsi);
+
+	my $count = 0;
+
+	foreach my $cuepoint (@cuepoints)
+	{	    
+	    my ($hh,$mm,$ss) = ($cuepoint =~ m/(\d\d):(\d\d):(\d\d)/);
+
+	    my $cuept_insecs = $self->hms_to_secs($hh,$mm,$ss);
+
+	    if ($cuept_insecs < 2) {
+		$cuept_insecs += 2;
+	    }
+	    my $cuept_inmsecs = 1000 * $cuept_insecs;
+	    
+	    $doc_obj->add_metadata($section,"cuepoint",$cuept_inmsecs);
+	    my $chap_title = $doc_obj->get_metadata_element($chap,"Title");
+
+	    # Navigation point (used in seeking)
+#	    print CUEOUT "  <metatag event=\"onCuePoint\" overwrite=\"true\">\n";
+#	    print CUEOUT "    <name>$chap_title</name>\n";
+#	    print CUEOUT "    <timestamp>$cuept_inmsecs</timestamp>\n";
+#	    print CUEOUT "    <parameters>\n";
+#	    print CUEOUT "      <thumb>dummy</thumb>\n";
+#	    print CUEOUT "      <sectionnum>$chap</sectionnum>\n";
+#	    print CUEOUT "      <subsectionnum>$count</subsectionnum>\n";
+#	    print CUEOUT "      <cuept>$cuept_inmsecs</cuept>\n";
+#	    print CUEOUT "    </parameters>\n";
+#	    print CUEOUT "    <type>navigation</type>\n";
+#	    print CUEOUT "  </metatag>\n";
+
+
+#	    print CUEOUT "  <metatag event=\"onCuePoint\" overwrite=\"true\">\n";
+#	    print CUEOUT "    <name>$chap_title</name>\n";
+#	    print CUEOUT "    <timestamp>$cuept_inmsecs</timestamp>\n";
+#	    print CUEOUT "    <parameters>\n";
+#	    print CUEOUT "      <thumb>foo.jpg</thumb>\n";
+#	    print CUEOUT "    </parameters>\n";
+#	    print CUEOUT "    <type>navigation</type>\n";
+#	    print CUEOUT "  </metatag>\n";
+
+	    if ($count==0)
+	    {
+		# Event (used to hook in to javascipt callback)
+		# Only do for the first in each chapter
+
+		print CUEOUT "  <metatag event=\"onCuePoint\" overwrite=\"true\">\n";
+##		print CUEOUT "    <name>Test $cc</name>\n";
+		print CUEOUT "    <name>$chap_title</name>\n";
+		print CUEOUT "    <timestamp>$cuept_inmsecs</timestamp>\n";
+		print CUEOUT "    <parameters>\n";
+		print CUEOUT "      <cuept>$cuept_inmsecs</cuept>\n";
+		print CUEOUT "      <sectionnum>$chap</sectionnum>\n";
+		print CUEOUT "    </parameters>\n";
+		print CUEOUT "    <type>event</type>\n";
+##		print CUEOUT "    <type>actionscript</type>\n";
+		print CUEOUT "  </metatag>\n";
+	    }
+
+	    $count++;
+	}
+    }
+
+
+    print CUEOUT "</tags>\n";
+    close(CUEOUT);
+
+    my $videoconvert = $self->{'videoconvert'};
+    my $oflash_filename = $self->{'oflash_filename'};
+    my $oflash_file = $self->{'oflash_file'};
+
+    my ($streamcuepts_cmd,$ostreamcuepts_filename) = $videoconvert->streamcuepts_cmd($oflash_filename);
+
+    my $verbosity = $self->{'verbosity'};
+    my $outhandle = $self->{'outhandle'};
+
+    my $streamcuepts_options = { @{$videoconvert->{'flvtool2_monitor'}},
+				 'message_prefix' => "Stream Cue Points",
+				 'message' => "Reprocessing video stream to add cuepoints on timeline: $oflash_file" }; 
+
+    my $streamable_regenerated = $self->{'streamable_regenerated'};
+
+    if ($streamable_regenerated) {
+	$videoconvert->run_general_cmd($streamcuepts_cmd,$streamcuepts_options);
+    }
+
+    
+
+}
+
+
+
+sub process {
+    my $self = shift (@_);
+    my ($textref, $pluginfo, $base_dir, $file, $metadata, $doc_obj, $gli) = @_;
+
+    my $filename = $file;
+    $filename = &util::filename_cat ($base_dir, $file) if $base_dir =~ /\w/;
+
+    my $top_section = $doc_obj->get_top_section();
+
+    $self->streamable_video($base_dir,$filename,$doc_obj,$top_section);
+
+    $self->hyperlink_timing_info($textref);
+
+    foreach my $mp3_excerpt (@{$self->{'mp3_excerpts'}}) {
+	my $omp3_file = $mp3_excerpt->{'omp3_file'};
+	my $omp3_filename = $mp3_excerpt->{'omp3_filename'};
+
+	$doc_obj->associate_file($omp3_filename,$omp3_file,"audio/mp3",
+				 $top_section);
+    }
+    $self->{'mp3_excerpts'} = undef;
+
+    my $metatable_store = $self->{'metatable_store'};
+    foreach my $metaname (keys %$metatable_store) {
+	my $metadata = $metatable_store->{$metaname};
+	$doc_obj->add_metadata($top_section,$metaname,$metadata);
+    }
+    $self->{'metatable_store'} = undef;
+
+    my $ret_val = $self->SUPER::process(@_);
+
+    $self->add_cuepoints($doc_obj);
+
+
+    return $ret_val;
+
+}
+
+
+
+sub replace_images {
+    my $self = shift (@_);
+    my ($front, $link, $back, $base_dir, 
+	$file, $doc_obj, $section) = @_;
+
+    if ($link =~ m/^"?_.*?_"?\//) {
+	# variety of greenstone macro, so let through unchanged
+	return $front . $link . $back ;
+    }
+
+    return $self->SUPER::replace_images(@_);
+}
+
+
+
+
+
+sub replace_href_links {
+    my $self = shift (@_);
+    my ($front, $link, $back, $base_dir, $file, $doc_obj, $section) = @_;
+
+
+    if ($link =~ m/^"?_.*?_"?/) {
+	# variety of greenstone macro, so let through unchanged
+	return $front . $link . $back ;
+    }
+
+    return $self->SUPER::replace_href_links(@_);
+}
+
+1;
Index: extensions/gsdl-video/trunk/perllib/plugins/VideoPlugin.pm
===================================================================
--- extensions/gsdl-video/trunk/perllib/plugins/VideoPlugin.pm	(revision 18425)
+++ extensions/gsdl-video/trunk/perllib/plugins/VideoPlugin.pm	(revision 18425)
@@ -0,0 +1,989 @@
+########################################################################
+#
+# VideoPlug.pm -- plugin for processing video largely based on ImagePlug
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# 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.
+#
+###########################################################################
+
+package VideoPlugin;
+
+use strict;
+no strict 'refs'; # allow filehandles to be variables and viceversa
+
+use videoconvert;
+use XMLParser;
+use gsprintf;
+
+use BasePlugin;
+
+sub BEGIN {
+    @VideoPlugin::ISA = ('BasePlugin');
+
+    if (!defined $ENV{'GEXTVIDEO'}) {
+	print STDERR "Warning: Greenstone Video extension not detected.\n";
+    }
+
+}
+
+my $arguments =
+    [ { 'name' => "process_exp",
+	'desc' => "{BasePlugin.process_exp}",
+	'type' => "regexp",
+	'deft' => &get_default_process_exp(),
+	'reqd' => "no" },
+      { 'name' => "noscaleup",
+	'desc' => "{VideoPlug.noscaleup}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "use_ascii_only_filenames",
+	'desc' => "{VideoPlug.use_ascii_only_filenames}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "video_excerpt_duration",
+	'desc' => "{VideoPlug.video_excerpt_duration}",
+	'type' => "string",
+	'deft' => "",
+	'reqd' => "no" },
+      { 'name' => "extractthumbnail",
+	'desc' => "{VideoPlug.extractthumbnail}",
+	'type' => "flag",
+	'deft' => "0",
+	'reqd' => "no" },
+      { 'name' => "thumbnailsize",
+	'desc' => "{VideoPlug.thumbnailsize}",
+	'type' => "int",
+	'deft' => "100",
+	'range' => "1,",
+	'reqd' => "no" },
+      { 'name' => "thumbnailtype",
+	'desc' => "{VideoPlug.thumbnailtype}",
+	'type' => "string",
+	'deft' => "jpeg",
+	'reqd' => "no" },
+      { 'name' => "extractscreenview",
+	'desc' => "{VideoPlug.extractscreenview}",
+	'type' => "flag",
+	'deft' => "0",
+	'reqd' => "no" },
+      { 'name' => "screenviewsize",
+	'desc' => "{VideoPlug.screenviewsize}",
+	'type' => "int",
+	'deft' => "0",
+	'range' => "1,",
+	'reqd' => "no" },
+      { 'name' => "screenviewtype",
+	'desc' => "{VideoPlug.screenviewtype}",
+	'type' => "string",
+	'deft' => "jpg",
+	'reqd' => "no" },
+      { 'name' => "converttotype",
+	'desc' => "{VideoPlug.converttotype}",
+	'type' => "string",
+	'deft' => "",
+	'reqd' => "no" },
+      { 'name' => "converttosize",
+	'desc' => "{VideoPlug.converttosize}",
+	'type' => "int",
+	'deft' => "",
+##	'deft' => "352",
+	'reqd' => "no" },
+      { 'name' => "converttobitrate",
+	'desc' => "{VideoPlug.converttobitrate}",
+	'type' => "string",
+	'deft' => "200k",
+	'reqd' => "no" },
+      { 'name' => "extractkeyframes",
+	'desc' => "{VideoPlug.extractkeyframes}",
+	'type' => "flag",
+	'deft' => "0",
+	'reqd' => "no" },
+      { 'name' => "enablestreaming",
+	'desc' => "{VideoPlug.enablestreaming}",
+	'type' => "flag",
+	'deft' => "1",
+	'reqd' => "no" },
+      { 'name' => "streamingsize",
+	'desc' => "{VideoPlug.streamingsize}",
+	'type' => "int",
+	'deft' => "352",
+	'reqd' => "no" },
+      { 'name' => "streamingbitrate",
+	'desc' => "{VideoPlug.streamingbitrate}",
+	'type' => "string",
+	'deft' => "200k",
+	'reqd' => "no" },
+      { 'name' => "minimumsize",
+	'desc' => "{VideoPlug.minimumsize}",
+	'type' => "int",
+	'deft' => "100",
+	'range' => "1,",
+	'reqd' => "no" } ];
+
+my $options = { 'name'     => "VideoPlug",
+		'desc'     => "{VideoPlug.desc}",
+		'abstract' => "no",
+		'inherits' => "yes",
+		'args'     => $arguments };
+
+
+my ($self);
+
+sub new {
+    my ($class) = shift (@_);
+    my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
+    push(@$pluginlist, $class);
+
+    push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
+    push(@{$hashArgOptLists->{"OptList"}},$options);
+
+    $self = new BasePlugin($pluginlist, $inputargs, $hashArgOptLists);
+
+    # Check that ffmpeg is installed and available on the path (except for Windows 95/98)
+    # This test is "inherited" from ImagePlugin where ImageMagick support
+    # for building cannot be used on these two versions of Windows as they
+    # do not have enough flexablity in the use of stdout and stderr to
+    # support how our code works.  It seems reasonable to assume the
+    # same is true for VideoPlugin work using ffmpeg.
+
+    if (($ENV{'GSDLOS'} ne "windows" || Win32::IsWinNT())) {
+
+	my $result = `ffmpeg -h 2>&1`;
+
+	if (!defined $result || $result !~ m/^FFmpeg version/) {
+	    $self->{'ffmpeg_not_installed'} = 1;
+	    print STDERR $result;
+	}
+    }
+
+
+    # create XML::Parser object for parsing metadata.xml files
+    my $parser;
+    if ($]<5.008) {
+	# Perl 5.6
+	$parser = new XML::Parser('Style' => 'Stream',
+				  'Handlers' => {'Char' => \&Char,
+						 'Doctype' => \&Doctype
+						 });
+    }
+    else {
+	# Perl 5.8
+	$parser = new XML::Parser('Style' => 'Stream',
+				  'ProtocolEncoding' => 'ISO-8859-1',
+				  'Handlers' => {'Char' => \&Char,
+						 'Doctype' => \&Doctype
+						 });
+    }
+
+    $self->{'parser'} = $parser;
+
+
+    return bless $self, $class;
+}
+
+
+sub init {
+    my $self = shift (@_);
+    my ($verbosity, $outhandle, $failhandle) = @_;
+
+    $self->SUPER::init(@_);
+    ## $self->ImageConverter::init(); # ****** VideoConverter::init ??
+}
+
+
+sub get_default_process_exp {
+    my $self = shift (@_);
+
+    return q^\.(?i)(mpe?g|flv|qt|vob|avi)$^; 
+}
+
+# this makes no sense for image
+sub block_cover_image
+{
+    my $self =shift (@_);
+    my ($filename) = @_;
+
+    return;
+}
+
+
+
+
+# Create the keyframes, thumbnail and screenview images, and discover
+# the Video's size, width, and height using the ffmpeg utility.
+
+sub run_convert {
+    my $self = shift (@_);
+    my $base_dir = shift (@_);
+    my $filename = shift (@_);   # filename with full path
+    my $file = shift (@_);       # filename without path
+    my $doc_obj = shift (@_);
+
+    my $section = $doc_obj->get_top_section();
+    
+    my $verbosity = $self->{'verbosity'};
+    my $outhandle = $self->{'outhandle'};
+
+    # check the filename is okay
+    return 0 if ($file eq "" || $filename eq "");
+
+    my $minimumsize = $self->{'minimumsize'};
+    if (defined $minimumsize && (-s $filename < $minimumsize)) {
+        print $outhandle "VideoPlug: \"$filename\" too small, skipping\n"
+	    if ($verbosity > 1);
+    }
+
+    my ($video_type, $video_width, $video_height, $video_duration, $video_size,
+	$vcodec,$vfps,$atype,$afreq,$achan,$arate) 
+	= &videoconvert::identify($filename, $outhandle, $verbosity);
+
+    if ($vfps eq "unknown") {
+	print $outhandle "Unknown framerate, defaulting to 25 frames per second.\n";
+	$vfps = 25;
+    }
+
+    my ($dur_hour,$dur_min,$dur_sec) 
+	= ($video_duration =~ m/(\d+):(\d+):(\d+\.\d+)/);
+    my $total_dur_secs = $dur_hour*3600 + $dur_min*60 + $dur_sec;
+
+    $self->{'video-fps'} = $vfps;
+    $self->{'num-total-frames'} = $total_dur_secs * $vfps;
+
+    # Convert the video to a new type (if required).
+    my $converttotype = $self->{'converttotype'};
+    my $converttosize = $self->{'converttosize'};
+
+    # shorten duration prcessed for experimentation purposes
+    my $exp_duration = undef;
+    
+    my $video_excerpt_duration = $self->{'video_excerpt_duration'};
+
+    if ((defined $video_excerpt_duration) && ($video_excerpt_duration ne "")) {
+	$exp_duration = $video_excerpt_duration;
+	my ($hh,$mm,$ss,$ms) = ($exp_duration =~ m/^(\d\d):(\d\d):(\d\d)\.?(\d\d)?/);
+	my $excerpt_dur_in_secs = $hh * 3600 + $mm * 60 + $ss;
+
+	if ($excerpt_dur_in_secs < $total_dur_secs) {
+	    $self->{'num-total-frames'} = $excerpt_dur_in_secs * $vfps; # override calculation for full length duration
+	}
+	else {
+	    # clip is already shorter than requested video excerpt duration
+	    # set exp_duration back to undefined
+	    $exp_duration = undef;
+	}
+    }
+
+
+    if (defined $exp_duration)
+    {
+	print $outhandle "Only encoding first $exp_duration of video.\n";
+	$self->{'exp_duration'} = $exp_duration;
+    }
+
+    my $ascii_only_filenames = $self->{'use_ascii_only_filenames'};
+    my $videoconvert 
+	= new videoconvert($base_dir,$filename,$verbosity,$outhandle,$exp_duration,$ascii_only_filenames);
+    $self->{'videoconvert'} = $videoconvert;
+
+    my $originalfilename = undef;
+    my $type = "unknown";
+
+    my $output_dir = $videoconvert->{'cached_dir'};
+    my $ivideo_root = $videoconvert->{'file_root'};
+
+    my $convertto_regenerated = 0;
+    if (($converttotype ne "" && $filename =~ m/$converttotype$/i) ||
+	(($converttosize ne "" && $converttosize ne $video_width) || ($converttosize ne "" && $converttosize ne $video_height))) {
+	if ($converttotype eq "") {
+	    # in this block because the video width x height different to original
+	    # => set (for this call to run_convert only) converttotype
+	    #    to input file extension
+	    ($converttotype) = ($filename =~ m/\.(.*?)$/);
+	}
+
+	$originalfilename = $filename;
+
+	$file = "$ivideo_root.$converttotype";
+	$filename = &util::filename_cat($output_dir,$file);
+ 
+	my $s_opt = $videoconvert->optional_frame_scale($converttosize,$video_width,$video_height);
+	my $exp_duration = $self->{'exp_duration'};
+	my $t_opt = (defined $exp_duration) ? "-t $exp_duration" : "";
+	    
+	my $main_opts = "-y $t_opt $s_opt";
+
+
+	my $convertto_command = "ffmpeg $main_opts -i \"$originalfilename\"";
+	$convertto_command .= " -ar 22050" if ($converttotype eq "flv");
+	$convertto_command .= " -y \"$filename\"";
+
+	my $convertto_result;
+	my $convertto_error;
+	
+	my $convertto_options = { @{$videoconvert->{'ffmpeg_monitor'}},
+				  'message_prefix' => "Convert to",
+				  'message' => "Converting video to $converttotype" }; 
+
+	($convertto_regenerated,$convertto_result,$convertto_error)
+	    = $videoconvert->run_cached_general_cmd($convertto_command,$filename,$convertto_options);
+						    
+	$type = $converttotype;
+    }
+    
+
+    # Add the video metadata
+
+    my $file_unicode = pack("U0C*", map { ord($_) } split(//,$file)); # force explicitly to unicode
+
+    $file_unicode =~ s/\x{2018}|\x{2019}|\x{201C}|\x{201D}//g; # remove smart quotes as cause problem in URL for video server
+    $file_unicode =~ s/\x{2013}/\-/g; # change en-dash to '-' as again causes problems for video server
+
+##    print STDERR "**** file metadata = ", &gsprintf::debug_unicode_string($file_unicode), "\n";
+
+    
+    # split filename on char if specified
+    if ($file_unicode =~ m/\-/) {
+
+	my @file_split = split(/\s*\-\s*/,$file_unicode);
+	my $creator = shift @file_split;
+	my $title = shift @file_split;
+
+	$title =~ s/\..*?$//;
+	$title =~ s/^(.)/\u$1/;
+
+	$doc_obj->add_utf8_metadata($section,"Title",$title);
+
+	my @creator_split = split(/\s+and\s+/,$creator);
+	foreach my $c (@creator_split) {
+	    $doc_obj->add_utf8_metadata($section,"Creator",$c);
+	}
+    }
+
+    $file = $file_unicode;
+    my $filemeta = $self->filename_to_utf8_metadata($file);
+    my $filemeta_url_safe = $videoconvert->url_safe($filemeta);
+
+    $doc_obj->add_utf8_metadata ($section, "Video", $filemeta_url_safe);
+
+    # Also want to set filename as 'Source' metadata to be
+    # consistent with other plugins
+    $doc_obj->add_utf8_metadata ($section, "Source", $filemeta_url_safe);
+
+
+    if ($video_type ne " ") {
+	$type = $video_type;
+    }
+    
+    $doc_obj->add_metadata ($section, "FileFormat", $type);
+    $doc_obj->add_metadata ($section, "FileSize",   $video_size);
+
+    $doc_obj->add_metadata ($section, "VideoType",     $video_type);
+    $doc_obj->add_metadata ($section, "VideoWidth",    $video_width);
+    $doc_obj->add_metadata ($section, "VideoHeight",   $video_height);
+    $doc_obj->add_metadata ($section, "VideoDuration", $video_duration);
+    $doc_obj->add_metadata ($section, "VideoSize",     $video_size);
+
+    $doc_obj->add_metadata ($section, "VideoCodec",    $vcodec);
+    $doc_obj->add_metadata ($section, "VideoFPS",      $vfps);
+
+    $doc_obj->add_metadata ($section, "AudioType",     $atype);
+    $doc_obj->add_metadata ($section, "AudioFreq",     $afreq);
+    $doc_obj->add_metadata ($section, "AudioChannels", $achan);
+    $doc_obj->add_metadata ($section, "AudioRate",     $arate);
+
+    $doc_obj->add_utf8_metadata ($section, "srclink", 
+			    "<a href=\"_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/[Video]\">");
+    $doc_obj->add_utf8_metadata ($section, "/srclink", "</a>");
+    $doc_obj->add_metadata ($section, "srcicon", "[VideoType]");
+
+    # Add the image as an associated file
+    $doc_obj->associate_file($filename,$file,"video/$type",$section);
+
+
+    if ($self->{'extractkeyframes'}) {
+	# Generate the keyframes with ffmpeg and hive
+	my ($keyframe_cmd,$okeyframe_filename) = $videoconvert->keyframe_cmd($originalfilename || $filename);
+
+	my $keyframe_options = { @{$videoconvert->{'ffmpeg_monitor'}},
+				 'message_prefix' => "Keyframe",
+				 'message' => "Extracting keyframes" }; 
+
+	$videoconvert->run_cached_general_cmd($keyframe_cmd,$okeyframe_filename,$keyframe_options);
+	$videoconvert->parse_shot_xml($self);
+	$videoconvert->associate_keyframes($doc_obj,$section,$self);
+    }
+
+    my $streamable_regenerated = 0;
+    my $optionally_run_general_cmd 
+	= ($convertto_regenerated) ? "regenerate_general_cmd" : "run_cached_general_cmd";
+
+    if ($self->{'enablestreaming'}) {
+	# Generate the Flash FLV format for streaming purposes
+
+	my $streaming_bitrate = $self->{'streamingbitrate'};
+	my $streaming_size    = $self->{'streamingsize'};
+
+	my $streaming_quality = "high";
+
+	my ($stream_cmd,$oflash_filename,$oflash_file) 
+	    = $videoconvert->stream_cmd($originalfilename || $filename,
+					$video_width,$video_height,
+					$streaming_quality,
+					$streaming_bitrate, $streaming_size);
+
+
+	my $streamable_options = { @{$videoconvert->{'ffmpeg_monitor'}},
+				   'message_prefix' => "Stream",
+				   'message' => "Generating streamable video: $oflash_file" }; 
+
+	my $streamable_result;
+	my $streamable_had_error;
+	($streamable_regenerated,$streamable_result,$streamable_had_error)
+	    = $videoconvert->$optionally_run_general_cmd($stream_cmd,$oflash_filename,$streamable_options);
+
+	if (!$streamable_had_error) {
+	    my ($streamseekable_cmd,$ostreamseekable_filename) = $videoconvert->streamseekable_cmd($oflash_filename);
+
+	    my $streamseekable_options = { @{$videoconvert->{'flvtool2_monitor'}},
+					   'message_prefix' => "Stream Seekable",
+					   'message' => "Reprocessing video stream to be seekable by timeline: $oflash_file" }; 
+
+	    if ($streamable_regenerated) {
+		$videoconvert->run_general_cmd($streamseekable_cmd,$streamseekable_options);
+	    }
+
+	    my $streamable_url = $oflash_file;
+	    ## $streamable_url =~ s/ /%20/g;
+	    my $streamable_url_safe = $videoconvert->url_safe($streamable_url);
+
+	    $doc_obj->add_utf8_metadata ($section, "streamablevideo", $streamable_url_safe);
+	    $doc_obj->associate_file($oflash_filename,$oflash_file,"video/flash",
+				     $section);
+	}
+
+	my $video_width = $doc_obj->get_metadata_element($section,"VideoWidth");
+	my $video_height = $doc_obj->get_metadata_element($section,"VideoHeight");
+	
+	#
+	# FlowPlayer.swf       height+22 pixels
+	# FlowPlayerBlack.swf  height+16 pixels
+	# FlowPlayerThermo.swf height+16 pixels
+	# FlowPlayerWhite.swf  height+26 pixels
+	my $flashwidth = $video_width;
+	my $flashheight = $video_height + 22;
+	if ($self->{'extractkeyframes'}) {
+	    $flashheight += 100;
+	}
+	$doc_obj->add_metadata ($section, "flashwidth",    $flashwidth);
+	$doc_obj->add_metadata ($section, "flashheight",   $flashheight);
+	
+	my $video_server = $ENV{'GEXT_VIDEO_SERVER'};
+	my $video_prefix = $ENV{'GEXT_VIDEO_PREFIX'};
+	my $base_url = "$video_server$video_prefix/collect/[collection]/index/assoc/[assocfilepath]/";
+	my $base_url_safe = $videoconvert->url_safe($base_url);
+	$doc_obj->add_utf8_metadata ($section, "baseurl",$base_url_safe);
+	
+	$self->{'oflash_file'} = $oflash_file;
+	$self->{'oflash_filename'} = $oflash_filename;
+    }
+
+
+    # Make the thumbnail image
+    my $thumbnailsize = $self->{'thumbnailsize'} || 100;
+    my $thumbnailtype = $self->{'thumbnailtype'} || 'jpg';
+	
+
+    my $thumbnailfile = &util::filename_cat($output_dir,"$ivideo_root.$thumbnailtype");
+
+
+    if ($self->{'extractthumbnail'}) {
+	# Generate the thumbnail with convert, a la ImagePlug
+	my ($thumb_cmd ,$othumb_filename)
+	    = $videoconvert->keyframe_thumbnail_cmd($filename,$thumbnailfile,$thumbnailsize);
+
+	my $thumb_options = { 'verbosity' => $verbosity,
+			      'outhandle' => $outhandle,
+			      'message_prefix' => "Thumbnail",
+			      'message' => "Generating thumbnail" }; 
+
+	my ($thumb_regenerated,$thumb_result,$thumb_had_error)
+	    = $videoconvert->$optionally_run_general_cmd($thumb_cmd,$thumbnailfile,$thumb_options);
+
+	# Add the thumbnail as an associated file ...
+	if (-e "$thumbnailfile") { 
+	    $doc_obj->associate_file("$thumbnailfile", "thumbnail.$thumbnailtype", 
+				     "image/$thumbnailtype",$section);
+	    $doc_obj->add_metadata ($section, "ThumbType", $thumbnailtype);
+	    $doc_obj->add_metadata ($section, "Thumb", "thumbnail.$thumbnailtype");
+
+	    $doc_obj->add_utf8_metadata ($section, "thumbicon", "<img src=\"_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/[Thumb]\" width=[ThumbWidth] height=[ThumbHeight]>");
+###	    $doc_obj->add_utf8_metadata ($section, "thumbicon", "<img src=\"_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/[Thumb]\">");
+	}
+
+	# Extract Thumnail metadata from convert output
+	if ($thumb_result =~ m/[0-9]+x[0-9]+=>([0-9]+)x([0-9]+)/) {
+	    $doc_obj->add_metadata ($section, "ThumbWidth", $1);
+	    $doc_obj->add_metadata ($section, "ThumbHeight", $2);
+	}
+	else {
+	    # Two reasons for getting to here:
+	    #   1.thumbnail was generated by ffmpeg, not imagemagick convert
+	    #   2.thumbnail was cached, so imagemagick convert was not run
+	    # Either way, the solution is the same:
+	    # => run "identify $thumbnailfile" and parse result
+
+	    $thumb_result = `identify \"$thumbnailfile\"`;
+	    
+	    if ($thumb_result =~ m/([0-9]+)x([0-9]+)/) {
+		$doc_obj->add_metadata ($section, "ThumbWidth", $1);
+		$doc_obj->add_metadata ($section, "ThumbHeight", $2);
+	    }
+	}
+    }
+
+    if ($self->{'extractkeyframes'}) {
+
+	# Generate the mosaic with 'montage'
+	my $montagefile = &util::filename_cat($output_dir,"$ivideo_root\_montage.$thumbnailtype");
+
+	my ($montage_cmd,$omontage_filename)
+	    = $videoconvert->keyframe_montage_cmd($filename,$montagefile);
+
+	my $montage_options = { 'message_prefix' => "Montage",
+				'message' => "Generating montage" }; 
+
+	my ($montage_result,$montage_had_error)
+	    = $videoconvert->run_general_cmd($montage_cmd,$montage_options);
+
+	# Add the montage as an associated file ...
+	if (-e "$montagefile") { 
+	    $doc_obj->associate_file("$montagefile", "montage.$thumbnailtype", 
+				     "image/$thumbnailtype",$section);
+	    $doc_obj->add_metadata ($section, "MontageType", $thumbnailtype);
+	    $doc_obj->add_metadata ($section, "Montage", "montage.$thumbnailtype");
+
+	    $doc_obj->add_utf8_metadata ($section, "montageicon", "<img src=\"_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/[Montage]\" >");
+	}
+    }
+
+
+    
+    # Make a screen-sized version of the picture if requested
+    if ($self->{'extractscreenview'}) {
+
+	# To do: if the actual image smaller than the screenview size,
+	# we should use the original !
+
+	my $screenviewsize = $self->{'screenviewsize'};
+	my $screenviewtype = $self->{'screenviewtype'} || 'jpeg';
+	my $screenviewfilename = &util::filename_cat($output_dir,"$ivideo_root.$screenviewtype");
+
+	# make the screenview image
+
+	my ($screenview_cmd,$oscreenview_filename)
+	    = $videoconvert->keyframe_thumbnail_cmd($filename,$screenviewfilename,$screenviewsize);
+
+	my $screenview_options = { 'message_prefix' => "Screenview",
+				   'message' => "Generating screenview image" }; 
+
+	my ($result,$had_error)
+	    = $videoconvert->run_general_cmd($screenview_cmd,$screenview_options);
+
+	# get screenview dimensions, size and type
+        if ($result =~ m/[0-9]+x[0-9]+=>([0-9]+)x([0-9]+)/) {
+	    $doc_obj->add_metadata ($section, "ScreenWidth", $1);
+	    $doc_obj->add_metadata ($section, "ScreenHeight", $2);
+	}
+	else {
+	    $doc_obj->add_metadata ($section, "ScreenWidth", $video_width);
+	    $doc_obj->add_metadata ($section, "ScreenHeight", $video_height);
+	}
+
+	#add the screenview as an associated file ...
+	if (-e "$screenviewfilename") { 
+	    $doc_obj->associate_file("$screenviewfilename", "screenview.$screenviewtype",
+				     "image/$screenviewtype",$section);
+	    $doc_obj->add_metadata ($section, "ScreenType", $screenviewtype);
+	    $doc_obj->add_metadata ($section, "Screen", "screenview.$screenviewtype");
+
+	    $doc_obj->add_utf8_metadata ($section, "screenicon", "<img src=\"_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/[Screen]\" width=[ScreenWidth] height=[ScreenHeight]>");
+	} else {
+	    print $outhandle "VideoPlug: couldn't find \"$screenviewfilename\"\n";
+	}
+    }
+
+    return $type;
+}
+
+
+
+
+
+# The VideoPlug read() function. 
+# VideoPlug overrides read() because there is no need to read the actual 
+# text of the file in, because the contents of the file is not text...
+#
+# Return number of files processed, undef if can't process
+# Note that $base_dir might be "" and that $file might 
+# include directories
+
+sub read {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $file, $metadata, $processor, $maxdocs, $total_count, $gli) = @_;
+
+    my $outhandle = $self->{'outhandle'};
+
+    #check process and block exps, smart block, etc
+    my ($block_status,$filename) = $self->read_block(@_);    
+    return $block_status if ((!defined $block_status) || ($block_status==0));
+
+    print STDERR "<Processing n='$file' p='VideoPlug'>\n" if ($gli);
+    print $outhandle "VideoPlug processing $file\n"
+	    if $self->{'verbosity'} > 1;
+
+    # None of this works very well on Windows 95/98...
+    if ($ENV{'GSDLOS'} eq "windows" && !Win32::IsWinNT()) {
+	if ($gli) {
+	    print STDERR "<ProcessingError n='$file' r='Windows 95/98 not supported'>\n";
+	}
+	print $outhandle "VideoPlug: Windows 95/98 not supported\n";
+	return -1;
+    }
+
+    # None of this is going to work very well without ffmpeg
+    if ($self->{'ffmpeg_not_installed'}) {
+	if ($gli) {
+	    print STDERR "<ProcessingError n='$file' r='ffmpeg not installed'>\n";
+	}
+	print $outhandle "VideoPlug: ffmpeg not installed\n";
+	return -1;
+    }
+
+    #if there's a leading directory name, eat it...
+    $file =~ s/^.*[\/\\]//;
+    
+    # create a new document
+    my $doc_obj = new doc ($filename, "indexed_doc");
+
+    $doc_obj->set_OIDtype ($processor->{'OIDtype'}, $processor->{'OIDmetadata'});    
+    $doc_obj->add_utf8_metadata($doc_obj->get_top_section(), "Plugin", "$self->{'plugin_type'}");
+
+    #run convert to get the thumbnail and extract size and type info
+    my $result = $self->run_convert($base_dir, $filename, $file, $doc_obj);
+    
+    if (!defined $result)
+    {
+	if ($gli) {
+	    print STDERR "<ProcessingError n='$file'>\n";
+	}
+	print $outhandle "VideoPlug: couldn't process \"$filename\"\n";
+	return -1; # error during processing
+    }
+
+    #create an empty text string so we don't break downstream plugins 
+    my $text = &gsprintf::lookup_string("{BasePlugin.dummy_text}");
+    # include any metadata passed in from previous plugins 
+    # note that this metadata is associated with the top level section
+    my $section = $doc_obj->get_top_section();
+    $self->extra_metadata ($doc_obj, $section, $metadata);
+
+    # do plugin specific processing of doc_obj
+    unless (defined ($self->process(\$text, $pluginfo, $base_dir, $file, $metadata, $doc_obj))) {
+	print STDERR "<ProcessingError n='$file'>\n" if ($gli);
+	return -1;
+    }
+
+
+
+    # do any automatic metadata extraction
+    $self->auto_extract_metadata ($doc_obj);
+
+    # if we haven't found any Title so far, assign one
+    # this was shifted to here from inside read()
+    $self->title_fallback($doc_obj,$section,$file);
+
+    # add an OID 
+    # 
+    # Caveat: Don't want to hash on the source/converted video as typically
+    # prohibitively large => temporarily set source/converted filename 
+    # to 'undef' (causes set_OID to hash on metadata and text stored within
+    # $doc_ob) then restore to previous value.
+    #
+    my $stored_gsdlsourcefilename = $doc_obj->get_source_filename();
+    $doc_obj->set_source_filename(undef);
+
+    $self->add_OID($doc_obj);
+
+    $doc_obj->set_source_filename($stored_gsdlsourcefilename);
+
+    $doc_obj->add_text($section, $text);
+
+    # process the document
+    $processor->process($doc_obj);
+
+    if (($self->{'enablestreaming'}) && ($self->{'extractkeyframes'})) {
+	my $oflash_filename = $self->{'oflash_filename'};
+	my $videoconvert = $self->{'videoconvert'};
+	my ($streamkeyframes_cmd,$ostreamkeyframes_filename) 
+	    = $videoconvert->streamkeyframes_cmd($oflash_filename,$doc_obj,$section);
+
+	my $verbosity = $self->{'verbosity'};
+
+	my $streamkeyframes_options = { @{$videoconvert->{'flvtool2_monitor'}},
+					'message_prefix' => "Stream Keyframes",
+					'message' => "Reprocessing video stream to add keyframes on timeline" }; 
+#### this used to be commented out!!!
+	$videoconvert->run_general_cmd($streamkeyframes_cmd,$streamkeyframes_options);
+    }
+
+
+    $self->{'num_processed'}++;
+
+    return 1;
+}
+
+# do plugin specific processing of doc_obj
+sub process {
+    my $self = shift (@_);
+    my ($textref, $pluginfo, $base_dir, $file, $metadata, $doc_obj) = @_;
+    my $outhandle = $self->{'outhandle'};
+    
+    return 1;
+}
+
+
+
+sub output_distributed_keyframes
+{
+    my ($self) = shift @_;
+    my ($timeline,$num_dist_frames) = @_;
+
+    my $num_total_frames = $self->{'num-total-frames'};
+
+    my $frame_delta = $num_total_frames/$num_dist_frames;
+
+    my $closest_to = $frame_delta;
+    my $prev_t = 0;
+
+#    print STDERR "*** num total frames  = $num_total_frames\n";
+#    print STDERR "*** frame delta = $frame_delta\n";
+
+    foreach my $curr_t (sort { $a <=> $b } keys %$timeline)
+    {
+#	print STDERR "*** curr_t = $curr_t\n";
+	
+	if ($curr_t>$closest_to) {
+	    # decide if previous t (prev_t_ or current t (curr_t) is closest
+
+	    my $timeline_rec;
+
+	    my $prev_t_dist = $closest_to - $prev_t;
+	    my $curr_t_dist = $curr_t - $closest_to;
+
+	    if ($curr_t_dist <= $prev_t_dist)
+	    {
+		$timeline_rec = $timeline->{$curr_t}
+	    }
+	    else
+	    {
+		$timeline_rec = $timeline->{$prev_t}
+	    }
+
+	    my $name      = $timeline_rec->{'name'};
+	    my $timestamp = $timeline_rec->{'timestamp'};
+	    my $thumb     = $timeline_rec->{'thumb'};
+
+
+	    print CUEOUT "  <metatag event=\"onCuePoint\" overwrite=\"true\">\n";
+	    print CUEOUT "    <name>$name</name>\n";
+	    print CUEOUT "    <timestamp>$timestamp</timestamp>\n";
+	    print CUEOUT "    <parameters>\n";
+	    print CUEOUT "      <thumb>$thumb</thumb>\n";
+	    print CUEOUT "    </parameters>\n";
+	    print CUEOUT "    <type>navigation</type>\n";
+	    print CUEOUT "  </metatag>\n";
+
+#	    my $testtime = $timestamp+1000;
+#	    print CUEOUT "  <metatag event=\"onCuePoint\" overwrite=\"true\">\n";
+#	    print CUEOUT "    <name>Test $name</name>\n";
+#	    print CUEOUT "    <timestamp>$testtime</timestamp>\n";
+#	    print CUEOUT "    <parameters>\n";
+#	    print CUEOUT "      <thumb>$thumb</thumb>\n";
+#	    print CUEOUT "      <secnum>1</secnum>\n";
+#	    print CUEOUT "      <subsecnum>0</subsecnum>\n";
+#	    print CUEOUT "    </parameters>\n";
+#	    print CUEOUT "    <type>event</type>\n";
+#	    print CUEOUT "  </metatag>\n";
+
+	    $closest_to += $frame_delta;
+	}
+	$prev_t = $curr_t;
+    }
+}
+
+
+
+sub Doctype {
+    my ($expat, $name, $sysid, $pubid, $internal) = @_;
+
+    # my $root_tag = $self->{'root_tag'};
+
+    if ($name !~ "seg") {	
+	die "Root tag $name does not match expected <seg>";
+    }
+}
+
+sub StartTag {
+    my ($expat, $element) = @_;
+
+    my %attr = %_;
+    
+    if ($element eq "seg") {
+	$self->{'keyframe_index'} = 0;
+	$self->{'keyframe_fnames'} = [];
+	$self->{'keyframe_timeline'} = {};
+
+	#$self->{'flowplayer_thumblist'} = "thumbs: \\[";
+
+	my $output_dir = $self->{'videoconvert'}->{'cached_dir'};
+	my $cue_filename = &util::filename_cat($output_dir,"on_cue.xml");
+
+	open(CUEOUT,">$cue_filename")
+	    || die "Unable to open $cue_filename: $!\n";
+	print CUEOUT "<tags>\n";
+    }
+    elsif ($element eq "trans") {
+	my $trans_type = $attr{'type'};
+	my $pre_frame_num = $attr{'preFNum'};
+	my $post_frame_num = $attr{'postFNum'};
+
+	my $avg_frame_num = int(($pre_frame_num+$post_frame_num)/2.0)+1;
+
+	my $output_dir = $self->{'videoconvert'}->{'cached_dir'};
+	my $ivideo_root = $self->{'videoconvert'}->{'file_root'};
+
+	my $keyframe_index = $self->{'keyframe_index'};
+
+	my $fps = $self->{'video-fps'};
+
+	if ($keyframe_index==0)
+	{
+	    # hive actually generates one extra keyframe at the start,
+	    # which is half way between frame 0 and the frist pre_frame
+
+	    my $thumb_file = sprintf("%s_%04d.jpg",$ivideo_root,$keyframe_index);
+	    my $thumb_filename = &util::filename_cat($output_dir,$thumb_file);
+	    push(@{$self->{'keyframe_fnames'}},$thumb_file);
+
+	    my $half_frame_num = $pre_frame_num/2.0;
+	    my $time_msec = ($half_frame_num / $fps) * 1000;
+
+#	    print CUEOUT "  <metatag event=\"onCuePoint\" overwrite=\"true\">\n";
+#	    print CUEOUT "    <name>Keyframe $keyframe_index</name>\n";
+#	    print CUEOUT "    <timestamp>$time_msec</timestamp>\n";
+#	    print CUEOUT "    <parameters>\n";
+#	    print CUEOUT "      <thumb>$thumb_file</thumb>\n";
+#	    print CUEOUT "    </parameters>\n";
+#	    print CUEOUT "    <type>navigation</type>\n";
+#	    print CUEOUT "  </metatag>\n";
+
+
+	    my $timeline_rec = { 'name'=> "Keyframe $keyframe_index",
+				 'keyframeindex' => $keyframe_index,
+				 'timestamp' => $time_msec,
+				 'thumb' => $thumb_file };
+
+	    $self->{'keyframe_timeline'}->{$half_frame_num}=$timeline_rec;
+
+	}
+
+	$keyframe_index++;
+
+	my $thumb_file = sprintf("%s_%04d.jpg",$ivideo_root,$keyframe_index);
+	my $thumb_filename = &util::filename_cat($output_dir,$thumb_file);
+	push(@{$self->{'keyframe_fnames'}},$thumb_file);
+
+	my $time_msec = (($avg_frame_num) / $fps) * 1000;
+	my $time_sec = (($avg_frame_num)/ $fps);
+
+#	print CUEOUT "  <metatag event=\"onCuePoint\" overwrite=\"true\">\n";
+#	print CUEOUT "    <name>Keyframe $keyframe_index</name>\n";
+#	print CUEOUT "    <timestamp>$time_msec</timestamp>\n";
+#	print CUEOUT "    <parameters>\n";
+#	print CUEOUT "      <thumb>$thumb_file</thumb>\n";
+#	print CUEOUT "    </parameters>\n";
+#	print CUEOUT "    <type>navigation</type>\n";
+#	print CUEOUT "  </metatag>\n";
+
+
+	my $timeline_rec = { 'name'=> "Keyframe $keyframe_index",
+			     'keyframeindex' => $keyframe_index,
+			     'timestamp' => $time_msec,
+			     'thumb' => $thumb_file };
+
+	$self->{'keyframe_timeline'}->{$avg_frame_num}=$timeline_rec;
+
+
+	# $self->{'flowplayer_thumblist'} .= "\\{ thumbNail: '$thumb_file', time: $time_sec \\},"; 
+
+	$self->{'keyframe_index'}  = $keyframe_index;
+    }
+}
+
+sub EndTag {
+    my ($expat, $element) = @_;
+
+    if ($element eq "seg") {
+
+	$self->output_distributed_keyframes($self->{'keyframe_timeline'},6);
+
+
+	print CUEOUT "</tags>\n";
+	close(CUEOUT);
+
+	#$self->{'flowplayer_thumblist'} .= "\\]";
+    }
+}
+
+
+sub Text {
+    my $text = $_;
+}
+
+# This Char function overrides the one in XML::Parser::Stream to overcome a
+# problem where $expat->{Text} is treated as the return value, slowing
+# things down significantly in some cases.
+sub Char {
+  $_[0]->{'Text'} .= $_[1];
+  return undef;
+}
+
+1;
+
+
+
+
+
+
+
+
+
+
+
Index: extensions/gsdl-video/trunk/perllib/videoconvert.pm
===================================================================
--- extensions/gsdl-video/trunk/perllib/videoconvert.pm	(revision 18425)
+++ extensions/gsdl-video/trunk/perllib/videoconvert.pm	(revision 18425)
@@ -0,0 +1,688 @@
+##########################################################################
+#
+# videoconvert.pm -- utility to help convert video file
+#
+# Copyright (C) 1999 DigiLib Systems Limited, NZ
+#
+# 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.
+#
+###########################################################################
+
+
+package videoconvert;
+
+use strict;
+no strict 'refs'; # allow filehandles to be variables and viceversa
+
+use baseconvert;
+
+sub BEGIN {
+    @videoconvert::ISA = ('baseconvert');
+}
+
+
+# Discover the characteristics of a video file.
+#  Equivalent step to that in ImagePlugin that uses ImageMagicks's 'indentify' utility
+#  Here we use 'ffmpeg' for video but for consistency keep the Perl method name the same 
+#  as before
+
+
+sub identify { 
+    my ($video, $outhandle, $verbosity) = @_;
+
+    # Use the ffmpeg command to get the file specs
+    my $command = "ffmpeg -i \"$video\"";
+
+    print $outhandle "  $command\n" if ($verbosity > 2);
+    my $result = '';
+    $result = `$command 2>&1`;
+    print $outhandle "  $result\n" if ($verbosity > 4);
+
+    # Read the type, width, and height etc.
+    my $vtype =  'unknown';
+    my $vcodec = 'unknown';
+    my $width =  'unknown';
+    my $height = 'unknown';
+    my $fps    = 'unknown';
+
+    my $atype =  'unknown';
+    my $afreq =  'unknown';
+    my $achan =  'unknown';
+    my $arate =  'unknown';
+
+    my $video_safe = quotemeta $video;
+
+    # strip off everything up to filename
+    $result =~ s/^.*\'$video_safe\'://s;
+
+    if ($result =~ m/Video: (.*?) fps/m) {
+	my $video_info = $1;
+	if ($video_info =~ m/([^,]+),(?: ([^,]+),)? (\d+)x(\d+),.*?(\d+\.\d+)/)
+	{
+	    $vtype = $1;
+	    $vcodec = $2 if defined $2;
+	    $width = $3;
+	    $height = $4;
+	    $fps = $5;
+	}
+    }
+
+##    if ($result =~ m/Video: (\w+), (\w+), (\d+)x(\d+),.*?(\d+\.\d+) fps/m) {
+#    if ($result =~ m/Video: ([^,]+),(?: ([^,]+),)? (\d+)x(\d+),.*?(\d+\.\d+) fps/m) {
+#	$vtype = $1;
+#	$vcodec = $2;
+#	$width = $3;
+#	$height = $4;
+#	$fps = $5;
+#    }
+
+    if ($result =~ m/Audio: (\w+), (\d+) Hz, (\w+)(?:, (\d+.*))?/m) {
+	$atype = $1;
+	$afreq = $2;
+	$achan = $3;
+	$arate = $4 if (defined $4);
+    }
+
+    # Read the duration
+    my $duration = "unknown";
+    if ($result =~ m/Duration: (\d+:\d+:\d+\.\d+)/m) {
+	$duration = $1;
+    }
+    print $outhandle "  file: $video:\t $vtype, $width, $height, $duration\n" 
+	if ($verbosity > 2);
+
+    if ($verbosity >3) {
+	print $outhandle "\t video codec=$vcodec, fps = $fps\n";
+	print $outhandle "\t audio codec=$atype, freq = $afreq Hz, $achan, $arate\n";
+    }
+
+    # Return the specs
+    return ($vtype, $width, $height, $duration, -s $video,
+	    $vcodec,$fps,$atype,$afreq,$achan,$arate);
+}
+
+
+sub vob_durations
+{
+    my ($media_base_dir,$title_num,$outhandle) = @_;
+
+    my $filter_re = sprintf("^VTS_%02d_[1-9]\\.VOB\$",$title_num);
+
+    my $duration_info = {};
+
+    if (opendir(VTSIN,$media_base_dir)) {
+	my @vts_title_vobs = grep { $_ =~ m/$filter_re/ } readdir(VTSIN);
+	closedir(VTSIN);
+
+	foreach my $v (@vts_title_vobs) {
+	    my $full_v = &util::filename_cat($media_base_dir,$v);
+
+	    my ($vtype, $width, $height, $duration, $vsize,
+		$vcodec,$fps,$atype,$afreq,$achan,$arate) = identify($full_v,$outhandle,0);
+
+	    my ($vob_num) = ($v =~ m/^VTS_\d\d_(\d)\.VOB$/);
+
+	    $duration_info->{$vob_num} = $duration;
+	    print STDERR "**** $title_num: $title_num, storing {$vob_num} => $duration\n";
+
+	}
+
+    }
+    else {
+	print $outhandle "Warning: unable to read files in directory $media_base_dir\n";
+    }
+    
+    return $duration_info;
+
+}
+
+
+
+sub new {
+    my ($class) = shift @_;
+
+    my ($base_dir,$video_filename, $verbosity,$outhandle,
+	$exp_duration,$ascii_only_filenames) = @_;
+
+    my $self = new baseconvert($base_dir,$video_filename,$verbosity,$outhandle);
+
+    $self->{'exp_duration'} = $exp_duration;
+
+    if (defined $ascii_only_filenames && ($ascii_only_filenames)) {
+	my $file_root = $self->{'file_root'};
+	$self->{'file_root'} = ascii_only_filename($file_root);
+    }
+				  
+    my @ffmpeg_monitor   = ( 'monitor_init'   , "videoconvert::ffmpeg_monitor_init",
+			     'monitor_line'   , "videoconvert::ffmpeg_monitor_line",
+			     'monitor_deinit' , "videoconvert::ffmpeg_monitor_deinit" );
+					
+    my @flvtool2_monitor = ( 'monitor_init'   ,"monitor_init_unbuffered",
+			     'monitor_line'   , "videoconvert::flvtool2_monitor_line",
+			     'monitor_deinit' , "monitor_deinit_unbuffered" );
+					
+    $self->{'ffmpeg_monitor'} = \@ffmpeg_monitor;
+    $self->{'flvtool2_monitor'} = \@flvtool2_monitor;
+
+
+    return bless $self, $class;
+}
+
+
+sub ascii_only_filename
+{
+    my ($file) = @_;
+
+    my $file_unicode = pack("U0C*", map { ord($_) } split(//,$file)); # force explicitly to unicode
+
+    my @ascii_only_chars 
+	= map { $_ >= 128 # if non-ascii
+		    ? "" 
+		    :  chr($_) } unpack("U*", $file_unicode); # unpack Unicode characters
+
+    my $ascii_file = join("",@ascii_only_chars);
+
+    if ($ascii_file eq "") {
+	print STDERR "Warning: filename includes no ASCII characters\n";
+	print STDERR "         Keeping as original filename\n";
+	$ascii_file = $file;
+    }
+
+    return $ascii_file;
+}
+
+
+sub remove_difficult_chars
+{
+    my $self = shift @_;
+
+    my ($file) = @_;
+
+    # remove problematic characters from filename that make using it in a URL difficult
+
+    my $file_unicode = pack("U0C*", map { ord($_) } split(//,$file)); # force explicitly to unicode
+
+    my $url = $file_unicode;
+    $url =~ s/\x{2018}|\x{2019}|\x{201C}|\x{201D}//g; # remove smart quotes as cause problem in URL for video server
+    $url =~ s/\x{2013}/\-/g; # change en-dash to '-' as again causes problems for video server
+    
+    return $url;
+}
+
+
+sub url_safe
+{
+    my $self = shift @_;
+
+    my ($file) = @_;
+    
+    my @url_utf8_chars 
+	= map { $_ >= 128 # if non-ascii
+		    ? "%" . sprintf("%02X", $_) 
+		    :  chr($_) } unpack("U*", $file); # unpack Unicode characters
+
+    my $url = join("",@url_utf8_chars);
+
+
+    return $url;
+}
+
+
+
+
+
+sub optional_frame_scale
+{
+    my $self = shift (@_);
+    my ($orig_size,$video_width,$video_height) = @_;
+
+    my $s_opt = "";
+    if ($video_width > $video_height) {
+	if ($video_width > $orig_size) {
+	    my $scale_factor = $orig_size/$video_width;
+	    my $scaled_width = int($video_width * $scale_factor);
+	    my $scaled_height = int($video_height * $scale_factor);
+
+	    # round to be ensure multiple of 2 (needed by some codecs)
+	    $scaled_width  = int($scaled_width/2)*2;
+	    $scaled_height = int($scaled_height/2)*2;
+
+	    $s_opt = "-s ${scaled_width}x${scaled_height}";
+	}
+	# else, video is smaller than requested size, don't scale up
+    }
+    else {
+	if ($video_height > $orig_size) {
+	    my $scale_factor = $orig_size/$video_height;
+	    my $scaled_width = int($video_width * $scale_factor);
+	    my $scaled_height = int($video_height * $scale_factor);
+
+	    # round to be ensure multiple of 2 (needed by some codecs)
+	    $scaled_width  = int($scaled_width/2)*2;
+	    $scaled_height = int($scaled_height/2)*2;
+
+	    $s_opt = "-s ${scaled_width}x${scaled_height}";
+	}
+	# else, video is smaller than requested size, don't scale up
+	
+    }
+    
+    return $s_opt;
+}
+
+
+sub keyframe_cmd
+{
+    my $self = shift (@_);
+    my ($ivideo_filename) = @_;
+
+    my $video_ext_dir = &util::filename_cat($ENV{'GSDLHOME'},"ext","video");
+
+    my $output_dir = $self->{'cached_dir'};
+    my $ivideo_root = $self->{'file_root'};
+
+    my $oshot_filename = &util::filename_cat($output_dir,"shots.xml");
+
+    my $exp_duration = $self->{'exp_duration'};
+    my $t_opt = (defined $exp_duration) ? "-t $exp_duration" : "";
+
+    my $main_opts = "-y $t_opt";
+
+    my $hive = &util::filename_cat($video_ext_dir,"lib","vhook","hive.so");
+
+    my $oflash_filename = &util::filename_cat($output_dir,"$ivideo_root\_keyframe.flv");
+
+    my $vhook_opts = "$hive  -o $oshot_filename -k $output_dir $ivideo_filename";
+
+    my $ffmpeg_cmd = "ffkeyframe  $main_opts -vhook \"$vhook_opts\"   -i \"$ivideo_filename\" -an -y \"$oflash_filename\"";
+
+
+    return ($ffmpeg_cmd,$oflash_filename);
+}
+
+
+sub stream_cmd
+{
+    my $self = shift (@_);
+    my ($ivideo_filename,$video_width,$video_height,
+	$streaming_quality,
+	$streaming_bitrate,$streaming_size, 
+	$opt_streaming_achan, $opt_streaming_arate) = @_;
+
+    my $streaming_achan 
+	= (defined $opt_streaming_achan) ? $opt_streaming_achan : 2;
+
+    my $streaming_arate 
+	= (defined $opt_streaming_arate) ? $opt_streaming_arate : 22050;
+
+    my $output_dir = $self->{'cached_dir'};
+    my $ivideo_root = $self->{'file_root'};
+
+    my $oflash_file = "${ivideo_root}_stream.flv";
+    my $oflash_filename = &util::filename_cat($output_dir,$oflash_file);
+
+    my $s_opt = $self->optional_frame_scale($streaming_size,$video_width,$video_height);
+
+    my $exp_duration = $self->{'exp_duration'};
+    my $t_opt = (defined $exp_duration) ? "-t $exp_duration" : "";
+
+    my $main_opts = "-y $t_opt";
+
+    my $bitrate_opt = "-b $streaming_bitrate";
+    ### my $stream_opts = "-r 25 $s_opt";
+    my $stream_opts .= " $s_opt -ac $streaming_achan -ar $streaming_arate";
+
+    # -flags +ilme+ildct' and maybe '-flags +alt' for interlaced material, and try '-top 0/1'
+
+    my $all_opts = "$main_opts $stream_opts"; 
+
+    my $ffmpeg_cmd;
+
+    if ($streaming_quality eq "high") {
+
+	my $pass_log_file = &util::filename_cat($output_dir,"$ivideo_root-logpass.txt");
+	if (-e $pass_log_file) {
+	    &util::rm($pass_log_file);
+	}
+
+	$all_opts .= " -passlogfile \"$pass_log_file\"";
+
+	my $ffmpeg_cmd_pass1 = "ffmpeg -pass 1 -i \"$ivideo_filename\" $all_opts -y \"$oflash_filename\"";
+
+	my $ffmpeg_cmd_pass2 = "ffmpeg -pass 2 -i \"$ivideo_filename\" $all_opts $bitrate_opt -y \"$oflash_filename\"";
+	$ffmpeg_cmd = "( $ffmpeg_cmd_pass1 ; $ffmpeg_cmd_pass2 )";
+    }
+    else {
+	# single pass
+
+	$ffmpeg_cmd = "ffmpeg -i \"$ivideo_filename\" $all_opts -y \"$oflash_filename\"";
+    }
+
+    return ($ffmpeg_cmd,$oflash_filename,$oflash_file);
+}
+
+
+
+sub audio_excerpt_cmd
+{
+    my $self = shift (@_);
+    my ($ivoa_filename,$hh,$mm,$ss,$opt_excerpt_len) = @_;
+
+    # ivoa = input video or audio
+
+    my $time_encoded = "$hh:$mm:$ss";
+    my $time_encoded_file = "$hh$mm$ss";
+    
+    
+    my $output_dir = $self->{'cached_dir'};
+    my $ivoa_root = $self->{'file_root'};
+
+    my $omp3_file = "${ivoa_root}_$time_encoded_file.mp3";
+    my $omp3_filename = &util::filename_cat($output_dir,$omp3_file);
+
+    my $all_opts = "-y -acodec mp3 -ss $time_encoded ";
+
+    if (defined $opt_excerpt_len) {
+	$all_opts .= "-t $opt_excerpt_len ";
+    }
+
+
+    my $ffmpeg_cmd = "ffmpeg -i \"$ivoa_filename\" $all_opts  \"$omp3_filename\"";
+
+    return ($ffmpeg_cmd,$omp3_filename,$omp3_file);
+}
+
+
+
+sub streamseekable_cmd
+{
+    my $self = shift (@_);
+    my ($oflash_filename) = @_;
+
+    my $output_dir = $self->{'cached_dir'};
+    my $ivideo_root = $self->{'file_root'};
+
+    my $cue_filename = &util::filename_cat($output_dir,"on_cue.xml");
+
+    my $flvtool_cmd = "flvtool2 -vUP \"$oflash_filename\"";
+
+    return ($flvtool_cmd,$oflash_filename);
+}
+
+
+sub streamkeyframes_cmd
+{
+    my $self = shift (@_);
+    my ($oflash_filename,$doc_obj,$section) = @_;
+
+    my $assocfilepath 
+	= $doc_obj->get_metadata_element($section,"assocfilepath");
+
+    my $output_dir = $self->{'cached_dir'};
+
+    my $cue_filename = &util::filename_cat($output_dir,"on_cue.xml");
+
+    my $video_server = $ENV{'GEXT_VIDEO_SERVER'}; 
+    my $video_prefix = $ENV{'GEXT_VIDEO_PREFIX'};
+
+    my $collect = $ENV{'GSDLCOLLECTION'};
+ 
+    my $flvtool_cmd = "flvtool2 -vAUtP \"$cue_filename\" -thumbLocation:$video_server$video_prefix/collect/$collect/index/assoc/$assocfilepath \"$oflash_filename\"";
+
+
+    return ($flvtool_cmd,$oflash_filename);
+}
+
+
+sub streamcuepts_cmd
+{
+    my $self = shift (@_);
+    my ($oflash_filename) = @_;
+
+    my $output_dir = $self->{'cached_dir'};
+
+    my $cue_filename = &util::filename_cat($output_dir,"on_cue.xml");
+
+    my $video_server = $ENV{'GEXT_VIDEO_SERVER'}; 
+    my $video_prefix = $ENV{'GEXT_VIDEO_PREFIX'};
+
+    my $collect = $ENV{'GSDLCOLLECTION'};
+    my $thumbloc = "$video_server$video_prefix/collect/$collect";
+
+
+#    my $flvtool_cmd = "flvtool2 -vUAtP \"$cue_filename\" -thumbLocation:$thumbloc \"$oflash_filename\"";
+
+#    my $flvtool_cmd = "flvtool2 -vUAt \"$cue_filename\" \"$oflash_filename\"";
+
+
+
+#    my $flvtool_cmd = "flvtool2 -vUAt \"$cue_filename\" \"$oflash_filename\"";
+
+
+##    my $flvtool_cmd = "flvtool2 -vAt \"$cue_filename\" -UP \"$oflash_filename\" \"$output_dir/updated.flv\"";
+
+##    my $flvtool_cmd = "flvtool2 -vAtU \"$cue_filename\" \"$oflash_filename\" \"$output_dir/updated.flv\"";
+
+    my $flvtool_cmd = "flvtool2 -vAtUP \"$cue_filename\" \"$oflash_filename\"";
+
+    return ($flvtool_cmd,$oflash_filename);
+}
+
+
+sub keyframe_thumbnail_cmd
+{
+    my $self = shift (@_);
+    my ($ivideo_filename,$thumbnailfile,$thumbnailsize) = @_;
+
+    my $output_dir = $self->{'cached_dir'};
+    my $ivideo_root = $self->{'file_root'};
+
+    my $key_filename_prefix = &util::filename_cat($output_dir,$ivideo_root);
+
+
+    # Try for 4th keyframe, but fall back to 1st if doesn't exist
+    my $key_filename = "${key_filename_prefix}_0003.jpg";
+    $key_filename = "${key_filename_prefix}_0000.jpg" if (!-e $key_filename);
+
+    my $command;
+
+    if (-e $key_filename) {
+	$command = "convert -interlace plane -verbose -geometry $thumbnailsize" 
+	    . "x$thumbnailsize \"$key_filename\" \"$thumbnailfile\"";
+    }
+    else {
+	# extractkeyframe has either not been switched on, or else had
+	# a problem when running
+	# => extract a from 
+	# my $frame_rate = 1.0 / 60.0;
+
+
+	$command = "ffmpeg -i \"$ivideo_filename\"  -ss 5.5 -vframes 1 -f image2 -s ${thumbnailsize}x${thumbnailsize} -y \"$thumbnailfile\"";
+
+	# fmpeg -i input.dv -r 1 -f image2 -s 120x96 images%05d.png
+    }
+
+    return ($command,$thumbnailfile);
+}
+
+
+sub keyframe_montage_cmd
+{
+    my $self = shift (@_);
+    my ($ivideo_filename,$montagefile) = @_;
+
+    my $output_dir = $self->{'cached_dir'};
+    my $ivideo_root = $self->{'file_root'};
+
+    my $key_filename_prefix = &util::filename_cat($output_dir,$ivideo_root);
+
+    my $options = "-tile 10  -geometry 75x62+2+2";
+
+    my $command = "montage $options ${key_filename_prefix}_*.jpg \"$montagefile\"";
+
+    return ($command,$montagefile);
+}
+
+
+
+sub parse_shot_xml
+{
+    my ($self) = shift(@_);
+
+    my ($plugin) = @_;
+
+    my $outhandle = $self->{'outhandle'};
+    my $output_dir = $self->{'cached_dir'};
+
+    my $shots_filename = &util::filename_cat($output_dir,"shots.xml");
+
+    eval {
+	$plugin->{'parser'}->parsefile($shots_filename);
+    };
+    
+    if ($@) {
+	print $outhandle "videoconvert.pm: skipping $shots_filename as not conformant to Hive shot syntax\n" if ($self->{'verbosity'} > 1);
+	print $outhandle "\n Perl Error:\n $@\n" if ($self->{'verbosity'}>2);
+	return 0;
+    }
+
+}
+
+sub associate_keyframes_old
+{
+    my ($self) = shift(@_);
+
+    my ($doc_obj,$section,$plugin) = @_;
+
+    my $output_dir = $self->{'cached_dir'};
+
+    my $count = 1;
+    foreach my $kframe_file (@{$plugin->{'keyframe_fnames'}}) {
+
+	my $kframe_filename = &util::filename_cat($output_dir,$kframe_file);
+	$doc_obj->associate_file($kframe_filename,"keyframe$count.jpg","image/jpeg",
+				 $section);
+	$count++;
+    }
+
+    $doc_obj->add_utf8_metadata($section,"NumKeyframes",scalar(@{$plugin->{'keyframe_fnames'}}));
+
+
+    # *****
+    # $doc_obj->add_metadata ($section, "thumblist", $plugin->{'flowplayer_thumblist'});
+
+}
+
+sub associate_keyframes
+{
+    my ($self) = shift(@_);
+
+    my ($doc_obj,$section,$plugin) = @_;
+
+    my $output_dir = $self->{'cached_dir'};
+    my $timeline = $plugin->{'keyframe_timeline'};
+    
+    my $count = 1;
+
+    foreach my $t (sort { $timeline->{$a}->{'keyframeindex'} <=> $timeline->{$b}->{'keyframeindex'} } keys %$timeline)
+    {
+	my $kframe_file = $timeline->{$t}->{'thumb'};
+	my $timestamp = $timeline->{$t}->{'timestamp'};
+
+	my $kframe_filename = &util::filename_cat($output_dir,$kframe_file);
+	$doc_obj->associate_file($kframe_filename,"keyframe$count.jpg","image/jpeg",
+				 $section);
+	$doc_obj->add_utf8_metadata($section,"KeyframeTimestamp",$timestamp);
+
+	$count++;
+    }
+
+    $doc_obj->add_utf8_metadata($section,"NumKeyframes",scalar(@{$plugin->{'keyframe_fnames'}}));
+
+
+    # *****
+    # $doc_obj->add_metadata ($section, "thumblist", $plugin->{'flowplayer_thumblist'});
+}
+
+
+
+sub ffmpeg_monitor_init
+{
+    my $saved_record_sep = $/;
+    $/ = "\r";
+
+    my $saved_buffer_len = $|;
+    $| = 1;
+
+    my $saved_rec = { 'saved_record_sep' => $saved_record_sep,
+		      'saved_buffer_len' => $saved_buffer_len };
+
+    return $saved_rec;
+}
+
+
+
+sub ffmpeg_monitor_deinit
+{
+    my ($saved_rec) = @_;
+
+    my $saved_record_sep = $saved_rec->{'saved_record_sep'};
+    my $saved_buffer_len = $saved_rec->{'saved_buffer_len'};
+
+    $/ = $saved_record_sep;
+    $| = $saved_buffer_len;
+}
+
+
+sub ffmpeg_monitor_line
+{
+    my ($line) = @_;
+    
+    my $had_error = 0;
+    my $generate_dot = 0;
+
+    if ($line =~ m/^frame=/) 
+    {
+	$generate_dot = 1;
+    }
+
+    return ($had_error,$generate_dot);
+}
+
+
+sub flvtool2_monitor_line
+{
+    my ($line) = @_;
+
+    my $had_error = 0;
+    my $generate_dot = 1;
+
+    if ($line =~ m/\s+\- /) {
+	# ignore tabulated output printed at end of command
+	$generate_dot = 0;
+    }
+    
+    if ($line =~ m/^Error:/i) {
+	$had_error = 1;
+    }
+
+    return ($had_error,$generate_dot);
+}
+
+
+
+
+
+1;
Index: extensions/gsdl-video/trunk/setup.bash
===================================================================
--- extensions/gsdl-video/trunk/setup.bash	(revision 18425)
+++ extensions/gsdl-video/trunk/setup.bash	(revision 18425)
@@ -0,0 +1,35 @@
+
+extdesc="the Video Extension"
+
+if [ "x$GEXTVIDEO" = "x" ] ; then
+  # These will need to be edited to suit your installation
+  export GEXT_VIDEO_SERVER=http://www.greenstone.org
+  export GEXT_VIDEO_PREFIX=/greenstone-videostream
+
+
+  export GEXTVIDEO=`pwd`
+  export GEXTVIDEO_INSTALLED=$GEXTVIDEO/installed
+
+  export PATH=$GEXTVIDEO_INSTALLED/server/bin:$GEXTVIDEO_INSTALLED/cmdline/bin:$PATH
+
+  if [ "x$LD_LIBRARY_PATH" = "x" ] ; then
+    export LD_LIBRARY_PATH=$GEXTVIDEO_INSTALLED/server/lib:$GEXTVIDEO_INSTALLED/cmdline/lib
+  else
+    export LD_LIBRARY_PATH=$GEXTVIDEO_INSTALLED/server/lib:$GEXTVIDEO_INSTALLED/cmdline/lib:$LD_LIBRARY_PATH
+  fi
+
+  if [ -e "packages/devel" ] ; then
+    export LD_LIBRARY_PATH=$GEXTVIDEO_INSTALLED/devel/lib:$LD_LIBRARY_PATH
+  fi
+
+  if [ "x$GSDLEXTS" = "x" ] ; then
+    export GSDLEXTS=video
+  else 
+    export GSDLEXTS=$GSDLEXTS:video
+  fi
+
+
+  echo "+Your environment is now setup for $extdesc"
+else
+  echo "+Your environment is already setup for $extdesc"
+fi
