ba4333b84dc63534d59b306fea2031d7e8d08fbf angie Thu Jan 14 12:24:50 2016 -0800 Added the capability to substitute $hgsid from the cart in a help file included by webIncludeHelpFileSubst, for internal links. Improved the description of hgVai Transcript Status options. refs #16502 diff --git src/hg/lib/hVarSubst.c src/hg/lib/hVarSubst.c index 458d1f0..1893e30 100644 --- src/hg/lib/hVarSubst.c +++ src/hg/lib/hVarSubst.c @@ -1,315 +1,341 @@ /* Handle variable substitutions in strings from trackDb and other * labels. See trackDb/README for descriptions of values that can be * substitute. This code needs to do a special handle to remain compatibility * with behavior of the old substitution mechanism. */ /* Copyright (C) 2014 The Regents of the University of California * See README in this or parent directory for licensing information. */ #include "common.h" #include "trackDb.h" #include "hdb.h" #include "hui.h" #include "sqlNum.h" #include "hVarSubst.h" static boolean isVarEnd(boolean inBraces, char c) /** does the character end a variable reference. */ { if (inBraces) return (c == '}'); else return !((c == '_') || isalnum(c)); } static char *parseVarName(char *desc, char *varStart, char *varName, int varNameSize) /* parse substitution variable name out of a string, returning next position * after name. */ { char *p = varStart+1; if (*p == '\0') errAbort("trailing `$' while doing variable substitution in %s", desc); boolean inBraces = (*p == '{'); if (inBraces) p++; int nameIdx = 0; while ((nameIdx < varNameSize-1) && !isVarEnd(inBraces, *p)) varName[nameIdx++] = *p++; if (nameIdx == 0) errAbort("empty variable name in %s varStart='%s' varName='%s'", desc, varStart, varName); if (nameIdx == varNameSize) errAbort("variable name in desc %s exceeds maximum length of %d, starting with: \"%.*s\"", desc, varNameSize-1, varNameSize-1, varName); varName[nameIdx] = '\0'; if (inBraces) p++; return p; } static char *lookupTrackDbSubVar(char *desc, struct trackDb *tdb, char *settingName, char *varName) /* get the specified track setting to substitute or die trying; more useful * message than trackDbRequiredSetting when doing substitution */ { char *val = trackDbSettingClosestToHome(tdb, settingName); if (val == NULL) errAbort("trackDb (%s) setting \"%s\" not found for variable substitution of \"$%s\" in %s", tdb->track, settingName, varName, desc); return val; } static char *lookupOtherDb(char *desc, struct trackDb *tdb, char *varName) /* look up the otherDb variable, which is needed for substituting varName */ { return lookupTrackDbSubVar(desc, tdb, "otherDb", varName); } static void insertLinearGapHtml(struct trackDb *tdb, char *linearGap, struct dyString *dest) /* Generate HTML table from chain linearGap variable */ { if (sameWord("medium",linearGap)) { dyStringPrintf(dest, "<PRE>-linearGap=%s\n\n\ tableSize 11\n\ smallSize 111\n\ position 1 2 3 11 111 2111 12111 32111 72111 152111 252111\n\ qGap 350 425 450 600 900 2900 22900 57900 117900 217900 317900\n\ tGap 350 425 450 600 900 2900 22900 57900 117900 217900 317900\n\ bothGap 750 825 850 1000 1300 3300 23300 58300 118300 218300 318300\n\ </PRE>", linearGap); } else if (sameWord("loose", linearGap)) { dyStringPrintf(dest, "<PRE>-linearGap=%s\n\n\ tablesize 11\n\ smallSize 111\n\ position 1 2 3 11 111 2111 12111 32111 72111 152111 252111\n\ qGap 325 360 400 450 600 1100 3600 7600 15600 31600 56600\n\ tGap 325 360 400 450 600 1100 3600 7600 15600 31600 56600\n\ bothGap 625 660 700 750 900 1400 4000 8000 16000 32000 57000\n\ </PRE>", linearGap); } else errAbort("Invalid chainLinearGap specified '%s', can only be 'medium' or 'loose'", linearGap); } static void insertMatrixHtml(struct trackDb *tdb, char *matrix, char *matrixHeader, struct dyString *dest) /* Generate HTML table from matrix setting in trackDb. matrixHeader is * optional. */ { char *words[100]; char *headerWords[10]; int size; int i, j, k; int wordCount = 0, headerCount = 0; wordCount = chopString(cloneString(matrix), ", \t", words, ArraySize(words)); if (matrixHeader != NULL) headerCount = chopString(cloneString(matrixHeader), ", \t", headerWords, ArraySize(headerWords)); errno = 0; size = sqrt(sqlDouble(words[0])); if (errno) errAbort("Invalid matrix size in for track %s: %s\n", tdb->track, words[0]); dyStringAppend(dest, "The following matrix was used:<P>\n"); k = 1; dyStringAppend(dest, "<BLOCKQUOTE><TABLE class='chainTbl'>\n"); if (matrixHeader) { dyStringAppend(dest, "<TR ALIGN=right><TD> </TD>"); for (i = 0; i < size && i < headerCount; i++) dyStringPrintf(dest, "<TD><B>%s</B></TD>", headerWords[i]); dyStringAppend(dest, "</TR>\n"); } for (i = 0; i < size; i++) { dyStringAppend(dest, "<TR ALIGN=right>"); if (matrixHeader) dyStringPrintf(dest, "<TD><B>%s<B></TD>", headerWords[i]); for (j = 0; j < size && k < wordCount ; j++) dyStringPrintf(dest, "<TD>%s</TD>", words[k++]); dyStringAppend(dest, "</TR>\n"); } dyStringAppend(dest, "</TABLE></BLOCKQUOTE></P>\n"); } static void substLinearGap(struct trackDb *tdb, struct dyString *dest) /* Generate HTML table from matrix setting in trackDb. Note: for * compatibility, substitutes and empty string if matrix setting not found in * trackDb. */ { char *linearGap = trackDbSettingClosestToHome(tdb, "chainLinearGap"); if (linearGap != NULL) insertLinearGapHtml(tdb, linearGap, dest); } static void substMatrixHtml(struct trackDb *tdb, struct dyString *dest) /* Generate HTML table from matrix setting in trackDb. Note: for * compatibility, substitutes and empty string if matrix setting not found in * trackDb. */ { char *matrix = trackDbSettingClosestToHome(tdb, "matrix"); if (matrix != NULL) insertMatrixHtml(tdb, matrix, trackDbSettingClosestToHome(tdb, "matrixHeader"), dest); } static boolean isAbbrevScientificName(char *name) /* Return true if name looks like an abbreviated scientific name * (e.g. D. yakuba). */ { return (name != NULL && strlen(name) > 4 && isalpha(name[0]) && name[1] == '.' && name[2] == ' ' && isalpha(name[3])); } static boolean isDatabaseVar(char *varBase) /* Is this a variable that can be resolved only from the database name? * Specify the base name, excluding the o_ prefix. */ { return (strcasecmp(varBase, "organism") == 0) || (strcasecmp(varBase, "date") == 0) || (strcasecmp(varBase, "linkToGatewayPage") == 0) - || (strcasecmp(varBase, "db") == 0); + || (strcasecmp(varBase, "db") == 0) + || (strcasecmp(varBase, "hgsid") == 0); } static char *valOrDb(char *val, char *database) /* return val if not-null, or a clone of database if it is null */ { if (val == NULL) val = cloneString(database); return val; } -static void substDatabaseVar(char *database, char *varBase, +static void substDatabaseVar(char *database, struct cart *cart, char *varBase, struct dyString *dest) /* substitute a variable resolved from the database name. * Specify the base name, excluding the o_ prefix. If database * can be looked up, just substitute the database name. */ { if (sameString(varBase, "Organism")) { char *org = valOrDb(hOrganism(database), database); dyStringAppend(dest, org); freeMem(org); } else if (sameString(varBase, "ORGANISM")) { char *org = hOrganism(database); if (org != NULL) touppers(org); else org = valOrDb(org, database); dyStringAppend(dest, org); freeMem(org); } else if (sameString(varBase, "organism")) { char *org = hOrganism(database); if ((org != NULL) && !isAbbrevScientificName(org)) tolowers(org); else org = valOrDb(org, database); dyStringAppend(dest, org); freeMem(org); } else if (sameString(varBase, "date")) { char *date = valOrDb(hFreezeDateOpt(database), database); dyStringAppend(dest, date); freeMem(date); } else if (sameString(varBase, "db")) dyStringAppend(dest, database); +else if (sameString(varBase, "hgsid") && cart != NULL) + dyStringAppend(dest, cartSessionId(cart)); } static void substTrackDbVar(char *desc, struct trackDb *tdb, char *database, char *varName, struct dyString *dest) /* substitute a variable value obtained from trackDb */ { if (sameString(varName, "matrix")) substMatrixHtml(tdb, dest); else if (sameString(varName, "chainLinearGap")) substLinearGap(tdb, dest); else if (sameString(varName, "downloadsServer")) dyStringAppend(dest, hDownloadsServer()); else dyStringAppend(dest, lookupTrackDbSubVar(desc, tdb, varName, varName)); } -static void substVar(char *desc, struct trackDb *tdb, char *database, +static void substVar(char *desc, struct cart *cart, struct trackDb *tdb, char *database, char *varName, struct dyString *dest) /* look up varName and insert value in output string. Error if variable * can't be found */ { if (isDatabaseVar(varName)) - substDatabaseVar(database, varName, dest); + substDatabaseVar(database, cart, varName, dest); else if (tdb == NULL) errAbort("invalid variable \"%s\" to substitute in %s", varName, desc); else if (startsWith("o_", varName) && isDatabaseVar(varName+2)) - substDatabaseVar(lookupOtherDb(desc, tdb, varName), varName+2, dest); + substDatabaseVar(lookupOtherDb(desc, tdb, varName), cart, varName+2, dest); else substTrackDbVar(desc, tdb, database, varName, dest); } -char *hVarSubst(char *desc, struct trackDb *tdb, char *database, char *src) +static char *hVarSubstExt(char *desc, struct cart *cart, struct trackDb *tdb, char *database, + char *src) /* Parse a string and substitute variable references. Return NULL if * no variable references were found. Error on missing variables (except * $matrix). desc is a brief description to print on an error to help with * debugging. tdb maybe NULL to only do substitutions based on database - * and organism. See trackDb/README for more information.*/ + * and organism. cart may be NULL. See trackDb/README for more information.*/ { struct dyString *dest = NULL; char *start = src; // start of current static string in src char *next = src; // cursor char varName[65]; while ((next = strchr(next, '$')) != NULL) { if (dest == NULL) dest = dyStringNew(strlen(src)); dyStringAppendN(dest, start, next-start); if (*(next+1) == '$') { // $$ is a literal $ dyStringAppendC(dest, '$'); start = next = next + 2; } else { // variable reference start = next = parseVarName(desc, next, varName, sizeof(varName)); - substVar(desc, tdb, database, varName, dest); + substVar(desc, cart, tdb, database, varName, dest); } } if (dest != NULL) { dyStringAppend(dest, start); return dyStringCannibalize(&dest); } else return NULL; // no substitutions } +char *hVarSubst(char *desc, struct trackDb *tdb, char *database, char *src) +/* Parse a string and substitute variable references. Return NULL if + * no variable references were found. Error on missing variables (except + * $matrix). desc is a brief description to print on error to help with + * debugging. tdb maybe NULL to only do substitutions based on database + * and organism. See trackDb/README for more information.*/ +{ +return hVarSubstExt(desc, NULL, tdb, database, src); +} + void hVarSubstInVar(char *desc, struct trackDb *tdb, char *database, char **varPtr) /* hVarSubst on a dynamically allocated string, replacing string in substitutions * occur, freeing the old memory if necessary. See hVarSubst for details. */ { -char *dest = hVarSubst(desc, tdb, database, *varPtr); +char *dest = hVarSubstExt(desc, NULL, tdb, database, *varPtr); if (dest != NULL) { freez(varPtr); *varPtr = dest; } } void hVarSubstTrackDb(struct trackDb *tdb, char *database) /* Substitute variables in trackDb shortLabel, longLabel, and html fields. */ { hVarSubstInVar(tdb->track, tdb, database, &tdb->shortLabel); hVarSubstInVar(tdb->track, tdb, database, &tdb->longLabel); hVarSubstInVar(tdb->track, tdb, database, &tdb->html); } + +void hVarSubstWithCart(char *desc, struct cart *cart, struct trackDb *tdb, char *database, + char **varPtr) +/* Like hVarSubstInVar, but if cart is non-NULL, $hgsid will be substituted. */ +{ +char *dest = hVarSubstExt(desc, cart, tdb, database, *varPtr); +if (dest != NULL) + { + freez(varPtr); + *varPtr = dest; + } +}