Patch:    ivtools-131007-scott-001
For:      ivtools-1.2.11
Author:   scott@wavesemi.com
Subject:  Miscellaneous fixes and extensions to ivtools

This is an intermediate patch to ivtools-1.2.11.  To apply, cd to the
top-level directory of the ivtools source tree (the directory with src
and config subdirs), and apply like this:

	patch -p0 <ThisFile

Then rebuild with "make;make install"


Index: src/ComTerp/debugfunc.h
===================================================================
--- src/ComTerp/debugfunc.h	(revision 7865)
+++ src/ComTerp/debugfunc.h	(revision 8205)
@@ -52,7 +52,7 @@
     virtual void execute();
     virtual void execute_body(ComValue&);
     virtual const char* docstring() { 
-	return "%s -- pause script execution until C/R"; }
+	return "%s([msgstr]) -- pause script execution until C/R"; }
     virtual boolean stepfunc() { return false; }
 
 };
Index: src/ComTerp/listfunc.c
===================================================================
--- src/ComTerp/listfunc.c	(revision 7865)
+++ src/ComTerp/listfunc.c	(revision 8205)
@@ -268,6 +268,9 @@
   static int all_symid = symbol_add("all");
   ComValue allv(stack_key(all_symid));
   boolean allflag = allv.is_true();
+  static int substr_symid = symbol_add("substr");
+  ComValue substrv(stack_key(substr_symid));
+  boolean substrflag = substrv.is_true();
   reset_stack();
 
   AttributeValueList *nvl = allflag ? new AttributeValueList : nil;
