Index: trunk/Ohana/src/libohana/Makefile
===================================================================
--- trunk/Ohana/src/libohana/Makefile	(revision 8631)
+++ trunk/Ohana/src/libohana/Makefile	(revision 8633)
@@ -6,4 +6,7 @@
 MAN	=	$(HOME)/doc
 INC	=	$(HOME)/include
+TESTDIR =       $(HOME)/test
+TESTLIB =       $(ROOT)/src/libtap/lib/$(ARCH)
+TESTINC =       $(ROOT)/src/libtap/include
 DESTBIN	=	$(LBIN)
 DESTLIB	=	$(LLIB)
@@ -11,5 +14,7 @@
 DESTMAN	=	$(LMAN)
 
-CFLAGS	=	-I$(LINC) -D$(ARCH)
+LIBS	= 	-L$(LLIB) -L$(XLIB) -lohana
+CFLAGS	=	-I$(INC) -I$(LINC) -D$(ARCH)
+TFLAGS  =       $(CFLAGS) $(LIBS) -L$(TESTLIB) -I$(TESTINC) -ltap
 
 default: install
@@ -37,4 +42,7 @@
 $(SRC)/version.$(ARCH).o
 
+TEST = \
+$(TESTDIR)/string.$(ARCH)
+
 $(OBJS): $(INCS)
 
@@ -55,4 +63,13 @@
 	cp $(INC)/$* $(DESTINC)/
 
+$(TESTDIR)/%.$(ARCH) : $(DESTLIB)/libohana.a $(TESTDIR)/%.c
+	$(CC) $^ -o $@ $(TFLAGS)
+
+testcode: install $(TEST)
+
+test:
+	make testcode
+	for i in $(TEST); do $$i; done
+
 clean:
 	rm -f */*~
@@ -66,3 +83,9 @@
 
 .c.$(ARCH).o:
+	echo make c
+	echo $(CFLAGS)
+	echo $*.c
+	echo $@
 	$(CC) $(CFLAGS) -c $*.c -o $@
+
+.PHONY: test
Index: trunk/Ohana/src/libohana/include/ohana.h
===================================================================
--- trunk/Ohana/src/libohana/include/ohana.h	(revision 8631)
+++ trunk/Ohana/src/libohana/include/ohana.h	(revision 8633)
@@ -115,4 +115,5 @@
 int     remove_argument        PROTO((int N, int *argc, char **argv));
 void    uppercase              PROTO((char *string));
+char   *strsubs                PROTO((char *string, char *match, char *with));
 
 /* in findexec.c */
Index: trunk/Ohana/src/libohana/src/string.c
===================================================================
--- trunk/Ohana/src/libohana/src/string.c	(revision 8631)
+++ trunk/Ohana/src/libohana/src/string.c	(revision 8633)
@@ -69,4 +69,62 @@
 }
 
