fd802431971bf493181727133d48e13beea7d74e
markd
  Sun May 14 19:28:01 2023 -0700
as long as hood is up, make pslTransMap function thread-safe

diff --git src/lib/pslTransMap.c src/lib/pslTransMap.c
index 555140e..dd89577 100644
--- src/lib/pslTransMap.c
+++ src/lib/pslTransMap.c
@@ -58,45 +58,30 @@
 static void pslProtToNA(struct psl *psl)
 /* convert a protein/NA alignment to a NA/NA alignment */
 {
 int iBlk;
 
 psl->qStart *= 3;
 psl->qEnd *= 3;
 psl->qSize *= 3;
 for (iBlk = 0; iBlk < psl->blockCount; iBlk++)
     {
     psl->blockSizes[iBlk] *= 3;
     psl->qStarts[iBlk] *= 3;
     }
 }
 
-static void pslNAToProt(struct psl *psl)
-/* undo pslProtToNA */
-{
-int iBlk;
-
-psl->qStart /= 3;
-psl->qEnd /= 3;
-psl->qSize /= 3;
-for (iBlk = 0; iBlk < psl->blockCount; iBlk++)
-    {
-    psl->blockSizes[iBlk] /= 3;
-    psl->qStarts[iBlk] /= 3;
-    }
-}
-
 static struct psl* createMappedPsl(struct psl* inPsl, struct psl *mapPsl,
                                    int mappedPslMax)
 /* setup a PSL for the output alignment */
 {
 char strand[3];
 assert(pslTStrand(inPsl) == pslQStrand(mapPsl));
 
 /* strand can be taken from both alignments, since common sequence is in same
  * orientation. */
 strand[0] = pslQStrand(inPsl);
 strand[1] = pslTStrand(mapPsl);
 strand[2] = '\n';
 
 return pslNew(inPsl->qName, inPsl->qSize, 0, 0,
               mapPsl->tName, mapPsl->tSize, 0, 0,
@@ -306,62 +291,59 @@
     {
     struct block align1Blk = blockFromPslBlock(inPsl, iBlock);
     while (mapBlock(inPsl, mapPsl, &iMapBlk, &align1Blk, mappedPsl,
                     &mappedPslMax))
         continue;
     }
 assert(mappedPsl->blockCount <= mappedPslMax);
 
 return mappedPsl;
 }
 
 struct psl* pslTransMap(unsigned opts, struct psl *inPsl, struct psl *mapPsl)
 /* map a psl via a mapping psl, a single psl is returned, or NULL if it
  * couldn't be mapped. */
 {
-char inPslOrigStrand[3];
 boolean rcInPsl = (pslTStrand(inPsl) != pslQStrand(mapPsl));
-boolean cnv1 = (pslIsProtein(inPsl) && !pslIsProtein(mapPsl));
-boolean cnv2 = (pslIsProtein(mapPsl) && !pslIsProtein(inPsl));
+boolean cnvIn = (pslIsProtein(inPsl) && !pslIsProtein(mapPsl));
+boolean cnvMap = (pslIsProtein(mapPsl) && !pslIsProtein(inPsl));
 
 /* sanity check size, but allow names to vary to allow ids to have
  * unique-ifying suffixes. */
 if (inPsl->tSize != mapPsl->qSize)
     errAbort("Error: inPsl %s tSize (%d) != mapPsl %s qSize (%d)",
             inPsl->tName, inPsl->tSize, mapPsl->qName, mapPsl->qSize);
 
-/* convert protein PSLs */
-if (cnv1)
-    pslProtToNA(inPsl);
-if (cnv2)
-    pslProtToNA(mapPsl);
-
-/* need to ensure common sequence is in same orientation, save strand for later */
+/* ensure common sequence is in same orientation and convert protein PSLs */
+char inPslOrigStrand[3];
 safef(inPslOrigStrand, sizeof(inPslOrigStrand), "%s", inPsl->strand);
+if (cnvIn || rcInPsl)
+    inPsl = pslClone(inPsl);
+if (cnvIn)
+    pslProtToNA(inPsl);
 if (rcInPsl)
     pslRc(inPsl);
+if (cnvMap)
+    {
+    mapPsl = pslClone(mapPsl);
+    pslProtToNA(mapPsl);
+    }
 
 struct psl* mappedPsl = doMapping(inPsl, mapPsl);
 
 /* finish up psl, or free if no blocks were added */
 if (mappedPsl->blockCount == 0)
     pslFree(&mappedPsl);  /* nothing made it */
 else
     {
     setPslBoundsCounts(mappedPsl);
     adjustOrientation(opts, inPsl, inPslOrigStrand, mappedPsl);
     }
 
-/* restore input */
-if (rcInPsl)
-    {
-    pslRc(inPsl);
-    strcpy(inPsl->strand, inPslOrigStrand);
-    }
-if (cnv1)
-    pslNAToProt(inPsl);
-if (cnv2)
-    pslNAToProt(mapPsl);
+if (cnvIn || rcInPsl)
+    pslFree(&inPsl);
+if (cnvMap)
+    pslFree(&mapPsl);
 
 return mappedPsl;
 }