Include Gromacs files with double quotes in C++ code.
[alexxy/gromacs.git] / src / gromacs / 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 "gromacs/utility/gmx_header_config.h"
40
41 #ifdef GMX_CRAY_XT3
42 #undef HAVE_PWD_H
43 #endif
44
45 #include <stdio.h>
46 #include <ctype.h>
47 #include <stdlib.h>
48 #include <errno.h>
49 #include <sys/types.h>
50 #include <time.h>
51
52 #ifdef HAVE_SYS_TIME_H
53 #include <sys/time.h>
54 #endif
55
56 #ifdef HAVE_UNISTD_H
57 #include <unistd.h>
58 #endif
59
60 #ifdef HAVE_PWD_H
61 #include <pwd.h>
62 #endif
63 #include <time.h>
64 #include <assert.h>
65
66 #include "typedefs.h"
67 #include "smalloc.h"
68 #include "gmx_fatal.h"
69 #include "macros.h"
70 #include "string2.h"
71 #include "futil.h"
72
73 int continuing(char *s)
74 {
75   int sl;
76   assert(s);
77
78   rtrim(s);
79   sl = strlen(s);
80   if ((sl > 0) && (s[sl-1] == CONTINUE)) {
81     s[sl-1] = 0;
82     return TRUE;
83   }
84   else
85     return FALSE;
86 }
87
88
89
90 char *fgets2(char *line, int n, FILE *stream)
91 {
92   char *c;
93   if (fgets(line,n,stream) == NULL) {
94     return NULL;
95   }
96   if ((c=strchr(line,'\n')) != NULL) {
97     *c = '\0';
98   } else {
99     /* A line not ending in a newline can only occur at the end of a file,
100      * or because of n being too small.
101      * Since both cases occur very infrequently, we can check for EOF.
102      */
103     if (!gmx_eof(stream)) {
104       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);
105     }
106   }
107   if ((c=strchr(line,'\r')) != NULL) {
108     *c = '\0';
109   }
110
111   return line;
112 }
113
114 void strip_comment (char *line)
115 {
116   char *c;
117
118   if (!line)
119     return;
120
121   /* search for a comment mark and replace it by a zero */
122   if ((c = strchr(line,COMMENTSIGN)) != NULL) 
123     (*c) = 0;
124 }
125
126 void upstring (char *str)
127 {
128   int i;
129
130   for (i=0; (i < (int)strlen(str)); i++) 
131     str[i] = toupper(str[i]);
132 }
133
134 void ltrim (char *str)
135 {
136   char *tr;
137   int i,c;
138
139   if (NULL == str)
140     return;
141
142   c = 0;
143   while (('\0' != str[c]) && isspace(str[c]))
144     c++;
145   if (c > 0) 
146     {
147       for(i=c; ('\0' != str[i]); i++)
148         str[i-c] = str[i];
149       str[i-c] = '\0';
150     }
151 }
152
153 void rtrim (char *str)
154 {
155   int nul;
156
157   if (NULL == str)
158     return;
159
160   nul = strlen(str)-1;
161   while ((nul > 0) && ((str[nul] == ' ') || (str[nul] == '\t')) ) {
162     str[nul] = '\0';
163     nul--;
164   }
165 }
166
167 void trim (char *str)
168 {
169   ltrim (str);
170   rtrim (str);
171 }
172
173 char *
174 gmx_ctime_r(const time_t *clock,char *buf, int n)
175 {
176     char tmpbuf[STRLEN];
177   
178 #ifdef GMX_NATIVE_WINDOWS
179     /* Windows */
180     ctime_s( tmpbuf, STRLEN, clock );
181 #elif (defined(__sun))
182     /*Solaris*/
183     ctime_r(clock, tmpbuf, n);
184 #else
185     ctime_r(clock,tmpbuf);
186 #endif
187     strncpy(buf,tmpbuf,n-1);
188     buf[n-1]='\0';
189     
190     return buf;
191 }
192           
193 void nice_header (FILE *out,const char *fn)
194 {
195   const char *unk = "onbekend";
196   time_t clock;
197   const char *user=unk;
198   int    gh;
199 #ifdef HAVE_PWD_H
200   uid_t  uid;
201 #else
202   int    uid;
203 #endif
204   char   buf[256]="";
205   char   timebuf[STRLEN];
206 #ifdef HAVE_PWD_H
207   struct passwd *pw;
208 #endif
209
210   /* Print a nice header above the file */
211   time(&clock);
212   fprintf (out,"%c\n",COMMENTSIGN);
213   fprintf (out,"%c\tFile '%s' was generated\n",COMMENTSIGN,fn ? fn : unk);
214   
215 #ifdef HAVE_PWD_H
216   uid = getuid();
217   pw  = getpwuid(uid);
218   gh  = gethostname(buf,255);
219   user= pw->pw_name;
220 #else
221   uid = 0;
222   gh  = -1;
223 #endif
224   
225   gmx_ctime_r(&clock,timebuf,STRLEN);
226   fprintf (out,"%c\tBy user: %s (%d)\n",COMMENTSIGN,
227            user ? user : unk,(int) uid);
228   fprintf(out,"%c\tOn host: %s\n",COMMENTSIGN,(gh == 0) ? buf : unk);
229
230   fprintf (out,"%c\tAt date: %s",COMMENTSIGN,timebuf);
231   fprintf (out,"%c\n",COMMENTSIGN);
232 }
233
234 int gmx_strcasecmp_min(const char *str1, const char *str2)
235 {
236   char ch1,ch2;
237   
238   do
239     {
240       do
241         ch1=toupper(*(str1++));
242       while ((ch1=='-') || (ch1=='_'));
243       do 
244         ch2=toupper(*(str2++));
245       while ((ch2=='-') || (ch2=='_'));
246       if (ch1!=ch2) return (ch1-ch2);
247     }
248   while (ch1);
249   return 0; 
250 }
251
252 int gmx_strncasecmp_min(const char *str1, const char *str2, int n)
253 {
254   char ch1,ch2;
255   char *stri1, *stri2;
256
257   stri1=(char *)str1;
258   stri2=(char *)str2;  
259   do
260     {
261       do
262         ch1=toupper(*(str1++));
263       while ((ch1=='-') || (ch1=='_'));
264       do 
265         ch2=toupper(*(str2++));
266       while ((ch2=='-') || (ch2=='_'));
267       if (ch1!=ch2) return (ch1-ch2);
268     }
269   while (ch1 && (str1-stri1<n) && (str2-stri2<n));
270   return 0; 
271 }
272
273 int gmx_strcasecmp(const char *str1, const char *str2)
274 {
275   char ch1,ch2;
276   
277   do
278     {
279       ch1=toupper(*(str1++));
280       ch2=toupper(*(str2++));
281       if (ch1!=ch2) return (ch1-ch2);
282     }
283   while (ch1);
284   return 0; 
285 }
286
287 int gmx_strncasecmp(const char *str1, const char *str2, int n)
288 {
289   char ch1,ch2;
290  
291   if(n==0) 
292     return 0;
293
294   do
295     {
296       ch1=toupper(*(str1++));
297       ch2=toupper(*(str2++));
298       if (ch1!=ch2) return (ch1-ch2);
299       n--;
300     }
301   while (ch1 && n);
302   return 0; 
303 }
304
305 char *gmx_strdup(const char *src)
306 {
307   char *dest;
308
309   snew(dest,strlen(src)+1);
310   strcpy(dest,src);
311   
312   return dest;
313 }
314
315 char *
316 gmx_strndup(const char *src, int n)
317 {
318     int   len;
319     char *dest;
320
321     len = strlen(src);
322     if (len > n) 
323     {
324         len = n;
325     }
326     snew(dest, len+1);
327     strncpy(dest, src, len);
328     dest[len] = 0;
329     return dest;
330 }
331
332 int
333 gmx_wcmatch(const char *pattern, const char *str)
334 {
335     while (*pattern)
336     {
337         if (*pattern == '*')
338         {
339             /* Skip multiple wildcards in a sequence */
340             while (*pattern == '*' || *pattern == '?')
341             {
342                 ++pattern;
343                 /* For ?, we need to check that there are characters left
344                  * in str. */
345                 if (*pattern == '?')
346                 {
347                     if (*str == 0)
348                     {
349                         return GMX_NO_WCMATCH;
350                     }
351                     else
352                     {
353                         ++str;
354                     }
355                 }
356             }
357             /* If the pattern ends after the star, we have a match */
358             if (*pattern == 0)
359             {
360                 return 0;
361             }
362             /* Match the rest against each possible suffix of str */
363             while (*str)
364             {
365                 /* Only do the recursive call if the first character
366                  * matches. We don't have to worry about wildcards here,
367                  * since we have processed them above. */
368                 if (*pattern == *str)
369                 {
370                     int rc;
371                     /* Match the suffix, and return if a match or an error */
372                     rc = gmx_wcmatch(pattern, str);
373                     if (rc != GMX_NO_WCMATCH)
374                     {
375                         return rc;
376                     }
377                 }
378                 ++str;
379             }
380             /* If no suffix of str matches, we don't have a match */
381             return GMX_NO_WCMATCH;
382         }
383         else if ((*pattern == '?' && *str != 0) || *pattern == *str)
384         {
385             ++str;
386         }
387         else
388         {
389             return GMX_NO_WCMATCH;
390         }
391         ++pattern;
392     }
393     /* When the pattern runs out, we have a match if the string has ended. */
394     return (*str == 0) ? 0 : GMX_NO_WCMATCH;
395 }
396
397 char *wrap_lines(const char *buf,int line_width, int indent,gmx_bool bIndentFirst)
398 {
399   char *b2;
400   int i,i0,i2,j,b2len,lspace=0,l2space=0;
401   gmx_bool bFirst,bFitsOnLine;
402
403   /* characters are copied from buf to b2 with possible spaces changed
404    * into newlines and extra space added for indentation.
405    * i indexes buf (source buffer) and i2 indexes b2 (destination buffer)
406    * i0 points to the beginning of the current line (in buf, source)
407    * lspace and l2space point to the last space on the current line
408    * bFirst is set to prevent indentation of first line
409    * bFitsOnLine says if the first space occurred before line_width, if 
410    * that is not the case, we have a word longer than line_width which 
411    * will also not fit on the next line, so we might as well keep it on 
412    * the current line (where it also won't fit, but looks better)
413    */
414   
415   b2=NULL;
416   b2len=strlen(buf)+1+indent;
417   snew(b2,b2len);
418   i0=i2=0;
419   if (bIndentFirst)
420     for(i2=0; (i2<indent); i2++)
421       b2[i2] = ' ';
422   bFirst=TRUE;
423   do {
424     l2space = -1;
425     /* find the last space before end of line */
426     for(i=i0; ((i-i0 < line_width) || (l2space==-1)) && (buf[i]); i++) {
427       b2[i2++] = buf[i];
428       /* remember the position of a space */
429       if (buf[i] == ' ') {
430         lspace = i;
431         l2space = i2-1;
432       }
433       /* if we have a newline before the line is full, reset counters */
434       if (buf[i]=='\n' && buf[i+1]) { 
435         i0=i+1;
436         b2len+=indent;
437         srenew(b2, b2len);
438         /* add indentation after the newline */
439         for(j=0; (j<indent); j++)
440           b2[i2++]=' ';
441       }
442     }
443     /* If we are at the last newline, copy it */
444     if (buf[i]=='\n' && !buf[i+1]) {
445       b2[i2++] = buf[i++];
446     }
447     /* if we're not at the end of the string */
448     if (buf[i]) {
449       /* check if one word does not fit on the line */
450       bFitsOnLine = (i-i0 <= line_width);
451       /* reset line counters to just after the space */
452       i0 = lspace+1;
453       i2 = l2space+1;
454       /* if the words fit on the line, and we're beyond the indentation part */
455       if ( (bFitsOnLine) && (l2space >= indent) ) {
456         /* start a new line */
457         b2[l2space] = '\n';
458         /* and add indentation */
459         if (indent) {
460           if (bFirst) {
461             line_width-=indent;
462             bFirst=FALSE;
463           }
464           b2len+=indent;
465           srenew(b2, b2len);
466           for(j=0; (j<indent); j++)
467             b2[i2++]=' ';
468           /* no extra spaces after indent; */
469           while(buf[i0]==' ')
470             i0++;
471         }
472       }
473     }
474   } while (buf[i]);
475   b2[i2] = '\0';
476   
477   return b2;
478 }
479
480 char **split(char sep,const char *str)
481 {
482   char **ptr = NULL;
483   int  n,nn,nptr = 0;
484   
485   if (str == NULL)
486     return NULL;
487   nn = strlen(str);
488   for(n=0; (n<nn); n++)
489     if (str[n] == sep)
490       nptr++;
491   snew(ptr,nptr+2);
492   nptr = 0;
493   while (*str != '\0') {
494     while ((*str != '\0') && (*str == sep))
495       str++;
496     if (*str != '\0') {
497       snew(ptr[nptr],1+strlen(str));
498       n = 0;
499       while ((*str != '\0') && (*str != sep)) {
500         ptr[nptr][n] = *str;
501         str++;
502         n++;
503       }
504       ptr[nptr][n] = '\0';
505       nptr++;
506     }
507   }
508   ptr[nptr] = NULL;
509   
510   return ptr;
511 }
512
513
514 gmx_large_int_t
515 str_to_large_int_t(const char *str, char **endptr)
516 {
517         int         sign = 1;
518         gmx_large_int_t  val  = 0;
519         char        ch;
520         const char  *p;
521         
522         p = str;
523         if(p==NULL)
524         {
525                 *endptr=NULL;
526                 return 0;
527         }
528         
529         /* Strip off initial white space */
530         while(isspace(*p))
531         {
532                 p++;
533         }
534         /* Conform to ISO C99 - return original pointer if string does not contain a number */
535         if(*str=='\0')
536         {
537                 *endptr=(char *)str;
538         }
539         
540         if(*p=='-')
541         {
542                 p++;
543                 sign *= -1;
544         }
545         
546         while( ((ch=*p) != '\0') && isdigit(ch) )
547         {
548                 /* Important to add sign here, so we dont overflow in final multiplication */
549                 ch = (ch-'0')*sign; 
550                 val = val*10 + ch;
551                 if(ch != val%10) 
552                 {
553                         /* Some sort of overflow has occured, set endptr to original string */
554                         *endptr=(char *)str;
555                         errno = ERANGE;
556                         return(0);
557                 }
558                 p++;
559         }
560         
561         *endptr=(char *)p;
562         
563         return val;
564 }
565
566 char *gmx_strsep(char **stringp, const char *delim)
567 {
568     char *ret;
569     int len=strlen(delim);
570     int i,j=0;
571     int found=0;
572
573     if (! *stringp)
574         return NULL;
575     ret=*stringp;
576     do
577     {
578         if ( (*stringp)[j] == '\0')
579         {
580             found=1;
581             *stringp=NULL;
582             break;
583         }
584         for (i=0;i<len;i++)
585         {
586             if ( (*stringp)[j]==delim[i])
587             {
588                 (*stringp)[j]='\0';
589                 *stringp=*stringp+j+1;
590                 found=1;
591                 break;
592             }
593         }
594         j++;
595     } while (!found);
596
597     return ret;
598 }
599