1 #ifdef _cplusplus
2 extern "C" {
3 #endif
4 #include "seqalign.h"
5 
6 /* Function:  is_gapped_SeqAlign(sa,pos)
7  *
8  * Descrip:    Tells you whether either . or - characters occur at
9  *             a position. Uses C-style coordinates
10  *
11  *
12  * Arg:         sa [UNKN ] Undocumented argument [SeqAlign *]
13  * Arg:        pos [UNKN ] Undocumented argument [int]
14  *
15  * Return [UNKN ]  Undocumented return value [boolean]
16  *
17  */
18 # line 46 "seqalign.dy"
is_gapped_SeqAlign(SeqAlign * sa,int pos)19 boolean is_gapped_SeqAlign(SeqAlign * sa,int pos)
20 {
21    int i;
22 
23    assert(sa != NULL);
24    assert(pos < sa->seq[0]->len);
25 
26    for(i=0;i<sa->len;i++) {
27      if( sa->seq[i]->seq[pos] == '.' ||
28          sa->seq[i]->seq[pos] == '-' ) {
29         return TRUE;
30      }
31   }
32 
33   return FALSE;
34 
35 }
36 
37 /* Function:  trim_from_N_SeqAlign(sa)
38  *
39  * Descrip:    trims sequence alignments to first and last
40  *             non N character (for DNA obviously)
41  *
42  *
43  * Arg:        sa [UNKN ] Undocumented argument [SeqAlign *]
44  *
45  * Return [UNKN ]  Undocumented return value [SeqAlign *]
46  *
47  */
48 # line 68 "seqalign.dy"
trim_from_N_SeqAlign(SeqAlign * sa)49 SeqAlign * trim_from_N_SeqAlign(SeqAlign * sa)
50 {
51   int i;
52   int j;
53   int k;
54   int left = 0;
55   int right = 0;
56 
57   SeqAlign * out;
58   Sequence * seq;
59 
60   char buffer[MAXLINE];
61 
62   assert(sa);
63   for(i=0;i<sa->len;i++) {
64     if( sa->seq[i]->len > left ) {
65      left = sa->seq[i]->len;
66     }
67   }
68 
69   for(i=0;i<sa->len;i++) {
70    for(j=0;j<sa->seq[i]->len;j++) {
71      if( sa->seq[i]->seq[j] != 'N' ) {
72        break;
73      }
74    }
75    if( left > j ) {
76      left = j;
77    }
78 
79    for(j=sa->seq[i]->len-1;j>=0;j--) {
80      if( sa->seq[i]->seq[j] != 'N' ) {
81        break;
82      }
83    }
84 
85    if ( right < j ) {
86      right = j;
87    }
88 
89   }
90 
91 
92   right++;
93   /* now we have left and right, make new sa */
94 
95   out = SeqAlign_alloc_len(sa->len);
96 
97   for(i=0;i<sa->len;i++) {
98    seq = Sequence_alloc();
99    add_SeqAlign(out,seq);
100    seq->name = stringalloc(sa->seq[i]->name);
101 
102    for(j=left,k=0;j<right && j<sa->seq[i]->len;j++,k++) {
103      buffer[k] = sa->seq[i]->seq[j];
104    }
105    for(;j<right;j++,k++) {
106      buffer[k] = 'N';
107    }
108    buffer[k] = '\0';
109 
110    seq->seq = stringalloc(buffer);
111    seq->len = k;
112    seq->type = SEQUENCE_DNA;
113  }
114 
115 
116  return out;
117 
118 }
119 
120 /* Function:  reweight_SeqAlign(sal)
121  *
122  * Descrip:    Provides reweighting for a seqalign so all the weights
123  *             add up to 1.0
124  *
125  *
126  * Arg:        sal [UNKN ] Undocumented argument [SeqAlign *]
127  *
128  */
129 # line 143 "seqalign.dy"
reweight_SeqAlign(SeqAlign * sal)130 void reweight_SeqAlign(SeqAlign * sal)
131 {
132   int i;
133   double total =0.0;
134 
135   for(i=0;i<sal->len;i++) {
136     total += sal->seq[i]->weight;
137   }
138 
139   for(i=0;i<sal->len;i++) {
140     sal->seq[i]->weight = sal->seq[i]->weight/ total;
141   }
142 
143 
144 }
145 
146 /* Function:  ColumnCount_from_SeqAlign(sa,col)
147  *
148  * Descrip:    Gives you a column count
149  *
150  *             You are supposed to have enough sense to
151  *             cache this on the caller if you need it again
152  *
153  *
154  * Arg:         sa [UNKN ] Undocumented argument [SeqAlign *]
155  * Arg:        col [UNKN ] Undocumented argument [int]
156  *
157  * Return [UNKN ]  Undocumented return value [ColumnCount *]
158  *
159  */
160 # line 165 "seqalign.dy"
ColumnCount_from_SeqAlign(SeqAlign * sa,int col)161 ColumnCount * ColumnCount_from_SeqAlign(SeqAlign * sa,int col)
162 {
163   ColumnCount * out;
164   double count[27] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
165 		       0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
166 		       0.0, 0.0, 0.0, 0.0, 0.0, 0.0 , 0.0};
167   int i;
168 
169   if( sa == NULL || sa->seq[0]->len < col ) {
170     warn("Cannot make column count at %d - out of range/seqalign null",col);
171     return NULL;
172   }
173 
174   for(i=0;i<sa->len;i++) {
175 
176     if( sa->seq[i]->len < col ) {
177       warn("For seqalign sequence %d (%s), although first seq ok, this doesn't extend to %d. Error.",i,sa->seq[i]->name,col);
178       return NULL;
179     }
180     if ( isalpha(sa->seq[i]->seq[col]) ) {
181       count[toupper(sa->seq[i]->seq[col]) - 'A']++;
182     } else {
183       count[26]++;
184     }
185 
186   }
187 
188   out = ColumnCount_alloc();
189   for(i=0;i<27;i++)
190     out->count[i] = count[i];
191 
192   return out;
193 }
194 
195 /* Function:  write_selex_SeqAlign(sa,name_len,block_len,ofp)
196  *
197  * Descrip:    Writes selex format
198  *
199  *
200  * Arg:               sa [UNKN ] Undocumented argument [const SeqAlign *]
201  * Arg:         name_len [UNKN ] Undocumented argument [int]
202  * Arg:        block_len [UNKN ] Undocumented argument [int]
203  * Arg:              ofp [UNKN ] Undocumented argument [FILE *]
204  *
205  * Return [UNKN ]  Undocumented return value [boolean]
206  *
207  */
208 # line 202 "seqalign.dy"
write_selex_SeqAlign(const SeqAlign * sa,int name_len,int block_len,FILE * ofp)209 boolean write_selex_SeqAlign(const SeqAlign * sa,int name_len,int block_len,FILE * ofp)
210 {
211   int col;
212   int i;
213   int j;
214   int k;
215 
216   assert(sa);
217   assert(ofp);
218   assert(name_len > 1);
219   assert(block_len > 1);
220 
221 
222   for(col=0;col<sa->seq[0]->len;) {
223     for(j=0;j<sa->len;j++) {
224       assert(sa->seq[j]->name);
225 
226       for(k=0;k<name_len && sa->seq[j]->name[k] != '\0';k++) {
227 	fputc(sa->seq[j]->name[k],ofp);
228       }
229       if( sa->seq[j]->name[k] == '\0' && k >= name_len ) {
230 	warn("In printing selex alignment, name %s is truncated at %d",sa->seq[j]->name,k);
231       }
232 
233       /* put in the rest of k */
234       for(;k<name_len;k++)
235 	fputc(' ',ofp);
236 
237       /* add one space */
238       fputc(' ',ofp);
239 
240       /* do the block */
241 
242       assert(sa->seq[j]->seq);
243 
244       for(i=col;(i - col) < block_len && i < sa->seq[j]->len ; i++) {
245 	fputc(sa->seq[j]->seq[i],ofp);
246       }
247       fputc('\n',ofp);
248     } /* end over all sequences for this block */
249 
250     col += block_len;
251     fprintf(ofp,"\n\n");
252   }
253 
254   return TRUE;
255 }
256 
257 /* Function:  read_fasta_SeqAlign_file(filename)
258  *
259  * Descrip:    Reads in fasta file opening the file
260  *
261  *
262  * Arg:        filename [UNKN ] Undocumented argument [char *]
263  *
264  * Return [UNKN ]  Undocumented return value [SeqAlign *]
265  *
266  */
267 # line 253 "seqalign.dy"
read_fasta_SeqAlign_file(char * filename)268 SeqAlign * read_fasta_SeqAlign_file(char * filename)
269 {
270   FILE * ifp;
271   SeqAlign * out;
272 
273   ifp = openfile(filename,"r");
274   if( ifp == NULL ) {
275     warn("Cannot open file %s",filename);
276     return NULL;
277   }
278 
279   out = read_fasta_SeqAlign(ifp);
280 
281   fclose(ifp);
282 
283   return out;
284 }
285 
286 /* Function:  read_fasta_SeqAlign(ifp)
287  *
288  * Descrip:    Reads in fasta file style alignments
289  *
290  *
291  * Arg:        ifp [UNKN ] Undocumented argument [FILE *]
292  *
293  * Return [UNKN ]  Undocumented return value [SeqAlign *]
294  *
295  */
296 # line 274 "seqalign.dy"
read_fasta_SeqAlign(FILE * ifp)297 SeqAlign * read_fasta_SeqAlign(FILE * ifp)
298 {
299   Sequence * seq;
300   SeqAlign * out;
301 
302   out = SeqAlign_alloc_std();
303 
304   while( (seq = read_fasta_Sequence(ifp)) != NULL ) {
305     fprintf(stderr,"Adding sequence %s\n",seq->name);
306     add_SeqAlign(out,seq);
307   }
308 
309   /* in multi-fasta alignments, this indicates the end */
310   if( out->len == 0 ) {
311     free_SeqAlign(out);
312     return NULL;
313   }
314 
315   return out;
316 }
317 
318 /* Function:  write_fasta_SeqAlign(sa,ofp)
319  *
320  * Descrip:    writes out Fasta file
321  *
322  *
323  * Arg:         sa [UNKN ] Undocumented argument [SeqAlign *]
324  * Arg:        ofp [UNKN ] Undocumented argument [FILE *]
325  *
326  */
327 # line 298 "seqalign.dy"
write_fasta_SeqAlign(SeqAlign * sa,FILE * ofp)328 void write_fasta_SeqAlign(SeqAlign * sa,FILE * ofp)
329 {
330   int i;
331 
332   for(i=0;i<sa->len;i++) {
333     write_fasta_Sequence(sa->seq[i],ofp);
334   }
335 }
336 
337 /* Function:  read_selex_SeqAlign_file(filename)
338  *
339  * Descrip:    Open files as well
340  *
341  *
342  * Arg:        filename [UNKN ] Undocumented argument [char *]
343  *
344  * Return [UNKN ]  Undocumented return value [SeqAlign *]
345  *
346  */
347 # line 310 "seqalign.dy"
read_selex_SeqAlign_file(char * filename)348 SeqAlign * read_selex_SeqAlign_file(char * filename)
349 {
350   FILE * ifp;
351   SeqAlign * out;
352 
353   ifp = openfile(filename,"r");
354   if( ifp == NULL ) {
355     warn("Cannot open file %s",filename);
356     return NULL;
357   }
358 
359   out = read_selex_SeqAlign(ifp);
360 
361   fclose(ifp);
362 
363   return out;
364 }
365 
366 
367 /* Function:  read_selex_SeqAlign(ifp)
368  *
369  * Descrip:    Reads in selex (Stockholm) alignment
370  *
371  *             At the moment ignores all #= stuff on the
372  *             sequence
373  *
374  *             Read HMMER documentation for a definition of
375  *             the format
376  *
377  *
378  * Arg:        ifp [UNKN ] Undocumented argument [FILE *]
379  *
380  * Return [UNKN ]  Undocumented return value [SeqAlign *]
381  *
382  */
383 # line 338 "seqalign.dy"
read_selex_SeqAlign(FILE * ifp)384 SeqAlign * read_selex_SeqAlign(FILE * ifp)
385 {
386   char buffer[4096];
387   SeqAlign * out;
388   Sequence * temp;
389   int i;
390   boolean isfirst;
391   boolean isfseq;
392   boolean isend;
393   char * name;
394   char * seq;
395   char * strip;
396   int pos;
397 
398   out = SeqAlign_alloc_std();
399 
400   while( fgets(buffer,4096,ifp) != NULL ) {
401     /*fprintf(stderr,"(selex) reading %s in selex alignment\n",buffer);*/
402     if( buffer[0] == '#' )
403       continue; /* skips over # */
404     if( buffer[0] == '/' && buffer[1] == '/' )
405       break;
406     if( !isspace(buffer[0]) ) {
407       /** in a block **/
408 
409       i = 0; /* this is the first sequence */
410       if( out->len == 0 ) {
411 	isfirst = TRUE;
412 	isfseq  = TRUE;
413       } else {
414 	isfirst = FALSE;
415 	isfseq  = FALSE;
416       }
417 
418       for(;;) {
419 	/* strip trailing white space */
420 
421 	for(strip = buffer + strlen(buffer) - 1;
422 	    strip > buffer && isspace(*strip);strip--)
423 	  ;
424 
425         strip++;
426 	*strip = '\0';
427 
428 	for(name = seq = buffer;!isspace(*seq) && *seq; seq++)
429 	  ;
430 
431 	/** if '\0' - worry **/
432 
433 	if( !*seq ) {
434 	  warn("For name %s in selex alignment, no sequence!",name);
435 	  return out;
436 	}
437 	*seq = '\0';
438 	if( isfirst == TRUE ) {
439 	  temp = empty_Sequence_from_dynamic_memory(stringalloc(name));
440 	  add_SeqAlign(out,temp);
441 	} else {
442 	  if ( i >= out->len ) {
443 	    warn("For sequence %s, got over previous blocks size",name);
444 	    return NULL;
445 	  }
446 
447 	  temp = out->seq[i++];
448 	}
449 
450 	/* if is fseq, then find the next character */
451 
452 	if( isfseq == TRUE ) {
453 	  for(seq++;*seq && isspace(*seq);seq++)
454 	    ;
455 	  if( *seq == '\0' ) {
456 	    warn("In first sequence %s, got to end of line with no sequence!",name);
457 	    return NULL;
458 	  }
459 
460 	  isfseq = FALSE;
461 	  pos = seq - buffer;
462 	}
463 	/* else pos is as normal */
464 
465 	/* map all non alnum chars to '-' */
466 
467 	for(seq = buffer+pos;*seq;seq++) {
468 	  if( !isalnum(*seq) ) {
469 	    *seq = '-';
470 	  }
471 	}
472 
473 	/* add to sequence */
474 	add_string_to_Sequence(temp,buffer+pos);
475 	/* get next line */
476 
477 	while( (seq = fgets(buffer,4096,ifp)) != NULL ) {
478 	  /*fprintf(stderr,"(selex - 2nd loop) reading %s in selex alignment\n",buffer);*/
479 	  if( buffer[0] != '#' )
480 	    break;
481 
482 	  if( buffer[0] == '/' && buffer[1] == '/' )
483 	    break;
484 
485 	}
486 
487 	/*fprintf(stderr,"Broken from second loop\n");*/
488 
489 	if( seq == NULL ) {
490 	  /*fprintf(stderr,"End of sequence?\n");*/
491 	  isend = TRUE;
492 	  break;
493 	}
494 
495 	if( buffer[0] == '/' && buffer[1] == '/' ) {
496 	  /*fprintf(stderr,"double slash terminator?\n");*/
497 	  isend = TRUE;
498 	  break;
499 	}
500 
501 	/* if it is blank, break out of block */
502 	if( !isalnum(buffer[0]) ) {
503 	  /*fprintf(stderr,"Back to loop?\n");*/
504 	  break;
505 	}
506 
507       }
508 
509       if( isend == TRUE )
510 	break;
511     } /* end of was a non space line */
512 
513     /* else - ignore it !*/
514 
515   }
516 
517   return out;
518 }
519 
520 
521 
522 
523 
524 # line 503 "seqalign.c"
525 /* Function:  swap_SeqAlign(list,i,j)
526  *
527  * Descrip:    swap function: an internal for qsort_SeqAlign
528  *             swaps two positions in the array
529  *
530  *
531  * Arg:        list [UNKN ] List of structures to swap in [Sequence **]
532  * Arg:           i [UNKN ] swap position [int]
533  * Arg:           j [UNKN ] swap position [int]
534  *
535  */
536 /* swap function for qsort function */
swap_SeqAlign(Sequence ** list,int i,int j)537 void swap_SeqAlign(Sequence ** list,int i,int j)
538 {
539     Sequence * temp;
540     temp=list[i];
541     list[i]=list[j];
542     list[j]=temp;
543 }
544 
545 
546 /* Function:  qsort_SeqAlign(list,left,right,comp)
547  *
548  * Descrip:    qsort - lifted from K&R
549  *             sorts the array using quicksort
550  *             Probably much better to call sort_SeqAlign which sorts from start to end
551  *
552  *
553  * Arg:         list [UNKN ] List of structures to swap in [Sequence **]
554  * Arg:         left [UNKN ] left position [int]
555  * Arg:        right [UNKN ] right position [int]
556  * Arg:         comp [FUNCP] Function which returns -1 or 1 to sort on [int (*comp]
557  *
558  */
qsort_SeqAlign(Sequence ** list,int left,int right,int (* comp)(Sequence *,Sequence *))559 void qsort_SeqAlign(Sequence ** list,int left,int right,int (*comp)(Sequence * ,Sequence * ))
560 {
561     int i,last;
562     if( left >= right )
563       return;
564 
565 
566     swap_SeqAlign(list,left,(left+right)/2);
567     last = left;
568     for ( i=left+1; i <= right;i++)  {
569       if( (*comp)(list[i],list[left]) < 0)
570         swap_SeqAlign (list,++last,i);
571       }
572     swap_SeqAlign (list,left,last);
573     qsort_SeqAlign(list,left,last-1,comp);
574     qsort_SeqAlign(list,last+1,right,comp);
575 }
576 
577 
578 /* Function:  sort_SeqAlign(obj,comp)
579  *
580  * Descrip:    sorts from start to end using comp
581  *             sorts the array using quicksort by calling qsort_SeqAlign
582  *
583  *
584  * Arg:         obj [UNKN ] Object containing list [SeqAlign *]
585  * Arg:        comp [FUNCP] Function which returns -1 or 1 to sort on [int (*comp]
586  *
587  */
sort_SeqAlign(SeqAlign * obj,int (* comp)(Sequence *,Sequence *))588 void sort_SeqAlign(SeqAlign * obj,int (*comp)(Sequence *, Sequence *))
589 {
590     qsort_SeqAlign(obj->seq,0,obj->len-1,comp);
591     return;
592 }
593 
594 
595 /* Function:  expand_SeqAlign(obj,len)
596  *
597  * Descrip:    Really an internal function for add_SeqAlign
598  *
599  *
600  * Arg:        obj [UNKN ] Object which contains the list [SeqAlign *]
601  * Arg:        len [UNKN ] Length to add one [int]
602  *
603  * Return [UNKN ]  Undocumented return value [boolean]
604  *
605  */
expand_SeqAlign(SeqAlign * obj,int len)606 boolean expand_SeqAlign(SeqAlign * obj,int len)
607 {
608 
609 
610     if( obj->maxlen > obj->len )     {
611       warn("expand_SeqAlign called with no need");
612       return TRUE;
613       }
614 
615 
616     if( (obj->seq = (Sequence ** ) ckrealloc (obj->seq,sizeof(Sequence *)*len)) == NULL)     {
617       warn("ckrealloc failed for expand_SeqAlign, returning FALSE");
618       return FALSE;
619       }
620     obj->maxlen = len;
621     return TRUE;
622 }
623 
624 
625 /* Function:  add_SeqAlign(obj,add)
626  *
627  * Descrip:    Adds another object to the list. It will expand the list if necessary
628  *
629  *
630  * Arg:        obj [UNKN ] Object which contains the list [SeqAlign *]
631  * Arg:        add [OWNER] Object to add to the list [Sequence *]
632  *
633  * Return [UNKN ]  Undocumented return value [boolean]
634  *
635  */
636 /* will expand function if necessary */
add_SeqAlign(SeqAlign * obj,Sequence * add)637 boolean add_SeqAlign(SeqAlign * obj,Sequence * add)
638 {
639     if( obj->len >= obj->maxlen) {
640       if( expand_SeqAlign(obj,obj->len + SeqAlignLISTLENGTH) == FALSE)
641         return FALSE;
642       }
643 
644 
645     obj->seq[obj->len++]=add;
646     return TRUE;
647 }
648 
649 
650 /* Function:  flush_SeqAlign(obj)
651  *
652  * Descrip:    Frees the list elements, sets length to 0
653  *             If you want to save some elements, use hard_link_xxx
654  *             to protect them from being actually destroyed in the free
655  *
656  *
657  * Arg:        obj [UNKN ] Object which contains the list  [SeqAlign *]
658  *
659  * Return [UNKN ]  Undocumented return value [int]
660  *
661  */
flush_SeqAlign(SeqAlign * obj)662 int flush_SeqAlign(SeqAlign * obj)
663 {
664     int i;
665 
666 
667     for(i=0;i<obj->len;i++)  { /*for i over list length*/
668       if( obj->seq[i] != NULL)   {
669         free_Sequence(obj->seq[i]);
670         obj->seq[i] = NULL;
671         }
672       } /* end of for i over list length */
673 
674 
675     obj->len = 0;
676     return i;
677 }
678 
679 
680 /* Function:  SeqAlign_alloc_std(void)
681  *
682  * Descrip:    Equivalent to SeqAlign_alloc_len(SeqAlignLISTLENGTH)
683  *
684  *
685  *
686  * Return [UNKN ]  Undocumented return value [SeqAlign *]
687  *
688  */
SeqAlign_alloc_std(void)689 SeqAlign * SeqAlign_alloc_std(void)
690 {
691     return SeqAlign_alloc_len(SeqAlignLISTLENGTH);
692 }
693 
694 
695 /* Function:  SeqAlign_alloc_len(len)
696  *
697  * Descrip:    Allocates len length to all lists
698  *
699  *
700  * Arg:        len [UNKN ] Length of lists to allocate [int]
701  *
702  * Return [UNKN ]  Undocumented return value [SeqAlign *]
703  *
704  */
SeqAlign_alloc_len(int len)705 SeqAlign * SeqAlign_alloc_len(int len)
706 {
707     SeqAlign * out; /* out is exported at the end of function */
708 
709 
710     /* Call alloc function: return NULL if NULL */
711     /* Warning message alread in alloc function */
712     if((out = SeqAlign_alloc()) == NULL)
713       return NULL;
714 
715 
716     /* Calling ckcalloc for list elements */
717     if((out->seq = (Sequence ** ) ckcalloc (len,sizeof(Sequence *))) == NULL)    {
718       warn("Warning, ckcalloc failed in SeqAlign_alloc_len");
719       return NULL;
720       }
721     out->len = 0;
722     out->maxlen = len;
723 
724 
725     return out;
726 }
727 
728 
729 /* Function:  hard_link_SeqAlign(obj)
730  *
731  * Descrip:    Bumps up the reference count of the object
732  *             Meaning that multiple pointers can 'own' it
733  *
734  *
735  * Arg:        obj [UNKN ] Object to be hard linked [SeqAlign *]
736  *
737  * Return [UNKN ]  Undocumented return value [SeqAlign *]
738  *
739  */
hard_link_SeqAlign(SeqAlign * obj)740 SeqAlign * hard_link_SeqAlign(SeqAlign * obj)
741 {
742     if( obj == NULL )    {
743       warn("Trying to hard link to a SeqAlign object: passed a NULL object");
744       return NULL;
745       }
746     obj->dynamite_hard_link++;
747     return obj;
748 }
749 
750 
751 /* Function:  SeqAlign_alloc(void)
752  *
753  * Descrip:    Allocates structure: assigns defaults if given
754  *
755  *
756  *
757  * Return [UNKN ]  Undocumented return value [SeqAlign *]
758  *
759  */
SeqAlign_alloc(void)760 SeqAlign * SeqAlign_alloc(void)
761 {
762     SeqAlign * out; /* out is exported at end of function */
763 
764 
765     /* call ckalloc and see if NULL */
766     if((out=(SeqAlign *) ckalloc (sizeof(SeqAlign))) == NULL)    {
767       warn("SeqAlign_alloc failed ");
768       return NULL;  /* calling function should respond! */
769       }
770     out->dynamite_hard_link = 1;
771 #ifdef PTHREAD
772     pthread_mutex_init(&(out->dynamite_mutex),NULL);
773 #endif
774     out->name = NULL;
775     out->seq = NULL;
776     out->len = out->maxlen = 0;
777 
778 
779     return out;
780 }
781 
782 
783 /* Function:  free_SeqAlign(obj)
784  *
785  * Descrip:    Free Function: removes the memory held by obj
786  *             Will chain up to owned members and clear all lists
787  *
788  *
789  * Arg:        obj [UNKN ] Object that is free'd [SeqAlign *]
790  *
791  * Return [UNKN ]  Undocumented return value [SeqAlign *]
792  *
793  */
free_SeqAlign(SeqAlign * obj)794 SeqAlign * free_SeqAlign(SeqAlign * obj)
795 {
796     int return_early = 0;
797     int i;
798 
799 
800     if( obj == NULL) {
801       warn("Attempting to free a NULL pointer to a SeqAlign obj. Should be trappable");
802       return NULL;
803       }
804 
805 
806 #ifdef PTHREAD
807     assert(pthread_mutex_lock(&(obj->dynamite_mutex)) == 0);
808 #endif
809     if( obj->dynamite_hard_link > 1)     {
810       return_early = 1;
811       obj->dynamite_hard_link--;
812       }
813 #ifdef PTHREAD
814     assert(pthread_mutex_unlock(&(obj->dynamite_mutex)) == 0);
815 #endif
816     if( return_early == 1)
817       return NULL;
818     if( obj->name != NULL)
819       ckfree(obj->name);
820     if( obj->seq != NULL)    {
821       for(i=0;i<obj->len;i++)    {
822         if( obj->seq[i] != NULL)
823           free_Sequence(obj->seq[i]);
824         }
825       ckfree(obj->seq);
826       }
827 
828 
829     ckfree(obj);
830     return NULL;
831 }
832 
833 
834 /* Function:  hard_link_ColumnCount(obj)
835  *
836  * Descrip:    Bumps up the reference count of the object
837  *             Meaning that multiple pointers can 'own' it
838  *
839  *
840  * Arg:        obj [UNKN ] Object to be hard linked [ColumnCount *]
841  *
842  * Return [UNKN ]  Undocumented return value [ColumnCount *]
843  *
844  */
hard_link_ColumnCount(ColumnCount * obj)845 ColumnCount * hard_link_ColumnCount(ColumnCount * obj)
846 {
847     if( obj == NULL )    {
848       warn("Trying to hard link to a ColumnCount object: passed a NULL object");
849       return NULL;
850       }
851     obj->dynamite_hard_link++;
852     return obj;
853 }
854 
855 
856 /* Function:  ColumnCount_alloc(void)
857  *
858  * Descrip:    Allocates structure: assigns defaults if given
859  *
860  *
861  *
862  * Return [UNKN ]  Undocumented return value [ColumnCount *]
863  *
864  */
ColumnCount_alloc(void)865 ColumnCount * ColumnCount_alloc(void)
866 {
867     ColumnCount * out;  /* out is exported at end of function */
868 
869 
870     /* call ckalloc and see if NULL */
871     if((out=(ColumnCount *) ckalloc (sizeof(ColumnCount))) == NULL)  {
872       warn("ColumnCount_alloc failed ");
873       return NULL;  /* calling function should respond! */
874       }
875     out->dynamite_hard_link = 1;
876 #ifdef PTHREAD
877     pthread_mutex_init(&(out->dynamite_mutex),NULL);
878 #endif
879     /* count[27] is an array: no default possible */
880 
881 
882     return out;
883 }
884 
885 
886 /* Function:  free_ColumnCount(obj)
887  *
888  * Descrip:    Free Function: removes the memory held by obj
889  *             Will chain up to owned members and clear all lists
890  *
891  *
892  * Arg:        obj [UNKN ] Object that is free'd [ColumnCount *]
893  *
894  * Return [UNKN ]  Undocumented return value [ColumnCount *]
895  *
896  */
free_ColumnCount(ColumnCount * obj)897 ColumnCount * free_ColumnCount(ColumnCount * obj)
898 {
899     int return_early = 0;
900 
901 
902     if( obj == NULL) {
903       warn("Attempting to free a NULL pointer to a ColumnCount obj. Should be trappable");
904       return NULL;
905       }
906 
907 
908 #ifdef PTHREAD
909     assert(pthread_mutex_lock(&(obj->dynamite_mutex)) == 0);
910 #endif
911     if( obj->dynamite_hard_link > 1)     {
912       return_early = 1;
913       obj->dynamite_hard_link--;
914       }
915 #ifdef PTHREAD
916     assert(pthread_mutex_unlock(&(obj->dynamite_mutex)) == 0);
917 #endif
918     if( return_early == 1)
919       return NULL;
920 
921 
922     ckfree(obj);
923     return NULL;
924 }
925 
926 
927 
928 #ifdef _cplusplus
929 }
930 #endif
931