Description: <short summary of the patch>
 TODO: Put a short summary on the line above and replace this paragraph
 with a longer explanation of this change. Complete the meta-information
 with other relevant fields (see below for details). To make it easier, the
 information below has been extracted from the changelog. Adjust it or drop
 it.
 .
 ivtools (1.2.11a4-1) unstable; urgency=medium
 .
   * new upstream release, removes (unused) IUE support
   * track upstream changes (bug fixes)
Author: Barak A. Pearlmutter <bap@debian.org>

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: https://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: 2020-06-07

--- ivtools-1.2.11a4.orig/INSTALL.OLD
+++ ivtools-1.2.11a4/INSTALL.OLD
@@ -4,7 +4,7 @@
 
 Instructions for building ivtools-1.2.11 from source, the short version:
 
-        cp Makefile.orig Makefile
+        cp Makefile.orig Makefile // if cloned from github
 	./configure
 	make
 	su -c "make install"
@@ -20,16 +20,16 @@ Instructions for building ivtools-1.2.11
 2. The configure script tests for the presence of imake, and builds it from a source copy
    within ivtools if necessary.
 
-3. The usual two struggles with the configure script are defining CPU and XCONFIGDIR. If
-   they fail they can be manually edited into config/config.mk after running configure.
-   CPU has to match one of the config/site.def.$CPU files.  XCONFIGDIR is the complete
-   pathname for wherever you have X11/lib/X11/config.
+3. The usual two problems with the configure script are determining the CPU and XCONFIGDIR
+   that it writes into config/config.mk. If this fails they can be manually edited into
+   config/config.mk after running configure.  CPU has to match one of the
+   config/site.def.$CPU files.  XCONFIGDIR is the complete pathname for wherever you
+   find X11/lib/X11/config.  If editing XCONFIGDIR in config.mk doesn't work, try explicitly
+   providing --x-includes and --x-libraries to the configure script.
 
 - Scott Johnston, May 2020
 
 
-And if that doesn't work...
-
 Instructions for building ivtools-1.2.11 from source, the long version:
 
 0. Compilation Environment
