Actual source code: str.c

petsc-3.11.4 2019-09-28
Report Typos and Errors

  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>             /* strstr */
 11: #endif
 12: #if defined(PETSC_HAVE_STRINGS_H)
 13: #  include <strings.h>          /* strcasecmp */
 14: #endif

 16: /*@C
 17:    PetscStrToArray - Separates a string by a charactor (for example ' ' or '\n') and creates an array of strings

 19:    Not Collective

 21:    Input Parameters:
 22: +  s - pointer to string
 23: -  sp - separator charactor

 25:    Output Parameter:
 26: +   argc - the number of entries in the array
 27: -   args - an array of the entries with a null at the end

 29:    Level: intermediate

 31:    Notes:
 32:     this may be called before PetscInitialize() or after PetscFinalize()

 34:    Not for use in Fortran

 36:    Developer Notes:
 37:     Using raw malloc() and does not call error handlers since this may be used before PETSc is initialized. Used
 38:      to generate argc, args arguments passed to MPI_Init()

 40: .seealso: PetscStrToArrayDestroy(), PetscToken, PetscTokenCreate()

 42: @*/
 43: PetscErrorCode  PetscStrToArray(const char s[],char sp,int *argc,char ***args)
 44: {
 45:   int       i,j,n,*lens,cnt = 0;
 46:   PetscBool flg = PETSC_FALSE;

 48:   if (!s) n = 0;
 49:   else    n = strlen(s);
 50:   *argc = 0;
 51:   *args = NULL;
 52:   for (; n>0; n--) {   /* remove separator chars at the end - and will empty the string if all chars are separator chars */
 53:     if (s[n-1] != sp) break;
 54:   }
 55:   if (!n) {
 56:     return(0);
 57:   }
 58:   for (i=0; i<n; i++) {
 59:     if (s[i] != sp) break;
 60:   }
 61:   for (;i<n+1; i++) {
 62:     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
 63:     else if (s[i] != sp) {flg = PETSC_FALSE;}
 64:   }
 65:   (*args) = (char**) malloc(((*argc)+1)*sizeof(char*)); if (!*args) return PETSC_ERR_MEM;
 66:   lens    = (int*) malloc((*argc)*sizeof(int)); if (!lens) return PETSC_ERR_MEM;
 67:   for (i=0; i<*argc; i++) lens[i] = 0;

 69:   *argc = 0;
 70:   for (i=0; i<n; i++) {
 71:     if (s[i] != sp) break;
 72:   }
 73:   for (;i<n+1; i++) {
 74:     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
 75:     else if (s[i] != sp) {lens[*argc]++;flg = PETSC_FALSE;}
 76:   }

 78:   for (i=0; i<*argc; i++) {
 79:     (*args)[i] = (char*) malloc((lens[i]+1)*sizeof(char));
 80:     if (!(*args)[i]) {
 81:       free(lens);
 82:       for (j=0; j<i; j++) free((*args)[j]);
 83:       free(*args);
 84:       return PETSC_ERR_MEM;
 85:     }
 86:   }
 87:   free(lens);
 88:   (*args)[*argc] = 0;

 90:   *argc = 0;
 91:   for (i=0; i<n; i++) {
 92:     if (s[i] != sp) break;
 93:   }
 94:   for (;i<n+1; i++) {
 95:     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*args)[*argc][cnt++] = 0; (*argc)++; cnt = 0;}
 96:     else if (s[i] != sp && s[i] != 0) {(*args)[*argc][cnt++] = s[i]; flg = PETSC_FALSE;}
 97:   }
 98:   return 0;
 99: }

101: /*@C
102:    PetscStrToArrayDestroy - Frees array created with PetscStrToArray().

104:    Not Collective

106:    Output Parameters:
107: +  argc - the number of arguments
108: -  args - the array of arguments

110:    Level: intermediate

112:    Concepts: command line arguments

114:    Notes:
115:     This may be called before PetscInitialize() or after PetscFinalize()

117:    Not for use in Fortran

119: .seealso: PetscStrToArray()

121: @*/
122: PetscErrorCode  PetscStrToArrayDestroy(int argc,char **args)
123: {
124:   PetscInt i;

126:   for (i=0; i<argc; i++) free(args[i]);
127:   if (args) free(args);
128:   return 0;
129: }

