24cf4a1294b7e146f488b877eb87b9f2e83eaa9c
hiram
  Wed Feb 28 17:39:28 2024 -0800
moving static loadSizes() function from hg/utils/pslCheck.c to lib/common.c no redmine

diff --git src/inc/common.h src/inc/common.h
index bbfdb28..c14cbcd 100644
--- src/inc/common.h
+++ src/inc/common.h
@@ -1,1636 +1,1639 @@
 /* Common.h - functions that are commonly used.  Includes
  * routines for managing singly linked lists, some basic
  * string manipulation stuff, and other stuff of the
  * short but useful nature.
  *
  * This file is copyright 2002-2005 Jim Kent, but license is hereby
  * granted for all use - public, private or commercial. */
 
 #ifndef COMMON_H	/* Wrapper to avoid including this twice. */
 #define COMMON_H
 
 /* Some stuff to support large files in Linux. */
 #ifndef _LARGEFILE_SOURCE
 #define _LARGEFILE_SOURCE 1
 #endif
 
 #ifndef _GNU_SOURCE
 #define _GNU_SOURCE
 #endif
 
 #ifndef _FILE_OFFSET_BITS
 #define _FILE_OFFSET_BITS 64
 #endif
 
 /* Some stuff for safer pthreads. */
 #ifndef _REENTRANT
 #define _REENTRANT
 #endif
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
 #include <ctype.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <strings.h>
 #include <fcntl.h>
 #include <assert.h>
 #include <setjmp.h>
 #include <time.h>
 #include <math.h>
 #include <errno.h>
 #include <unistd.h>
 #include <libgen.h>
 
 #if defined(MACHTYPE_ppc)
 #include <sys/wait.h>
 #endif
 
 #if defined(__APPLE__)
 #if defined(__i686__)
 /* The i686 apple math library defines warn. */
 #define warn jkWarn
 #endif
 #endif
 
 #ifdef __CYGWIN32__
 #include <mingw/math.h>
 #endif
 
 #ifndef NAN
 #define NAN (0.0 / 0.0)
 #endif
 
 #ifndef WIFEXITED
 #define WIFEXITED(stat)  (((*((int *) &(stat))) & 0xff) == 0)
 #endif
 
 #ifndef WEXITSTATUS
 #define WEXITSTATUS(stat) (short)(((*((int *) &(stat))) >> 8) & 0xffff)
 #endif
 
 #ifndef WIFSIGNALED
 #define WIFSIGNALED(stat) (((*((int *) &(stat)))) && ((*((int *) &(stat))) == ((*((int *) &(stat))) &0x00ff)))
 #endif
 
 #ifndef WTERMSIG
 #define WTERMSIG(stat)    ((*((int *) &(stat))) & 0x7f)
 #endif
 
 #ifndef WIFSTOPPED
 #define WIFSTOPPED(stat)  (((*((int *) &(stat))) & 0xff) == 0177)
 #endif
 
 #ifndef WSTOPSIG
 #define WSTOPSIG(stat)    (((*((int *) &(stat))) >> 8) & 0xff)
 #endif
 
 #ifndef HUGE
 #define HUGE MAXFLOAT
 #endif
 
 
 /* Let's pretend C has a boolean type. */
 #define TRUE 1
 #define FALSE 0
 #define boolean int
 #ifndef	__cplusplus
 #ifndef bool
 #define bool char
 #endif
 #endif
 
 /* Some other type synonyms */
 #define UBYTE unsigned char   /* Wants to be unsigned 8 bits. */
 #define BYTE signed char      /* Wants to be signed 8 bits. */
 #define UWORD unsigned short  /* Wants to be unsigned 16 bits. */
 #define WORD short	      /* Wants to be signed 16 bits. */
 #define bits64 unsigned long long  /* Wants to be unsigned 64 bits. */
 #define bits32 unsigned       /* Wants to be unsigned 32 bits. */
 #define bits16 unsigned short /* Wants to be unsigned 16 bits. */
 #define bits8 unsigned char   /* Wants to be unsigned 8 bits. */
 #define signed32 int	      /* Wants to be signed 32 bits. */
 #define bits8 unsigned char   /* Wants to be unsigned 8 bits. */
 
 #define BIGNUM 0x3fffffff	/* A really big number but most subtraction won't cause overflow */
 #define BIGDOUBLE 1.7E+308	/* Close to biggest double-precision number */
 #define BIGLONGLONG 0x3fffffffffffffff /* A really big long long value safe for a subtraction */
 
 #define LIMIT_2or8GB (2147483647 * ((sizeof(size_t)/4)*(sizeof(size_t)/4)))
 /*      == 2 Gb for 32 bit machines, 8 Gb for 64 bit machines */
 #define LIMIT_2or6GB (2147483647 + (2147483647 * ((sizeof(size_t)/4)-1)) + \
 	(2147483647 * ((sizeof(size_t)/4)-1)))
 /*      == 2 Gb for 32 bit machines, 6 Gb for 64 bit machines */
 
 /* Default size of directory path, file name and extension string buffers */
 #define PATH_LEN 512
 #define FILENAME_LEN 128
 #define FILEEXT_LEN 64
 
 /* inline functions: To declare a function inline, place the entire function
  * in a header file and prefix it with the INLINE macro.  If used with a
  * compiler that doesn't support inline, change the INLINE marco to be simply
  * `static'.
  */
 #ifndef INLINE
 #define INLINE static inline
 #endif
 
 /* stdargs compatibility: in a unix universe a long time ago, types of va_list
  * were passed by value.  It was assume one could do things like:
  *
  *     va_start(args);
  *     vfprintf(fh1, fmt, args);
  *     vfprintf(fh2, fmt, args);
  *     va_end(args);
  *
  * and life would good.  However this is not true on some modern systems (for
  * instance gcc/glibc on x86_64), where va_args can be a pointer to some type
  * of object).  The second call to vfprintf() would then crash, since the
  * first call modified the object that va_args was pointing to. C99 adds a
  * va_copy macro that to address this issue.  Many non-C99 system include this
  * macro, sometimes called __va_copy.  Here we ensure that va_copy is defined.
  * If if doesn't exist, we try to define it in terms of __va_copy.  If that is
  * not available, we make the assumption that va_list can be copied by value
  * and create our own.  Our implementation is the same as used on Solaris.
  */
 #if defined(__va_copy) && !defined(va_copy)
 #   define va_copy __va_copy
 #endif
 #if !defined(va_copy)
 #   define va_copy(to, from) ((to) = (from))
 #endif
 
 /* Cast a pointer to a long long. Use to printf format points as long-longs
  * in a 32/64bit portable manner.  Format should use %llx for the result.
  * Needed because casting a pointer to a different sized number cause a
  * warning with gcc */
 #define ptrToLL(p) ((long long)((size_t)p))
 
 /* How big is this array? */
 #define ArraySize(a) (sizeof(a)/sizeof((a)[0]))
 
 #define uglyf printf  /* debugging printf */
 #define uglyAbort errAbort /* debugging error abort. */
 #define uglyOut stdout /* debugging fprintf target. */
 
 unsigned long memCheckPoint();
 /* Return the amount of memory allocated since last called. */
 
 void *needMem(size_t size);
 /* Need mem calls abort if the memory allocation fails. The memory
  * is initialized to zero. */
 
 void *needLargeMem(size_t size);
 /* This calls abort if the memory allocation fails. The memory is
  * not initialized to zero. */
 
 void *needLargeZeroedMem(size_t size);
 /* Request a large block of memory and zero it. */
 
 void *needLargeMemResize(void* vp, size_t size);
 /* Adjust memory size on a block, possibly relocating it.  If vp is NULL,
  * a new memory block is allocated.  Memory not initted. */
 
 void *needLargeZeroedMemResize(void* vp, size_t oldSize, size_t newSize);
 /* Adjust memory size on a block, possibly relocating it.  If vp is NULL, a
  * new memory block is allocated.  If block is grown, new memory is zeroed. */
 
 void *needHugeMem(size_t size);
 /* No checking on size.  Memory not initted to 0. */
 
 void *needHugeZeroedMem(size_t size);
 /* Request a large block of memory and zero it. */
 
 void *needHugeMemResize(void* vp, size_t size);
 /* Adjust memory size on a block, possibly relocating it.  If vp is NULL,
  * a new memory block is allocated.  No checking on size.  Memory not
  * initted. */
 
 void *needHugeZeroedMemResize(void* vp, size_t oldSize, size_t newSize);
 /* Adjust memory size on a block, possibly relocating it.  If vp is NULL, a
  * new memory block is allocated.  No checking on size.  If block is grown,
  * new memory is zeroed. */
 
 void *needMoreMem(void *old, size_t copySize, size_t newSize);
 /* Allocate a new buffer, copy old buffer to it, free old buffer. */
 
 void *cloneMem(void *pt, size_t size);
 /* Allocate a new buffer of given size, and copy pt to it. */
 
 #define CloneVar(pt) cloneMem(pt, sizeof((pt)[0]))
 /* Allocate copy of a structure. */
 
 void *wantMem(size_t size);
 /* Want mem just calls malloc - no zeroing of memory, no
  * aborting if request fails. */
 
 void freeMem(void *pt);
 /* Free memory will check for null before freeing. */
 
 void freez(void *ppt);
 /* Pass address of pointer.  Will free pointer and set it
  * to NULL. Typical use:
  *     s = needMem(1024);
  *          ...
  *     freez(&s); */
 
 #define AllocVar(pt) (pt = needMem(sizeof(*pt)))
 /* Shortcut to allocating a single variable on the heap and
  * assigning pointer to it. */
 
 #define AllocArray(pt, size) (pt = needLargeZeroedMem(sizeof(*pt) * (size)))
 
 #define AllocA(type) needMem(sizeof(type))
 /* Shortcut to allocating a variable on heap of a specific type. */
 
 #define AllocN(type,count) ((type*)needLargeZeroedMem(sizeof(type) * (count)))
 /* Shortcut to allocating an array on the heap of a specific type. */
 
 #define ExpandArray(array, oldCount, newCount) \
   (array = needMoreMem((array), (oldCount)*sizeof((array)[0]), (newCount)*sizeof((array)[0])))
 /* Expand size of dynamically allocated array. */
 
 #define CopyArray(source, dest,count) memcpy(dest,source,(count)*sizeof(dest[0]))
 /* Copy count elements of array from source to dest. */
 
 #define CloneArray(a, count) cloneMem(a, (count)*sizeof(a[0]))
 /* Make new dynamic array initialized with  count elements of a */
 
 void errAbort(char *format, ...)
 /* Abort function, with optional (printf formatted) error message. */
 #if defined(__GNUC__)
 __attribute__((format(printf, 1, 2)))
 #endif
 ;
 
 void errnoAbort(char *format, ...)
 /* Prints error message from UNIX errno first, then does errAbort. */
 #if defined(__GNUC__)
 __attribute__((format(printf, 1, 2)))
 #endif
 ;
 
 #define internalErr()  errAbort("Internal error %s %d", __FILE__, __LINE__)
 /* Generic internal error message */
 
 void warn(char *format, ...)
 /* Issue a warning message. */
 #if defined(__GNUC__)
 __attribute__((format(printf, 1, 2)))
 #endif
 ;
 
 void warnWithBackTrace(char *format, ...)
 /* Issue a warning message and append backtrace. */
 #if defined(__GNUC__)
 __attribute__((format(printf, 1, 2)))
 #endif
 ;
 
 void verbose(int verbosity, char *format, ...)
 /* Write printf formatted message to log (which by
  * default is stdout) if global verbose variable
  * is set to verbosity or higher.  Default level is 1. */
 #if defined(__GNUC__)
 __attribute__((format(printf, 2, 3)))
 #endif
     ;
 
 void verboseTimeInit(void);
 /* Initialize or reinitialize the previous time for use by verboseTime. */
 
 void verboseTime(int verbosity, char *label, ...)
 /* Print label and how long it's been since last call.  Start time can be
  * initialized with verboseTimeInit, otherwise the elapsed time will be
  * zero. */
 #if defined(__GNUC__)
 __attribute__((format(printf, 2, 3)))
 #endif
     ;
 
 void verboseDot();
 /* Write I'm alive dot (at verbosity level 1) */
 
 int verboseLevel();
 /* Get verbosity level. */
 
 void verboseSetLevel(int verbosity);
 /* Set verbosity level in log.  0 for no logging,
  * higher number for increasing verbosity. */
 
 INLINE void zeroBytes(void *vpt, int count)
 /* fill a specified area of memory with zeroes */
 {
 memset(vpt, '\0', count);
 }
 
 #define ZeroVar(v) zeroBytes(v, sizeof(*v))
 
 void reverseBytes(char *bytes, long length);
 /* Reverse the order of the bytes. */
 
 void reverseInts(int *a, int length);
 /* Reverse the order of the integer array. */
 
 void reverseUnsigned(unsigned *a, int length);
 /* Reverse the order of the unsigned array. */
 
 void reverseDoubles(double *a, int length);
 /* Reverse the order of the double array. */
 
 void reverseStrings(char **a, int length);
 /* Reverse the order of the char* array. */
 
 void sortStrings(char **array, int count);
 /* Sort array using strcmp */
 
 
 void swapBytes(char *a, char *b, int length);
 /* Swap buffers a and b. */
 
 /******* Some things to manage simple lists - structures that begin ******
  ******* with a pointer to the next element in the list.            ******/
 struct slList
     {
     struct slList *next;
     };
 
 int slCount(const void *list);
 /* Return # of elements in list.  */
 
 void *slElementFromIx(void *list, int ix);
 /* Return the ix'th element in list.  Returns NULL
  * if no such element. */
 
 int slIxFromElement(void *list, void *el);
 /* Return index of el in list.  Returns -1 if not on list. */
 
 INLINE void slAddHead(void *listPt, void *node)
 /* Add new node to start of list.
  * Usage:
  *    slAddHead(&list, node);
  * where list and nodes are both pointers to structure
  * that begin with a next pointer.
  */
 {
 struct slList **ppt = (struct slList **)listPt;
 struct slList *n = (struct slList *)node;
 n->next = *ppt;
 *ppt = n;
 }
 
 INLINE void slSafeAddHead(void *listPt, void *node)
 /* Add new node to start of list.  Now that slAddHead is an inline instead of
  * a macro, this function is obsolete.
  */
 {
 slAddHead(listPt, node);
 }
 
 void slAddTail(void *listPt, void *node);
 /* Add new node to tail of list.
  * Usage:
  *    slAddTail(&list, node);
  * where list and nodes are both pointers to structure
  * that begin with a next pointer. This is sometimes
  * convenient but relatively slow.  For longer lists
  * it's better to slAddHead, and slReverse when done.
  */
 
 void *slPopHead(void *listPt);
 /* Return head of list and remove it from list. (Fast) */
 
 void *slPopTail(void *listPt);
 /* Return tail of list and remove it from list. (Not so fast) */
 
 void *slCat(void *a, void *b);
 /* Return concatenation of lists a and b.
  * Example Usage:
  *   struct slName *a = getNames("a");
  *   struct slName *b = getNames("b");
  *   struct slName *ab = slCat(a,b)
  * After this it is no longer safe to use a or b.
  */
 
 void *slLastEl(void *list);
 /* Returns last element in list or NULL if none. */
 
 void slReverse(void *listPt);
 /* Reverse order of a list.
  * Usage:
  *    slReverse(&list);
  */
 
 typedef int CmpFunction(const void *elem1, const void *elem2);
 
 void slSort(void *pList, CmpFunction *compare);
 /* Sort a singly linked list with Qsort and a temporary array.
  * The arguments to the compare function in real, non-void, life
  * are pointers to pointers. */
 
 void slUniqify(void *pList, CmpFunction *compare, void (*free)());
 /* Return sorted list with duplicates removed.
  * Compare should be same type of function as slSort's compare (taking
  * pointers to pointers to elements.  Free should take a simple
  * pointer to dispose of duplicate element, and can be NULL. */
 
 void slSortMerge(void *pA, void *b, CmpFunction *compare);
 // Merges and sorts a pair of singly linked lists using slSort.
 
 void slSortMergeUniq(void *pA, void *b, CmpFunction *compare, void (*free)());
 // Merges and sorts a pair of singly linked lists leaving only unique
 // items via slUniqufy.  duplicate itens are defined by the compare routine
 // returning 0. If free is provided, items dropped from list can disposed of.
 
 boolean slRemoveEl(void *vpList, void *vToRemove);
 /* Remove element from singly linked list.  Usage:
  *    slRemove(&list, el);
  * Returns TRUE if element in list.  */
 
 void slFreeList(void *listPt);
 /* Free all elements in list and set list pointer to null.
  * Usage:
  *    slFreeList(&list);
  */
 
 void slFreeListWithFunc(void *listPt, void (*freeFunc)());
 /* Free a list by calling freeFunc on each element.
  * listPt must be a pointer to a pointer to some slList-compatible struct (&list).
  * freeFunc must take one arg: a pointer to a pointer to the item it is going to free. */
 
 /******* slInt - an int on a list - the first of many singly linked list structures *******/
 
 struct slInt
 /* List of integers. */
     {
     struct slInt *next;	/* Next in list. */
     int val;		/* Integer value. */
     };
 
 struct slInt *slIntNew(int x);
 #define newSlInt slIntNew
 /* Return a new double. */
 
 int slIntCmp(const void *va, const void *vb);
 /* Compare two slInts. */
 
 int slIntCmpRev(const void *va, const void *vb);
 /* Compare two slInts in reverse direction. */
 
 struct slInt * slIntFind(struct slInt *list, int target);
 /* Find target in slInt list or return NULL */
 
 struct slUnsigned
 /* List of unsigned */
     {
     struct slUnsigned *next;  /* Next in list */
     unsigned val;	      /* Unsigned value */
     };
 
 struct slUnsigned *slUnsignedNew(unsigned x);
 /* Return a new slUnsigned. */
 
 /******* slDouble - a double on a list *******/
 
 struct slDouble
 /* List of double-precision numbers. */
     {
     struct slDouble *next;	/* Next in list. */
     double val;			/* Double-precision value. */
     };
 
 struct slDouble *slDoubleNew(double x);
 #define newSlDouble slDoubleNew
 /* Return a new int. */
 
 int slDoubleCmp(const void *va, const void *vb);
 /* Compare two slDoubles. */
 
 double slDoubleMedian(struct slDouble *list);
 /* Return median value on list. */
 
 /******* slName - a zero terminated string on a list *******/
 
 struct slName
 /* List of names. The name array is allocated to accommodate full name
  */
     {
     struct slName *next;	/* Next in list. */
     char name[1];               /* Allocated at run time to length of string. */
     };
 
 struct slName *newSlName(char *name);
 
 #define slNameNew newSlName
 /* Return a new slName. */
 
 #define slNameFree freez
 /* Free a single slName */
 
 #define slNameFreeList slFreeList
 /* Free a list of slNames */
 
 struct slName *slNameNewN(char *name, int size);
 /* Return new slName of given size. */
 
 int slNameCmpCase(const void *va, const void *vb);
 /* Compare two slNames, ignore case. */
 
 int slNameCmp(const void *va, const void *vb);
 /* Compare two slNames. */
 
 int slNameCmpStringsWithEmbeddedNumbers(const void *va, const void *vb);
 /* Compare strings such as gene names that may have embedded numbers,
  * so that bmp4a comes before bmp14a */
 
 int slNameCmpWordsWithEmbeddedNumbers(const void *va, const void *vb);
 /* Compare strings such as gene names that may have embedded numbers,
  * in a string sensitive way so that bmp4a comes before bmp14a 
  * and ABc and abC are treated as the same.  A little slow. */
 
 void slNameSortCase(struct slName **pList);
 /* Sort slName list, ignore case. */
 
 void slNameSort(struct slName **pList);
 /* Sort slName list. */
 
 boolean slNameInList(struct slName *list, char *string);
 /* Return true if string is in name list -- case insensitive. */
 
 boolean slNameInListUseCase(struct slName *list, char *string);
 /* Return true if string is in name list -- case sensitive. */
 
 void *slNameFind(void *list, char *string);
 /* Return first element of slName list (or any other list starting
  * with next/name fields) that matches string. This is case insensitive. */
 
 int slNameFindIx(struct slName *list, char *string);
 /* Return index of first element of slName list (or any other
  * list starting with next/name fields) that matches string.
  * ... Return -1 if not found. */
 
 char *slNameStore(struct slName **pList, char *string);
 /* Put string into list if it's not there already.
  * Return the version of string stored in list. */
 
 struct slName *slNameAddHead(struct slName **pList, char *name);
 /* Add name to start of list and return it. */
 
 struct slName *slNameAddTail(struct slName **pList, char *name);
 /* Add name to end of list (not efficient for long lists),
  * and return it. */
 
 struct slName *slNameCloneList(struct slName *list);
 /* Return clone of list. */
 
 struct slName *slNameListFromString(char *s, char delimiter);
 /* Return list of slNames gotten from parsing delimited string.
  * The final delimiter is optional. a,b,c  and a,b,c, are equivalent
  * for comma-delimited lists. */
 
 #define slNameListFromComma(s) slNameListFromString(s, ',')
 /* Parse out comma-separated list. */
 
 struct slName *slNameListFromCommaEscaped(char *s);
 /* Return list of slNames gotten from parsing comma delimited string.
  * The final comma is optional. a,b,c  and a,b,c, are equivalent
  * for comma-delimited lists. To escape commas, put two in a row, 
  * which eliminates the possibility for null names 
  * (eg.  a,,b,c will parse to two elements a,b and c). */
 
 struct slName *slNameListFromStringArray(char *stringArray[], int arraySize);
 /* Return list of slNames from an array of strings of length arraySize.
  * If a string in the array is NULL, the array will be treated as
  * NULL-terminated. */
 
 char *slNameListToString(struct slName *list, char delimiter);
 /* Return string created by joining all names with the delimiter. */
 
 struct slName *slNameLoadReal(char *fileName);
 /* load file lines that are not blank or start with a '#' into a slName
  * list */
 
 struct slName *slNameIntersection(struct slName *a, struct slName *b);
 /* return intersection of two slName lists.  */
 
 /******* slRef - a void pointer on a list *******/
 
 struct slRef
 /* Singly linked list of generic references. */
     {
     struct slRef *next;	/* Next in list. */
     void *val;		/* A reference to something. */
     };
 
 struct slRef *slRefNew(void *val);
 /* Create new slRef element. */
 
 struct slRef *refOnList(struct slRef *refList, void *val);
 /* Return ref if val is already on list, otherwise NULL. */
 
 void refAdd(struct slRef **pRefList, void *val);
 /* Add reference to list. */
 
 void refAddUnique(struct slRef **pRefList, void *val);
 /* Add reference to list if not already on list. */
 
 void slRefFreeListAndVals(struct slRef **pList);
 /* Free up (with simple freeMem()) each val on list, and the list itself as well. */
 
 struct slRef *refListFromSlList(void *list);
 /* Make a reference list that mirrors a singly-linked list. */
 
 /******* slPair - a name/value pair on list where value not always a string *******/
 
 struct slPair
 /* A name/value pair. */
     {
     struct slPair *next;	/* Next in list. */
     char *name;			/* Name of item. */
     void *val;			/* Pointer to item data. */
     };
 
 struct slPair *slPairNew(char *name, void *val);
 /* Allocate new name/value pair. */
 
 void slPairAdd(struct slPair **pList, char *name, void *val);
 /* Add new slPair to head of list. */
 
 void slPairFree(struct slPair **pEl);
 /* Free up struct and name.  (Don't free up values.) */
 
 void slPairFreeList(struct slPair **pList);
 /* Free up list.  (Don't free up values.) */
 
 void slPairFreeVals(struct slPair *list);
 /* Free up all values on list. */
 
 void slPairFreeValsAndList(struct slPair **pList);
 /* Free up all values on list and list itself */
 
 void slPairFreeValsAndListExt(struct slPair **pList, void (*freeFunc)());
 /* Free up all values on list using freeFunc and list itself.  freeFunc should take a simple
  * pointer to free an item, and can be NULL. */
 
 struct slPair *slPairFind(struct slPair *list, char *name);
 /* Return list element of given name, or NULL if not found. */
 
 void *slPairFindVal(struct slPair *list, char *name);
 /* Return value associated with name in list, or NULL if not found. */
 
 struct slPair *slPairListFromString(char *str,boolean respectQuotes);
 // Return slPair list parsed from list in string like:  [name1=val1 name2=val2 ...]
 // if respectQuotes then string can have double quotes: [name1="val 1" "name 2"=val2 ...]
 //    resulting pair strips quotes: {name1}={val 1},{name 2}={val2}
 // Returns NULL if parse error.  Free this up with slPairFreeValsAndList.
 #define slPairFromString(s) slPairListFromString(s,FALSE)
 
 char *slPairListToString(struct slPair *list,boolean quoteIfSpaces);
 // Returns an allocated string of pairs in form of [name1=val1 name2=val2 ...]
 // If requested, will wrap name or val in quotes if contain spaces: [name1="val 1" "name 2"=val2]
 
 char *slPairNameToString(struct slPair *list, char delimiter,boolean quoteIfSpaces);
 // Return string created by joining all names (ignoring vals) with the delimiter.
 // If requested, will wrap name in quotes if contain spaces: [name1,"name 2" ...]
 
 int slPairCmpCase(const void *va, const void *vb);
 /* Compare two slPairs, ignore case. */
 
 void slPairSortCase(struct slPair **pList);
 /* Sort slPair list, ignore case. */
 
 int slPairCmpWordsWithEmbeddedNumbers(const void *va, const void *vb);
 /* Sort slPairList ignoring case and dealing with embedded numbers so 2 comes
  * before 10, not after. */
 
 int slPairCmp(const void *va, const void *vb);
 /* Compare two slPairs. */
 
 int slPairValCmpCase(const void *va, const void *vb);
 /* Case insensitive compare two slPairs on their values (must be string). */
 
 int slPairValCmp(const void *va, const void *vb);
 /* Compare two slPairs on their values (must be string). */
 
 void slPairValSortCase(struct slPair **pList);
 /* Sort slPair list on values (must be string), ignore case. */
 
 void slPairValSort(struct slPair **pList);
 /* Sort slPair list on values (must be string). */
 
 int slPairIntCmp(const void *va, const void *vb);
 // Compare two slPairs on their integer values.
 
 void slPairIntSort(struct slPair **pList);
 // Sort slPair list on integer values.
 
 int slPairAtoiCmp(const void *va, const void *vb);
 // Compare two slPairs on their strings interpreted as integer values.
 
 void slPairValAtoiSort(struct slPair **pList);
 // Sort slPair list on string values interpreted as integers.
 
 
 
 /******* Some old stuff maybe we could trim. *******/
 
 void gentleFree(void *pt);
 /* check pointer for NULL before freeing.
  * (Actually plain old freeMem does that these days.) */
 
 /******* Some math stuff *******/
 
 void doubleSort(int count, double *array);
 /* Sort an array of doubles. */
 
 double doubleMedian(int count, double *array);
 /* Return median value in array.  This will sort
  * the array as a side effect. */
 
 void doubleBoxWhiskerCalc(int count, double *array, double *retMin,
 	double *retQ1, double *retMedian, double *retQ3, double *retMax);
 /* Calculate what you need to draw a box and whiskers plot from an array of doubles. */
 
 void slDoubleBoxWhiskerCalc(struct slDouble *list, double *retMin,
 	double *retQ1, double *retMedian, double *retQ3, double *retMax);
 /* Calculate what you need to draw a box and whiskers plot from a list of slDoubles. */
 
 int intMedian(int count, int *array);
 /* Return median value in array.  This will sort
  * the array as a side effect. */
 
 void intSort(int count, int *array);
 /* Sort an array of ints. */
 
 
 /*******  Some stuff for processing strings. *******/
 
 char *cloneStringZ(const char *s, int size);
 /* Make a zero terminated copy of string in memory */
 
 char *cloneString(const char *s);
 /* Make copy of string in dynamic memory */
 
 char *cloneLongString(char *s);
 /* Make clone of long string. */
 
 char *catTwoStrings(char *a, char *b);
 /* Allocate new string that is a concatenation of two strings. */
 
 char *catThreeStrings(char *a, char *b, char *c);
 /* Allocate new string that is a concatenation of three strings. */
 
 int differentWord(char *s1, char *s2);
 /* strcmp ignoring case - returns zero if strings are
  * the same (ignoring case) otherwise returns difference
  * between first non-matching characters. */
 
 #define sameWord(a,b) (!differentWord(a,b))
 /* Return TRUE if two strings are same ignoring case */
 
 int differentWordNullOk(char *s1, char *s2);
 /* Returns 0 if two strings (either of which may be NULL)
  * are the same, ignoring case.  Otherwise returns the
  * difference between the first non-matching characters. */
 
 #define sameWordOk(a,b) (!differentWordNullOk(a,b))
 
 #define differentString(a,b) (strcmp(a,b))
 /* Returns FALSE if two strings same. */
 
 int differentStringNullOk(char *a, char *b);
 /* Returns 0 if two strings (either of which may be NULL)
  * are the same.  Otherwise it returns a positive or negative
  * number depending on the alphabetical order of the two
  * strings.
  * This is basically a strcmp that can handle NULLs in
  * the input.  If used in a sort the NULLs will end
  * up before any of the cases with data.   */
 
 #define sameOk(a,b) (differentStringNullOk(a,b) == 0)
 /* returns TRUE if two strings same, NULLs OK */
 
 #define sameString(a,b) (strcmp(a,b)==0)
 /* Returns TRUE if two strings same. */
 
 #define sameStringN(a,b,c) (strncmp(a,b,c)==0)
 /* Returns TRUE if two strings start with the same c characters. */
 
 #define isEmpty(string) ((string) == NULL || (string)[0] == 0)
 #define isNotEmpty(string) (! isEmpty(string))
 
 boolean isEmptyTextField(char *s);
 /* Recognize empty string or dot as empty text */
 
 int cmpStringsWithEmbeddedNumbers(const char *a, const char *b);
 /* Compare strings such as gene names that may have embedded numbers,
  * so that bmp4a comes before bmp14a */
 
 int cmpWordsWithEmbeddedNumbers(const char *a, const char *b);
 /* Case insensitive version of cmpStringsWithEmbeddedNumbers. */
 
 boolean startsWith(const char *start, const char *string);
 /* Returns TRUE if string begins with start. */
 
 boolean startsWithNoCase(const char *start, const char *string);
 /* Returns TRUE if string begins with start, case-insensitive. */
 
 boolean startsWithWord(char *firstWord, char *line);
 /* Return TRUE if first white-space-delimited word in line
  * is same as firstWord.  Comparison is case sensitive. */
 
 boolean startsWithWordByDelimiter(char *firstWord,char delimit, char *line);
 /* Return TRUE if first word in line is same as firstWord as delimited by delimit.
    Comparison is case sensitive. Delimit of ' ' uses isspace() */
 
 #define stringIn(needle, haystack) strstr(haystack, needle)
 /* Returns position of needle in haystack or NULL if it's not there. */
 /*        char *stringIn(char *needle, char *haystack);      */
 
 char *rStringIn(char *needle, char *haystack);
 /* Return last position of needle in haystack, or NULL if it's not there. */
 
 char *stringBetween(char *start, char *end, char *haystack);
 /* Return string between start and end strings, or NULL if
  * none found.  The first such instance is returned.
  * String must be freed by caller. */
 
 char *nextStringBetween(char *start, char *end, char **pHaystack);
 /* Return next string that occurs between start and end strings
  * starting seach at *pHaystack.  This will update *pHaystack to after 
  * end, so it can be called repeatedly. Returns NULL when
  * no more to be found*/
 
 char * findWordByDelimiter(char *word,char delimit, char *line);
 /* Return pointer to first word in line matching 'word' and delimited
    by 'delimit'. Comparison is case sensitive. Delimit of ' ' uses isspace() */
 
 boolean endsWith(char *string, char *end);
 /* Returns TRUE if string ends with end. */
 
 char lastChar(char *s);
 /* Return last character in string. */
 
 void trimLastChar(char *s);
 /* Erase last character in string. */
 
 char *lastNonwhitespaceChar(char *s);
 // Return pointer to last character in string that is not whitespace.
 
 char *matchingCharBeforeInLimits(char *limit, char *s, char c);
 /* Look for character c sometime before s, but going no further than limit.
  * Return NULL if not found. */
 
 boolean wildMatch(const char *wildCard, const char *string);
 /* does a case insensitive wild card match with a string.
  * * matches any string or no character.
  * ? matches any single character.
  * anything else etc must match the character exactly. */
 
 boolean sqlMatchLike(char *wildCard, char *string);
 /* Match using % and _ wildcards. */
 
 boolean anyWild(const char *string);
 /* Return TRUE if any wild card characters in string. */
 
 struct slName *wildExpandList(struct slName *allList, struct slName *wildList,
     boolean abortMissing);
 /* Wild list is a list of names, possibly including * and ? wildcard characters.  This
  * function returns names taken from allList that match patterns in wildList.  Works much
  * like wildcard expansion over a file system but expands over allList instead. */
 
 char *memMatch(char *needle, int nLen, char *haystack, int hLen);
 /* Returns first place where needle (of nLen chars) matches
  * haystack (of hLen chars) */
 
 void toUpperN(char *s, int n);
 /* Convert a section of memory to upper case. */
 
 void toLowerN(char *s, int n);
 /* Convert a section of memory to lower case. */
 
 void toggleCase(char *s, int size);
 /* toggle upper and lower case chars in string. */
 
 char *strUpper(char *s);
 #define touppers(s) (void)strUpper(s)
 /* Convert entire string to upper case. */
 
 char *strLower(char *s);
 #define tolowers(s) (void)strLower(s)
 /* Convert entire string to lower case */
 
 void replaceChar(char *s, char oldc, char newc);
 /* Repace one char with another. Modifies original string. */
 
 char *replaceChars(char *string, char *oldStr, char *newStr);
 /*
   Replaces the old with the new.
  The old and new string need not be of equal size
  Can take any length string.
  Return value needs to be freeMem'd.
 */
 
 int strSwapStrs(char *string, int sz,char *oldStr, char *newStr);
 /* Swaps all occurrences of the oldStr with the newStr in string. Need not be same size
    Swaps in place but restricted by sz.  Returns count of swaps or -1 for sz failure.*/
 
 char * memSwapChar(char *s, int len, char oldChar, char newChar);
 /* Substitute newChar for oldChar throughout memory of given length.
    old or new may be null */
 #define strSwapChar(s,old,new)   memSwapChar((s),strlen(s),(old),(new))
 #define subChar(s,old,new) (void)memSwapChar((s),strlen(s),(old),(new))
 /* Substitute newChar for oldChar throughout string s. */
 
 void stripChar(char *s, char c);
 /* Remove all occurences of c from s. */
 
 char *stripEnclosingChar(char *inout,char encloser);
 // Removes enclosing char if found at both beg and end, preserving pointer
 // Note: handles brackets '(','{' and '[' by complement at end
 #define stripEnclosingDoubleQuotes(inout) stripEnclosingChar((inout),'"')
 #define stripEnclosingSingleQuotes(inout) stripEnclosingChar((inout),'\'')
 
 void stripString(char *s, char *strip);
 /* Remove all occurences of strip from s. */
 
 int countCase(char *s,boolean upper);
 // Count letters with case (upper or lower)
 
 int countChars(char *s, char c);
 /* Return number of characters c in string s. */
 
 int countCharsN(char *s, char c, int size);
 /* Return number of characters c in string s of given size. */
 
 int countLeadingChars(char *s, char c);
 /* Count number of characters c at start of string. */
 
 int countLeadingDigits(const char *s);
 /* Return number of leading digits in s */
 
 int countLeadingNondigits(const char *s);
 /* Count number of leading non-digit characters in s. */
 
 int countSame(char *a, char *b);
 /* Count number of characters that from start in a,b that are same. */
 
 int countSeparatedItems(char *string, char separator);
 /* Count number of items in string you would parse out with given
  * separator,  assuming final separator is optional. */
 
 int chopString(char *in, char *sep, char *outArray[], int outSize);
 /* int chopString(in, sep, outArray, outSize); */
 /* This chops up the input string (cannabilizing it)
  * into an array of zero terminated strings in
  * outArray.  It returns the number of strings.
  * If you pass in NULL for outArray, it will just
  * return the number of strings that it *would*
  * chop. */
 
 extern char crLfChopper[];
 extern char whiteSpaceChopper[];
 /* Some handy predefined separators. */
 
 int chopByWhite(char *in, char *outArray[], int outSize);
 /* Like chopString, but specialized for white space separators. */
 
 #define chopLine(line, words) chopByWhite(line, words, ArraySize(words))
 /* Chop line by white space. */
 
 int chopByWhiteRespectDoubleQuotes(char *in, char *outArray[], int outSize);
 /* Like chopString, but specialized for white space separators.
  * Further, any doubleQuotes (") are respected.
  * If doubleQuote encloses whole string, then they are removed:
  *   "Fred and Ethyl" results in word [Fred and Ethyl]
  * If doubleQuotes exist inside string they are retained:
  *   Fred "and Ethyl" results in word [Fred "and Ethyl"]
  * Special note "" is a valid, though empty word. */
 
 int chopByCharRespectDoubleQuotes(char *in, char sep, char *outArray[], int outSize);
 /* Chop a string into sep delimited strings but honor double quotes */
 
 int chopByChar(char *in, char chopper, char *outArray[], int outSize);
 /* Chop based on a single character. */
 
 #define chopTabs(string, words) chopByChar(string, '\t', words, ArraySize(words))
 /* Chop string by tabs. */
 
 #define chopCommas(string, words) chopByChar(string, ',', words, ArraySize(words))
 /* Chop string by commas. */
 
 
 char *skipBeyondDelimit(char *s,char delimit);
 /* Returns NULL or pointer to first char beyond one (or more contiguous) delimit char.
    If delimit is ' ' then skips beyond first patch of whitespace. */
 
 char *skipLeadingSpaces(const char *s);
 /* Return first white space or NULL if none.. */
 
 char *skipToSpaces(const char *s);
 /* Return first white space. */
 
 int eraseTrailingSpaces(char *s);
 /* Replace trailing white space with zeroes. Returns number of
  * spaces erased. */
 
 void eraseWhiteSpace(char *s);
 /* Remove white space from a string */
 
 void eraseNonDigits(char *s);
 /* Remove any chars leaving digits only */
 
 void eraseNonAlphaNum(char *s);
 /* Remove non-alphanumeric chars from string */
 
 char *trimSpaces(char *s);
 /* Remove leading and trailing white space. */
 
 void repeatCharOut(FILE *f, char c, int count);
 /* Write character to file repeatedly. */
 
 void spaceOut(FILE *f, int count);
 /* Put out some spaces to file. */
 
 void starOut(FILE *f, int count);
 /* Put out some asterisks to file. */
 
 boolean hasWhiteSpace(char *s);
 /* Return TRUE if there is white space in string. */
 
 char *firstWordInLine(char *line);
 /* Returns first word in line if any (white space separated).
  * Puts 0 in place of white space after word. */
 
 char *lastWordInLine(char *line);
 /* Returns last word in line if any (white space separated).
  * Returns NULL if string is empty.  Removes any terminating white space
  * from line. */
 
 char *nextWord(char **pLine);
 /* Return next word in *pLine and advance *pLine to next
  * word. Returns NULL when no more words. */
 
 char *cloneFirstWord(char *line);
 /* Clone first word in line */
 
 char *cloneNotFirstWord(char *s);
 /* Clone part of string after first word. */
 
 char *nextTabWord(char **pLine);
 /* Return next tab-separated word. */
 
 char *cloneFirstWordByDelimiterNoSkip(char *line,char delimit);
 /* Returns a cloned first word, not harming the memory passed in.
  * Does not skip leading white space.*/
 
 char *cloneFirstWordByDelimiter(char *line,char delimit);
 /* Returns a cloned first word, not harming the memory passed in
    Skips leading white space.
    Delimiter of ' ' will delimit by isspace() */
 #define cloneFirstWordInLine(line) cloneFirstWordByDelimiter((line),' ')
 #define cloneFirstWordByTab(line)  cloneFirstWordByDelimiter((line),'\t')
 /* Returns a cloned first word, not harming the memory passed in */
 
 char *cloneNextWordByDelimiter(char **line,char delimit);
 /* Returns a cloned first word, advancing the line pointer
    but not harming memory passed in. Delimit ' ' uses isspace() */
 #define cloneNextWord(line)      cloneNextWordByDelimiter((line),' ')
 #define cloneNextWordByTab(line) cloneNextWordByDelimiter((line),'\t')
 
 char *nextStringInList(char **pStrings);
 /* returns pointer to the first string and advances pointer to next in
    list of strings dilimited by 1 null and terminated by 2 nulls. */
 
 int cntStringsInList(char *pStrings);
 /* returns count of strings in a
    list of strings dilimited by 1 null and terminated by 2 nulls. */
 
 int stringArrayIx(char *string, char *array[], int arraySize);
 /* Return index of string in array or -1 if not there. */
 
 int ptArrayIx(void *pt, void *array, int arraySize);
 /* Return index of pt in array or -1 if not there. */
 
 #define stringIx(string, array) stringArrayIx( (string), (array), ArraySize(array))
 
 int cmpStringOrder(char *a, char *b, char **orderFields, int orderCount);
 /* Compare two strings to sort in same order as orderedFields.  If strings are
  * not in order, will sort them to be after all ordered fields, alphabetically */
 /* Some stuff that is left out of GNU .h files!? */
 
 #ifndef SEEK_SET
 #define SEEK_SET 0
 #endif
 
 #ifndef SEEK_CUR
 #define SEEK_CUR 1
 #endif
 
 #ifndef SEEK_END
 #define SEEK_END 2
 #endif
 
 #ifndef FILEPATH_H
 void splitPath(char *path, char dir[PATH_LEN], char name[FILENAME_LEN],
 	       char extension[FILEEXT_LEN]);
 /* Split a full path into components.  The dir component will include the
  * trailing / if any.  The extension component will include the starting
  * . if any.   Pass in NULL for dir, name, or extension if you don't care about
  * that part. */
 #endif /* FILEPATH_H */
 
 char *addSuffix(char *head, char *suffix);
 /* Return a needMem'd string containing "headsuffix". Should be free'd
  when finished. */
 
 void chopSuffix(char *s);
 /* Remove suffix (last . in string and beyond) if any. */
 
 void chopSuffixAt(char *s, char c);
 /* Remove end of string from last occurrence of char c.
  * chopSuffixAt(s, '.') is equivalent to regular chopSuffix. */
 
 char *chopPrefix(char *s);
 /* This will replace the first '.' in a string with
  * 0, and return the character after this.  If there
  * is no '.' in the string this will just return the
  * unchanged s passed in. */
 
 char *chopPrefixAt(char *s, char c);
 /* Like chopPrefix, but can chop on any character, not just '.' */
 
 INLINE char *findTail(char *s, char c)
 /* find the start of the string following the last occurrence of c.
  * return the whole string if not found.  Does not modify the string. */
 {
 char *cp = strrchr(s, c);
 return (cp == NULL) ? s : cp+1;
 }
 
 FILE *mustOpen(char *fileName, char *mode);
 /* Open a file - or squawk and die. */
 
 void mustWrite(FILE *file, void *buf, size_t size);
 /* Write to file or squawk and die. */
 
 #define writeOne(file, var) mustWrite((file), &(var), sizeof(var))
 /* Write out one variable to file. */
 
 void mustRead(FILE *file, void *buf, size_t size);
 /* Read size bytes from a file or squawk and die. */
 
 #define mustReadOne(file, var) mustRead((file), &(var), sizeof(var))
 /* Read one variable from file or die. */
 
 void mustGetLine(FILE *file, char *buf, int charCount);
 /* Read at most charCount-1 bytes from file, but stop after newline if one is
  * encountered.  The string in buf is '\0'-terminated.  (See man 3 fgets.)
  * Die if there is an error. */
 
 void mustSeek(FILE *file, off_t offset, int whence);
 /* Seek to given offset, relative to whence (see man fseek) in file or errAbort. */
 
 int mustOpenFd(char *fileName, int flags);
 /* Open a file descriptor (see man 2 open) or squawk and die. */
 
 void mustReadFd(int fd, void *buf, size_t size);
 /* Read size bytes from a file descriptor or squawk and die. */
 
 void mustWriteFd(int fd, void *buf, size_t size);
 /* Write size bytes to file descriptor fd or die.  (See man 2 write.) */
 
 off_t mustLseek(int fd, off_t offset, int whence);
 /* Seek to given offset, relative to whence (see man lseek) in file descriptor fd or errAbort.
  * Return final offset (e.g. if this is just an (fd, 0, SEEK_CUR) query for current position). */
 
 void mustCloseFd(int *pFd);
 /* Close file descriptor *pFd if >= 0, abort if there's an error, set *pFd = -1. */
 
 #define writeOneFd(fd, var) mustWriteFd((fd), &(var), sizeof(var))
 /* Write out one variable to file descriptor fd. */
 
 #define readOne(file, var) (fread(&(var), sizeof(var), 1, (file)) == 1)
 /* Read one variable from file. Returns FALSE if can't do it. */
 
 #define readOneFd(fd, var) (read((fd), &(var), sizeof(var)) == sizeof(var))
 /* Read one variable from file. Returns FALSE if can't do it. */
 
 #define mustReadOneFd(fd, var) mustReadFd((fd), &(var), sizeof(var))
 /* Read one variable from file or die. */
 
 #define memReadOne(pPt, var) memRead((pPt), &(var), sizeof(var))
 /* Read one variable from memory. */
 
 void writeString(FILE *f, char *s);
 /* Write a 255 or less character string to a file.
  * This will write the length of the string in the first
  * byte then the string itself. */
 
 void writeStringSafe(FILE *f, char *s);
 /* Write a 255 or less character string to a file.  Generate an error if
  * longer.  This will write the length of the string in the first byte then
  * the string itself. */
 
 char *readString(FILE *f);
 /* Read a string (written with writeString) into
  * memory.  freeMem the result when done. Returns
  * NULL at EOF. */
 
 char *mustReadString(FILE *f);
 /* Read a string.  Squawk and die at EOF or if any problem. */
 
 boolean fastReadString(FILE *f, char buf[256]);
 /* Read a string into buffer, which must be long enough
  * to hold it.  String is in 'writeString' format.
  * Returns FALSE at EOF. */
 
 void msbFirstWriteBits64(FILE *f, bits64 x);
 /* Write out 64 bit number in manner that is portable across architectures */
 
 bits64 msbFirstReadBits64(FILE *f);
 /* Write out 64 bit number in manner that is portable across architectures */
 
 void carefulClose(FILE **pFile);
 /* Close file if open and null out handle to it. */
 
 boolean carefulCloseWarn(FILE **pFile);
 /* Close file if open and null out handle to it.
  * Return FALSE and print a warning message if there
  * is a problem.*/
 
 char *firstWordInFile(char *fileName, char *wordBuf, int wordBufSize);
 /* Read the first word in file into wordBuf. */
 
 struct fileOffsetSize
 /* A piece of a file. */
    {
    struct fileOffsetSize *next;	/* Next in list. */
    bits64	offset;		/* Start offset of block. */
    bits64	size;		/* Size of block. */
    };
 
 int fileOffsetSizeCmp(const void *va, const void *vb);
 /* Help sort fileOffsetSize by offset. */
 
 struct fileOffsetSize *fileOffsetSizeMerge(struct fileOffsetSize *inList);
 /* Returns a new list which is inList transformed to have adjacent blocks
  * merged.  Best to use this with a sorted list. */
 
 void fileOffsetSizeFindGap(struct fileOffsetSize *list,
 	struct fileOffsetSize **pBeforeGap, struct fileOffsetSize **pAfterGap);
 /* Starting at list, find all items that don't have a gap between them and the previous item.
  * Return at gap, or at end of list, returning pointers to the items before and after the gap. */
 
 void mustSystem(char *cmd);
 /* Execute cmd using "sh -c" or die.  (See man 3 system.) fail on errors */
 
 int roundingScale(int a, int p, int q);
 /* returns rounded a*p/q */
 
 int intAbs(int a);
 /* Return integer absolute value */
 
 #define logBase2(x)(log(x)/log(2))
 /* return log base two of number */
 
 #define round(a) ((int)((a)+0.5))
 /* Round floating point val to nearest integer. */
 
 #define roundll(a) ((long long)((a)+0.5))
 /* Round floating point val to nearest long long. */
 
 #if !(defined(min) || defined(__cplusplus))
 #define min(a,b) ( (a) < (b) ? (a) : (b) )
 /* Return min of a and b. */
 #endif
 
 #if !(defined(max) || defined(__cplusplus))
 #define max(a,b) ( (a) > (b) ? (a) : (b) )
 /* Return max of a and b. */
 #endif
 
 int  rangeIntersection(int start1, int end1, int start2, int end2);
 /* Return amount of bases two ranges intersect over, 0 or negative if no
  * intersection. */
 
 int  positiveRangeIntersection(int start1, int end1, int start2, int end2);
 /* Return amount of bases two ranges intersect over, 0 if no
  * intersection. */
 
 INLINE void memRead(char **pPt, void *buf, int size)
 /* Copy memory from *pPt to buf, and advance *pPt by size. */
 {
 memcpy(buf, *pPt, size);
 *pPt += size;
 }
 
 INLINE void memWrite(char **pPt, void *buf, int size)
 /* Copy memory from buf to *pPt and advance *pPt by size. */
 {
 memcpy(*pPt, buf, size);
 *pPt += size;
 }
 
 #define memWriteOne(pPt, var) memWrite((pPt), &(var), sizeof(var))
 /* Write out one variable to memory stream. */
 
 INLINE void memWriteFloat(char **pPt, float val)
 /* Write out floating point val to file.  Mostly to convert from double... */
 {
 memWriteOne(pPt, val);
 }
 
 bits64 byteSwap64(bits64 a);
 /* Swap from intel to sparc order of a 64 bit quantity. */
 
 bits64 readBits64(FILE *f, boolean isSwapped);
 /* Read and optionally byte-swap 64 bit entity. */
 
 bits64 fdReadBits64(int fd, boolean isSwapped);
 /* Read and optionally byte-swap 64 bit entity. */
 
 bits64 memReadBits64(char **pPt, boolean isSwapped);
 /* Read and optionally byte-swap 64 bit entity from memory buffer pointed to by
  * *pPt, and advance *pPt past read area. */
 
 bits32 byteSwap32(bits32 a);
 /* Swap from intel to sparc order of a 32 bit quantity. */
 
 bits32 readBits32(FILE *f, boolean isSwapped);
 /* Read and optionally byte-swap 32 bit entity. */
 
 bits32 fdReadBits32(int fd, boolean isSwapped);
 /* Read and optionally byte-swap 32 bit entity. */
 
 bits32 memReadBits32(char **pPt, boolean isSwapped);
 /* Read and optionally byte-swap 32 bit entity from memory buffer pointed to by
  * *pPt, and advance *pPt past read area. */
 
 bits16 byteSwap16(bits16 a);
 /* Swap from intel to sparc order of a 16 bit quantity. */
 
 bits16 readBits16(FILE *f, boolean isSwapped);
 /* Read and optionally byte-swap 16 bit entity. */
 
 bits16 fdReadBits16(int fd, boolean isSwapped);
 /* Read and optionally byte-swap 16 bit entity. */
 
 bits16 memReadBits16(char **pPt, boolean isSwapped);
 /* Read and optionally byte-swap 32 bit entity from memory buffer pointed to by
  * *pPt, and advance *pPt past read area. */
 
 double byteSwapDouble(double a);
 /* Return byte-swapped version of a */
 
 double readDouble(FILE *f, boolean isSwapped);
 /* Read and optionally byte-swap double-precision floating point entity. */
 
 double memReadDouble(char **pPt, boolean isSwapped);
 /* Read and optionally byte-swap double-precision floating point entity
  * from memory buffer pointed to by *pPt, and advance *pPt past read area. */
 
 float byteSwapFloat(float a);
 /* Return byte-swapped version of a */
 
 float readFloat(FILE *f, boolean isSwapped);
 /* Read and optionally byte-swap single-precision floating point entity. */
 
 float memReadFloat(char **pPt, boolean isSwapped);
 /* Read and optionally byte-swap single-precision floating point entity
  * from memory buffer pointed to by *pPt, and advance *pPt past read area. */
 
 void removeReturns(char* dest, char* src);
 /* Removes the '\r' character from a string.
  * the source and destination strings can be the same,
  * if there are no threads */
 
 int intExp(char *text);
 /* Convert text to integer expression and evaluate.
  * Throws if it finds a non-number. */
 
 double doubleExp(char *text);
 /* Convert text to floating point expression and
  * evaluate. */
 
 char* readLine(FILE* fh);
 /* Read a line of any size into dynamic memory, return null on EOF */
 
 off_t fileSize(char *fileName);
 /* The size of a file. */
 
 boolean fileExists(char *fileName);
 /* Does a file exist? */
 
 /*
  Friendly name for strstrNoCase
 */
 char *containsStringNoCase(char *haystack, char *needle);
 
 char *strstrNoCase(char *haystack, char *needle);
 /* A case-insensitive strstr */
 
 int vasafef(char* buffer, int bufSize, char *format, va_list args);
 /* Format string to buffer, vsprintf style, only with buffer overflow
  * checking.  The resulting string is always terminated with zero byte. */
 
 int vatruncatef(char *buf, int size, char *format, va_list args);
 /* Like vasafef, but truncates the formatted string instead of barfing on
  * overflow. */
 
 void truncatef(char *buf, int size, char *format, ...);
 /* Like safef, but truncates the formatted string instead of barfing on
  * overflow. */
 
 int safef(char* buffer, int bufSize, char *format, ...)
 /* Format string to buffer, vsprintf style, only with buffer overflow
  * checking.  The resulting string is always terminated with zero byte. */
 #ifdef __GNUC__
 __attribute__((format(printf, 3, 4)))
 #endif
 ;
 
 int safefcat(char* buffer, int bufSize, char *format, ...)
 /* Safely format string to the end of the buffer.  Returns number of characters
  * appended. */
 #ifdef __GNUC__
 __attribute__((format(printf, 3, 4)))
 #endif
 ;
 
 void safecpy(char *buf, size_t bufSize, const char *src);
 /* copy a string to a buffer, with bounds checking.*/
 
 void safencpy(char *buf, size_t bufSize, const char *src, size_t n);
 /* copy n characters from a string to a buffer, with bounds checking.
  * Unlike strncpy, always null terminates the result */
 
 void safecat(char *buf, size_t bufSize, const char *src);
 /* Append  a string to a buffer, with bounds checking.*/
 
 void safencat(char *buf, size_t bufSize, const char *src, size_t n);
 /* append n characters from a string to a buffer, with bounds checking. */
 
 void safememset(char *buf, size_t bufSize, const char c, size_t n);
 /* Append a character to a buffer repeatedly, n times with bounds checking.*/
 
 char *naForNull(char *s);
 /* Return 'n/a' if s is NULL, otherwise s. */
 
 char *naForEmpty(char *s);
 /* Return n/a if s is "" or NULL, otherwise s. */
 
 char *emptyForNull(char *s);
 /* Return "" if s is NULL, otherwise s. */
 
 char *nullIfAllSpace(char *s);
 /* Return NULL if s is all spaces, otherwise s. */
 
 char *trueFalseString(boolean b);
 /* Return "true" or "false" */
 
 void uglyTime(char *label, ...)
 /* Print label and how long it's been since last call.  Call with
  * a NULL label to initialize. Works better in html pages cause of formatting */
 
 #if defined(__GNUC__)
 __attribute__((format(printf, 1, 2)))
 #endif
 ;
 
 
 void uglyt(char *label, ...)
 /* Print label and how long it's been since last call.  Call with
  * a NULL label to initialize. Like uglyTime without the html formatting */
 
 #if defined(__GNUC__)
 __attribute__((format(printf, 1, 2)))
 #endif
 ;
 
 /*	In case the development environment does not supply INFINITY	*/
 #if !defined(INFINITY)
 #define INFINITY (1.0/0.0)
 #endif
 
 void makeDirs(char* path);
 /* make a directory, including parent directories */
 
 boolean isSymbolString(char *s);
 /* Return TRUE if s can be used as a symbol in the C language */
 
 boolean isNumericString(char *s);
 /* Return TRUE if string is numeric (integer or floating point) */
 
 boolean isAllDigits(char *s);
 /* Return TRUE if string is non-empty and contains only digits (i.e. is a nonnegative integer). */
 
 char *skipNumeric(char *s);
 /* Return first char of s that's not a digit */
 
 char *skipToNumeric(char *s);
 /* skip up to where numeric digits appear */
 
 char *splitOffNonNumeric(char *s);
 /* Split off non-numeric part, e.g. mm of mm8. Result should be freed when done */
 
 char *splitOffNumber(char *db);
 /* Split off number part, e.g. 8 of mm8. Result should be freed when done */
 
 
 void childExecFailedExit(char *msg);
 /* Child exec failed, so quit without atexit cleanup */
 
 void vaDumpStack(char *format, va_list args);
 /* debugging function to run the pstack program on the current process. In
  * prints a message, following by a new line, and then the stack track.  Just
  * prints errors to stderr rather than aborts. For debugging purposes
  * only.  */
 
 void dumpStack(char *format, ...)
 /* debugging function to run the pstack program on the current process. In
  * prints a message, following by a new line, and then the stack track.  Just
  * prints errors to stderr rather than aborts. For debugging purposes
  * only.  */
 #if defined(__GNUC__)
 __attribute__((format(printf, 1, 2)))
 #endif
 ;
 
 // SETTING_ON set of macros are frequently used comparisons of string values for boolean questions.
 // Notice the subtle difference between NOT_ON and IS_OFF.
 //        NOT_ON could be NULL but IS_OFF must be explicitly set
 #define SETTING_IS_ON(setting) (  setting && (sameWord(setting,"on") || sameWord(setting,"true") \
                                || sameWord(setting,"yes") || sameWord(setting,"enabled") \
                                || atoi(setting) != 0) )
 #define SETTING_NOT_ON(setting)   (!SETTING_IS_ON(setting))
 #define SETTING_IS_OFF(setting) (  setting && (sameWord(setting,"off") \
                                 || sameWord(setting,"false") || sameWord(setting,"no") \
                                 || sameWord(setting,"disabled") || sameWord(setting,"0")) )
 
 // Standard bit mask macros
 #define BITS_ADD(    flags,bits) ((flags) = ((flags) |  (bits)))
 #define BITS_REMOVE( flags,bits) ((flags) = ((flags) & ~(bits)))
 #define BITS_ARE_ON( flags,bits) (((flags) & (bits)) == (bits))
 #define BITS_ARE_OFF(flags,bits) (((flags) & (bits)) == 0)
 
 // It is sometimes useful to distinguish between 3 "boolean" states: TRUE, FALSE and UNKNOWN
 enum enumBool
     {
     beUnknown=0,              // Not yet set
     ebYes=1,                  // already set to TRUE
     ebNo=-1                   // already set to FALSE
     };
 #define SET_TO_YES(ebool) { (ebool) = ebYes; }
 #define SET_TO_NO(ebool)  { (ebool) = ebNo; }
 #define IS_YES(ebool)     ((ebool) == ebYes)
 #define IS_NO(ebool)      ((ebool) == ebNo)
 #define IS_KNOWN(ebool)   (IS_YES(ebool) || IS_NO(ebool))
 #define IS_TRUE           IS_YES
 #define IS_FALSE          IS_NO
 
 time_t mktimeFromUtc (struct tm *t);
 /* Return time_t for tm in UTC (GMT)
  * Useful for stuff like converting to time_t the
  * last-modified HTTP response header
  * which is always GMT. Returns -1 on failure of mktime */
 
 
 time_t dateToSeconds(const char *date,const char*format);
 // Convert a string date to time_t
 
 boolean dateIsOld(const char *date,const char*format);
 // Is this string date older than now?
 
 boolean dateIsOlderBy(const char *date,const char*format, time_t seconds);
 // Is this string date older than now by this many seconds?
 
 char *dateAddTo(char *date,char *format,int addYears,int addMonths,int addDays);
 /* Add years,months,days to a formatted date and returns the new date as a cloned string
 *  format is a strptime/strftime format: %F = yyyy-mm-dd */
 
 unsigned dayOfYear();
 /* Return the day of the year. */
 
 boolean haplotype(const char *name);
 /* Is this name a haplotype name ?  _hap or _alt in the name */
 
 char *shorterDouble(double value);
 /* Work around a "bug" in %g output that goes into scientific notation too early. */
 
 struct runTimes
 /* clock time since epoch, user CPU, and system CPU, in seconds */
 {
     double clockSecs;
     double userSecs;
     double sysSecs;
 };
 
 struct runTimes getTimesInSeconds(void);
 /* get the current clock time since epoch, process user CPU, and system CPU times, all in
  * seconds. */
 
+struct hash *loadSizes(char *sizesFile);
+/* load a sizes file */
+
 #endif /* COMMON_H */