JPRED-2 Add alscript to the Git repository
[jpred.git] / sources / alscript / gjutil / 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         float q;
859
860         for (j=1;j<=n;j++) indx[j]=j;
861         l=(n >> 1) + 1;
862         ir=n;
863         for (;;) {
864                 if (l > 1)
865                         q=arrin[(indxt=indx[--l])];
866                 else {
867                         q=arrin[(indxt=indx[ir])];
868                         indx[ir]=indx[1];
869                         if (--ir == 1) {
870                                 indx[1]=indxt;
871                                 return;
872                         }
873                 }
874                 i=l;
875                 j=l << 1;
876                 while (j <= ir) {
877                         if (j < ir && arrin[indx[j]] < arrin[indx[j+1]]) j++;
878                         if (q < arrin[indx[j]]) {
879                                 indx[i]=indx[j];
880                                 j += (i=j);
881                         }
882                         else j=ir+1;
883                 }
884                 indx[i]=indxt;
885         }
886 }
887
888
889
890 void GJpline(FILE *fp,char c,int n)
891 /* print n copies of c to fp terminated by newline */
892 {
893   int i;
894   for(i=0;i<n;++i){
895     fprintf(fp,"%c",c);
896   }
897   fprintf(fp,"\n");
898 }
899
900 char *GJlocaltime(void)
901 {
902   time_t t;
903   char *ret_val;
904   t = time(NULL);
905   ret_val=asctime(localtime(&t));
906   return ret_val;
907 }
908
909 void GJpstring(FILE *fp,char *s,int n)
910 /* print a string so that it occupies n characters */
911 /* strings are left-justified and either truncated or padded on output */
912 {
913   int i,l;
914
915
916   l = strlen(s);
917
918   if(l > n){
919     for(i=0;i<n;++i){
920       fprintf(fp,"%c",s[i]);
921     }
922   }else{
923     for(i=0;i<l;++i){
924       fprintf(fp,"%c",s[i]);
925     }
926     for(i=l;i<n;++i){
927       fprintf(fp," ");
928     }
929   }
930 }
931
932 /* return min and max of an integer vector */
933 IRANGE *irange(int *ivec,int n)
934 {
935   int i;
936   int imin,imax;
937   IRANGE *ret_val;
938
939   imin = imax = ivec[0];
940   
941   for(i=1;i<n;++i){
942     if(ivec[i] > imax) imax = ivec[i];
943     if(ivec[i] < imin) imin = ivec[i];
944   }
945   
946   ret_val = (IRANGE *) GJmalloc(sizeof(IRANGE));
947   ret_val->min = imin;
948   ret_val->max = imax;
949
950   return ret_val;
951 }
952
953 /* 
954
955 $Id: gjutil.c,v 1.1.1.1 1999/07/09 13:34:10 geoff Exp $ 
956
957 $Log: gjutil.c,v $
958 Revision 1.1.1.1  1999/07/09 13:34:10  geoff
959 Import alscript 2_07 with the cygwin executables.
960
961 Revision 1.9  1999/07/09 13:34:10  geoff
962 modified these as a test
963
964 Revision 1.8  1998/08/11 15:38:50  geoff
965 Modified the copyright notice to reflect the new
966 ownership of this software.
967
968 Revision 1.7  1997/06/29 00:43:57  gjb
969 Changes to add sysinfo calls and test of license reading routines
970
971 Revision 1.6  1997/06/27 16:42:41  gjb
972 Add trlic.c test.lic and clean up gjutil.c
973
974 Revision 1.5  1997/06/27 07:17:31  gjb
975 Added rlic.c linfo.h and
976 changes to gjutil.c to give better support for
977 token manipulation
978
979 Revision 1.4  1997/05/12 11:10:53  gjb
980 Re-added gjutil.c and gjutil.h to repository
981 after deleting them
982
983 Revision 1.2  1997/05/12 10:47:52  gjb
984 Modified CVS header and log position
985
986 */