xref: /petsc/src/sys/utils/str.c (revision 560360af1e0197128c3ad6271bbfa2e76ad345d4)
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>             /* strstr */
11 #endif
12 #if defined(PETSC_HAVE_STRINGS_H)
13 #  include <strings.h>          /* strcasecmp */
14 #endif
15 
16 #undef __FUNCT__
17 #define __FUNCT__ "PetscStrToArray"
18 /*@C
19    PetscStrToArray - Separates a string by a charactor (for example ' ' or '\n') and creates an array of strings
20 
21    Not Collective
22 
23    Input Parameters:
24 +  s - pointer to string
25 -  sp - separator charactor
26 
27    Output Parameter:
28 +   argc - the number of entries in the array
29 -   args - an array of the entries with a null at the end
30 
31    Level: intermediate
32 
33    Notes: this may be called before PetscInitialize() or after PetscFinalize()
34 
35    Not for use in Fortran
36 
37    Developer Notes: Using raw malloc() and does not call error handlers since this may be used before PETSc is initialized. Used
38      to generate argc, args arguments passed to MPI_Init()
39 
40 .seealso: PetscStrToArrayDestroy(), PetscToken, PetscTokenCreate()
41 
42 @*/
43 PetscErrorCode  PetscStrToArray(const char s[],char sp,int *argc,char ***args)
44 {
45   int       i,n,*lens,cnt = 0;
46   PetscBool flg = PETSC_FALSE;
47 
48   if (!s) n = 0;
49   else    n = strlen(s);
50   *argc = 0;
51   *args = NULL;
52   if (!n) {
53     return(0);
54   }
55   for (i=0; i<n; i++) {
56     if (s[i] != sp) break;
57   }
58   for (;i<n+1; i++) {
59     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
60     else if (s[i] != sp) {flg = PETSC_FALSE;}
61   }
62   if (!*argc) { /* string only has separator characters */
63     return(0);
64   }
65   (*args) = (char**) malloc(((*argc)+1)*sizeof(char*)); if (!*args) return PETSC_ERR_MEM;
66   lens    = (int*) malloc((*argc)*sizeof(int)); if (!lens) return PETSC_ERR_MEM;
67   for (i=0; i<*argc; i++) lens[i] = 0;
68 
69   *argc = 0;
70   for (i=0; i<n; i++) {
71     if (s[i] != sp) break;
72   }
73   for (;i<n+1; i++) {
74     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
75     else if (s[i] != sp) {lens[*argc]++;flg = PETSC_FALSE;}
76   }
77 
78   for (i=0; i<*argc; i++) {
79     (*args)[i] = (char*) malloc((lens[i]+1)*sizeof(char)); if (!(*args)[i]) return PETSC_ERR_MEM;
80   }
81   free(lens);
82   (*args)[*argc] = 0;
83 
84   *argc = 0;
85   for (i=0; i<n; i++) {
86     if (s[i] != sp) break;
87   }
88   for (;i<n+1; i++) {
89     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*args)[*argc][cnt++] = 0; (*argc)++; cnt = 0;}
90     else if (s[i] != sp && s[i] != 0) {(*args)[*argc][cnt++] = s[i]; flg = PETSC_FALSE;}
91   }
92   return 0;
93 }
94 
95 #undef __FUNCT__
96 #define __FUNCT__ "PetscStrToArrayDestroy"
97 /*@C
98    PetscStrToArrayDestroy - Frees array created with PetscStrToArray().
99 
100    Not Collective
101 
102    Output Parameters:
103 +  argc - the number of arguments
104 -  args - the array of arguments
105 
106    Level: intermediate
107 
108    Concepts: command line arguments
109 
110    Notes: This may be called before PetscInitialize() or after PetscFinalize()
111 
112    Not for use in Fortran
113 
114 .seealso: PetscStrToArray()
115 
116 @*/
117 PetscErrorCode  PetscStrToArrayDestroy(int argc,char **args)
118 {
119   PetscInt i;
120 
121   for (i=0; i<argc; i++) free(args[i]);
122   if (args) free(args);
123   return 0;
124 }
125 
126 #undef __FUNCT__
127 #define __FUNCT__ "PetscStrlen"
128 /*@C
129    PetscStrlen - Gets length of a string
130 
131    Not Collective
132 
133    Input Parameters:
134 .  s - pointer to string
135 
136    Output Parameter:
137 .  len - length in bytes
138 
139    Level: intermediate
140 
141    Note:
142    This routine is analogous to strlen().
143 
144    Null string returns a length of zero
145 
146    Not for use in Fortran
147 
148   Concepts: string length
149 
150 @*/
151 PetscErrorCode  PetscStrlen(const char s[],size_t *len)
152 {
153   PetscFunctionBegin;
154   if (!s) *len = 0;
155   else    *len = strlen(s);
156   PetscFunctionReturn(0);
157 }
158 
159 #undef __FUNCT__
160 #define __FUNCT__ "PetscStrallocpy"
161 /*@C
162    PetscStrallocpy - Allocates space to hold a copy of a string then copies the string
163 
164    Not Collective
165 
166    Input Parameters:
167 .  s - pointer to string
168 
169    Output Parameter:
170 .  t - the copied string
171 
172    Level: intermediate
173 
174    Note:
175       Null string returns a new null string
176 
177       Not for use in Fortran
178 
179   Concepts: string copy
180 
181 @*/
182 PetscErrorCode  PetscStrallocpy(const char s[],char *t[])
183 {
184   PetscErrorCode ierr;
185   size_t         len;
186   char           *tmp = 0;
187 
188   PetscFunctionBegin;
189   if (s) {
190     ierr = PetscStrlen(s,&len);CHKERRQ(ierr);
191     ierr = PetscMalloc1(1+len,&tmp);CHKERRQ(ierr);
192     ierr = PetscStrcpy(tmp,s);CHKERRQ(ierr);
193   }
194   *t = tmp;
195   PetscFunctionReturn(0);
196 }
197 
198 #undef __FUNCT__
199 #define __FUNCT__ "PetscStrArrayallocpy"
200 /*@C
201    PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
202 
203    Not Collective
204 
205    Input Parameters:
206 .  s - pointer to array of strings (final string is a null)
207 
208    Output Parameter:
209 .  t - the copied array string
210 
211    Level: intermediate
212 
213    Note:
214       Not for use in Fortran
215 
216   Concepts: string copy
217 
218 .seealso: PetscStrallocpy() PetscStrArrayDestroy()
219 
220 @*/
221 PetscErrorCode  PetscStrArrayallocpy(const char *const *list,char ***t)
222 {
223   PetscErrorCode ierr;
224   PetscInt       i,n = 0;
225 
226   PetscFunctionBegin;
227   while (list[n++]) ;
228   ierr = PetscMalloc1(n+1,t);CHKERRQ(ierr);
229   for (i=0; i<n; i++) {
230     ierr = PetscStrallocpy(list[i],(*t)+i);CHKERRQ(ierr);
231   }
232   (*t)[n] = NULL;
233   PetscFunctionReturn(0);
234 }
235 
236 #undef __FUNCT__
237 #define __FUNCT__ "PetscStrArrayDestroy"
238 /*@C
239    PetscStrArrayDestroy - Frees array of strings created with PetscStrArrayallocpy().
240 
241    Not Collective
242 
243    Output Parameters:
244 .   list - array of strings
245 
246    Level: intermediate
247 
248    Concepts: command line arguments
249 
250    Notes: Not for use in Fortran
251 
252 .seealso: PetscStrArrayallocpy()
253 
254 @*/
255 PetscErrorCode PetscStrArrayDestroy(char ***list)
256 {
257   PetscInt       n = 0;
258   PetscErrorCode ierr;
259 
260   PetscFunctionBegin;
261   if (!*list) PetscFunctionReturn(0);
262   while ((*list)[n]) {
263     ierr = PetscFree((*list)[n]);CHKERRQ(ierr);
264     n++;
265   }
266   ierr = PetscFree(*list);CHKERRQ(ierr);
267   PetscFunctionReturn(0);
268 }
269 
270 #undef __FUNCT__
271 #define __FUNCT__ "PetscStrNArrayallocpy"
272 /*@C
273    PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
274 
275    Not Collective
276 
277    Input Parameters:
278 +  n - the number of string entries
279 -  s - pointer to array of strings
280 
281    Output Parameter:
282 .  t - the copied array string
283 
284    Level: intermediate
285 
286    Note:
287       Not for use in Fortran
288 
289   Concepts: string copy
290 
291 .seealso: PetscStrallocpy() PetscStrArrayDestroy()
292 
293 @*/
294 PetscErrorCode  PetscStrNArrayallocpy(PetscInt n,const char *const *list,char ***t)
295 {
296   PetscErrorCode ierr;
297   PetscInt       i;
298 
299   PetscFunctionBegin;
300   ierr = PetscMalloc1(n,t);CHKERRQ(ierr);
301   for (i=0; i<n; i++) {
302     ierr = PetscStrallocpy(list[i],(*t)+i);CHKERRQ(ierr);
303   }
304   PetscFunctionReturn(0);
305 }
306 
307 #undef __FUNCT__
308 #define __FUNCT__ "PetscStrNArrayDestroy"
309 /*@C
310    PetscStrNArrayDestroy - Frees array of strings created with PetscStrArrayallocpy().
311 
312    Not Collective
313 
314    Output Parameters:
315 +   n - number of string entries
316 -   list - array of strings
317 
318    Level: intermediate
319 
320    Notes: Not for use in Fortran
321 
322 .seealso: PetscStrArrayallocpy()
323 
324 @*/
325 PetscErrorCode PetscStrNArrayDestroy(PetscInt n,char ***list)
326 {
327   PetscErrorCode ierr;
328   PetscInt       i;
329 
330   PetscFunctionBegin;
331   if (!*list) PetscFunctionReturn(0);
332   for (i=0; i<n; i++){
333     ierr = PetscFree((*list)[i]);CHKERRQ(ierr);
334   }
335   ierr = PetscFree(*list);CHKERRQ(ierr);
336   PetscFunctionReturn(0);
337 }
338 
339 #undef __FUNCT__
340 #define __FUNCT__ "PetscStrcpy"
341 /*@C
342    PetscStrcpy - Copies a string
343 
344    Not Collective
345 
346    Input Parameters:
347 .  t - pointer to string
348 
349    Output Parameter:
350 .  s - the copied string
351 
352    Level: intermediate
353 
354    Notes:
355      Null string returns a string starting with zero
356 
357      Not for use in Fortran
358 
359   Concepts: string copy
360 
361 .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()
362 
363 @*/
364 
365 PetscErrorCode  PetscStrcpy(char s[],const char t[])
366 {
367   PetscFunctionBegin;
368   if (t && !s) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
369   if (t) strcpy(s,t);
370   else if (s) s[0] = 0;
371   PetscFunctionReturn(0);
372 }
373 
374 #undef __FUNCT__
375 #define __FUNCT__ "PetscStrncpy"
376 /*@C
377    PetscStrncpy - Copies a string up to a certain length
378 
379    Not Collective
380 
381    Input Parameters:
382 +  t - pointer to string
383 -  n - the length to copy
384 
385    Output Parameter:
386 .  s - the copied string
387 
388    Level: intermediate
389 
390    Note:
391      Null string returns a string starting with zero
392 
393      If the string that is being copied is of length n or larger then the entire string is not
394      copied and the file location of s is set to NULL. This is different then the behavior of
395      strncpy() which leaves s non-terminated.
396 
397   Concepts: string copy
398 
399 .seealso: PetscStrcpy(), PetscStrcat(), PetscStrncat()
400 
401 @*/
402 PetscErrorCode  PetscStrncpy(char s[],const char t[],size_t n)
403 {
404   PetscFunctionBegin;
405   if (t && !s) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
406   if (t) {
407     if (n > 1) {
408       strncpy(s,t,n-1);
409       s[n-1] = '\0';
410     } else {
411       s[0] = '\0';
412     }
413   } else if (s) s[0] = 0;
414   PetscFunctionReturn(0);
415 }
416 
417 #undef __FUNCT__
418 #define __FUNCT__ "PetscStrcat"
419 /*@C
420    PetscStrcat - Concatenates a string onto a given string
421 
422    Not Collective
423 
424    Input Parameters:
425 +  s - string to be added to
426 -  t - pointer to string to be added to end
427 
428    Level: intermediate
429 
430    Notes: Not for use in Fortran
431 
432   Concepts: string copy
433 
434 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
435 
436 @*/
437 PetscErrorCode  PetscStrcat(char s[],const char t[])
438 {
439   PetscFunctionBegin;
440   if (!t) PetscFunctionReturn(0);
441   strcat(s,t);
442   PetscFunctionReturn(0);
443 }
444 
445 #undef __FUNCT__
446 #define __FUNCT__ "PetscStrncat"
447 /*@C
448    PetscStrncat - Concatenates a string onto a given string, up to a given length
449 
450    Not Collective
451 
452    Input Parameters:
453 +  s - pointer to string to be added to end
454 .  t - string to be added to
455 .  n - maximum length to copy
456 
457    Level: intermediate
458 
459   Notes:    Not for use in Fortran
460 
461   Concepts: string copy
462 
463 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
464 
465 @*/
466 PetscErrorCode  PetscStrncat(char s[],const char t[],size_t n)
467 {
468   PetscFunctionBegin;
469   strncat(s,t,n);
470   PetscFunctionReturn(0);
471 }
472 
473 #undef __FUNCT__
474 #define __FUNCT__ "PetscStrcmpNoError"
475 /*
476    Only to be used with PetscCheck__FUNCT__()!
477 
478    Will be removed once we eliminate the __FUNCT__ paradigm
479 */
480 void  PetscStrcmpNoError(const char a[],const char b[],PetscBool  *flg)
481 {
482   int c;
483 
484   if (!a && !b)      *flg = PETSC_TRUE;
485   else if (!a || !b) *flg = PETSC_FALSE;
486   else {
487     c = strcmp(a,b);
488     if (c) *flg = PETSC_FALSE;
489     else   *flg = PETSC_TRUE;
490   }
491 }
492 
493 #undef __FUNCT__
494 #define __FUNCT__ "PetscStrcmp"
495 /*@C
496    PetscStrcmp - Compares two strings,
497 
498    Not Collective
499 
500    Input Parameters:
501 +  a - pointer to string first string
502 -  b - pointer to second string
503 
504    Output Parameter:
505 .  flg - PETSC_TRUE if the two strings are equal
506 
507    Level: intermediate
508 
509    Notes:    Not for use in Fortran
510 
511 .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()
512 
513 @*/
514 PetscErrorCode  PetscStrcmp(const char a[],const char b[],PetscBool  *flg)
515 {
516   int c;
517 
518   PetscFunctionBegin;
519   if (!a && !b)      *flg = PETSC_TRUE;
520   else if (!a || !b) *flg = PETSC_FALSE;
521   else {
522     c = strcmp(a,b);
523     if (c) *flg = PETSC_FALSE;
524     else   *flg = PETSC_TRUE;
525   }
526   PetscFunctionReturn(0);
527 }
528 
529 #undef __FUNCT__
530 #define __FUNCT__ "PetscStrgrt"
531 /*@C
532    PetscStrgrt - If first string is greater than the second
533 
534    Not Collective
535 
536    Input Parameters:
537 +  a - pointer to first string
538 -  b - pointer to second string
539 
540    Output Parameter:
541 .  flg - if the first string is greater
542 
543    Notes:
544     Null arguments are ok, a null string is considered smaller than
545     all others
546 
547    Not for use in Fortran
548 
549    Level: intermediate
550 
551 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()
552 
553 @*/
554 PetscErrorCode  PetscStrgrt(const char a[],const char b[],PetscBool  *t)
555 {
556   int c;
557 
558   PetscFunctionBegin;
559   if (!a && !b) *t = PETSC_FALSE;
560   else if (a && !b) *t = PETSC_TRUE;
561   else if (!a && b) *t = PETSC_FALSE;
562   else {
563     c = strcmp(a,b);
564     if (c > 0) *t = PETSC_TRUE;
565     else       *t = PETSC_FALSE;
566   }
567   PetscFunctionReturn(0);
568 }
569 
570 #undef __FUNCT__
571 #define __FUNCT__ "PetscStrcasecmp"
572 /*@C
573    PetscStrcasecmp - Returns true if the two strings are the same
574      except possibly for case.
575 
576    Not Collective
577 
578    Input Parameters:
579 +  a - pointer to first string
580 -  b - pointer to second string
581 
582    Output Parameter:
583 .  flg - if the two strings are the same
584 
585    Notes:
586     Null arguments are ok
587 
588    Not for use in Fortran
589 
590    Level: intermediate
591 
592 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()
593 
594 @*/
595 PetscErrorCode  PetscStrcasecmp(const char a[],const char b[],PetscBool  *t)
596 {
597   int c;
598 
599   PetscFunctionBegin;
600   if (!a && !b) c = 0;
601   else if (!a || !b) c = 1;
602 #if defined(PETSC_HAVE_STRCASECMP)
603   else c = strcasecmp(a,b);
604 #elif defined(PETSC_HAVE_STRICMP)
605   else c = stricmp(a,b);
606 #else
607   else {
608     char           *aa,*bb;
609     PetscErrorCode ierr;
610     ierr = PetscStrallocpy(a,&aa);CHKERRQ(ierr);
611     ierr = PetscStrallocpy(b,&bb);CHKERRQ(ierr);
612     ierr = PetscStrtolower(aa);CHKERRQ(ierr);
613     ierr = PetscStrtolower(bb);CHKERRQ(ierr);
614     ierr = PetscStrcmp(aa,bb,t);CHKERRQ(ierr);
615     ierr = PetscFree(aa);CHKERRQ(ierr);
616     ierr = PetscFree(bb);CHKERRQ(ierr);
617     PetscFunctionReturn(0);
618   }
619 #endif
620   if (!c) *t = PETSC_TRUE;
621   else    *t = PETSC_FALSE;
622   PetscFunctionReturn(0);
623 }
624 
625 
626 
627 #undef __FUNCT__
628 #define __FUNCT__ "PetscStrncmp"
629 /*@C
630    PetscStrncmp - Compares two strings, up to a certain length
631 
632    Not Collective
633 
634    Input Parameters:
635 +  a - pointer to first string
636 .  b - pointer to second string
637 -  n - length to compare up to
638 
639    Output Parameter:
640 .  t - if the two strings are equal
641 
642    Level: intermediate
643 
644    Notes:    Not for use in Fortran
645 
646 .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()
647 
648 @*/
649 PetscErrorCode  PetscStrncmp(const char a[],const char b[],size_t n,PetscBool  *t)
650 {
651   int c;
652 
653   PetscFunctionBegin;
654   c = strncmp(a,b,n);
655   if (!c) *t = PETSC_TRUE;
656   else    *t = PETSC_FALSE;
657   PetscFunctionReturn(0);
658 }
659 
660 #undef __FUNCT__
661 #define __FUNCT__ "PetscStrchr"
662 /*@C
663    PetscStrchr - Locates first occurance of a character in a string
664 
665    Not Collective
666 
667    Input Parameters:
668 +  a - pointer to string
669 -  b - character
670 
671    Output Parameter:
672 .  c - location of occurance, NULL if not found
673 
674    Level: intermediate
675 
676    Notes:    Not for use in Fortran
677 
678 @*/
679 PetscErrorCode  PetscStrchr(const char a[],char b,char *c[])
680 {
681   PetscFunctionBegin;
682   *c = (char*)strchr(a,b);
683   PetscFunctionReturn(0);
684 }
685 
686 #undef __FUNCT__
687 #define __FUNCT__ "PetscStrrchr"
688 /*@C
689    PetscStrrchr - Locates one location past the last occurance of a character in a string,
690       if the character is not found then returns entire string
691 
692    Not Collective
693 
694    Input Parameters:
695 +  a - pointer to string
696 -  b - character
697 
698    Output Parameter:
699 .  tmp - location of occurance, a if not found
700 
701    Level: intermediate
702 
703    Notes:    Not for use in Fortran
704 
705 @*/
706 PetscErrorCode  PetscStrrchr(const char a[],char b,char *tmp[])
707 {
708   PetscFunctionBegin;
709   *tmp = (char*)strrchr(a,b);
710   if (!*tmp) *tmp = (char*)a;
711   else *tmp = *tmp + 1;
712   PetscFunctionReturn(0);
713 }
714 
715 #undef __FUNCT__
716 #define __FUNCT__ "PetscStrtolower"
717 /*@C
718    PetscStrtolower - Converts string to lower case
719 
720    Not Collective
721 
722    Input Parameters:
723 .  a - pointer to string
724 
725    Level: intermediate
726 
727    Notes:    Not for use in Fortran
728 
729 @*/
730 PetscErrorCode  PetscStrtolower(char a[])
731 {
732   PetscFunctionBegin;
733   while (*a) {
734     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
735     a++;
736   }
737   PetscFunctionReturn(0);
738 }
739 
740 #undef __FUNCT__
741 #define __FUNCT__ "PetscStrtoupper"
742 /*@C
743    PetscStrtolower - Converts string to upper case
744 
745    Not Collective
746 
747    Input Parameters:
748 .  a - pointer to string
749 
750    Level: intermediate
751 
752    Notes:    Not for use in Fortran
753 
754 @*/
755 PetscErrorCode  PetscStrtoupper(char a[])
756 {
757   PetscFunctionBegin;
758   while (*a) {
759     if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a';
760     a++;
761   }
762   PetscFunctionReturn(0);
763 }
764 
765 #undef __FUNCT__
766 #define __FUNCT__ "PetscStrendswith"
767 /*@C
768    PetscStrendswith - Determines if a string ends with a certain string
769 
770    Not Collective
771 
772    Input Parameters:
773 +  a - pointer to string
774 -  b - string to endwith
775 
776    Output Parameter:
777 .  flg - PETSC_TRUE or PETSC_FALSE
778 
779    Notes:     Not for use in Fortran
780 
781    Level: intermediate
782 
783 @*/
784 PetscErrorCode  PetscStrendswith(const char a[],const char b[],PetscBool *flg)
785 {
786   char           *test;
787   PetscErrorCode ierr;
788   size_t         na,nb;
789 
790   PetscFunctionBegin;
791   *flg = PETSC_FALSE;
792   ierr = PetscStrrstr(a,b,&test);CHKERRQ(ierr);
793   if (test) {
794     ierr = PetscStrlen(a,&na);CHKERRQ(ierr);
795     ierr = PetscStrlen(b,&nb);CHKERRQ(ierr);
796     if (a+na-nb == test) *flg = PETSC_TRUE;
797   }
798   PetscFunctionReturn(0);
799 }
800 
801 #undef __FUNCT__
802 #define __FUNCT__ "PetscStrbeginswith"
803 /*@C
804    PetscStrbeginswith - Determines if a string begins with a certain string
805 
806    Not Collective
807 
808    Input Parameters:
809 +  a - pointer to string
810 -  b - string to beginwith
811 
812    Output Parameter:
813 .  flg - PETSC_TRUE or PETSC_FALSE
814 
815    Notes:     Not for use in Fortran
816 
817    Level: intermediate
818 
819 @*/
820 PetscErrorCode  PetscStrbeginswith(const char a[],const char b[],PetscBool *flg)
821 {
822   char           *test;
823   PetscErrorCode ierr;
824 
825   PetscFunctionBegin;
826   *flg = PETSC_FALSE;
827   ierr = PetscStrrstr(a,b,&test);CHKERRQ(ierr);
828   if (test && (test == a)) *flg = PETSC_TRUE;
829   PetscFunctionReturn(0);
830 }
831 
832 
833 #undef __FUNCT__
834 #define __FUNCT__ "PetscStrendswithwhich"
835 /*@C
836    PetscStrendswithwhich - Determines if a string ends with one of several possible strings
837 
838    Not Collective
839 
840    Input Parameters:
841 +  a - pointer to string
842 -  bs - strings to endwith (last entry must be null)
843 
844    Output Parameter:
845 .  cnt - the index of the string it ends with or 1+the last possible index
846 
847    Notes:     Not for use in Fortran
848 
849    Level: intermediate
850 
851 @*/
852 PetscErrorCode  PetscStrendswithwhich(const char a[],const char *const *bs,PetscInt *cnt)
853 {
854   PetscBool      flg;
855   PetscErrorCode ierr;
856 
857   PetscFunctionBegin;
858   *cnt = 0;
859   while (bs[*cnt]) {
860     ierr = PetscStrendswith(a,bs[*cnt],&flg);CHKERRQ(ierr);
861     if (flg) PetscFunctionReturn(0);
862     *cnt += 1;
863   }
864   PetscFunctionReturn(0);
865 }
866 
867 #undef __FUNCT__
868 #define __FUNCT__ "PetscStrrstr"
869 /*@C
870    PetscStrrstr - Locates last occurance of string in another string
871 
872    Not Collective
873 
874    Input Parameters:
875 +  a - pointer to string
876 -  b - string to find
877 
878    Output Parameter:
879 .  tmp - location of occurance
880 
881    Notes:     Not for use in Fortran
882 
883    Level: intermediate
884 
885 @*/
886 PetscErrorCode  PetscStrrstr(const char a[],const char b[],char *tmp[])
887 {
888   const char *stmp = a, *ltmp = 0;
889 
890   PetscFunctionBegin;
891   while (stmp) {
892     stmp = (char*)strstr(stmp,b);
893     if (stmp) {ltmp = stmp;stmp++;}
894   }
895   *tmp = (char*)ltmp;
896   PetscFunctionReturn(0);
897 }
898 
899 #undef __FUNCT__
900 #define __FUNCT__ "PetscStrstr"
901 /*@C
902    PetscStrstr - Locates first occurance of string in another string
903 
904    Not Collective
905 
906    Input Parameters:
907 +  haystack - string to search
908 -  needle - string to find
909 
910    Output Parameter:
911 .  tmp - location of occurance, is a NULL if the string is not found
912 
913    Notes: Not for use in Fortran
914 
915    Level: intermediate
916 
917 @*/
918 PetscErrorCode  PetscStrstr(const char haystack[],const char needle[],char *tmp[])
919 {
920   PetscFunctionBegin;
921   *tmp = (char*)strstr(haystack,needle);
922   PetscFunctionReturn(0);
923 }
924 
925 struct _p_PetscToken {char token;char *array;char *current;};
926 
927 #undef __FUNCT__
928 #define __FUNCT__ "PetscTokenFind"
929 /*@C
930    PetscTokenFind - Locates next "token" in a string
931 
932    Not Collective
933 
934    Input Parameters:
935 .  a - pointer to token
936 
937    Output Parameter:
938 .  result - location of occurance, NULL if not found
939 
940    Notes:
941 
942      This version is different from the system version in that
943   it allows you to pass a read-only string into the function.
944 
945      This version also treats all characters etc. inside a double quote "
946    as a single token.
947 
948      For example if the separator character is + and the string is xxxx+y then the first fine will return a pointer to a null terminated xxxx and the
949    second will return a null terminated y
950 
951      If the separator character is + and the string is xxxx then the first and only token found will be a pointer to a null terminated xxxx
952 
953     Not for use in Fortran
954 
955    Level: intermediate
956 
957 
958 .seealso: PetscTokenCreate(), PetscTokenDestroy()
959 @*/
960 PetscErrorCode  PetscTokenFind(PetscToken a,char *result[])
961 {
962   char *ptr = a->current,token;
963 
964   PetscFunctionBegin;
965   *result = a->current;
966   if (ptr && !*ptr) {*result = 0;PetscFunctionReturn(0);}
967   token = a->token;
968   if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
969   while (ptr) {
970     if (*ptr == token) {
971       *ptr++ = 0;
972       while (*ptr == a->token) ptr++;
973       a->current = ptr;
974       break;
975     }
976     if (!*ptr) {
977       a->current = 0;
978       break;
979     }
980     ptr++;
981   }
982   PetscFunctionReturn(0);
983 }
984 
985 #undef __FUNCT__
986 #define __FUNCT__ "PetscTokenCreate"
987 /*@C
988    PetscTokenCreate - Creates a PetscToken used to find tokens in a string
989 
990    Not Collective
991 
992    Input Parameters:
993 +  string - the string to look in
994 -  b - the separator character
995 
996    Output Parameter:
997 .  t- the token object
998 
999    Notes:
1000 
1001      This version is different from the system version in that
1002   it allows you to pass a read-only string into the function.
1003 
1004     Not for use in Fortran
1005 
1006    Level: intermediate
1007 
1008 .seealso: PetscTokenFind(), PetscTokenDestroy()
1009 @*/
1010 PetscErrorCode  PetscTokenCreate(const char a[],const char b,PetscToken *t)
1011 {
1012   PetscErrorCode ierr;
1013 
1014   PetscFunctionBegin;
1015   ierr = PetscNew(t);CHKERRQ(ierr);
1016   ierr = PetscStrallocpy(a,&(*t)->array);CHKERRQ(ierr);
1017 
1018   (*t)->current = (*t)->array;
1019   (*t)->token   = b;
1020   PetscFunctionReturn(0);
1021 }
1022 
1023 #undef __FUNCT__
1024 #define __FUNCT__ "PetscTokenDestroy"
1025 /*@C
1026    PetscTokenDestroy - Destroys a PetscToken
1027 
1028    Not Collective
1029 
1030    Input Parameters:
1031 .  a - pointer to token
1032 
1033    Level: intermediate
1034 
1035    Notes:     Not for use in Fortran
1036 
1037 .seealso: PetscTokenCreate(), PetscTokenFind()
1038 @*/
1039 PetscErrorCode  PetscTokenDestroy(PetscToken *a)
1040 {
1041   PetscErrorCode ierr;
1042 
1043   PetscFunctionBegin;
1044   if (!*a) PetscFunctionReturn(0);
1045   ierr = PetscFree((*a)->array);CHKERRQ(ierr);
1046   ierr = PetscFree(*a);CHKERRQ(ierr);
1047   PetscFunctionReturn(0);
1048 }
1049 
1050 
1051 #undef __FUNCT__
1052 #define __FUNCT__ "PetscGetPetscDir"
1053 /*@C
1054    PetscGetPetscDir - Gets the directory PETSc is installed in
1055 
1056    Not Collective
1057 
1058    Output Parameter:
1059 .  dir - the directory
1060 
1061    Level: developer
1062 
1063    Notes: Not for use in Fortran
1064 
1065 @*/
1066 PetscErrorCode  PetscGetPetscDir(const char *dir[])
1067 {
1068   PetscFunctionBegin;
1069   *dir = PETSC_DIR;
1070   PetscFunctionReturn(0);
1071 }
1072 
1073 #undef __FUNCT__
1074 #define __FUNCT__ "PetscStrreplace"
1075 /*@C
1076    PetscStrreplace - Replaces substrings in string with other substrings
1077 
1078    Not Collective
1079 
1080    Input Parameters:
1081 +   comm - MPI_Comm of processors that are processing the string
1082 .   aa - the string to look in
1083 .   b - the resulting copy of a with replaced strings (b can be the same as a)
1084 -   len - the length of b
1085 
1086    Notes:
1087       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
1088       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values
1089       as well as any environmental variables.
1090 
1091       PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what
1092       PETSc was built with and do not use environmental variables.
1093 
1094       Not for use in Fortran
1095 
1096    Level: intermediate
1097 
1098 @*/
1099 PetscErrorCode  PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
1100 {
1101   PetscErrorCode ierr;
1102   int            i = 0;
1103   size_t         l,l1,l2,l3;
1104   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
1105   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}","${HOSTNAME}",0};
1106   const char     *r[] = {0,0,0,0,0,0,0,0,0};
1107   PetscBool      flag;
1108 
1109   PetscFunctionBegin;
1110   if (!a || !b) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
1111   if (aa == b) {
1112     ierr = PetscStrallocpy(aa,(char**)&a);CHKERRQ(ierr);
1113   }
1114   ierr = PetscMalloc1(len,&work);CHKERRQ(ierr);
1115 
1116   /* get values for replaced variables */
1117   ierr = PetscStrallocpy(PETSC_ARCH,(char**)&r[0]);CHKERRQ(ierr);
1118   ierr = PetscStrallocpy(PETSC_DIR,(char**)&r[1]);CHKERRQ(ierr);
1119   ierr = PetscStrallocpy(PETSC_LIB_DIR,(char**)&r[2]);CHKERRQ(ierr);
1120   ierr = PetscMalloc1(256,&r[3]);CHKERRQ(ierr);
1121   ierr = PetscMalloc1(PETSC_MAX_PATH_LEN,&r[4]);CHKERRQ(ierr);
1122   ierr = PetscMalloc1(PETSC_MAX_PATH_LEN,&r[5]);CHKERRQ(ierr);
1123   ierr = PetscMalloc1(256,&r[6]);CHKERRQ(ierr);
1124   ierr = PetscMalloc1(256,&r[7]);CHKERRQ(ierr);
1125   ierr = PetscGetDisplay((char*)r[3],256);CHKERRQ(ierr);
1126   ierr = PetscGetHomeDirectory((char*)r[4],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
1127   ierr = PetscGetWorkingDirectory((char*)r[5],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
1128   ierr = PetscGetUserName((char*)r[6],256);CHKERRQ(ierr);
1129   ierr = PetscGetHostName((char*)r[7],256);CHKERRQ(ierr);
1130 
1131   /* replace that are in environment */
1132   ierr = PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);CHKERRQ(ierr);
1133   if (flag) {
1134     ierr = PetscFree(r[2]);CHKERRQ(ierr);
1135     ierr = PetscStrallocpy(env,(char**)&r[2]);CHKERRQ(ierr);
1136   }
1137 
1138   /* replace the requested strings */
1139   ierr = PetscStrncpy(b,a,len);CHKERRQ(ierr);
1140   while (s[i]) {
1141     ierr = PetscStrlen(s[i],&l);CHKERRQ(ierr);
1142     ierr = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
1143     while (par) {
1144       *par =  0;
1145       par += l;
1146 
1147       ierr = PetscStrlen(b,&l1);CHKERRQ(ierr);
1148       ierr = PetscStrlen(r[i],&l2);CHKERRQ(ierr);
1149       ierr = PetscStrlen(par,&l3);CHKERRQ(ierr);
1150       if (l1 + l2 + l3 >= len) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
1151       ierr = PetscStrcpy(work,b);CHKERRQ(ierr);
1152       ierr = PetscStrcat(work,r[i]);CHKERRQ(ierr);
1153       ierr = PetscStrcat(work,par);CHKERRQ(ierr);
1154       ierr = PetscStrncpy(b,work,len);CHKERRQ(ierr);
1155       ierr = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
1156     }
1157     i++;
1158   }
1159   i = 0;
1160   while (r[i]) {
1161     tfree = (char*)r[i];
1162     ierr  = PetscFree(tfree);CHKERRQ(ierr);
1163     i++;
1164   }
1165 
1166   /* look for any other ${xxx} strings to replace from environmental variables */
1167   ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
1168   while (par) {
1169     *par  = 0;
1170     par  += 2;
1171     ierr  = PetscStrcpy(work,b);CHKERRQ(ierr);
1172     ierr  = PetscStrstr(par,"}",&epar);CHKERRQ(ierr);
1173     *epar = 0;
1174     epar += 1;
1175     ierr  = PetscOptionsGetenv(comm,par,env,256,&flag);CHKERRQ(ierr);
1176     if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
1177     ierr = PetscStrcat(work,env);CHKERRQ(ierr);
1178     ierr = PetscStrcat(work,epar);CHKERRQ(ierr);
1179     ierr = PetscStrcpy(b,work);CHKERRQ(ierr);
1180     ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
1181   }
1182   ierr = PetscFree(work);CHKERRQ(ierr);
1183   if (aa == b) {
1184     ierr = PetscFree(a);CHKERRQ(ierr);
1185   }
1186   PetscFunctionReturn(0);
1187 }
1188 
1189 #undef __FUNCT__
1190 #define __FUNCT__ "PetscEListFind"
1191 /*@C
1192    PetscEListFind - searches list of strings for given string, using case insensitive matching
1193 
1194    Not Collective
1195 
1196    Input Parameters:
1197 +  n - number of strings in
1198 .  list - list of strings to search
1199 -  str - string to look for, empty string "" accepts default (first entry in list)
1200 
1201    Output Parameters:
1202 +  value - index of matching string (if found)
1203 -  found - boolean indicating whether string was found (can be NULL)
1204 
1205    Notes:
1206    Not for use in Fortran
1207 
1208    Level: advanced
1209 @*/
1210 PetscErrorCode PetscEListFind(PetscInt n,const char *const *list,const char *str,PetscInt *value,PetscBool *found)
1211 {
1212   PetscErrorCode ierr;
1213   PetscBool matched;
1214   PetscInt i;
1215 
1216   PetscFunctionBegin;
1217   if (found) *found = PETSC_FALSE;
1218   for (i=0; i<n; i++) {
1219     ierr = PetscStrcasecmp(str,list[i],&matched);CHKERRQ(ierr);
1220     if (matched || !str[0]) {
1221       if (found) *found = PETSC_TRUE;
1222       *value = i;
1223       break;
1224     }
1225   }
1226   PetscFunctionReturn(0);
1227 }
1228 
1229 #undef __FUNCT__
1230 #define __FUNCT__ "PetscEnumFind"
1231 /*@C
1232    PetscEListFind - searches enum list of strings for given string, using case insensitive matching
1233 
1234    Not Collective
1235 
1236    Input Parameters:
1237 +  enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL
1238 -  str - string to look for
1239 
1240    Output Parameters:
1241 +  value - index of matching string (if found)
1242 -  found - boolean indicating whether string was found (can be NULL)
1243 
1244    Notes:
1245    Not for use in Fortran
1246 
1247    Level: advanced
1248 @*/
1249 PetscErrorCode PetscEnumFind(const char *const *enumlist,const char *str,PetscEnum *value,PetscBool *found)
1250 {
1251   PetscErrorCode ierr;
1252   PetscInt n = 0,evalue;
1253   PetscBool efound;
1254 
1255   PetscFunctionBegin;
1256   while (enumlist[n++]) if (n > 50) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument appears to be wrong or have more than 50 entries");
1257   if (n < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument must have at least two entries: typename and type prefix");
1258   n -= 3; /* drop enum name, prefix, and null termination */
1259   ierr = PetscEListFind(n,enumlist,str,&evalue,&efound);CHKERRQ(ierr);
1260   if (efound) *value = (PetscEnum)evalue;
1261   if (found) *found = efound;
1262   PetscFunctionReturn(0);
1263 }
1264