Index: /trunk/Ohana/doc/elixir-cvs.txt
===================================================================
--- /trunk/Ohana/doc/elixir-cvs.txt	(revision 2791)
+++ /trunk/Ohana/doc/elixir-cvs.txt	(revision 2792)
@@ -54,2 +54,128 @@
 Ohana scripts.  I have modified sp_plot and el_plot to use 'dvo'
 instead.  I have also modified elixir.photreport.  
+
+---
+
+Working with Elixir / Ohana and CVS:
+
+The CVS repositories allows the developer to work on a copy of the
+Ohana software, make changes to their copy of the code, test the
+changes within their own version of the Elixir configuration system,
+share the changes with other developers, and freeze a tested, working
+snapshot of portions of the software.
+
+The Ohana software tree is divided into packages, each possibly
+containing a single program, a group of related programs, or a C
+library.  Within the Ohana software version control system, each of
+these packages should be released as a single entity.  Changes may be
+made to any of the elements which make up the package.  The new
+changes should be tested so that the developer is confident that the
+new version of the software may be safely introduced into the
+production system.  At this point, the entire package is tagged with
+an identifying name and the new release of the package may be loaded
+into the production tree.
+
+In the following discussion, we illustrate the process of creating a
+new release of a package within Elixir. 
+
+First, check out the Ohana tree:
+
+set CVSROOT to username@machine:/data/elixir2/srcdir/cvs where
+'username' is your user ID and machine is one of the CFHT linux
+machines which mount /data/elixir2/srcdir.  
+
+check out your copy of the software tree:
+
+ cvs co ohana
+
+you may also check out specific releases of packages with the command:
+ cvs co -r TAG PACKAGE  eg:
+ cvs co -r libfits-1-0 libfits
+
+this version should be executed from the same directory level as the
+cvs co ohana command; each package is placed in the directory
+ohana/src/PACKAGE.
+
+The entire ohana package may be compiled from the ohana directory
+with:
+
+> configure
+> make
+> make install
+
+Make edits, changes, etc to the programs in some package.  For
+example, you might edit the .c files in the directory
+ohana/src/gastro/src.  Occasionally publish your changes to the CVS
+repository:
+
+cvs update (check for changes by other developers)
+cvs commit [filename] (publish the changes)
+
+also:
+
+cvs add (filename)  (add a new file to the repository).  
+
+Once the changes have been made, make sure to compile and test your
+copy of the program.  If you are acting as a developer, you must have
+your version of the ohana/bin/ARCH directory in your path (before the
+production installation path, /apps/elixir/bin).  Once the code has
+been tested, and the package is ready for release, commit all of your
+changes to the repository (cvs commit).  Now you may tag the new
+release of the package.  Within the top-level directory of the
+package, give the command:
+
+cvs tag -c TAG 
+
+where TAG is the name of this release.  Within the Ohana system,
+packages are generally tagged with names of the form PACKAGE-N-M where
+N and M are major and minor version numbers.  For example, libfits has
+tag names starting from libfits-1-0.  If the changes are minor, and
+don't affect interaction with other packages, then it is only
+necessary to change the minor version number.  If the new package
+forces changes on other packages, it is best to change the major
+version as well.  Major version changes should be introduced only with
+discussion among the affected parties!   It is possible to check the
+currenly assigned tags for a package with the command:
+cvs status -v (filename) 
+where (filename) is some file that is part of the package.  A
+convenient file to use is the Makefile for the package.  Assigning the
+tag affects the repository directly (there is no need to run 'commit'
+afterwards).  If you have outstanding changes, the -c option will
+force CVS to complain, so you will not tag different versions of the
+files from what you expect.
+
+Once the tag has been assigned, the new version of the package may be
+introduced to the production system. This is a two step process:
+first the new source tree is placed in the appropriate location and
+compiled.  Then the new binaries are pushed to their final locations.
+There are two options for installing the new package source code.
+First, you may make a new elixir distribution.  To do this, go into
+the ohana/etc directory, and edit the distributions.txt file.  This
+defines the package releases which make up a complete distribution.
+There are entries for the ohana/elixir distributions, mana
+distributions, etc.  Make a new distribution version, update the
+appropriate package, and save the file.  This distribution (or any
+other older distribution) may now be constructed by executing the
+command 'mkdist (distribution) (version)', for example:
+mkdist elixir 1.0
+This command extracts from the CVS repository all of the package
+versions which are specified to be part of the given distribution
+version.  These are placed in a single directory, along with the ohana
+infrastructure pieces, with the directory name matching the package
+name and version number.  This new directory may be moved or copied to
+the official production source code location
+(/data/elixir2/srcdir/ohana).  The entire tree may then be compiled.  
+
+An alternative to the above is to checkout only the new package
+version.  To do this, go to the directory containing the production
+code (ie, /data/elixir2/srcdir).  Perform a checkout of the specific
+tagged release of the package of interest:
+cvs co -r TAG PACKAGE (ie, cvs co -r libfits-1-0 libfits).  This will
+replace the old version of the package with the new version.  Now the
+software may be recompiled from the ohana directory. 
+
+Once a new version of the software has been compiled, it may be pushed
+to the production binary directory.  From the /data/elixir2/srcdir
+directory, issue the command 'make install' (make install-test will
+show what programs are new).
+
Index: /trunk/Ohana/src/opihi/cmd.basic/run_if.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.basic/run_if.c	(revision 2791)
+++ /trunk/Ohana/src/opihi/cmd.basic/run_if.c	(revision 2792)
@@ -30,22 +30,7 @@
   /* determine value of conditional expression */
   val = dvomath (1, &argv[1], &size, 0);