131: /*@C
132:    PetscStrlen - Gets length of a string

134:    Not Collective

136:    Input Parameters:
137: .  s - pointer to string

139:    Output Parameter:
140: .  len - length in bytes

142:    Level: intermediate

144:    Note:
145:    This routine is analogous to strlen().

147:    Null string returns a length of zero

149:    Not for use in Fortran

151:   Concepts: string length

153: @*/
154: PetscErrorCode  PetscStrlen(const char s[],size_t *len)
155: {
157:   if (!s) *len = 0;
158:   else    *len = strlen(s);
159:   return(0);
160: }

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

165:    Not Collective

167:    Input Parameters:
168: .  s - pointer to string

170:    Output Parameter:
171: .  t - the copied string

173:    Level: intermediate

175:    Note:
176:       Null string returns a new null string

178:       Not for use in Fortran

180:   Concepts: string copy

182: @*/
183: PetscErrorCode  PetscStrallocpy(const char s[],char *t[])
184: {
186:   size_t         len;
187:   char           *tmp = 0;

190:   if (s) {
191:     PetscStrlen(s,&len);
192:     PetscMalloc1(1+len,&tmp);
193:     PetscStrcpy(tmp,s);
194:   }
195:   *t = tmp;
196:   return(0);
197: }

199: /*@C
200:    PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings

202:    Not Collective

204:    Input Parameters:
205: .  s - pointer to array of strings (final string is a null)

207:    Output Parameter:
208: .  t - the copied array string

210:    Level: intermediate

212:    Note:
213:       Not for use in Fortran

215:   Concepts: string copy

217: .seealso: PetscStrallocpy() PetscStrArrayDestroy()

219: @*/
220: PetscErrorCode  PetscStrArrayallocpy(const char *const *list,char ***t)
221: {
223:   PetscInt       i,n = 0;

226:   while (list[n++]) ;
227:   PetscMalloc1(n+1,t);
228:   for (i=0; i<n; i++) {
229:     PetscStrallocpy(list[i],(*t)+i);
230:   }
231:   (*t)[n] = NULL;
232:   return(0);
233: }

235: /*@C
236:    PetscStrArrayDestroy - Frees array of strings created with PetscStrArrayallocpy().

238:    Not Collective

240:    Output Parameters:
241: .   list - array of strings

243:    Level: intermediate

245:    Concepts: command line arguments

247:    Notes:
248:     Not for use in Fortran

250: .seealso: PetscStrArrayallocpy()

252: @*/
253: PetscErrorCode PetscStrArrayDestroy(char ***list)
254: {
255:   PetscInt       n = 0;

259:   if (!*list) return(0);
260:   while ((*list)[n]) {
261:     PetscFree((*list)[n]);
262:     n++;
263:   }
264:   PetscFree(*list);
265:   return(0);
266: }

268: /*@C
269:    PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings

271:    Not Collective

273:    Input Parameters:
274: +  n - the number of string entries
275: -  s - pointer to array of strings

277:    Output Parameter:
278: .  t - the copied array string

280:    Level: intermediate

282:    Note:
283:       Not for use in Fortran

285:   Concepts: string copy

287: .seealso: PetscStrallocpy() PetscStrArrayDestroy()

289: @*/
290: PetscErrorCode  PetscStrNArrayallocpy(PetscInt n,const char *const *list,char ***t)
291: {
293:   PetscInt       i;

296:   PetscMalloc1(n,t);
297:   for (i=0; i<n; i++) {
298:     PetscStrallocpy(list[i],(*t)+i);
299:   }
300:   return(0);
301: }

