14f04b894268dfdf9a94c8123df088e54683fa2c kent Fri Dec 17 16:48:33 2021 -0800 Fixing tidy() function in strex. diff --git src/lib/strex.c src/lib/strex.c index 2736f3d..ba8e4d4 100644 --- src/lib/strex.c +++ src/lib/strex.c @@ -1964,30 +1964,44 @@ { idHash = hashNew(0); hashAdd(prefixHash, prefix, idHash); } char *id = hashFindVal(idHash, original); if (id == NULL) { char symbuf[128]; safef(symbuf, sizeof(symbuf), "%s%d", prefix, idHash->elCount + 1); id = lmCloneString(idHash->lm, symbuf); hashAdd(idHash, original, id); } return id; } +char *finalMatchToSubstring(char *haystack,char *needle) +/* Return the final position of needle in haystack */ +{ +char *match = NULL; +for (;;) + { + haystack = strstr(haystack, needle); + if (haystack == NULL) + break; + match = haystack; + haystack += 1; // Don't repeat last match + } +return match; +} static struct strexEval strexEvalCallBuiltIn(struct strexParse *p, struct strexRun *run) /* Handle parse tree generated by call to a built in function. */ { struct strexBuiltIn *builtIn = p->val.builtIn; struct strexEval res; res.type = builtIn->returnType; struct lm *lm = run->lm; switch (builtIn->func) { case strexBuiltInTrim: { struct strexEval a = strexLocalEval(p->children, run); res.val.s = trimSpaces(a.val.s); @@ -2141,49 +2155,47 @@ res.val.b = (strcmp(a.val.s, b.val.s) == 0); break; } case strexBuiltInTidy: { /* Get parameters */ struct strexEval a = strexLocalEval(p->children, run); struct strexEval b = strexLocalEval(p->children->next, run); struct strexEval c = strexLocalEval(p->children->next->next, run); char *before = a.val.s; char *orig = b.val.s; char *after = c.val.s; /* Figure out start position - start of string if before string is empty or doesn't match * otherwise right after the place where before matches. */ - char *ourStart = NULL; + char *ourStart = orig; if (!isEmpty(before)) { - ourStart = strstr(orig, before); - if (ourStart != NULL) - ourStart += strlen(before); + char *newStart = strstr(orig, before); + if (newStart != NULL) + ourStart = newStart + strlen(before); } - if (ourStart == NULL) - ourStart = orig; /* Figure out end position */ char *defaultEnd = ourStart + strlen(ourStart); - char *ourEnd = NULL; + char *ourEnd = defaultEnd; if (!isEmpty(after)) { - ourEnd = strstr(ourStart, after); + char *newEnd = finalMatchToSubstring(ourStart, after); + if (newEnd != NULL) + ourEnd = newEnd; } - 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(run->symbols, output); res.val.s = output;