fdf32b5ca1079c6ba32eb160f7396aef563b97b4 angie Tue Mar 10 11:00:54 2015 -0700 Fixing item name buffer overflow: fixes #14966 diff --git src/hg/lib/hgSeq.c src/hg/lib/hgSeq.c index 65c54a9..f6bae45 100644 --- src/hg/lib/hgSeq.c +++ src/hg/lib/hgSeq.c @@ -1,811 +1,811 @@ /* hgSeq - Fetch and format DNA sequence data (to stdout) for gene records. */ /* Copyright (C) 2014 The Regents of the University of California * See README in this or parent directory for licensing information. */ #include "common.h" #include "dnautil.h" #include "dnaseq.h" #include "cart.h" #include "cheapcgi.h" #include "hdb.h" #include "web.h" #include "rmskOut.h" #include "fa.h" #include "genePred.h" #include "bed.h" #include "hgSeq.h" #include "trackHub.h" int hgSeqChromSize(char *db, char *chromName) /* get chrom size if there's a database out there, * otherwise just return 0 */ { int thisSize = 0; if (hDbExists(db)) thisSize = hChromSize(db, chromName); return thisSize; } static void hgSeqFeatureRegionOptions(struct cart *cart, boolean canDoUTR, boolean canDoIntrons) /* Print out HTML FORM entries for feature region options. */ { char *exonStr = canDoIntrons ? " Exons" : ""; char *setting; puts("\n

Sequence Retrieval Region Options:

\n"); if (canDoIntrons || canDoUTR) { cgiMakeCheckBox("hgSeq.promoter", cartCgiUsualBoolean(cart, "hgSeq.promoter", FALSE)); puts("Promoter/Upstream by "); setting = cartCgiUsualString(cart, "hgSeq.promoterSize", "1000"); cgiMakeTextVar("hgSeq.promoterSize", setting, 5); puts("bases
"); } if (canDoUTR) { cgiMakeCheckBox("hgSeq.utrExon5", cartCgiUsualBoolean(cart, "hgSeq.utrExon5", TRUE)); printf("5' UTR%s
\n", exonStr); } if (canDoIntrons) { cgiMakeCheckBox("hgSeq.cdsExon", cartCgiUsualBoolean(cart, "hgSeq.cdsExon", TRUE)); if (canDoUTR) printf("CDS Exons
\n"); else printf("Blocks
\n"); } else if (canDoUTR) { cgiMakeCheckBox("hgSeq.cdsExon", cartCgiUsualBoolean(cart, "hgSeq.cdsExon", TRUE)); printf("CDS
\n"); } else { cgiMakeHiddenVar("hgSeq.cdsExon", "1"); } if (canDoUTR) { cgiMakeCheckBox("hgSeq.utrExon3", cartCgiUsualBoolean(cart, "hgSeq.utrExon3", TRUE)); printf("3' UTR%s
\n", exonStr); } if (canDoIntrons) { cgiMakeCheckBox("hgSeq.intron", cartCgiUsualBoolean(cart, "hgSeq.intron", TRUE)); if (canDoUTR) puts("Introns
"); else puts("Regions between blocks
"); } if (canDoIntrons || canDoUTR) { cgiMakeCheckBox("hgSeq.downstream", cartCgiUsualBoolean(cart, "hgSeq.downstream", FALSE)); puts("Downstream by "); setting = cartCgiUsualString(cart, "hgSeq.downstreamSize", "1000"); cgiMakeTextVar("hgSeq.downstreamSize", setting, 5); puts("bases
"); } if (canDoIntrons || canDoUTR) { setting = cartCgiUsualString(cart, "hgSeq.granularity", "gene"); cgiMakeRadioButton("hgSeq.granularity", "gene", sameString(setting, "gene")); if (canDoUTR) puts("One FASTA record per gene.
"); else puts("One FASTA record per item.
"); cgiMakeRadioButton("hgSeq.granularity", "feature", sameString(setting, "feature")); if (canDoUTR) puts("One FASTA record per region (exon, intron, etc.) with "); else puts("One FASTA record per region (block/between blocks) with "); } else { puts("Add "); } setting = cartCgiUsualString(cart, "hgSeq.padding5", "0"); cgiMakeTextVar("hgSeq.padding5", setting, 5); puts("extra bases upstream (5') and "); setting = cartCgiUsualString(cart, "hgSeq.padding3", "0"); cgiMakeTextVar("hgSeq.padding3", setting, 5); puts("extra downstream (3')
"); if (canDoIntrons && canDoUTR) { puts("   "); cgiMakeCheckBox("hgSeq.splitCDSUTR", cartCgiUsualBoolean(cart, "hgSeq.splitCDSUTR", FALSE)); puts("Split UTR and CDS parts of an exon into separate FASTA records"); } puts("
\n"); puts("Note: if a feature is close to the beginning or end of a chromosome \n" "and upstream/downstream bases are added, they may be truncated \n" "in order to avoid extending past the edge of the chromosome.