303: /*@C
304:    PetscStrNArrayDestroy - Frees array of strings created with PetscStrArrayallocpy().

306:    Not Collective

308:    Output Parameters:
309: +   n - number of string entries
310: -   list - array of strings

312:    Level: intermediate

314:    Notes:
315:     Not for use in Fortran

317: .seealso: PetscStrArrayallocpy()

319: @*/
320: PetscErrorCode PetscStrNArrayDestroy(PetscInt n,char ***list)
321: {
323:   PetscInt       i;

326:   if (!*list) return(0);
327:   for (i=0; i<n; i++){
328:     PetscFree((*list)[i]);
329:   }
330:   PetscFree(*list);
331:   return(0);
332: }

334: /*@C
335:    PetscStrcpy - Copies a string

337:    Not Collective

339:    Input Parameters:
340: .  t - pointer to string

342:    Output Parameter:
343: .  s - the copied string

345:    Level: intermediate

347:    Notes:
348:      Null string returns a string starting with zero

350:      Not for use in Fortran

352:   Concepts: string copy

354: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrlcat()

356: @*/

358: PetscErrorCode  PetscStrcpy(char s[],const char t[])
359: {
361:   if (t && !s) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
362:   if (t) strcpy(s,t);
363:   else if (s) s[0] = 0;
364:   return(0);
365: }

