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