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 petscsys.h
  9: #if defined(PETSC_HAVE_STRING_H)
 10: #include <string.h>
 11: #endif
 12: #if defined(PETSC_HAVE_STRINGS_H)
 13: #include <strings.h>
 14: #endif

 18: /*@C
 19:    PetscStrlen - Gets length of a string

 21:    Not Collective

 23:    Input Parameters:
 24: .  s - pointer to string

 26:    Output Parameter:
 27: .  len - length in bytes

 29:    Level: intermediate

 31:    Note:
 32:    This routine is analogous to strlen().

 34:    Null string returns a length of zero

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

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

 55:    Not Collective

 57:    Input Parameters:
 58: .  s - pointer to string

 60:    Output Parameter:
 61: .  t - the copied string

 63:    Level: intermediate

 65:    Note:
 66:       Null string returns a new null string

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

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

 89: /*@C
 90:    PetscStrcpy - Copies a string

 92:    Not Collective

 94:    Input Parameters:
 95: .  t - pointer to string

 97:    Output Parameter:
 98: .  s - the copied string

100:    Level: intermediate

102:    Note:
103:      Null string returns a string starting with zero

105:   Concepts: string copy
106:   
107: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()

109: @*/

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

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

127:    Not Collective

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

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

136:    Level: intermediate

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

141:   Concepts: string copy

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

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

162:    Not Collective

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

168:    Level: intermediate

170:   Concepts: string copy

172: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
173:   
174: @*/
175: PetscErrorCode  PetscStrcat(char s[],const char t[])
176: {
178:   if (!t) return(0);
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_STRCASECMP)
318:   else c = strcasecmp(a,b);
319: #elif defined(PETSC_HAVE_STRICMP)
320:   else c = stricmp(a,b);
321: #else
322:   else {
323:     char *aa,*bb;
325:     PetscStrallocpy(a,&aa);
326:     PetscStrallocpy(b,&bb);
327:     PetscStrtolower(aa);
328:     PetscStrtolower(bb);
329:     PetscStrcmp(aa,bb,t);
330:     PetscStrfree(aa);
331:     PetscStrfree(bb);
332:     return(0);
333:   }
334: #endif
335:   if (!c) *t = PETSC_TRUE;
336:   else    *t = PETSC_FALSE;
337:   return(0);
338: }



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

347:    Not Collective

349:    Input Parameters:
350: +  a - pointer to first string
351: .  b - pointer to second string
352: -  n - length to compare up to

354:    Output Parameter:
355: .  t - if the two strings are equal

357:    Level: intermediate

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

361: @*/
362: PetscErrorCode  PetscStrncmp(const char a[],const char b[],size_t n,PetscTruth *t)
363: {
364:   int c;

367:   c = strncmp(a,b,n);
368:   if (!c) *t = PETSC_TRUE;
369:   else    *t = PETSC_FALSE;
370:   return(0);
371: }

375: /*@C
376:    PetscStrchr - Locates first occurance of a character in a string

378:    Not Collective

380:    Input Parameters:
381: +  a - pointer to string
382: -  b - character

384:    Output Parameter:
385: .  c - location of occurance, PETSC_NULL if not found

387:    Level: intermediate

389: @*/
390: PetscErrorCode  PetscStrchr(const char a[],char b,char *c[])
391: {
393:   *c = (char *)strchr(a,b);
394:   return(0);
395: }

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

403:    Not Collective

405:    Input Parameters:
406: +  a - pointer to string
407: -  b - character

409:    Output Parameter:
410: .  tmp - location of occurance, a if not found

412:    Level: intermediate

414: @*/
415: PetscErrorCode  PetscStrrchr(const char a[],char b,char *tmp[])
416: {
418:   *tmp = (char *)strrchr(a,b);
419:   if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
420:   return(0);
421: }

425: /*@C
426:    PetscStrtolower - Converts string to lower case

428:    Not Collective

430:    Input Parameters:
431: .  a - pointer to string

433:    Level: intermediate

435: @*/
436: PetscErrorCode  PetscStrtolower(char a[])
437: {
439:   while (*a) {
440:     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
441:     a++;
442:   }
443:   return(0);
444: }

