Actual source code: str.c

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

  6: */
 7:  #include petsc.h
 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
 15: #include "petscfix.h"

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

 22:    Not Collective

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

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

 30:    Level: intermediate

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

 35:    Null string returns a length of zero

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

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

 56:    Not Collective

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

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

 64:    Level: intermediate

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

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

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

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

 93:    Not Collective

 95:    Input Parameters:
 96: .  s - pointer to string

 98:    Output Parameter:
 99: .  t - the copied string

101:    Level: intermediate

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

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

110: @*/
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 {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: +  s - pointer to string
131: -  n - the length to copy

133:    Output Parameter:
134: .  t - 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:   strncpy(s,t,n);
150:   return(0);
151: }

155: /*@C
156:    PetscStrcat - Concatenates a string onto a given string

158:    Not Collective

160:    Input Parameters:
161: +  s - pointer to string to be added to end
162: -  t - string to be added to

164:    Level: intermediate

166:   Concepts: string copy

168: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
169:   
170: @*/
171: PetscErrorCode PetscStrcat(char s[],const char t[])
172: {
174:   strcat(s,t);
175:   return(0);
176: }

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

183:    Not Collective

185:    Input Parameters:
186: +  s - pointer to string to be added to end
187: .  t - string to be added to
188: .  n - maximum length to copy 

190:    Level: intermediate

192:   Concepts: string copy

194: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
195:   
196: @*/
197: PetscErrorCode PetscStrncat(char s[],const char t[],size_t n)
198: {
200:   strncat(s,t,n);
201:   return(0);
202: }

206: /*@C
207:    PetscStrcmp - Compares two strings,

209:    Not Collective

211:    Input Parameters:
212: +  a - pointer to string first string
213: -  b - pointer to second string

215:    Output Parameter:
216: .  flg - if the two strings are equal

218:    Level: intermediate

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

222: @*/
223: PetscErrorCode PetscStrcmp(const char a[],const char b[],PetscTruth *flg)
224: {
225:   int c;

228:   if (!a && !b) {
229:     *flg = PETSC_TRUE;
230:   } else if (!a || !b) {
231:     *flg = PETSC_FALSE;
232:   } else {
233:     c = strcmp(a,b);
234:     if (c) *flg = PETSC_FALSE;
235:     else   *flg = PETSC_TRUE;
236:   }
237:   return(0);
238: }

242: /*@C
243:    PetscStrgrt - If first string is greater than the second

245:    Not Collective

247:    Input Parameters:
248: +  a - pointer to first string
249: -  b - pointer to second string

251:    Output Parameter:
252: .  flg - if the first string is greater

254:    Notes:
255:     Null arguments are ok, a null string is considered smaller than 
256:     all others

258:    Level: intermediate

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

262: @*/
263: PetscErrorCode PetscStrgrt(const char a[],const char b[],PetscTruth *t)
264: {
265:   int c;

268:   if (!a && !b) {
269:     *t = PETSC_FALSE;
270:   } else if (a && !b) {
271:     *t = PETSC_TRUE;
272:   } else if (!a && b) {
273:     *t = PETSC_FALSE;
274:   } else {
275:     c = strcmp(a,b);
276:     if (c > 0) *t = PETSC_TRUE;
277:     else       *t = PETSC_FALSE;
278:   }
279:   return(0);
280: }

284: /*@C
285:    PetscStrcasecmp - Returns true if the two strings are the same
286:      except possibly for case.

288:    Not Collective

290:    Input Parameters:
291: +  a - pointer to first string
292: -  b - pointer to second string

294:    Output Parameter:
295: .  flg - if the two strings are the same

297:    Notes:
298:     Null arguments are ok

300:    Level: intermediate

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

304: @*/
305: PetscErrorCode PetscStrcasecmp(const char a[],const char b[],PetscTruth *t)
306: {
307:   int c;

310:   if (!a && !b) c = 0;
311:   else if (!a || !b) c = 1;
312: #if defined(PETSC_HAVE_STRICMP)
313:   else c = stricmp(a,b);
314: #else
315:   else c = strcasecmp(a,b);
316: #endif
317:   if (!c) *t = PETSC_TRUE;
318:   else    *t = PETSC_FALSE;
319:   return(0);
320: }

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

