Index: /trunk/Ohana/src/opihi/doc/image-graph-overlay.txt
===================================================================
--- /trunk/Ohana/src/opihi/doc/image-graph-overlay.txt	(revision 30614)
+++ /trunk/Ohana/src/opihi/doc/image-graph-overlay.txt	(revision 30614)
@@ -0,0 +1,103 @@
+
+the kapa display tool has the ability to show both images (2D grid
+with grey or color scale) and graphs (plot of points and lines).
+
+normally, the kapa graph and image displays are used independently
+(either in different windows or in different sections of the same
+window).  
+
+there are situations in which it is useful to combine these two tools
+and show graphs overlayed on images.
+
+there are several mana / dvo functions which enable graph/image
+overlays, and have use in different contexts.
+
+* basic points
+
+  here are some aspects of image/graph overlays to keep in mind.
+
+  * the image and graph are not dynamically linked.  althought it is
+    possible to set the graph to have limits that correspond to the
+    image in some way (see below), this relationship is not maintained
+    dynamically.  if you change the view of the image (eg, by
+    clicking, zooming, or recentering), the graph does not change
+    without re-issuing some of the commands given below.
+
+  * the boundaries of the image and the graph are dependent on whether
+    or not they are both present and on whether or not the zoom box
+    tools are displayed.  the status of the zoom tools is modifed with
+    the 'section' command as follows:
+
+    section (name) -imtool (option)
+
+    where (option) may be one of -x, +x, -y, +y or none
+
+    for example, use: section default -imtool none to remove the zoom
+    tool from the default section of the current display.
+
+* set graph limits based on the current image
+
+  the simplest way to have the image and the graph interact is to
+  display an image and graph in the same window, and to set the graph
+  limits based on the view of the displayed image:
+
+  # create a contour and overlay in pixel coordinates
+  contour image xc yc 100
+  tv image -50 200
+  box
+  limits -image
+  plot xc yc -pt 100 -c red
+
+* image with WCS overlay on display 'region'
+
+  if you have an image with WCS elements, then it is possible to
+  define the sky region to correspond to the displayed portion of the
+  image.
+
+  # create a contour and convert to celestial coords based on the image:
+  contour image xc yc 100
+  set rc = xc
+  set dc = yc
+  coords image -p rc dc
+
+  # display the image, set the sky region, plot the contour
+  tv image -50 200
+  box -ticks 0000 -labels 0000
+  region -image
+  cplot rc dc -pt 100 -c red
+
+* setting the display size based on the image size
+
+  sometimes it is convenient to ensure the whole image will fit on a
+  graph.  it is possible to use the 'resize -by-image' and section
+  -image options to control this behavior:
+
+  * resize -by-image adjusts the display size so that the image in the
+    currently active section completely fills that section (not that
+    this command assumes the image is centered, but does not center
+    it.
+
+    for example, the following commands display a sample 1000x1000
+    image in a section:
+
+    section view 0.2 0.2 0.6 0.6
+    section view -imtool none
+    box -ticks 0000 -labels 0000
+    tv image -50 200
+    center 500 500 -2
+    resize -by-image
+    
+  * section -image gives something like the opposite behavior.  It
+    defines the size of the section to completely contain the image,
+    with the lower-left corner defined.  Note: this may result in a
+    section which extends beyond the edge of the window.
+
+    resize 800 800
+    section view -imtool none
+    tv image -50 200
+    center 500 500 -2
+    section view -image 0.1 0.1
+
+NOTE: in the examples above, the 'box' command is currently necessary
+to ensure a graph box is defined.  Otherwise, the coordinate systems
+may be inconsistent.
Index: /trunk/Ohana/src/opihi/include/dvoshell.h
===================================================================
--- /trunk/Ohana/src/opihi/include/dvoshell.h	(revision 30613)
+++ /trunk/Ohana/src/opihi/include/dvoshell.h	(revision 30614)
@@ -107,4 +107,5 @@
       MEAS_XCCD_ERR, 
       MEAS_YCCD_ERR, 
+      MEAS_POS_SYS_ERR, 
       MEAS_XMOSAIC, 
       MEAS_YMOSAIC, 
@@ -116,4 +117,5 @@
       MEAS_IMAGE_ID, 
       MEAS_PSF_QF, 
+      MEAS_PSF_QF_PERFECT, 
       MEAS_PSF_CHISQ, 
       MEAS_PSF_NDOF,
@@ -218,4 +220,11 @@
       IMAGE_Y_UL_FP,
       IMAGE_Y_UR_FP,
+      IMAGE_X_ERR_SYS,
+      IMAGE_Y_ERR_SYS,
+      IMAGE_MAG_ERR_SYS,
+      IMAGE_NFIT_PHOTOM,
+      IMAGE_NFIT_ASTROM,
+      IMAGE_NLINK_PHOTOM,
+      IMAGE_NLINK_ASTROM
 };
 
