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.
17 ******************************************************************************/
29 /* define pointers for standard streams to allow redefinition to files */
36 clock_t start_time, end_time,initial_time,final_time;
38 void *GJmalloc(size_t size)
39 /* malloc with simple error check */
40 /* G. J. Barton 1992 */
43 ptr = (void *) malloc(size);
45 GJerror("malloc error");
51 void *GJrealloc(void *ptr,size_t size)
52 /* realloc with error check */
53 /* G. J. Barton 1992 */
55 ptr = (void *) realloc(ptr,size);
57 GJerror("realloc error");
62 void *GJmallocNQ(size_t size)
63 /* as for GJmalloc, but returns NULL on error*/
64 /* G. J. Barton 1992 */
67 ptr = (void *) malloc(size);
69 GJerror("malloc error");
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 */
79 ptr = (void *) realloc(ptr,size);
81 GJerror("realloc error");
86 void GJfree(void *ptr)
87 /* free with error check */
88 /* G. J. Barton 1992 */
91 GJerror("Attempt to free NULL pointer");
97 void GJerror(const char *prefix)
98 /* writes error message contained in prefix and contents of errno
101 /* G. J. Barton 1992 */
105 fprintf(std_err,"%s: ",prefix);
108 fprintf(std_err,"%s\n",strerror(errno));
114 void error(const char *str,int flag)
121 char *GJstoupper(const char *s)
122 /* return a copy of s in upper case */
123 /* G. J. Barton 1992 */
129 while(temp[i] != '\0'){
130 temp[i] = toupper(temp[i]);
135 char *GJstolower(const char *s)
136 /* return a copy of s in lower case */
137 /* G. J. Barton 1992 */
143 while(temp[i] != '\0'){
144 temp[i] = tolower(temp[i]);
149 char *GJstoup(char *s)
150 /* return s in upper case */
151 /* G. J. Barton 1992 */
156 s[i] = toupper(s[i]);
161 char *GJstolo(char *s)
162 /* return s in lower case */
163 /* G. J. Barton 1992 */
168 s[i] = tolower(s[i]);
174 char *GJstrdup(const char *s)
175 /* returns a pointer to a copy of string s */
176 /* G. J. Barton 1992 */
180 temp = (char *) GJmalloc(sizeof(char) * (strlen(s)+1));
181 temp = strcpy(temp,s);
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
192 old = (char *) GJrealloc(old,sizeof(char) * (nlen + 1));
193 old = strcpy(old,new);
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.
204 /* G. J. Barton 1992 */
205 /* modified July 1995 - error message only printed if action is 1 */
208 ret_val = fopen(fname,type);
210 /* GJerror(strcat("Cannot Open File: ",fname));*/
212 GJerror(strcat("Cannot Open File: ",fname));
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.
224 /* G. J. Barton 1992 */
227 ret_val = fclose(fp);
230 GJerror("Error closing File");
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 */
247 ret_val = (GJFILE *) GJmalloc(sizeof(GJFILE));
248 ret_val->name = GJstrdup(name);
250 ret_val->handle = GJfopen(ret_val->name,type,0);
251 }else if(action == 0){
252 ret_val->handle = NULL;
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 */
263 if(ret_val->name != NULL) {
264 GJfree(ret_val->name);
265 ret_val->name = GJstrdup(name);
267 if(ret_val->handle != NULL) {
268 GJfclose(ret_val->handle,0);
269 ret_val->handle = NULL;
274 GJFILE *GJfileclose(GJFILE *ret_val,int action)
275 /* Closes a file named in the struct file structure returns the struct
278 /* G. J. Barton July 1995 */
282 if(GJfclose(ret_val->handle,0) == 0){
286 GJerror("Error closing File");
287 fprintf(std_err,"%s\n",ret_val->name);
294 GJFILE *GJfileopen(GJFILE *ret_val,const char *type,int action)
295 /* Opens a file named in the struct file structure */
297 /* G. J. Barton October 1995 */
301 ret_val->handle = GJfopen(ret_val->name,type,0);
302 if(ret_val->handle == NULL){
304 GJerror("Error opening File");
305 fprintf(std_err,"%s\n",ret_val->name);
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 */
316 /* G. J. Barton July 1995 */
318 if(GJfclose(ret_val->handle,0) == 0) {
319 ret_val->handle = NULL;
320 GJfree(ret_val->name);
324 GJerror("Error closing File");
325 fprintf(std_err,"%s\n",ret_val->name);
332 void GJinitfile(void)
333 /* just set the standard streams */
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 */
344 while(*string != '\0'){
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
354 string1 and string2 must have been allocated with malloc.
356 /* G. J. Barton July 1992 */
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);
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.
373 /* G. J. Barton (July 1992) */
379 while(string[i] != '\0'){
388 temp = (char *) GJmalloc(sizeof(char) * (strlen(string)-nchar + 1));
391 while(string[i] != '\0'){
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
408 /* G. J. Barton (July 1992) */
414 temp = (char *) GJmalloc(sizeof(char) * (len+1));
415 for(i=0;i<(len+1);++i){
421 for(i=0;i<(strlen(temp)+1);++i){
429 char *GJsubchar(char *string,char c2,char c1)
430 /* substitutes c1 for c2 in string
432 /* G. J. Barton (July 1992) */
437 while(string[i] != '\0'){
446 /* create a string and if fchar != NULL fill with characters */
447 /* always set the len-1 character to '\0' */
449 char *GJstrcreate(size_t len,char *fchar)
452 ret_val = (char *) GJmalloc(sizeof(char) * len);
457 ret_val[len] = *fchar;
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
467 char *GJstrlocate(char *s1, char *s2)
472 if(strlen(s1) == 0 || strlen(s2) == 0) return NULL;
473 while(i < strlen(s1)){
476 while(j < strlen(s2) && s1[k] == s2[j]){
480 if(j == strlen(s2)) return &s1[i];
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
496 char *GJstrtok(char *input_string,const char *token_list)
501 if(input_string != NULL){
506 /* search for next non-token character */
507 while(strchr(token_list,*work)!=NULL){
512 /* if we've reached the end of string, then return NULL */
515 return_ptr = (char *) work;
516 while(strchr(token_list,*work) == NULL){
518 /* end of the string */
526 /* now increment work until we find the next non-delimiter character */
527 while(strchr(token_list,*work) != NULL){
537 /**************************************************************************
538 return a pointer to space for a rectangular unsigned character array
539 Version 2.0 ANSI and uses GJmallocNQ
540 --------------------------------------------------------------------------*/
542 unsigned char **uchararr(int i,int j)
544 unsigned char **temp;
547 temp = (unsigned char **) GJmallocNQ(sizeof(unsigned char *) * i);
548 if(temp == NULL) return NULL;
550 rowsiz = sizeof(unsigned char) * j;
552 for (k = 0; k < i; ++k){
553 temp[k] = (unsigned char *) GJmallocNQ(rowsiz);
554 if(temp[k] == NULL) return NULL;
559 /**************************************************************************
560 free up space pointed to by rectangular unsigned character array
561 -------------------------------------------------------------------------*/
562 void ucharfree(unsigned char **array,int i)
567 for (k = 0; k < i; ++k){
568 GJfree((char *) array[k]);
570 GJfree((char *) array);
574 /**************************************************************************
575 return a pointer to space for a rectangular signed character array
577 --------------------------------------------------------------------------*/
578 signed char **chararr(int i,int j)
584 temp = (signed char **) GJmallocNQ(sizeof(char *) * i);
586 if(temp == NULL) return NULL;
588 rowsiz = sizeof(char) * j;
590 for (k = 0; k < i; ++k){
591 temp[k] = (signed char *) GJmallocNQ(rowsiz);
592 if(temp[k] == NULL) return NULL;
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*/
602 void mcheck(void *ptr,char *msg)
606 GJerror("malloc/realloc error");
611 /* set a string to blanks and add terminating nul */
612 char *GJstrblank(char *string,int len)
625 /* Initialise an unsigned char array */
626 void GJUCinit(unsigned char **array,int i,int j,unsigned char val)
636 /*Initialise a signed char array */
638 void GJCinit(signed char **array,int i,int j,char val)
650 /* Initialise an integer vector */
651 void GJIinit(int *array,int i,int val)
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,...)
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 */
675 values = (char **) GJmalloc(sizeof(char *) * N);
676 value_len = (int *) GJmalloc(sizeof(int *) * N);
678 va_start(parminfo,N);
680 /* Get pointers and lengths for the N arguments */
682 values[i] = va_arg(parminfo,char *);
683 value_len[i] = strlen(values[i]);
684 ret_len += value_len[i];
687 ret_val = (char *) GJmalloc(sizeof(char) * (ret_len+1));
689 /* Transfer input strings to output string */
692 for(j=0;j<value_len[i];++j){
693 ret_val[k] = values[i][j];
706 /************************************************************************
710 The aim of this routine is to emulate the strtok() function, but reading
711 from a file. The functionality may differ slightly...
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.
718 ------------------------------------------------------------------------*/
721 char *GJGetToken(FILE *in, const char *delim)
730 token = GJmalloc(sizeof(char));
732 while((c=fgetc(in)) != EOF){
733 if(strchr(delim,c) == NULL){
734 /* not a delimiter */
736 token = GJrealloc(token,sizeof(char) * (i+1));
742 /* GJerror("End of File Encountered");*/
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 */
755 token = strtok(buff,delims);
756 if(token == NULL) return NULL;
758 tok = (struct tokens *) GJmalloc(sizeof(struct tokens));
760 tok->tok = (char **) GJmalloc(sizeof(char *));
761 tok->tok[0] = GJstrdup(token);
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);
772 void GJfreetokens(struct tokens *tok)
773 /* frees a tokens structure */
777 for(i=0;i<tok->ntok;++i) {
782 tok = NULL; /* add this to avoid odd pointer 27/6/1997*/
785 char * GJtoktostr(struct tokens *tok,char delim,int s, int e)
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.
800 if(s < 0 || s >= tok->ntok) s = 0;
801 if(e < 0 || e >= tok->ntok) e = tok->ntok - 1;
804 n += strlen(tok->tok[i]);
808 ret_val = (char *) GJmalloc(sizeof(char) * n);
811 for(k=0;k<strlen(tok->tok[i]);++k){
812 ret_val[j] = tok->tok[i][k];
815 ret_val[j++] = delim;
822 void GJ_start_clock()
824 extern clock_t start_time, end_time,initial_time,final_time;
825 start_time = clock();
826 initial_time = start_time;
829 void GJ_stop_clock(FILE *fp)
831 extern clock_t start_time, end_time,initial_time,final_time;
833 fprintf(fp,"CPU time: %f seconds\n",
834 ((float) (end_time - start_time))/CLOCKS_PER_SEC);
839 void GJ_start_clock(void)
844 void GJ_stop_clock(FILE *fp)
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
860 for (j=1;j<=n;j++) indx[j]=j;
865 q=arrin[(indxt=indx[--l])];
867 q=arrin[(indxt=indx[ir])];
877 if (j < ir && arrin[indx[j]] < arrin[indx[j+1]]) j++;
878 if (q < arrin[indx[j]]) {
890 void GJpline(FILE *fp,char c,int n)
891 /* print n copies of c to fp terminated by newline */
900 char *GJlocaltime(void)
905 ret_val=asctime(localtime(&t));
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 */
920 fprintf(fp,"%c",s[i]);
924 fprintf(fp,"%c",s[i]);
932 /* return min and max of an integer vector */
933 IRANGE *irange(int *ivec,int n)
939 imin = imax = ivec[0];
942 if(ivec[i] > imax) imax = ivec[i];
943 if(ivec[i] < imin) imin = ivec[i];
946 ret_val = (IRANGE *) GJmalloc(sizeof(IRANGE));
955 $Id: gjutil.c,v 1.1.1.1 1999/07/09 13:34:10 geoff Exp $
958 Revision 1.1.1.1 1999/07/09 13:34:10 geoff
959 Import alscript 2_07 with the cygwin executables.
961 Revision 1.9 1999/07/09 13:34:10 geoff
962 modified these as a test
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.
968 Revision 1.7 1997/06/29 00:43:57 gjb
969 Changes to add sysinfo calls and test of license reading routines
971 Revision 1.6 1997/06/27 16:42:41 gjb
972 Add trlic.c test.lic and clean up gjutil.c
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
979 Revision 1.4 1997/05/12 11:10:53 gjb
980 Re-added gjutil.c and gjutil.h to repository
983 Revision 1.2 1997/05/12 10:47:52 gjb
984 Modified CVS header and log position