"); } static void hgSeqDisplayOptions(struct cart *cart, boolean canDoUTR, boolean canDoIntrons, boolean offerRevComp) /* Print out HTML FORM entries for sequence display options. */ { char *casing, *repMasking; puts("\n

Sequence Formatting Options:

\n"); casing = cartCgiUsualString(cart, "hgSeq.casing", "exon"); if (canDoIntrons) { cgiMakeRadioButton("hgSeq.casing", "exon", sameString(casing, "exon")); if (canDoUTR) puts("Exons in upper case, everything else in lower case.
"); else puts("Blocks in upper case, everything else in lower case.
"); } if (canDoUTR) { if (sameString(casing, "exon") && !canDoIntrons) casing = "cds"; cgiMakeRadioButton("hgSeq.casing", "cds", sameString(casing, "cds")); puts("CDS in upper case, UTR in lower case.
"); } if ((sameString(casing, "exon") && !canDoIntrons) || (sameString(casing, "cds") && !canDoUTR)) casing = "upper"; cgiMakeRadioButton("hgSeq.casing", "upper", sameString(casing, "upper")); puts("All upper case.
"); cgiMakeRadioButton("hgSeq.casing", "lower", sameString(casing, "lower")); puts("All lower case.
"); cgiMakeCheckBox("hgSeq.maskRepeats", cartCgiUsualBoolean(cart, "hgSeq.maskRepeats", FALSE)); puts("Mask repeats: "); repMasking = cartCgiUsualString(cart, "hgSeq.repMasking", "lower"); cgiMakeRadioButton("hgSeq.repMasking", "lower", sameString(repMasking, "lower")); puts(" to lower case "); cgiMakeRadioButton("hgSeq.repMasking", "N", sameString(repMasking, "N")); puts(" to N
"); if (offerRevComp) { cgiMakeCheckBox("hgSeq.revComp", cartCgiUsualBoolean(cart, "hgSeq.revComp", FALSE)); puts("Reverse complement (get \'-\' strand sequence)"); } } void hgSeqOptionsHtiCart(struct hTableInfo *hti, struct cart *cart) /* Print out HTML FORM entries for gene region and sequence display options. * Use defaults from CGI and cart. */ { boolean canDoUTR, canDoIntrons, offerRevComp; if (hti == NULL) { canDoUTR = canDoIntrons = FALSE; offerRevComp = TRUE; } else { canDoUTR = hti->hasCDS; canDoIntrons = hti->hasBlocks; offerRevComp = (hti->strandField[0] == 0); } hgSeqFeatureRegionOptions(cart, canDoUTR, canDoIntrons); hgSeqDisplayOptions(cart, canDoUTR, canDoIntrons, offerRevComp); } #ifdef NEVER void hgSeqOptionsHti(struct hTableInfo *hti) /* Print out HTML FORM entries for gene region and sequence display options. * Use defaults from CGI. */ { hgSeqOptionsHtiCart(hti, NULL); } #endif /* NEVER */ void hgSeqOptions(struct cart *cart, char *db, char *table) /* Print out HTML FORM entries for gene region and sequence display options. */ { struct hTableInfo *hti; char chrom[32]; char rootName[256]; if (isCustomTrack(table) || startsWith("hub_", table)) { // we asssume that this is a bigGenePred table if we got here with it hgSeqFeatureRegionOptions(cart, TRUE, TRUE); hgSeqDisplayOptions(cart, TRUE, TRUE, FALSE); return; } else if ((table == NULL) || (table[0] == 0)) { hti = NULL; } else { hParseTableName(db, table, rootName, chrom); hti = hFindTableInfo(db, chrom, rootName); if (hti == NULL) webAbort("Error", "Could not find table info for table %s (%s)", rootName, table); } hgSeqOptionsHtiCart(hti, cart); } static void hgSeqConcatRegionsDb(char *db, char *chrom, int chromSize, char strand, char *name, int rCount, unsigned *rStarts, unsigned *rSizes, boolean *exonFlags, boolean *cdsFlags) /* Concatenate and print out dna for a series of regions. */ { // Note: this code use to generate different sequence ids if the global // database in hdb was different than the db parameter. This functionality // has been removed since the global database was removed and it didn't // appear to be used. struct dnaSeq *rSeq = NULL; struct dnaSeq *cSeq = NULL; char recName[256]; int seqStart, seqEnd; int offset, cSize; int i; boolean isRc = (strand == '-') || cgiBoolean("hgSeq.revComp"); boolean maskRep = cgiBoolean("hgSeq.maskRepeats"); int padding5 = cgiOptionalInt("hgSeq.padding5", 0); int padding3 = cgiOptionalInt("hgSeq.padding3", 0); char *casing = cgiString("hgSeq.casing"); char *repMasking = cgiString("hgSeq.repMasking"); char *granularity = cgiOptionalString("hgSeq.granularity"); boolean concatRegions = granularity && sameString("gene", granularity); if (rCount < 1) return; /* Don't support padding if granularity is gene (i.e. concat'ing all). */ if (concatRegions) { padding5 = padding3 = 0; } i = rCount - 1; seqStart = rStarts[0] - (isRc ? padding3 : padding5); seqEnd = rStarts[i] + rSizes[i] + (isRc ? padding5 : padding3); /* Padding might push us off the edge of the chrom; if so, truncate: */ if (seqStart < 0) { if (isRc) padding3 += seqStart; else padding5 += seqStart; seqStart = 0; } /* if we know the chromSize, don't pad out beyond it */ if ((chromSize > 0) && (seqEnd > chromSize)) { if (isRc) padding5 += (chromSize - seqEnd); else padding3 += (chromSize - seqEnd); seqEnd = chromSize; } if (seqEnd <= seqStart) { printf("# Null range for %s_%s (range=%s:%d-%d 5'pad=%d 3'pad=%d) (may indicate a query-side insert)\n", db, name, chrom, seqStart+1, seqEnd, padding5, padding3); return; } if (maskRep) { rSeq = hDnaFromSeq(db, chrom, seqStart, seqEnd, dnaMixed); if (sameString(repMasking, "N")) lowerToN(rSeq->dna, strlen(rSeq->dna)); if (!sameString(casing, "upper")) tolowers(rSeq->dna); } else if (sameString(casing, "upper")) rSeq = hDnaFromSeq(db, chrom, seqStart, seqEnd, dnaUpper); else rSeq = hDnaFromSeq(db, chrom, seqStart, seqEnd, dnaLower); /* Handle casing and compute size of concatenated sequence */ cSize = 0; for (i=0; i < rCount; i++) { if ((sameString(casing, "exon") && exonFlags[i]) || (sameString(casing, "cds") && cdsFlags[i])) { int rStart = rStarts[i] - seqStart; toUpperN(rSeq->dna+rStart, rSizes[i]); } cSize += rSizes[i]; } cSize += (padding5 + padding3); AllocVar(cSeq); cSeq->dna = needLargeMem(cSize+1); cSeq->size = cSize; offset = 0; for (i=0; i < rCount; i++) { int start = rStarts[i] - seqStart; int size = rSizes[i]; if (i == 0) { start -= (isRc ? padding3 : padding5); assert(start == 0); size += (isRc ? padding3 : padding5); } if (i == rCount-1) { size += (isRc ? padding5 : padding3); } memcpy(cSeq->dna+offset, rSeq->dna+start, size); offset += size; } assert(offset == cSeq->size); cSeq->dna[offset] = 0; freeDnaSeq(&rSeq); if (isRc) reverseComplement(cSeq->dna, cSeq->size); safef(recName, sizeof(recName), "%s_%s range=%s:%d-%d 5'pad=%d 3'pad=%d " "strand=%c repeatMasking=%s", db, name, chrom, seqStart+1, seqEnd, padding5, padding3, (isRc ? '-' : '+'), (maskRep ? repMasking : "none")); faWriteNext(stdout, recName, cSeq->dna, cSeq->size); freeDnaSeq(&cSeq); } static void hgSeqRegionsAdjDb(char *db, char *chrom, int chromSize, char strand, char *name, boolean concatRegions, boolean concatAdjacent, int rCount, unsigned *rStarts, unsigned *rSizes, boolean *exonFlags, boolean *cdsFlags) /* Concatenate and print out dna for a series of regions, * optionally concatenating adjacent exons. */ { if (concatRegions || (rCount == 1)) { hgSeqConcatRegionsDb(db, chrom, chromSize, strand, name, rCount, rStarts, rSizes, exonFlags, cdsFlags); } else { int i, count; boolean isRc = (strand == '-'); char rName[256]; for (i=0,count=0; i < rCount; i++,count++) { int j, jEnd, len, lo, hi; safef(rName, sizeof(rName), "%s_%d", name, count); j = (isRc ? (rCount - i - 1) : i); jEnd = (isRc ? (j - 1) : (j + 1)); if (concatAdjacent && exonFlags[j]) { lo = (isRc ? jEnd : (jEnd - 1)); hi = (isRc ? (jEnd + 1) : jEnd); while ((i < rCount) && ((rStarts[lo] + rSizes[lo]) == rStarts[hi]) && exonFlags[jEnd]) { i++; jEnd = (isRc ? (jEnd - 1) : (jEnd + 1)); lo = (isRc ? jEnd : (jEnd - 1)); hi = (isRc ? (jEnd + 1) : jEnd); } } len = (isRc ? (j - jEnd) : (jEnd - j)); lo = (isRc ? (jEnd + 1) : j); hgSeqConcatRegionsDb(db, chrom, chromSize, strand, rName, len, &rStarts[lo], &rSizes[lo], &exonFlags[lo], &cdsFlags[lo]); } } } static void hgSeqRegionsDb(char *db, char *chrom, int chromSize, char strand, char *name, boolean concatRegions, int rCount, unsigned *rStarts, unsigned *rSizes, boolean *exonFlags, boolean *cdsFlags) /* Concatenate and print out dna for a series of regions. */ { hgSeqRegionsAdjDb(db, chrom, chromSize, strand, name, concatRegions, FALSE, rCount, rStarts, rSizes, exonFlags, cdsFlags); } static int maxStartsOffset = 0; static void addFeature(int *count, unsigned *starts, unsigned *sizes, boolean *exonFlags, boolean *cdsFlags, int start, int size, boolean eFlag, boolean cFlag, int chromSize) { if (start < 0) { size += start; start = 0; } /* if we know the chromSize, don't try to get more than's there */ if ((chromSize > 0) && (start + size > chromSize)) size = chromSize - start; if (*count > maxStartsOffset) errAbort("addFeature: overflow (%d > %d)", *count, maxStartsOffset); starts[*count] = start; sizes[*count] = size; exonFlags[*count] = eFlag; cdsFlags[*count] = cFlag; (*count)++; } void hgSeqRange(char *db, char *chrom, int chromStart, int chromEnd, char strand, char *name) /* Print out dna sequence for the given range. */ { int count = 0; unsigned starts[1]; unsigned sizes[1]; boolean exonFlags[1]; boolean cdsFlags[1]; int chromSize = hgSeqChromSize(db, chrom); maxStartsOffset = 0; addFeature(&count, starts, sizes, exonFlags, cdsFlags, chromStart, chromEnd - chromStart, FALSE, FALSE, chromSize); hgSeqRegionsDb(db, chrom, chromSize, strand, name, FALSE, count, starts, sizes, exonFlags, cdsFlags); } int hgSeqBed(char *db, struct hTableInfo *hti, struct bed *bedList) /* Print out dna sequence from the given database of all items in bedList. * hti describes the bed-compatibility level of bedList items. * Returns number of FASTA records printed out. */ { struct bed *bedItem; -char itemName[128]; +char itemName[512]; boolean isRc; int count; unsigned *starts = NULL; unsigned *sizes = NULL; boolean *exonFlags = NULL; boolean *cdsFlags = NULL; int i, rowCount, totalCount; boolean promoter = cgiBoolean("hgSeq.promoter"); boolean intron = cgiBoolean("hgSeq.intron"); boolean utrExon5 = cgiBoolean("hgSeq.utrExon5"); boolean utrIntron5 = utrExon5 && intron; boolean cdsExon = cgiBoolean("hgSeq.cdsExon"); boolean cdsIntron = cdsExon && intron; boolean utrExon3 = cgiBoolean("hgSeq.utrExon3"); boolean utrIntron3 = utrExon3 && intron; boolean downstream = cgiBoolean("hgSeq.downstream"); int promoterSize = cgiOptionalInt("hgSeq.promoterSize", 0); int downstreamSize = cgiOptionalInt("hgSeq.downstreamSize", 0); char *granularity = cgiOptionalString("hgSeq.granularity"); boolean concatRegions = granularity && sameString("gene", granularity); boolean concatAdjacent = (cgiBooleanDefined("hgSeq.splitCDSUTR") && (! cgiBoolean("hgSeq.splitCDSUTR"))); boolean isCDS, doIntron; boolean canDoUTR, canDoIntrons; /* catch a special case: introns selected, but no exons -> include all introns * instead of qualifying intron with exon flags. */ if (intron && !(utrExon5 || cdsExon || utrExon3)) { utrIntron5 = cdsIntron = utrIntron3 = TRUE; } canDoUTR = hti->hasCDS; canDoIntrons = hti->hasBlocks; rowCount = totalCount = 0; for (bedItem = bedList; bedItem != NULL; bedItem = bedItem->next) { if (bedItem->blockCount == 0) /* An intersection may have made hti unreliable. */ canDoIntrons = FALSE; int chromSize = hgSeqChromSize(db, bedItem->chrom); // bed: translate relative starts to absolute starts for (i=0; i < bedItem->blockCount; i++) { bedItem->chromStarts[i] += bedItem->chromStart; } isRc = (bedItem->strand[0] == '-'); // here's the max # of feature regions: if (canDoIntrons) count = 4 + (2 * bedItem->blockCount); else count = 5; maxStartsOffset = count-1; starts = needMem(sizeof(unsigned) * count); sizes = needMem(sizeof(unsigned) * count); exonFlags = needMem(sizeof(boolean) * count); cdsFlags = needMem(sizeof(boolean) * count); // build up a list of selected regions count = 0; if (!isRc && promoter && (promoterSize > 0)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, (bedItem->chromStart - promoterSize), promoterSize, FALSE, FALSE, chromSize); } else if (isRc && downstream && (downstreamSize > 0)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, (bedItem->chromStart - downstreamSize), downstreamSize, FALSE, FALSE, chromSize); } if (canDoIntrons && canDoUTR) { for (i=0; i < bedItem->blockCount; i++) { if ((bedItem->chromStarts[i] + bedItem->blockSizes[i]) <= bedItem->thickStart) { if ((!isRc && utrExon5) || (isRc && utrExon3)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->chromStarts[i], bedItem->blockSizes[i], TRUE, FALSE, chromSize); } if (((!isRc && utrIntron5) || (isRc && utrIntron3)) && (i < bedItem->blockCount - 1)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, (bedItem->chromStarts[i] + bedItem->blockSizes[i]), (bedItem->chromStarts[i+1] - bedItem->chromStarts[i] - bedItem->blockSizes[i]), FALSE, FALSE, chromSize); } } else if (bedItem->chromStarts[i] < bedItem->thickEnd) { if ((bedItem->chromStarts[i] < bedItem->thickStart) && ((bedItem->chromStarts[i] + bedItem->blockSizes[i]) > bedItem->thickEnd)) { if ((!isRc && utrExon5) || (isRc && utrExon3)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->chromStarts[i], (bedItem->thickStart - bedItem->chromStarts[i]), TRUE, FALSE, chromSize); } if (cdsExon) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->thickStart, (bedItem->thickEnd - bedItem->thickStart), TRUE, TRUE, chromSize); } if ((!isRc && utrExon3) || (isRc && utrExon5)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->thickEnd, (bedItem->chromStarts[i] + bedItem->blockSizes[i] - bedItem->thickEnd), TRUE, FALSE, chromSize); } } else if (bedItem->chromStarts[i] < bedItem->thickStart) { if ((!isRc && utrExon5) || (isRc && utrExon3)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->chromStarts[i], (bedItem->thickStart - bedItem->chromStarts[i]), TRUE, FALSE, chromSize); } if (cdsExon) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->thickStart, (bedItem->chromStarts[i] + bedItem->blockSizes[i] - bedItem->thickStart), TRUE, TRUE, chromSize); } } else if ((bedItem->chromStarts[i] + bedItem->blockSizes[i]) > bedItem->thickEnd) { if (cdsExon) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->chromStarts[i], (bedItem->thickEnd - bedItem->chromStarts[i]), TRUE, TRUE, chromSize); } if ((!isRc && utrExon3) || (isRc && utrExon5)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->thickEnd, (bedItem->chromStarts[i] + bedItem->blockSizes[i] - bedItem->thickEnd), TRUE, FALSE, chromSize); } } else if (cdsExon) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->chromStarts[i], bedItem->blockSizes[i], TRUE, TRUE, chromSize); } isCDS = ! ((bedItem->chromStarts[i] + bedItem->blockSizes[i]) > bedItem->thickEnd); doIntron = (isCDS ? cdsIntron : ((!isRc) ? utrIntron3 : utrIntron5)); if (doIntron && (i < bedItem->blockCount - 1)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, (bedItem->chromStarts[i] + bedItem->blockSizes[i]), (bedItem->chromStarts[i+1] - bedItem->chromStarts[i] - bedItem->blockSizes[i]), FALSE, isCDS, chromSize); } } else { if ((!isRc && utrExon3) || (isRc && utrExon5)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->chromStarts[i], bedItem->blockSizes[i], TRUE, FALSE, chromSize); } if (((!isRc && utrIntron3) || (isRc && utrIntron5)) && (i < bedItem->blockCount - 1)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, (bedItem->chromStarts[i] + bedItem->blockSizes[i]), (bedItem->chromStarts[i+1] - bedItem->chromStarts[i] - bedItem->blockSizes[i]), FALSE, FALSE, chromSize); } } } } else if (canDoIntrons) { for (i=0; i < bedItem->blockCount; i++) { if (cdsExon) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->chromStarts[i], bedItem->blockSizes[i], TRUE, FALSE, chromSize); } if (cdsIntron && (i < bedItem->blockCount - 1)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, (bedItem->chromStarts[i] + bedItem->blockSizes[i]), (bedItem->chromStarts[i+1] - bedItem->chromStarts[i] - bedItem->blockSizes[i]), FALSE, FALSE, chromSize); } } } else if (canDoUTR) { if (bedItem->thickStart == 0 && bedItem->thickEnd == 0) bedItem->thickStart = bedItem->thickEnd = bedItem->chromStart; if ((!isRc && utrExon5) || (isRc && utrExon3)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->chromStart, (bedItem->thickStart - bedItem->chromStart), TRUE, FALSE, chromSize); } if (cdsExon) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->thickStart, (bedItem->thickEnd - bedItem->thickStart), TRUE, TRUE, chromSize); } if ((!isRc && utrExon3) || (isRc && utrExon5)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->thickEnd, (bedItem->chromEnd - bedItem->thickEnd), TRUE, FALSE, chromSize); } } else { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->chromStart, (bedItem->chromEnd - bedItem->chromStart), TRUE, FALSE, chromSize); } if (!isRc && downstream && (downstreamSize > 0)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->chromEnd, downstreamSize, FALSE, FALSE, chromSize); } else if (isRc && promoter && (promoterSize > 0)) { addFeature(&count, starts, sizes, exonFlags, cdsFlags, bedItem->chromEnd, promoterSize, FALSE, FALSE, chromSize); } if (bedItem->name != NULL) safef(itemName, sizeof(itemName), "%s_%s", hti->rootName, bedItem->name); else safef(itemName, sizeof(itemName), "%s_%d", hti->rootName, rowCount); hgSeqRegionsAdjDb(db, bedItem->chrom, chromSize, bedItem->strand[0], itemName, concatRegions, concatAdjacent, count, starts, sizes, exonFlags, cdsFlags); rowCount++; totalCount += count; freeMem(starts); freeMem(sizes); freeMem(exonFlags); freeMem(cdsFlags); } return totalCount; } int hgSeqItemsInRange(char *db, char *table, char *chrom, int chromStart, int chromEnd, char *sqlConstraints) /* Print out dna sequence of all items (that match sqlConstraints, if nonNULL) in the given range in table. Return number of items. */ { struct hTableInfo *hti; struct bed *bedList = NULL; char rootName[256]; char parsedChrom[32]; int itemCount; hParseTableName(db, table, rootName, parsedChrom); hti = hFindTableInfo(db, chrom, rootName); if (hti == NULL) webAbort("Error", "Could not find table info for table %s (%s)", rootName, table); bedList = hGetBedRange(db, table, chrom, chromStart, chromEnd, sqlConstraints); itemCount = hgSeqBed(db, hti, bedList); bedFreeList(&bedList); return itemCount; }