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