JPRED-2 Add sources of all binaries (except alscript) to Git
[jpred.git] / sources / oc / gjutil.c
1
2 /****************************************************************************
3
4 gjutil.c:  Various utility routines - error checking malloc and
5 free, string functions etc...
6
7 Copyright:  Geoffrey J. Barton  (1992, 1993, 1995, 1997)
8 email: geoff@ebi.ac.uk
9
10 This software is made available for educational and non-commercial research 
11 purposes.
12
13 For commercial use, a commercial licence is required - contact the author
14 at the above address for details.
15
16
17 ******************************************************************************/
18 #include <stdio.h>
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <time.h>
25
26 #include "gjtimes.h"
27 #include "gjutil.h"
28
29 /* define pointers for standard streams to allow redefinition to files */
30
31 FILE *std_err;
32 FILE *std_in;
33 FILE *std_out;
34
35 /* clock externs */
36 clock_t start_time, end_time,initial_time,final_time;
37
38 void *GJmalloc(size_t size)
39 /* malloc with simple error check */
40 /* G. J. Barton 1992 */
41 {
42         void *ptr;
43         ptr = (void *) malloc(size);
44         if(ptr == NULL){
45                 GJerror("malloc error");
46                 exit(0);
47         }
48         return ptr;
49 }
50
51 void *GJrealloc(void *ptr,size_t size)
52 /* realloc with error check */
53 /* G. J. Barton 1992 */
54 {
55         ptr = (void *) realloc(ptr,size);
56         if(ptr == NULL){
57                 GJerror("realloc error");
58                 exit(0);
59         }
60         return ptr;
61 }
62 void *GJmallocNQ(size_t size)
63 /* as for GJmalloc, but returns NULL on error*/
64 /* G. J. Barton 1992 */
65 {
66         void *ptr;
67         ptr = (void *) malloc(size);
68         if(ptr == NULL){
69                 GJerror("malloc error");
70                 return NULL;
71         }
72         return ptr;
73 }
74
75 void *GJreallocNQ(void *ptr,size_t size)
76 /* as for GJrealloc with error check but returns NULL on error*/
77 /* G. J. Barton 1992 */
78 {
79         ptr = (void *) realloc(ptr,size);
80         if(ptr == NULL){
81                 GJerror("realloc error");
82                 return NULL;
83         }
84         return ptr;
85 }
86 void GJfree(void *ptr)
87 /* free with error check */
88 /* G. J. Barton 1992 */
89 {
90         if(ptr == NULL){
91                 GJerror("Attempt to free NULL pointer");
92                 exit(0);
93         }
94         free(ptr);
95 }
96
97 void GJerror(const char *prefix)
98 /* writes error message contained in prefix and contents of errno
99    to std_err.
100 */
101 /* G. J. Barton 1992 */
102 {
103         if(prefix != NULL){
104                 if(*prefix != '\0'){
105                         fprintf(std_err,"%s: ",prefix);
106                 }
107         }
108         fprintf(std_err,"%s\n",strerror(errno));
109 }
110
111 /*
112 error:   calls GJerror 
113 */
114 void error(const char *str,int flag)
115 {
116     GJerror(str);
117     if(flag)exit(0);
118 }
119
120
121 char *GJstoupper(const char *s)
122 /* return a copy of s in upper case */
123 /* G. J. Barton 1992 */
124 {
125         char *temp;
126         int i;
127         temp = GJstrdup(s);
128         i=0;
129         while(temp[i] != '\0'){
130                 temp[i] = toupper(temp[i]);
131                 ++i;
132         }
133         return temp;
134 }
135 char *GJstolower(const char *s)
136 /* return a copy of s in lower case */
137 /* G. J. Barton 1992 */
138 {
139         char *temp;
140         int i;
141         temp = GJstrdup(s);
142         i=0;
143         while(temp[i] != '\0'){
144                 temp[i] = tolower(temp[i]);
145                 ++i;
146         }
147         return temp;
148 }
149 char *GJstoup(char *s)
150 /* return s in upper case */
151 /* G. J. Barton 1992 */
152 {
153         int i;
154         i=0;
155         while(s[i] != '\0'){
156                 s[i] = toupper(s[i]);
157                 ++i;
158         }
159         return s;
160 }
161 char *GJstolo(char *s)
162 /* return s in lower case */
163 /* G. J. Barton 1992 */
164 {
165         int i;
166         i=0;
167         while(s[i] != '\0'){
168                 s[i] = tolower(s[i]);
169                 ++i;
170         }
171         return s;
172 }  
173
174 char *GJstrdup(const char *s)
175 /* returns a pointer to a copy of string s */
176 /* G. J. Barton 1992 */
177
178 {
179         char *temp;
180         temp = (char *) GJmalloc(sizeof(char) * (strlen(s)+1));
181         temp = strcpy(temp,s);
182         return temp;
183 }
184
185 char *GJstrrename(char *old,const char *new)
186 /* takes old which is a pointer to a string, then replaces the contents
187    of the string with new, reallocating to the correct size
188 */ 
189 {
190   int nlen;
191   nlen = strlen(new);
192   old = (char *) GJrealloc(old,sizeof(char) * (nlen + 1));
193   old = strcpy(old,new);
194   return old;
195 }
196   
197
198
199 FILE *GJfopen(const char *fname,const char *type,int action)
200 /* a file open function with error checking.  The third argument
201 is set to 0 if we want a failed open to return, or 1 if we
202 want a failed open to exit the program.
203 */
204 /* G. J. Barton 1992 */
205 /* modified July 1995 - error message only printed if action is 1 */
206 {
207         FILE *ret_val;
208         ret_val = fopen(fname,type);
209         if(ret_val == NULL){
210           /*      GJerror(strcat("Cannot Open File: ",fname));*/
211                 if(action == 1){
212                   GJerror(strcat("Cannot Open File: ",fname));
213                   exit(1);
214                 }
215         }
216         return ret_val;
217 }
218
219 int GJfclose(FILE *fp,int action)
220 /* a file close function with error checking.  The second argument
221 is set to 0 if we want a failed close to return, or 1 if we
222 want a failed close to exit the program.
223 */
224 /* G. J. Barton 1992 */
225 {
226         int ret_val;
227         ret_val = fclose(fp);
228         if(ret_val != 0){
229                 if(action == 1){
230                         GJerror("Error closing File");
231                         exit(1);
232                 }
233         }
234         return ret_val;
235 }
236
237
238 GJFILE *GJfilemake(const char *name,const char *type,int action)
239 /* If action = 1 then 
240 Tries to open the file with the given name.  If successful returns 
241 a pointer to a struct file structure with the name and filehandle.  If
242 the open fails, or action= 0 then returns a struct file structure 
243 with the name and a NULL filehandle */
244 /* G. J. Barton 1995 */
245 {
246         GJFILE *ret_val;
247         ret_val = (GJFILE *) GJmalloc(sizeof(GJFILE));
248         ret_val->name = GJstrdup(name);
249         if(action == 1) {
250           ret_val->handle = GJfopen(ret_val->name,type,0);
251         }else if(action == 0){
252           ret_val->handle = NULL;
253         }
254         return ret_val;
255 }
256
257 GJFILE *GJfilerename(GJFILE *ret_val, const char *name)
258 /* When passed the fval structure - renames the name part of the
259 file structure to name, if the handle is non null it tries to close 
260 the file, then sets the file handle to NULL. */
261 /* G. J. Barton 1995 */
262 {
263         if(ret_val->name != NULL) {
264           GJfree(ret_val->name);
265           ret_val->name = GJstrdup(name);
266         }
267         if(ret_val->handle != NULL) {
268           GJfclose(ret_val->handle,0);
269           ret_val->handle = NULL;
270         }
271         return ret_val;
272 }
273
274 GJFILE *GJfileclose(GJFILE *ret_val,int action)
275 /* Closes a file named in the  struct file structure returns the struct
276  file structure */
277
278 /* G. J. Barton July 1995 */
279 {
280         STD_FILES;
281
282         if(GJfclose(ret_val->handle,0) == 0){
283           return ret_val;
284         }else {
285           if(action == 1){
286             GJerror("Error closing File");
287             fprintf(std_err,"%s\n",ret_val->name);
288             exit(-1);
289           }
290         }
291         return ret_val;  
292 }
293
294 GJFILE *GJfileopen(GJFILE *ret_val,const char *type,int action)
295 /* Opens a file named in the  struct file structure */
296
297 /* G. J. Barton October 1995 */
298 {
299         STD_FILES;
300
301         ret_val->handle = GJfopen(ret_val->name,type,0);
302         if(ret_val->handle == NULL){
303                 if(action == 1){
304                         GJerror("Error opening File");
305                         fprintf(std_err,"%s\n",ret_val->name);
306                         exit(-1);
307                 }
308         }
309         return ret_val;  
310 }
311
312 GJFILE *GJfileclean(GJFILE *ret_val,int action)
313 /*  Closes the file then sets the file pointer to NULL, then 
314     frees the filename string */
315
316 /* G. J. Barton July 1995 */
317 {
318   if(GJfclose(ret_val->handle,0) == 0) {
319     ret_val->handle = NULL;
320     GJfree(ret_val->name);
321     return ret_val;
322   }else {
323     if(action == 1){
324       GJerror("Error closing File");
325       fprintf(std_err,"%s\n",ret_val->name);
326       exit(-1);
327     }
328   }
329   return ret_val;
330 }
331
332 void GJinitfile(void)
333 /* just set the standard streams */
334 {
335         std_err = stderr;
336         std_in = stdin;
337         std_out = stdout;
338 }
339
340 char *GJfnonnull(char *string)
341 /* return pointer to first non null character in the string */
342 /* this could cause problems if the string is not null terminated */
343 {
344         while(*string != '\0'){
345                 ++string;
346         }
347         return ++string;
348 }
349
350 char *GJstrappend(char *string1, char *string2)
351 /* appends string2 to the end of string2.  Any newline characters are removed
352 from string1, then the first character of string2 overwrites the null at the
353 end of string1.
354 string1 and string2 must have been allocated with malloc.
355 */
356 /* G. J. Barton July 1992 */
357 {
358         char *ret_val;
359         ret_val = GJremovechar(string1,'\n');
360         ret_val = (char *) GJrealloc(ret_val,
361                            sizeof(char) * (strlen(ret_val) + strlen(string2) + 1));
362         ret_val = strcat(ret_val,string2);
363         return ret_val;
364 }
365
366 char *GJremovechar(char *string,char c)
367 /* removes all instances of character c from string
368    returns a pointer to the reduced, null terminated string
369    11/8/1996:  couple of bugs found in this routine.
370    the length of the string returned was too short by 2 bytes.
371    This is a dodgy routine since string is freed.
372 */
373 /* G. J. Barton (July 1992) */
374 {
375         char *temp;
376         int j,i,nchar;
377         nchar = 0;
378         i=0;
379         while(string[i] != '\0'){
380                 if(string[i] == c){
381                         ++nchar;
382                 }
383                 ++i;
384         }
385         if(nchar == 0){
386                  return string;
387         }else{
388                 temp = (char *) GJmalloc(sizeof(char) * (strlen(string)-nchar + 1));
389                 j=0;
390                 i=0;
391                 while(string[i] != '\0'){
392                         if(string[i] != c){
393                                 temp[j] = string[i];
394                                 ++j;
395                         }
396                         ++i;
397                 }
398                 temp[j] = '\0';
399                 GJfree(string);
400                 return temp;
401         }
402 }
403
404 char *GJremovechar2(char *string,char c)
405 /* removes all instances of character c from string
406    returns a pointer to the reduced, null terminated string
407 */
408 /* G. J. Barton (July 1992) */
409 {
410         char *temp;
411         int i,k,len;
412         k=0;
413         len=strlen(string);
414         temp = (char *) GJmalloc(sizeof(char) * (len+1));
415         for(i=0;i<(len+1);++i){
416           if(string[i] != c){
417             temp[k] = string[i];
418             ++k;
419           }
420         }
421         for(i=0;i<(strlen(temp)+1);++i){
422           string[i] = temp[i];
423         }
424         GJfree(temp);
425         return string;
426 }
427
428
429 char *GJsubchar(char *string,char c2,char c1)
430 /* substitutes c1 for c2 in string
431 */
432 /* G. J. Barton (July 1992) */
433 {
434         int i;
435
436         i=0;
437         while(string[i] != '\0'){
438                 if(string[i] == c1){
439                     string[i] = c2;
440                 }
441                 ++i;
442         }
443         return string;
444 }
445
446 /* create a string and if fchar != NULL fill with characters  */
447 /* always set the len-1 character to '\0' */
448
449 char *GJstrcreate(size_t len,char *fchar)
450 {
451         char *ret_val;
452         ret_val = (char *) GJmalloc(sizeof(char) * len);
453         --len;
454         ret_val[len] = '\0';
455         if(fchar != NULL){
456                 while(len > -1){
457                         ret_val[len] = *fchar;
458                         --len;
459                 }
460         }
461         return ret_val;
462 }
463
464 /* searches for string s2 in string s1 and returns pointer to first instance
465 of s2 in s1 or NULL if no instance found.  s1 and s2 must be null terminated
466 */              
467 char *GJstrlocate(char *s1, char *s2)
468 {
469     int i=0;
470     int j=0;
471     int k;
472     if(strlen(s1) == 0 || strlen(s2) == 0) return NULL;
473     while(i < strlen(s1)){
474         j=0;
475         k=i;
476         while(j < strlen(s2) && s1[k] == s2[j]){
477                 ++k;
478                 ++j;
479         }
480         if(j == strlen(s2)) return &s1[i];
481         ++i;
482     }
483     return NULL;
484 }
485 #include <stdlib.h>
486 #include <string.h>
487
488
489 /* GJstrtok()
490
491 This version of strtok places the work pointer at the location of the first 
492 character in the next token, rather than just after the last character of the 
493 current token.  This is useful for extracting quoted strings 
494 */
495
496 char *GJstrtok(char *input_string,const char *token_list)
497 {
498   static char *work;
499   char *return_ptr;
500
501   if(input_string != NULL){
502     /* first call */
503     work =  input_string;
504   }
505
506   /* search for next non-token character */
507   while(strchr(token_list,*work)!=NULL){
508     ++work;
509   }
510
511   if(*work == '\0'){
512     /* if we've reached the end of string, then return NULL */
513     return NULL;
514   }else{
515     return_ptr = (char *) work;
516     while(strchr(token_list,*work) == NULL){
517       if(*work == '\0'){
518         /* end of the string */
519         return return_ptr;
520       }else{
521         ++work;
522       }
523     }
524     *work = '\0';
525     ++work;
526     /* now increment work until we find the next non-delimiter character */
527     while(strchr(token_list,*work) != NULL){
528       if(*work == '\0'){
529         break;
530       }else{
531         ++work;
532       }
533     }
534     return return_ptr;
535   }
536 }
537 /**************************************************************************
538 return a pointer to space for a rectangular unsigned character array
539 Version 2.0  ANSI and uses GJmallocNQ
540 --------------------------------------------------------------------------*/
541
542 unsigned char **uchararr(int i,int j)
543 {
544     unsigned char **temp;
545     int k, rowsiz;
546
547     temp = (unsigned char **) GJmallocNQ(sizeof(unsigned char *) * i);
548     if(temp == NULL) return NULL;
549
550     rowsiz = sizeof(unsigned char) * j;
551
552     for (k = 0; k < i; ++k){
553         temp[k] =  (unsigned char *) GJmallocNQ(rowsiz);
554         if(temp[k] == NULL) return NULL;
555     }
556     return temp;
557 }
558
559 /**************************************************************************
560 free up space pointed to by rectangular unsigned character array
561 -------------------------------------------------------------------------*/
562 void ucharfree(unsigned char **array,int i)
563
564 {
565     int k;
566
567     for (k = 0; k < i; ++k){
568         GJfree((char *) array[k]);
569     }
570     GJfree((char *) array);
571
572 }
573
574 /**************************************************************************
575 return a pointer to space for a rectangular signed character array
576 Version 2.0  ANSI
577 --------------------------------------------------------------------------*/
578 signed char **chararr(int i,int j)
579
580 {
581     signed char **temp;
582     int k, rowsiz;
583
584     temp = (signed char **) GJmallocNQ(sizeof(char *) * i);
585
586     if(temp == NULL) return NULL;
587
588     rowsiz = sizeof(char) * j;
589
590     for (k = 0; k < i; ++k){
591         temp[k] =  (signed char *) GJmallocNQ(rowsiz);
592         if(temp[k] == NULL) return NULL;
593     }
594     return temp;
595 }
596
597
598 /* mcheck - check a call to malloc - if the call has failed, print the
599 error message and exit the program */
600 /* ANSI Version - also uses GJerror routine and ptr is declared void*/
601
602 void mcheck(void *ptr,char *msg)
603
604 {
605     if(ptr == NULL){
606         GJerror("malloc/realloc error");
607         exit(0);
608     }
609 }
610
611 /* set a string to blanks and add terminating nul */
612 char *GJstrblank(char *string,int len)
613
614 {
615   --len;
616   string[len] = '\0';
617   --len;
618   while(len > -1){
619     string[len] = ' ';
620     --len;
621   }
622   return string;
623 }
624
625 /* Initialise an unsigned char array */  
626 void GJUCinit(unsigned char **array,int i,int j,unsigned char val)
627 {
628   int k,l;
629
630   for(k=0;k<i;++k){
631     for(l=0;l<j;++l){
632       array[k][l] = val;
633     }
634   }
635 }
636 /*Initialise a signed char array */
637
638 void GJCinit(signed char **array,int i,int j,char val)
639
640 {
641   int k,l;
642
643   for(k=0;k<i;++k){
644     for(l=0;l<j;++l){
645       array[k][l] = val;
646     }
647   }
648 }
649
650 /* Initialise an integer vector  */  
651 void GJIinit(int *array,int i,int val)
652 {
653   int k;
654
655   for(k=0;k<i;++k){
656       array[k] = val;
657   }
658 }
659
660 /******************************************************************
661 GJcat:  concatenate N NULL terminated strings into a single string.
662 The source strings are not altered
663 Author: G. J. Barton (Feb 1993)
664 ------------------------------------------------------------------*/
665 char *GJcat(int N,...)
666 {
667         va_list parminfo;
668         int i,j,k;
669         char **values;  /*input strings */
670         int *value_len; /*lengths of input strings */
671         int ret_len;    /*length of returned string */
672         char *ret_val;  /*returned string */
673
674         ret_len = 0;
675         values = (char **) GJmalloc(sizeof(char *) * N);
676         value_len = (int *) GJmalloc(sizeof(int *) * N);
677
678         va_start(parminfo,N);
679
680         /* Get pointers and lengths for the N arguments */
681         for(i=0;i<N;++i){
682                 values[i] = va_arg(parminfo,char *);
683                 value_len[i] = strlen(values[i]);
684                 ret_len += value_len[i];
685         }
686         
687         ret_val = (char *) GJmalloc(sizeof(char) * (ret_len+1));
688
689         /* Transfer input strings to output string */
690         k=0;
691         for(i=0;i<N;++i){
692                 for(j=0;j<value_len[i];++j){
693                         ret_val[k] = values[i][j];
694                         ++k;
695                 }
696         }
697         ret_val[k] = '\0';
698         GJfree(values);
699         GJfree(value_len);
700
701         va_end(parminfo);
702
703         return ret_val;
704 }
705
706 /************************************************************************
707
708 GJGetToken:
709
710 The aim of this routine is to emulate the strtok() function, but reading
711 from a file.  The functionality may differ slightly...
712
713 Characters are read from the file until a character that is found in
714 delim is encountered.  When this occurs, token is returned.  If the
715 file consists entirely of delimiters, then token is freed
716 and NULL is returned.  Similarly, if end of file is encountered.
717
718 ------------------------------------------------------------------------*/
719
720
721 char *GJGetToken(FILE *in, const char *delim)
722
723 {
724         int i;
725         int c;
726         char *token;
727
728         i=0;
729
730         token = GJmalloc(sizeof(char));
731         
732         while((c=fgetc(in)) != EOF){
733                 if(strchr(delim,c) == NULL){
734                         /* not a delimiter */
735                         token[i++] = c;
736                         token = GJrealloc(token,sizeof(char) * (i+1));
737                 }else if(i>0){
738                         token[i] = '\0';
739                         return token;
740                 }
741         }
742 /*      GJerror("End of File Encountered");*/
743         GJfree(token);
744         return NULL;
745 }
746
747 struct tokens *GJgettokens(const char *delims, char *buff)
748 /* This splits a buffer into tokens at each position defined by delims.*/
749 /* The structure returned contains the number of tokens and the */
750 /* tokens themselves as a char ** array */
751 {
752   char *token;
753   struct tokens *tok;
754
755   token = strtok(buff,delims);
756   if(token == NULL) return NULL;
757
758   tok = (struct tokens *) GJmalloc(sizeof(struct tokens));
759   tok->ntok = 0;
760   tok->tok = (char **) GJmalloc(sizeof(char *));
761   tok->tok[0] = GJstrdup(token);
762   ++tok->ntok;
763   while((token = strtok(NULL,delims)) != NULL) {
764       tok->tok = (char **) GJrealloc(tok->tok,sizeof(char *) * (tok->ntok+1));
765       tok->tok[tok->ntok] = GJstrdup(token);
766       ++tok->ntok;
767   }
768   
769   return tok;
770 }
771
772 void GJfreetokens(struct tokens *tok)
773 /* frees a tokens structure */
774
775 {
776   int i;
777   for(i=0;i<tok->ntok;++i) {
778     GJfree(tok->tok[i]);
779   }
780   GJfree(tok->tok);
781   GJfree(tok);
782   tok = NULL;   /* add this to avoid odd pointer 27/6/1997*/
783 }
784
785 char * GJtoktostr(struct tokens *tok,char delim,int s, int e)
786
787 /* 
788    returns a string with the tokens between s and e inclusive written to 
789    it separated by delim 
790    the tok structure is unmodified.
791 */
792
793 {
794   int n, i, j,k;
795   char *ret_val;
796
797   n = 0;
798
799
800   if(s < 0 || s >= tok->ntok) s = 0;
801   if(e < 0 || e >= tok->ntok) e = tok->ntok - 1;
802
803   for(i=s;i<=e;++i){
804     n += strlen(tok->tok[i]);
805     ++n;
806   }
807
808   ret_val = (char *) GJmalloc(sizeof(char) * n);
809   j = 0;
810   for(i=s;i<=e;++i){
811     for(k=0;k<strlen(tok->tok[i]);++k){
812       ret_val[j] = tok->tok[i][k];
813       ++j;
814     }
815     ret_val[j++] = delim;
816   }
817   ret_val[n-1] = '\0';
818   return ret_val;
819 }
820
821 /*
822 void GJ_start_clock() 
823 {
824   extern clock_t start_time, end_time,initial_time,final_time;
825   start_time = clock();
826   initial_time = start_time;
827 }  
828
829 void GJ_stop_clock(FILE *fp) 
830 {
831   extern clock_t start_time, end_time,initial_time,final_time;
832   end_time = clock();
833   fprintf(fp,"CPU time: %f seconds\n",
834                 ((float) (end_time - start_time))/CLOCKS_PER_SEC); 
835 }
836 */
837
838
839 void GJ_start_clock(void) 
840 {
841   GJ_init_times();
842 }  
843
844 void GJ_stop_clock(FILE *fp) 
845 {
846   GJ_show_times(fp,3);
847   GJ_reset_times();
848 }
849
850
851 void GJindexx(int *arrin,int n,int *indx)
852   /* indexed heap sort - adapted from the NR routine indexx.
853      inarr is an integer array to sort,
854      indx is the returned index array
855   */
856 {
857         int l,j,ir,indxt,i;
858 /* SMJS
859         float q;
860 */
861         int q;
862
863         for (j=1;j<=n;j++) indx[j]=j;
864         l=(n >> 1) + 1;
865         ir=n;
866         for (;;) {
867                 if (l > 1)
868                         q=arrin[(indxt=indx[--l])];
869                 else {
870                         q=arrin[(indxt=indx[ir])];
871                         indx[ir]=indx[1];
872                         if (--ir == 1) {
873                                 indx[1]=indxt;
874                                 return;
875                         }
876                 }
877                 i=l;
878                 j=l << 1;
879                 while (j <= ir) {
880                         if (j < ir && arrin[indx[j]] < arrin[indx[j+1]]) j++;
881                         if (q < arrin[indx[j]]) {
882                                 indx[i]=indx[j];
883                                 j += (i=j);
884                         }
885                         else j=ir+1;
886                 }
887                 indx[i]=indxt;
888         }
889 }
890
891 void GJindexxD(double *arrin,int n,int *indx)
892   /* indexed heap sort - adapted from the NR routine indexx.
893      arrin is a double array to sort,
894      indx is the returned index array
895   */
896 {
897         int l,j,ir,indxt,i;
898 /*
899         float q;
900 */ 
901         double q;
902
903         for (j=1;j<=n;j++) indx[j]=j;
904         l=(n >> 1) + 1;
905         ir=n;
906         for (;;) {
907                 if (l > 1)
908                         q=arrin[(indxt=indx[--l])];
909                 else {
910                         q=arrin[(indxt=indx[ir])];
911                         indx[ir]=indx[1];
912                         if (--ir == 1) {
913                                 indx[1]=indxt;
914                                 return;
915                         }
916                 }
917                 i=l;
918                 j=l << 1;
919                 while (j <= ir) {
920                         if (j < ir && arrin[indx[j]] < arrin[indx[j+1]]) j++;
921                         if (q < arrin[indx[j]]) {
922                                 indx[i]=indx[j];
923                                 j += (i=j);
924                         }
925                         else j=ir+1;
926                 }
927                 indx[i]=indxt;
928         }
929 }
930
931 void GJindexxS1(char **arrin,int n,int *indx)
932      /*indexed sort of a character array - this uses qsort rather than the 
933        heapsort in GJindexxS.  indx runs from 0..(n-1) rather than 1..n as in 
934        GJindexxS.
935      */
936 {
937   int i;
938   CWORK  *ret;
939
940   ret = (CWORK *) GJmalloc(sizeof(CWORK) * n);
941
942   for(i=0;i<n;++i){
943     ret[i].val = arrin[i];
944     ret[i].i = i;
945   }
946   qsort(ret,  n, sizeof(CWORK), Sworkcomp);
947
948   for(i=0;i<n;++i){
949     indx[i] = ret[i].i;
950   }
951   GJfree(ret);
952 }
953
954 int Sworkcomp(const void *left, const void *right)
955 {
956   CWORK *a = (CWORK *) left;
957   CWORK *b = (CWORK *) right;
958
959   return strcmp(a->val,b->val);
960 }
961
962   
963 void GJindexxS(char **arrin,int n,int *indx)
964   /* indexed heap sort - adapted from the NR routine indexx.
965      arrin is a character string array to sort
966      indx is the returned index array
967   */
968 {
969         int l,j,ir,indxt,i;
970 /*
971         float q;
972 */
973         char *q;
974
975         for (j=1;j<=n;j++) indx[j]=j;
976         l=(n >> 1) + 1;
977         ir=n;
978         for (;;) {
979                 if (l > 1)
980                         q=arrin[(indxt=indx[--l])];
981                 else {
982                         q=arrin[(indxt=indx[ir])];
983                         indx[ir]=indx[1];
984                         if (--ir == 1) {
985                                 indx[1]=indxt;
986                                 return;
987                         }
988                 }
989                 i=l;
990                 j=l << 1;
991                 while (j <= ir) {
992                         if (j < ir && (strcmp(arrin[indx[j]],arrin[indx[j+1]]) < 0)  ) j++;
993                         if (strcmp(q,arrin[indx[j]])<0) {
994                                 indx[i]=indx[j];
995                                 j += (i=j);
996                         }
997                         else j=ir+1;
998                 }
999                 indx[i]=indxt;
1000         }
1001 }
1002  
1003
1004
1005 void GJpline(FILE *fp,char c,int n)
1006 /* print n copies of c to fp terminated by newline */
1007 {
1008   int i;
1009   for(i=0;i<n;++i){
1010     fprintf(fp,"%c",c);
1011   }
1012   fprintf(fp,"\n");
1013 }
1014
1015 char *GJlocaltime(void)
1016 {
1017   time_t t;
1018   char *ret_val;
1019   t = time(NULL);
1020   ret_val=asctime(localtime(&t));
1021   return ret_val;
1022 }
1023
1024 void GJpstring(FILE *fp,char *s,int n)
1025 /* print a string so that it occupies n characters */
1026 /* strings are left-justified and either truncated or padded on output */
1027 {
1028   int i,l;
1029
1030
1031   l = strlen(s);
1032
1033   if(l > n){
1034     for(i=0;i<n;++i){
1035       fprintf(fp,"%c",s[i]);
1036     }
1037   }else{
1038     for(i=0;i<l;++i){
1039       fprintf(fp,"%c",s[i]);
1040     }
1041     for(i=l;i<n;++i){
1042       fprintf(fp," ");
1043     }
1044   }
1045 }
1046
1047 /* return min and max of an integer vector */
1048 IRANGE *irange(int *ivec,int n)
1049 {
1050   int i;
1051   int imin,imax;
1052   IRANGE *ret_val;
1053
1054   imin = imax = ivec[0];
1055   
1056   for(i=1;i<n;++i){
1057     if(ivec[i] > imax) imax = ivec[i];
1058     if(ivec[i] < imin) imin = ivec[i];
1059   }
1060   
1061   ret_val = (IRANGE *) GJmalloc(sizeof(IRANGE));
1062   ret_val->min = imin;
1063   ret_val->max = imax;
1064
1065   return ret_val;
1066 }
1067
1068 #define BLIM 5
1069 int GJbsearchINXS(char **cod, int n, char *query)
1070
1071 /* binary search for query  in table cod.   If query is found, return index of query in cod.*/
1072 /* if it is   not found, return -1 */
1073
1074 {
1075         int r;          /* right limit */
1076         int l;          /* left limit */
1077         int cv;         /* centre value */
1078
1079         r = n-1;
1080         l = 0;
1081
1082         for(;;){
1083                 if((r-l) > BLIM){
1084                         cv = (r+l)/2;
1085                         if(strcmp(query,cod[cv]) == 0){
1086                                 return cv;
1087                         }else if(strcmp(query,cod[cv]) > 0){
1088                                 l = cv;
1089                         }else if(strcmp(query,cod[cv]) < 0){
1090                                 r = cv;
1091                         }
1092                 }else{
1093                         for(cv=l;cv<(r+1);++cv){
1094                                 if(strcmp(query,cod[cv]) == 0){                     
1095                                         return cv;
1096                                 }
1097                         }
1098                         return (int) -1;
1099                 }
1100         }
1101 }
1102
1103 int GJbsearchINX_IS(char **cod, int *inx, int n, char *query)
1104
1105 /* binary search for query  in table cod.  inx is the index into the table that specifies
1106    the sorted order of the table cod.
1107    If query is found, return index of query in inx that can be used to recover the value of 
1108    cod .*/
1109 /* if it is   not found, return -1 */
1110
1111 {
1112         int r;          /* right limit */
1113         int l;          /* left limit */
1114         int cv;         /* centre value */
1115
1116         r = n-1;
1117         l = 0;
1118
1119         for(;;){
1120                 if((r-l) > BLIM){
1121                         cv = (r+l)/2;
1122                         if(strcmp(query,cod[inx[cv]]) == 0){
1123                                 return cv;
1124                         }else if(strcmp(query,cod[inx[cv]]) > 0){
1125                                 l = cv;
1126                         }else if(strcmp(query,cod[inx[cv]]) < 0){
1127                                 r = cv;
1128                         }
1129                 }else{
1130                         for(cv=l;cv<(r+1);++cv){
1131                                 if(strcmp(query,cod[inx[cv]]) == 0){                        
1132                                         return cv;
1133                                 }
1134                         }
1135                         return (int) -1;
1136                 }
1137         }
1138 }
1139
1140 /* 
1141
1142 $Id: gjutil.c,v 1.2 2003/05/13 09:42:18 jon Exp $ 
1143
1144 $Log: gjutil.c,v $
1145 Revision 1.2  2003/05/13 09:42:18  jon
1146 Bug found in OC file input. The problem occurs when the first line giving
1147 the number of entries to be clustered is missing, and the first ID has
1148 a number at the beginning. This number is then taken to be the number
1149 of entries in the file and much hilarious dumping of core results.
1150
1151 To fix this requires a replacement of the file reading routines without
1152 fscanf. This will be done... later.
1153
1154 Revision 1.1  2002/08/04 19:06:18  geoff
1155 Add the gjutil programs to oc archive
1156
1157 Revision 1.1.1.1  2002/06/25 22:30:32  geoff
1158 Import of gjnoc routines
1159
1160
1161 Revision 1.12  2000/12/21 17:25:44  geoff
1162 Add the option to output the sequence fragments from the multiple alignment
1163 output option in fasta or pir format.  Unlike the block file output, these
1164 fragments contain the complete sequence between the start and end points, including
1165 any parts deleted in the alignment process.
1166 Add appropriate commands to scanps_alias.dat, getpars and getcmd.
1167
1168 Revision 1.11  2000/07/04 11:01:37  searle
1169 Changes for MMX
1170
1171 Revision 1.10  1999/11/17 21:06:47  geoff
1172 Add setup_caleb and other changes to swpp2 and so on.
1173
1174 Revision 1.9  1999/07/09 13:34:10  geoff
1175 modified these as a test
1176
1177 Revision 1.8  1998/08/11 15:38:50  geoff
1178 Modified the copyright notice to reflect the new
1179 ownership of this software.
1180
1181 Revision 1.7  1997/06/29 00:43:57  gjb
1182 Changes to add sysinfo calls and test of license reading routines
1183
1184 Revision 1.6  1997/06/27 16:42:41  gjb
1185 Add trlic.c test.lic and clean up gjutil.c
1186
1187 Revision 1.5  1997/06/27 07:17:31  gjb
1188 Added rlic.c linfo.h and
1189 changes to gjutil.c to give better support for
1190 token manipulation
1191
1192 Revision 1.4  1997/05/12 11:10:53  gjb
1193 Re-added gjutil.c and gjutil.h to repository
1194 after deleting them
1195
1196 Revision 1.2  1997/05/12 10:47:52  gjb
1197 Modified CVS header and log position
1198
1199 */
1200
1201
1202
1203