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