-  if (val == NULL) { /* try expression as string op string */
-    char **stack;
-    int Nstack;
+  if (val == NULL) return (FALSE);
+  logic = atof (val); /* warning: round-off error is a danger */ 
 
-    stack = isolate_elements (1, &argv[1], &Nstack); 
-    if (Nstack != 5) goto syntax;
-    if (strcmp (stack[0], "(")) goto syntax;
-    if (strcmp (stack[4], ")")) goto syntax;
-    equals = -1;
-    if (!strcmp (stack[2], "==")) equals = TRUE;
-    if (!strcmp (stack[2], "!=")) equals = TRUE;
-    if (equals == -1) goto syntax;
-    logic = FALSE;
-    if (equals && !strcmp (stack[1], stack[3])) logic = TRUE;
-    if (!equals && strcmp (stack[1], stack[3])) logic = TRUE;
-  } else {
-    logic = atof (val); /* warning: round-off error is a danger */ 
-  }
   if (BreakOnTrue) {
     if (logic) {
Index: /trunk/Ohana/src/opihi/include/dvomath.h
===================================================================
--- /trunk/Ohana/src/opihi/include/dvomath.h	(revision 2791)
+++ /trunk/Ohana/src/opihi/include/dvomath.h	(revision 2792)
@@ -50,5 +50,5 @@
 char        **isolate_elements      PROTO((int argc, char **argv, int *nstack));
 StackVar     *convert_to_RPN        PROTO((int argc, char **argv, int *nstack));
-int           check_stack           PROTO((StackVar *stack, int Nstack));
+int           check_stack           PROTO((StackVar *stack, int Nstack, int validsize));
 int           evaluate_stack        PROTO((StackVar *stack, int *Nstack));
 void          init_stack            PROTO((StackVar *stack));
Index: /trunk/Ohana/src/opihi/lib.shell/check_stack.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/check_stack.c	(revision 2791)
+++ /trunk/Ohana/src/opihi/lib.shell/check_stack.c	(revision 2792)
@@ -1,7 +1,7 @@
 # include "opihi.h"
 
-int check_stack (StackVar *stack, int Nstack) {
+int check_stack (StackVar *stack, int Nstack, int validsize) {
 
-  int i, Nx, Ny, Nv;
+  int i, Nx, Ny, Nv, size;
   char *c, line[128];
 
@@ -10,4 +10,5 @@
   for (i = 0; i < Nstack; i++) {
     if (stack[i].type == 'X') {
+
       /** if this is a number, put it on the list of scalers and move on **/
       stack[i].Float = strtod (stack[i].name, &c);
@@ -17,4 +18,11 @@
 	continue;
       } 
+
+      /** if we demand a scalar, interpret strings as strings */
+      if (validsize == 0) {
+	stack[i].type  = 'W';
+	continue;
+      } 
+	
       /** if this is a matrix, find the dimensions and check with existing values **/
       if (IsBuffer (stack[i].name)) {
@@ -38,4 +46,5 @@
 	continue;
       }
+
       /** if this is a vector, find the dimensions and check with existing values **/
       if (IsVector (stack[i].name)) {
@@ -63,7 +72,10 @@
   }
 
-  /* we return a value which is 1 greater than the object dimension */
-  if (Nx != -1) return (2);
-  if (Nv != -1) return (1);
-  return (0);
+  /* return object dimensions */
+  size = 0;
+  if (Nv != -1) size = 1;
+  if (Nx != -1) size = 2;
+  if (validsize == -1)   return (size);
+  if (validsize != size) return (-1);
+  return (size);
 }
Index: /trunk/Ohana/src/opihi/lib.shell/dvomath.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/dvomath.c	(revision 2791)
+++ /trunk/Ohana/src/opihi/lib.shell/dvomath.c	(revision 2792)
@@ -22,6 +22,5 @@
 
   /* distinguish scalar, vector, matrix, check dimensions */
-  *size = check_stack (stack, Nstack);
-  if ((validsize != -1) && (validsize != *size)) goto error;
+  *size = check_stack (stack, Nstack, validsize);
   if (*size < 0) goto error;
 
Index: /trunk/Ohana/src/opihi/lib.shell/evaluate_stack.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/evaluate_stack.c	(revision 2791)
+++ /trunk/Ohana/src/opihi/lib.shell/evaluate_stack.c	(revision 2792)
@@ -26,5 +26,5 @@
       return (TRUE);
     }
-    fprintf (stderr, "syntax error!\n");
+    push_error ("syntax error!");
     free (tmp_stack.name);
     return (FALSE);
@@ -54,4 +54,22 @@
 	return (FALSE);
       }
+
+      /* this could be macro generated... */
+      # define TWO_OP(A,B,FUNC) \
+      if (!strncasecmp (&stack[i - 2].type, A, 1) && !strncasecmp (&stack[i - 1].type, B, 1)) \
+	status = FUNC (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name); 
+
+      TWO_OP ("M","M",MM_binary);
+      TWO_OP ("M","V",MV_binary);
+      TWO_OP ("M","S",MS_binary);
+      TWO_OP ("V","M",VM_binary);
+      TWO_OP ("V","V",VV_binary);
+      TWO_OP ("V","S",VS_binary);
+      TWO_OP ("S","M",SM_binary);
+      TWO_OP ("S","V",SV_binary);
+      TWO_OP ("S","S",SS_binary);      
+      TWO_OP ("W","W",WW_binary);      
+      
+      /*
       if (!strncasecmp (&stack[i - 2].type, "V", 1) && !strncasecmp (&stack[i - 1].type, "V", 1)) 
 	status = VV_binary (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
@@ -72,4 +90,18 @@
       if (!strncasecmp (&stack[i - 2].type, "S", 1) && !strncasecmp (&stack[i - 1].type, "S", 1)) 
 	status = SS_binary (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
+      if (!strncasecmp (&stack[i - 2].type, "X", 1) && !strncasecmp (&stack[i - 1].type, "X", 1)) 
+	status = XX_binary (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
+      */
+
+      /* string op number is not valid */
+      if (!strncasecmp (&stack[i - 2].type, "W", 1) && strncasecmp (&stack[i - 1].type, "W", 1)) {
+	free (tmp_stack.name);
+	return (FALSE);
+      }
+      if (strncasecmp (&stack[i - 2].type, "W", 1) && !strncasecmp (&stack[i - 1].type, "W", 1)) {
+	free (tmp_stack.name);
+	return (FALSE);
+      }
+
       if (!status) {
 	free (tmp_stack.name);
@@ -102,4 +134,11 @@
       if (!strncasecmp (&stack[i - 1].type, "S", 1)) 
 	S_unary (&tmp_stack, &stack[i - 1], stack[i].name);
+
+      /* there are no valid unary string operators */
+      if (!strncasecmp (&stack[i - 1].type, "W", 1)) {
+	fprintf (stderr, "syntax error\n");
+	free (tmp_stack.name);
+	return (FALSE);
+      }
 
       move_stack (&stack[i-1], &tmp_stack);
Index: /trunk/Ohana/src/opihi/lib.shell/expand_vectors.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/expand_vectors.c	(revision 2791)
+++ /trunk/Ohana/src/opihi/lib.shell/expand_vectors.c	(revision 2792)
@@ -37,9 +37,11 @@
       ALLOCATE (val, char, 64);
       sprintf (val, "-1");
+      /* this choice of sentinel prevents us from using 
+	 x[-1], x[-2], and is not really needed */
     } else {
       strncpy (tmpline, p+1, n);
       tmpline[n] = 0;
       val = dvomath (1, &tmpline, &size, 0);
-      if (val == NULL) goto dumpline; /* not really a vector */
+      if (val == NULL) goto dumpline; /* not a valid vector subscript */
     }
     /* find vector name */
Index: /trunk/Ohana/src/opihi/lib.shell/parse.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/parse.c	(revision 2791)
+++ /trunk/Ohana/src/opihi/lib.shell/parse.c	(revision 2792)
@@ -56,6 +56,6 @@
     if (*V1 == 0) goto error;
 
-    /* command replacement.  execute the line, place answer in val. */
     if (*V1 == '`') {
+      /* command replacement.  execute the line, place answer in val. */
 
       /* look for end of line, must be ` */
Index: /trunk/Ohana/src/opihi/lib.shell/stack_math.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/stack_math.c	(revision 2791)
+++ /trunk/Ohana/src/opihi/lib.shell/stack_math.c	(revision 2792)
@@ -1043,4 +1043,28 @@
 
 }
+
+int WW_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int value;
+  
+  switch (op[0]) { 
+  case 'E': 
+    value = strcmp (V1[0].name, V2[0].name) ? 0 : 1;
+    break; 
+  case 'N': 
+    value = strcmp (V1[0].name, V2[0].name) ? 1 : 0;
+    break; 
+  default:
+    fprintf (stderr, "error: op %c not valid\n", op[0]);
+  }
+
+  strcpy (OUT[0].name, "tmp");
+  OUT[0].Float = value;
+  OUT[0].type = 'S';
+  OUT[0].ptr = &OUT[0].Float;
+  return (TRUE);
+
+}
+
 
 int S_unary (StackVar *OUT, StackVar *V1, char *op) {