446: struct _p_PetscToken {char token;char *array;char *current;};


451: /*@C
452:    PetscTokenFind - Locates next "token" in a string

454:    Not Collective

456:    Input Parameters:
457: .  a - pointer to token

459:    Output Parameter:
460: .  result - location of occurance, PETSC_NULL if not found

462:    Notes:

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

467:      This version also treats all characters etc. inside a double quote "
468:    as a single token.

470:    Level: intermediate

472: .seealso: PetscTokenCreate(), PetscTokenDestroy()
473: @*/
474: PetscErrorCode  PetscTokenFind(PetscToken a,char *result[])
475: {
476:   char *ptr = a->current,token;

479:   *result = a->current;
480:   if (ptr && !*ptr) {*result = 0;return(0);}
481:   token = a->token;
482:   if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
483:   while (ptr) {
484:     if (*ptr == token) {
485:       *ptr++ = 0;
486:       while (*ptr == a->token) ptr++;
487:       a->current = ptr;
488:       break;
489:     }
490:     if (!*ptr) {
491:       a->current = 0;
492:       break;
493:     }
494:     ptr++;
495:   }
496:   return(0);
497: }

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

504:    Not Collective

506:    Input Parameters:
507: +  string - the string to look in
508: -  token - the character to look for

510:    Output Parameter:
511: .  a - pointer to token

513:    Notes:

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

518:    Level: intermediate

520: .seealso: PetscTokenFind(), PetscTokenDestroy()
521: @*/
522: PetscErrorCode  PetscTokenCreate(const char a[],const char b,PetscToken *t)
523: {

527:   PetscNew(struct _p_PetscToken,t);
528:   PetscStrallocpy(a,&(*t)->array);
529:   (*t)->current = (*t)->array;
530:   (*t)->token   = b;
531:   return(0);
532: }

536: /*@C
537:    PetscTokenDestroy - Destroys a PetscToken

539:    Not Collective

541:    Input Parameters:
542: .  a - pointer to token

544:    Level: intermediate

546: .seealso: PetscTokenCreate(), PetscTokenFind()
547: @*/
548: PetscErrorCode  PetscTokenDestroy(PetscToken a)
549: {

553:   PetscFree(a->array);
554:   PetscFree(a);
555:   return(0);
556: }

560: /*@C
561:    PetscStrrstr - Locates last occurance of string in another string

563:    Not Collective

565:    Input Parameters:
566: +  a - pointer to string
567: -  b - string to find

569:    Output Parameter:
570: .  tmp - location of occurance

572:    Level: intermediate

574: @*/
575: PetscErrorCode  PetscStrrstr(const char a[],const char b[],char *tmp[])
576: {
577:   const char *stmp = a, *ltmp = 0;

580:   while (stmp) {
581:     stmp = (char *)strstr(stmp,b);
582:     if (stmp) {ltmp = stmp;stmp++;}
583:   }
584:   *tmp = (char *)ltmp;
585:   return(0);
586: }

590: /*@C
591:    PetscStrstr - Locates first occurance of string in another string

593:    Not Collective

595:    Input Parameters:
596: +  a - pointer to string
597: -  b - string to find

599:    Output Parameter:
600: .  tmp - location of occurance

602:    Level: intermediate

604: @*/
605: PetscErrorCode  PetscStrstr(const char a[],const char b[],char *tmp[])
606: {
608:   *tmp = (char *)strstr(a,b);
609:   return(0);
610: }

614: /*@C
615:    PetscGetPetscDir - Gets the directory PETSc is installed in

617:    Not Collective

619:    Output Parameter:
620: .  dir - the directory

622:    Level: developer

624: @*/
625: PetscErrorCode  PetscGetPetscDir(const char *dir[])
626: {
628:   *dir = PETSC_DIR;
629:   return(0);
630: }