327:    Not Collective

329:    Input Parameters:
330: +  a - pointer to first string
331: .  b - pointer to second string
332: -  n - length to compare up to

334:    Output Parameter:
335: .  t - if the two strings are equal

337:    Level: intermediate

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

341: @*/
342: PetscErrorCode PetscStrncmp(const char a[],const char b[],size_t n,PetscTruth *t)
343: {
344:   int c;

347:   c = strncmp(a,b,n);
348:   if (!c) *t = PETSC_TRUE;
349:   else    *t = PETSC_FALSE;
350:   return(0);
351: }

355: /*@C
356:    PetscStrchr - Locates first occurance of a character in a string

358:    Not Collective

360:    Input Parameters:
361: +  a - pointer to string
362: -  b - character

364:    Output Parameter:
365: .  c - location of occurance, PETSC_NULL if not found

367:    Level: intermediate

369: @*/
370: PetscErrorCode PetscStrchr(const char a[],char b,char *c[])
371: {
373:   *c = (char *)strchr(a,b);
374:   return(0);
375: }

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

383:    Not Collective

385:    Input Parameters:
386: +  a - pointer to string
387: -  b - character

389:    Output Parameter:
390: .  tmp - location of occurance, a if not found

392:    Level: intermediate

394: @*/
395: PetscErrorCode PetscStrrchr(const char a[],char b,char *tmp[])
396: {
398:   *tmp = (char *)strrchr(a,b);
399:   if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
400:   return(0);
401: }

405: /*@C
406:    PetscStrtolower - Converts string to lower case

408:    Not Collective

410:    Input Parameters:
411: .  a - pointer to string

413:    Level: intermediate

415: @*/
416: PetscErrorCode PetscStrtolower(char a[])
417: {
419:   while (*a) {
420:     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
421:     a++;
422:   }
423:   return(0);
424: }

428: /*@C
429:    PetscTokenFind - Locates next "token" in a string

431:    Not Collective

433:    Input Parameters:
434: .  a - pointer to token

436:    Output Parameter:
437: .  result - location of occurance, PETSC_NULL if not found

439:    Notes:

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

444:    Level: intermediate

446: .seealso: PetscTokenCreate(), PetscTokenDestroy()
447: @*/
448: PetscErrorCode PetscTokenFind(PetscToken *a,char *result[])
449: {
450:   char *ptr = a->current;

453:   *result = a->current;
454:   if (ptr && !*ptr) *result = 0;
455:   while (ptr) {
456:     if (*ptr == a->token) {
457:       *ptr++ = 0;
458:       while (*ptr == a->token) ptr++;
459:       a->current = ptr;
460:       break;
461:     }
462:     if (!*ptr) {
463:       a->current = 0;
464:       break;
465:     }
466:     ptr++;
467:   }
468:   return(0);
469: }

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

476:    Not Collective

478:    Input Parameters:
479: +  string - the string to look in
480: -  token - the character to look for

482:    Output Parameter:
483: .  a - pointer to token

485:    Notes:

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

490:    Level: intermediate

492: .seealso: PetscTokenFind(), PetscTokenDestroy()
493: @*/
494: PetscErrorCode PetscTokenCreate(const char a[],const char b,PetscToken **t)
495: {
497:   size_t         len;

500:   PetscNew(PetscToken,t);
501:   PetscStrlen(a,&len);
502:   PetscStrallocpy(a,&(*t)->array);
503:   (*t)->current = (*t)->array;
504:   (*t)->token   = b;
505:   return(0);
506: }

510: /*@C
511:    PetscTokenDestroy - Destroys a PetscToken

513:    Not Collective

515:    Input Parameters:
516: .  a - pointer to token

518:    Level: intermediate

520: .seealso: PetscTokenCreate(), PetscTokenFind()
521: @*/
522: PetscErrorCode PetscTokenDestroy(PetscToken *a)
523: {

527:   PetscFree(a->array);
528:   PetscFree(a);
529:   return(0);
530: }

534: /*@C
535:    PetscStrstr - Locates first occurance of string in another string

537:    Not Collective

539:    Input Parameters:
540: +  a - pointer to string
541: -  b - string to find

543:    Output Parameter:
544: .  tmp - location of occurance

546:    Level: intermediate

548: @*/
549: PetscErrorCode PetscStrstr(const char a[],const char b[],char *tmp[])
550: {
552:   *tmp = (char *)strstr(a,b);
553:   return(0);
554: }

