Actual source code: str.c

petsc-3.3-p7 2013-05-11
  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>                   /*I  "petscsys.h"   I*/
  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:    PetscStrToArray - Seperates a string by its spaces and creates an array of strings

 21:    Not Collective

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

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

 30:    Level: intermediate

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

 34:    Not for use in Fortran

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

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

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

 47:   n = strlen(s);
 48:   *argc = 0;
 49:   for (i=0; i<n; i++) {
 50:     if (s[i] != ' ') break;
 51:   }
 52:   for (;i<n+1; i++) {
 53:     if ((s[i] == ' ' || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
 54:     else if (s[i] != ' ') {flg = PETSC_FALSE;}
 55:   }
 56:   (*args) = (char **) malloc(((*argc)+1)*sizeof(char**)); if (!*args) return PETSC_ERR_MEM;
 57:   lens    = (int*) malloc((*argc)*sizeof(int)); if (!lens) return PETSC_ERR_MEM;
 58:   for (i=0; i<*argc; i++) lens[i] = 0;

 60:   *argc = 0;
 61:   for (i=0; i<n; i++) {
 62:     if (s[i] != ' ') break;
 63:   }
 64:   for (;i<n+1; i++) {
 65:     if ((s[i] == ' ' || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
 66:     else if (s[i] != ' ') {lens[*argc]++;flg = PETSC_FALSE;}
 67:   }

 69:   for (i=0; i<*argc; i++) {
 70:     (*args)[i] = (char*) malloc((lens[i]+1)*sizeof(char)); if (!(*args)[i]) return PETSC_ERR_MEM;
 71:   }
 72:   (*args)[*argc] = 0;

 74:   *argc = 0;
 75:   for (i=0; i<n; i++) {
 76:     if (s[i] != ' ') break;
 77:   }
 78:   for (;i<n+1; i++) {
 79:     if ((s[i] == ' ' || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*args)[*argc][cnt++] = 0; (*argc)++; cnt = 0;}
 80:     else if (s[i] != ' ' && s[i] != 0) {(*args)[*argc][cnt++] = s[i]; flg = PETSC_FALSE;}
 81:   }
 82:   return 0;
 83: }

 87: /*@C
 88:    PetscStrToArrayDestroy - Frees array created with PetscStrToArray().

 90:    Not Collective

 92:    Output Parameters:
 93: +  argc - the number of arguments
 94: -  args - the array of arguments

 96:    Level: intermediate

 98:    Concepts: command line arguments
 99:    
100:    Notes: This may be called before PetscInitialize() or after PetscFinalize()

102:    Not for use in Fortran

104: .seealso: PetscStrToArray()

106: @*/
107: PetscErrorCode  PetscStrToArrayDestroy(int argc,char **args)
108: {
109:   PetscInt i;

111:   for (i=0; i<argc; i++) {
112:     free(args[i]);
113:   }
114:   free(args);
115:   return 0;
116: }

120: /*@C
121:    PetscStrlen - Gets length of a string

123:    Not Collective

125:    Input Parameters:
126: .  s - pointer to string

128:    Output Parameter:
129: .  len - length in bytes

131:    Level: intermediate

133:    Note:
134:    This routine is analogous to strlen().

136:    Null string returns a length of zero

138:    Not for use in Fortran

140:   Concepts: string length
141:   
142: @*/
143: PetscErrorCode  PetscStrlen(const char s[],size_t *len)
144: {
146:   if (!s) {
147:     *len = 0;
148:   } else {
149:     *len = strlen(s);
150:   }
151:   return(0);
152: }

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

159:    Not Collective

161:    Input Parameters:
162: .  s - pointer to string

164:    Output Parameter:
165: .  t - the copied string

167:    Level: intermediate

169:    Note:
170:       Null string returns a new null string

172:       Not for use in Fortran

174:   Concepts: string copy
175:   
176: @*/
177: PetscErrorCode  PetscStrallocpy(const char s[],char *t[])
178: {
180:   size_t         len;
181:   char           *tmp = 0;

184:   if (s) {
185:     PetscStrlen(s,&len);
186:     PetscMalloc((1+len)*sizeof(char),&tmp);
187:     PetscStrcpy(tmp,s);
188:   }
189:   *t = tmp;
190:   return(0);
191: }

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

198:    Not Collective

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

203:    Output Parameter:
204: .  t - the copied array string

206:    Level: intermediate

208:    Note:
209:       Not for use in Fortran

211:   Concepts: string copy

213: .seealso: PetscStrallocpy() PetscStrArrayDestroy()
214:  
215: @*/
216: PetscErrorCode  PetscStrArrayallocpy(const char *const*list,char ***t)
217: {
219:   PetscInt       i,n = 0;

222:   while (list[n++]) ;
223:   PetscMalloc((n+1)*sizeof(char**),t);
224:   for (i=0; i<n; i++) {
225:     PetscStrallocpy(list[i],(*t)+i);
226:   }
227:   (*t)[n] = PETSC_NULL;
228:   return(0);
229: }

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

236:    Not Collective

238:    Output Parameters:
239: .   list - array of strings

241:    Level: intermediate

243:    Concepts: command line arguments
244:    
245:    Notes: Not for use in Fortran

247: .seealso: PetscStrArrayallocpy()

249: @*/
250: PetscErrorCode PetscStrArrayDestroy(char ***list)
251: {
252:   PetscInt       n = 0;

256:   if (!*list) return(0);
257:   while ((*list)[n]) {
258:     PetscFree((*list)[n]);
259:     n++;
260:   }
261:   PetscFree(*list);
262:   return(0);
263: }

267: /*@C
268:    PetscStrcpy - Copies a string

270:    Not Collective

272:    Input Parameters:
273: .  t - pointer to string

275:    Output Parameter:
276: .  s - the copied string

278:    Level: intermediate

280:    Notes:
281:      Null string returns a string starting with zero

283:      Not for use in Fortran

285:   Concepts: string copy
286:   
287: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()

289: @*/

291: PetscErrorCode  PetscStrcpy(char s[],const char t[])
292: {
294:   if (t && !s) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
295:   if (t) {strcpy(s,t);}
296:   else if (s) {s[0] = 0;}
297:   return(0);
298: }

302: /*@C
303:    PetscStrncpy - Copies a string up to a certain length

305:    Not Collective

307:    Input Parameters:
308: +  t - pointer to string
309: -  n - the length to copy

311:    Output Parameter:
312: .  s - the copied string

314:    Level: intermediate

316:    Note:
317:      Null string returns a string starting with zero

319:   Concepts: string copy

321: .seealso: PetscStrcpy(), PetscStrcat(), PetscStrncat()
322:   
323: @*/
324: PetscErrorCode  PetscStrncpy(char s[],const char t[],size_t n)
325: {
327:   if (t && !s) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
328:   if (t) {strncpy(s,t,n);}
329:   else if (s) {s[0] = 0;}
330:   return(0);
331: }

335: /*@C
336:    PetscStrcat - Concatenates a string onto a given string

338:    Not Collective

340:    Input Parameters:
341: +  s - string to be added to
342: -  t - pointer to string to be added to end

344:    Level: intermediate

346:    Notes: Not for use in Fortran

348:   Concepts: string copy

350: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
351:   
352: @*/
353: PetscErrorCode  PetscStrcat(char s[],const char t[])
354: {
356:   if (!t) return(0);
357:   strcat(s,t);
358:   return(0);
359: }

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

366:    Not Collective

368:    Input Parameters:
369: +  s - pointer to string to be added to end
370: .  t - string to be added to
371: .  n - maximum length to copy 

373:    Level: intermediate

375:   Notes:    Not for use in Fortran

377:   Concepts: string copy

379: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
380:   
381: @*/
382: PetscErrorCode  PetscStrncat(char s[],const char t[],size_t n)
383: {
385:   strncat(s,t,n);
386:   return(0);
387: }

391: /*@C
392:    PetscStrcmp - Compares two strings,

394:    Not Collective

396:    Input Parameters:
397: +  a - pointer to string first string
398: -  b - pointer to second string

400:    Output Parameter:
401: .  flg - PETSC_TRUE if the two strings are equal

403:    Level: intermediate

405:    Notes:    Not for use in Fortran

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

409: @*/
410: PetscErrorCode  PetscStrcmp(const char a[],const char b[],PetscBool  *flg)
411: {
412:   int c;

415:   if (!a && !b) {
416:     *flg = PETSC_TRUE;
417:   } else if (!a || !b) {
418:     *flg = PETSC_FALSE;
419:   } else {
420:     c = strcmp(a,b);
421:     if (c) *flg = PETSC_FALSE;
422:     else   *flg = PETSC_TRUE;
423:   }
424:   return(0);
425: }

429: /*@C
430:    PetscStrgrt - If first string is greater than the second

432:    Not Collective

434:    Input Parameters:
435: +  a - pointer to first string
436: -  b - pointer to second string

438:    Output Parameter:
439: .  flg - if the first string is greater

441:    Notes:
442:     Null arguments are ok, a null string is considered smaller than 
443:     all others

445:    Not for use in Fortran

447:    Level: intermediate

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

451: @*/
452: PetscErrorCode  PetscStrgrt(const char a[],const char b[],PetscBool  *t)
453: {
454:   int c;

457:   if (!a && !b) {
458:     *t = PETSC_FALSE;
459:   } else if (a && !b) {
460:     *t = PETSC_TRUE;
461:   } else if (!a && b) {
462:     *t = PETSC_FALSE;
463:   } else {
464:     c = strcmp(a,b);
465:     if (c > 0) *t = PETSC_TRUE;
466:     else       *t = PETSC_FALSE;
467:   }
468:   return(0);
469: }

473: /*@C
474:    PetscStrcasecmp - Returns true if the two strings are the same
475:      except possibly for case.

477:    Not Collective

479:    Input Parameters:
480: +  a - pointer to first string
481: -  b - pointer to second string

483:    Output Parameter:
484: .  flg - if the two strings are the same

486:    Notes:
487:     Null arguments are ok

489:    Not for use in Fortran

491:    Level: intermediate

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

495: @*/
496: PetscErrorCode  PetscStrcasecmp(const char a[],const char b[],PetscBool  *t)
497: {
498:   int c;

501:   if (!a && !b) c = 0;
502:   else if (!a || !b) c = 1;
503: #if defined(PETSC_HAVE_STRCASECMP)
504:   else c = strcasecmp(a,b);
505: #elif defined(PETSC_HAVE_STRICMP)
506:   else c = stricmp(a,b);
507: #else
508:   else {
509:     char           *aa,*bb;
511:     PetscStrallocpy(a,&aa);
512:     PetscStrallocpy(b,&bb);
513:     PetscStrtolower(aa);
514:     PetscStrtolower(bb);
515:     PetscStrcmp(aa,bb,t);
516:     PetscFree(aa);
517:     PetscFree(bb);
518:     return(0);
519:   }
520: #endif
521:   if (!c) *t = PETSC_TRUE;
522:   else    *t = PETSC_FALSE;
523:   return(0);
524: }



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

533:    Not Collective

535:    Input Parameters:
536: +  a - pointer to first string
537: .  b - pointer to second string
538: -  n - length to compare up to

540:    Output Parameter:
541: .  t - if the two strings are equal

543:    Level: intermediate

545:    Notes:    Not for use in Fortran

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

549: @*/
550: PetscErrorCode  PetscStrncmp(const char a[],const char b[],size_t n,PetscBool  *t)
551: {
552:   int c;

555:   c = strncmp(a,b,n);
556:   if (!c) *t = PETSC_TRUE;
557:   else    *t = PETSC_FALSE;
558:   return(0);
559: }

563: /*@C
564:    PetscStrchr - Locates first occurance of a character in a string

566:    Not Collective

568:    Input Parameters:
569: +  a - pointer to string
570: -  b - character

572:    Output Parameter:
573: .  c - location of occurance, PETSC_NULL if not found

575:    Level: intermediate

577:    Notes:    Not for use in Fortran

579: @*/
580: PetscErrorCode  PetscStrchr(const char a[],char b,char *c[])
581: {
583:   *c = (char *)strchr(a,b);
584:   return(0);
585: }

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

593:    Not Collective

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

599:    Output Parameter:
600: .  tmp - location of occurance, a if not found

602:    Level: intermediate

604:    Notes:    Not for use in Fortran

606: @*/
607: PetscErrorCode  PetscStrrchr(const char a[],char b,char *tmp[])
608: {
610:   *tmp = (char *)strrchr(a,b);
611:   if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
612:   return(0);
613: }

617: /*@C
618:    PetscStrtolower - Converts string to lower case

620:    Not Collective

622:    Input Parameters:
623: .  a - pointer to string

625:    Level: intermediate

627:    Notes:    Not for use in Fortran

629: @*/
630: PetscErrorCode  PetscStrtolower(char a[])
631: {
633:   while (*a) {
634:     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
635:     a++;
636:   }
637:   return(0);
638: }

642: /*@C
643:    PetscStrendswith - Determines if a string ends with a certain string

645:    Not Collective

647:    Input Parameters:
648: +  a - pointer to string
649: -  b - string to endwith

651:    Output Parameter:
652: .  flg - PETSC_TRUE or PETSC_FALSE

654:    Notes:     Not for use in Fortran

656:    Level: intermediate

658: @*/
659: PetscErrorCode  PetscStrendswith(const char a[],const char b[],PetscBool *flg)
660: {
661:   char           *test;
663:   size_t         na,nb;

666:   *flg = PETSC_FALSE;
667:   PetscStrrstr(a,b,&test);
668:   if (test) {
669:     PetscStrlen(a,&na);
670:     PetscStrlen(b,&nb);
671:     if (a+na-nb == test) *flg = PETSC_TRUE;
672:   }
673:   return(0);
674: }

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

681:    Not Collective

683:    Input Parameters:
684: +  a - pointer to string
685: -  bs - strings to endwith (last entry must be null)

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

690:    Notes:     Not for use in Fortran

692:    Level: intermediate

694: @*/
695: PetscErrorCode  PetscStrendswithwhich(const char a[],const char *const *bs,PetscInt *cnt)
696: {
697:   PetscBool      flg;

701:   *cnt = 0;
702:   while (bs[*cnt]) {
703:     PetscStrendswith(a,bs[*cnt],&flg);
704:     if (flg) return(0);
705:     *cnt += 1;
706:   }
707:   return(0);
708: }

712: /*@C
713:    PetscStrrstr - Locates last occurance of string in another string

715:    Not Collective

717:    Input Parameters:
718: +  a - pointer to string
719: -  b - string to find

721:    Output Parameter:
722: .  tmp - location of occurance

724:    Notes:     Not for use in Fortran

726:    Level: intermediate

728: @*/
729: PetscErrorCode  PetscStrrstr(const char a[],const char b[],char *tmp[])
730: {
731:   const char *stmp = a, *ltmp = 0;

734:   while (stmp) {
735:     stmp = (char *)strstr(stmp,b);
736:     if (stmp) {ltmp = stmp;stmp++;}
737:   }
738:   *tmp = (char *)ltmp;
739:   return(0);
740: }

744: /*@C
745:    PetscStrstr - Locates first occurance of string in another string

747:    Not Collective

749:    Input Parameters:
750: +  haystack - string to search
751: -  needle - string to find

753:    Output Parameter:
754: .  tmp - location of occurance, is a PETSC_NULL if the string is not found

756:    Notes: Not for use in Fortran

758:    Level: intermediate

760: @*/
761: PetscErrorCode  PetscStrstr(const char haystack[],const char needle[],char *tmp[])
762: {
764:   *tmp = (char *)strstr(haystack,needle);
765:   return(0);
766: }

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

772: /*@C
773:    PetscTokenFind - Locates next "token" in a string

775:    Not Collective

777:    Input Parameters:
778: .  a - pointer to token

780:    Output Parameter:
781: .  result - location of occurance, PETSC_NULL if not found

783:    Notes:

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

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

791:     Not for use in Fortran

793:    Level: intermediate


796: .seealso: PetscTokenCreate(), PetscTokenDestroy()
797: @*/
798: PetscErrorCode  PetscTokenFind(PetscToken a,char *result[])
799: {
800:   char *ptr = a->current,token;

803:   *result = a->current;
804:   if (ptr && !*ptr) {*result = 0;return(0);}
805:   token = a->token;
806:   if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
807:   while (ptr) {
808:     if (*ptr == token) {
809:       *ptr++ = 0;
810:       while (*ptr == a->token) ptr++;
811:       a->current = ptr;
812:       break;
813:     }
814:     if (!*ptr) {
815:       a->current = 0;
816:       break;
817:     }
818:     ptr++;
819:   }
820:   return(0);
821: }

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

828:    Not Collective

830:    Input Parameters:
831: +  string - the string to look in
832: -  token - the character to look for

834:    Output Parameter:
835: .  a - pointer to token

837:    Notes:

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

842:     Not for use in Fortran

844:    Level: intermediate

846: .seealso: PetscTokenFind(), PetscTokenDestroy()
847: @*/
848: PetscErrorCode  PetscTokenCreate(const char a[],const char b,PetscToken *t)
849: {

853:   PetscNew(struct _p_PetscToken,t);
854:   PetscStrallocpy(a,&(*t)->array);
855:   (*t)->current = (*t)->array;
856:   (*t)->token   = b;
857:   return(0);
858: }

862: /*@C
863:    PetscTokenDestroy - Destroys a PetscToken

865:    Not Collective

867:    Input Parameters:
868: .  a - pointer to token

870:    Level: intermediate

872:    Notes:     Not for use in Fortran

874: .seealso: PetscTokenCreate(), PetscTokenFind()
875: @*/
876: PetscErrorCode  PetscTokenDestroy(PetscToken *a)
877: {

881:   if (!*a) return(0);
882:   PetscFree((*a)->array);
883:   PetscFree(*a);
884:   return(0);
885: }


890: /*@C
891:    PetscGetPetscDir - Gets the directory PETSc is installed in

893:    Not Collective

895:    Output Parameter:
896: .  dir - the directory

898:    Level: developer

900:    Notes: Not for use in Fortran

902: @*/
903: PetscErrorCode  PetscGetPetscDir(const char *dir[])
904: {
906:   *dir = PETSC_DIR;
907:   return(0);
908: }

912: /*@C
913:    PetscStrreplace - Replaces substrings in string with other substrings

915:    Not Collective

917:    Input Parameters:
918: +   comm - MPI_Comm of processors that are processing the string
919: .   aa - the string to look in
920: .   b - the resulting copy of a with replaced strings (b can be the same as a)
921: -   len - the length of b

923:    Notes:
924:       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
925:       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values
926:       as well as any environmental variables.

928:       PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what
929:       PETSc was built with and do not use environmental variables.
930:    
931:       Not for use in Fortran
932:    
933:    Level: intermediate

935: @*/
936: PetscErrorCode  PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
937: {
939:   int            i = 0;
940:   size_t         l,l1,l2,l3;
941:   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
942:   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}","${HOSTNAME}",0};
943:   const char     *r[] = {0,0,0,0,0,0,0,0,0};
944:   PetscBool      flag;

947:   if (!a || !b) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
948:   if (aa == b) {
949:     PetscStrallocpy(aa,(char **)&a);
950:   }
951:   PetscMalloc(len*sizeof(char*),&work);

953:   /* get values for replaced variables */
954:   PetscStrallocpy(PETSC_ARCH,(char**)&r[0]);
955:   PetscStrallocpy(PETSC_DIR,(char**)&r[1]);
956:   PetscStrallocpy(PETSC_LIB_DIR,(char**)&r[2]);
957:   PetscMalloc(256*sizeof(char),&r[3]);
958:   PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[4]);
959:   PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);
960:   PetscMalloc(256*sizeof(char),&r[6]);
961:   PetscMalloc(256*sizeof(char),&r[7]);
962:   PetscGetDisplay((char*)r[3],256);
963:   PetscGetHomeDirectory((char*)r[4],PETSC_MAX_PATH_LEN);
964:   PetscGetWorkingDirectory((char*)r[5],PETSC_MAX_PATH_LEN);
965:   PetscGetUserName((char*)r[6],256);
966:   PetscGetHostName((char*)r[7],256);

968:   /* replace that are in environment */
969:   PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);
970:   if (flag) {
971:     PetscStrallocpy(env,(char**)&r[2]);
972:   }