367: /*@C
368:    PetscStrncpy - Copies a string up to a certain length

370:    Not Collective

372:    Input Parameters:
373: +  t - pointer to string
374: -  n - the length to copy

376:    Output Parameter:
377: .  s - the copied string

379:    Level: intermediate

381:    Note:
382:      Null string returns a string starting with zero

384:      If the string that is being copied is of length n or larger then the entire string is not
385:      copied and the final location of s is set to NULL. This is different then the behavior of 
386:      strncpy() which leaves s non-terminated if there is not room for the entire string.

388:   Concepts: string copy

390:   Developers Note: Should this be PetscStrlcpy() to reflect its behavior which is like strlcpy() not strncpy()

392: .seealso: PetscStrcpy(), PetscStrcat(), PetscStrlcat()

394: @*/
395: PetscErrorCode  PetscStrncpy(char s[],const char t[],size_t n)
396: {
398:   if (t && !s) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
399:   if (s && !n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Requires an output string of length at least 1 to hold the termination character");
400:   if (t) {
401:     if (n > 1) {
402:       strncpy(s,t,n-1);
403:       s[n-1] = '\0';
404:     } else {
405:       s[0] = '\0';
406:     }
407:   } else if (s) s[0] = 0;
408:   return(0);
409: }

411: /*@C
412:    PetscStrcat - Concatenates a string onto a given string

414:    Not Collective

416:    Input Parameters:
417: +  s - string to be added to
418: -  t - pointer to string to be added to end

420:    Level: intermediate

422:    Notes:
423:     Not for use in Fortran

425:   Concepts: string copy

427: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrlcat()

429: @*/
430: PetscErrorCode  PetscStrcat(char s[],const char t[])
431: {
433:   if (!t) return(0);
434:   strcat(s,t);
435:   return(0);
436: }

438: /*@C
439:    PetscStrlcat - Concatenates a string onto a given string, up to a given length

441:    Not Collective

443:    Input Parameters:
444: +  s - pointer to string to be added to at end
445: .  t - string to be added to
446: -  n - length of the original allocated string

448:    Level: intermediate

450:   Notes:
451:   Not for use in Fortran

453:   Unlike the system call strncat(), the length passed in is the length of the
454:   original allocated space, not the length of the left-over space. This is
455:   similar to the BSD system call strlcat().

457:   Concepts: string copy

459: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()

461: @*/
462: PetscErrorCode  PetscStrlcat(char s[],const char t[],size_t n)
463: {
464:   size_t         len;

468:   if (t && !n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"String buffer length must be positive");
469:   if (!t) return(0);
470:   PetscStrlen(t,&len);
471:   strncat(s,t,n - len);
472:   s[n-1] = 0;
473:   return(0);
474: }

476: void  PetscStrcmpNoError(const char a[],const char b[],PetscBool  *flg)
477: {
478:   int c;

480:   if (!a && !b)      *flg = PETSC_TRUE;
481:   else if (!a || !b) *flg = PETSC_FALSE;
482:   else {
483:     c = strcmp(a,b);
484:     if (c) *flg = PETSC_FALSE;
485:     else   *flg = PETSC_TRUE;
486:   }
487: }

489: /*@C
490:    PetscStrcmp - Compares two strings,

492:    Not Collective

494:    Input Parameters:
495: +  a - pointer to string first string
496: -  b - pointer to second string

498:    Output Parameter:
499: .  flg - PETSC_TRUE if the two strings are equal

501:    Level: intermediate

503:    Notes:
504:     Not for use in Fortran

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

508: @*/
509: PetscErrorCode  PetscStrcmp(const char a[],const char b[],PetscBool  *flg)
510: {
511:   int c;

514:   if (!a && !b)      *flg = PETSC_TRUE;
515:   else if (!a || !b) *flg = PETSC_FALSE;
516:   else {
517:     c = strcmp(a,b);
518:     if (c) *flg = PETSC_FALSE;
519:     else   *flg = PETSC_TRUE;
520:   }
521:   return(0);
522: }

524: /*@C
525:    PetscStrgrt - If first string is greater than the second

527:    Not Collective

529:    Input Parameters:
530: +  a - pointer to first string
531: -  b - pointer to second string

533:    Output Parameter:
534: .  flg - if the first string is greater

536:    Notes:
537:     Null arguments are ok, a null string is considered smaller than
538:     all others

540:    Not for use in Fortran

542:    Level: intermediate

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

546: @*/
547: PetscErrorCode  PetscStrgrt(const char a[],const char b[],PetscBool  *t)
548: {
549:   int c;

552:   if (!a && !b) *t = PETSC_FALSE;
553:   else if (a && !b) *t = PETSC_TRUE;
554:   else if (!a && b) *t = PETSC_FALSE;
555:   else {
556:     c = strcmp(a,b);
557:     if (c > 0) *t = PETSC_TRUE;
558:     else       *t = PETSC_FALSE;
559:   }
560:   return(0);
561: }

563: /*@C
564:    PetscStrcasecmp - Returns true if the two strings are the same
565:      except possibly for case.

567:    Not Collective

569:    Input Parameters:
570: +  a - pointer to first string
571: -  b - pointer to second string

573:    Output Parameter:
574: .  flg - if the two strings are the same

576:    Notes:
577:     Null arguments are ok

579:    Not for use in Fortran

581:    Level: intermediate

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

585: @*/
586: PetscErrorCode  PetscStrcasecmp(const char a[],const char b[],PetscBool  *t)
587: {
588:   int c;

591:   if (!a && !b) c = 0;
592:   else if (!a || !b) c = 1;
593: #if defined(PETSC_HAVE_STRCASECMP)
594:   else c = strcasecmp(a,b);
595: #elif defined(PETSC_HAVE_STRICMP)
596:   else c = stricmp(a,b);
597: #else
598:   else {
599:     char           *aa,*bb;
601:     PetscStrallocpy(a,&aa);
602:     PetscStrallocpy(b,&bb);
603:     PetscStrtolower(aa);
604:     PetscStrtolower(bb);
605:     PetscStrcmp(aa,bb,t);
606:     PetscFree(aa);
607:     PetscFree(bb);
608:     return(0);
609:   }
610: #endif
611:   if (!c) *t = PETSC_TRUE;
612:   else    *t = PETSC_FALSE;
613:   return(0);
614: }



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

621:    Not Collective

623:    Input Parameters:
624: +  a - pointer to first string
625: .  b - pointer to second string
626: -  n - length to compare up to

628:    Output Parameter:
629: .  t - if the two strings are equal

631:    Level: intermediate

633:    Notes:
634:     Not for use in Fortran

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

638: @*/
639: PetscErrorCode  PetscStrncmp(const char a[],const char b[],size_t n,PetscBool  *t)
640: {
641:   int c;

644:   c = strncmp(a,b,n);
645:   if (!c) *t = PETSC_TRUE;
646:   else    *t = PETSC_FALSE;
647:   return(0);
648: }

650: /*@C
651:    PetscStrchr - Locates first occurance of a character in a string

653:    Not Collective

655:    Input Parameters:
656: +  a - pointer to string
657: -  b - character

659:    Output Parameter:
660: .  c - location of occurance, NULL if not found

662:    Level: intermediate

664:    Notes:
665:     Not for use in Fortran

667: @*/
668: PetscErrorCode  PetscStrchr(const char a[],char b,char *c[])
669: {
671:   *c = (char*)strchr(a,b);
672:   return(0);
673: }

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

679:    Not Collective

681:    Input Parameters:
682: +  a - pointer to string
683: -  b - character

685:    Output Parameter:
686: .  tmp - location of occurance, a if not found

688:    Level: intermediate

690:    Notes:
691:     Not for use in Fortran

693: @*/
694: PetscErrorCode  PetscStrrchr(const char a[],char b,char *tmp[])
695: {
697:   *tmp = (char*)strrchr(a,b);
698:   if (!*tmp) *tmp = (char*)a;
699:   else *tmp = *tmp + 1;
700:   return(0);
701: }

703: /*@C
704:    PetscStrtolower - Converts string to lower case

706:    Not Collective

708:    Input Parameters:
709: .  a - pointer to string

711:    Level: intermediate

713:    Notes:
714:     Not for use in Fortran

716: @*/
717: PetscErrorCode  PetscStrtolower(char a[])
718: {
720:   while (*a) {
721:     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
722:     a++;
723:   }
724:   return(0);
725: }

727: /*@C
728:    PetscStrtoupper - Converts string to upper case

730:    Not Collective

732:    Input Parameters:
733: .  a - pointer to string

735:    Level: intermediate

737:    Notes:
738:     Not for use in Fortran

740: @*/
741: PetscErrorCode  PetscStrtoupper(char a[])
742: {
744:   while (*a) {
745:     if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a';
746:     a++;
747:   }
748:   return(0);
749: }

751: /*@C
752:    PetscStrendswith - Determines if a string ends with a certain string

754:    Not Collective

756:    Input Parameters:
757: +  a - pointer to string
758: -  b - string to endwith

760:    Output Parameter:
761: .  flg - PETSC_TRUE or PETSC_FALSE

763:    Notes:
764:     Not for use in Fortran

766:    Level: intermediate

768: @*/
769: PetscErrorCode  PetscStrendswith(const char a[],const char b[],PetscBool *flg)
770: {
771:   char           *test;
773:   size_t         na,nb;

776:   *flg = PETSC_FALSE;
777:   PetscStrrstr(a,b,&test);
778:   if (test) {
779:     PetscStrlen(a,&na);
780:     PetscStrlen(b,&nb);
781:     if (a+na-nb == test) *flg = PETSC_TRUE;
782:   }
783:   return(0);
784: }

786: /*@C
787:    PetscStrbeginswith - Determines if a string begins with a certain string

789:    Not Collective

791:    Input Parameters:
792: +  a - pointer to string
793: -  b - string to begin with

795:    Output Parameter:
796: .  flg - PETSC_TRUE or PETSC_FALSE

798:    Notes:
799:     Not for use in Fortran

801:    Level: intermediate

803: .seealso: PetscStrendswithwhich(), PetscStrendswith(), PetscStrtoupper, PetscStrtolower(), PetscStrrchr(), PetscStrchr(),
804:           PetscStrncmp(), PetscStrlen(), PetscStrncmp(), PetscStrcmp()

806: @*/
807: PetscErrorCode  PetscStrbeginswith(const char a[],const char b[],PetscBool *flg)
808: {
809:   char           *test;

813:   *flg = PETSC_FALSE;
814:   PetscStrrstr(a,b,&test);
815:   if (test && (test == a)) *flg = PETSC_TRUE;
816:   return(0);
817: }


820: /*@C
821:    PetscStrendswithwhich - Determines if a string ends with one of several possible strings

823:    Not Collective

825:    Input Parameters:
826: +  a - pointer to string
827: -  bs - strings to endwith (last entry must be null)

829:    Output Parameter:
830: .  cnt - the index of the string it ends with or 1+the last possible index

832:    Notes:
833:     Not for use in Fortran

835:    Level: intermediate

837: @*/
838: PetscErrorCode  PetscStrendswithwhich(const char a[],const char *const *bs,PetscInt *cnt)
839: {
840:   PetscBool      flg;

844:   *cnt = 0;
845:   while (bs[*cnt]) {
846:     PetscStrendswith(a,bs[*cnt],&flg);
847:     if (flg) return(0);
848:     *cnt += 1;
849:   }
850:   return(0);
851: }

853: /*@C
854:    PetscStrrstr - Locates last occurance of string in another string

856:    Not Collective

858:    Input Parameters:
859: +  a - pointer to string
860: -  b - string to find

862:    Output Parameter:
863: .  tmp - location of occurance

865:    Notes:
866:     Not for use in Fortran

868:    Level: intermediate

870: @*/
871: PetscErrorCode  PetscStrrstr(const char a[],const char b[],char *tmp[])
872: {
873:   const char *stmp = a, *ltmp = 0;

876:   while (stmp) {
877:     stmp = (char*)strstr(stmp,b);
878:     if (stmp) {ltmp = stmp;stmp++;}
879:   }
880:   *tmp = (char*)ltmp;
881:   return(0);
882: }

884: /*@C
885:    PetscStrstr - Locates first occurance of string in another string

887:    Not Collective

889:    Input Parameters:
890: +  haystack - string to search
891: -  needle - string to find

893:    Output Parameter:
894: .  tmp - location of occurance, is a NULL if the string is not found

896:    Notes:
897:     Not for use in Fortran

899:    Level: intermediate

901: @*/
902: PetscErrorCode  PetscStrstr(const char haystack[],const char needle[],char *tmp[])
903: {
905:   *tmp = (char*)strstr(haystack,needle);
906:   return(0);
907: }

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

911: /*@C
912:    PetscTokenFind - Locates next "token" in a string

914:    Not Collective

916:    Input Parameters:
917: .  a - pointer to token

919:    Output Parameter:
920: .  result - location of occurance, NULL if not found

922:    Notes:

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

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

930:      For example if the separator character is + and the string is xxxx+y then the first fine will return a pointer to a null terminated xxxx and the 
931:    second will return a null terminated y

933:      If the separator character is + and the string is xxxx then the first and only token found will be a pointer to a null terminated xxxx

935:     Not for use in Fortran

937:    Level: intermediate


940: .seealso: PetscTokenCreate(), PetscTokenDestroy()
941: @*/
942: PetscErrorCode  PetscTokenFind(PetscToken a,char *result[])
943: {
944:   char *ptr = a->current,token;

947:   *result = a->current;
948:   if (ptr && !*ptr) {*result = 0;return(0);}
949:   token = a->token;
950:   if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
951:   while (ptr) {
952:     if (*ptr == token) {
953:       *ptr++ = 0;
954:       while (*ptr == a->token) ptr++;
955:       a->current = ptr;
956:       break;
957:     }
958:     if (!*ptr) {
959:       a->current = 0;
960:       break;
961:     }
962:     ptr++;
963:   }
964:   return(0);
965: }

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

970:    Not Collective

972:    Input Parameters:
973: +  string - the string to look in
974: -  b - the separator character

976:    Output Parameter:
977: .  t- the token object

979:    Notes:

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

984:     Not for use in Fortran

986:    Level: intermediate

988: .seealso: PetscTokenFind(), PetscTokenDestroy()
989: @*/
990: PetscErrorCode  PetscTokenCreate(const char a[],const char b,PetscToken *t)
991: {

995:   PetscNew(t);
996:   PetscStrallocpy(a,&(*t)->array);

998:   (*t)->current = (*t)->array;
999:   (*t)->token   = b;
1000:   return(0);
1001: }

1003: /*@C
1004:    PetscTokenDestroy - Destroys a PetscToken

1006:    Not Collective

1008:    Input Parameters:
1009: .  a - pointer to token

1011:    Level: intermediate

1013:    Notes:
1014:     Not for use in Fortran

1016: .seealso: PetscTokenCreate(), PetscTokenFind()
1017: @*/
1018: PetscErrorCode  PetscTokenDestroy(PetscToken *a)
1019: {

1023:   if (!*a) return(0);
1024:   PetscFree((*a)->array);
1025:   PetscFree(*a);
1026:   return(0);
1027: }

1029: /*@C
1030:    PetscStrInList - search string in character-delimited list

1032:    Not Collective

1034:    Input Parameters:
1035: +  str - the string to look for
1036: .  list - the list to search in
1037: -  sep - the separator character

1039:    Output Parameter:
1040: .  found - whether str is in list

1042:    Level: intermediate

1044:    Notes:
1045:     Not for use in Fortran

1047: .seealso: PetscTokenCreate(), PetscTokenFind(), PetscStrcmp()
1048: @*/
1049: PetscErrorCode PetscStrInList(const char str[],const char list[],char sep,PetscBool *found)
1050: {
1051:   PetscToken     token;
1052:   char           *item;

1056:   *found = PETSC_FALSE;
1057:   PetscTokenCreate(list,sep,&token);
1058:   PetscTokenFind(token,&item);
1059:   while (item) {
1060:     PetscStrcmp(str,item,found);
1061:     if (*found) break;
1062:     PetscTokenFind(token,&item);
1063:   }
1064:   PetscTokenDestroy(&token);
1065:   return(0);
1066: }

1068: /*@C
1069:    PetscGetPetscDir - Gets the directory PETSc is installed in

1071:    Not Collective

1073:    Output Parameter:
1074: .  dir - the directory

1076:    Level: developer

1078:    Notes:
1079:     Not for use in Fortran

1081: @*/
1082: PetscErrorCode  PetscGetPetscDir(const char *dir[])
1083: {
1085:   *dir = PETSC_DIR;
1086:   return(0);
1087: }

1089: /*@C
1090:    PetscStrreplace - Replaces substrings in string with other substrings

1092:    Not Collective

1094:    Input Parameters:
1095: +   comm - MPI_Comm of processors that are processing the string
1096: .   aa - the string to look in
1097: .   b - the resulting copy of a with replaced strings (b can be the same as a)
1098: -   len - the length of b

1100:    Notes:
1101:       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
1102:       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values
1103:       as well as any environmental variables.

1105:       PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what
1106:       PETSc was built with and do not use environmental variables.

1108:       Not for use in Fortran

1110:    Level: intermediate

1112: @*/
1113: PetscErrorCode  PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
1114: {
1116:   int            i = 0;
1117:   size_t         l,l1,l2,l3;
1118:   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
1119:   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}","${HOSTNAME}",0};
1120:   char           *r[] = {0,0,0,0,0,0,0,0,0};
1121:   PetscBool      flag;

1124:   if (!a || !b) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
1125:   if (aa == b) {
1126:     PetscStrallocpy(aa,(char**)&a);
1127:   }
1128:   PetscMalloc1(len,&work);

1130:   /* get values for replaced variables */
1131:   PetscStrallocpy(PETSC_ARCH,&r[0]);
1132:   PetscStrallocpy(PETSC_DIR,&r[1]);
1133:   PetscStrallocpy(PETSC_LIB_DIR,&r[2]);
1134:   PetscMalloc1(256,&r[3]);
1135:   PetscMalloc1(PETSC_MAX_PATH_LEN,&r[4]);
1136:   PetscMalloc1(PETSC_MAX_PATH_LEN,&r[5]);
1137:   PetscMalloc1(256,&r[6]);
1138:   PetscMalloc1(256,&r[7]);
1139:   PetscGetDisplay(r[3],256);
1140:   PetscGetHomeDirectory(r[4],PETSC_MAX_PATH_LEN);
1141:   PetscGetWorkingDirectory(r[5],PETSC_MAX_PATH_LEN);
1142:   PetscGetUserName(r[6],256);
1143:   PetscGetHostName(r[7],256);

1145:   /* replace that are in environment */
1146:   PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);
1147:   if (flag) {
1148:     PetscFree(r[2]);
1149:     PetscStrallocpy(env,&r[2]);
1150:   }