Index: /trunk/Ohana/src/opihi/include/shell.h
===================================================================
--- /trunk/Ohana/src/opihi/include/shell.h	(revision 30613)
+++ /trunk/Ohana/src/opihi/include/shell.h	(revision 30614)
@@ -76,5 +76,5 @@
 char         *expand_vars           	PROTO((char *line));
 char         *expand_vectors        	PROTO((char *line));
-char         *parse                 	PROTO((char *line));
+char         *parse                 	PROTO((int *status, char *line));
 char        **parse_commands        	PROTO((char *, int *));
 void          welcome                   PROTO((void));
Index: /trunk/Ohana/src/opihi/lib.shell/VectorOps.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/VectorOps.c	(revision 30613)
+++ /trunk/Ohana/src/opihi/lib.shell/VectorOps.c	(revision 30614)
@@ -178,8 +178,8 @@
   vec[0].Nelements = Nelements;
   if (type == OPIHI_FLT) {
-    REALLOCATE (vec[0].elements.Flt, opihi_flt, Nelements);
+    REALLOCATE (vec[0].elements.Flt, opihi_flt, MAX(1, Nelements));
     vec[0].type = OPIHI_FLT;
   } else {
-    REALLOCATE (vec[0].elements.Int, opihi_int, Nelements);
+    REALLOCATE (vec[0].elements.Int, opihi_int, MAX(1, Nelements));
     vec[0].type = OPIHI_INT;
   }
Index: /trunk/Ohana/src/opihi/lib.shell/command.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/command.c	(revision 30613)
+++ /trunk/Ohana/src/opihi/lib.shell/command.c	(revision 30614)
@@ -10,6 +10,8 @@
   Command *cmd;
 
-  // rawline = NULL;
-  rawline = strcreate (line);
+  // the input line is never NULL
+  if (!line) { fprintf (stderr, "programming error\n"); abort(); }
+
+  rawline = strcreate (line);  // used for error messages which should echo the unparsed line
 
   /* force a space between ! and first word: !ls becomes ! ls */
@@ -22,6 +24,9 @@
   /* expand anything of the form $fred or $fred$sam, etc */ 
   line = expand_vars (line);     /* line is freed here, new one allocated */
+  if (!line) goto escape;
+
   /* expand anything of the form fred[N] */ 
   line = expand_vectors (line);  /* line is freed here, new one allocated */
+  if (!line) goto escape;
 
   // print the line with the variables and vectors expanded, but before evaluating 
@@ -29,7 +34,8 @@
   if (VERBOSE_SHELL == OPIHI_VERBOSE_ON) gprint (GP_ERR, "opihi: %s\n", line);
 
-  /* solve math expresions, assign variable, if needed */
-  line = parse (line);        /* line is freed here, new one allocated */
-  /* any entry in line of the form {foo} returns value or tmp vector / buffer */
+  /* solve math expresions, assign variable, if needed.  any entry in line of the form {foo}
+   * returns value or tmp vector / buffer */
+  line = parse (&status, line);        /* line is freed here, new one allocated */
+  if (!status) goto escape;
 
   /* we may have reallocated line, return new pointer */
@@ -39,4 +45,5 @@
   if (argc == 0) {
       FREE (rawline);
+      set_int_variable ("STATUS", TRUE);
       return (TRUE);  /* empty command or assignment */
   }
