2be851c8acf32ce69189a0d0bae0d81d9523ac5f kent Thu Dec 9 16:06:58 2021 -0800 Adding new symbol_id() builtin function. diff --git src/lib/strex.c src/lib/strex.c index 7100492..2736f3d 100644 --- src/lib/strex.c +++ src/lib/strex.c @@ -47,30 +47,31 @@ * aa correspondence between these names and the built in function name */ { strexBuiltInTrim, strexBuiltInBetween, strexBuiltInWord, strexBuiltInNow, strexBuiltInMd5, strexBuiltInChop, strexBuiltInUncsv, strexBuiltInUntsv, strexBuiltInReplace, strexBuiltInFix, strexBuiltInStrip, strexBuiltInLen, strexBuiltInSymbol, + strexBuiltInSymbolId, strexBuiltInLower, strexBuiltInUpper, strexBuiltInIn, strexBuiltInStarts, strexBuiltInEnds, strexBuiltInSame, strexBuiltInTidy, strexBuiltInWarn, strexBuiltInError, strexBuiltInLetterRange, strexBuiltInWordRange, strexBuiltInChopRange, }; struct strexBuiltIn @@ -93,31 +94,31 @@ struct strexBuiltIn *builtIn; }; struct strexEval /* Result of evaluation of parse tree. */ { enum strexType type; union strexVal val; }; enum strexOp /* An operation in the parse tree. */ { strexOpUnknown, /* Should not occur */ strexOpLiteral, /* Literal string or number. */ - strexOpSymbol, /* A symbol name. */ + strexOpSymbol, /* Symbol/variable. */ strexOpBuiltInCall, /* Call a built in function */ strexOpPick, /* Similar to built in but pick deserves it's own op. */ strexOpConditional, /* Conditional trinary operation */ strexOpArrayIx, /* An array with an index. */ strexOpArrayRange, /* An array with a range. */ strexOpStrlen, /* Length of a string */ /* Unary minus for numbers, logical not */ strexOpUnaryMinusInt, strexOpUnaryMinusDouble, strexOpNot, @@ -182,30 +183,31 @@ * fill in if you add a new built in function. */ static struct strexBuiltIn builtins[] = { { "trim", strexBuiltInTrim, strexTypeString, 1, oneString, }, { "between", strexBuiltInBetween, strexTypeString, 3, threeStrings }, { "word", strexBuiltInWord, strexTypeString, 2, stringInt }, { "now", strexBuiltInNow, strexTypeString, 0, NULL }, { "md5", strexBuiltInMd5, strexTypeString, 1, oneString }, { "chop", strexBuiltInChop, 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 }, + { "symbol_id", strexBuiltInSymbolId, strexTypeString, 2, twoStrings }, { "upper", strexBuiltInUpper, strexTypeString, 1, oneString }, { "lower", strexBuiltInLower, strexTypeString, 1, oneString }, { "in", strexBuiltInIn, strexTypeBoolean, 2, twoStrings }, { "starts_with", strexBuiltInStarts, strexTypeBoolean, 2, twoStrings}, { "ends_with", strexBuiltInEnds, strexTypeBoolean, 2, twoStrings}, { "same", strexBuiltInSame, strexTypeBoolean, 2, twoStrings}, { "tidy", strexBuiltInTidy, strexTypeString, 3, threeStrings }, { "warn", strexBuiltInWarn, strexTypeString, 1, oneString}, { "error", strexBuiltInError, strexTypeString, 1, oneString}, { "letter_range", strexBuiltInLetterRange, strexTypeString, 3, stringIntInt}, { "word_range", strexBuiltInWordRange, strexTypeString, 3, stringIntInt}, { "chop_range", strexBuiltInChopRange, strexTypeString, 4, stringStringIntInt}, }; static struct hash *hashBuiltIns() @@ -1939,30 +1941,54 @@ out += strlen(hexBuf); } } *out++ = 0; int len = strlen(result) - prefixSize; if (len > 32) { char *md5 = hmacMd5("", original); strcpy(result + prefixSize, md5); freeMem(md5); } return result; } +static char *idify(char *prefix, char *original, struct lm *lm) +/* Convert original to something could use as a prefix plus a numeric id */ +{ +static struct hash *prefixHash = NULL; +if (prefixHash == NULL) + prefixHash = hashNew(0); +struct hash *idHash = hashFindVal(prefixHash, prefix); +if (idHash == NULL) + { + 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; +} + + 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); break; @@ -2054,30 +2080,37 @@ break; } case strexBuiltInLen: { struct strexEval a = strexLocalEval(p->children, run); res.val.i = strlen(a.val.s); break; } case strexBuiltInSymbol: // Convert string to something could use as a C language symbol { struct strexEval a = strexLocalEval(p->children, run); struct strexEval b = strexLocalEval(p->children->next, run); res.val.s = symbolify(a.val.s, b.val.s, lm); break; } + case strexBuiltInSymbolId: // Convert string to something could use numeric id + { + struct strexEval a = strexLocalEval(p->children, run); + struct strexEval b = strexLocalEval(p->children->next, run); + res.val.s = idify(a.val.s, b.val.s, lm); + break; + } case strexBuiltInLower: { struct strexEval a = strexLocalEval(p->children, run); res.val.s = lmCloneString(lm, a.val.s); tolowers(res.val.s); break; } case strexBuiltInUpper: { struct strexEval a = strexLocalEval(p->children, run); res.val.s = lmCloneString(lm, a.val.s); touppers(res.val.s); break; } case strexBuiltInIn: