Actual source code: str.c

  1: #define PETSC_DLL
  2: /*
  3:     We define the string operations here. The reason we just do not use 
  4:   the standard string routines in the PETSc code is that on some machines 
  5:   they are broken or have the wrong prototypes.

  7: */
 8:  #include petsc.h
 9:  #include petscsys.h
 10: #if defined(PETSC_HAVE_STRING_H)
 11: #include <string.h>
 12: #endif
 13: #if defined(PETSC_HAVE_STRINGS_H)
 14: #include <strings.h>
 15: #endif
 16: #include "petscfix.h"

 20: /*@C
 21:    PetscStrlen - Gets length of a string

 23:    Not Collective

 25:    Input Parameters:
 26: .  s - pointer to string

 28:    Output Parameter:
 29: .  len - length in bytes

 31:    Level: intermediate

 33:    Note:
 34:    This routine is analogous to strlen().

 36:    Null string returns a length of zero

 38:   Concepts: string length
 39:   
 40: @*/
 41: PetscErrorCode  PetscStrlen(const char s[],size_t *len)
 42: {
 44:   if (!s) {
 45:     *len = 0;
 46:   } else {
 47:     *len = strlen(s);
 48:   }
 49:   return(0);
 50: }

 54: /*@C
 55:    PetscStrallocpy - Allocates space to hold a copy of a string then copies the string

 57:    Not Collective

 59:    Input Parameters:
 60: .  s - pointer to string

 62:    Output Parameter:
 63: .  t - the copied string

 65:    Level: intermediate

 67:    Note:
 68:       Null string returns a new null string

 70:   Concepts: string copy
 71:   
 72: @*/
 73: PetscErrorCode  PetscStrallocpy(const char s[],char *t[])
 74: {
 76:   size_t         len;
 77:   char           *tmp = 0;

 80:   if (s) {
 81:     PetscStrlen(s,&len);
 82:     PetscMalloc((1+len)*sizeof(char),&tmp);
 83:     PetscStrcpy(tmp,s);
 84:   }
 85:   *t = tmp;
 86:   return(0);
 87: }

 91: /*@C
 92:    PetscStrcpy - Copies a string

 94:    Not Collective

 96:    Input Parameters:
 97: .  t - pointer to string

 99:    Output Parameter:
100: .  s - the copied string

102:    Level: intermediate

104:    Note:
105:      Null string returns a string starting with zero

107:   Concepts: string copy
108:   
109: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()

111: @*/
112: PetscErrorCode  PetscStrcpy(char s[],const char t[])
113: {
115:   if (t && !s) {
116:     SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
117:   }
118:   if (t) {strcpy(s,t);}
119:   else if (s) {s[0] = 0;}
120:   return(0);
121: }

125: /*@C
126:    PetscStrncpy - Copies a string up to a certain length

128:    Not Collective

130:    Input Parameters:
131: +  t - pointer to string
132: -  n - the length to copy

134:    Output Parameter:
135: .  s - the copied string

137:    Level: intermediate

139:    Note:
140:      Null string returns a string starting with zero

142:   Concepts: string copy

144: .seealso: PetscStrcpy(), PetscStrcat(), PetscStrncat()
145:   
146: @*/
147: PetscErrorCode  PetscStrncpy(char s[],const char t[],size_t n)
148: {
150:   if (t && !s) {
151:     SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
152:   }
153:   if (t) {strncpy(s,t,n);}
154:   else if (s) {s[0] = 0;}
155:   return(0);
156: }

160: /*@C
161:    PetscStrcat - Concatenates a string onto a given string

163:    Not Collective

165:    Input Parameters:
166: +  s - string to be added to
167: -  t - pointer to string to be added to end

169:    Level: intermediate

171:   Concepts: string copy

173: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
174:   
175: @*/
176: PetscErrorCode  PetscStrcat(char s[],const char t[])
177: {
179:   strcat(s,t);
180:   return(0);
181: }

185: /*@C
186:    PetscStrncat - Concatenates a string onto a given string, up to a given length

188:    Not Collective

190:    Input Parameters:
191: +  s - pointer to string to be added to end
192: .  t - string to be added to
193: .  n - maximum length to copy 

195:    Level: intermediate

197:   Concepts: string copy

199: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
200:   
201: @*/
202: PetscErrorCode  PetscStrncat(char s[],const char t[],size_t n)
203: {
205:   strncat(s,t,n);
206:   return(0);
207: }

211: /*@C
212:    PetscStrcmp - Compares two strings,

214:    Not Collective

216:    Input Parameters:
217: +  a - pointer to string first string
218: -  b - pointer to second string

220:    Output Parameter:
221: .  flg - if the two strings are equal

223:    Level: intermediate

225: .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()

227: @*/
228: PetscErrorCode  PetscStrcmp(const char a[],const char b[],PetscTruth *flg)
229: {
230:   int c;

233:   if (!a && !b) {
234:     *flg = PETSC_TRUE;
235:   } else if (!a || !b) {
236:     *flg = PETSC_FALSE;
237:   } else {
238:     c = strcmp(a,b);
239:     if (c) *flg = PETSC_FALSE;
240:     else   *flg = PETSC_TRUE;
241:   }
242:   return(0);
243: }

247: /*@C
248:    PetscStrgrt - If first string is greater than the second

250:    Not Collective

252:    Input Parameters:
253: +  a - pointer to first string
254: -  b - pointer to second string

256:    Output Parameter:
257: .  flg - if the first string is greater

259:    Notes:
260:     Null arguments are ok, a null string is considered smaller than 
261:     all others

263:    Level: intermediate

265: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()

267: @*/
268: PetscErrorCode  PetscStrgrt(const char a[],const char b[],PetscTruth *t)
269: {
270:   int c;

273:   if (!a && !b) {
274:     *t = PETSC_FALSE;
275:   } else if (a && !b) {
276:     *t = PETSC_TRUE;
277:   } else if (!a && b) {
278:     *t = PETSC_FALSE;
279:   } else {
280:     c = strcmp(a,b);
281:     if (c > 0) *t = PETSC_TRUE;
282:     else       *t = PETSC_FALSE;
283:   }
284:   return(0);
285: }

289: /*@C
290:    PetscStrcasecmp - Returns true if the two strings are the same
291:      except possibly for case.

293:    Not Collective

295:    Input Parameters:
296: +  a - pointer to first string
297: -  b - pointer to second string

299:    Output Parameter:
300: .  flg - if the two strings are the same

302:    Notes:
303:     Null arguments are ok

305:    Level: intermediate

307: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()

309: @*/
310: PetscErrorCode  PetscStrcasecmp(const char a[],const char b[],PetscTruth *t)
311: {
312:   int c;

315:   if (!a && !b) c = 0;
316:   else if (!a || !b) c = 1;
317: #if defined(PETSC_HAVE_STRICMP)
318:   else c = stricmp(a,b);
319: #else
320:   else c = strcasecmp(a,b);
321: #endif
322:   if (!c) *t = PETSC_TRUE;
323:   else    *t = PETSC_FALSE;
324:   return(0);
325: }

329: /*@C
330:    PetscStrncmp - Compares two strings, up to a certain length

332:    Not Collective

334:    Input Parameters:
335: +  a - pointer to first string
336: .  b - pointer to second string
337: -  n - length to compare up to

339:    Output Parameter:
340: .  t - if the two strings are equal

342:    Level: intermediate

344: .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()

346: @*/
347: PetscErrorCode  PetscStrncmp(const char a[],const char b[],size_t n,PetscTruth *t)
348: {
349:   int c;

352:   c = strncmp(a,b,n);
353:   if (!c) *t = PETSC_TRUE;
354:   else    *t = PETSC_FALSE;
355:   return(0);
356: }

360: /*@C
361:    PetscStrchr - Locates first occurance of a character in a string

363:    Not Collective

365:    Input Parameters:
366: +  a - pointer to string
367: -  b - character

369:    Output Parameter:
370: .  c - location of occurance, PETSC_NULL if not found

372:    Level: intermediate

374: @*/
375: PetscErrorCode  PetscStrchr(const char a[],char b,char *c[])
376: {
378:   *c = (char *)strchr(a,b);
379:   return(0);
380: }

384: /*@C
385:    PetscStrrchr - Locates one location past the last occurance of a character in a string,
386:       if the character is not found then returns entire string

388:    Not Collective

390:    Input Parameters:
391: +  a - pointer to string
392: -  b - character

394:    Output Parameter:
395: .  tmp - location of occurance, a if not found

397:    Level: intermediate

399: @*/
400: PetscErrorCode  PetscStrrchr(const char a[],char b,char *tmp[])
401: {
403:   *tmp = (char *)strrchr(a,b);
404:   if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
405:   return(0);
406: }

410: /*@C
411:    PetscStrtolower - Converts string to lower case

413:    Not Collective

415:    Input Parameters:
416: .  a - pointer to string

418:    Level: intermediate

420: @*/
421: PetscErrorCode  PetscStrtolower(char a[])
422: {
424:   while (*a) {
425:     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
426:     a++;
427:   }
428:   return(0);
429: }

433: /*@C
434:    PetscTokenFind - Locates next "token" in a string

436:    Not Collective

438:    Input Parameters:
439: .  a - pointer to token

441:    Output Parameter:
442: .  result - location of occurance, PETSC_NULL if not found

444:    Notes:

446:      This version is different from the system version in that
447:   it allows you to pass a read-only string into the function.

449:    Level: intermediate

451: .seealso: PetscTokenCreate(), PetscTokenDestroy()
452: @*/
453: PetscErrorCode  PetscTokenFind(PetscToken *a,char *result[])
454: {
455:   char *ptr = a->current;

458:   *result = a->current;
459:   if (ptr && !*ptr) *result = 0;
460:   while (ptr) {
461:     if (*ptr == a->token) {
462:       *ptr++ = 0;
463:       while (*ptr == a->token) ptr++;
464:       a->current = ptr;
465:       break;
466:     }
467:     if (!*ptr) {
468:       a->current = 0;
469:       break;
470:     }
471:     ptr++;
472:   }
473:   return(0);
474: }

478: /*@C
479:    PetscTokenCreate - Creates a PetscToken used to find tokens in a string

481:    Not Collective

483:    Input Parameters:
484: +  string - the string to look in
485: -  token - the character to look for

487:    Output Parameter:
488: .  a - pointer to token

490:    Notes:

492:      This version is different from the system version in that
493:   it allows you to pass a read-only string into the function.

495:    Level: intermediate

497: .seealso: PetscTokenFind(), PetscTokenDestroy()
498: @*/
499: PetscErrorCode  PetscTokenCreate(const char a[],const char b,PetscToken **t)
500: {
502:   size_t         len;

505:   PetscNew(PetscToken,t);
506:   PetscStrlen(a,&len);
507:   PetscStrallocpy(a,&(*t)->array);
508:   (*t)->current = (*t)->array;
509:   (*t)->token   = b;
510:   return(0);
511: }

515: /*@C
516:    PetscTokenDestroy - Destroys a PetscToken

518:    Not Collective

520:    Input Parameters:
521: .  a - pointer to token

523:    Level: intermediate

525: .seealso: PetscTokenCreate(), PetscTokenFind()
526: @*/
527: PetscErrorCode  PetscTokenDestroy(PetscToken *a)
528: {

532:   PetscFree(a->array);
533:   PetscFree(a);
534:   return(0);
535: }

539: /*@C
540:    PetscStrrstr - Locates last occurance of string in another string

542:    Not Collective

544:    Input Parameters:
545: +  a - pointer to string
546: -  b - string to find

548:    Output Parameter:
549: .  tmp - location of occurance

551:    Level: intermediate

553: @*/
554: PetscErrorCode  PetscStrrstr(const char a[],const char b[],char *tmp[])
555: {
556:   const char *stmp = a, *ltmp = 0;

559:   while (stmp) {
560:     stmp = (char *)strstr(stmp,b);
561:     if (stmp) {ltmp = stmp;stmp++;}
562:   }
563:   *tmp = (char *)ltmp;
564:   return(0);
565: }

569: /*@C
570:    PetscStrstr - Locates first occurance of string in another string

572:    Not Collective

574:    Input Parameters:
575: +  a - pointer to string
576: -  b - string to find

578:    Output Parameter:
579: .  tmp - location of occurance

581:    Level: intermediate

583: @*/
584: PetscErrorCode  PetscStrstr(const char a[],const char b[],char *tmp[])
585: {
587:   *tmp = (char *)strstr(a,b);
588:   return(0);
589: }

