Don't use POSIX fnmatch() for pattern matching.
[gromacs/qmmm-gamess-us.git] / src / gmxlib / string2.c
blob752d1038f8fed5dcb7928b8b354b32b5a20f2274
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.
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.
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.
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.
30 * For more info, check our website at http://www.gromacs.org
32 * And Hey:
33 * GROningen Mixture of Alchemy and Childrens' Stories
35 /* This file is completely threadsafe - keep it that way! */
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
40 #ifdef GMX_CRAY_XT3
41 #undef HAVE_PWD_H
42 #endif
44 #include <stdio.h>
45 #include <ctype.h>
46 #include <stdlib.h>
47 #include <errno.h>
48 #include <sys/types.h>
50 #ifdef HAVE_PWD_H
51 #include <pwd.h>
52 #endif
53 #include <time.h>
55 #include "typedefs.h"
56 #include "smalloc.h"
57 #include "gmx_fatal.h"
58 #include "macros.h"
59 #include "string2.h"
61 int continuing(char *s)
62 /* strip trailing spaces and if s ends with a CONTINUE remove that too.
63 * returns TRUE if s ends with a CONTINUE, FALSE otherwise.
66 int sl;
68 rtrim(s);
69 sl = strlen(s);
70 if ((sl > 0) && (s[sl-1] == CONTINUE)) {
71 s[sl-1] = 0;
72 return TRUE;
74 else
75 return FALSE;
78 char *fgets2(char *line, int n, FILE *stream)
79 /* This routine reads a string from stream of max length n
80 * and zero terminated, without newlines
81 * line should be long enough (>= n)
84 char *c;
85 if (fgets(line,n,stream)==NULL) return NULL;
86 if ((c=strchr(line,'\n'))!=NULL) *c=0;
87 if ((c=strchr(line,'\r'))!=NULL) *c=0;
88 return line;
91 void strip_comment (char *line)
93 char *c;
95 if (!line)
96 return;
98 /* search for a comment mark and replace it by a zero */
99 if ((c = strchr(line,COMMENTSIGN)) != NULL)
100 (*c) = 0;
103 void upstring (char *str)
105 int i;
107 for (i=0; (i < (int)strlen(str)); i++)
108 str[i] = toupper(str[i]);
111 void ltrim (char *str)
113 char *tr;
114 int c;
116 if (!str)
117 return;
119 tr = strdup (str);
120 c = 0;
121 while ((tr[c] == ' ') || (tr[c] == '\t'))
122 c++;
124 strcpy (str,tr+c);
125 free (tr);
128 void rtrim (char *str)
130 int nul;
132 if (!str)
133 return;
135 nul = strlen(str)-1;
136 while ((nul > 0) && ((str[nul] == ' ') || (str[nul] == '\t')) ) {
137 str[nul] = '\0';
138 nul--;
142 void trim (char *str)
144 ltrim (str);
145 rtrim (str);
148 void nice_header (FILE *out,const char *fn)
150 const char *unk = "onbekend";
151 time_t clock;
152 char *user=NULL;
153 int gh;
154 uid_t uid;
155 char buf[256];
156 #ifdef HAVE_PWD_H
157 struct passwd *pw;
158 #endif
160 /* Print a nice header above the file */
161 clock = time (0);
162 fprintf (out,"%c\n",COMMENTSIGN);
163 fprintf (out,"%c\tFile '%s' was generated\n",COMMENTSIGN,fn ? fn : unk);
165 #ifdef HAVE_PWD_H
166 uid = getuid();
167 pw = getpwuid(uid);
168 gh = gethostname(buf,255);
169 user= pw->pw_name;
170 #else
171 uid = 0;
172 gh = -1;
173 #endif
175 fprintf (out,"%c\tBy user: %s (%d)\n",COMMENTSIGN,
176 user ? user : unk,(int) uid);
177 fprintf(out,"%c\tOn host: %s\n",COMMENTSIGN,(gh == 0) ? buf : unk);
179 fprintf (out,"%c\tAt date: %s",COMMENTSIGN,ctime(&clock));
180 fprintf (out,"%c\n",COMMENTSIGN);
183 int strcasecmp_min(const char *str1, const char *str2)
185 char ch1,ch2;
190 ch1=toupper(*(str1++));
191 while ((ch1=='-') || (ch1=='_'));
193 ch2=toupper(*(str2++));
194 while ((ch2=='-') || (ch2=='_'));
195 if (ch1!=ch2) return (ch1-ch2);
197 while (ch1);
198 return 0;
201 int strncasecmp_min(const char *str1, const char *str2, int n)
203 char ch1,ch2;
204 char *stri1, *stri2;
206 stri1=(char *)str1;
207 stri2=(char *)str2;
211 ch1=toupper(*(str1++));
212 while ((ch1=='-') || (ch1=='_'));
214 ch2=toupper(*(str2++));
215 while ((ch2=='-') || (ch2=='_'));
216 if (ch1!=ch2) return (ch1-ch2);
218 while (ch1 && (str1-stri1<n) && (str2-stri2<n));
219 return 0;
222 int gmx_strcasecmp(const char *str1, const char *str2)
224 char ch1,ch2;
228 ch1=toupper(*(str1++));
229 ch2=toupper(*(str2++));
230 if (ch1!=ch2) return (ch1-ch2);
232 while (ch1);
233 return 0;
236 int gmx_strncasecmp(const char *str1, const char *str2, int n)
238 char ch1,ch2;
240 if(n==0)
241 return 0;
245 ch1=toupper(*(str1++));
246 ch2=toupper(*(str2++));
247 if (ch1!=ch2) return (ch1-ch2);
248 n--;
250 while (ch1 && n);
251 return 0;
254 char *gmx_strdup(const char *src)
256 char *dest;
258 snew(dest,strlen(src)+1);
259 strcpy(dest,src);
261 return dest;
264 char *
265 gmx_strndup(const char *src, int n)
267 int len;
268 char *dest;
270 len = strlen(src);
271 if (len > n)
273 len = n;
275 snew(dest, len+1);
276 strncpy(dest, src, len);
277 dest[len] = 0;
278 return dest;
282 * \param[in] pattern Pattern to match against.
283 * \param[in] str String to match.
284 * \returns 0 on match, GMX_NO_WCMATCH if there is no match.
286 * Matches \p str against \p pattern, which may contain * and ? wildcards.
287 * All other characters are matched literally.
288 * Currently, it is not possible to match literal * or ?.
291 gmx_wcmatch(const char *pattern, const char *str)
293 while (*pattern)
295 if (*pattern == '*')
297 /* Skip multiple wildcards in a sequence */
298 while (*pattern == '*' || *pattern == '?')
300 ++pattern;
301 /* For ?, we need to check that there are characters left
302 * in str. */
303 if (*pattern == '?')
305 if (*str == 0)
307 return GMX_NO_WCMATCH;
309 else
311 ++str;
315 /* If the pattern ends after the star, we have a match */
316 if (*pattern == 0)
318 return 0;
320 /* Match the rest against each possible suffix of str */
321 while (*str)
323 /* Only do the recursive call if the first character
324 * matches. We don't have to worry about wildcards here,
325 * since we have processed them above. */
326 if (*pattern == *str)
328 int rc;
329 /* Match the suffix, and return if a match or an error */
330 rc = gmx_wcmatch(pattern, str);
331 if (rc != GMX_NO_WCMATCH)
333 return rc;
336 ++str;
338 /* If no suffix of str matches, we don't have a match */
339 return GMX_NO_WCMATCH;
341 else if ((*pattern == '?' && *str != 0) || *pattern == *str)
343 ++str;
345 else
347 return GMX_NO_WCMATCH;
349 ++pattern;
351 return 0;
354 char *wrap_lines(const char *buf,int line_width, int indent,bool bIndentFirst)
356 char *b2;
357 int i,i0,i2,j,b2len,lspace=0,l2space=0;
358 bool bFirst,bFitsOnLine;
360 /* characters are copied from buf to b2 with possible spaces changed
361 * into newlines and extra space added for indentation.
362 * i indexes buf (source buffer) and i2 indexes b2 (destination buffer)
363 * i0 points to the beginning of the current line (in buf, source)
364 * lspace and l2space point to the last space on the current line
365 * bFirst is set to prevent indentation of first line
366 * bFitsOnLine says if the first space occurred before line_width, if
367 * that is not the case, we have a word longer than line_width which
368 * will also not fit on the next line, so we might as well keep it on
369 * the current line (where it also won't fit, but looks better)
372 b2=NULL;
373 b2len=strlen(buf)+1+indent;
374 snew(b2,b2len);
375 i0=i2=0;
376 if (bIndentFirst)
377 for(i2=0; (i2<indent); i2++)
378 b2[i2] = ' ';
379 bFirst=TRUE;
380 do {
381 l2space = -1;
382 /* find the last space before end of line */
383 for(i=i0; ((i-i0 < line_width) || (l2space==-1)) && (buf[i]); i++) {
384 b2[i2++] = buf[i];
385 /* remember the position of a space */
386 if (buf[i] == ' ') {
387 lspace = i;
388 l2space = i2-1;
390 /* if we have a newline before the line is full, reset counters */
391 if (buf[i]=='\n' && buf[i+1]) {
392 i0=i+1;
393 b2len+=indent;
394 srenew(b2, b2len);
395 /* add indentation after the newline */
396 for(j=0; (j<indent); j++)
397 b2[i2++]=' ';
400 /* If we are at the last newline, copy it */
401 if (buf[i]=='\n' && !buf[i+1]) {
402 b2[i2++] = buf[i++];
404 /* if we're not at the end of the string */
405 if (buf[i]) {
406 /* check if one word does not fit on the line */
407 bFitsOnLine = (i-i0 <= line_width);
408 /* reset line counters to just after the space */
409 i0 = lspace+1;
410 i2 = l2space+1;
411 /* if the words fit on the line, and we're beyond the indentation part */
412 if ( (bFitsOnLine) && (l2space >= indent) ) {
413 /* start a new line */
414 b2[l2space] = '\n';
415 /* and add indentation */
416 if (indent) {
417 if (bFirst) {
418 line_width-=indent;
419 bFirst=FALSE;
421 b2len+=indent;
422 srenew(b2, b2len);
423 for(j=0; (j<indent); j++)
424 b2[i2++]=' ';
425 /* no extra spaces after indent; */
426 while(buf[i0]==' ')
427 i0++;
431 } while (buf[i]);
432 b2[i2] = '\0';
434 return b2;
437 char **split(char sep,char *str)
439 char **ptr = NULL;
440 int n,nn,nptr = 0;
442 if (str == NULL)
443 return NULL;
444 nn = strlen(str);
445 for(n=0; (n<nn); n++)
446 if (str[n] == sep)
447 nptr++;
448 snew(ptr,nptr+2);
449 nptr = 0;
450 while (*str != '\0') {
451 while ((*str != '\0') && (*str == sep))
452 str++;
453 if (*str != '\0') {
454 snew(ptr[nptr],1+strlen(str));
455 n = 0;
456 while ((*str != '\0') && (*str != sep)) {
457 ptr[nptr][n] = *str;
458 str++;
459 n++;
461 ptr[nptr][n] = '\0';
462 nptr++;
465 ptr[nptr] = NULL;
467 return ptr;
471 gmx_large_int_t
472 str_to_large_int_t(const char *str, char **endptr)
474 int sign = 1;
475 gmx_large_int_t val = 0;
476 char ch;
477 const char *p;
479 p = str;
480 if(p==NULL)
482 *endptr=NULL;
483 return 0;
486 /* Strip off initial white space */
487 while(isspace(*p))
489 p++;
491 /* Conform to ISO C99 - return original pointer if string does not contain a number */
492 if(*str=='\0')
494 *endptr=(char *)str;
497 if(*p=='-')
499 p++;
500 sign *= -1;
503 while( ((ch=*p) != '\0') && isdigit(ch) )
505 /* Important to add sign here, so we dont overflow in final multiplication */
506 ch = (ch-'0')*sign;
507 val = val*10 + ch;
508 if(ch != val%10)
510 /* Some sort of overflow has occured, set endptr to original string */
511 *endptr=(char *)str;
512 errno = ERANGE;
513 return(0);
515 p++;
518 *endptr=(char *)p;
520 return val;
523 char *gmx_strsep(char **stringp, const char *delim)
525 char *ret;
526 int len=strlen(delim);
527 int i,j=0;
528 int found=0;
530 if (! *stringp)
531 return NULL;
532 ret=*stringp;
535 if ( (*stringp)[j] == '\0')
537 found=1;
538 *stringp=NULL;
539 break;
541 for (i=0;i<len;i++)
543 if ( (*stringp)[j]==delim[i])
545 (*stringp)[j]='\0';
546 *stringp=*stringp+j+1;
547 found=1;
548 break;
551 j++;
552 } while (!found);
554 return ret;