1152:   /* replace the requested strings */
1153:   PetscStrncpy(b,a,len);
1154:   while (s[i]) {
1155:     PetscStrlen(s[i],&l);
1156:     PetscStrstr(b,s[i],&par);
1157:     while (par) {
1158:       *par =  0;
1159:       par += l;

1161:       PetscStrlen(b,&l1);
1162:       PetscStrlen(r[i],&l2);
1163:       PetscStrlen(par,&l3);
1164:       if (l1 + l2 + l3 >= len) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
1165:       PetscStrcpy(work,b);
1166:       PetscStrcat(work,r[i]);
1167:       PetscStrcat(work,par);
1168:       PetscStrncpy(b,work,len);
1169:       PetscStrstr(b,s[i],&par);
1170:     }
1171:     i++;
1172:   }
1173:   i = 0;
1174:   while (r[i]) {
1175:     tfree = (char*)r[i];
1176:     PetscFree(tfree);
1177:     i++;
1178:   }

1180:   /* look for any other ${xxx} strings to replace from environmental variables */
1181:   PetscStrstr(b,"${",&par);
1182:   while (par) {
1183:     *par  = 0;
1184:     par  += 2;
1185:     PetscStrcpy(work,b);
1186:     PetscStrstr(par,"}",&epar);
1187:     *epar = 0;
1188:     epar += 1;
1189:     PetscOptionsGetenv(comm,par,env,256,&flag);
1190:     if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
1191:     PetscStrcat(work,env);
1192:     PetscStrcat(work,epar);
1193:     PetscStrcpy(b,work);
1194:     PetscStrstr(b,"${",&par);
1195:   }
1196:   PetscFree(work);
1197:   if (aa == b) {
1198:     PetscFree(a);
1199:   }
1200:   return(0);
1201: }

