2 /****************************************************************************
4 gjutil.c: Various utility routines - error checking malloc and
5 free, string functions etc...
7 Copyright: Geoffrey J. Barton (1992, 1993, 1995, 1997)
10 This software is made available for educational and non-commercial research
13 For commercial use, a commercial licence is required - contact the author
14 at the above address for details.
16 ******************************************************************************/
28 /* define pointers for standard streams to allow redefinition to files */
35 clock_t start_time, end_time,initial_time,final_time;
37 void *GJmalloc(size_t size)
38 /* malloc with simple error check */
39 /* G. J. Barton 1992 */
42 ptr = (void *) malloc(size);
44 GJerror("malloc error");
50 void *GJrealloc(void *ptr,size_t size)
51 /* realloc with error check */
52 /* G. J. Barton 1992 */
54 ptr = (void *) realloc(ptr,size);
56 GJerror("realloc error");
61 void *GJmallocNQ(size_t size)
62 /* as for GJmalloc, but returns NULL on error*/
63 /* G. J. Barton 1992 */
66 ptr = (void *) malloc(size);
68 GJerror("malloc error");
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 */
78 ptr = (void *) realloc(ptr,size);
80 GJerror("realloc error");
85 void GJfree(void *ptr)
86 /* free with error check */
87 /* G. J. Barton 1992 */
90 GJerror("Attempt to free NULL pointer");
96 void GJerror(const char *prefix)
97 /* writes error message contained in prefix and contents of errno
100 /* G. J. Barton 1992 */
104 fprintf(std_err,"%s: ",prefix);
107 fprintf(std_err,"%s\n",strerror(errno));
113 void error(const char *str,int flag)
120 char *GJstoupper(const char *s)
121 /* return a copy of s in upper case */
122 /* G. J. Barton 1992 */
128 while(temp[i] != '\0'){
129 temp[i] = toupper(temp[i]);
134 char *GJstolower(const char *s)
135 /* return a copy of s in lower case */
136 /* G. J. Barton 1992 */
142 while(temp[i] != '\0'){
143 temp[i] = tolower(temp[i]);
148 char *GJstoup(char *s)
149 /* return s in upper case */
150 /* G. J. Barton 1992 */
155 s[i] = toupper(s[i]);
160 char *GJstolo(char *s)
161 /* return s in lower case */
162 /* G. J. Barton 1992 */
167 s[i] = tolower(s[i]);
173 char *GJstrdup(const char *s)
174 /* returns a pointer to a copy of string s */
175 /* G. J. Barton 1992 */
179 temp = (char *) GJmalloc(sizeof(char) * (strlen(s)+1));
180 temp = strcpy(temp,s);
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
191 old = (char *) GJrealloc(old,sizeof(char) * (nlen + 1));
192 old = strcpy(old,new);
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.
203 /* G. J. Barton 1992 */
204 /* modified July 1995 - error message only printed if action is 1 */
207 ret_val = fopen(fname,type);
209 /* GJerror(strcat("Cannot Open File: ",fname));*/
211 GJerror(strcat("Cannot Open File: ",fname));
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.
223 /* G. J. Barton 1992 */
226 ret_val = fclose(fp);
229 GJerror("Error closing File");
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 */
246 ret_val = (GJFILE *) GJmalloc(sizeof(GJFILE));
247 ret_val->name = GJstrdup(name);
249 ret_val->handle = GJfopen(ret_val->name,type,0);
250 }else if(action == 0){
251 ret_val->handle = NULL;
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 */
262 if(ret_val->name != NULL) {
263 GJfree(ret_val->name);
264 ret_val->name = GJstrdup(name);
266 if(ret_val->handle != NULL) {
267 GJfclose(ret_val->handle,0);
268 ret_val->handle = NULL;
273 GJFILE *GJfileclose(GJFILE *ret_val,int action)
274 /* Closes a file named in the struct file structure returns the struct
277 /* G. J. Barton July 1995 */
281 if(GJfclose(ret_val->handle,0) == 0){
285 GJerror("Error closing File");
286 fprintf(std_err,"%s\n",ret_val->name);
293 GJFILE *GJfileopen(GJFILE *ret_val,const char *type,int action)
294 /* Opens a file named in the struct file structure */
296 /* G. J. Barton October 1995 */
300 ret_val->handle = GJfopen(ret_val->name,type,0);
301 if(ret_val->handle == NULL){
303 GJerror("Error opening File");
304 fprintf(std_err,"%s\n",ret_val->name);
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 */
315 /* G. J. Barton July 1995 */
317 if(GJfclose(ret_val->handle,0) == 0) {
318 ret_val->handle = NULL;
319 GJfree(ret_val->name);
323 GJerror("Error closing File");
324 fprintf(std_err,"%s\n",ret_val->name);
331 void GJinitfile(void)
332 /* just set the standard streams */
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 */
343 while(*string != '\0'){
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
353 string1 and string2 must have been allocated with malloc.
355 /* G. J. Barton July 1992 */
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);
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.
372 /* G. J. Barton (July 1992) */
378 while(string[i] != '\0'){
387 temp = (char *) GJmalloc(sizeof(char) * (strlen(string)-nchar + 1));
390 while(string[i] != '\0'){
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
407 /* G. J. Barton (July 1992) */
413 temp = (char *) GJmalloc(sizeof(char) * (len+1));
414 for(i=0;i<(len+1);++i){
420 for(i=0;i<(strlen(temp)+1);++i){
428 char *GJsubchar(char *string,char c2,char c1)
429 /* substitutes c1 for c2 in string
431 /* G. J. Barton (July 1992) */
436 while(string[i] != '\0'){
445 /* create a string and if fchar != NULL fill with characters */
446 /* always set the len-1 character to '\0' */
448 char *GJstrcreate(size_t len,char *fchar)
451 ret_val = (char *) GJmalloc(sizeof(char) * len);
456 ret_val[len] = *fchar;
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
466 char *GJstrlocate(char *s1, char *s2)
471 if(strlen(s1) == 0 || strlen(s2) == 0) return NULL;
472 while(i < strlen(s1)){
475 while(j < strlen(s2) && s1[k] == s2[j]){
479 if(j == strlen(s2)) return &s1[i];
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
495 char *GJstrtok(char *input_string,const char *token_list)
500 if(input_string != NULL){
505 /* search for next non-token character */
506 while(strchr(token_list,*work)!=NULL){
511 /* if we've reached the end of string, then return NULL */
514 return_ptr = (char *) work;
515 while(strchr(token_list,*work) == NULL){
517 /* end of the string */
525 /* now increment work until we find the next non-delimiter character */
526 while(strchr(token_list,*work) != NULL){
536 /**************************************************************************
537 return a pointer to space for a rectangular unsigned character array
538 Version 2.0 ANSI and uses GJmallocNQ
539 --------------------------------------------------------------------------*/
541 unsigned char **uchararr(int i,int j)
543 unsigned char **temp;
546 temp = (unsigned char **) GJmallocNQ(sizeof(unsigned char *) * i);
547 if(temp == NULL) return NULL;
549 rowsiz = sizeof(unsigned char) * j;
551 for (k = 0; k < i; ++k){
552 temp[k] = (unsigned char *) GJmallocNQ(rowsiz);
553 if(temp[k] == NULL) return NULL;
558 /**************************************************************************
559 free up space pointed to by rectangular unsigned character array
560 -------------------------------------------------------------------------*/
561 void ucharfree(unsigned char **array,int i)
566 for (k = 0; k < i; ++k){
567 GJfree((char *) array[k]);
569 GJfree((char *) array);
573 /**************************************************************************
574 return a pointer to space for a rectangular signed character array
576 --------------------------------------------------------------------------*/
577 signed char **chararr(int i,int j)
583 temp = (signed char **) GJmallocNQ(sizeof(char *) * i);
585 if(temp == NULL) return NULL;
587 rowsiz = sizeof(char) * j;
589 for (k = 0; k < i; ++k){
590 temp[k] = (signed char *) GJmallocNQ(rowsiz);
591 if(temp[k] == NULL) return NULL;
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*/
601 void mcheck(void *ptr,char *msg)
605 GJerror("malloc/realloc error");
610 /* set a string to blanks and add terminating nul */
611 char *GJstrblank(char *string,int len)
624 /* Initialise an unsigned char array */
625 void GJUCinit(unsigned char **array,int i,int j,unsigned char val)
635 /*Initialise a signed char array */
637 void GJCinit(signed char **array,int i,int j,char val)
649 /* Initialise an integer vector */
650 void GJIinit(int *array,int i,int val)
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,...)
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 */
674 values = (char **) GJmalloc(sizeof(char *) * N);
675 value_len = (int *) GJmalloc(sizeof(int *) * N);
677 va_start(parminfo,N);
679 /* Get pointers and lengths for the N arguments */
681 values[i] = va_arg(parminfo,char *);
682 value_len[i] = strlen(values[i]);
683 ret_len += value_len[i];
686 ret_val = (char *) GJmalloc(sizeof(char) * (ret_len+1));
688 /* Transfer input strings to output string */
691 for(j=0;j<value_len[i];++j){
692 ret_val[k] = values[i][j];
705 /************************************************************************
709 The aim of this routine is to emulate the strtok() function, but reading
710 from a file. The functionality may differ slightly...
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.
717 ------------------------------------------------------------------------*/
720 char *GJGetToken(FILE *in, const char *delim)
729 token = GJmalloc(sizeof(char));
731 while((c=fgetc(in)) != EOF){
732 if(strchr(delim,c) == NULL){
733 /* not a delimiter */
735 token = GJrealloc(token,sizeof(char) * (i+1));
741 /* GJerror("End of File Encountered");*/
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 */
754 token = strtok(buff,delims);
755 if(token == NULL) return NULL;
757 tok = (struct tokens *) GJmalloc(sizeof(struct tokens));
759 tok->tok = (char **) GJmalloc(sizeof(char *));
760 tok->tok[0] = GJstrdup(token);
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);
771 void GJfreetokens(struct tokens *tok)
772 /* frees a tokens structure */
776 for(i=0;i<tok->ntok;++i) {
781 tok = NULL; /* add this to avoid odd pointer 27/6/1997*/
784 char * GJtoktostr(struct tokens *tok,char delim,int s, int e)
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.
799 if(s < 0 || s >= tok->ntok) s = 0;
800 if(e < 0 || e >= tok->ntok) e = tok->ntok - 1;
803 n += strlen(tok->tok[i]);
807 ret_val = (char *) GJmalloc(sizeof(char) * n);
810 for(k=0;k<strlen(tok->tok[i]);++k){
811 ret_val[j] = tok->tok[i][k];
814 ret_val[j++] = delim;
821 void GJ_start_clock()
823 extern clock_t start_time, end_time,initial_time,final_time;
824 start_time = clock();
825 initial_time = start_time;
828 void GJ_stop_clock(FILE *fp)
830 extern clock_t start_time, end_time,initial_time,final_time;
832 fprintf(fp,"CPU time: %f seconds\n",
833 ((float) (end_time - start_time))/CLOCKS_PER_SEC);
838 void GJ_start_clock(void)
843 void GJ_stop_clock(FILE *fp)
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
859 for (j=1;j<=n;j++) indx[j]=j;
864 q=arrin[(indxt=indx[--l])];
866 q=arrin[(indxt=indx[ir])];
876 if (j < ir && arrin[indx[j]] < arrin[indx[j+1]]) j++;
877 if (q < arrin[indx[j]]) {
889 void GJpline(FILE *fp,char c,int n)
890 /* print n copies of c to fp terminated by newline */
899 char *GJlocaltime(void)
904 ret_val=asctime(localtime(&t));
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 */
919 fprintf(fp,"%c",s[i]);
923 fprintf(fp,"%c",s[i]);
931 /* return min and max of an integer vector */
932 IRANGE *irange(int *ivec,int n)
938 imin = imax = ivec[0];
941 if(ivec[i] > imax) imax = ivec[i];
942 if(ivec[i] < imin) imin = ivec[i];
945 ret_val = (IRANGE *) GJmalloc(sizeof(IRANGE));
954 $Id: gjutil.c,v 1.2 1998/09/17 16:55:01 geoff Exp $
957 Revision 1.2 1998/09/17 16:55:01 geoff
958 Check consistency with archive
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.
964 Revision 1.7 1997/06/29 00:43:57 gjb
965 Changes to add sysinfo calls and test of license reading routines
967 Revision 1.6 1997/06/27 16:42:41 gjb
968 Add trlic.c test.lic and clean up gjutil.c
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
975 Revision 1.4 1997/05/12 11:10:53 gjb
976 Re-added gjutil.c and gjutil.h to repository
979 Revision 1.2 1997/05/12 10:47:52 gjb
980 Modified CVS header and log position