6770ee085321b29453a487768932d1d782ca7e6e
kent
  Sat Aug 17 13:02:03 2019 -0700
Implemented warn() built in function.

diff --git src/lib/strex.c src/lib/strex.c
index 04481bc..5312ef3 100644
--- src/lib/strex.c
+++ src/lib/strex.c
@@ -57,30 +57,31 @@
     strexBuiltInSeparate,
     strexBuiltInUncsv,
     strexBuiltInUntsv,
     strexBuiltInReplace,
     strexBuiltInFix,
     strexBuiltInStrip,
     strexBuiltInLen,
     strexBuiltInSymbol,
     strexBuiltInLower,
     strexBuiltInUpper,
     strexBuiltInIn, 
     strexBuiltInStarts,
     strexBuiltInEnds,
     strexBuiltInSame,
     strexBuiltInTidy,
+    strexBuiltInWarn,
     };
 
 struct strexBuiltIn
 /* Information to describe a built in function */
     {
     char *name;		/* Name in strex language:  trim, split, etc */
     enum strexBuiltInFunc func;  /* enum version: strexBuiltInTrim strexBuiltInSplit etc. */
     enum strexType returnType;	 /* Type of return value */
     int paramCount;	/* Number of parameters, not flexible in this language! */
     enum strexType *paramTypes;  /* Array of types, one for each parameter */
     };
 
 union strexVal
 /* Some value of arbirary type that can be of any type corresponding to strexType */
     {
@@ -176,30 +177,31 @@
     { "separate", strexBuiltInSeparate, strexTypeString, 3, stringStringInt },
     { "uncsv", strexBuiltInUncsv, strexTypeString, 2, stringInt },
     { "untsv", strexBuiltInUntsv, strexTypeString, 2, stringInt },
     { "replace", strexBuiltInReplace, strexTypeString, 3, threeStrings },
     { "fix", strexBuiltInFix, strexTypeString, 3, threeStrings },
     { "strip", strexBuiltInStrip, strexTypeString, 2, twoStrings },
     { "len", strexBuiltInLen, strexTypeInt, 1, oneString},
     { "symbol", strexBuiltInSymbol, strexTypeString, 2, twoStrings },
     { "upper", strexBuiltInUpper, strexTypeString, 1, oneString },
     { "lower", strexBuiltInLower, strexTypeString, 1, oneString },
     { "in", strexBuiltInIn, strexTypeBoolean, 2, twoStrings },
     { "starts", strexBuiltInStarts, strexTypeBoolean, 2, twoStrings}, 
     { "ends", strexBuiltInEnds, strexTypeBoolean, 2, twoStrings}, 
     { "same", strexBuiltInSame, strexTypeBoolean, 2, twoStrings}, 
     { "tidy", strexBuiltInTidy, strexTypeString, 3, threeStrings },
+    { "warn", strexBuiltInWarn, strexTypeString, 1, oneString},
 };
 
 static struct hash *hashBuiltIns()
 /* Build a hash of builtins keyed by name */
 {
 struct hash *hash = hashNew(0);
 int i;
 for (i=0; i<ArraySize(builtins); ++i)
     hashAdd(hash, builtins[i].name, &builtins[i]);
 return hash;
 }
 
 static struct strexIn *strexInNew(struct lineFile *lf,
     void *symbols, StrexLookup lookup)
 /* Return a new strexIn structure wrapped around lineFile */
@@ -1129,52 +1131,46 @@
 return parseTree;
 }
 
 /************ The parsing section is done, now for the evaluation section. **************/
 
 struct strexRun
 /* What we need to run a strex expression evaluation */
     {
     void *symbols;	/* Pointer to symbol table */
     StrexLookup lookup; /* Something that can look up things in symbol table */
     struct lm *lm;	/* Local memory for evaluation */
     void (*warnHandler)(char *warning);  /* Send warning messages here */
     void (*abortHandler)();	    /* Call this guy to abort */
     };
 
-static void strexDefaultWarn(char *warning)
-/* Default warning handler */
-{
-warn("%s", warning);
-}
-
 static void strexDefaultAbort()
 /* Default abort handler */
 {
 noWarnAbort();
 }
 
 static struct strexRun *strexRunNew(void *symbols, StrexLookup lookup, 
     void (*warnHandler)(char *warning), void (*abortHandler)() )
 /* Return new strexRun structure */
 {
 struct strexRun *run;
 AllocVar(run);
 run->lm = lmInit(0);
 run->symbols = symbols;
 run->lookup = lookup;
-run->warnHandler = (warnHandler != NULL ? warnHandler : strexDefaultWarn);
+run->warnHandler = warnHandler;
 run->abortHandler = (abortHandler != NULL ? abortHandler : strexDefaultAbort);
 return run;
 }
 
 static void strexRunFree(struct strexRun **pRun)
 /* Free up strex run structure */
 {
 struct strexRun *run = *pRun;
 if (run != NULL)
     {
     lmCleanup(&run->lm);
     freez(pRun);
     }
 }
 
@@ -1688,30 +1684,42 @@
 	    ourStart = orig;
 
 	/* Figure out end position */
 	char *defaultEnd = ourStart + strlen(ourStart);
 	char *ourEnd = NULL;
 	if (!isEmpty(after))
 	    {
 	    ourEnd = strstr(ourStart, after);
 	    }
 	if (ourEnd == NULL)
 	    ourEnd = defaultEnd;
 
 	int size = ourEnd - ourStart;
 	assert(size >= 0);
 	res.val.s = lmCloneStringZ(lm, ourStart, size);
+	break;
+	}
+    case strexBuiltInWarn:
+        {
+	/* Figure out the message we want to convey, send it to warning handler
+	 * before returning it. */
+        struct strexEval a = strexLocalEval(p->children, run);
+	char *message = a.val.s;
+	char *output = lmJoinStrings(run->lm, "WARNING: ", message);
+	if (run->warnHandler != NULL) run->warnHandler(output);
+	res.val.s = output;
+	break;
 	}
     }
 return res;
 }
 
 static struct strexEval strexEvalPick(struct strexParse *pick, struct strexRun *run)
 /* Evaluate a pick operator. */
 {
 /* Evaluate the keyValue */
 struct strexParse *p = pick->children;
 struct strexEval keyVal = strexLocalEval(p, run);
 p = p->next;
 
 /* Get pointer to default expression but don't evaluate it yet */
 struct strexParse *defaultExp = p;