- Implement and use xsnprintf(), a wrapper to snprintf(3) that uses
  assert(3) to ensure there was no truncation. This time also pass
  the correct buffer size around, especially down the path to
  math_formatter(), which got (too small) sizes based on inlen
  instead of maxlen in my previous diff.

- No need to deal with goto in math_formatter(); just use an if ...
  else if ... else if ... else ... sequence.

- In stralmath() and strpnmath(), check the desired field width before
  even starting to create the output format string. If it's too large,
  bail out. Also, for the int cases, use %d (and cast the width to int)
  instead of %g to create the field width format string.

- Move up the tempstring declaration in stralmath() to comply with
  good old C89. Pun intended ;-)
  [But there may be more of this, I don't have old compilers to check.]

- Remove that large block of now unused code (old stralmath() and
  stralmath_reduce()). It isn't fun working on code and then realizing
  it's already dead code.

- Someone please remind me to replace idioms like
	if (strlen (keep_buf) > 0)
  by
	if (*keep_buf)
  or, if you prefer verbosity,
	if (*keep_buf != '\0')
  (just found when re-reading the diff)


Index: Makefile
===================================================================
RCS file: /var/cvs/outback/crm/Makefile,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -u -p -r1.1.1.2 -r1.4
Index: crm114.h
===================================================================
RCS file: /var/cvs/outback/crm/crm114.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm114.h
--- crm114.h	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm114.h	13 Jun 2007 18:55:06 -0000
@@ -59,17 +59,11 @@ long strntrn (
 	      long tostrlen,
 	      long flags);
 
+// snprintf(3) wrapper using assert(3) to bail out on truncation
+int xsnprintf(char *str, size_t size, const char *format, ...);
 
 //   basic math evaluator top function
 long strmath (char *buf, long inlen, long maxlen, long *retstat); 
-
-//   basic math evaluator in RPN
-long strpnmath (char *buf, long inlen, long maxlen, long *retstat); 
-
-//   basic math evaluator in RPN
-long stralmath (char *buf, long inlen, long maxlen, long *retstat); 
-long stralmath_reduce (double *valstack, long *opstack, 
-		       long *sp, char *outformat);
 
 //   load a file with info in a partially filled out csl cell.
 int crm_load_csl (CSL_CELL *csl);
Index: crm114_sysincludes.h
===================================================================
RCS file: /var/cvs/outback/crm/crm114_sysincludes.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm114_sysincludes.h
--- crm114_sysincludes.h	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm114_sysincludes.h	13 Jun 2007 18:55:06 -0000
@@ -4,6 +4,8 @@
 //   Unix declarations follow:
 
 #ifdef POSIX
+#include <assert.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <errno.h>
@@ -30,6 +32,8 @@
 
 #ifdef WIN32
 #define _CRTDBG_MAP_ALLOC
+#include <assert.h>
+#include <stdarg.h>
 #include <stdlib.h>
 #include <crtdbg.h>
 #include <stdio.h>
Index: crm_bit_entropy.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_bit_entropy.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_bit_entropy.c
--- crm_bit_entropy.c	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm_bit_entropy.c	13 Jun 2007 18:55:06 -0000
@@ -2716,11 +2716,11 @@ int crm_expr_bit_entropy_classify (CSL_C
 	
 	if (tprob > 0.5000)
 	  {
-	    sprintf (buf, "CLASSIFY succeeds; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
+	    xsnprintf (buf, sizeof(buf), "CLASSIFY succeeds; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
 	  }
 	else
 	  {
-	    sprintf (buf, "CLASSIFY fails; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
+	    xsnprintf (buf, sizeof(buf), "CLASSIFY fails; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
 	  };
 	if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	  strcat (stext, buf);
@@ -2733,7 +2733,7 @@ int crm_expr_bit_entropy_classify (CSL_C
 	  {
 	    remainder = remainder + ptc[m];
 	  };
-	sprintf (buf, "Best match to file #%ld (%s) "	\
+	xsnprintf (buf, sizeof(buf), "Best match to file #%ld (%s) "
 		 "prob: %6.4f  pR: %6.4f  \n",
 		 bestseen,
 		 hashname[bestseen],
@@ -2741,7 +2741,8 @@ int crm_expr_bit_entropy_classify (CSL_C
 		 (log10(ptc[bestseen]) - log10(remainder)));
 	if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	  strcat (stext, buf);
-	sprintf (buf, "Total features in input file: %ld\n", totalfeatures); 
+	xsnprintf (buf, sizeof(buf), "Total features in input file: %ld\n",
+		    totalfeatures); 
 	if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	  strcat (stext, buf);
 	for (k = 0; k < maxhash; k++)
@@ -2759,8 +2760,8 @@ int crm_expr_bit_entropy_classify (CSL_C
 	    pctused = nodes[0].abet[0].nextcell;
 	    if (nodes[0].abet[0].nextcell == 0) pctused = nodelens[k];
 	    pctused = 100.0 * pctused / nodelens[k];
-	    sprintf (buf, 
-		     "#%ld (%s):"					\
+	    xsnprintf (buf, sizeof(buf),
+		     "#%ld (%s):"
 		     " features: %lld (%.0f%%), entropy: %8f, jumps: %ld, prob: %3.2e, pR: %6.2f \n", 
 		     k,
 		     hashname[k],
Index: crm_correlate.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_correlate.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_correlate.c
--- crm_correlate.c	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm_correlate.c	13 Jun 2007 18:55:06 -0000
@@ -746,11 +746,11 @@ int crm_expr_correlate_classify (CSL_CEL
       
       if (tprob > 0.5000)
 	{
-	  sprintf (buf, "CLASSIFY succeeds; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
+	  xsnprintf (buf, sizeof(buf), "CLASSIFY succeeds; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
 	}
       else
 	{
-	  sprintf (buf, "CLASSIFY fails; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
+	  xsnprintf (buf, sizeof(buf), "CLASSIFY fails; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
 	};
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
@@ -763,7 +763,7 @@ int crm_expr_correlate_classify (CSL_CEL
 	  {
 	    remainder = remainder + ptc[m];
 	  };
-      sprintf (buf, "Best match to file #%ld (%s) "\
+      xsnprintf (buf, sizeof(buf), "Best match to file #%ld (%s) "
 	       "prob: %6.4f  pR: %6.4f  \n",
 	       bestseen,
 	       hashname[bestseen],
@@ -771,7 +771,8 @@ int crm_expr_correlate_classify (CSL_CEL
 	       (log10(ptc[bestseen]) - log10(remainder)));
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
-      sprintf (buf, "Total features in input file: %ld\n", hashlens[bestseen]);
+      xsnprintf (buf, sizeof(buf), "Total features in input file: %ld\n",
+		  hashlens[bestseen]);
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
       for (k = 0; k < maxhash; k++)
@@ -783,8 +784,8 @@ int crm_expr_correlate_classify (CSL_CEL
 	      {
 		remainder = remainder + ptc[m];
 	      };
-	  sprintf (buf, 
-		   "#%ld (%s):"\
+	  xsnprintf (buf, sizeof(buf),
+		   "#%ld (%s):"
 		   " features: %ld, L1: %lld L2: %lld L3: %lld, l4: %lld prob: %3.2e, pR: %6.2f \n", 
 		   k,
 		   hashname[k],
Index: crm_errorhandlers.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_errorhandlers.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_errorhandlers.c
--- crm_errorhandlers.c	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm_errorhandlers.c	13 Jun 2007 18:55:06 -0000
@@ -89,10 +89,10 @@ long fatalerror ( char *text1, char *tex
   //   long, so we put out only the first 1024 characters
   //
   if (strlen (text2) < 1023)
-    sprintf (reason, "\n%s: *ERROR* \n %.1024s %.1024s\n Sorry, but this program is very sick and probably should be killed off.\nThis happened at line %ld of file %s\n", 
+    xsnprintf (reason, sizeof(reason), "\n%s: *ERROR* \n %.1024s %.1024s\n Sorry, but this program is very sick and probably should be killed off.\nThis happened at line %ld of file %s\n", 
 	   prog_argv[0], text1, text2, csl->cstmt, csl->filename);
   else
-    sprintf (reason, "\n%s: *ERROR* \n %.1024s %.1024s(...truncated)\n Sorry, but this program is very sick and probably should be killed off.\nThis happened at line %ld of file %s\n", 
+    xsnprintf (reason, sizeof(reason), "\n%s: *ERROR* \n %.1024s %.1024s(...truncated)\n Sorry, but this program is very sick and probably should be killed off.\nThis happened at line %ld of file %s\n", 
 	   prog_argv[0], text1, text2, csl->cstmt, csl->filename);
 
   //     Check to see - is there a trap available or is this a non-trap 
@@ -158,10 +158,10 @@ long nonfatalerror ( char *text1, char *
   //   long, so we put out only the first 1024 characters
   //
   if (strlen (text2) < 1023)
-    sprintf (reason, "\n%s: *WARNING* \n %.1024s %.1024s\nI'll try to keep working.\nThis happened at line %ld of file %s\n", 
+    xsnprintf (reason, sizeof(reason), "\n%s: *WARNING* \n %.1024s %.1024s\nI'll try to keep working.\nThis happened at line %ld of file %s\n", 
 	   prog_argv[0], text1, text2, csl->cstmt, csl->filename);
   else
-    sprintf (reason, "\n%s: *WARNING* \n %.1024s %.1024s(...truncated)\nI'll try to keep working.\nThis happened at line %ld of file %s\n", 
+    xsnprintf (reason, sizeof(reason), "\n%s: *WARNING* \n %.1024s %.1024s(...truncated)\nI'll try to keep working.\nThis happened at line %ld of file %s\n", 
 	   prog_argv[0], text1, text2, csl->cstmt, csl->filename);
 
   //     Check to see - is there a trap available or is this a non-trap 
Index: crm_exec_engine.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_exec_engine.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_exec_engine.c
--- crm_exec_engine.c	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm_exec_engine.c	13 Jun 2007 18:55:06 -0000
@@ -238,7 +238,8 @@ int crm_invoke ()
       {
         char bogusbuffer[1024];
 	char bogusstmt [1024];
-        sprintf (bogusbuffer, "Statement %ld is bogus!!!  Here's the text: \n",
+        xsnprintf (bogusbuffer, sizeof(bogusbuffer),
+		 "Statement %ld is bogus!!!  Here's the text: \n",
  		 csl->cstmt);
 	memmove (bogusstmt, 
 		&csl->filetext[csl->mct[csl->cstmt]->start],
@@ -343,7 +344,7 @@ int crm_invoke ()
 	  //   since the vht index of the return location was actually 
 	  //   set during the CALL statement, not calculated during RETURN.
 	  char depthstr[33];
-	  sprintf (depthstr, "%ld", csl->calldepth);
+	  xsnprintf (depthstr, sizeof(depthstr), "%ld", csl->calldepth);
 	  crm_set_temp_var (":_cd:", depthstr);
 	};
       }
@@ -620,7 +621,7 @@ int crm_invoke ()
 
 	//    The pattern is now expanded, we can hash it to obscure meaning.
 	hval = strnhash (tempbuf, newstrlen );
-	sprintf (newstr, "%08lX", hval);
+	xsnprintf (newstr, sizeof(newstr), "%08lX", hval);
 
 	if (internal_trace)
 	  {
@@ -814,7 +815,7 @@ int crm_invoke ()
 	  {
 	    //   properly set :_cd: since we're now in the 'callee' code
 	    char depthstr[33];
-	    sprintf (depthstr, "%ld", csl->calldepth);
+	    xsnprintf (depthstr, sizeof(depthstr), "%ld", csl->calldepth);
 	    crm_set_temp_var (":_cd:", depthstr);
 	  };
 
@@ -1122,7 +1123,8 @@ int crm_invoke ()
       {
         char bogusbuffer[1024];
 	char bogusstmt [1024];
-        sprintf (bogusbuffer, "Statement %ld NOT YET IMPLEMENTED !!!"
+        xsnprintf (bogusbuffer, sizeof(bogusbuffer),
+		 "Statement %ld NOT YET IMPLEMENTED !!!"
 		 "Here's the text: \n",
 		 csl->cstmt);
 	memmove(bogusstmt, 
@@ -1140,7 +1142,7 @@ int crm_invoke ()
       {
         char bogusbuffer[1024];
 	char bogusstmt [1024];
-        sprintf (bogusbuffer, 
+        xsnprintf (bogusbuffer, sizeof(bogusbuffer),
 		 "Statement %ld way, way bizarre !!!  Here's the text: \n",
 		 csl->cstmt);
 	memmove (bogusstmt, 
Index: crm_expandvar.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_expandvar.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_expandvar.c
--- crm_expandvar.c	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm_expandvar.c	13 Jun 2007 18:55:06 -0000
@@ -480,7 +480,8 @@ long crm_zexpandvar (char *buf, 
 			  char lcstring [32];
 			  long lclen;
 			  lcstring[0] = '\0';
-			  lclen = sprintf (lcstring, "%ld", csl->cstmt);
+			  lclen = xsnprintf (lcstring, sizeof(lcstring),
+						"%ld", csl->cstmt);
 			  crm_set_temp_nvar (":_cs:", lcstring, lclen); 
 			};
 		    };
@@ -724,7 +725,7 @@ long crm_zexpandvar (char *buf, 
 			int m, mm;
 			//   the vlen-2 is because we need to get
 			//    rid of the ':' 
-			sprintf (lentext, "%ld", vlen-2);
+			xsnprintf (lentext, sizeof(lentext), "%ld", vlen-2);
 			mm = strlen (lentext);
 			for (m = 0; m < mm && id < maxlen; m++)
 			  {
@@ -757,7 +758,8 @@ long crm_zexpandvar (char *buf, 
 			//
 			char lentext[MAX_VARNAME];
 			int m, mm;
-			sprintf (lentext, "%ld", vht[vht_index]->vlen);
+			xsnprintf (lentext, sizeof(lentext), "%ld",
+					vht[vht_index]->vlen);
 			mm = strlen (lentext);
 			for (m = 0; m < mm && id < maxlen; m++)
 			  {
@@ -861,7 +863,8 @@ long crm_zexpandvar (char *buf, 
 			mathtext[vlen-2] = '\000';
 			if (internal_trace)
 			  fprintf (stderr, "In-Mathtext is -'%s'-\n", mathtext); 
-			m = strmath (mathtext, vlen-2, MAX_VARNAME, retstat);
+			m = strmath (mathtext, vlen-2, sizeof(mathtext),
+					retstat);
 			if (internal_trace)
 			  fprintf (stderr, "Out-Mathtext is -'%s'-\n", mathtext);
 			if (retstat && *retstat < 0)
@@ -909,7 +912,8 @@ long crm_zexpandvar (char *buf, 
 			    m++;
 			  }
 			mathtext[vlen-1] = '\000';
-			m = strmath (mathtext, vlen-2, MAX_VARNAME, retstat );
+			m = strmath (mathtext, vlen-2, sizeof(mathtext),
+					retstat);
 			if (retstat && *retstat < 0)
 			  {
 			    q = fatalerror ("Problem during math evaluation of ",
Index: crm_expr_syscall.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_expr_syscall.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_expr_syscall.c
--- crm_expr_syscall.c	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm_expr_syscall.c	13 Jun 2007 18:55:06 -0000
@@ -306,12 +306,12 @@ int crm_expr_syscall ( CSL_CELL *csl, AR
 		char pidstr [32];
 		long pid;
 		pid = (long) getpid();
-		sprintf (pidstr, "%ld", pid);
+		xsnprintf (pidstr, sizeof(pidstr), "%ld", pid);
 		crm_set_temp_var (":_pid:", pidstr);
 		if (user_trace)
 		  fprintf (stderr, "My new PID is %s\n", pidstr);
 		pid = (long) getppid();
-		sprintf (pidstr, "%ld", pid);
+		xsnprintf (pidstr, sizeof(pidstr), "%ld", pid);
 		crm_set_temp_var (":_ppid:", pidstr);
 	      }
 	      //   See if we have redirection of stdin and stdout
@@ -371,7 +371,7 @@ int crm_expr_syscall ( CSL_CELL *csl, AR
 	      if (retcode == -1 ) 
 		{
 		  char errstr [4096];
-		  sprintf (errstr, 
+		  xsnprintf (errstr, sizeof(errstr),
 			   "The command was >%s< and returned exit code %d .",
 			   sys_cmd, WEXITSTATUS (retcode));
 		  nonfatalerror ("This program tried a shell command that "
@@ -522,7 +522,7 @@ int crm_expr_syscall ( CSL_CELL *csl, AR
   //  Record useful minion data, if possible.
   if (strlen (keep_buf) > 0)
     {
-      sprintf (exp_keep_buf, 
+      xsnprintf (exp_keep_buf, sizeof(exp_keep_buf),
 	       "MINION PROC PID: %d from-pipe: %d to-pipe: %d",
 	       minion,
 	       from_minion[0],
@@ -558,7 +558,8 @@ int crm_expr_syscall ( CSL_CELL *csl, AR
 	    fprintf (stderr, "minion waitpid result :%d; whacking %s\n", 
 		     minion_exit_status, 
 		     keep_buf);
-	  sprintf (exit_value_string, "DEAD MINION, EXIT CODE: %d", 
+	  xsnprintf (exit_value_string, sizeof(exit_value_string),
+		   "DEAD MINION, EXIT CODE: %d", 
 		   WEXITSTATUS (minion_exit_status)); 
 	  if (keep_len > 0)
 	    crm_destructive_alter_nvariable (keep_buf, keep_len,
@@ -631,7 +632,8 @@ int crm_expr_syscall ( CSL_CELL *csl, AR
           if (!retcode)
             {
               char errstr [4096];
-              sprintf (errstr, "The command was >>%s<< and returned exit code %d .",
+              xsnprintf (errstr, sizeof(errstr),
+		       "The command was >>%s<< and returned exit code %d .",
                        sys_cmd, retcode);
               fatalerror ("This program tried a shell command that "
                           "didn't run correctly. ",
@@ -770,7 +772,7 @@ int crm_expr_syscall ( CSL_CELL *csl, AR
       //  Record useful minion data, if possible.
       if (strlen (keep_buf) > 0)
         {
-          sprintf (exp_keep_buf,
+          xsnprintf (exp_keep_buf, sizeof(exp_keep_buf),
                    "MINION PROC PID: %d from-pipe: %d to-pipe: %d",
                    minion,
                    from_minion[0],
@@ -806,7 +808,8 @@ int crm_expr_syscall ( CSL_CELL *csl, AR
                 fprintf (stderr, "minion exit code :%d; whacking %s\n",
                          exit_code,
                          keep_buf);
-              sprintf (exit_value_string, "DEAD MINION, EXIT CODE: %d",
+              xsnprintf (exit_value_string, sizeof(exit_value_string),
+		       "DEAD MINION, EXIT CODE: %d",
                        exit_code);
               if (keep_len > 0)
                 crm_destructive_alter_nvariable (keep_buf, keep_len,
Index: crm_markovian.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_markovian.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_markovian.c
--- crm_markovian.c	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm_markovian.c	13 Jun 2007 18:55:06 -0000
@@ -2080,11 +2080,11 @@ int crm_expr_markov_classify (CSL_CELL *
 
       if (tprob > 0.5000)
 	{
-	  sprintf (buf, "CLASSIFY succeeds; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
+	  xsnprintf (buf, sizeof(buf), "CLASSIFY succeeds; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
 	}
       else
 	{
-	  sprintf (buf, "CLASSIFY fails; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
+	  xsnprintf (buf, sizeof(buf), "CLASSIFY fails; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
 	};
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
@@ -2097,15 +2097,16 @@ int crm_expr_markov_classify (CSL_CELL *
 	  {
 	    remainder = remainder + ptc[m];
 	  };
-      sprintf (buf, "Best match to file #%ld (%s) "\
-    		    "prob: %6.4f  pR: %6.4f  \n",
+      xsnprintf (buf, sizeof(buf), "Best match to file #%ld (%s) "
+				   "prob: %6.4f  pR: %6.4f  \n",
 	       bestseen,
 	       hashname[bestseen],
 	       ptc[bestseen],
 	       (log10(ptc[bestseen]) - log10(remainder)));
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
-      sprintf (buf, "Total features in input file: %ld\n", totalfeatures); 
+      xsnprintf (buf, sizeof(buf), "Total features in input file: %ld\n",
+		 totalfeatures); 
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
       for (k = 0; k < maxhash; k++)
@@ -2117,7 +2118,7 @@ int crm_expr_markov_classify (CSL_CELL *
 		{
 		  remainder = remainder + ptc[m];
 		};
-	  sprintf (buf, 
+	  xsnprintf (buf, sizeof(buf),
 		   "#%ld (%s):"\
 		   " features: %ld, hits: %ld, prob: %3.2e, pR: %6.2f \n", 
 		   k,
Index: crm_math_exec.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_math_exec.c,v
retrieving revision 1.1.1.2
retrieving revision 1.7
diff -u -p -r1.1.1.2 -r1.7
--- crm_math_exec.c	12 Jun 2007 13:00:56 -0000	1.1.1.2
+++ crm_math_exec.c	13 Jun 2007 19:19:06 -0000	1.7
@@ -34,7 +34,11 @@ extern char *inbuf;
 extern char *outbuf;
 extern char *tempbuf;
 
-static int math_formatter ( double value, char *format, char *buf);
+int math_formatter (double value, char *format, char *buf, long maxlen);
+long stralmath (char *buf, long inlen, long maxlen, long *retstat);
+long stralmath_reduce (double *valstack, long *opstack, long *sp,
+			char *outformat, size_t ofsize);
+long strpnmath (char *buf, long inlen, long maxlen, long *retstat);
 
 
 //
@@ -399,24 +403,32 @@ long strpnmath (char *buf, long inlen, l
 	    if (sp > 0)
 	      {
 		char tempstring [2048];
+		double fwidth = stack[sp];
 		tempstring[0] = '\0';
 		sp--;
+		if (abs(fwidth) >= sizeof(tempstring))
+		  {
+		    errstat = nonfatalerror("Too large field width.", "");
+		    return 0;
+		  }
 		//  Special case - if the format is an integer, add a ".0"
 		//  to the format string so we get integer output.
 		if ( buf[ip] == 'x' || buf[ip] == 'X')
 		  {
-		    sprintf (outformat,  "%%%g.0ll%c",
-                             stack[sp+1], (short) buf[ip] );
+		    xsnprintf (outformat, sizeof(outformat), "%%%d.0ll%c",
+                             (int) fwidth, (short) buf[ip] );
                   }
                 else
                   {
 		    if ( ((long)stack[sp+1]) / 1 == stack[sp+1])
 		      {
-			sprintf(outformat,"%%%g.0%c", stack[sp+1], buf[ip]);
+			xsnprintf(outformat, sizeof(outformat),
+					"%%%d.0%c", (int) fwidth, buf[ip]);
 		      }
 		    else
 		      {
-			sprintf(outformat,"%%%g%c", stack[sp+1], buf[ip]);
+			xsnprintf(outformat, sizeof(outformat),
+					"%%%g%c", fwidth, buf[ip]);
 		      };
 		  };
 		if (internal_trace)
@@ -424,7 +436,8 @@ long strpnmath (char *buf, long inlen, l
 		stack[sp+1] = 0;
 		if (buf[ip] != 'x' && buf[ip] != 'X')
 		  {
-		    sprintf (tempstring, outformat, stack[sp]);
+		    xsnprintf (tempstring, sizeof(tempstring), outformat,
+				  stack[sp]);
 		    if (internal_trace)
 		      fprintf (stderr, 
 			       "Intermediate result string -->%s<-- \n", 
@@ -434,7 +447,8 @@ long strpnmath (char *buf, long inlen, l
 		  {
 		    long long intpart ;
 		    intpart = ((long long) stack[sp]) / 1;
-		    sprintf (tempstring, outformat, intpart);
+		    xsnprintf (tempstring, sizeof(tempstring), outformat,
+				  intpart);
 		    if (internal_trace)
 		      fprintf (stderr, 
 			       "Intermediate hex result string -->%s<-- \n", 
@@ -494,7 +508,7 @@ long strpnmath (char *buf, long inlen, l
 
   //      now the top of stack contains the result of the calculation.
   //      fprintf it into the output buffer, and we're done.
-  outstringlen = math_formatter ( stack[sp], outformat, buf) ;
+  outstringlen = math_formatter ( stack[sp], outformat, buf, maxlen) ;
   return (outstringlen);
 }
  
@@ -507,7 +521,7 @@ long strpnmath (char *buf, long inlen, l
 //     formatting on the number itself.
 //
 //   
-int math_formatter ( double value, char *format, char *buf)
+int math_formatter ( double value, char *format, char *buf, long maxlen)
 {
   long outlen;
   //  If the user supplied a format, use that.
@@ -525,547 +539,63 @@ int math_formatter ( double value, char 
 	  if (internal_trace)
 	    fprintf (stderr, "Final hex format: %s\n", format ); 
 	  equiv = value * 1;
-	  outlen = sprintf (buf, format, equiv);
-	  return (outlen);
-	};
-      //  	
-      //    Nothing so special; use the user format as it is.
-      if (internal_trace)
-	fprintf (stderr, "Final format: %s\n", format ); 
-      outlen = sprintf (buf, format, value);
-      return (outlen);
-    };
-     
+	  outlen = xsnprintf (buf, maxlen, format, equiv);
+	}
+      else
+	{
+	  //  	
+	  //    Nothing so special; use the user format as it is.
+	  if (internal_trace)
+	    fprintf (stderr, "Final format: %s\n", format ); 
+	  outlen = xsnprintf (buf, maxlen, format, value);
+	}
+    }
   //   Nope - we didn't get a preferred formatting, so here's the 
   //   adaptive smart code.
-	       
+  else if (value == 0.0 )
   //
   //      print out 0 as 0
   //
-  if (value == 0.0 )
     {
-      outlen = sprintf (buf, "0");
-      goto formatdone;
+      outlen = xsnprintf (buf, maxlen, "0");
     }
   //
   //       use E notation if bigger than 1 trillion
   //
-  if (value > 1000000000000.0 || value < -1000000000000.0 )
+  else if (value > 1000000000000.0 || value < -1000000000000.0 )
     {
-      outlen = sprintf (buf, "%.5E", value);
-      goto formatdone;
+      outlen = xsnprintf (buf, maxlen, "%.5E", value);
     }
   // 
   //       use E notation if smaller than .01
   //
-  if ( value  < 0.01 && value > -0.01 )
+  else if ( value  < 0.01 && value > -0.01 )
     {
-      outlen = sprintf (buf, "%.5E", value);
-      goto formatdone;
+      outlen = xsnprintf (buf, maxlen, "%.5E", value);
     }
   //
   //       if an integer value, print with 0 precision
   //
-  if (((long)(value*2.0) / 2) == value)
+  else if (((long)(value*2.0) / 2) == value)
     {
-      outlen = sprintf (buf, "%.0f", value);
-      goto formatdone;
+      outlen = xsnprintf (buf, maxlen, "%.0f", value);
     }
   //
   //       if none of the above, print with five digits precision
   //
-  outlen = sprintf (buf, "%.5f", value);
+  else
+    {
+      outlen = xsnprintf (buf, maxlen, "%.5f", value);
+    }
   //
   //
   //         one way or another, once we're here, we've sprinted it.
- formatdone:
   if (internal_trace)
     fprintf (stderr, "math_formatter outlen = %ld\n", outlen);
   return (outlen);
 }
 
 
-//#define OLD_STRALMATH
-#ifdef OLD_STRALMATH
-
-//
-//      stralnmath - evaluate a mathematical expression in algebraic
-//    (that is, infix parenthesized) notation.
-//
-//      The algorithm is this:
-//    see an open parenthesis - push an empty level
-//    see an operator - push it onto opstack, sp++
-//    see a number - push it, then try to "reduce" if there's a valid op.
-//    see a close parethesis -  try to "reduce", then pop over the empty 
-//
-//    reduce: 
-//         while sp > 0 
-//             if opstack[sp-1] valid
-//                   sp--
-//                   execute opstack[sp] on [sp], [sp+1]
-//                   replace sp with result
-//
-//    Note that the empty levels (opstack[sp] == '\000') that are
-//    produced by open and close parens are how we prevent runaway
-//    reduce operations on the stack.
-//
-
-long stralmath (char *buf, long inlen, long maxlen, long *retstat)
-{
-  double valstack [DEFAULT_MATHSTK_LIMIT];     // the evaluation value stack
-  long opstack [DEFAULT_MATHSTK_LIMIT];     // the evaluation operator stack
-  double sd;             //  how many 10^n's we've seen since a decimal
-  long od;               //  output decimal flag               
-  long ip, op;           //  in string pointer, out string pointer
-  long sp;               //  stack pointer - points to next (vacant) space
-  long sinc;             //  stack incrmenter - do we push on next digit in?
-  long errstat;          //  error status
-  char outformat[64];   // output format (if needed)
-
-  //  internal_trace = 1;
-  //user_trace = 1;
-  //    start off by initializing things
-  ip = 0;    //  in pointer is zero
-  op = 0;    // output pointer is zero
-  sp = 0;    // still at the top of the stack
-  od = 0;    // no decimals seen yet, so no flag to output in decimal
-  sinc = 0;  // no autopush.
-
-  outformat [0] = '\0';
-
-  //     now our number-inputting hacks
-  valstack[sp] = 0.0 ; 
-  opstack[sp] = '\000';
-  sd = 1.0;
-
-  //      all initialized... let's begin.
-
-  if (internal_trace) 
-    fprintf (stderr, "Math on '%s' len %ld *retstat %lx \n", 
-	     buf, inlen, (long) retstat);
-
-  for (ip = 0; ip < inlen; ip++)
-    {
-      if (internal_trace)
-	fprintf (stderr, "ip = %ld, sp = %ld, valstack[sp] = %f," 
-		 " opstack = '%c', buf ='%c'\n",
-		 ip, sp, valstack[sp], (short) opstack[sp], buf[ip]);
-
-      if (sp < 0) 
-	{
-	  errstat = nonfatalerror ("Stack Underflow in math evaluation",
-			 "");
-	  return (0);
-	};
-
-      if (sp >= DEFAULT_MATHSTK_LIMIT)
-	{
-	  errstat = nonfatalerror ("Stack Overflow in math evaluation. ",
-			 "CRM114 Barbie says 'This math is too hard'.");
-	  return (0);
-	};
-
-
-      switch (buf[ip])
-	{
-	  //
-	  //        a digit,or maybe a number - big change - we now use strtod
-	  //
-	case '.':
-	case '0':
-	case '1':
-	case '2':
-	case '3':
-	case '4':
-	case '5':
-	case '6':
-	case '7':
-	case '8':
-	case '9':
-	case '-':
-	  {
-	    char *frejected;
-	    if (user_trace)
-	      fprintf (stderr, " found a poss number starting with %c, ",
-		       buf[ip]);
-
-	    //    handle the case of a minus sign that isn't a unary -.
-	    if (buf[ip] == '-' 
-		&& !( isdigit (buf[ip+1]))) 
-	      {
-		if (sp > 0 && opstack[sp-1] != '\000')
-		  {
-		    long state;
-		    if (user_trace) 
-		      fprintf (stderr, "nope, dyadic minus. \n");
-		    if (sp > 0) sp--;
-		    state = stralmath_reduce (valstack, opstack, 
-					      &sp, outformat);
-		    if (state != -1 && retstat) *retstat = state;
-		  }
-		opstack[sp] = buf[ip]; 
-		if (opstack[sp] == ' ') opstack[sp] = '\000';
-	      }
-	    else
-	      {
-		
-		//   use strtod to convert the string we're looking at.
-		sp++;
-		opstack[sp] = '\000';
-		valstack[sp] = strtod ( &buf[ip], &frejected);
-		if (user_trace)
-		  fprintf (stderr, " got number: %e\n", valstack[sp]);
-		//
-		//    Now, move [ip] over to accomodate characters used.
-		//    (the -1 is because there's an auto-increment in the big 
-		//    FOR-loop)
-		ip = ((unsigned long) frejected) - ((unsigned long) buf ) - 1;
-		sinc = 0;
-	      }
-	  }
-	  break;
-	  //
-	  //         and now the parenthesis ops
-	  //
-	  //        open paren- we start a new stack level
-	case '(':
-	  {
-	    if (user_trace)
-	      fprintf (stderr, " got open parenthesis\n");
-	    sd = 1.0;
-	    sp++;
-	    valstack[sp] = 0.0;
-	    opstack[sp] = '\000';
-	  };
-	  break;
-	  //
-	  //        close paren- we finish evaluation down to the open,
-	  //        then supply the result to the next lower level.
-	case ')':
-	  {
-	    long state;
-	    if (user_trace)
-	      fprintf (stderr, " got close parenthesis\n");
-	    if (sp > 0) sp--;
-	    state = stralmath_reduce (valstack, opstack, &sp, outformat);
-	    if (state != -1 && retstat) *retstat = state;
-	    if (sp > 0) sp--;
-	    //   and get rid of that extra level we inserted before.
-	    valstack[sp] = valstack[sp+1];
-	  };
-	  break;
-	  //   
-	  //      The se dyadic operators just put themselves on the
-	  //      stack unless there's a prior dyadic operator, that
-	  //      operator runs first.
-	  //
-	  //	case '-': (this is handled up above, as part of unary '-'
-	case '+':
-	case '*':
-	case '/':
-	case '%':
-	case '=':
-	case '>':
-	case '<':
-	case '!':
-	case 'e':
-	case 'E':
-	case 'f':
-	case 'F':
-	case 'g':
-	case 'G':
-	case 'x':
-	case 'X':
-	  {
-	    if (user_trace)
-	      {
-		if (buf[ip+1] == '=')
-		  {
-		    fprintf (stderr, " got 2-char dyadic operator %c%c\n", 
-			     buf[ip], buf[ip+1]);
-		  }
-		else
-		  fprintf (stderr, " got dyadic operator %c\n", buf[ip]);
-	      };
-	    //     If there's something on the stack, run it first.
-	    if (sp > 0 && opstack[sp-1] != '\000')
-	      {
-		long state;
-		if (sp > 0) sp--;
-		state = stralmath_reduce (valstack, opstack, &sp, outformat);
-		if (state != -1 && retstat) *retstat = state;
-	      };
-	    sd = 1.0;
-	    sinc = 1;
-	    //         now put ourselves onto the stack
-	    if (buf[ip+1] == '=')
-	      {
-		opstack[sp] = (buf[ip] << 8) + buf[ip+1];
-		ip++ ; // gobble up the extra characters
-	      }
-	    else
-	      {
-		opstack[sp] = buf[ip];
-	      }
-	    if (opstack[sp] == ' ') opstack[sp] = '\000';
-	  };
-	  break;
-	case ' ':
-	case '\n':
-	case '\t':
-	  break;
-	default:
-	  {
-	    char bogus[4];
-	    bogus[0] = buf[ip];
-	    bogus[1] = '\000';
-	    nonfatalerror (" Sorry, but I can't do math on the un-mathy "
-			   "character found: ", bogus); 
-	  };
-	  break;
-	};
-    };
-
-  //  Now do final executes....
-  if (sp > 0) 
-    {
-      long state;
-      if (sp > 0 && opstack [sp-1] != '\000') sp--;
-      state = stralmath_reduce (valstack, opstack, &sp, outformat);
-      if (state != -1 && retstat) *retstat = state; 
-    };
-
-
-
-  if (internal_trace)
-    {
-      fprintf (stderr, 
-	       "Final qexpand state:  ip = %ld, sp = %ld,"
-	       " valstack[sp] = %f, buff='%c'\n", 
-	       ip, sp, valstack[sp], buf[ip]);
-      if (retstat) 
-	fprintf (stderr, "retstat = %ld\n", *retstat);
-    };
-
-  //      now the top of stack contains the result of the calculation.
-  //      fprintf it into the output buffer, and we're done.
-
-  //internal_trace = 0;
-  //user_trace = 0;
-  return (math_formatter (valstack[sp], outformat, buf));
-
-}
-
-//////////////////////////////////////////////////////////////////////
-//
-//            stralmath_reduce - actually do the math for algebraic arithmetic.
-//            retval is 0 for "successful EQ's", and 1 for unsuccessful,
-//            and -1 for "no change".
-//
-//            stralmath_reduce keeps applying the operator from the 
-//            top of the opstack against the top two things in the
-//            valstack, until it hits a "null level" (that is, an op of \000)
-//            which is a flag to stop for now.
-//
-long stralmath_reduce (double *valstack, long *opstack, long *sp, char *outformat)
-{
-  long retval;
-  retval = -1;
-  if (internal_trace)
-    fprintf (stderr, "  start: *sp = %3ld, "
-	     "vs[*sp] = %6.3f, vs[*sp+1] = %6.3f, "
-	     "op[*sp] = 0x%lX('%c')\n", 
-	     *sp, valstack[*sp], valstack[*sp+1], 
-	     (unsigned long) opstack[*sp],
-	     (short) opstack[*sp]);
-  
-  while (*sp >= 0 && opstack[*sp] != '\000')
-    {
-      if (internal_trace)
-	fprintf (stderr, "running: *sp = %3ld, "
-		 "vs[*sp] = %6.3f, vs[*sp+1] = %6.3f, "
-		 "op[*sp] = 0x%lX('%c')\n", 
-		 *sp, valstack[*sp], valstack[*sp+1], 
-		 (unsigned long)opstack[*sp],
-		 (short)opstack[*sp]);
-      switch (opstack[*sp])
-	{
-	case '+':
-	  valstack[*sp] = valstack[*sp] + valstack[*sp+1];
-	  opstack[*sp] = '\000';
-	  break;
-	case '-':
-	  valstack[*sp] = valstack[*sp] - valstack[*sp+1];
-	  opstack[*sp] = '\000';
-	  break;
-	case '*':
-	  valstack[*sp] = valstack[*sp] * valstack[*sp+1];
-	  opstack[*sp] = '\000';
-	  break;
-	case '/':
-	  if (valstack[*sp+1] == 0.0) 
-	    {
-	      opstack[*sp+1] = '\000';
-	      nonfatalerror ("Attempt to divide by zero.","");
-	      return (-1);		    
-	    };
-	  valstack[*sp] = valstack[*sp] / valstack[*sp+1];
-	  opstack[*sp] = '\000';
-	  break;
-	case '%':
-	  valstack[*sp] = ((long long)valstack[*sp]) % ((long long) valstack[*sp+1]);
-	  opstack[*sp] = '\000';
-	  break;
-	case 'e':
-	case 'E':
-	case 'f':
-	case 'F':
-	case 'g':
-	case 'G':
-	case 'x':
-	case 'X':
-	  //             User-specified formatting; use the user's 
-	  //             top-of-stack value as a format.
-	  //
-	  //             Note the funny business in the cases where a .0
-	  //             format is needed, because .0 won't print directly
-	  //             when we build the format with a %g .
-	  {
-	    char tempstring [2048];
-	    if ( ((long)valstack[*sp+1]) / 1 == valstack[*sp+1])
-	      {
-		sprintf (outformat, "%%%g.0%c", 
-			 valstack[*sp+1], (short) opstack[*sp]);
-	      }
-	    else
-	      {
-		sprintf (outformat, "%%%g%c", valstack[*sp+1], 
-			 (short) opstack[*sp]);
-	      };
-	    if (internal_trace)
-	      fprintf (stderr, "Format string -->%s<-- \n", outformat);
-
-	    //      A little more funny business needed for hexadecimal print
-	    //      out, because X format can't take IEEE floating point
-	    //      as inputs.
-	    if (opstack[*sp] != 'x' &&
-		opstack[*sp] != 'X')
-	      {
-		// fprintf (stderr, "NORMAL ");
-		sprintf (tempstring, outformat, valstack[*sp]);
-		valstack[*sp] = strtod (tempstring, NULL);
-	      }
-	    else
-	      {
-		//    Note that we actually don't use the results of octal
-		//    conversion; the only effect is to set the final format
-		//    string.
-		long long equiv;
-		// fprintf (stderr, "BLORT ");
-		equiv = valstack[*sp] + 0;
-		// fprintf (stderr, "equiv -->%10lld<-- \n", equiv);
-		sprintf (tempstring, outformat, equiv);
-	      }
-	    if (internal_trace)
-	      fprintf (stderr, "Intermediate result string -->%s<-- \n", 
-		       tempstring);
-	    opstack [*sp] = '\000';
-	  };
-	  break;
-	case (('!' << 8) + '='):
-	  //fprintf (stderr, "BANG EQUALS \n");
-	  if (valstack[*sp] != valstack[*sp+1])
-	    {
-	      valstack[*sp] = 1 ;
-	    }
-	  else
-	    {
-	      valstack[*sp] = 0;
-	    }
-	  opstack[*sp] = '\000';
-	  retval = 1 - valstack[*sp]; 
-	  break;
-	case '=':
-	  if (valstack[*sp] == valstack[*sp+1])
-	    {
-	      valstack[*sp] = 1 ;
-	    }
-	  else
-	    {
-	      valstack[*sp] = 0;
-	    }
-	  opstack[*sp] = '\000';
-	  retval = 1 - valstack[*sp]; 
-	  break;
-	case '>':
-	  if (valstack[*sp] > valstack[*sp+1])
-	    {
-	      valstack[*sp] = 1 ;
-	    }
-	  else
-	    {
-	      valstack[*sp] = 0;
-	    }
-	  opstack[*sp] = '\000';
-	  retval = 1 - valstack[*sp]; 
-	  break;
-	case (('>' << 8) + '='):
-	  // fprintf (stderr, "GREATER EQUALS\n");
-	  if (valstack[*sp] >= valstack[*sp+1])
-	    {
-	      valstack[*sp] = 1 ;
-	    }
-	  else
-	    {
-	      valstack[*sp] = 0;
-	    }
-	  opstack[*sp] = '\000';
-	  retval = 1 - valstack[*sp]; 
-	  break;
-	case (('<' << 8) + '='):
-	  // fprintf (stderr, "LESSER EQUALS\n");
-	  if (valstack[*sp] <= valstack[*sp+1])
-	    {
-	      valstack[*sp] = 1 ;
-	    }
-	  else
-	    {
-	      valstack[*sp] = 0;
-	    }
-	  opstack[*sp] = '\000';
-	  retval = 1 - valstack[*sp]; 
-	  break;
-	case '<':
-	  if (valstack[*sp] < valstack[*sp+1])
-	    {
-	      valstack[*sp] = 1 ;
-	    }
-	  else
-	    {
-	      valstack[*sp] = 0;
-	    }
-	  opstack[*sp] = '\000';
-	  retval = 1 - valstack[*sp]; 
-	  break;
-	default:
-	  break;
-	};
-      if (*sp > 0 && opstack[(*sp)-1] != '\000') *sp = *sp - 1;
-    };
-  if (internal_trace)
-    fprintf (stderr, " finish: *sp = %3ld, "
-	     "vs[*sp] = %6.3f, vs[*sp+1] = %6.3f, "
-	     "op[*sp] = 0x%lX('%c')\n", 
-	     *sp, valstack[*sp], valstack[*sp+1], 
-	     (unsigned long) opstack[*sp],
-	     (short) opstack[*sp]) ;
-  return (retval);
-}
-
-#endif
-
-#define NEW_STRALMATH
-#ifdef NEW_STRALMATH
 ////////////////////////////////////////////////////////////////////
 //
 //   Alternative implementation of the uglyness that is string math.
@@ -1420,26 +950,31 @@ long stralmath (char *buf, long inlen, l
 	    case 'x':
 	    case 'X':
 	      {
+		char tempstring [2048];
 		if (internal_trace)
 		  fprintf (stderr, "Formatting operator %c \n", 
 			   (short)opstack[sp]);
-		char tempstring [2048];
+		if (abs(rightarg) >= sizeof(tempstring))
+		  {
+		    errstat = nonfatalerror("Too large field width.", "");
+		    return 0;
+		  }
 		//     Do we have a float or an int format?
 		if (opstack[sp] == 'x' || opstack[sp] == 'X')
 		  {
-		    sprintf (outformat, "%%%g.0ll%c",
-			     rightarg, (short) opstack[sp]);
+		    xsnprintf (outformat, sizeof(outformat), "%%%d.0ll%c",
+			     (int) rightarg, (short) opstack[sp]);
 		  }
 		else 
 		  {
 		    if (((long) rightarg) / 1 == rightarg)
 		      {
-			sprintf (outformat, "%%%g.0%c",
-				 rightarg, (short) opstack[sp]);
+			xsnprintf (outformat, sizeof(outformat), "%%%d.0%c",
+				 (int) rightarg, (short) opstack[sp]);
 		      }
 		    else
 		      {
-			sprintf (outformat, "%%%g%c", 
+			xsnprintf (outformat, sizeof(outformat), "%%%g%c", 
 				 rightarg, (short)opstack[sp]);
 		      };
 		  };
@@ -1455,7 +990,8 @@ long stralmath (char *buf, long inlen, l
 		  {
 		    if (internal_trace)
 		      fprintf (stderr, "Normal convert ");
-		    sprintf (tempstring, outformat, leftarg[sp] );
+		    xsnprintf (tempstring, sizeof(tempstring), outformat,
+				  leftarg[sp] );
 		    leftarg[sp] = strtod (tempstring, NULL);
 		    validstack[sp] = LEFTVALID;
 		  }
@@ -1471,7 +1007,8 @@ long stralmath (char *buf, long inlen, l
 		    equiv = leftarg[sp] + 0.0;
 		    if (internal_trace)
 		      fprintf (stderr, "equiv -->%10lld<-- \n", equiv);
-		    sprintf (tempstring, outformat, equiv);
+		    xsnprintf (tempstring, sizeof(tempstring), outformat,
+				  equiv);
 		  };
 	      };
 	      break;
@@ -1513,9 +1050,8 @@ long stralmath (char *buf, long inlen, l
   //    All's good, return with a value.
   {
     long return_length;
-    return_length = (math_formatter (leftarg[sp], outformat, buf));
+    return_length = (math_formatter (leftarg[sp], outformat, buf, maxlen));
     outformat [return_length] = '\000';
     return (return_length);
   };
 }      
-#endif
Index: crm_osb_bayes.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_osb_bayes.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_osb_bayes.c
--- crm_osb_bayes.c	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm_osb_bayes.c	13 Jun 2007 18:55:06 -0000
@@ -1767,11 +1767,11 @@ int crm_expr_osb_bayes_classify (CSL_CEL
 
       if (tprob > 0.5000)
 	{
-	  sprintf (buf, "CLASSIFY succeeds; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
+	  xsnprintf (buf, sizeof(buf), "CLASSIFY succeeds; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
 	}
       else
 	{
-	  sprintf (buf, "CLASSIFY fails; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
+	  xsnprintf (buf, sizeof(buf), "CLASSIFY fails; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
 	};
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
@@ -1784,15 +1784,16 @@ int crm_expr_osb_bayes_classify (CSL_CEL
 	  {
 	    remainder = remainder + ptc[m];
 	  };
-      sprintf (buf, "Best match to file #%ld (%s) "\
-    		    "prob: %6.4f  pR: %6.4f  \n",
+      xsnprintf (buf, sizeof(buf), "Best match to file #%ld (%s) "
+				   "prob: %6.4f  pR: %6.4f  \n",
 	       bestseen,
 	       hashname[bestseen],
 	       ptc[bestseen],
 	       (log10(ptc[bestseen]) - log10(remainder)));
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
-      sprintf (buf, "Total features in input file: %ld\n", unk_features); 
+      xsnprintf (buf, sizeof(buf), "Total features in input file: %ld\n",
+		unk_features); 
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
       if (use_chisquared)
@@ -1806,7 +1807,7 @@ int crm_expr_osb_bayes_classify (CSL_CEL
 		  {
 		    remainder = remainder + ptc[m];
 		  };
-	      sprintf (buf, 
+	      xsnprintf (buf, sizeof(buf),
 		       "#%ld (%s):" \
 		       " features: %ld, hits: %ld,"   // exp: %ld," 
 		       " chi2: %3.2e, pR: %6.2f \n", 
@@ -1833,7 +1834,7 @@ int crm_expr_osb_bayes_classify (CSL_CEL
 		  {
 		    remainder = remainder + ptc[m];
 		  };
-	      sprintf (buf, 
+	      xsnprintf (buf, sizeof(buf),
 		       "#%ld (%s):"					\
 		       " features: %ld, hits: %ld, prob: %3.2e, pR: %6.2f \n", 
 		       k,
Index: crm_osb_hyperspace.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_osb_hyperspace.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_osb_hyperspace.c
--- crm_osb_hyperspace.c	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm_osb_hyperspace.c	13 Jun 2007 18:55:06 -0000
@@ -1798,11 +1798,11 @@ int crm_expr_osb_hyperspace_classify (CS
 
       if (tprob > 0.5000)
 	{
-	  sprintf (buf, "CLASSIFY succeeds; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
+	  xsnprintf (buf, sizeof(buf), "CLASSIFY succeeds; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
 	}
       else
 	{
-	  sprintf (buf, "CLASSIFY fails; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
+	  xsnprintf (buf, sizeof(buf), "CLASSIFY fails; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
 	};
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
@@ -1815,8 +1815,8 @@ int crm_expr_osb_hyperspace_classify (CS
 	  {
 	    remainder = remainder + ptc[m];
 	  };
-      sprintf (buf, "Best match to file #%ld (%s) "\
-    		    "prob: %6.4f  pR: %6.4f  \n",
+      xsnprintf (buf, sizeof(buf), "Best match to file #%ld (%s) "
+				   "prob: %6.4f  pR: %6.4f  \n",
 	       bestseen,
 	       hashname[bestseen],
 	       ptc[bestseen],
@@ -1829,7 +1829,8 @@ int crm_expr_osb_hyperspace_classify (CS
 	       );
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
-      sprintf (buf, "Total features in input file: %ld\n", totalfeatures); 
+      xsnprintf (buf, sizeof(buf), "Total features in input file: %ld\n",
+		totalfeatures); 
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
       for (k = 0; k < maxhash; k++)
@@ -1841,7 +1842,7 @@ int crm_expr_osb_hyperspace_classify (CS
 		{
 		  remainder = remainder + ptc[m];
 		};
-	  sprintf (buf, 
+	  xsnprintf (buf, sizeof(buf),
 		   "#%ld (%s):"\
 		   " features: %ld, hits: %ld, radiance: %3.2e, prob: %3.2e, pR: %6.2f \n", 
 		   k,
Index: crm_osb_winnow.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_osb_winnow.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_osb_winnow.c
--- crm_osb_winnow.c	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm_osb_winnow.c	13 Jun 2007 18:55:06 -0000
@@ -1309,11 +1309,11 @@ int crm_expr_osb_winnow_classify (CSL_CE
 
       if (tprob > 0.5000)
 	{
-	  sprintf (buf, "CLASSIFY succeeds; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
+	  xsnprintf (buf, sizeof(buf), "CLASSIFY succeeds; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
 	}
       else
 	{
-	  sprintf (buf, "CLASSIFY fails; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
+	  xsnprintf (buf, sizeof(buf), "CLASSIFY fails; success probability: %6.4f  pR: %6.4f\n", tprob, overall_pR );
 	};
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
@@ -1333,7 +1333,7 @@ int crm_expr_osb_winnow_classify (CSL_CE
 
       //   ... and format some output of best single matching file
       //    
-      sprintf (buf, "Best match to file #%ld (%s) "\
+      xsnprintf (buf, sizeof(buf), "Best match to file #%ld (%s) "\
     		    "weight: %6.4f  pR: %6.4f  \n",
 	       bestseen,
 	       hashname[bestseen],
@@ -1341,7 +1341,8 @@ int crm_expr_osb_winnow_classify (CSL_CE
 	       classifierprs[bestseen]);
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
-      sprintf (buf, "Total features in input file: %ld\n", totalfeatures); 
+      xsnprintf (buf, sizeof(buf), "Total features in input file: %ld\n",
+		totalfeatures); 
       if (strlen (stext) + strlen(buf) <= stext_maxlen)
 	strcat (stext, buf);
 
@@ -1356,7 +1357,7 @@ int crm_expr_osb_winnow_classify (CSL_CE
 		{
 		  remainder = remainder + totalweights[m];
 		};
-	  sprintf (buf, 
+	  xsnprintf (buf, sizeof(buf),
 		   "#%ld (%s):"\
 		   " features: %.2f, unseen: %3.2e, weight: %3.2e, pR: %6.2f \n", 
 		   k,
Index: crm_osbf_bayes.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_osbf_bayes.c,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 crm_osbf_bayes.c
--- crm_osbf_bayes.c	12 Jun 2007 13:00:56 -0000	1.1.1.2
+++ crm_osbf_bayes.c	13 Jun 2007 18:55:06 -0000
@@ -1517,14 +1517,14 @@ crm_expr_osbf_bayes_classify (CSL_CELL *
 	  // if a pR offset was given, print it together with the real pR
 	  if (oslen > 0)
 	    {
-	      sprintf (buf,
+	      xsnprintf (buf, sizeof(buf),
 		       "CLASSIFY succeeds; success probability: "
 		       "%6.4f  pR: %6.4f/%6.4f\n",
 		       tprob, overall_pR, pR_offset);
 	    }
 	  else
 	    {
-	      sprintf (buf,
+	      xsnprintf (buf, sizeof(buf),
 		       "CLASSIFY succeeds; success probability: "
 		       "%6.4f  pR: %6.4f\n", tprob, overall_pR);
 	    }
@@ -1534,14 +1534,14 @@ crm_expr_osbf_bayes_classify (CSL_CELL *
 	  // if a pR offset was given, print it together with the real pR
 	  if (oslen > 0)
 	    {
-	      sprintf (buf,
+	      xsnprintf (buf, sizeof(buf),
 		       "CLASSIFY fails; success probability: "
 		       "%6.4f  pR: %6.4f/%6.4f\n",
 		       tprob, overall_pR, pR_offset);
 	    }
 	  else
 	    {
-	      sprintf (buf,
+	      xsnprintf (buf, sizeof(buf),
 		       "CLASSIFY fails; success probability: "
 		       "%6.4f  pR: %6.4f\n", tprob, overall_pR);
 	    }
@@ -1558,14 +1558,15 @@ crm_expr_osbf_bayes_classify (CSL_CELL *
 	  {
 	    remainder = remainder + ptc[m];
 	  };
-      sprintf (buf, "Best match to file #%ld (%s) "
-	       "prob: %6.4f  pR: %6.4f  \n",
+      xsnprintf (buf, sizeof(buf), "Best match to file #%ld (%s) "
+				   "prob: %6.4f  pR: %6.4f  \n",
 	       bestseen,
 	       hashname[bestseen],
 	       ptc[bestseen], (log10 (ptc[bestseen]) - log10 (remainder)));
       if (strlen (stext) + strlen (buf) <= stext_maxlen)
 	strcat (stext, buf);
-      sprintf (buf, "Total features in input file: %ld\n", totalfeatures);
+      xsnprintf (buf, sizeof(buf), "Total features in input file: %ld\n",
+		totalfeatures);
       if (strlen (stext) + strlen (buf) <= stext_maxlen)
 	strcat (stext, buf);
       for (k = 0; k < maxhash; k++)
@@ -1577,7 +1578,7 @@ crm_expr_osbf_bayes_classify (CSL_CELL *
 	      {
 		remainder = remainder + ptc[m];
 	      };
-	  sprintf (buf,
+	  xsnprintf (buf, sizeof(buf),
 		   "#%ld (%s):"
 		   " hits: %ld, ufeats: %ld, prob: %3.2e, pR: %6.2f \n",
 		   k,
Index: crm_preprocessor.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_preprocessor.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_preprocessor.c
--- crm_preprocessor.c	12 Jun 2007 12:44:55 -0000	1.1.1.1
+++ crm_preprocessor.c	13 Jun 2007 18:55:06 -0000
@@ -301,7 +301,7 @@ int crm_preprocessor (CSL_CELL *csl, int
 
 	      //
 	      //    Build the fault string.
-	      sprintf (faulttext,
+	      xsnprintf (faulttext, sizeof(faulttext),
 		       "\n######  THE NEXT LINE WAS AUTO_INSERTED BECAUSE THE FILE COULDN'T BE FOUND \nfault /Couldn't insert the file named '%s' that you asked for.  This is probably a bad thing./\n",
 		       insertfilename);
 	      textlen = strlen (faulttext)  ; //  -1 gets rid of the \0
@@ -337,7 +337,8 @@ int crm_preprocessor (CSL_CELL *csl, int
   //
   {
     char myhash[32];
-    sprintf (myhash, "%08lX", strnhash (csl->filetext, csl->nchars));
+    xsnprintf (myhash, sizeof(myhash), "%08lX", strnhash (csl->filetext,
+		csl->nchars));
     myhash[8] = '\0';
     crm_set_temp_var (":_pgm_hash:", myhash);
   };
Index: crm_str_funcs.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_str_funcs.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_str_funcs.c
--- crm_str_funcs.c	12 Jun 2007 12:44:56 -0000	1.1.1.1
+++ crm_str_funcs.c	13 Jun 2007 18:55:06 -0000
@@ -1041,3 +1041,18 @@ long strntrn (
 //   and Miller
 //
 //////////////////////////////////////////////////////////////////
+
+
+// Same as snprintf(3) with the exception that it aborts immediately if
+// a truncation occurs, so you don't have to check it at every place in
+// the sources.
+int xsnprintf(char *str, size_t size, const char *format, ...) {
+	int n;
+	va_list ap;
+
+	va_start(ap, format);
+	n = vsnprintf(str, size, format, ap);
+	va_end(ap);
+	assert(n < 0 || (size_t) n < size);
+	return n;
+}
Index: crm_var_hash_table.c
===================================================================
RCS file: /var/cvs/outback/crm/crm_var_hash_table.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crm_var_hash_table.c
--- crm_var_hash_table.c	12 Jun 2007 12:44:56 -0000	1.1.1.1
+++ crm_var_hash_table.c	13 Jun 2007 18:55:06 -0000
@@ -123,14 +123,14 @@ void crm_vht_init (int argc, char **argv
 	  }
 	else
 	  {
-	    sprintf (anamebuf, ":_arg%ld:", j);
+	    xsnprintf (anamebuf, sizeof(anamebuf), ":_arg%ld:", j);
 	    crm_set_temp_var ( anamebuf, argv[i] );
 	    j++;
 	  };
       };
     //
     //    and put the "user-visible" argc into a var as well.
-    sprintf (anamebuf, "%ld", j);
+    xsnprintf (anamebuf, sizeof(anamebuf), "%ld", j);
     crm_set_temp_var (":_argc:", anamebuf);
     //
     //   Go through argv, and place positional arguments (that is,
@@ -152,14 +152,14 @@ void crm_vht_init (int argc, char **argv
 	//                     if there is no "-" sign.
 	if (argv[i][0] != '-')
 	  {
-	    sprintf (anamebuf, ":_pos%ld:", j);
+	    xsnprintf (anamebuf, sizeof(anamebuf), ":_pos%ld:", j);
 	    crm_set_temp_var ( anamebuf, argv[i] );
 	    j++;
 	    if (j>0)    strcat (posvars, " ");
 	    strcat (posvars, argv[i]);
 	  };
       };
-    sprintf (anamebuf, "%ld", j);
+    xsnprintf (anamebuf, sizeof(anamebuf), "%ld", j);
     crm_set_temp_var (":_posc:", anamebuf);
     crm_set_temp_var (":_pos_str:", posvars);
     //
@@ -174,11 +174,11 @@ void crm_vht_init (int argc, char **argv
       char pidstr [32];
       long pid;
       pid = (long) getpid();
-      sprintf (pidstr, "%ld", pid);
+      xsnprintf (pidstr, sizeof(pidstr), "%ld", pid);
       crm_set_temp_var (":_pid:", pidstr);
 #ifdef POSIX
       pid = (long) getppid();
-      sprintf (pidstr, "%ld", pid);
+      xsnprintf (pidstr, sizeof(pidstr), "%ld", pid);
       crm_set_temp_var (":_ppid:", pidstr);
 #endif
     }
