xref: /petsc/src/sys/utils/str.c (revision 607a6623fc3ebf1ec03868e90ff90ff3b0120740)
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 
10 #if defined(PETSC_HAVE_STRINGS_H)
11 #  include <strings.h>          /* strcasecmp */
12 #endif
13 
14 #undef __FUNCT__
15 #define __FUNCT__ "PetscStrToArray"
16 /*@C
17    PetscStrToArray - Seperates a string by a charactor (for example ' ' or '\n') and creates an array of strings
18 
19    Not Collective
20 
21    Input Parameters:
22 +  s - pointer to string
23 -  sp - separator charactor
24 
25    Output Parameter:
26 +   argc - the number of entries in the array
27 -   args - an array of the entries with a null at the end
28 
29    Level: intermediate
30 
31    Notes: this may be called before PetscInitialize() or after PetscFinalize()
32 
33    Not for use in Fortran
34 
35    Developer Notes: Using raw malloc() and does not call error handlers since this may be used before PETSc is initialized. Used
36      to generate argc, args arguments passed to MPI_Init()
37 
38 .seealso: PetscStrToArrayDestroy(), PetscToken, PetscTokenCreate()
39 
40 @*/
41 PetscErrorCode  PetscStrToArray(const char s[],char sp,int *argc,char ***args)
42 {
43   int       i,n,*lens,cnt = 0;
44   PetscBool flg = PETSC_FALSE;
45 
46   if (!s) n = 0;
47   else    n = strlen(s);
48   *argc = 0;
49   if (!n) {
50     *args = 0;
51     return(0);
52   }
53   for (i=0; i<n; i++) {
54     if (s[i] != sp) break;
55   }
56   for (;i<n+1; i++) {
57     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
58     else if (s[i] != sp) {flg = PETSC_FALSE;}
59   }
60   (*args) = (char**) malloc(((*argc)+1)*sizeof(char*)); if (!*args) return PETSC_ERR_MEM;
61   lens    = (int*) malloc((*argc)*sizeof(int)); if (!lens) return PETSC_ERR_MEM;
62   for (i=0; i<*argc; i++) lens[i] = 0;
63 
64   *argc = 0;
65   for (i=0; i<n; i++) {
66     if (s[i] != sp) break;
67   }
68   for (;i<n+1; i++) {
69     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
70     else if (s[i] != sp) {lens[*argc]++;flg = PETSC_FALSE;}
71   }
72 
73   for (i=0; i<*argc; i++) {
74     (*args)[i] = (char*) malloc((lens[i]+1)*sizeof(char)); if (!(*args)[i]) return PETSC_ERR_MEM;
75   }
76   free(lens);
77   (*args)[*argc] = 0;
78 
79   *argc = 0;
80   for (i=0; i<n; i++) {
81     if (s[i] != sp) break;
82   }
83   for (;i<n+1; i++) {
84     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*args)[*argc][cnt++] = 0; (*argc)++; cnt = 0;}
85     else if (s[i] != sp && s[i] != 0) {(*args)[*argc][cnt++] = s[i]; flg = PETSC_FALSE;}
86   }
87   return 0;
88 }
89 
90 #undef __FUNCT__
91 #define __FUNCT__ "PetscStrToArrayDestroy"
92 /*@C
93    PetscStrToArrayDestroy - Frees array created with PetscStrToArray().
94 
95    Not Collective
96 
97    Output Parameters:
98 +  argc - the number of arguments
99 -  args - the array of arguments
100 
101    Level: intermediate
102 
103    Concepts: command line arguments
104 
105    Notes: This may be called before PetscInitialize() or after PetscFinalize()
106 
107    Not for use in Fortran
108 
109 .seealso: PetscStrToArray()
110 
111 @*/
112 PetscErrorCode  PetscStrToArrayDestroy(int argc,char **args)
113 {
114   PetscInt i;
115 
116   for (i=0; i<argc; i++) free(args[i]);
117   if (args) free(args);
118   return 0;
119 }
120 
121 #undef __FUNCT__
122 #define __FUNCT__ "PetscStrlen"
123 /*@C
124    PetscStrlen - Gets length of a string
125 
126    Not Collective
127 
128    Input Parameters:
129 .  s - pointer to string
130 
131    Output Parameter:
132 .  len - length in bytes
133 
134    Level: intermediate
135 
136    Note:
137    This routine is analogous to strlen().
138 
139    Null string returns a length of zero
140 
141    Not for use in Fortran
142 
143   Concepts: string length
144 
145 @*/
146 PetscErrorCode  PetscStrlen(const char s[],size_t *len)
147 {
148   PetscFunctionBegin;
149   if (!s) *len = 0;
150   else    *len = strlen(s);
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] = 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   PetscFunctionBegin;
256   if (!*list) PetscFunctionReturn(0);
257   while ((*list)[n]) {
258     ierr = PetscFree((*list)[n]);CHKERRQ(ierr);
259     n++;
260   }
261   ierr = PetscFree(*list);CHKERRQ(ierr);
262   PetscFunctionReturn(0);
263 }
264 
265 #undef __FUNCT__
266 #define __FUNCT__ "PetscStrcpy"
267 /*@C
268    PetscStrcpy - Copies a string
269 
270    Not Collective
271 
272    Input Parameters:
273 .  t - pointer to string
274 
275    Output Parameter:
276 .  s - the copied string
277 
278    Level: intermediate
279 
280    Notes:
281      Null string returns a string starting with zero
282 
283      Not for use in Fortran
284 
285   Concepts: string copy
286 
287 .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()
288 
289 @*/
290 
291 PetscErrorCode  PetscStrcpy(char s[],const char t[])
292 {
293   PetscFunctionBegin;
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   PetscFunctionReturn(0);
298 }
299 
300 #undef __FUNCT__
301 #define __FUNCT__ "PetscStrncpy"
302 /*@C
303    PetscStrncpy - Copies a string up to a certain length
304 
305    Not Collective
306 
307    Input Parameters:
308 +  t - pointer to string
309 -  n - the length to copy
310 
311    Output Parameter:
312 .  s - the copied string
313 
314    Level: intermediate
315 
316    Note:
317      Null string returns a string starting with zero
318 
319   Concepts: string copy
320 
321 .seealso: PetscStrcpy(), PetscStrcat(), PetscStrncat()
322 
323 @*/
324 PetscErrorCode  PetscStrncpy(char s[],const char t[],size_t n)
325 {
326   PetscFunctionBegin;
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   PetscFunctionReturn(0);
331 }
332 
333 #undef __FUNCT__
334 #define __FUNCT__ "PetscStrcat"
335 /*@C
336    PetscStrcat - Concatenates a string onto a given string
337 
338    Not Collective
339 
340    Input Parameters:
341 +  s - string to be added to
342 -  t - pointer to string to be added to end
343 
344    Level: intermediate
345 
346    Notes: Not for use in Fortran
347 
348   Concepts: string copy
349 
350 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
351 
352 @*/
353 PetscErrorCode  PetscStrcat(char s[],const char t[])
354 {
355   PetscFunctionBegin;
356   if (!t) PetscFunctionReturn(0);
357   strcat(s,t);
358   PetscFunctionReturn(0);
359 }
360 
361 #undef __FUNCT__
362 #define __FUNCT__ "PetscStrncat"
363 /*@C
364    PetscStrncat - Concatenates a string onto a given string, up to a given length
365 
366    Not Collective
367 
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
372 
373    Level: intermediate
374 
375   Notes:    Not for use in Fortran
376 
377   Concepts: string copy
378 
379 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
380 
381 @*/
382 PetscErrorCode  PetscStrncat(char s[],const char t[],size_t n)
383 {
384   PetscFunctionBegin;
385   strncat(s,t,n);
386   PetscFunctionReturn(0);
387 }
388 
389 #undef __FUNCT__
390 #define __FUNCT__ "PetscStrcmpNoError"
391 /*
392    Only to be used with PetscCheck__FUNCT__()!
393 
394    Will be removed once we eliminate the __FUNCT__ paradigm
395 */
396 void  PetscStrcmpNoError(const char a[],const char b[],PetscBool  *flg)
397 {
398   int c;
399 
400   if (!a && !b)      *flg = PETSC_TRUE;
401   else if (!a || !b) *flg = PETSC_FALSE;
402   else {
403     c = strcmp(a,b);
404     if (c) *flg = PETSC_FALSE;
405     else   *flg = PETSC_TRUE;
406   }
407 }
408 
409 #undef __FUNCT__
410 #define __FUNCT__ "PetscStrcmp"
411 /*@C
412    PetscStrcmp - Compares two strings,
413 
414    Not Collective
415 
416    Input Parameters:
417 +  a - pointer to string first string
418 -  b - pointer to second string
419 
420    Output Parameter:
421 .  flg - PETSC_TRUE if the two strings are equal
422 
423    Level: intermediate
424 
425    Notes:    Not for use in Fortran
426 
427 .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()
428 
429 @*/
430 PetscErrorCode  PetscStrcmp(const char a[],const char b[],PetscBool  *flg)
431 {
432   int c;
433 
434   PetscFunctionBegin;
435   if (!a && !b)      *flg = PETSC_TRUE;
436   else if (!a || !b) *flg = PETSC_FALSE;
437   else {
438     c = strcmp(a,b);
439     if (c) *flg = PETSC_FALSE;
440     else   *flg = PETSC_TRUE;
441   }
442   PetscFunctionReturn(0);
443 }
444 
445 #undef __FUNCT__
446 #define __FUNCT__ "PetscStrgrt"
447 /*@C
448    PetscStrgrt - If first string is greater than the second
449 
450    Not Collective
451 
452    Input Parameters:
453 +  a - pointer to first string
454 -  b - pointer to second string
455 
456    Output Parameter:
457 .  flg - if the first string is greater
458 
459    Notes:
460     Null arguments are ok, a null string is considered smaller than
461     all others
462 
463    Not for use in Fortran
464 
465    Level: intermediate
466 
467 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()
468 
469 @*/
470 PetscErrorCode  PetscStrgrt(const char a[],const char b[],PetscBool  *t)
471 {
472   int c;
473 
474   PetscFunctionBegin;
475   if (!a && !b) *t = PETSC_FALSE;
476   else if (a && !b) *t = PETSC_TRUE;
477   else if (!a && b) *t = PETSC_FALSE;
478   else {
479     c = strcmp(a,b);
480     if (c > 0) *t = PETSC_TRUE;
481     else       *t = PETSC_FALSE;
482   }
483   PetscFunctionReturn(0);
484 }
485 
486 #undef __FUNCT__
487 #define __FUNCT__ "PetscStrcasecmp"
488 /*@C
489    PetscStrcasecmp - Returns true if the two strings are the same
490      except possibly for case.
491 
492    Not Collective
493 
494    Input Parameters:
495 +  a - pointer to first string
496 -  b - pointer to second string
497 
498    Output Parameter:
499 .  flg - if the two strings are the same
500 
501    Notes:
502     Null arguments are ok
503 
504    Not for use in Fortran
505 
506    Level: intermediate
507 
508 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()
509 
510 @*/
511 PetscErrorCode  PetscStrcasecmp(const char a[],const char b[],PetscBool  *t)
512 {
513   int c;
514 
515   PetscFunctionBegin;
516   if (!a && !b) c = 0;
517   else if (!a || !b) c = 1;
518 #if defined(PETSC_HAVE_STRCASECMP)
519   else c = strcasecmp(a,b);
520 #elif defined(PETSC_HAVE_STRICMP)
521   else c = stricmp(a,b);
522 #else
523   else {
524     char           *aa,*bb;
525     PetscErrorCode ierr;
526     ierr = PetscStrallocpy(a,&aa);CHKERRQ(ierr);
527     ierr = PetscStrallocpy(b,&bb);CHKERRQ(ierr);
528     ierr = PetscStrtolower(aa);CHKERRQ(ierr);
529     ierr = PetscStrtolower(bb);CHKERRQ(ierr);
530     ierr = PetscStrcmp(aa,bb,t);CHKERRQ(ierr);
531     ierr = PetscFree(aa);CHKERRQ(ierr);
532     ierr = PetscFree(bb);CHKERRQ(ierr);
533     PetscFunctionReturn(0);
534   }
535 #endif
536   if (!c) *t = PETSC_TRUE;
537   else    *t = PETSC_FALSE;
538   PetscFunctionReturn(0);
539 }
540 
541 
542 
543 #undef __FUNCT__
544 #define __FUNCT__ "PetscStrncmp"
545 /*@C
546    PetscStrncmp - Compares two strings, up to a certain length
547 
548    Not Collective
549 
550    Input Parameters:
551 +  a - pointer to first string
552 .  b - pointer to second string
553 -  n - length to compare up to
554 
555    Output Parameter:
556 .  t - if the two strings are equal
557 
558    Level: intermediate
559 
560    Notes:    Not for use in Fortran
561 
562 .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()
563 
564 @*/
565 PetscErrorCode  PetscStrncmp(const char a[],const char b[],size_t n,PetscBool  *t)
566 {
567   int c;
568 
569   PetscFunctionBegin;
570   c = strncmp(a,b,n);
571   if (!c) *t = PETSC_TRUE;
572   else    *t = PETSC_FALSE;
573   PetscFunctionReturn(0);
574 }
575 
576 #undef __FUNCT__
577 #define __FUNCT__ "PetscStrchr"
578 /*@C
579    PetscStrchr - Locates first occurance of a character in a string
580 
581    Not Collective
582 
583    Input Parameters:
584 +  a - pointer to string
585 -  b - character
586 
587    Output Parameter:
588 .  c - location of occurance, NULL if not found
589 
590    Level: intermediate
591 
592    Notes:    Not for use in Fortran
593 
594 @*/
595 PetscErrorCode  PetscStrchr(const char a[],char b,char *c[])
596 {
597   PetscFunctionBegin;
598   *c = (char*)strchr(a,b);
599   PetscFunctionReturn(0);
600 }
601 
602 #undef __FUNCT__
603 #define __FUNCT__ "PetscStrrchr"
604 /*@C
605    PetscStrrchr - Locates one location past the last occurance of a character in a string,
606       if the character is not found then returns entire string
607 
608    Not Collective
609 
610    Input Parameters:
611 +  a - pointer to string
612 -  b - character
613 
614    Output Parameter:
615 .  tmp - location of occurance, a if not found
616 
617    Level: intermediate
618 
619    Notes:    Not for use in Fortran
620 
621 @*/
622 PetscErrorCode  PetscStrrchr(const char a[],char b,char *tmp[])
623 {
624   PetscFunctionBegin;
625   *tmp = (char*)strrchr(a,b);
626   if (!*tmp) *tmp = (char*)a;
627   else *tmp = *tmp + 1;
628   PetscFunctionReturn(0);
629 }
630 
631 #undef __FUNCT__
632 #define __FUNCT__ "PetscStrtolower"
633 /*@C
634    PetscStrtolower - Converts string to lower case
635 
636    Not Collective
637 
638    Input Parameters:
639 .  a - pointer to string
640 
641    Level: intermediate
642 
643    Notes:    Not for use in Fortran
644 
645 @*/
646 PetscErrorCode  PetscStrtolower(char a[])
647 {
648   PetscFunctionBegin;
649   while (*a) {
650     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
651     a++;
652   }
653   PetscFunctionReturn(0);
654 }
655 
656 #undef __FUNCT__
657 #define __FUNCT__ "PetscStrtoupper"
658 /*@C
659    PetscStrtolower - Converts string to upper case
660 
661    Not Collective
662 
663    Input Parameters:
664 .  a - pointer to string
665 
666    Level: intermediate
667 
668    Notes:    Not for use in Fortran
669 
670 @*/
671 PetscErrorCode  PetscStrtoupper(char a[])
672 {
673   PetscFunctionBegin;
674   while (*a) {
675     if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a';
676     a++;
677   }
678   PetscFunctionReturn(0);
679 }
680 
681 #undef __FUNCT__
682 #define __FUNCT__ "PetscStrendswith"
683 /*@C
684    PetscStrendswith - Determines if a string ends with a certain string
685 
686    Not Collective
687 
688    Input Parameters:
689 +  a - pointer to string
690 -  b - string to endwith
691 
692    Output Parameter:
693 .  flg - PETSC_TRUE or PETSC_FALSE
694 
695    Notes:     Not for use in Fortran
696 
697    Level: intermediate
698 
699 @*/
700 PetscErrorCode  PetscStrendswith(const char a[],const char b[],PetscBool *flg)
701 {
702   char           *test;
703   PetscErrorCode ierr;
704   size_t         na,nb;
705 
706   PetscFunctionBegin;
707   *flg = PETSC_FALSE;
708   ierr = PetscStrrstr(a,b,&test);CHKERRQ(ierr);
709   if (test) {
710     ierr = PetscStrlen(a,&na);CHKERRQ(ierr);
711     ierr = PetscStrlen(b,&nb);CHKERRQ(ierr);
712     if (a+na-nb == test) *flg = PETSC_TRUE;
713   }
714   PetscFunctionReturn(0);
715 }
716 
717 #undef __FUNCT__
718 #define __FUNCT__ "PetscStrbeginswith"
719 /*@C
720    PetscStrbeginswith - Determines if a string begins with a certain string
721 
722    Not Collective
723 
724    Input Parameters:
725 +  a - pointer to string
726 -  b - string to beginwith
727 
728    Output Parameter:
729 .  flg - PETSC_TRUE or PETSC_FALSE
730 
731    Notes:     Not for use in Fortran
732 
733    Level: intermediate
734 
735 @*/
736 PetscErrorCode  PetscStrbeginswith(const char a[],const char b[],PetscBool *flg)
737 {
738   char           *test;
739   PetscErrorCode ierr;
740 
741   PetscFunctionBegin;
742   *flg = PETSC_FALSE;
743   ierr = PetscStrrstr(a,b,&test);CHKERRQ(ierr);
744   if (test && (test == a)) *flg = PETSC_TRUE;
745   PetscFunctionReturn(0);
746 }
747 
748 
749 #undef __FUNCT__
750 #define __FUNCT__ "PetscStrendswithwhich"
751 /*@C
752    PetscStrendswithwhich - Determines if a string ends with one of several possible strings
753 
754    Not Collective
755 
756    Input Parameters:
757 +  a - pointer to string
758 -  bs - strings to endwith (last entry must be null)
759 
760    Output Parameter:
761 .  cnt - the index of the string it ends with or 1+the last possible index
762 
763    Notes:     Not for use in Fortran
764 
765    Level: intermediate
766 
767 @*/
768 PetscErrorCode  PetscStrendswithwhich(const char a[],const char *const *bs,PetscInt *cnt)
769 {
770   PetscBool      flg;
771   PetscErrorCode ierr;
772 
773   PetscFunctionBegin;
774   *cnt = 0;
775   while (bs[*cnt]) {
776     ierr = PetscStrendswith(a,bs[*cnt],&flg);CHKERRQ(ierr);
777     if (flg) PetscFunctionReturn(0);
778     *cnt += 1;
779   }
780   PetscFunctionReturn(0);
781 }
782 
783 #undef __FUNCT__
784 #define __FUNCT__ "PetscStrrstr"
785 /*@C
786    PetscStrrstr - Locates last occurance of string in another string
787 
788    Not Collective
789 
790    Input Parameters:
791 +  a - pointer to string
792 -  b - string to find
793 
794    Output Parameter:
795 .  tmp - location of occurance
796 
797    Notes:     Not for use in Fortran
798 
799    Level: intermediate
800 
801 @*/
802 PetscErrorCode  PetscStrrstr(const char a[],const char b[],char *tmp[])
803 {
804   const char *stmp = a, *ltmp = 0;
805 
806   PetscFunctionBegin;
807   while (stmp) {
808     stmp = (char*)strstr(stmp,b);
809     if (stmp) {ltmp = stmp;stmp++;}
810   }
811   *tmp = (char*)ltmp;
812   PetscFunctionReturn(0);
813 }
814 
815 #undef __FUNCT__
816 #define __FUNCT__ "PetscStrstr"
817 /*@C
818    PetscStrstr - Locates first occurance of string in another string
819 
820    Not Collective
821 
822    Input Parameters:
823 +  haystack - string to search
824 -  needle - string to find
825 
826    Output Parameter:
827 .  tmp - location of occurance, is a NULL if the string is not found
828 
829    Notes: Not for use in Fortran
830 
831    Level: intermediate
832 
833 @*/
834 PetscErrorCode  PetscStrstr(const char haystack[],const char needle[],char *tmp[])
835 {
836   PetscFunctionBegin;
837   *tmp = (char*)strstr(haystack,needle);
838   PetscFunctionReturn(0);
839 }
840 
841 struct _p_PetscToken {char token;char *array;char *current;};
842 
843 #undef __FUNCT__
844 #define __FUNCT__ "PetscTokenFind"
845 /*@C
846    PetscTokenFind - Locates next "token" in a string
847 
848    Not Collective
849 
850    Input Parameters:
851 .  a - pointer to token
852 
853    Output Parameter:
854 .  result - location of occurance, NULL if not found
855 
856    Notes:
857 
858      This version is different from the system version in that
859   it allows you to pass a read-only string into the function.
860 
861      This version also treats all characters etc. inside a double quote "
862    as a single token.
863 
864     Not for use in Fortran
865 
866    Level: intermediate
867 
868 
869 .seealso: PetscTokenCreate(), PetscTokenDestroy()
870 @*/
871 PetscErrorCode  PetscTokenFind(PetscToken a,char *result[])
872 {
873   char *ptr = a->current,token;
874 
875   PetscFunctionBegin;
876   *result = a->current;
877   if (ptr && !*ptr) {*result = 0;PetscFunctionReturn(0);}
878   token = a->token;
879   if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
880   while (ptr) {
881     if (*ptr == token) {
882       *ptr++ = 0;
883       while (*ptr == a->token) ptr++;
884       a->current = ptr;
885       break;
886     }
887     if (!*ptr) {
888       a->current = 0;
889       break;
890     }
891     ptr++;
892   }
893   PetscFunctionReturn(0);
894 }
895 
896 #undef __FUNCT__
897 #define __FUNCT__ "PetscTokenCreate"
898 /*@C
899    PetscTokenCreate - Creates a PetscToken used to find tokens in a string
900 
901    Not Collective
902 
903    Input Parameters:
904 +  string - the string to look in
905 -  token - the character to look for
906 
907    Output Parameter:
908 .  a - pointer to token
909 
910    Notes:
911 
912      This version is different from the system version in that
913   it allows you to pass a read-only string into the function.
914 
915     Not for use in Fortran
916 
917    Level: intermediate
918 
919 .seealso: PetscTokenFind(), PetscTokenDestroy()
920 @*/
921 PetscErrorCode  PetscTokenCreate(const char a[],const char b,PetscToken *t)
922 {
923   PetscErrorCode ierr;
924 
925   PetscFunctionBegin;
926   ierr = PetscNew(struct _p_PetscToken,t);CHKERRQ(ierr);
927   ierr = PetscStrallocpy(a,&(*t)->array);CHKERRQ(ierr);
928 
929   (*t)->current = (*t)->array;
930   (*t)->token   = b;
931   PetscFunctionReturn(0);
932 }
933 
934 #undef __FUNCT__
935 #define __FUNCT__ "PetscTokenDestroy"
936 /*@C
937    PetscTokenDestroy - Destroys a PetscToken
938 
939    Not Collective
940 
941    Input Parameters:
942 .  a - pointer to token
943 
944    Level: intermediate
945 
946    Notes:     Not for use in Fortran
947 
948 .seealso: PetscTokenCreate(), PetscTokenFind()
949 @*/
950 PetscErrorCode  PetscTokenDestroy(PetscToken *a)
951 {
952   PetscErrorCode ierr;
953 
954   PetscFunctionBegin;
955   if (!*a) PetscFunctionReturn(0);
956   ierr = PetscFree((*a)->array);CHKERRQ(ierr);
957   ierr = PetscFree(*a);CHKERRQ(ierr);
958   PetscFunctionReturn(0);
959 }
960 
961 
962 #undef __FUNCT__
963 #define __FUNCT__ "PetscGetPetscDir"
964 /*@C
965    PetscGetPetscDir - Gets the directory PETSc is installed in
966 
967    Not Collective
968 
969    Output Parameter:
970 .  dir - the directory
971 
972    Level: developer
973 
974    Notes: Not for use in Fortran
975 
976 @*/
977 PetscErrorCode  PetscGetPetscDir(const char *dir[])
978 {
979   PetscFunctionBegin;
980   *dir = PETSC_DIR;
981   PetscFunctionReturn(0);
982 }
983 
984 #undef __FUNCT__
985 #define __FUNCT__ "PetscStrreplace"
986 /*@C
987    PetscStrreplace - Replaces substrings in string with other substrings
988 
989    Not Collective
990 
991    Input Parameters:
992 +   comm - MPI_Comm of processors that are processing the string
993 .   aa - the string to look in
994 .   b - the resulting copy of a with replaced strings (b can be the same as a)
995 -   len - the length of b
996 
997    Notes:
998       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
999       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values
1000       as well as any environmental variables.
1001 
1002       PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what
1003       PETSc was built with and do not use environmental variables.
1004 
1005       Not for use in Fortran
1006 
1007    Level: intermediate
1008 
1009 @*/
1010 PetscErrorCode  PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
1011 {
1012   PetscErrorCode ierr;
1013   int            i = 0;
1014   size_t         l,l1,l2,l3;
1015   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
1016   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}","${HOSTNAME}",0};
1017   const char     *r[] = {0,0,0,0,0,0,0,0,0};
1018   PetscBool      flag;
1019 
1020   PetscFunctionBegin;
1021   if (!a || !b) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
1022   if (aa == b) {
1023     ierr = PetscStrallocpy(aa,(char**)&a);CHKERRQ(ierr);
1024   }
1025   ierr = PetscMalloc(len*sizeof(char*),&work);CHKERRQ(ierr);
1026 
1027   /* get values for replaced variables */
1028   ierr = PetscStrallocpy(PETSC_ARCH,(char**)&r[0]);CHKERRQ(ierr);
1029   ierr = PetscStrallocpy(PETSC_DIR,(char**)&r[1]);CHKERRQ(ierr);
1030   ierr = PetscStrallocpy(PETSC_LIB_DIR,(char**)&r[2]);CHKERRQ(ierr);
1031   ierr = PetscMalloc(256*sizeof(char),&r[3]);CHKERRQ(ierr);
1032   ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[4]);CHKERRQ(ierr);
1033   ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);CHKERRQ(ierr);
1034   ierr = PetscMalloc(256*sizeof(char),&r[6]);CHKERRQ(ierr);
1035   ierr = PetscMalloc(256*sizeof(char),&r[7]);CHKERRQ(ierr);
1036   ierr = PetscGetDisplay((char*)r[3],256);CHKERRQ(ierr);
1037   ierr = PetscGetHomeDirectory((char*)r[4],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
1038   ierr = PetscGetWorkingDirectory((char*)r[5],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
1039   ierr = PetscGetUserName((char*)r[6],256);CHKERRQ(ierr);
1040   ierr = PetscGetHostName((char*)r[7],256);CHKERRQ(ierr);
1041 
1042   /* replace that are in environment */
1043   ierr = PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);CHKERRQ(ierr);
1044   if (flag) {
1045     ierr = PetscStrallocpy(env,(char**)&r[2]);CHKERRQ(ierr);
1046   }
1047 
1048   /* replace the requested strings */
1049   ierr = PetscStrncpy(b,a,len);CHKERRQ(ierr);
1050   while (s[i]) {
1051     ierr = PetscStrlen(s[i],&l);CHKERRQ(ierr);
1052     ierr = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
1053     while (par) {
1054       *par =  0;
1055       par += l;
1056 
1057       ierr = PetscStrlen(b,&l1);CHKERRQ(ierr);
1058       ierr = PetscStrlen(r[i],&l2);CHKERRQ(ierr);
1059       ierr = PetscStrlen(par,&l3);CHKERRQ(ierr);
1060       if (l1 + l2 + l3 >= len) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
1061       ierr = PetscStrcpy(work,b);CHKERRQ(ierr);
1062       ierr = PetscStrcat(work,r[i]);CHKERRQ(ierr);
1063       ierr = PetscStrcat(work,par);CHKERRQ(ierr);
1064       ierr = PetscStrncpy(b,work,len);CHKERRQ(ierr);
1065       ierr = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
1066     }
1067     i++;
1068   }
1069   i = 0;
1070   while (r[i]) {
1071     tfree = (char*)r[i];
1072     ierr  = PetscFree(tfree);CHKERRQ(ierr);
1073     i++;
1074   }
1075 
1076   /* look for any other ${xxx} strings to replace from environmental variables */
1077   ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
1078   while (par) {
1079     *par  = 0;
1080     par  += 2;
1081     ierr  = PetscStrcpy(work,b);CHKERRQ(ierr);
1082     ierr  = PetscStrstr(par,"}",&epar);CHKERRQ(ierr);
1083     *epar = 0;
1084     epar += 1;
1085     ierr  = PetscOptionsGetenv(comm,par,env,256,&flag);CHKERRQ(ierr);
1086     if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
1087     ierr = PetscStrcat(work,env);CHKERRQ(ierr);
1088     ierr = PetscStrcat(work,epar);CHKERRQ(ierr);
1089     ierr = PetscStrcpy(b,work);CHKERRQ(ierr);
1090     ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
1091   }
1092   ierr = PetscFree(work);CHKERRQ(ierr);
1093   if (aa == b) {
1094     ierr = PetscFree(a);CHKERRQ(ierr);
1095   }
1096   PetscFunctionReturn(0);
1097 }
1098 
1099 
1100