--- /dev/null
+++ ivtools-1.2.11a4/m4/ax_compiler_vendor.m4
@@ -0,0 +1,117 @@
+# ===========================================================================
+#    https://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_COMPILER_VENDOR
+#
+# DESCRIPTION
+#
+#   Determine the vendor of the C, C++ or Fortran compiler.  The vendor is
+#   returned in the cache variable $ax_cv_c_compiler_vendor for C,
+#   $ax_cv_cxx_compiler_vendor for C++ or $ax_cv_fc_compiler_vendor for
+#   (modern) Fortran.  The value is one of "intel", "ibm", "pathscale",
+#   "clang" (LLVM), "cray", "fujitsu", "sdcc", "sx", "portland" (PGI), "gnu"
+#   (GCC), "sun" (Oracle Developer Studio), "hp", "dec", "borland",
+#   "comeau", "kai", "lcc", "sgi", "microsoft", "metrowerks", "watcom",
+#   "tcc" (Tiny CC) or "unknown" (if the compiler cannot be determined).
+#
+#   To check for a Fortran compiler, you must first call AC_FC_PP_SRCEXT
+#   with an appropriate preprocessor-enabled extension.  For example:
+#
+#     AC_LANG_PUSH([Fortran])
+#     AC_PROG_FC
+#     AC_FC_PP_SRCEXT([F])
+#     AX_COMPILER_VENDOR
+#     AC_LANG_POP([Fortran])
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+#   Copyright (c) 2008 Matteo Frigo
+#   Copyright (c) 2018-19 John Zaitseff <J.Zaitseff@zap.org.au>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 30
+
+AC_DEFUN([AX_COMPILER_VENDOR], [dnl
+    AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, [dnl
+	dnl  If you modify this list of vendors, please add similar support
+	dnl  to ax_compiler_version.m4 if at all possible.
+	dnl
+	dnl  Note: Do NOT check for GCC first since some other compilers
+	dnl  define __GNUC__ to remain compatible with it.  Compilers that
+	dnl  are very slow to start (such as Intel) are listed first.
+
+	vendors="
+		intel:		__ICC,__ECC,__INTEL_COMPILER
+		ibm:		__xlc__,__xlC__,__IBMC__,__IBMCPP__,__ibmxl__
+		pathscale:	__PATHCC__,__PATHSCALE__
+		clang:		__clang__
+		cray:		_CRAYC
+		fujitsu:	__FUJITSU
+		sdcc:		SDCC,__SDCC
+		sx:		_SX
+		portland:	__PGI
+		gnu:		__GNUC__
+		sun:		__SUNPRO_C,__SUNPRO_CC,__SUNPRO_F90,__SUNPRO_F95
+		hp:		__HP_cc,__HP_aCC
+		dec:		__DECC,__DECCXX,__DECC_VER,__DECCXX_VER
+		borland:	__BORLANDC__,__CODEGEARC__,__TURBOC__
+		comeau:		__COMO__
+		kai:		__KCC
+		lcc:		__LCC__
+		sgi:		__sgi,sgi
+		microsoft:	_MSC_VER
+		metrowerks:	__MWERKS__
+		watcom:		__WATCOMC__
+		tcc:		__TINYC__
+		unknown:	UNKNOWN
+	"
+	for ventest in $vendors; do
+	    case $ventest in
+		*:)
+		    vendor=$ventest
+		    continue
+		    ;;
+		*)
+		    vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")"
+		    ;;
+	    esac
+
+	    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[
+#if !($vencpp)
+      thisisanerror;
+#endif
+	    ]])], [break])
+	done
+
+	ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1`
+    ])
+])dnl
--- ivtools-1.2.11a4.orig/src/ComTerp/comfunc.h
+++ ivtools-1.2.11a4/src/ComTerp/comfunc.h
@@ -178,7 +178,7 @@ public:
 
     virtual boolean post_eval() { return false; }
     virtual const char* docstring() { return "%s: no docstring method defined"; }
-    const char* docstring2() { return _docstring2 ? _docstring2 : docstring(); }
+    const char* docstring2() { return _docstring2; }
     void docstring2(const char* str) { delete _docstring2; _docstring2 = strnew(str); }
     static int bintest(const char* name);
     static boolean bincheck(const char* name);
--- ivtools-1.2.11a4.orig/src/ComTerp/comterp.cc
+++ ivtools-1.2.11a4/src/ComTerp/comterp.cc
@@ -416,16 +416,20 @@ void ComTerp::eval_expr_internals(int pe
 	} else
 	  push_stack(ComValue::nullval());
       } else {
+	// cerr << "looking up " << sv.symbol_ptr() << "\n";
+	const char* funcname = sv.symbol_ptr();
         ComValue val = lookup_symval(sv);
         if(val.is_object(FuncObj::class_symid())) {
           EvalFunc ef(this);
           if(val.narg()!=val.nkey()) {
-            fprintf(stderr, "free format args not yet supported for custom funcs\n");
-            exit(1);
+            fprintf(stderr, "free format args not yet supported for custom funcs (%s)\n", funcname);
+            push_stack(ComValue::nullval());
+	    return;
 	  }
           if(val.narg()==0) {
-            fprintf(stderr, "keyword arguments needed for custom func invoking\n");
-            exit(1);
+            fprintf(stderr, "keyword arguments needed for custom func invoking (%s)\n", funcname);
+            push_stack(ComValue::nullval());
+	    return;
 	  }
           AttributeList* al = new AttributeList();
           for(int i=0; i<val.narg(); i++) {
@@ -515,7 +519,7 @@ void ComTerp::load_sub_expr() {
       } 
     }
     _pfoff++;
-    if ((stack_top().type() == ComValue::CommandType || stack_top().is_funcobj()) && 
+    if ((stack_top().type() == ComValue::CommandType || stack_top().is_funcobj(this)) && 
 	!_pfcomvals[_pfoff-1].pedepth()) break;
   }
   
@@ -605,7 +609,7 @@ int ComTerp::post_eval_expr(int tokcnt,
 	offset++;
 	if (_pfcomvals[offset-1].pedepth()!=pedepth)
 	  continue;
-	if ((stack_top().is_type(ComValue::CommandType) || stack_top().is_funcobj()) 
+	if ((stack_top().is_type(ComValue::CommandType) || stack_top().is_funcobj(this)) 
 	    && stack_top().pedepth() == pedepth) break;
       }
 #ifdef POSTEVAL_EXPERIMENT 
@@ -1198,13 +1202,14 @@ void ComTerp::add_defaults() {
     add_command("minus", new MinusFunc(this));
     add_command("mpy", new MpyFunc(this));
     add_command("div", new DivFunc(this));
-    add_command("mod", new ModFunc(this));
+    add_command("mod", new ModFunc(this), NULL, "mod (%) is the mod operator");
     add_command("min", new MinFunc(this));
     add_command("max", new MaxFunc(this));
     add_command("abs", new AbsFunc(this));
 
     add_command("assign", new AssignFunc(this));
-    add_command("mod_assign", new ModAssignFunc(this));
+    add_command("mod_assign", new ModAssignFunc(this), NULL, "mod_assign (%=) is the mod assign operator");
+    
     add_command("mpy_assign", new MpyAssignFunc(this));
     add_command("add_assign", new AddAssignFunc(this));
     add_command("sub_assign", new SubAssignFunc(this));
--- ivtools-1.2.11a4.orig/src/ComTerp/comvalue.cc
+++ ivtools-1.2.11a4/src/ComTerp/comvalue.cc
@@ -27,6 +27,8 @@
 #include <ComTerp/comfunc.h>
 #include <ComTerp/comvalue.h>
 #include <ComTerp/comterp.h>
+#include <ComTerp/ctrlfunc.h>
+#include <ComTerp/iofunc.h>
 #include <ComTerp/postfunc.h>
 #include <ComTerp/timefunc.h>
 #include <Attribute/attrlist.h>
@@ -315,7 +317,8 @@ ostream& operator<< (ostream& out, const
 	  break;
 	    
 	case ComValue::StreamType:
-	  out << "<stream:" << svp->stream_mode() << "(" << symbol_pntr(((ComFunc*)svp->stream_func())->funcid()) << ")" << ">";
+	  // out << "<stream:" << (svp->stream_mode()<0?"int":"ext") << "(" << symbol_pntr(((ComFunc*)svp->stream_func())->funcid()) << ")" << ">";
+	  out << "StreamObj";
 	  break;
 	    
 	case ComValue::CommandType:
@@ -431,12 +434,30 @@ boolean ComValue::isa(int id, int compid
   return false;
 }
 
-boolean ComValue::is_funcobj() {
+boolean ComValue::is_funcobj(ComTerp* comterp) {
   ComValue tv = *this;
-  if (!comterp()) return false;  // required for FuncObj in a ComValue
   if (is_symbol())
-    tv = ((ComTerp*)comterp())->lookup_symval(tv);
-  else
-    tv = *this;
+    tv = comterp->lookup_symval(tv);
   return tv.is_object(FuncObj::class_symid());
 }
+
+boolean ComValue::is_fileobj() {
+  ComValue tv = *this;
+  return tv.is_object(FileObj::class_symid());
+}
+
+boolean ComValue::is_pipeobj() {
+  ComValue tv = *this;
+  return tv.is_object(PipeObj::class_symid());
+}
+
+boolean ComValue::is_socketobj() {
+  ComValue tv = *this;
+  return tv.is_object(SocketObj::class_symid());
+}
+
+boolean ComValue::is_dateobj() {
+  ComValue tv = *this;
+  return tv.is_object(DateObj::class_symid());
+}
+
--- ivtools-1.2.11a4.orig/src/ComTerp/comvalue.h
+++ ivtools-1.2.11a4/src/ComTerp/comvalue.h
@@ -167,8 +167,16 @@ public:
     void linenum(unsigned ln) { _linenum=ln; }
     // Set line number of command in script file.
 
-    boolean is_funcobj();
-    // return true if ObjectType of FuncObj
+    boolean is_funcobj(ComTerp*);
+    // return true if ObjectType of FuncObj of symbol resolves to same
+    boolean is_fileobj();
+    // return true if ObjectType of FileObj
+    boolean is_pipeobj();
+    // return true if ObjectType of PipeObj
+    boolean is_socketobj();
+    // return true if ObjectType of SocketObj
+    boolean is_dateobj();
+    // return true if ObjectType of DateObj
 
 protected:
     void zero_vals() { _narg = _nkey = _nids = _pedepth = _bquote = 0; }
--- ivtools-1.2.11a4.orig/src/ComTerp/helpfunc.cc
+++ ivtools-1.2.11a4/src/ComTerp/helpfunc.cc
@@ -188,8 +188,12 @@ void HelpFunc::execute() {
 	    *out << '\n';
 	  {
 	    char buffer[BUFSIZ];
-	    snprintf(buffer, BUFSIZ, 
-		     comfuncs[i]->docstring2(), symbol_pntr(command_ids[i]));
+	    if (comfuncs[i]->docstring2()!=NULL) {
+	      strncpy(buffer, comfuncs[i]->docstring2(), BUFSIZ-1);
+	    } else {
+	      snprintf(buffer, BUFSIZ, 
+		       comfuncs[i]->docstring(), symbol_pntr(command_ids[i]));
+	    }
 	    *out << buffer;
 	  }
 	  printed = true;
@@ -215,8 +219,12 @@ void HelpFunc::execute() {
 		  out->put('\n');
 		{
 		  char buffer[BUFSIZ];
-		  snprintf(buffer, BUFSIZ, 
-			   comfunc->docstring2(), symbol_pntr(value->command_symid()));
+		  if (comfunc->docstring2()!=NULL) {
+		    strncpy(buffer, comfunc->docstring2(), BUFSIZ-1);
+		  } else {
+  		    snprintf(buffer, BUFSIZ, 
+			     comfunc->docstring(), symbol_pntr(value->command_symid()));
+		  }
 		  *out << buffer;
 		}
 	      } else 
@@ -258,8 +266,21 @@ void HelpFunc::execute() {
 OptableFunc::OptableFunc(ComTerp* comterp) : ComFunc(comterp) {
 }
 
-void OptableFunc::execute() {
+  void OptableFunc::execute() {
+    
+  static int bypri_symid = symbol_add("bypri");
+  ComValue bypriflag(stack_key(bypri_symid));
+  static int byopr_symid = symbol_add("byopr");
+  ComValue byoprflag(stack_key(byopr_symid));
+  static int bycom_symid = symbol_add("bycom");
+  ComValue bycomflag(stack_key(bycom_symid));
+  
   reset_stack();
-  opr_tbl_print(stdout, OPBY_PRIORITY);
+  int sort = OPBY_PRIORITY;
+  if (bycomflag.is_true()) { sort = OPBY_COMMAND; }
+  if (byoprflag.is_true()) { sort = OPBY_OPERATOR; }
+  if (bypriflag.is_true()) { sort = OPBY_PRIORITY; }
+  
+  opr_tbl_print(stdout, sort);
   return;
 }
--- ivtools-1.2.11a4.orig/src/ComTerp/helpfunc.h
+++ ivtools-1.2.11a4/src/ComTerp/helpfunc.h
@@ -53,7 +53,7 @@ public:
     virtual void execute();
 
     virtual const char* docstring() { 
-      return "%s() -- print contents of operator table"; }
+      return "%s(:bypri :byopr :bycom) -- print contents of operator table"; }
 };
 
 #endif /* !defined(_helpfunc_h) */
--- ivtools-1.2.11a4.orig/src/ComTerp/iofunc.cc
+++ ivtools-1.2.11a4/src/ComTerp/iofunc.cc
@@ -63,8 +63,12 @@ FileObj::FileObj(FILE* fptr) {
   _fptr = fptr;
 }
 
-FileObj::~FileObj() { 
+void FileObj::close() {
   if( _fptr && _fptr!=stdin && _filename) _pipe ? pclose(_fptr) : fclose(_fptr);
+}
+
+FileObj::~FileObj() { 
+  close();
   delete _filename;
   delete _mode;
 }
@@ -380,6 +384,7 @@ void OpenFileFunc::execute() {
       (strcmp(modev.string_ptr(),"rw")==0 || strcmp(modev.string_ptr(),"wr")==0)) {
     PipeObj* pipeobj = new PipeObj(filenamev.string_ptr());
     ComValue retval(PipeObj::class_symid(), (void*)pipeobj);
+    fprintf(stderr, "ready to push retval of type %s and class %s\n", retval.type_name(), retval.class_name());
     push_stack(retval);
 #ifdef HAVE_ACE
     if (Component::use_unidraw()) {
--- ivtools-1.2.11a4.orig/src/ComTerp/iofunc.h
+++ ivtools-1.2.11a4/src/ComTerp/iofunc.h
@@ -77,6 +77,7 @@ class FileObj {
   const char* filename() { return _filename; }
   const char* mode() { return _mode; }
   FILE* fptr() { return _fptr; }
+  void close();
 
  protected:
   char* _filename;
--- ivtools-1.2.11a4.orig/src/ComTerp/numfunc.cc
+++ ivtools-1.2.11a4/src/ComTerp/numfunc.cc
@@ -25,6 +25,7 @@
 #include <ComTerp/numfunc.h>
 #include <ComTerp/comvalue.h>
 #include <ComTerp/comterp.h>
+#include <ComTerp/timefunc.h>
 #include <Unidraw/iterator.h>
 #include <Attribute/attrlist.h>
 #include <Attribute/lexscan.h>
@@ -279,6 +280,19 @@ void AddFunc::execute() {
         }
         break;
 
+    case ComValue::ObjectType:
+      {
+	if (operand1.is_dateobj() && operand2.is_int()) {
+	  DateObj *dateobj = new DateObj((DateObj*)operand1.geta(DateObj::class_symid()));
+          int addend = operand2.int_val();
+	  *dateobj->date() = ((const Date)*dateobj->date()) + addend;
+	  result = ComValue(DateObj::class_symid(), (void*)dateobj);
+	} else {
+	  fprintf(stderr, "Unhandled add operand1 of class %s (line %d)\n", operand1.class_name(), funcstate()->linenum());
+	}
+      }
+      break;
+
     default: {
         fprintf(stderr, "Unhandled add operand1 type %s (line %d)\n", operand1.type_name(), funcstate()->linenum());
         }
@@ -310,8 +324,8 @@ SubFunc::SubFunc(ComTerp* comterp) : Num
 }
 
 void SubFunc::execute() {
-    ComValue& operand1 = stack_arg(0);
-    ComValue& operand2 = stack_arg(1);
+    ComValue operand1 = stack_arg(0);
+    ComValue operand2 = stack_arg(1);
     promote(operand1, operand2);
     ComValue result(operand1);
 
@@ -352,6 +366,23 @@ void SubFunc::execute() {
     case ComValue::DoubleType:
 	result.double_ref() = operand1.double_val() - operand2.double_val();
 	break;
+    case ComValue::ObjectType:
+      {
+        if (operand1.is_dateobj() && operand2.is_int()) {
+	  DateObj *dateobj = new DateObj((DateObj*)operand1.geta(DateObj::class_symid()));
+          int subtrahend = operand2.int_val();
+	  *dateobj->date() = ((const Date)*dateobj->date()) - subtrahend;
+	  result = ComValue(DateObj::class_symid(), (void*)dateobj);
+	} else {
+	  fprintf(stderr, "Unhandled subtraction operand1 of class %s (line %d)\n", operand1.class_name(), funcstate()->linenum());
+	}
+      }
+      break;
+
+    default: {
+        fprintf(stderr, "Unhandled subtraction operand1 type %s (line %d)\n", operand1.type_name(), funcstate()->linenum());
+        }
+        break;
     }
     reset_stack();
     push_stack(result);
@@ -361,7 +392,7 @@ MinusFunc::MinusFunc(ComTerp* comterp) :
 }
 
 void MinusFunc::execute() {
-    ComValue& operand1 = stack_arg(0);
+    ComValue operand1 = stack_arg(0);
     ComValue result(operand1);
 
     if (operand1.is_unknown()) {
@@ -410,8 +441,8 @@ MpyFunc::MpyFunc(ComTerp* comterp) : Num
 }
 
 void MpyFunc::execute() {
-    ComValue& operand1 = stack_arg(0);
-    ComValue& operand2 = stack_arg(1);
+    ComValue operand1 = stack_arg(0);
+    ComValue operand2 = stack_arg(1);
     promote(operand1, operand2);
     ComValue result(operand1);
 
@@ -615,8 +646,8 @@ DivFunc::DivFunc(ComTerp* comterp) : Num
 }
 
 void DivFunc::execute() {
-    ComValue& operand1 = stack_arg(0);
-    ComValue& operand2 = stack_arg(1);
+    ComValue operand1 = stack_arg(0);
+    ComValue operand2 = stack_arg(1);
     promote(operand1, operand2);
 
     if (operand1.is_unknown() || operand2.is_unknown()) {
@@ -697,8 +728,8 @@ ModFunc::ModFunc(ComTerp* comterp) : Num
 }
 
 void ModFunc::execute() {
-    ComValue& operand1 = stack_arg(0);
-    ComValue& operand2 = stack_arg(1);
+    ComValue operand1 = stack_arg(0);
+    ComValue operand2 = stack_arg(1);
     promote(operand1, operand2);
     ComValue result(operand1);
 
@@ -778,8 +809,8 @@ MinFunc::MinFunc(ComTerp* comterp) : Num
 }
 
 void MinFunc::execute() {
-    ComValue& operand1 = stack_arg(0);
-    ComValue& operand2 = stack_arg(1);
+    ComValue operand1 = stack_arg(0);
+    ComValue operand2 = stack_arg(1);
     promote(operand1, operand2);
     ComValue result(operand1);
 
@@ -842,8 +873,8 @@ MaxFunc::MaxFunc(ComTerp* comterp) : Num
 }
 
 void MaxFunc::execute() {
-    ComValue& operand1 = stack_arg(0);
-    ComValue& operand2 = stack_arg(1);
+    ComValue operand1 = stack_arg(0);
+    ComValue operand2 = stack_arg(1);
     promote(operand1, operand2);
     ComValue result(operand1);
 
@@ -907,7 +938,7 @@ AbsFunc::AbsFunc(ComTerp* comterp) : Num
 }
 
 void AbsFunc::execute() {
-    ComValue& operand1 = stack_arg(0);
+    ComValue operand1 = stack_arg(0);
     ComValue result(operand1);
 
     if (operand1.is_unknown()) {
@@ -1069,7 +1100,7 @@ FloorFunc::FloorFunc(ComTerp* comterp) :
 }
 
 void FloorFunc::execute() {
-    ComValue& operand1 = stack_arg(0);
+    ComValue operand1 = stack_arg(0);
     ComValue result(operand1);
     switch (result.type()) {
     case ComValue::CharType:
@@ -1102,7 +1133,7 @@ CeilFunc::CeilFunc(ComTerp* comterp) : N
 }
 
 void CeilFunc::execute() {
-    ComValue& operand1 = stack_arg(0);
+    ComValue operand1 = stack_arg(0);
     ComValue result(operand1);
     switch (result.type()) {
     case ComValue::CharType:
@@ -1135,7 +1166,7 @@ RoundFunc::RoundFunc(ComTerp* comterp) :
 }
 
 void RoundFunc::execute() {
-    ComValue& operand1 = stack_arg(0);
+    ComValue operand1 = stack_arg(0);
     ComValue result(operand1);
     switch (result.type()) {
     case ComValue::CharType:
--- ivtools-1.2.11a4.orig/src/ComTerp/numfunc.h
+++ ivtools-1.2.11a4/src/ComTerp/numfunc.h
@@ -111,7 +111,7 @@ public:
 
     virtual void execute();
     virtual const char* docstring() { 
-      return "%s is the mod operator"; }
+      return "%s (%) is the mod operator"; }
 
 };
 
--- ivtools-1.2.11a4.orig/src/ComTerp/strmfunc.cc
+++ ivtools-1.2.11a4/src/ComTerp/strmfunc.cc
@@ -23,8 +23,10 @@
  */
 
 #include <ComTerp/strmfunc.h>
+#include <ComTerp/comfunc.h>
 #include <ComTerp/comvalue.h>
 #include <ComTerp/comterp.h>
+#include <ComTerp/iofunc.h>
 #include <Attribute/attrlist.h>
 #include <Attribute/attribute.h>
 #include <Unidraw/iterator.h>
@@ -101,7 +103,9 @@ void StreamFunc::execute() {
       ComValue stream(snfunc, avl);
       stream.stream_mode(-1); // for internal use (use by this func)
       push_stack(stream);
-    } else if (operand1.is_attributelist()) {
+    } 
+
+    else if (operand1.is_attributelist()) {
       AttributeValueList* avl = new AttributeValueList();
       AttributeList* al = (AttributeList*)operand1.obj_val();
       Iterator i;
@@ -114,7 +118,9 @@ void StreamFunc::execute() {
       ComValue stream(snfunc, avl);
       stream.stream_mode(-1); // for internal use (use by this func)
       push_stack(stream);
-    } else {
+    }
+
+    else {
       AttributeValueList* avl = new AttributeValueList();
       avl->Append(new AttributeValue(operand1));
       ComValue stream(snfunc, avl);
@@ -143,6 +149,24 @@ void StreamNextFunc::execute() {
     Iterator i;
     avl->First(i);
     AttributeValue* retval = avl->Done(i) ? nil : avl->GetAttrVal(i);
+
+    if (((ComValue*)retval)->is_fileobj() || ((ComValue*)retval)->is_pipeobj()) {
+      ComValue fpobj((ComValue*)retval);
+      comterp()->push_stack(fpobj);
+      GetStringFunc func(comterp());
+      func.exec(1,0);
+      if (comterp()->stack_top().is_null()) {
+	if (fpobj.is_fileobj()) {
+	  FileObj *fileobj = (FileObj*)fpobj.geta(FileObj::class_symid());
+	  fileobj->close();
+	} else if (fpobj.is_pipeobj()) {
+	  PipeObj *pipeobj = (PipeObj*)fpobj.geta(PipeObj::class_symid());
+	  pipeobj->close();
+	}
+      }
+      return;
+    }
+    
     if (retval) {
       push_stack(*retval);
       avl->Remove(retval);
--- ivtools-1.2.11a4.orig/src/ComTerp/strmfunc.h
+++ ivtools-1.2.11a4/src/ComTerp/strmfunc.h
@@ -50,7 +50,7 @@ public:
     virtual void execute();
     virtual boolean post_eval() { return true; }
     virtual const char* docstring() { 
-      return "strm=%s(ostrm|list|attrlist|val) -- copy stream or convert list (unary $)"; }
+      return "strm=%s(ostrm|list|attrlist|val|fileobj|pipeobj) -- copy stream or convert list (unary $)"; }
 
     CLASS_SYMID("StreamFunc");
 
--- ivtools-1.2.11a4.orig/src/ComTerp/timefunc.cc
+++ ivtools-1.2.11a4/src/ComTerp/timefunc.cc
@@ -40,6 +40,14 @@ DateObj::DateObj(long datenum) {
   _date = new Date(datenum);
 }
 
+DateObj::DateObj(DateObj *dateobj) {
+  _date = new Date(*dateobj->date());
+}
+
+DateObj::DateObj() {
+  _date = new Date();
+}
+
 DateObj::~DateObj() {
   delete _date;
 }
@@ -71,6 +79,8 @@ void DateFunc::execute() {
   } else if (datev.is_string()) {
     dateobj = new DateObj(datev.string_ptr());
     fresh = true;
+  } else if (datev.is_null()) {
+    dateobj = new DateObj();
   } else {
     dateobj = (DateObj*)datev.geta(DateObj::class_symid());
   }
--- ivtools-1.2.11a4.orig/src/ComTerp/timefunc.h
+++ ivtools-1.2.11a4/src/ComTerp/timefunc.h
@@ -35,6 +35,8 @@ class DateObj {
  public:
   DateObj(const char* datestr);
   DateObj(long datenum); // 1/1/1901 is day zero
+  DateObj(DateObj*); // copy
+  DateObj(); // today
   virtual ~DateObj();
 
   Date *date() {return _date;}
@@ -52,7 +54,7 @@ public:
 
     virtual void execute();
     virtual const char* docstring() { 
-      return "dateobj|int = %s(num|str|dateobj :day :month :year :daymo) -- create date from days since 1/1/1901 or string"; }
+      return "dateobj|int = %s([num|str|dateobj] :day :month :year :daymo) -- create date from days since 1/1/1901 or string"; }
 };
 
 #endif /* !defined(_datefunc_h) */
--- ivtools-1.2.11a4.orig/src/ComUtil/optable.cc
+++ ivtools-1.2.11a4/src/ComUtil/optable.cc
@@ -98,7 +98,7 @@ struct _opr_tbl_default_entry {
   BOOLEAN rtol;
   unsigned optype;
 } DefaultOperatorTable[] = {
-  {" ",          "space",              140,        FALSE,      OPTYPE_BINARY },
+  // {" ",          "space",              140,        FALSE,      OPTYPE_BINARY }, // I have no recall why this is here
   {".",          "dot",                130,        FALSE,      OPTYPE_BINARY },
   {"`",          "bquote",             125,        TRUE,       OPTYPE_UNARY_PREFIX },
   {"!",          "negate",             110,        TRUE,       OPTYPE_UNARY_PREFIX },