1203: /*@C
1204:    PetscEListFind - searches list of strings for given string, using case insensitive matching

1206:    Not Collective

1208:    Input Parameters:
1209: +  n - number of strings in
1210: .  list - list of strings to search
1211: -  str - string to look for, empty string "" accepts default (first entry in list)

1213:    Output Parameters:
1214: +  value - index of matching string (if found)
1215: -  found - boolean indicating whether string was found (can be NULL)

1217:    Notes:
1218:    Not for use in Fortran

1220:    Level: advanced
1221: @*/
1222: PetscErrorCode PetscEListFind(PetscInt n,const char *const *list,const char *str,PetscInt *value,PetscBool *found)
1223: {
1225:   PetscBool matched;
1226:   PetscInt i;

1229:   if (found) *found = PETSC_FALSE;
1230:   for (i=0; i<n; i++) {
1231:     PetscStrcasecmp(str,list[i],&matched);
1232:     if (matched || !str[0]) {
1233:       if (found) *found = PETSC_TRUE;
1234:       *value = i;
1235:       break;
1236:     }
1237:   }
1238:   return(0);
1239: }

1241: /*@C
1242:    PetscEnumFind - searches enum list of strings for given string, using case insensitive matching

1244:    Not Collective

1246:    Input Parameters:
1247: +  enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL
1248: -  str - string to look for

1250:    Output Parameters:
1251: +  value - index of matching string (if found)
1252: -  found - boolean indicating whether string was found (can be NULL)

1254:    Notes:
1255:    Not for use in Fortran

1257:    Level: advanced
1258: @*/
1259: PetscErrorCode PetscEnumFind(const char *const *enumlist,const char *str,PetscEnum *value,PetscBool *found)
1260: {
1262:   PetscInt n = 0,evalue;
1263:   PetscBool efound;

1266:   while (enumlist[n++]) if (n > 50) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument appears to be wrong or have more than 50 entries");
1267:   if (n < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument must have at least two entries: typename and type prefix");
1268:   n -= 3; /* drop enum name, prefix, and null termination */
1269:   PetscEListFind(n,enumlist,str,&evalue,&efound);
1270:   if (efound) *value = (PetscEnum)evalue;
1271:   if (found) *found = efound;
1272:   return(0);
1273: }