974:   /* replace the requested strings */
975:   PetscStrncpy(b,a,len);
976:   while (s[i]) {
977:     PetscStrlen(s[i],&l);
978:     PetscStrstr(b,s[i],&par);
979:     while (par) {
980:       *par  =  0;
981:       par  += l;

983:       PetscStrlen(b,&l1);
984:       PetscStrlen(r[i],&l2);
985:       PetscStrlen(par,&l3);
986:       if (l1 + l2 + l3 >= len) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
987:       PetscStrcpy(work,b);
988:       PetscStrcat(work,r[i]);
989:       PetscStrcat(work,par);
990:       PetscStrncpy(b,work,len);
991:       PetscStrstr(b,s[i],&par);
992:     }
993:     i++;
994:   }
995:   i = 0;
996:   while (r[i]) {
997:     tfree = (char*)r[i];
998:     PetscFree(tfree);
999:     i++;
1000:   }

1002:   /* look for any other ${xxx} strings to replace from environmental variables */
1003:   PetscStrstr(b,"${",&par);
1004:   while (par) {
1005:     *par = 0;
1006:     par += 2;
1007:     PetscStrcpy(work,b);
1008:     PetscStrstr(par,"}",&epar);
1009:     *epar = 0;
1010:     epar += 1;
1011:     PetscOptionsGetenv(comm,par,env,256,&flag);
1012:     if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
1013:     PetscStrcat(work,env);
1014:     PetscStrcat(work,epar);
1015:     PetscStrcpy(b,work);
1016:     PetscStrstr(b,"${",&par);
1017:   }
1018:   PetscFree(work);
1019:   if (aa == b) {
1020:     PetscFree(a);
1021:   }
1022:   return(0);
1023: }