9d8e535df48096df7c2ecf5ba747eb8b779b80fe
[alexxy/gromacs.git] / src / gmxlib / string2.c
1 /*
2  * 
3  *                This source code is part of
4  * 
5  *                 G   R   O   M   A   C   S
6  * 
7  *          GROningen MAchine for Chemical Simulations
8  * 
9  *                        VERSION 3.2.0
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2004, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  * 
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  * 
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  * 
30  * For more info, check our website at http://www.gromacs.org
31  * 
32  * And Hey:
33  * GROningen Mixture of Alchemy and Childrens' Stories
34  */
35 /* This file is completely threadsafe - keep it that way! */
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39 #include "visibility.h"
40 #include "gmx_header_config.h"
41
42 #ifdef GMX_CRAY_XT3
43 #undef HAVE_PWD_H
44 #endif
45
46 #include <stdio.h>
47 #include <ctype.h>
48 #include <stdlib.h>
49 #include <errno.h>
50 #include <sys/types.h>
51 #include <time.h>
52
53 #ifdef HAVE_SYS_TIME_H
54 #include <sys/time.h>
55 #endif
56
57
58 #ifdef HAVE_PWD_H
59 #include <pwd.h>
60 #endif
61 #include <time.h>
62 #include <assert.h>
63
64 #include "typedefs.h"
65 #include "smalloc.h"
66 #include "gmx_fatal.h"
67 #include "macros.h"
68 #include "string2.h"
69 #include "futil.h"
70
71 int continuing(char *s)
72 /* strip trailing spaces and if s ends with a CONTINUE remove that too.
73  * returns TRUE if s ends with a CONTINUE, FALSE otherwise.
74  */
75 {
76   int sl;
77   assert(s);
78
79   rtrim(s);
80   sl = strlen(s);
81   if ((sl > 0) && (s[sl-1] == CONTINUE)) {
82     s[sl-1] = 0;
83     return TRUE;
84   }
85   else
86     return FALSE;
87 }
88
89
90
91 char *fgets2(char *line, int n, FILE *stream)
92 /* This routine reads a string from stream of max length n
93  * and zero terminated, without newlines
94  * line should be long enough (>= n)
95  */
96 {
97   char *c;
98   if (fgets(line,n,stream) == NULL) {
99     return NULL;
100   }
101   if ((c=strchr(line,'\n')) != NULL) {
102     *c = '\0';
103   } else {
104     /* A line not ending in a newline can only occur at the end of a file,
105      * or because of n being too small.
106      * Since both cases occur very infrequently, we can check for EOF.
107      */
108     if (!gmx_eof(stream)) {
109       gmx_fatal(FARGS,"An input file contains a line longer than %d characters, while the buffer passed to fgets2 has size %d. The line starts with: '%20.20s'",n,n,line);
110     }
111   }
112   if ((c=strchr(line,'\r')) != NULL) {
113     *c = '\0';
114   }
115
116   return line;
117 }
118
119 void strip_comment (char *line)
120 {
121   char *c;
122
123   if (!line)
124     return;
125
126   /* search for a comment mark and replace it by a zero */
127   if ((c = strchr(line,COMMENTSIGN)) != NULL) 
128     (*c) = 0;
129 }
130
131 void upstring (char *str)
132 {
133   int i;
134
135   for (i=0; (i < (int)strlen(str)); i++) 
136     str[i] = toupper(str[i]);
137 }
138
139 void ltrim (char *str)
140 {
141   char *tr;
142   int i,c;
143
144   if (NULL == str)
145     return;
146
147   c = 0;
148   while (('\0' != str[c]) && isspace(str[c]))
149     c++;
150   if (c > 0) 
151     {
152       for(i=c; ('\0' != str[i]); i++)
153         str[i-c] = str[i];
154       str[i-c] = '\0';
155     }
156 }
157
158 void rtrim (char *str)
159 {
160   int nul;
161
162   if (NULL == str)
163     return;
164
165   nul = strlen(str)-1;
166   while ((nul > 0) && ((str[nul] == ' ') || (str[nul] == '\t')) ) {
167     str[nul] = '\0';
168     nul--;
169   }
170 }
171
172 void trim (char *str)
173 {
174   ltrim (str);
175   rtrim (str);
176 }
177
178 GMX_LIBGMX_EXPORT
179 char *
180 gmx_ctime_r(const time_t *clock,char *buf, int n)
181 {
182     char tmpbuf[STRLEN];
183   
184 #ifdef GMX_NATIVE_WINDOWS
185     /* Windows */
186     ctime_s( tmpbuf, STRLEN, clock );
187 #elif (defined(__sun))
188     /*Solaris*/
189     ctime_r(clock, tmpbuf, n);
190 #else
191     ctime_r(clock,tmpbuf);
192 #endif
193     strncpy(buf,tmpbuf,n-1);
194     buf[n-1]='\0';
195     
196     return buf;
197 }
198           
199 void nice_header (FILE *out,const char *fn)
200 {
201   const char *unk = "onbekend";
202   time_t clock;
203   const char *user=unk;
204   int    gh;
205   uid_t  uid;
206   char   buf[256]="";
207   char   timebuf[STRLEN];
208 #ifdef HAVE_PWD_H
209   struct passwd *pw;
210 #endif
211
212   /* Print a nice header above the file */
213   time(&clock);
214   fprintf (out,"%c\n",COMMENTSIGN);
215   fprintf (out,"%c\tFile '%s' was generated\n",COMMENTSIGN,fn ? fn : unk);
216   
217 #ifdef HAVE_PWD_H
218   uid = getuid();
219   pw  = getpwuid(uid);
220   gh  = gethostname(buf,255);
221   user= pw->pw_name;
222 #else
223   uid = 0;
224   gh  = -1;
225 #endif
226   
227   gmx_ctime_r(&clock,timebuf,STRLEN);
228   fprintf (out,"%c\tBy user: %s (%d)\n",COMMENTSIGN,
229            user ? user : unk,(int) uid);
230   fprintf(out,"%c\tOn host: %s\n",COMMENTSIGN,(gh == 0) ? buf : unk);
231
232   fprintf (out,"%c\tAt date: %s",COMMENTSIGN,timebuf);
233   fprintf (out,"%c\n",COMMENTSIGN);
234 }
235
236
237 int gmx_strcasecmp_min(const char *str1, const char *str2)
238 {
239     char ch1,ch2;
240
241     do
242     {
243         do
244         {
245             ch1=toupper(*(str1++));
246         }
247         while ((ch1=='-') || (ch1=='_'));
248         do
249         {
250             ch2=toupper(*(str2++));
251         }
252         while ((ch2=='-') || (ch2=='_'));
253
254         if (ch1!=ch2) return (ch1-ch2);
255     }
256     while (ch1);
257     return 0;
258 }
259
260 int gmx_strncasecmp_min(const char *str1, const char *str2, int n)
261 {
262     char ch1,ch2;
263     char *stri1, *stri2;
264
265     stri1=(char *)str1;
266     stri2=(char *)str2;
267     do
268     {
269         do
270         {
271             ch1=toupper(*(str1++));
272         }
273         while ((ch1=='-') || (ch1=='_'));
274         do
275         {
276             ch2=toupper(*(str2++));
277         }
278         while ((ch2=='-') || (ch2=='_'));
279
280         if (ch1!=ch2) return (ch1-ch2);
281     }
282     while (ch1 && (str1-stri1<n) && (str2-stri2<n));
283   return 0; 
284 }
285
286 int gmx_strcasecmp(const char *str1, const char *str2)
287 {
288   char ch1,ch2;
289   
290   do
291     {
292       ch1=toupper(*(str1++));
293       ch2=toupper(*(str2++));
294       if (ch1!=ch2) return (ch1-ch2);
295     }
296   while (ch1);
297   return 0; 
298 }
299
300 int gmx_strncasecmp(const char *str1, const char *str2, int n)
301 {
302   char ch1,ch2;
303  
304   if(n==0) 
305     return 0;
306
307   do
308     {
309       ch1=toupper(*(str1++));
310       ch2=toupper(*(str2++));
311       if (ch1!=ch2) return (ch1-ch2);
312       n--;
313     }
314   while (ch1 && n);
315   return 0; 
316 }
317
318 char *gmx_strdup(const char *src)
319 {
320   char *dest;
321
322   snew(dest,strlen(src)+1);
323   strcpy(dest,src);
324   
325   return dest;
326 }
327
328 char *
329 gmx_strndup(const char *src, int n)
330 {
331     int   len;
332     char *dest;
333
334     len = strlen(src);
335     if (len > n) 
336     {
337         len = n;
338     }
339     snew(dest, len+1);
340     strncpy(dest, src, len);
341     dest[len] = 0;
342     return dest;
343 }
344
345 /* Magic hash init number for Dan J. Bernsteins algorithm.
346  * Do NOT use any other value unless you really know what you are doing.
347  */
348 const unsigned int
349 gmx_string_hash_init = 5381;
350
351
352 unsigned int
353 gmx_string_hash_func(const char *s, unsigned int hash_init)
354 {
355     int c;
356
357     while ((c = toupper(*s++)) != '\0')
358     {
359         if(isalnum(c)) hash_init = ((hash_init << 5) + hash_init) ^ c; /* (hash * 33) xor c */
360     }
361     return hash_init;
362 }
363
364 /*!
365  * \param[in] pattern  Pattern to match against.
366  * \param[in] str      String to match.
367  * \returns   0 on match, GMX_NO_WCMATCH if there is no match.
368  *
369  * Matches \p str against \p pattern, which may contain * and ? wildcards.
370  * All other characters are matched literally.
371  * Currently, it is not possible to match literal * or ?.
372  */
373 int
374 gmx_wcmatch(const char *pattern, const char *str)
375 {
376     while (*pattern)
377     {
378         if (*pattern == '*')
379         {
380             /* Skip multiple wildcards in a sequence */
381             while (*pattern == '*' || *pattern == '?')
382             {
383                 ++pattern;
384                 /* For ?, we need to check that there are characters left
385                  * in str. */
386                 if (*pattern == '?')
387                 {
388                     if (*str == 0)
389                     {
390                         return GMX_NO_WCMATCH;
391                     }
392                     else
393                     {
394                         ++str;
395                     }
396                 }
397             }
398             /* If the pattern ends after the star, we have a match */
399             if (*pattern == 0)
400             {
401                 return 0;
402             }
403             /* Match the rest against each possible suffix of str */
404             while (*str)
405             {
406                 /* Only do the recursive call if the first character
407                  * matches. We don't have to worry about wildcards here,
408                  * since we have processed them above. */
409                 if (*pattern == *str)
410                 {
411                     int rc;
412                     /* Match the suffix, and return if a match or an error */
413                     rc = gmx_wcmatch(pattern, str);
414                     if (rc != GMX_NO_WCMATCH)
415                     {
416                         return rc;
417                     }
418                 }
419                 ++str;
420             }
421             /* If no suffix of str matches, we don't have a match */
422             return GMX_NO_WCMATCH;
423         }
424         else if ((*pattern == '?' && *str != 0) || *pattern == *str)
425         {
426             ++str;
427         }
428         else
429         {
430             return GMX_NO_WCMATCH;
431         }
432         ++pattern;
433     }
434     /* When the pattern runs out, we have a match if the string has ended. */
435     return (*str == 0) ? 0 : GMX_NO_WCMATCH;
436 }
437
438 char *wrap_lines(const char *buf,int line_width, int indent,gmx_bool bIndentFirst)
439 {
440   char *b2;
441   int i,i0,i2,j,b2len,lspace=0,l2space=0;
442   gmx_bool bFirst,bFitsOnLine;
443
444   /* characters are copied from buf to b2 with possible spaces changed
445    * into newlines and extra space added for indentation.
446    * i indexes buf (source buffer) and i2 indexes b2 (destination buffer)
447    * i0 points to the beginning of the current line (in buf, source)
448    * lspace and l2space point to the last space on the current line
449    * bFirst is set to prevent indentation of first line
450    * bFitsOnLine says if the first space occurred before line_width, if 
451    * that is not the case, we have a word longer than line_width which 
452    * will also not fit on the next line, so we might as well keep it on 
453    * the current line (where it also won't fit, but looks better)
454    */
455   
456   b2=NULL;
457   b2len=strlen(buf)+1+indent;
458   snew(b2,b2len);
459   i0=i2=0;
460   if (bIndentFirst)
461     for(i2=0; (i2<indent); i2++)
462       b2[i2] = ' ';
463   bFirst=TRUE;
464   do {
465     l2space = -1;
466     /* find the last space before end of line */
467     for(i=i0; ((i-i0 < line_width) || (l2space==-1)) && (buf[i]); i++) {
468       b2[i2++] = buf[i];
469       /* remember the position of a space */
470       if (buf[i] == ' ') {
471         lspace = i;
472         l2space = i2-1;
473       }
474       /* if we have a newline before the line is full, reset counters */
475       if (buf[i]=='\n' && buf[i+1]) { 
476         i0=i+1;
477         b2len+=indent;
478         srenew(b2, b2len);
479         /* add indentation after the newline */
480         for(j=0; (j<indent); j++)
481           b2[i2++]=' ';
482       }
483     }
484     /* If we are at the last newline, copy it */
485     if (buf[i]=='\n' && !buf[i+1]) {
486       b2[i2++] = buf[i++];
487     }
488     /* if we're not at the end of the string */
489     if (buf[i]) {
490       /* check if one word does not fit on the line */
491       bFitsOnLine = (i-i0 <= line_width);
492       /* reset line counters to just after the space */
493       i0 = lspace+1;
494       i2 = l2space+1;
495       /* if the words fit on the line, and we're beyond the indentation part */
496       if ( (bFitsOnLine) && (l2space >= indent) ) {
497         /* start a new line */
498         b2[l2space] = '\n';
499         /* and add indentation */
500         if (indent) {
501           if (bFirst) {
502             line_width-=indent;
503             bFirst=FALSE;
504           }
505           b2len+=indent;
506           srenew(b2, b2len);
507           for(j=0; (j<indent); j++)
508             b2[i2++]=' ';
509           /* no extra spaces after indent; */
510           while(buf[i0]==' ')
511             i0++;
512         }
513       }
514     }
515   } while (buf[i]);
516   b2[i2] = '\0';
517   
518   return b2;
519 }
520
521 char **split(char sep,char *str)
522 {
523   char **ptr = NULL;
524   int  n,nn,nptr = 0;
525   
526   if (str == NULL)
527     return NULL;
528   nn = strlen(str);
529   for(n=0; (n<nn); n++)
530     if (str[n] == sep)
531       nptr++;
532   snew(ptr,nptr+2);
533   nptr = 0;
534   while (*str != '\0') {
535     while ((*str != '\0') && (*str == sep))
536       str++;
537     if (*str != '\0') {
538       snew(ptr[nptr],1+strlen(str));
539       n = 0;
540       while ((*str != '\0') && (*str != sep)) {
541         ptr[nptr][n] = *str;
542         str++;
543         n++;
544       }
545       ptr[nptr][n] = '\0';
546       nptr++;
547     }
548   }
549   ptr[nptr] = NULL;
550   
551   return ptr;
552 }
553
554
555 gmx_large_int_t
556 str_to_large_int_t(const char *str, char **endptr)
557 {
558         int         sign = 1;
559         gmx_large_int_t  val  = 0;
560         char        ch;
561         const char  *p;
562         
563         p = str;
564         if(p==NULL)
565         {
566                 *endptr=NULL;
567                 return 0;
568         }
569         
570         /* Strip off initial white space */
571         while(isspace(*p))
572         {
573                 p++;
574         }
575         /* Conform to ISO C99 - return original pointer if string does not contain a number */
576         if(*str=='\0')
577         {
578                 *endptr=(char *)str;
579         }
580         
581         if(*p=='-')
582         {
583                 p++;
584                 sign *= -1;
585         }
586         
587         while( ((ch=*p) != '\0') && isdigit(ch) )
588         {
589                 /* Important to add sign here, so we dont overflow in final multiplication */
590                 ch = (ch-'0')*sign; 
591                 val = val*10 + ch;
592                 if(ch != val%10) 
593                 {
594                         /* Some sort of overflow has occured, set endptr to original string */
595                         *endptr=(char *)str;
596                         errno = ERANGE;
597                         return(0);
598                 }
599                 p++;
600         }
601         
602         *endptr=(char *)p;
603         
604         return val;
605 }
606
607 char *gmx_strsep(char **stringp, const char *delim)
608 {
609     char *ret;
610     int len=strlen(delim);
611     int i,j=0;
612     int found=0;
613
614     if (! *stringp)
615         return NULL;
616     ret=*stringp;
617     do
618     {
619         if ( (*stringp)[j] == '\0')
620         {
621             found=1;
622             *stringp=NULL;
623             break;
624         }
625         for (i=0;i<len;i++)
626         {
627             if ( (*stringp)[j]==delim[i])
628             {
629                 (*stringp)[j]='\0';
630                 *stringp=*stringp+j+1;
631                 found=1;
632                 break;
633             }
634         }
635         j++;
636     } while (!found);
637
638     return ret;
639 }
640