xref: /petsc/src/sys/utils/str.c (revision 17a7a2b03df7c463461bef78abfb0dbf6e4c60b2)
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.
6 
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
15 
16 #undef __FUNCT__
17 #define __FUNCT__ "PetscStrToArray"
18 /*@C
19    PetscStrToArray - Seperates a string by its spaces and creates and array of strings
20 
21    Not Collective
22 
23    Input Parameters:
24 .  s - pointer to string
25 
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
29 
30    Level: intermediate
31 
32    Notes: this may be called before PetscInitialize()
33 
34    Developer Notes: Using raw malloc()
35 
36 @*/
37 PetscErrorCode PETSC_DLLEXPORT PetscStrToArray(const char s[],int *argc,char ***args)
38 {
39   int        i,n,*lens,cnt = 0;
40   PetscTruth flg = PETSC_FALSE;
41 
42   n = strlen(s);
43   *argc = 0;
44   for (i=0; i<n; i++) {
45     if (s[i] != ' ') break;
46   }
47   for (;i<n+1; i++) {
48     if ((s[i] == ' ' || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
49     else if (s[i] != ' ') {flg = PETSC_FALSE;}
50   }
51   (*args) = (char **) malloc((*argc)*sizeof(char**)); if (!*args) return PETSC_ERR_MEM;
52   lens  = malloc((*argc)*sizeof(int)); if (!lens) return PETSC_ERR_MEM;
53   for (i=0; i<*argc; i++) lens[i] = 0;
54 
55   *argc = 0;
56   for (i=0; i<n; i++) {
57     if (s[i] != ' ') break;
58   }
59   for (;i<n+1; i++) {
60     if ((s[i] == ' ' || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
61     else if (s[i] != ' ') {lens[*argc]++;flg = PETSC_FALSE;}
62   }
63 
64   for (i=0; i<*argc; i++) {
65     (*args)[i] = malloc((lens[i]+1)*sizeof(char)); if (!(*args)[i]) return PETSC_ERR_MEM;
66   }
67 
68   *argc = 0;
69   for (i=0; i<n; i++) {
70     if (s[i] != ' ') break;
71   }
72   for (;i<n+1; i++) {
73     if ((s[i] == ' ' || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*args)[*argc][cnt++] = 0; (*argc)++; cnt = 0;}
74     else if (s[i] != ' ') {(*args)[*argc][cnt++] = s[i]; flg = PETSC_FALSE;}
75   }
76   return 0;
77 }
78 
79 #undef __FUNCT__
80 #define __FUNCT__ "PetscStrlen"
81 /*@C
82    PetscStrlen - Gets length of a string
83 
84    Not Collective
85 
86    Input Parameters:
87 .  s - pointer to string
88 
89    Output Parameter:
90 .  len - length in bytes
91 
92    Level: intermediate
93 
94    Note:
95    This routine is analogous to strlen().
96 
97    Null string returns a length of zero
98 
99   Concepts: string length
100 
101 @*/
102 PetscErrorCode PETSC_DLLEXPORT PetscStrlen(const char s[],size_t *len)
103 {
104   PetscFunctionBegin;
105   if (!s) {
106     *len = 0;
107   } else {
108     *len = strlen(s);
109   }
110   PetscFunctionReturn(0);
111 }
112 
113 #undef __FUNCT__
114 #define __FUNCT__ "PetscStrallocpy"
115 /*@C
116    PetscStrallocpy - Allocates space to hold a copy of a string then copies the string
117 
118    Not Collective
119 
120    Input Parameters:
121 .  s - pointer to string
122 
123    Output Parameter:
124 .  t - the copied string
125 
126    Level: intermediate
127 
128    Note:
129       Null string returns a new null string
130 
131   Concepts: string copy
132 
133 @*/
134 PetscErrorCode PETSC_DLLEXPORT PetscStrallocpy(const char s[],char *t[])
135 {
136   PetscErrorCode ierr;
137   size_t         len;
138   char           *tmp = 0;
139 
140   PetscFunctionBegin;
141   if (s) {
142     ierr = PetscStrlen(s,&len);CHKERRQ(ierr);
143     ierr = PetscMalloc((1+len)*sizeof(char),&tmp);CHKERRQ(ierr);
144     ierr = PetscStrcpy(tmp,s);CHKERRQ(ierr);
145   }
146   *t = tmp;
147   PetscFunctionReturn(0);
148 }
149 
150 #undef __FUNCT__
151 #define __FUNCT__ "PetscStrcpy"
152 /*@C
153    PetscStrcpy - Copies a string
154 
155    Not Collective
156 
157    Input Parameters:
158 .  t - pointer to string
159 
160    Output Parameter:
161 .  s - the copied string
162 
163    Level: intermediate
164 
165    Note:
166      Null string returns a string starting with zero
167 
168   Concepts: string copy
169 
170 .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()
171 
172 @*/
173 
174 PetscErrorCode PETSC_DLLEXPORT PetscStrcpy(char s[],const char t[])
175 {
176   PetscFunctionBegin;
177   if (t && !s) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
178   if (t) {strcpy(s,t);}
179   else if (s) {s[0] = 0;}
180   PetscFunctionReturn(0);
181 }
182 
183 #undef __FUNCT__
184 #define __FUNCT__ "PetscStrncpy"
185 /*@C
186    PetscStrncpy - Copies a string up to a certain length
187 
188    Not Collective
189 
190    Input Parameters:
191 +  t - pointer to string
192 -  n - the length to copy
193 
194    Output Parameter:
195 .  s - the copied string
196 
197    Level: intermediate
198 
199    Note:
200      Null string returns a string starting with zero
201 
202   Concepts: string copy
203 
204 .seealso: PetscStrcpy(), PetscStrcat(), PetscStrncat()
205 
206 @*/
207 PetscErrorCode PETSC_DLLEXPORT PetscStrncpy(char s[],const char t[],size_t n)
208 {
209   PetscFunctionBegin;
210   if (t && !s) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
211   if (t) {strncpy(s,t,n);}
212   else if (s) {s[0] = 0;}
213   PetscFunctionReturn(0);
214 }
215 
216 #undef __FUNCT__
217 #define __FUNCT__ "PetscStrcat"
218 /*@C
219    PetscStrcat - Concatenates a string onto a given string
220 
221    Not Collective
222 
223    Input Parameters:
224 +  s - string to be added to
225 -  t - pointer to string to be added to end
226 
227    Level: intermediate
228 
229   Concepts: string copy
230 
231 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
232 
233 @*/
234 PetscErrorCode PETSC_DLLEXPORT PetscStrcat(char s[],const char t[])
235 {
236   PetscFunctionBegin;
237   if (!t) PetscFunctionReturn(0);
238   strcat(s,t);
239   PetscFunctionReturn(0);
240 }
241 
242 #undef __FUNCT__
243 #define __FUNCT__ "PetscStrncat"
244 /*@C
245    PetscStrncat - Concatenates a string onto a given string, up to a given length
246 
247    Not Collective
248 
249    Input Parameters:
250 +  s - pointer to string to be added to end
251 .  t - string to be added to
252 .  n - maximum length to copy
253 
254    Level: intermediate
255 
256   Concepts: string copy
257 
258 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
259 
260 @*/
261 PetscErrorCode PETSC_DLLEXPORT PetscStrncat(char s[],const char t[],size_t n)
262 {
263   PetscFunctionBegin;
264   strncat(s,t,n);
265   PetscFunctionReturn(0);
266 }
267 
268 #undef __FUNCT__
269 #define __FUNCT__ "PetscStrcmp"
270 /*@C
271    PetscStrcmp - Compares two strings,
272 
273    Not Collective
274 
275    Input Parameters:
276 +  a - pointer to string first string
277 -  b - pointer to second string
278 
279    Output Parameter:
280 .  flg - if the two strings are equal
281 
282    Level: intermediate
283 
284 .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()
285 
286 @*/
287 PetscErrorCode PETSC_DLLEXPORT PetscStrcmp(const char a[],const char b[],PetscTruth *flg)
288 {
289   int c;
290 
291   PetscFunctionBegin;
292   if (!a && !b) {
293     *flg = PETSC_TRUE;
294   } else if (!a || !b) {
295     *flg = PETSC_FALSE;
296   } else {
297     c = strcmp(a,b);
298     if (c) *flg = PETSC_FALSE;
299     else   *flg = PETSC_TRUE;
300   }
301   PetscFunctionReturn(0);
302 }
303 
304 #undef __FUNCT__
305 #define __FUNCT__ "PetscStrgrt"
306 /*@C
307    PetscStrgrt - If first string is greater than the second
308 
309    Not Collective
310 
311    Input Parameters:
312 +  a - pointer to first string
313 -  b - pointer to second string
314 
315    Output Parameter:
316 .  flg - if the first string is greater
317 
318    Notes:
319     Null arguments are ok, a null string is considered smaller than
320     all others
321 
322    Level: intermediate
323 
324 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()
325 
326 @*/
327 PetscErrorCode PETSC_DLLEXPORT PetscStrgrt(const char a[],const char b[],PetscTruth *t)
328 {
329   int c;
330 
331   PetscFunctionBegin;
332   if (!a && !b) {
333     *t = PETSC_FALSE;
334   } else if (a && !b) {
335     *t = PETSC_TRUE;
336   } else if (!a && b) {
337     *t = PETSC_FALSE;
338   } else {
339     c = strcmp(a,b);
340     if (c > 0) *t = PETSC_TRUE;
341     else       *t = PETSC_FALSE;
342   }
343   PetscFunctionReturn(0);
344 }
345 
346 #undef __FUNCT__
347 #define __FUNCT__ "PetscStrcasecmp"
348 /*@C
349    PetscStrcasecmp - Returns true if the two strings are the same
350      except possibly for case.
351 
352    Not Collective
353 
354    Input Parameters:
355 +  a - pointer to first string
356 -  b - pointer to second string
357 
358    Output Parameter:
359 .  flg - if the two strings are the same
360 
361    Notes:
362     Null arguments are ok
363 
364    Level: intermediate
365 
366 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()
367 
368 @*/
369 PetscErrorCode PETSC_DLLEXPORT PetscStrcasecmp(const char a[],const char b[],PetscTruth *t)
370 {
371   int c;
372 
373   PetscFunctionBegin;
374   if (!a && !b) c = 0;
375   else if (!a || !b) c = 1;
376 #if defined(PETSC_HAVE_STRCASECMP)
377   else c = strcasecmp(a,b);
378 #elif defined(PETSC_HAVE_STRICMP)
379   else c = stricmp(a,b);
380 #else
381   else {
382     char *aa,*bb;
383     PetscErrorCode ierr;
384     ierr = PetscStrallocpy(a,&aa);CHKERRQ(ierr);
385     ierr = PetscStrallocpy(b,&bb);CHKERRQ(ierr);
386     ierr = PetscStrtolower(aa);CHKERRQ(ierr);
387     ierr = PetscStrtolower(bb);CHKERRQ(ierr);
388     ierr = PetscStrcmp(aa,bb,t);CHKERRQ(ierr);
389     ierr = PetscFree(aa);CHKERRQ(ierr);
390     ierr = PetscFree(bb);CHKERRQ(ierr);
391     PetscFunctionReturn(0);
392   }
393 #endif
394   if (!c) *t = PETSC_TRUE;
395   else    *t = PETSC_FALSE;
396   PetscFunctionReturn(0);
397 }
398 
399 
400 
401 #undef __FUNCT__
402 #define __FUNCT__ "PetscStrncmp"
403 /*@C
404    PetscStrncmp - Compares two strings, up to a certain length
405 
406    Not Collective
407 
408    Input Parameters:
409 +  a - pointer to first string
410 .  b - pointer to second string
411 -  n - length to compare up to
412 
413    Output Parameter:
414 .  t - if the two strings are equal
415 
416    Level: intermediate
417 
418 .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()
419 
420 @*/
421 PetscErrorCode PETSC_DLLEXPORT PetscStrncmp(const char a[],const char b[],size_t n,PetscTruth *t)
422 {
423   int c;
424 
425   PetscFunctionBegin;
426   c = strncmp(a,b,n);
427   if (!c) *t = PETSC_TRUE;
428   else    *t = PETSC_FALSE;
429   PetscFunctionReturn(0);
430 }
431 
432 #undef __FUNCT__
433 #define __FUNCT__ "PetscStrchr"
434 /*@C
435    PetscStrchr - Locates first occurance of a character in a string
436 
437    Not Collective
438 
439    Input Parameters:
440 +  a - pointer to string
441 -  b - character
442 
443    Output Parameter:
444 .  c - location of occurance, PETSC_NULL if not found
445 
446    Level: intermediate
447 
448 @*/
449 PetscErrorCode PETSC_DLLEXPORT PetscStrchr(const char a[],char b,char *c[])
450 {
451   PetscFunctionBegin;
452   *c = (char *)strchr(a,b);
453   PetscFunctionReturn(0);
454 }
455 
456 #undef __FUNCT__
457 #define __FUNCT__ "PetscStrrchr"
458 /*@C
459    PetscStrrchr - Locates one location past the last occurance of a character in a string,
460       if the character is not found then returns entire string
461 
462    Not Collective
463 
464    Input Parameters:
465 +  a - pointer to string
466 -  b - character
467 
468    Output Parameter:
469 .  tmp - location of occurance, a if not found
470 
471    Level: intermediate
472 
473 @*/
474 PetscErrorCode PETSC_DLLEXPORT PetscStrrchr(const char a[],char b,char *tmp[])
475 {
476   PetscFunctionBegin;
477   *tmp = (char *)strrchr(a,b);
478   if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
479   PetscFunctionReturn(0);
480 }
481 
482 #undef __FUNCT__
483 #define __FUNCT__ "PetscStrtolower"
484 /*@C
485    PetscStrtolower - Converts string to lower case
486 
487    Not Collective
488 
489    Input Parameters:
490 .  a - pointer to string
491 
492    Level: intermediate
493 
494 @*/
495 PetscErrorCode PETSC_DLLEXPORT PetscStrtolower(char a[])
496 {
497   PetscFunctionBegin;
498   while (*a) {
499     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
500     a++;
501   }
502   PetscFunctionReturn(0);
503 }
504 
505 struct _p_PetscToken {char token;char *array;char *current;};
506 
507 
508 #undef __FUNCT__
509 #define __FUNCT__ "PetscTokenFind"
510 /*@C
511    PetscTokenFind - Locates next "token" in a string
512 
513    Not Collective
514 
515    Input Parameters:
516 .  a - pointer to token
517 
518    Output Parameter:
519 .  result - location of occurance, PETSC_NULL if not found
520 
521    Notes:
522 
523      This version is different from the system version in that
524   it allows you to pass a read-only string into the function.
525 
526      This version also treats all characters etc. inside a double quote "
527    as a single token.
528 
529    Level: intermediate
530 
531 .seealso: PetscTokenCreate(), PetscTokenDestroy()
532 @*/
533 PetscErrorCode PETSC_DLLEXPORT PetscTokenFind(PetscToken a,char *result[])
534 {
535   char *ptr = a->current,token;
536 
537   PetscFunctionBegin;
538   *result = a->current;
539   if (ptr && !*ptr) {*result = 0;PetscFunctionReturn(0);}
540   token = a->token;
541   if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
542   while (ptr) {
543     if (*ptr == token) {
544       *ptr++ = 0;
545       while (*ptr == a->token) ptr++;
546       a->current = ptr;
547       break;
548     }
549     if (!*ptr) {
550       a->current = 0;
551       break;
552     }
553     ptr++;
554   }
555   PetscFunctionReturn(0);
556 }
557 
558 #undef __FUNCT__
559 #define __FUNCT__ "PetscTokenCreate"
560 /*@C
561    PetscTokenCreate - Creates a PetscToken used to find tokens in a string
562 
563    Not Collective
564 
565    Input Parameters:
566 +  string - the string to look in
567 -  token - the character to look for
568 
569    Output Parameter:
570 .  a - pointer to token
571 
572    Notes:
573 
574      This version is different from the system version in that
575   it allows you to pass a read-only string into the function.
576 
577    Level: intermediate
578 
579 .seealso: PetscTokenFind(), PetscTokenDestroy()
580 @*/
581 PetscErrorCode PETSC_DLLEXPORT PetscTokenCreate(const char a[],const char b,PetscToken *t)
582 {
583   PetscErrorCode ierr;
584 
585   PetscFunctionBegin;
586   ierr = PetscNew(struct _p_PetscToken,t);CHKERRQ(ierr);
587   ierr = PetscStrallocpy(a,&(*t)->array);CHKERRQ(ierr);
588   (*t)->current = (*t)->array;
589   (*t)->token   = b;
590   PetscFunctionReturn(0);
591 }
592 
593 #undef __FUNCT__
594 #define __FUNCT__ "PetscTokenDestroy"
595 /*@C
596    PetscTokenDestroy - Destroys a PetscToken
597 
598    Not Collective
599 
600    Input Parameters:
601 .  a - pointer to token
602 
603    Level: intermediate
604 
605 .seealso: PetscTokenCreate(), PetscTokenFind()
606 @*/
607 PetscErrorCode PETSC_DLLEXPORT PetscTokenDestroy(PetscToken a)
608 {
609   PetscErrorCode ierr;
610 
611   PetscFunctionBegin;
612   ierr = PetscFree(a->array);CHKERRQ(ierr);
613   ierr = PetscFree(a);CHKERRQ(ierr);
614   PetscFunctionReturn(0);
615 }
616 
617 #undef __FUNCT__
618 #define __FUNCT__ "PetscStrrstr"
619 /*@C
620    PetscStrrstr - Locates last occurance of string in another string
621 
622    Not Collective
623 
624    Input Parameters:
625 +  a - pointer to string
626 -  b - string to find
627 
628    Output Parameter:
629 .  tmp - location of occurance
630 
631    Level: intermediate
632 
633 @*/
634 PetscErrorCode PETSC_DLLEXPORT PetscStrrstr(const char a[],const char b[],char *tmp[])
635 {
636   const char *stmp = a, *ltmp = 0;
637 
638   PetscFunctionBegin;
639   while (stmp) {
640     stmp = (char *)strstr(stmp,b);
641     if (stmp) {ltmp = stmp;stmp++;}
642   }
643   *tmp = (char *)ltmp;
644   PetscFunctionReturn(0);
645 }
646 
647 #undef __FUNCT__
648 #define __FUNCT__ "PetscStrstr"
649 /*@C
650    PetscStrstr - Locates first occurance of string in another string
651 
652    Not Collective
653 
654    Input Parameters:
655 +  a - pointer to string
656 -  b - string to find
657 
658    Output Parameter:
659 .  tmp - location of occurance
660 
661    Level: intermediate
662 
663 @*/
664 PetscErrorCode PETSC_DLLEXPORT PetscStrstr(const char a[],const char b[],char *tmp[])
665 {
666   PetscFunctionBegin;
667   *tmp = (char *)strstr(a,b);
668   PetscFunctionReturn(0);
669 }
670 
671 #undef __FUNCT__
672 #define __FUNCT__ "PetscGetPetscDir"
673 /*@C
674    PetscGetPetscDir - Gets the directory PETSc is installed in
675 
676    Not Collective
677 
678    Output Parameter:
679 .  dir - the directory
680 
681    Level: developer
682 
683 @*/
684 PetscErrorCode PETSC_DLLEXPORT PetscGetPetscDir(const char *dir[])
685 {
686   PetscFunctionBegin;
687   *dir = PETSC_DIR;
688   PetscFunctionReturn(0);
689 }
690 
691 #undef __FUNCT__
692 #define __FUNCT__ "PetscStrreplace"
693 /*@C
694    PetscStrreplace - Replaces substrings in string with other substrings
695 
696    Not Collective
697 
698    Input Parameters:
699 +   comm - MPI_Comm of processors that are processing the string
700 .   aa - the string to look in
701 .   b - the resulting copy of a with replaced strings (b can be the same as a)
702 -   len - the length of b
703 
704    Notes:
705       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
706       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME} with appropriate values
707       as well as any environmental variables.
708 
709       Note: PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what
710       PETSc was built with and do not use environmental variables.
711 
712    Level: intermediate
713 
714 @*/
715 PetscErrorCode PETSC_DLLEXPORT PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
716 {
717   PetscErrorCode ierr;
718   int            i = 0;
719   size_t         l,l1,l2,l3;
720   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
721   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}",0};
722   const char     *r[] = {0,0,0,0,0,0,0,0};
723   PetscTruth     flag;
724 
725   PetscFunctionBegin;
726   if (!a || !b) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
727   if (aa == b) {
728     ierr    = PetscStrallocpy(aa,(char **)&a);CHKERRQ(ierr);
729   }
730   ierr = PetscMalloc(len*sizeof(char*),&work);CHKERRQ(ierr);
731 
732   /* get values for replaced variables */
733   ierr = PetscStrallocpy(PETSC_ARCH,(char**)&r[0]);CHKERRQ(ierr);
734   ierr = PetscStrallocpy(PETSC_DIR,(char**)&r[1]);CHKERRQ(ierr);
735   ierr = PetscStrallocpy(PETSC_LIB_DIR,(char**)&r[2]);CHKERRQ(ierr);
736   ierr = PetscMalloc(256*sizeof(char),&r[3]);CHKERRQ(ierr);
737   ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[4]);CHKERRQ(ierr);
738   ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);CHKERRQ(ierr);
739   ierr = PetscMalloc(256*sizeof(char),&r[6]);CHKERRQ(ierr);
740   ierr = PetscGetDisplay((char*)r[3],256);CHKERRQ(ierr);
741   ierr = PetscGetHomeDirectory((char*)r[4],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
742   ierr = PetscGetWorkingDirectory((char*)r[5],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
743   ierr = PetscGetUserName((char*)r[6],256);CHKERRQ(ierr);
744 
745   /* replace that are in environment */
746   ierr = PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);CHKERRQ(ierr);
747   if (flag) {
748     ierr = PetscStrallocpy(env,(char**)&r[2]);CHKERRQ(ierr);
749   }
750 
751   /* replace the requested strings */
752   ierr = PetscStrncpy(b,a,len);CHKERRQ(ierr);
753   while (s[i]) {
754     ierr = PetscStrlen(s[i],&l);CHKERRQ(ierr);
755     ierr = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
756     while (par) {
757       *par  =  0;
758       par  += l;
759 
760       ierr = PetscStrlen(b,&l1);CHKERRQ(ierr);
761       ierr = PetscStrlen(r[i],&l2);CHKERRQ(ierr);
762       ierr = PetscStrlen(par,&l3);CHKERRQ(ierr);
763       if (l1 + l2 + l3 >= len) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
764       ierr  = PetscStrcpy(work,b);CHKERRQ(ierr);
765       ierr  = PetscStrcat(work,r[i]);CHKERRQ(ierr);
766       ierr  = PetscStrcat(work,par);CHKERRQ(ierr);
767       ierr  = PetscStrncpy(b,work,len);CHKERRQ(ierr);
768       ierr  = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
769     }
770     i++;
771   }
772   i = 0;
773   while (r[i]) {
774     tfree = (char*)r[i];
775     ierr = PetscFree(tfree);CHKERRQ(ierr);
776     i++;
777   }
778 
779   /* look for any other ${xxx} strings to replace from environmental variables */
780   ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
781   while (par) {
782     *par = 0;
783     par += 2;
784     ierr  = PetscStrcpy(work,b);CHKERRQ(ierr);
785     ierr = PetscStrstr(par,"}",&epar);CHKERRQ(ierr);
786     *epar = 0;
787     epar += 1;
788     ierr = PetscOptionsGetenv(comm,par,env,256,&flag);CHKERRQ(ierr);
789     if (!flag) {
790       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
791     }
792     ierr = PetscStrcat(work,env);CHKERRQ(ierr);
793     ierr = PetscStrcat(work,epar);CHKERRQ(ierr);
794     ierr = PetscStrcpy(b,work);CHKERRQ(ierr);
795     ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
796   }
797   ierr = PetscFree(work);CHKERRQ(ierr);
798   if (aa == b) {
799     ierr = PetscFree(a);CHKERRQ(ierr);
800   }
801   PetscFunctionReturn(0);
802 }
803 
804 
805