+// replace a single entry of 'match' in the string with 'with'
+// (quick-and-dirty regex for a common case...)
+char *strsubs (char *string, char *match, char *with) {
+
+  int N1, N2, N3;
+  char *root;
+  char *out;
+  char *ext;
+
+  if (string == NULL) return NULL;
+  if (match == NULL) return NULL;
+  if (with == NULL) return NULL;
+
+  root = strstr (string, match);
+  if (root == NULL) {
+    return (strcreate (string));
+  }
+  N1 = root - string;
+
+  N2 = strlen (with);
+
+  ext = root + strlen(match);
+  N3 = strlen (ext);
+
+  ALLOCATE (out, char *, N1 + N2 + N3 + 1);
+
+  strncpy (out, string, N1);
+  strncpy (&out[N1], with, N2);
+  strncpy (&out[N1+N2], ext, N3);
+  out[N1+N2+N3] = 0;
+
+  return out;
+}
+
+# if 0
+// replace a single entry of 'match' in the string with 'with'
+// (quick-and-dirty regex for a common case...)
+char *strrsubs (char *string, char *match, char *with) {
+
+  char *root;
+  char *out;
+
+  if (string == NULL) return NULL;
+  if (match == NULL) return NULL;
+  if (with == NULL) return NULL;
+
+  root = strstr (string, match);
+  if (root == NULL) return NULL;
+
+  ext = string + strlen (match);
+  ALLOCATE (out, char *, strlen(with) + strlen(ext) + 1);
+  strcpy (out, with);
+  strcat (out, ext);
+
+  return out;
+}
+# endif
+
 int scan_line (FILE *f, char *line) {
 
Index: trunk/Ohana/src/libohana/test/.cvsignore
===================================================================
--- trunk/Ohana/src/libohana/test/.cvsignore	(revision 8633)
+++ trunk/Ohana/src/libohana/test/.cvsignore	(revision 8633)
@@ -0,0 +1,1 @@
+*.linux *.lin64 *.sol
Index: trunk/Ohana/src/libohana/test/string.c
===================================================================
--- trunk/Ohana/src/libohana/test/string.c	(revision 8633)
+++ trunk/Ohana/src/libohana/test/string.c	(revision 8633)
@@ -0,0 +1,70 @@
+# include "ohana.h"
+# include "tap.h"
+
+int main (void) {
+
+  plan_tests (16);
+
+  diag ("libohana string.c tests");
+
+  /*** stripwhite ***/
+  {
+    int status;
+    char string[128];
+
+    status = stripwhite (NULL);
+    
+    ok (!status, "stripwhite status for NULL is FALSE");
+
+    sprintf (string, "  a test line  ");
+    status = stripwhite (string);
+    
+    ok (status, "stripwhite returns %d", status);
+    ok (!strcmp (string, "a test line"), "string is stripped");
+
+    sprintf (string, "a test line");
+    status = stripwhite (string);
+    
+    ok (status, "stripwhite returns %d", status);
+    ok (!strcmp (string, "a test line"), "string is stripped");
+  }
+    
+  /*** strsubs ***/
+  {
+    char *output;
+
+    output = strsubs (NULL, "needle", "noodle");
+    ok (output == NULL, "strsubs for NULL is NULL");
+
+    output = strsubs ("needle in haystack", NULL, "noodle");
+    ok (output == NULL, "strsubs for NULL is NULL");
+
+    output = strsubs ("needle in haystack", "needle", NULL);
+    ok (output == NULL, "strsubs for NULL is NULL");
+
+    output = strsubs ("needle in haystack", "needle", "noodle");
+    ok (output != NULL, "stripwhite status is TRUE");
+    skip_start (output == NULL, 1, "Skipping 1 test because strsubs returned NULL");
+    ok (!strcmp (output, "noodle in haystack"), "successful sustitution at beginning: %s", output);
+    skip_end();
+
+    output = strsubs ("needle in haystack", "in", "noodle");
+    ok (output != NULL, "stripwhite status is TRUE");
+    skip_start (output == NULL, 1, "Skipping 1 test because strsubs returned NULL");
+    ok (!strcmp (output, "needle noodle haystack"), "successful sustitution in middle: %s", output);
+    skip_end();
+
+    output = strsubs ("needle in haystack", "stack", "noodle");
+    ok (output != NULL, "stripwhite status is TRUE");
+    skip_start (output == NULL, 1, "Skipping 1 test because strsubs returned NULL");
+    ok (!strcmp (output, "needle in haynoodle"), "successful sustitution at end: %s", output);
+    skip_end();
+
+    output = strsubs ("needle in haystack", "junk", "noodle");
+    ok (output != NULL, "stripwhite status is TRUE");
+    skip_start (output == NULL, 1, "Skipping 1 test because strsubs returned NULL");
+    ok (!strcmp (output, "needle in haystack"), "successful sustitution without match: %s", output);
+    skip_end();
+  }
+  return exit_status();
+}