558: /*@C
559:    PetscGetPetscDir - Gets the directory PETSc is installed in

561:    Not Collective

563:    Output Parameter:
564: .  dir - the directory

566:    Level: developer

568: @*/
569: PetscErrorCode PetscGetPetscDir(const char *dir[])
570: {
572:   *dir = PETSC_DIR;
573:   return(0);
574: }

578: /*@C
579:    PetscStrreplace - Replaces substrings in string with other substrings

581:    Not Collective

583:    Input Parameters:
584: +   comm - MPI_Comm of processors that are processing the string
585: .   a - the string to look in
586: .   b - the resulting copy of a with replaced strings
587: -   len - the length of b

589:    Notes:
590:       Replaces   ${PETSC_ARCH},${BOPT},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
591:       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME} with appropriate values
592:       as well as any environmental variables.
593:    
594:    Level: intermediate

596: @*/
597: PetscErrorCode PetscStrreplace(MPI_Comm comm,const char a[],char b[],size_t len)
598: {
600:   int            i = 0;
601:   size_t         l,l1,l2,l3;
602:   char           *work,*par,*epar,env[1024],*tfree;
603:   const char     *s[] = {"${PETSC_ARCH}","${BOPT}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}",0};
604:   const char     *r[] = {PETSC_ARCH,PETSC_BOPT,PETSC_DIR,PETSC_LIB_DIR,0,0,0,0,0};
605:   PetscTruth     flag;

608:   if (!a || !b) SETERRQ(PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
609:   PetscMalloc(len*sizeof(char*),&work);

611:   /* get values for replaced variables */
612:   PetscMalloc(256*sizeof(char),&r[4]);
613:   PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);
614:   PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[6]);
615:   PetscMalloc(256*sizeof(char),&r[7]);
616:   PetscGetDisplay((char*)r[4],256);
617:   PetscGetHomeDirectory((char*)r[5],PETSC_MAX_PATH_LEN);
618:   PetscGetWorkingDirectory((char*)r[6],PETSC_MAX_PATH_LEN);
619:   PetscGetUserName((char*)r[7],256);

621:   /* replace the requested strings */
622:   PetscStrncpy(b,a,len);
623:   while (s[i]) {
624:     PetscStrlen(s[i],&l);
625:     PetscStrstr(b,s[i],&par);
626:     while (par) {
627:       *par  =  0;
628:       par  += l;

630:       PetscStrlen(b,&l1);
631:       PetscStrlen(r[i],&l2);
632:       PetscStrlen(par,&l3);
633:       if (l1 + l2 + l3 >= len) {
634:         SETERRQ(PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
635:       }
636:       PetscStrcpy(work,b);
637:       PetscStrcat(work,r[i]);
638:       PetscStrcat(work,par);
639:       PetscStrncpy(b,work,len);
640:       PetscStrstr(b,s[i],&par);
641:     }
642:     i++;
643:   }
644:   for ( i=4; i<8; i++){
645:     tfree = (char*)r[i];
646:     PetscFree(tfree);
647:   }

649:   /* look for any other ${xxx} strings to replace from environmental variables */
650:   PetscStrstr(b,"${",&par);
651:   while (par) {
652:     *par = 0;
653:     par += 2;
654:     PetscStrcpy(work,b);
655:     PetscStrstr(par,"}",&epar);
656:     *epar = 0;
657:     epar += 1;
658:     PetscOptionsGetenv(comm,par,env,256,&flag);
659:     if (!flag) {
660:       SETERRQ1(PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
661:     }
662:     PetscStrcat(work,env);
663:     PetscStrcat(work,epar);
664:     PetscStrcpy(b,work);
665:     PetscStrstr(b,"${",&par);
666:   }
667:   PetscFree(work);
668:   return(0);
669: }

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

674:    Not Collective

676:    Synopsis:
677:    PetscErrorCode PetscStrfree(char *s)

679:    Input Parameter:
680: .  s - pointer to string

682:    Level: intermediate

684:   Concepts: string free
685:   
686: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat(), PetscStrallocpy()

688: M*/