@@ -74,4 +81,19 @@
   FREE (rawline);
   return (status);
+
+ escape:
+  set_int_variable ("STATUS", FALSE);
+
+  # if (DEBUG) 
+  gprint (GP_ERR, "command: %s, status: %d\n", line, FALSE);
+  # endif
+
+  FREE (rawline);
+
+  if (VERBOSE_SHELL != OPIHI_VERBOSE_OFF) gprint (GP_ERR, "error on line: %s\n", rawline);
+
+  // return the current value of line, in case it was modified
+  *outline = line;
+  return FALSE;
 }
 
Index: /trunk/Ohana/src/opihi/lib.shell/expand_vars.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/expand_vars.c	(revision 30613)
+++ /trunk/Ohana/src/opihi/lib.shell/expand_vars.c	(revision 30614)
@@ -64,5 +64,14 @@
     /* variable assignment (skip these variables) */
     if ((L == line) && (V1 != NULL)) {
-      if ((*V1 == '=') || !strcmp (V1, "++") || !strcmp (V1, "--")) {
+      int isAssignment;
+
+      isAssignment = FALSE;
+      isAssignment |= (V1[0] == '=');
+      isAssignment |= (V1[0] == '+') && (V1[1] == '=');
+      isAssignment |= (V1[0] == '-') && (V1[1] == '=');
+      isAssignment |= (V1[0] == '+') && (V1[1] == '+');
+      isAssignment |= (V1[0] == '-') && (V1[1] == '-');
+
+      if (isAssignment) {
 	*N = *L;
 	free (V0);
Index: /trunk/Ohana/src/opihi/lib.shell/parse.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/parse.c	(revision 30613)
+++ /trunk/Ohana/src/opihi/lib.shell/parse.c	(revision 30614)
@@ -1,13 +1,15 @@
 # include "opihi.h"
 
-char *parse (char *line) {
+char *parse (int *status, char *line) {
 
   double fval;
   float *fptr;
   char *newline, *N, *L, *val, *B, *V, *V0, *V1, *c1, *c2, *p;
-  int Nx, Ny, Nbytes, status, size, NLINE, isBuffer, inRange;
+  int Nx, Ny, Nbytes, filestatus, size, NLINE, isBuffer, inRange;
   FILE *f;
   Vector *vec;
   Buffer *buf;
+
+  *status = TRUE; 
 
   Ny = 0;
@@ -49,4 +51,48 @@
     }
 
+    if (!strncmp (V1, "+=", 2)) {
+	V1 ++;
+	if (*V1 == 0) goto error;
+	V1 ++;
+	if (*V1 == 0) goto error;
+
+	val = get_variable (V0);
+	if (val == NULL) {
+	    fval = 0.0;
+	} else {
+	    fval = atof (val);
+	}
+
+	/* dvomath returns a new string, or NULL, with the result of the expression */
+	val = dvomath (1, &V1, &size, 0);
+	if (val == NULL) goto error;
+	fval += atof(val);
+	// save the result
+	set_variable (V0, fval);
+	goto escape;
+    }
+
+    if (!strncmp (V1, "-=", 2)) {
+	V1 ++;
+	if (*V1 == 0) goto error;
+	V1 ++;
+	if (*V1 == 0) goto error;
+
+	val = get_variable (V0);
+	if (val == NULL) {
+	    fval = 0.0;
+	} else {
+	    fval = atof (val);
+	}
+
+	/* dvomath returns a new string, or NULL, with the result of the expression */
+	val = dvomath (1, &V1, &size, 0);
+	if (val == NULL) goto error;
+	fval -= atof(val);
+	// save the result
+	set_variable (V0, fval);
+	goto escape;
+    }
+
     /* not an assignement, syntax error */
     if (*V1 != '=') goto error;
@@ -73,8 +119,8 @@
       Nbytes = fread (val, 1, 1023, f);
       val[Nbytes] = 0;
-      status = pclose (f);
+      filestatus = pclose (f);
       free (B);
 
-      if (status) gprint (GP_ERR, "warning: exit status of command %d\n", status);
+      if (filestatus) gprint (GP_ERR, "warning: exit status of command %d\n", filestatus);
 
       /* convert all but last return to ' '.  drop last return */
@@ -88,16 +134,17 @@
 	}
       }
+      // save the resulting value
+      set_str_variable (V0, val);
+      goto escape;  /* frees temp variables */
+    }
+
+    /* simple variable assignment */
+    /* dvomath returns a new string, or NULL, with the result of the expression */
+    val = dvomath (1, &V1, &size, 0);
+    if (val == NULL) { 
+      while (OHANA_WHITESPACE (*V1)) V1++;
+      val = strcreate (V1);
     } 
-
-    /* simple variable assignment */
-    if (*V1 != '`') {
-      /* dvomath returns a new string, or NULL, with the result of the expression */
-      val = dvomath (1, &V1, &size, 0);
-      if (val == NULL) { 
-	while (OHANA_WHITESPACE (*V1)) V1++;
-	val = strcreate (V1);
-      } 
-    }
-    /* both dvomath and command replacement create (char *) val */
+    // save the result
     set_str_variable (V0, val);
     goto escape;  /* frees temp variables */
@@ -172,5 +219,5 @@
       if (!inRange) {
 	gprint (GP_ERR, "no element %d,%d\n", Nx, Ny);
-	goto escape;
+	goto error;
       }
       if (Nx < 0) Nx += buf[0].header.Naxis[0];
@@ -188,5 +235,5 @@
       if (!inRange) {
 	gprint (GP_ERR, "no element %d\n", Nx);
-	goto escape;
+	goto error;
       }
       if (Nx < 0) Nx += vec[0].Nelements;
@@ -197,5 +244,4 @@
       }
     }