@@ -280,12 +283,18 @@
 	avl->First(it);
       int index= lastflag ? avl->Number()-1 : 0;
       while(!avl->Done(it)) {
+        int match;
 	AttributeValue* testv = avl->GetAttrVal(it);
-	comterp()->push_stack(*testv);
-	comterp()->push_stack(valv);
-	EqualFunc eqfunc(comterp());
-	eqfunc.exec(2,0);
-	if(comterp()->pop_stack().is_true()) {
+        if(!substrflag) {
+	  comterp()->push_stack(*testv);
+	  comterp()->push_stack(valv);
+	  EqualFunc eqfunc(comterp());
+	  eqfunc.exec(2,0);
+	  match =  comterp()->pop_stack().is_true();
+	} else {
+	  match = strstr(testv->string_ptr(), valv.string_ptr()) != NULL;
+	}
+	if(match) {
 	  if (allflag)
 	    nvl->Append(new AttributeValue(index, AttributeValue::IntType));
 	  else {
@@ -294,13 +303,14 @@
 	    return;
 	  }
 	}
+	
 	if (lastflag)
 	  avl->Prev(it);
 	else
 	  avl->Next(it);
 	index += lastflag ? -1 : 1;
       };
-
+      
   } else if (listorstrv.is_string()) {
 
       if (valv.is_char()) {
Index: src/ComTerp/listfunc.h
===================================================================
--- src/ComTerp/listfunc.h	(revision 7865)
+++ src/ComTerp/listfunc.h	(revision 8205)
@@ -85,14 +85,14 @@
 
 
 //: list index command for ComTerp.
-// val=index(list|str val|char|str :last :all) -- return index of value (or char or string) in list (or string), nil if not found.
+// val=index(list|str val|char|str :last :all :substr) -- return index of value (or char or string) in list (or string), nil if not found.
 class ListIndexFunc : public ComFunc {
 public:
     ListIndexFunc(ComTerp*);
 
     virtual void execute();
     virtual const char* docstring() { 
-      return "num=index(list|str val|char|str :last :all) -- return index of value (or char or string) in list (or string), nil if not found"; }
+      return "num=index(list|str val|char|str :last :all :substr) -- return index of value (or char or string) in list (or string), nil if not found"; }
 };
 
 #endif /* !defined(_listfunc_h) */
Index: src/ComTerp/symbolfunc.c
===================================================================
--- src/ComTerp/symbolfunc.c	(revision 7865)
+++ src/ComTerp/symbolfunc.c	(revision 8205)
@@ -481,8 +481,12 @@
   }
   else {
     const char* foundstr = strstr(string, nv.symbol_ptr());
-    n = afterflag ?  strlen(string)-(foundstr-string) : foundstr-string;
-    offset = afterflag ? foundstr-string : 0;
+    if(foundstr==NULL) {
+      push_stack(ComValue::nullval());
+      return;
+    }
+    n = afterflag ?  strlen(string)-(foundstr-string)-strlen(nv.symbol_ptr()) : foundstr-string;
+    offset = afterflag ? foundstr-string+strlen(nv.symbol_ptr()) : 0;
   };
   if(n>0) { 
     char buffer[n+1];
Index: src/ComTerp/iofunc.c
===================================================================
--- src/ComTerp/iofunc.c	(revision 7865)
+++ src/ComTerp/iofunc.c	(revision 8205)
@@ -116,24 +116,9 @@
   const char* fstr = formatstr.is_string() ? formatstr.string_ptr() : "nil";
   ComValue::comterp(comterp());
 
-#if __GNUC__<3
   streambuf* strmbuf = nil;
   if (stringflag.is_false() && strflag.is_false() &&
       symbolflag.is_false() && symflag.is_false()) {
-    filebuf * fbuf = new filebuf();
-    strmbuf = fbuf;
-    if (comterp()->handler()) {
-      int fd = Math::max(1, comterp()->handler()->get_handle());
-      fbuf->attach(fd);
-    } else
-      fbuf->attach(fileno(errflag.is_false() ? stdout : stderr));
-  } else {
-    strmbuf = new std::strstreambuf();
-  }
-#else
-  streambuf* strmbuf = nil;
-  if (stringflag.is_false() && strflag.is_false() &&
-      symbolflag.is_false() && symflag.is_false()) {
     fileptr_filebuf * fbuf = nil;
     if (comterp()->handler() && fileobjv.is_unknown() && errflag.is_false() && outflag.is_false()) {
       fbuf = new fileptr_filebuf(comterp()->handler() && comterp()->handler()->wrfptr() 
@@ -151,7 +136,6 @@
     strmbuf = fbuf;
   } else
     strmbuf = new std::strstreambuf();
-#endif
   ostream out(strmbuf);
 
   int narg = nargsfixed();
Index: src/man/man1/comterp.1
===================================================================
--- src/man/man1/comterp.1	(revision 7865)
+++ src/man/man1/comterp.1	(revision 8205)
@@ -8,20 +8,23 @@
 remote
 .br
 .B comterp 
-server 'portnum'
+server "portnum"
 .br
 .B comterp 
-logger 'portnum'
+logger "portnum"
 .br
 .B comterp 
-client 'host' 'portnum' ['file']
+client "host" "portnum" ["file"]
 .br
 .B comterp 
-telcat 'host' 'portnum' ['file']
+telcat "host" "portnum" ["file"]
 .br
 .B comterp 
-run 'file'  
+run "file"  
 .br
+.B comterp 
+"expr"
+.br
 .SH DESCRIPTION
 comterp demonstrates the command interpreter incorporated into
 ivtools. A user (or client program) can interact with comterp via
@@ -53,33 +56,36 @@
 Invoke a single command interpreter, like the default, and include a
 remote command for accessing other comterp's in server mode.
 
-comterp server 'portnum'
+comterp server "portnum"
 
 Listens for and accept connections on portnum, then setup a command
 interpreter to wait for and process commands from that connection.
 
-comterp logger 'portnum'
+comterp logger "portnum"
 
 Listens for and accept connections on portnum, then simply forward
 the incoming messages to stdout, while ack'ing back with newlines. For
 debugging purposes, not really a use of the interpreter.
 
-comterp client 'host' 'portnum' ['file']
+comterp client "host" "portnum" ["file"]
 
 Connect to a portnum on a host and send/receive new-line terminated
 text buffers.  For debugging purposes, not really a use of the
 interpreter.
 
-comterp telcat 'host' 'portnum' ['file']
+comterp telcat "host" "portnum" ["file"]
 
 Connect to a portnum on a host, cat the file, then close the
 connection.  Not really a use of the interpreter either.
 
-comterp run 'file'
+comterp run "file"
 
 Run contents of file then exit.
 
+comterp "expr"
 
+Evaluate single expression then exit.
+
 .SH OPERATOR TABLE
 .nf
     Operators  Command Name   Priority    Order       Type
@@ -202,7 +208,7 @@
 
  num=size(list|attrlist|str) -- return size of a list (or string)
 
- val=index(list|str val|char|str :last :all) -- return index of value (or char or string) in list (or string), nil if not found.
+ val=index(list|str val|char|str :last :all :substr) -- return index of value (or char or string) in list (or string), nil if not found.
 
 .SH STREAM COMMANDS:
  
@@ -230,7 +236,7 @@
 
  val=trace([flag] :get) -- toggle or set trace mode
 
- pause()  -- pause script execution until C/R
+ pause([msgstr])  -- pause script execution until C/R
 
  step() -- toggle stepwise script execution
 
Index: src/GraphUnidraw/nodecomp.c
===================================================================
--- src/GraphUnidraw/nodecomp.c	(revision 7865)
+++ src/GraphUnidraw/nodecomp.c	(revision 8205)
@@ -178,23 +178,25 @@
     _node = new TopoNode(this);
     _reqlabel = true;
 
-    Picture* pic = new Picture();
-    SF_Ellipse* ellipse = new SF_Ellipse(0, 0, xradius, yradius, stdgraphic);
-    ellipse->SetPattern(unidraw->GetCatalog()->FindGrayLevel(1));
-    TextGraphic* txt = new TextGraphic(graph->GetFile(), stdgraphic);
-    ellipse->Align(4, txt, 4); // same as Center in IV-2_6/InterViews/alignment.h
-    pic->Append(ellipse, txt);
-    SetGraphic(pic);
-
-    GraphGraphic();
-
-    // kludge to fix ps: fonts are collected from comp\'s graphic, so we
-    // need to add the font to the picture\'s gs
-    pic->FillBg(ellipse->BgFilled() && !ellipse->GetBgColor()->None());
-    pic->SetColors(ellipse->GetFgColor(), ellipse->GetBgColor());
-    pic->SetPattern(ellipse->GetPattern());
-    pic->SetBrush(ellipse->GetBrush());
-    pic->SetFont(txt->GetFont());
+    if (unidraw) {
+      Picture* pic = new Picture();
+      SF_Ellipse* ellipse = new SF_Ellipse(0, 0, xradius, yradius, stdgraphic);
+      ellipse->SetPattern(unidraw->GetCatalog()->FindGrayLevel(1));
+      TextGraphic* txt = new TextGraphic(graph->GetFile(), stdgraphic);
+      ellipse->Align(4, txt, 4); // same as Center in IV-2_6/InterViews/alignment.h
+      pic->Append(ellipse, txt);
+      SetGraphic(pic);
+      
+      GraphGraphic();
+      
+      // kludge to fix ps: fonts are collected from comp\'s graphic, so we
+      // need to add the font to the picture\'s gs
+      pic->FillBg(ellipse->BgFilled() && !ellipse->GetBgColor()->None());
+      pic->SetColors(ellipse->GetFgColor(), ellipse->GetBgColor());
+      pic->SetPattern(ellipse->GetPattern());
+      pic->SetBrush(ellipse->GetBrush());
+      pic->SetFont(txt->GetFont());
+    }
 }
 
 NodeComp::NodeComp(OverlayComp* parent) : OverlayComp(nil, parent) {
Index: src/comterp_/main.c
===================================================================
--- src/comterp_/main.c	(revision 7865)
+++ src/comterp_/main.c	(revision 8205)
@@ -41,6 +41,7 @@
 #include <version.h>
 
 #include <ComTerp/comterpserv.h>
+#include <ComTerp/comvalue.h>
 
 
 #if BUFSIZ>1024
@@ -71,6 +72,8 @@
     boolean client_flag = argc>1 && strcmp(argv[1], "client") == 0;
     boolean telcat_flag = argc>1 && strcmp(argv[1], "telcat") == 0;
     boolean run_flag = argc>1 && strcmp(argv[1], "run") == 0;
+    boolean expr_flag = argc>1 && !server_flag && !logger_flag && 
+                        !remote_flag && !client_flag && !telcat_flag && !run_flag;
 
 #ifdef HAVE_ACE
     if (server_flag || logger_flag) {
@@ -253,6 +256,12 @@
 	terp->set_args(argc-3, argv+2);
 	terp->runfile(rfile);
 	return 0;
+      } if (expr_flag) {
+	terp->brief(1);
+	ComValue::comterp(terp);
+        ComValue comval(terp->run(argv[1]));
+        cout << comval << '\n';
+        return 0;
       } else {
 	
 	struct stat buf;
Index: src/comterp_/README
===================================================================
--- src/comterp_/README	(revision 7865)
+++ src/comterp_/README	(revision 8205)
@@ -4,11 +4,12 @@
 SYNOPSIS
      comterp
      comterp remote
-     comterp server 'portnum'
-     comterp logger 'portnum'
-     comterp client 'host' 'portnum' ['file']
-     comterp telcat 'host' 'portnum' ['file']
-     comterp run 'file'	
+     comterp server "portnum"
+     comterp logger "portnum"
+     comterp client "host" "portnum" ["file"]
+     comterp telcat "host" "portnum" ["file"]
+     comterp run "file"	
+     comterp "expr"
 
 DESCRIPTION
 
@@ -43,33 +44,37 @@
 remote command for accessing other comterp's in server mode.
 
 
-comterp server 'portnum'
+comterp server "portnum"
 
 Listens for and accept connections on portnum, then setup a command
 interpreter to wait for and process commands from that connection.
 
-comterp logger 'portnum'
+comterp logger "portnum"
 
 Listens for and accept connections on portnum, then simply forward
 the incoming messages to stdout, while ack'ing back with newlines. For
 debugging purposes, not really a use of the interpreter.
 
-comterp client 'host' 'portnum' ['file']
+comterp client "host" "portnum" ["file"]
 
 Connect to a portnum on a host and send/receive new-line terminated
 text buffers.  For debugging purposes, not really a use of the
 interpreter.
 
-comterp telcat 'host' 'portnum' ['file']
+comterp telcat "host" "portnum" ["file"]
 
 Connect to a portnum on a host, cat the file, then close the
 connection.  Not really a use of the interpreter either.
 
-comterp run 'file'
+comterp run "file"
 
 Run contents of file then exit.
 
+comterp "expr"
 
+Evaluate single expression then exit.
+
+
 OPERATOR TABLE
 
     Operators     Command Name         Priority    Order       Type
@@ -190,7 +195,7 @@
 
 num=size(list|attrlist|str) -- return size of a list (or string)
 
-val=index(list|str val|char|str :last :all) -- return index of value (or char or string) in list (or string), nil if not found.
+val=index(list|str val|char|str :last :all :substr) -- return index of value (or char or string) in list (or string), nil if not found.
 
 STREAM COMMANDS:
 
@@ -226,7 +231,7 @@
 
 val=trace([flag] :get) -- toggle or set trace mode
 
-pause()  -- pause script execution until C/R
+pause([msgstr])  -- pause script execution until C/R
 
 step() -- toggle stepwise script execution
 