593: /*@C
594:    PetscGetPetscDir - Gets the directory PETSc is installed in

596:    Not Collective

598:    Output Parameter:
599: .  dir - the directory

601:    Level: developer

603: @*/
604: PetscErrorCode  PetscGetPetscDir(const char *dir[])
605: {
607:   *dir = PETSC_DIR;
608:   return(0);
609: }

613: /*@C
614:    PetscStrreplace - Replaces substrings in string with other substrings

616:    Not Collective

618:    Input Parameters:
619: +   comm - MPI_Comm of processors that are processing the string
620: .   aa - the string to look in
621: .   b - the resulting copy of a with replaced strings (b can be the same as a)
622: -   len - the length of b

624:    Notes:
625:       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
626:       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME} with appropriate values
627:       as well as any environmental variables.
628:    
629:    Level: intermediate

631: @*/
632: PetscErrorCode  PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
633: {
635:   int            i = 0;
636:   size_t         l,l1,l2,l3;
637:   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
638:   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}",0};
639:   const char     *r[] = {PETSC_ARCH,PETSC_DIR,PETSC_LIB_DIR,0,0,0,0,0};
640:   PetscTruth     flag;

643:   if (!a || !b) SETERRQ(PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
644:   if (aa == b) {
645:     PetscStrallocpy(aa,(char **)&a);
646:   }
647:   PetscMalloc(len*sizeof(char*),&work);

649:   /* get values for replaced variables */
650:   PetscMalloc(256*sizeof(char),&r[4]);
651:   PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);
652:   PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[6]);
653:   PetscMalloc(256*sizeof(char),&r[7]);
654:   PetscGetDisplay((char*)r[4],256);
655:   PetscGetHomeDirectory((char*)r[5],PETSC_MAX_PATH_LEN);
656:   PetscGetWorkingDirectory((char*)r[6],PETSC_MAX_PATH_LEN);
657:   PetscGetUserName((char*)r[7],256);

659:   /* replace the requested strings */
660:   PetscStrncpy(b,a,len);
661:   while (s[i]) {
662:     PetscStrlen(s[i],&l);
663:     PetscStrstr(b,s[i],&par);
664:     while (par) {
665:       *par  =  0;
666:       par  += l;

668:       PetscStrlen(b,&l1);
669:       PetscStrlen(r[i],&l2);
670:       PetscStrlen(par,&l3);
671:       if (l1 + l2 + l3 >= len) {
672:         SETERRQ(PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
673:       }
674:       PetscStrcpy(work,b);
675:       PetscStrcat(work,r[i]);
676:       PetscStrcat(work,par);
677:       PetscStrncpy(b,work,len);
678:       PetscStrstr(b,s[i],&par);
679:     }
680:     i++;
681:   }
682:   for ( i=4; i<8; i++){
683:     tfree = (char*)r[i];
684:     PetscFree(tfree);
685:   }

687:   /* look for any other ${xxx} strings to replace from environmental variables */
688:   PetscStrstr(b,"${",&par);
689:   while (par) {
690:     *par = 0;
691:     par += 2;
692:     PetscStrcpy(work,b);
693:     PetscStrstr(par,"}",&epar);
694:     *epar = 0;
695:     epar += 1;
696:     PetscOptionsGetenv(comm,par,env,256,&flag);
697:     if (!flag) {
698:       SETERRQ1(PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
699:     }
700:     PetscStrcat(work,env);
701:     PetscStrcat(work,epar);
702:     PetscStrcpy(b,work);
703:     PetscStrstr(b,"${",&par);
704:   }
705:   PetscFree(work);
706:   if (aa == b) {
707:     PetscFree(a);
708:   }
709:   return(0);
710: }

712: /*MC
713:    PetscStrfree - Frees a string (if it is not null)

715:    Not Collective

717:    Synopsis:
718:    PetscErrorCode PetscStrfree(char *s)

720:    Input Parameter:
721: .  s - pointer to string

723:    Level: intermediate

725:   Concepts: string free
726:   
727: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat(), PetscStrallocpy()

729: M*/