634: /*@C
635:    PetscStrreplace - Replaces substrings in string with other substrings

637:    Not Collective

639:    Input Parameters:
640: +   comm - MPI_Comm of processors that are processing the string
641: .   aa - the string to look in
642: .   b - the resulting copy of a with replaced strings (b can be the same as a)
643: -   len - the length of b

645:    Notes:
646:       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
647:       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME} with appropriate values
648:       as well as any environmental variables.

650:       Note: PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what
651:       PETSc was built with and do not use environmental variables.
652:    
653:    Level: intermediate

655: @*/
656: PetscErrorCode  PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
657: {
659:   int            i = 0;
660:   size_t         l,l1,l2,l3;
661:   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
662:   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}",0};
663:   const char     *r[] = {0,0,0,0,0,0,0,0};
664:   PetscTruth     flag;

667:   if (!a || !b) SETERRQ(PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
668:   if (aa == b) {
669:     PetscStrallocpy(aa,(char **)&a);
670:   }
671:   PetscMalloc(len*sizeof(char*),&work);

673:   /* get values for replaced variables */
674:   PetscStrallocpy(PETSC_ARCH,(char**)&r[0]);
675:   PetscStrallocpy(PETSC_DIR,(char**)&r[1]);
676:   PetscStrallocpy(PETSC_LIB_DIR,(char**)&r[2]);
677:   PetscMalloc(256*sizeof(char),&r[3]);
678:   PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[4]);
679:   PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);
680:   PetscMalloc(256*sizeof(char),&r[6]);
681:   PetscGetDisplay((char*)r[3],256);
682:   PetscGetHomeDirectory((char*)r[4],PETSC_MAX_PATH_LEN);
683:   PetscGetWorkingDirectory((char*)r[5],PETSC_MAX_PATH_LEN);
684:   PetscGetUserName((char*)r[6],256);

686:   /* replace that are in environment */
687:   PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);
688:   if (flag) {
689:     PetscStrallocpy(env,(char**)&r[2]);
690:   }

692:   /* replace the requested strings */
693:   PetscStrncpy(b,a,len);
694:   while (s[i]) {
695:     PetscStrlen(s[i],&l);
696:     PetscStrstr(b,s[i],&par);
697:     while (par) {
698:       *par  =  0;
699:       par  += l;

701:       PetscStrlen(b,&l1);
702:       PetscStrlen(r[i],&l2);
703:       PetscStrlen(par,&l3);
704:       if (l1 + l2 + l3 >= len) {
705:         SETERRQ(PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
706:       }
707:       PetscStrcpy(work,b);
708:       PetscStrcat(work,r[i]);
709:       PetscStrcat(work,par);
710:       PetscStrncpy(b,work,len);
711:       PetscStrstr(b,s[i],&par);
712:     }
713:     i++;
714:   }
715:   i = 0;
716:   while (r[i]) {
717:     tfree = (char*)r[i];
718:     PetscFree(tfree);
719:     i++;
720:   }

722:   /* look for any other ${xxx} strings to replace from environmental variables */
723:   PetscStrstr(b,"${",&par);
724:   while (par) {
725:     *par = 0;
726:     par += 2;
727:     PetscStrcpy(work,b);
728:     PetscStrstr(par,"}",&epar);
729:     *epar = 0;
730:     epar += 1;
731:     PetscOptionsGetenv(comm,par,env,256,&flag);
732:     if (!flag) {
733:       SETERRQ1(PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
734:     }
735:     PetscStrcat(work,env);
736:     PetscStrcat(work,epar);
737:     PetscStrcpy(b,work);
738:     PetscStrstr(b,"${",&par);
739:   }
740:   PetscFree(work);
741:   if (aa == b) {
742:     PetscFree(a);
743:   }
744:   return(0);
745: }

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

750:    Not Collective

752:    Synopsis:
753:    PetscErrorCode PetscStrfree(char *s)

755:    Input Parameter:
756: .  s - pointer to string

758:    Level: intermediate

760:   Concepts: string free
761:   
762: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat(), PetscStrallocpy()

764: M*/