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