@@ -443,6 +443,66 @@ int commid;			/* Id of command in symbol
 
 }
 
+static void merge_sort(int* arr, int l, int r, int(*gtfunc)(int a, int b)) {
+  if (r>l) {
+    // Find the middle point to divide the array into two halves:
+    int m = (l+r)/2;
+
+    // First half
+    merge_sort(arr, l, m, gtfunc);
+
+    // Second half
+    merge_sort(arr, m+1, r, gtfunc);
+    
+    // Merge the two halves
+    int nf = m-l+1;
+    int front[nf];
+    for(int i=0; i<nf; i++) {
+      front[i]=arr[l+i];
+    }
+      
+    int nb = r-m;
+    int back[nb];
+    for(int i=0; i<nb; i++) {
+      back[i]=arr[m+i+1];
+     }
+
+    int fi = 0;
+    int bi = 0;
+    int curr = l;
+    
+     while(fi<nf || bi<nb) {
+      if(fi==nf) {
+	arr[curr] = back[bi++];
+      } else if (bi==nb) {
+	arr[curr] = front[fi++];
+      } else if ((*gtfunc)(front[fi], back[bi])) {
+	arr[curr] = front[fi++];
+      } else {
+	arr[curr] = back[bi++];
+      }
+       curr++;
+    }
+   }
+}
+
+static int gt_pri(int a, int b) {
+  return OperatorTable[a].priority > OperatorTable[b].priority;
+}
+
+static int gt_com(int a, int b) {
+  char *astr = (char*)COMMAND(a);
+  char *bstr = (char*)COMMAND(b);
+  while (*astr != '\0' || *bstr != '\0') {
+    if(*astr=='\0') { return 1; }
+    if(*bstr=='\0') { return 0; }
+    if (*astr<*bstr) { return 1; }
+    if (*astr>*bstr) { return 0; }
+    astr++;
+    bstr++;
+  }
+  return 0;
+}
 
 
 /*!
@@ -501,21 +561,34 @@ int counter;
       return FUNCOK;
       }
 
+/* Create indirect for index to reflect sort if needed */
+   int indirect[NumOperators];
+   for(int i=0; i<NumOperators; i++) {
+      indirect[i]=i;
+   }
+
+/* merge sort by priority or command name if needed */ 
+   if (by==OPBY_PRIORITY ) {
+     merge_sort(indirect, 0, NumOperators-1, &gt_pri);
+   } else if (by==OPBY_COMMAND) {
+     merge_sort(indirect, 0, NumOperators-1, &gt_com);
+   }
+
 /* Print contents of table sorted by operator */
    fprintf( outfile, "Operator   Command            Priority   RtoL   Type\n" );
    fprintf( outfile, "--------   -------            --------   ----   ----\n" );
    for( index=0; index<NumOperators; index++ ) {
-      counter = fprintf( outfile, "%s", OPSTR( index )); 
+      counter = fprintf( outfile, "%s", OPSTR( indirect[index] )); 
       while( counter++ < 11 ) putc( ' ', outfile );
-      counter += fprintf( outfile, "%s", COMMAND( index ));
+      counter += fprintf( outfile, "%s", COMMAND( indirect[index] ));
       while( counter++ < 31 ) putc( ' ', outfile );
-      counter += fprintf( outfile, "%d", OperatorTable[ index ].priority );
+      counter += fprintf( outfile, "%d", OperatorTable[ indirect[index] ].priority );
       while( counter++ < 43 ) putc( ' ', outfile );
       fprintf( outfile, "%c      %s\n",
-	 OperatorTable[ index ].rtol ? 'Y' : 'N',
-	 OperatorTable[ index ].optype == OPTYPE_UNARY_POSTFIX
+	 OperatorTable[ indirect[index] ].rtol ? 'Y' : 'N',
+	 OperatorTable[ indirect[index] ].optype == OPTYPE_UNARY_POSTFIX
 	    ? "UNARY POSTFIX"
-	    : ( OperatorTable[ index ].optype == OPTYPE_UNARY_PREFIX
+	    : ( OperatorTable[ indirect[index] ].optype == OPTYPE_UNARY_PREFIX
 	       ? "UNARY PREFIX" : "BINARY" ));
       }
 
--- ivtools-1.2.11a4.orig/src/InterViews/smf_kit.cc
+++ ivtools-1.2.11a4/src/InterViews/smf_kit.cc
@@ -89,7 +89,7 @@ static const int num_colors = 13;
 static const unsigned int checkmark_width = 32;
 static const unsigned int checkmark_height = 12;
 
-static char checkmark_bits[] = {
+static unsigned char checkmark_bits[] = {
     0x00, 0x00, 0x3e, 0x00, 0x00, 0xc0, 0x0f, 0x00,
     0x04, 0xf0, 0x03, 0x00, 0x1e, 0xf8, 0x00, 0x00,
     0x3f, 0x3e, 0x00, 0x00, 0xbf, 0x1f, 0x00, 0x00,
@@ -101,7 +101,7 @@ static char checkmark_bits[] = {
 static const unsigned int shadow1_width = 32;
 static const unsigned int shadow1_height = 13;
 
-static char shadow1_bits[] = {
+static unsigned char shadow1_bits[] = {
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0xc0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
@@ -114,7 +114,7 @@ static char shadow1_bits[] = {
 static const unsigned int shadow2_width = 32;
 static const unsigned int shadow2_height = 5;
 
-static char shadow2_bits[] = {
+static unsigned char shadow2_bits[] = {
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00,
     0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x00,
     0x00, 0x00, 0x03, 0x00
--- ivtools-1.2.11a4.orig/src/OverlayUnidraw/ovimport.cc
+++ ivtools-1.2.11a4/src/OverlayUnidraw/ovimport.cc
@@ -144,13 +144,13 @@ const char PBMA_MAGIC_BYTES[2] = {'P', '
 const char PGMA_MAGIC_BYTES[2] = {'P', '2'};
 const char PPMA_MAGIC_BYTES[2] = {'P', '3'};
 
-const char GZIP_MAGIC_BYTES[2] = {0x1f, 0x8b};
-const char COMPRESS_MAGIC_BYTES[2] = {0x1f, 0x9d};
+const char GZIP_MAGIC_BYTES[2] = {(char)0x1f, (char)0x8b};
+const char COMPRESS_MAGIC_BYTES[2] = {(char)0x1f, (char)0x9d};
 
-const char TIFF1_MAGIC_BYTES[2] = {0x4d, 0x4d}; /* TIFF with BIGENDIAN byte order */
-const char TIFF2_MAGIC_BYTES[2] = {0x49, 0x49}; /* TIFF with LITLEENDIAN byte order */
-const char SUN_MAGIC_BYTES[2] = {0x59, 0xa6}; /* Sun rasterfile (0x59a66a95) */
-const char JPEG_MAGIC_BYTES[2] = {0xff, 0xd8}; 
+const char TIFF1_MAGIC_BYTES[2] = {(char)0x4d, (char)0x4d}; /* TIFF with BIGENDIAN byte order */
+const char TIFF2_MAGIC_BYTES[2] = {(char)0x49, (char)0x49}; /* TIFF with LITLEENDIAN byte order */
+const char SUN_MAGIC_BYTES[2] = {(char)0x59, (char)0xa6}; /* Sun rasterfile (0x59a66a95) */
+const char JPEG_MAGIC_BYTES[2] = {(char)0xff, (char)0xd8}; 
 /*****************************************************************************/
 
 static void closef(FILE* file, boolean compressed) {
--- ivtools-1.2.11a4.orig/src/Unidraw/globals.cc
+++ ivtools-1.2.11a4/src/Unidraw/globals.cc
@@ -86,6 +86,7 @@ void GetLine (
     lineSize = i - begin;
 }
 
+#ifndef UnidrawCommon
 void GetAlignmentPoint (Graphic* gr, Alignment a, float& x, float& y) {
     float l, b, r, t;
 
@@ -131,6 +132,7 @@ void GetAlignmentPoint (Graphic* gr, Ali
 	    break;
     }
 }
+#endif
 
 void Ref (Resource* r) {
     if (r != nil) {
--- ivtools-1.2.11a4.orig/src/include/Makefile.am
+++ ivtools-1.2.11a4/src/include/Makefile.am
@@ -114,4 +114,4 @@ IV-X11/Xlib.h IV-X11/xbitmap.h IV-X11/xs
 ivstd/iosfwd ivstd/signal.h ivstd/string.h ivstd/leakchecker.h		\
 ivstd/malloc.h ivstd/stdio.h ivstd/math.h ivstd/nan.h			\
 ivstd/iostream.h ivstd/fstream.h ivstd/osfcn.h ivstd/stdlib.h		\
-ivstd/stream.h
+ivstd/stream.h ivstd/fstream ivstd/ignores.h
--- ivtools-1.2.11a4.orig/src/man/man1/comterp.1
+++ ivtools-1.2.11a4/src/man/man1/comterp.1
@@ -204,7 +204,7 @@ Evaluate single expression then exit.
 
 .SH LIST COMMANDS:
  
- lst=list([olst|strm|val] :strmlst :attr :size n) -- create list, copy list, or convert stream
+ lst=list([olst|strm|val|fileobj|pipeobj) :strmlst :attr :size n) -- create list, copy list, or convert stream
 
  val=at(list|attrlist|str n :set val :ins val) -- return (or set or insert after) nth item in a list or string
 
@@ -248,6 +248,8 @@ Evaluate single expression then exit.
 
  help(cmdname [cmdname ...] :all :posteval) -- help for commands
 
+ optable(:bypri :byopr :bycom) -- print contents of operator table
+
  val=trace([flag] :get) -- toggle or set trace mode
 
  pause([msgstr])  -- pause script execution until C/R
@@ -362,7 +364,7 @@ Evaluate single expression then exit.
 
  num=xnor(a b) -- bitwise XNOR (negated XOR)
 
- dateobj|int = date(num|str|dateobj :day :month :year :daymo :weekday) -- create date from days since 1/1/1901 or string
+ dateobj|int = date([num|str|dateobj] :day :month :year :daymo :weekday) -- create date from days since 1/1/1901 or string
 
 
 .SH ONLY IN SERVER MODE