-
     goto escape;
   }
@@ -226,10 +272,10 @@
     if (c1 == NULL) {
       gprint (GP_ERR, "no close brackets!\n");
-      goto escape;
+      goto error;
     }
     c2 = strchr (L, '{');
     if ((c2 != NULL) && (c2 < c1)) {
       gprint (GP_ERR, "can't nest brackets!\n");
-      goto escape;
+      goto error;
     }
     *c1 = 0;
@@ -240,5 +286,5 @@
     if (val == NULL) {
       print_error ();
-      goto escape;
+      goto error;
     } 
 
@@ -257,13 +303,22 @@
   
   REALLOCATE (newline, char, strlen (newline) + 1);
+  *status = TRUE;
   return (newline); 
 
 error:
   gprint (GP_ERR, "syntax error\n");
-
-escape:
+  // assignment or increment operation: free line and return NULL
   if (line != (char *) NULL) free (line);
   if (val != (char *) NULL) free (val);
   if (V0 != (char *) NULL) free (V0);
+  *status = FALSE;
+  return NULL;
+
+escape:
+  // assignment or increment operation: free line and return NULL
+  if (line != (char *) NULL) free (line);
+  if (val != (char *) NULL) free (val);
+  if (V0 != (char *) NULL) free (V0);
+  *status = TRUE;
   return (NULL);
 }
Index: /trunk/Ohana/src/opihi/lib.shell/stack_math.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/stack_math.c	(revision 30613)
+++ /trunk/Ohana/src/opihi/lib.shell/stack_math.c	(revision 30614)
@@ -972,6 +972,5 @@
 	*out = OP;						\
       }								\
-      clear_stack (V1);						\
-      return (TRUE);						\
+      goto escape;						\
     }								\
     if ((V1->vector->type == OPIHI_INT) && (FTYPE == 'S')) {	\
@@ -982,6 +981,5 @@
 	*out = OP;						\
       }								\
-      clear_stack (V1);						\
-      return (TRUE);						\
+      goto escape;						\
     }								\
     if ((V1->vector->type == OPIHI_INT) && (FTYPE == 's')) {	\
@@ -992,6 +990,5 @@
 	*out = OP;						\
       }								\
-      clear_stack (V1);						\
-      return (TRUE);						\
+      goto escape;						\
     } }							
 
@@ -1035,4 +1032,6 @@
 # undef V_FUNC
 
+escape:
+
   if (V1[0].type == 'v') {
     free (V1[0].vector[0].elements.Ptr);
