boolean bedFilterString(char *value, enum stringFilterType sft, char **filterValues, boolean invert) /* Return TRUE if value passes the filter. */ { char *thisVal; if (filterValues == NULL) return(TRUE); switch (sft) { case (sftIgnore): return(TRUE); break; case (sftSingleLiteral): return(sameString(value, *filterValues) ^ invert); break; case (sftMultiLiteral): while ((thisVal = *(filterValues++)) != NULL) if (sameString(value, thisVal)) return(TRUE ^ invert); break; case (sftSingleRegexp): return(wildMatch(*filterValues, value) ^ invert); break; case (sftMultiRegexp): while ((thisVal = *(filterValues++)) != NULL) if (wildMatch(thisVal, value)) return(TRUE ^ invert); break; default: errAbort("illegal stringFilterType: %d", sft); break; } return(FALSE ^ invert); }
static boolean singleFilter(struct annoFilter *filter, char **row, int rowSize) /* Apply one filter, using either filterFunc or type-based filter on column value. * Return TRUE if isExclude and filter passes, or if !isExclude and filter fails. */ { boolean fail = FALSE; if (filter->filterFunc != NULL) fail = filter->filterFunc(filter, row, rowSize); else if (filter->op == afMatch) fail = !wildMatch((char *)(filter->values), row[filter->columnIx]); else if (filter->op == afNotMatch) fail = wildMatch((char *)(filter->values), row[filter->columnIx]); else { // column is a number -- integer or floating point? enum asTypes type = filter->type; if (asTypesIsFloating(type)) fail = annoFilterDouble(filter, sqlDouble(row[filter->columnIx])); else if (asTypesIsInt(type)) fail = annoFilterLongLong(filter, sqlLongLong(row[filter->columnIx])); else errAbort("annoFilterRowFails: unexpected enum asTypes %d for numeric filter op %d", type, filter->op); } if ((filter->isExclude && !fail) || (!filter->isExclude && fail)) return TRUE; return FALSE; }
void tellSubscribers(struct sqlConnection *conn, char *submitDir, char *submitFileName, unsigned id) /* Tell subscribers that match about file of given id */ { char query[256]; sqlSafef(query, sizeof(query), "select tags from edwFile where id=%u", id); char *tagsString = sqlQuickString(conn, query); struct hash *tagHash=NULL; struct cgiVar *tagList=NULL; if (!isEmpty(tagsString)) cgiParseInputAbort(tagsString, &tagHash, &tagList); char **row; struct sqlResult *sr = sqlGetResult(conn, "NOSQLINJ select * from edwSubscriber order by runOrder,id"); while ((row = sqlNextRow(sr)) != NULL) { struct edwSubscriber *subscriber = edwSubscriberLoad(row); if (wildMatch(subscriber->filePattern, submitFileName) && wildMatch(subscriber->dirPattern, submitDir)) { /* Might have to check for tags match, which involves db load and a cgi vs. cgi compare */ boolean tagsOk = TRUE; if (!isEmpty(subscriber->tagPattern)) { if (tagHash == NULL) // if we're nonempty they better be too tagsOk = FALSE; else { if (!allTagsWildMatch(subscriber->tagPattern, tagHash)) tagsOk = FALSE; } } if (tagsOk) { int maxNumSize=16; // more than enough digits base ten. int maxCommandSize = strlen(subscriber->onFileEndUpload) + maxNumSize + 1; char command[maxCommandSize]; safef(command, sizeof(command), subscriber->onFileEndUpload, id); verbose(2, "system(%s)\n", command); int err = system(command); if (err != 0) warn("err %d from system(%s)\n", err, command); } } edwSubscriberFree(&subscriber); } sqlFreeResult(&sr); freez(&tagsString); slFreeList(&tagList); hashFree(&tagHash); }
struct blastFile *blastFileOpenVerify(char *fileName) /* Open file, read and verify header. */ { struct blastFile *bf; char *line; char *words[16]; int wordCount; struct lineFile *lf; AllocVar(bf); bf->lf = lf = lineFileOpen(fileName, TRUE); bf->fileName = cloneString(fileName); /* Parse first line - something like: */ line = bfNeedNextLine(bf); wordCount = chopLine(line, words); if (wordCount < 3) bfBadHeader(bf); bf->program = cloneString(words[0]); bf->version = cloneString(words[1]); bf->buildDate = cloneString(words[2]); if (!wildMatch("*BLAST*", bf->program)) bfBadHeader(bf); if (!isdigit(bf->version[0])) bfBadHeader(bf); if (bf->buildDate[0] != '[') bfBadHeader(bf); return bf; }
struct slName *listDir(char *dir, char *pattern) /* Return an alphabetized list of all files that match * the wildcard pattern in directory. */ { struct slName *list = NULL, *name; struct dirent *de; DIR *d; if ((d = opendir(dir)) == NULL) return NULL; while ((de = readdir(d)) != NULL) { char *fileName = de->d_name; if (differentString(fileName, ".") && differentString(fileName, "..")) { if (pattern == NULL || wildMatch(pattern, fileName)) { name = newSlName(fileName); slAddHead(&list, name); } } } closedir(d); slNameSort(&list); return list; }
static void joinerValidateFields(struct joiner *joiner, struct hash *fieldHash, char *oneIdentifier) /* Make sure that joiner refers to fields that exist at * least somewhere. */ { struct joinerSet *js; struct joinerField *jf; for (js=joiner->jsList; js != NULL; js = js->next) { if (oneIdentifier == NULL || wildMatch(oneIdentifier, js->name)) { for (jf = js->fieldList; jf != NULL; jf = jf->next) { if (!fieldExists(fieldHash, js, jf)) { if (!js->expanded) { fprintf(stderr, "Error: "); printField(jf, stderr); fprintf(stderr, " not found in %s line %d of %s\n", js->name, jf->lineIx, joiner->fileName); } } } } } }
boolean allTagsWildMatch(char *tagPattern, struct hash *tagHash) /* Tag pattern is a cgi encoded list of tags with wild card values. This routine returns TRUE * if every tag in tagPattern is also in tagHash, and the value in tagHash is wildcard * compatible with tagPattern. */ { boolean match = TRUE; char *tagsString = cloneString(tagPattern); struct cgiVar *pattern, *patternList=NULL; struct hash *patternHash=NULL; cgiParseInputAbort(tagsString, &patternHash, &patternList); for (pattern = patternList; pattern != NULL; pattern = pattern->next) { struct cgiVar *cv = hashFindVal(tagHash, pattern->name); char *val = cv->val; if (val == NULL) { match = FALSE; break; } if (!wildMatch(pattern->val, val)) { match = FALSE; break; } } slFreeList(&patternList); hashFree(&patternHash); freez(&tagsString); return match; }
struct bed *bedFilterByWildNames(struct bed *bedList, struct slName *wildNames) /* Given a bed list and a list of names that may include wildcard characters, * return the list of bed items whose name matches at least one wildName. */ { struct bed *bedListOut = NULL, *bed=NULL; struct slName *wildName=NULL; for (bed=bedList; bed != NULL; bed=bed->next) { for (wildName=wildNames; wildName != NULL; wildName=wildName->next) { if (bed->name == NULL) errAbort("bedFilterByWildNames: bed item at %s:%d-%d has no name.", bed->chrom, bed->chromStart+1, bed->chromEnd); if (wildMatch(wildName->name, bed->name)) { struct bed *newBed = cloneBed(bed); slAddHead(&bedListOut, newBed); break; } } } slReverse(&bedListOut); return bedListOut; }
void catDir(int dirCount, char *dirs[]) /* catDir - concatenate files in directory - for those times when too * many files for cat to handle.. */ { int i; struct fileInfo *list, *el; for (i=0; i<dirCount; ++i) { list = listDirX(dirs[i], NULL, TRUE); for (el = list; el != NULL; el = el->next) { char *name = el->name; if (el->isDir && recurse) { catDir(1, &name); } else if (wildCard == NULL || wildMatch(wildCard, name)) { if (suffix == NULL || endsWith(name, suffix)) catFile(name); } } slFreeList(&list); } }
boolean wildMatchAll(char *word, struct slName *wildList) /* Return TRUE if word matches all things in wildList. */ { struct slName *w; for (w = wildList; w != NULL; w = w->next) if (!wildMatch(w->name, word) ) return FALSE; return TRUE; }
struct slName *getTableNames(struct sqlConnection *conn) /* Return a list of names of tables that have not been excluded by * command line options. */ { char *query = hoursOld ? "NOSQLINJ show table status" : "NOSQLINJ show tables"; struct sqlResult *sr = sqlGetResult(conn, query); struct slName *tableList = NULL; char **row = NULL; int startTime = clock1(); int ageThresh = hoursOld * 3600; while((row = sqlNextRow(sr)) != NULL) { struct slName *tableName = NULL; struct slName *pat = NULL; boolean gotMatch = FALSE; if (hoursOld) { if (row[11] != NULL) { int tableUpdateTime = sqlDateToUnixTime(row[11]); int ageInSeconds = startTime - tableUpdateTime; if (ageInSeconds > ageThresh) continue; } else { verbose(2, "Got NULL update time for table %s.%s with hoursOld=%d\n", sqlGetDatabase(conn), row[0], hoursOld); } } for (pat = excludePatterns; pat != NULL; pat=pat->next) { if (wildMatch(pat->name, row[0])) { gotMatch = TRUE; break; } } if (gotMatch) continue; if (verboseLevel() >= 3 || justList) fprintf(stderr, "Adding %s\n", row[0]); tableName = newSlName(row[0]); slAddHead(&tableList, tableName); } sqlFreeResult(&sr); if (justList) exit(0); slReverse(&tableList); return tableList; }
static boolean wildAnyRefMatch(char *wild, struct slRef *refList) /* Return true if any string-valued reference on list matches * wildcard. */ { struct slRef *ref; for (ref = refList; ref != NULL; ref = ref->next) { if (wildMatch(wild, ref->val)) return TRUE; } return FALSE; }
static boolean searchMatchToken(char *string, char *token) { // do this with regex ? Would require all sorts of careful parsing for ()., etc. if (string == NULL) return (token == NULL); if (token == NULL) return TRUE; if (!strchr(token,'*') && !strchr(token,'?')) return (strcasestr(string,token) != NULL); char wordWild[1024]; safef(wordWild,sizeof wordWild,"*%s*",token); return wildMatch(wordWild, string); }
struct fileInfo *listDirXExt(char *dir, char *pattern, boolean fullPath, boolean ignoreStatFailures) /* Return list of files matching wildcard pattern with * extra info. If full path is true then the path will be * included in the name of each file. */ { struct fileInfo *list = NULL, *el; struct dirent *de; DIR *d; int dirNameSize = strlen(dir); int fileNameOffset = dirNameSize+1; char pathName[512]; if ((d = opendir(dir)) == NULL) return NULL; memcpy(pathName, dir, dirNameSize); pathName[dirNameSize] = '/'; while ((de = readdir(d)) != NULL) { char *fileName = de->d_name; if (differentString(fileName, ".") && differentString(fileName, "..")) { if (pattern == NULL || wildMatch(pattern, fileName)) { struct stat st; bool isDir = FALSE; int statErrno = 0; strcpy(pathName+fileNameOffset, fileName); if (stat(pathName, &st) < 0) { if (ignoreStatFailures) statErrno = errno; else errAbort("stat failed in listDirX"); } if (S_ISDIR(st.st_mode)) isDir = TRUE; if (fullPath) fileName = pathName; el = newFileInfo(fileName, st.st_size, isDir, statErrno, st.st_atime); slAddHead(&list, el); } } } closedir(d); slSort(&list, cmpFileInfo); return list; }
struct hashEl *wildHashLookup(struct hash *hash, char *name) /* If wildcards are in hash, then look up var in "wildCardHash" bin. */ { struct slPair *wild = hashFindVal(hash, WILD_CARD_HASH_BIN); if (wild == NULL) // Hasn't been made yet. wild = wildHashMakeList(hash); if (wild == NULL || (slCount(wild) == 1 && sameString(wild->name,WILD_CARD_HASH_EMPTY))) return NULL; // Empty list means hash contains no names with wildcards for ( ;wild != NULL; wild=wild->next) if (wildMatch(wild->name,name)) return wild->val; return NULL; }
boolean matchName(char *seqHeader) /* see if the sequence name matches */ { /* find end of name */ char *nameSep = skipToSpaces(seqHeader); char sepChr = '\0'; boolean isMatch = FALSE; if (nameSep != NULL) { sepChr = *nameSep; /* terminate name */ *nameSep = '\0'; } isMatch = wildMatch(namePat, seqHeader); if (nameSep != NULL) *nameSep = sepChr; return isMatch; }
void eapAddStep(char *pattern) /* eapAddStep - Add a step to eapStep and related tables. This is just a small shortcut for doing * it in SQL. You can only add steps defined in C code.. */ { struct sqlConnection *conn = eapConnectReadWrite(); int i; for (i=0; i<ArraySize(steps); ++i) { struct stepInit *init = &steps[i]; if (wildMatch(pattern, init->name)) { if (clList) puts(init->name); else initStep(conn, init); } } }
void removeUserJobs(char *user, int argc, char *argv[]) /* Remove jobs associated with user. */ { struct jobInfo *jobList = getJobList(), *job; char *wildCard = NULL; if (!sameString(user, userName) && !sameString("root", userName)) errAbort("You can only remove your own jobs (unless you are root)."); if (argc > 0) wildCard = argv[0]; slReverse(&jobList); /* Improves performance to remove from tail first. */ for (job = jobList; job != NULL; job = job->next) { if (sameString(user, job->user) && (wildCard == NULL || wildMatch(wildCard, job->command))) { removeJob(job->id); } } jobInfoFreeList(&jobList); }
void joinerValidateKeys(struct joiner *joiner, char *oneIdentifier, char *oneDatabase) /* Validate all keys in joiner. If oneDatabase is non-NULL then do it on * that database. Otherwise do it on all databases. */ { struct joinerSet *js; int validations = 0; verbose(1, "Checking keys on database %s\n", oneDatabase); for (js = joiner->jsList; js != NULL; js = js->next) { verbose(2, "identifier %s\n", js->name); if (oneIdentifier == NULL || wildMatch(oneIdentifier, js->name)) { jsValidateKeys(joiner, js, oneDatabase); ++validations; } } if (validations < 1 && oneIdentifier) errAbort("Identifier %s not found in %s", oneIdentifier, joiner->fileName); }
/* Go through the given tags and determine the union of flags. Also remove * any tags from the list that we don't know about */ unsigned int tagtransform::c_filter_basic_tags(OsmType type, const taglist_t &tags, int *polygon, int *roads, const export_list &exlist, taglist_t &out_tags, bool strict) { //assume we dont like this set of tags int filter = 1; int flags = 0; int add_area_tag = 0; OsmType export_type; if (type == OSMTYPE_RELATION) { export_type = OSMTYPE_WAY; } else { export_type = type; } const std::vector<taginfo> &infos = exlist.get(export_type); /* We used to only go far enough to determine if it's a polygon or not, but now we go through and filter stuff we don't need pop each tag off and keep it in the temp list if we like it */ for (taglist_t::const_iterator item = tags.begin(); item != tags.end(); ++item) { //if we want to do more than the export list says if(!strict) { if (type == OSMTYPE_RELATION && "type" == item->key) { out_tags.push_back(*item); filter = 0; continue; } /* Allow named islands to appear as polygons */ if ("natural" == item->key && "coastline" == item->value) { add_area_tag = 1; /* Discard natural=coastline tags (we render these from a shapefile instead) */ if (!options->keep_coastlines) { continue; } } } //go through the actual tags found on the item and keep the ones in the export list size_t i = 0; for (; i < infos.size(); i++) { const taginfo &info = infos[i]; if (wildMatch(info.name.c_str(), item->key.c_str())) { if (info.flags & FLAG_DELETE) { break; } filter = 0; flags |= info.flags; out_tags.push_back(*item); break; } } // if we didn't find any tags that we wanted to export // and we aren't strictly adhering to the list if (i == infos.size() && !strict) { if (options->hstore_mode != HSTORE_NONE) { /* with hstore, copy all tags... */ out_tags.push_back(*item); /* ... but if hstore_match_only is set then don't take this as a reason for keeping the object */ if (!options->hstore_match_only && "osm_uid" != item->key && "osm_user" != item->key && "osm_timestamp" != item->key && "osm_version" != item->key && "osm_changeset" != item->key) filter = 0; } else if (options->hstore_columns.size() > 0) { /* does this column match any of the hstore column prefixes? */ size_t j = 0; for(; j < options->hstore_columns.size(); ++j) { size_t pos = item->key.find(options->hstore_columns[j]); if (pos == 0) { out_tags.push_back(*item); /* ... but if hstore_match_only is set then don't take this as a reason for keeping the object */ if (!options->hstore_match_only && "osm_uid" != item->key && "osm_user" != item->key && "osm_timestamp" != item->key && "osm_version" != item->key && "osm_changeset" != item->key) filter = 0; break; } } } } } if (polygon) { if (add_area_tag) { /* If we need to force this as a polygon, append an area tag */ out_tags.push_dedupe(tag("area", "yes")); *polygon = 1; } else { *polygon = tags.get_bool("area", flags & FLAG_POLYGON); } } if (roads && !filter && (type == OSMTYPE_WAY)) { add_z_order(out_tags, roads); } return filter; }
static boolean rkeyEval(struct kvt *kvt, struct exp *exp) /* Recursively evaluate expression. */ { if (exp == NULL) return TRUE; switch (exp->type) { case kxMatch: { char *key = exp->left; char *matcher = exp->right; char *val = kvtLookup(kvt, key); if (val == NULL) return sameWord(matcher, "null"); else return sameWord(matcher, val); } case kxWildMatch: { char *key = exp->left; char *matcher = exp->right; char *val = kvtLookup(kvt, key); if (val == NULL) return sameString(matcher, "*"); else return wildMatch(matcher, val); } case kxGT: { int left, right; getIntVals(kvt, exp, &left, &right); return left > right; } case kxGE: { int left, right; getIntVals(kvt, exp, &left, &right); return left >= right; } case kxLT: { int left, right; getIntVals(kvt, exp, &left, &right); return left < right; } case kxLE: { int left, right; getIntVals(kvt, exp, &left, &right); return left <= right; } case kxNot: { return !rkeyEval(kvt, exp->right); } case kxAnd: { return rkeyEval(kvt, exp->left) && rkeyEval(kvt, exp->right); } case kxOr: { return rkeyEval(kvt, exp->left) || rkeyEval(kvt, exp->right); } case kxXor: { return rkeyEval(kvt, exp->left) ^ rkeyEval(kvt, exp->right); } default: { errAbort("unknown expression type %d", exp->type); return 0; } } }
/* Go through the given tags and determine the union of flags. Also remove * any tags from the list that we don't know about */ static unsigned int tagtransform_c_filter_basic_tags(enum OsmType type, struct keyval *tags, int *polygon, int * roads) { int i, filter = 1; int flags = 0; int add_area_tag = 0; enum OsmType export_type; const char *area; struct keyval *item; struct keyval temp; initList(&temp); if (type == OSMTYPE_RELATION) {export_type = OSMTYPE_WAY;} else {export_type = type;} /* We used to only go far enough to determine if it's a polygon or not, but now we go through and filter stuff we don't need */ while ((item = popItem(tags)) != NULL ) { if (type == OSMTYPE_RELATION && !strcmp("type", item->key)) { pushItem(&temp, item); item = NULL; filter = 0; continue; } /* Allow named islands to appear as polygons */ if (!strcmp("natural", item->key) && !strcmp("coastline", item->value)) { add_area_tag = 1; } /* Discard natural=coastline tags (we render these from a shapefile instead) */ if (!options->keep_coastlines && !strcmp("natural", item->key) && !strcmp("coastline", item->value)) { freeItem(item); item = NULL; continue; } for (i = 0; i < exportListCount[export_type]; i++) { if (wildMatch(exportList[export_type][i].name, item->key)) { if (exportList[export_type][i].flags & FLAG_DELETE) { freeItem(item); item = NULL; break; } filter = 0; flags |= exportList[export_type][i].flags; pushItem(&temp, item); item = NULL; break; } } /** if tag not found in list of exports: */ if (i == exportListCount[export_type]) { if (options->enable_hstore) { /* with hstore, copy all tags... */ pushItem(&temp, item); /* ... but if hstore_match_only is set then don't take this as a reason for keeping the object */ if (!options->hstore_match_only && strcmp("osm_uid", item->key) && strcmp("osm_user", item->key) && strcmp("osm_timestamp", item->key) && strcmp("osm_version", item->key) && strcmp("osm_changeset", item->key)) filter = 0; } else if (options->n_hstore_columns) { /* does this column match any of the hstore column prefixes? */ int j; for (j = 0; j < options->n_hstore_columns; j++) { char *pos = strstr(item->key, options->hstore_columns[j]); if (pos == item->key) { pushItem(&temp, item); /* ... but if hstore_match_only is set then don't take this as a reason for keeping the object */ if (!options->hstore_match_only && strcmp("osm_uid", item->key) && strcmp("osm_user", item->key) && strcmp("osm_timestamp", item->key) && strcmp("osm_version", item->key) && strcmp("osm_changeset", item->key)) filter = 0; break; } } /* if not, skip the tag */ if (j == options->n_hstore_columns) { freeItem(item); } } else { freeItem(item); } item = NULL; } } /* Move from temp list back to original list */ while ((item = popItem(&temp)) != NULL ) pushItem(tags, item); *polygon = flags & FLAG_POLYGON; /* Special case allowing area= to override anything else */ if ((area = getItem(tags, "area"))) { if (!strcmp(area, "yes") || !strcmp(area, "true") || !strcmp(area, "1")) *polygon = 1; else if (!strcmp(area, "no") || !strcmp(area, "false") || !strcmp(area, "0")) *polygon = 0; } else { /* If we need to force this as a polygon, append an area tag */ if (add_area_tag) { addItem(tags, "area", "yes", 0); *polygon = 1; } } if (!filter && (type == OSMTYPE_WAY)) { add_z_order(tags,roads); } return filter; }
static void filterBed(struct track *tg, struct linkedFeatures **pLfList) /* Apply filters if any to mRNA linked features. */ { struct linkedFeatures *lf, *next, *newList = NULL, *oldList = NULL; struct mrnaUiData *mud = tg->extraUiData; struct mrnaFilter *fil; char *type; boolean anyFilter = FALSE; boolean colorIx = 0; boolean isExclude = FALSE; boolean andLogic = TRUE; if (*pLfList == NULL || mud == NULL) return; /* First make a quick pass through to see if we actually have * to do the filter. */ for (fil = mud->filterList; fil != NULL; fil = fil->next) { fil->pattern = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, fil->suffix, ""); if (fil->pattern[0] != 0) anyFilter = TRUE; } if (!anyFilter) return; type = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, mud->filterTypeSuffix, "red"); if (sameString(type, "exclude")) isExclude = TRUE; else if (sameString(type, "include")) isExclude = FALSE; else colorIx = getFilterColor(type, MG_BLACK); type = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, mud->logicTypeSuffix, "and"); andLogic = sameString(type, "and"); /* Make a pass though each filter, and start setting up search for * those that have some text. */ for (fil = mud->filterList; fil != NULL; fil = fil->next) { if (fil->pattern[0] != 0) // Already retrieved above. fil->hash = newHash(10); } /* Scan tables id/name tables to build up hash of matching id's. */ for (fil = mud->filterList; fil != NULL; fil = fil->next) { struct hash *hash = fil->hash; int wordIx, wordCount; char *words[128]; if (hash != NULL) { boolean anyWild; char *dupPat = cloneString(fil->pattern); wordCount = chopLine(dupPat, words); for (wordIx=0; wordIx <wordCount; ++wordIx) { char *pattern = cloneString(words[wordIx]); if (lastChar(pattern) != '*') { int len = strlen(pattern)+1; pattern = needMoreMem(pattern, len, len+1); pattern[len-1] = '*'; } anyWild = (strchr(pattern, '*') != NULL || strchr(pattern, '?') != NULL); touppers(pattern); for(lf = *pLfList; lf != NULL; lf=lf->next) { char copy[SMALLBUF]; boolean gotMatch; safef(copy, sizeof(copy), "%s", lf->name); touppers(copy); if (anyWild) gotMatch = wildMatch(pattern, copy); else gotMatch = sameString(pattern, copy); if (gotMatch) { hashAdd(hash, lf->name, NULL); } } freez(&pattern); } freez(&dupPat); } } /* Scan through linked features coloring and or including/excluding ones that * match filter. */ for (lf = *pLfList; lf != NULL; lf = next) { boolean passed = andLogic; next = lf->next; for (fil = mud->filterList; fil != NULL; fil = fil->next) { if (fil->hash != NULL) { if (hashLookup(fil->hash, lf->name) == NULL) { if (andLogic) passed = FALSE; } else { if (!andLogic) passed = TRUE; } } } if (passed ^ isExclude) { slAddHead(&newList, lf); if (colorIx > 0) lf->filterColor = colorIx; } else { slAddHead(&oldList, lf); } } slReverse(&newList); slReverse(&oldList); if (colorIx > 0) { /* Draw stuff that passes filter first in full mode, last in dense. */ if (tg->visibility == tvDense) { newList = slCat(oldList, newList); } else { newList = slCat(newList, oldList); } } *pLfList = newList; tg->limitedVisSet = FALSE; /* Need to recalculate this after filtering. */ /* Free up hashes, etc. */ for (fil = mud->filterList; fil != NULL; fil = fil->next) { hashFree(&fil->hash); } }
static void rCheck(struct tagStanza *stanzaList, char *fileName, struct slRef *wildList, struct hash *hash, struct slRef *requiredList, struct dyString *scratch) /* Recurse through tagStorm */ { struct tagStanza *stanza; struct dyString *csvScratch = dyStringNew(0); for (stanza = stanzaList; stanza != NULL; stanza = stanza->next) { struct slPair *pair; for (pair = stanza->tagList; pair != NULL; pair = pair->next) { /* Break out tag and value */ char *tag = tagSchemaFigureArrayName(pair->name, scratch); char *val = pair->val; /* Make sure val exists and is non-empty */ if (isEmpty(val)) { reportError(fileName, stanza->startLineIx, "%s tag has no value", tag); continue; } /* Check against SQL reserved words */ if (gReservedHash != NULL) { if (sqlReservedCheck(gReservedHash, tag)) { reportError(fileName, stanza->startLineIx, "%s in tag name is a SQL reserved word", tag); continue; } } /* Find schema in hash or wildSchemaList */ struct tagSchema *schema = hashFindVal(hash, tag); if (schema == NULL) { struct slRef *ref; for (ref = wildList; ref != NULL; ref = ref->next) { struct tagSchema *s = ref->val; if (wildMatch(s->name, tag)) { schema = s; break; } } } /* Do checking on tag */ if (schema == NULL) reportError(fileName, stanza->startLineIx, "Unrecognized tag %s", tag); else { char type = schema->type; char *pos = val; char *oneVal; while ((oneVal =csvParseNext(&pos, csvScratch)) != NULL) { if (type == '#') { char *end; long long v = strtoll(oneVal, &end, 10); if (end == oneVal || *end != 0) // oneVal is not integer reportError(fileName, stanza->startLineIx, "Non-integer value %s for %s", oneVal, tag); else if (v < schema->minVal) reportError(fileName, stanza->startLineIx, "Value %s too low for %s", oneVal, tag); else if (v > schema->maxVal) reportError(fileName, stanza->startLineIx, "Value %s too high for %s", oneVal, tag); } else if (type == '%') { char *end; double v = strtod(oneVal, &end); if (end == oneVal || *end != 0) // val is not just a floating point number reportError(fileName, stanza->startLineIx, "Non-numerical value %s for %s", oneVal, tag); else if (v < schema->minVal) reportError(fileName, stanza->startLineIx, "Value %s too low for %s", oneVal, tag); else if (v > schema->maxVal) reportError(fileName, stanza->startLineIx, "Value %s too high for %s", oneVal, tag); } else { boolean gotMatch = FALSE; struct slName *okVal; for (okVal = schema->allowedVals; okVal != NULL; okVal = okVal->next) { if (wildMatch(okVal->name, oneVal)) { gotMatch = TRUE; break; } } if (!gotMatch) reportError(fileName, stanza->startLineIx, "Unrecognized value '%s' for tag %s", oneVal, tag); } struct hash *uniqHash = schema->uniqHash; if (uniqHash != NULL) { if (hashLookup(uniqHash, oneVal)) reportError(fileName, stanza->startLineIx, "Non-unique value '%s' for tag %s", oneVal, tag); else hashAdd(uniqHash, oneVal, NULL); } } } } if (stanza->children) { rCheck(stanza->children, fileName, wildList, hash, requiredList, scratch); } else { struct slRef *ref; for (ref = requiredList; ref != NULL; ref = ref->next) { struct tagSchema *schema = ref->val; if (schema->objArrayPieces != NULL) // It's an array, complex to handle, needs own routine { checkInAllArrayItems(fileName, stanza, schema, scratch); } else { if (tagFindVal(stanza, schema->name) == NULL) reportError(fileName, stanza->startLineIx, "Missing required '%s' tag", schema->name); } } } } dyStringFree(&csvScratch); }