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