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