xref: /petsc/src/sys/utils/str.c (revision 62a5de146ab38f349c1c27a61c00dd9ebdf4766c)
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   Developers Note: Should this be PetscStrlcpy() to reflect its behavior which is like strlcpy() not strncpy()
391 
392 .seealso: PetscStrcpy(), PetscStrcat(), PetscStrlcat()
393 
394 @*/
395 PetscErrorCode  PetscStrncpy(char s[],const char t[],size_t n)
396 {
397   PetscFunctionBegin;
398   if (t && !s) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
399   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");
400   if (t) {
401     if (n > 1) {
402       strncpy(s,t,n-1);
403       s[n-1] = '\0';
404     } else {
405       s[0] = '\0';
406     }
407   } else if (s) s[0] = 0;
408   PetscFunctionReturn(0);
409 }
410 
411 /*@C
412    PetscStrcat - Concatenates a string onto a given string
413 
414    Not Collective
415 
416    Input Parameters:
417 +  s - string to be added to
418 -  t - pointer to string to be added to end
419 
420    Level: intermediate
421 
422    Notes:
423     Not for use in Fortran
424 
425   Concepts: string copy
426 
427 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrlcat()
428 
429 @*/
430 PetscErrorCode  PetscStrcat(char s[],const char t[])
431 {
432   PetscFunctionBegin;
433   if (!t) PetscFunctionReturn(0);
434   strcat(s,t);
435   PetscFunctionReturn(0);
436 }
437 
438 /*@C
439    PetscStrlcat - Concatenates a string onto a given string, up to a given length
440 
441    Not Collective
442 
443    Input Parameters:
444 +  s - pointer to string to be added to end
445 .  t - string to be added to
446 -  n - length of the original allocated string
447 
448    Level: intermediate
449 
450   Notes:
451   Not for use in Fortran
452 
453   Unlike the system call strncat(), the length passed in is the length of the
454   original allocated space, not the length of the left-over space. This is
455   similar to the BSD system call strlcat().
456 
457   Concepts: string copy
458 
459 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
460 
461 @*/
462 PetscErrorCode  PetscStrlcat(char s[],const char t[],size_t n)
463 {
464   size_t         len;
465   PetscErrorCode ierr;
466 
467   PetscFunctionBegin;
468   ierr = PetscStrlen(t,&len);CHKERRQ(ierr);
469   strncat(s,t,n - len);
470   PetscFunctionReturn(0);
471 }
472 
473 /*
474    Only to be used with PetscCheck__FUNCT__()!
475 
476 */
477 void  PetscStrcmpNoError(const char a[],const char b[],PetscBool  *flg)
478 {
479   int c;
480 
481   if (!a && !b)      *flg = PETSC_TRUE;
482   else if (!a || !b) *flg = PETSC_FALSE;
483   else {
484     c = strcmp(a,b);
485     if (c) *flg = PETSC_FALSE;
486     else   *flg = PETSC_TRUE;
487   }
488 }
489 
490 /*@C
491    PetscStrcmp - Compares two strings,
492 
493    Not Collective
494 
495    Input Parameters:
496 +  a - pointer to string first string
497 -  b - pointer to second string
498 
499    Output Parameter:
500 .  flg - PETSC_TRUE if the two strings are equal
501 
502    Level: intermediate
503 
504    Notes:
505     Not for use in Fortran
506 
507 .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()
508 
509 @*/
510 PetscErrorCode  PetscStrcmp(const char a[],const char b[],PetscBool  *flg)
511 {
512   int c;
513 
514   PetscFunctionBegin;
515   if (!a && !b)      *flg = PETSC_TRUE;
516   else if (!a || !b) *flg = PETSC_FALSE;
517   else {
518     c = strcmp(a,b);
519     if (c) *flg = PETSC_FALSE;
520     else   *flg = PETSC_TRUE;
521   }
522   PetscFunctionReturn(0);
523 }
524 
525 /*@C
526    PetscStrgrt - If first string is greater than the second
527 
528    Not Collective
529 
530    Input Parameters:
531 +  a - pointer to first string
532 -  b - pointer to second string
533 
534    Output Parameter:
535 .  flg - if the first string is greater
536 
537    Notes:
538     Null arguments are ok, a null string is considered smaller than
539     all others
540 
541    Not for use in Fortran
542 
543    Level: intermediate
544 
545 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()
546 
547 @*/
548 PetscErrorCode  PetscStrgrt(const char a[],const char b[],PetscBool  *t)
549 {
550   int c;
551 
552   PetscFunctionBegin;
553   if (!a && !b) *t = PETSC_FALSE;
554   else if (a && !b) *t = PETSC_TRUE;
555   else if (!a && b) *t = PETSC_FALSE;
556   else {
557     c = strcmp(a,b);
558     if (c > 0) *t = PETSC_TRUE;
559     else       *t = PETSC_FALSE;
560   }
561   PetscFunctionReturn(0);
562 }
563 
564 /*@C
565    PetscStrcasecmp - Returns true if the two strings are the same
566      except possibly for case.
567 
568    Not Collective
569 
570    Input Parameters:
571 +  a - pointer to first string
572 -  b - pointer to second string
573 
574    Output Parameter:
575 .  flg - if the two strings are the same
576 
577    Notes:
578     Null arguments are ok
579 
580    Not for use in Fortran
581 
582    Level: intermediate
583 
584 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()
585 
586 @*/
587 PetscErrorCode  PetscStrcasecmp(const char a[],const char b[],PetscBool  *t)
588 {
589   int c;
590 
591   PetscFunctionBegin;
592   if (!a && !b) c = 0;
593   else if (!a || !b) c = 1;
594 #if defined(PETSC_HAVE_STRCASECMP)
595   else c = strcasecmp(a,b);
596 #elif defined(PETSC_HAVE_STRICMP)
597   else c = stricmp(a,b);
598 #else
599   else {
600     char           *aa,*bb;
601     PetscErrorCode ierr;
602     ierr = PetscStrallocpy(a,&aa);CHKERRQ(ierr);
603     ierr = PetscStrallocpy(b,&bb);CHKERRQ(ierr);
604     ierr = PetscStrtolower(aa);CHKERRQ(ierr);
605     ierr = PetscStrtolower(bb);CHKERRQ(ierr);
606     ierr = PetscStrcmp(aa,bb,t);CHKERRQ(ierr);
607     ierr = PetscFree(aa);CHKERRQ(ierr);
608     ierr = PetscFree(bb);CHKERRQ(ierr);
609     PetscFunctionReturn(0);
610   }
611 #endif
612   if (!c) *t = PETSC_TRUE;
613   else    *t = PETSC_FALSE;
614   PetscFunctionReturn(0);
615 }
616 
617 
618 
619 /*@C
620    PetscStrncmp - Compares two strings, up to a certain length
621 
622    Not Collective
623 
624    Input Parameters:
625 +  a - pointer to first string
626 .  b - pointer to second string
627 -  n - length to compare up to
628 
629    Output Parameter:
630 .  t - if the two strings are equal
631 
632    Level: intermediate
633 
634    Notes:
635     Not for use in Fortran
636 
637 .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()
638 
639 @*/
640 PetscErrorCode  PetscStrncmp(const char a[],const char b[],size_t n,PetscBool  *t)
641 {
642   int c;
643 
644   PetscFunctionBegin;
645   c = strncmp(a,b,n);
646   if (!c) *t = PETSC_TRUE;
647   else    *t = PETSC_FALSE;
648   PetscFunctionReturn(0);
649 }
650 
651 /*@C
652    PetscStrchr - Locates first occurance of a character in a string
653 
654    Not Collective
655 
656    Input Parameters:
657 +  a - pointer to string
658 -  b - character
659 
660    Output Parameter:
661 .  c - location of occurance, NULL if not found
662 
663    Level: intermediate
664 
665    Notes:
666     Not for use in Fortran
667 
668 @*/
669 PetscErrorCode  PetscStrchr(const char a[],char b,char *c[])
670 {
671   PetscFunctionBegin;
672   *c = (char*)strchr(a,b);
673   PetscFunctionReturn(0);
674 }
675 
676 /*@C
677    PetscStrrchr - Locates one location past the last occurance of a character in a string,
678       if the character is not found then returns entire string
679 
680    Not Collective
681 
682    Input Parameters:
683 +  a - pointer to string
684 -  b - character
685 
686    Output Parameter:
687 .  tmp - location of occurance, a if not found
688 
689    Level: intermediate
690 
691    Notes:
692     Not for use in Fortran
693 
694 @*/
695 PetscErrorCode  PetscStrrchr(const char a[],char b,char *tmp[])
696 {
697   PetscFunctionBegin;
698   *tmp = (char*)strrchr(a,b);
699   if (!*tmp) *tmp = (char*)a;
700   else *tmp = *tmp + 1;
701   PetscFunctionReturn(0);
702 }
703 
704 /*@C
705    PetscStrtolower - Converts string to lower case
706 
707    Not Collective
708 
709    Input Parameters:
710 .  a - pointer to string
711 
712    Level: intermediate
713 
714    Notes:
715     Not for use in Fortran
716 
717 @*/
718 PetscErrorCode  PetscStrtolower(char a[])
719 {
720   PetscFunctionBegin;
721   while (*a) {
722     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
723     a++;
724   }
725   PetscFunctionReturn(0);
726 }
727 
728 /*@C
729    PetscStrtoupper - Converts string to upper case
730 
731    Not Collective
732 
733    Input Parameters:
734 .  a - pointer to string
735 
736    Level: intermediate
737 
738    Notes:
739     Not for use in Fortran
740 
741 @*/
742 PetscErrorCode  PetscStrtoupper(char a[])
743 {
744   PetscFunctionBegin;
745   while (*a) {
746     if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a';
747     a++;
748   }
749   PetscFunctionReturn(0);
750 }
751 
752 /*@C
753    PetscStrendswith - Determines if a string ends with a certain string
754 
755    Not Collective
756 
757    Input Parameters:
758 +  a - pointer to string
759 -  b - string to endwith
760 
761    Output Parameter:
762 .  flg - PETSC_TRUE or PETSC_FALSE
763 
764    Notes:
765     Not for use in Fortran
766 
767    Level: intermediate
768 
769 @*/
770 PetscErrorCode  PetscStrendswith(const char a[],const char b[],PetscBool *flg)
771 {
772   char           *test;
773   PetscErrorCode ierr;
774   size_t         na,nb;
775 
776   PetscFunctionBegin;
777   *flg = PETSC_FALSE;
778   ierr = PetscStrrstr(a,b,&test);CHKERRQ(ierr);
779   if (test) {
780     ierr = PetscStrlen(a,&na);CHKERRQ(ierr);
781     ierr = PetscStrlen(b,&nb);CHKERRQ(ierr);
782     if (a+na-nb == test) *flg = PETSC_TRUE;
783   }
784   PetscFunctionReturn(0);
785 }
786 
787 /*@C
788    PetscStrbeginswith - Determines if a string begins with a certain string
789 
790    Not Collective
791 
792    Input Parameters:
793 +  a - pointer to string
794 -  b - string to begin with
795 
796    Output Parameter:
797 .  flg - PETSC_TRUE or PETSC_FALSE
798 
799    Notes:
800     Not for use in Fortran
801 
802    Level: intermediate
803 
804 .seealso: PetscStrendswithwhich(), PetscStrendswith(), PetscStrtoupper, PetscStrtolower(), PetscStrrchr(), PetscStrchr(),
805           PetscStrncmp(), PetscStrlen(), PetscStrncmp(), PetscStrcmp()
806 
807 @*/
808 PetscErrorCode  PetscStrbeginswith(const char a[],const char b[],PetscBool *flg)
809 {
810   char           *test;
811   PetscErrorCode ierr;
812 
813   PetscFunctionBegin;
814   *flg = PETSC_FALSE;
815   ierr = PetscStrrstr(a,b,&test);CHKERRQ(ierr);
816   if (test && (test == a)) *flg = PETSC_TRUE;
817   PetscFunctionReturn(0);
818 }
819 
820 
821 /*@C
822    PetscStrendswithwhich - Determines if a string ends with one of several possible strings
823 
824    Not Collective
825 
826    Input Parameters:
827 +  a - pointer to string
828 -  bs - strings to endwith (last entry must be null)
829 
830    Output Parameter:
831 .  cnt - the index of the string it ends with or 1+the last possible index
832 
833    Notes:
834     Not for use in Fortran
835 
836    Level: intermediate
837 
838 @*/
839 PetscErrorCode  PetscStrendswithwhich(const char a[],const char *const *bs,PetscInt *cnt)
840 {
841   PetscBool      flg;
842   PetscErrorCode ierr;
843 
844   PetscFunctionBegin;
845   *cnt = 0;
846   while (bs[*cnt]) {
847     ierr = PetscStrendswith(a,bs[*cnt],&flg);CHKERRQ(ierr);
848     if (flg) PetscFunctionReturn(0);
849     *cnt += 1;
850   }
851   PetscFunctionReturn(0);
852 }
853 
854 /*@C
855    PetscStrrstr - Locates last occurance of string in another string
856 
857    Not Collective
858 
859    Input Parameters:
860 +  a - pointer to string
861 -  b - string to find
862 
863    Output Parameter:
864 .  tmp - location of occurance
865 
866    Notes:
867     Not for use in Fortran
868 
869    Level: intermediate
870 
871 @*/
872 PetscErrorCode  PetscStrrstr(const char a[],const char b[],char *tmp[])
873 {
874   const char *stmp = a, *ltmp = 0;
875 
876   PetscFunctionBegin;
877   while (stmp) {
878     stmp = (char*)strstr(stmp,b);
879     if (stmp) {ltmp = stmp;stmp++;}
880   }
881   *tmp = (char*)ltmp;
882   PetscFunctionReturn(0);
883 }
884 
885 /*@C
886    PetscStrstr - Locates first occurance of string in another string
887 
888    Not Collective
889 
890    Input Parameters:
891 +  haystack - string to search
892 -  needle - string to find
893 
894    Output Parameter:
895 .  tmp - location of occurance, is a NULL if the string is not found
896 
897    Notes:
898     Not for use in Fortran
899 
900    Level: intermediate
901 
902 @*/
903 PetscErrorCode  PetscStrstr(const char haystack[],const char needle[],char *tmp[])
904 {
905   PetscFunctionBegin;
906   *tmp = (char*)strstr(haystack,needle);
907   PetscFunctionReturn(0);
908 }
909 
910 struct _p_PetscToken {char token;char *array;char *current;};
911 
912 /*@C
913    PetscTokenFind - Locates next "token" in a string
914 
915    Not Collective
916 
917    Input Parameters:
918 .  a - pointer to token
919 
920    Output Parameter:
921 .  result - location of occurance, NULL if not found
922 
923    Notes:
924 
925      This version is different from the system version in that
926   it allows you to pass a read-only string into the function.
927 
928      This version also treats all characters etc. inside a double quote "
929    as a single token.
930 
931      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
932    second will return a null terminated y
933 
934      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
935 
936     Not for use in Fortran
937 
938    Level: intermediate
939 
940 
941 .seealso: PetscTokenCreate(), PetscTokenDestroy()
942 @*/
943 PetscErrorCode  PetscTokenFind(PetscToken a,char *result[])
944 {
945   char *ptr = a->current,token;
946 
947   PetscFunctionBegin;
948   *result = a->current;
949   if (ptr && !*ptr) {*result = 0;PetscFunctionReturn(0);}
950   token = a->token;
951   if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
952   while (ptr) {
953     if (*ptr == token) {
954       *ptr++ = 0;
955       while (*ptr == a->token) ptr++;
956       a->current = ptr;
957       break;
958     }
959     if (!*ptr) {
960       a->current = 0;
961       break;
962     }
963     ptr++;
964   }
965   PetscFunctionReturn(0);
966 }
967 
968 /*@C
969    PetscTokenCreate - Creates a PetscToken used to find tokens in a string
970 
971    Not Collective
972 
973    Input Parameters:
974 +  string - the string to look in
975 -  b - the separator character
976 
977    Output Parameter:
978 .  t- the token object
979 
980    Notes:
981 
982      This version is different from the system version in that
983   it allows you to pass a read-only string into the function.
984 
985     Not for use in Fortran
986 
987    Level: intermediate
988 
989 .seealso: PetscTokenFind(), PetscTokenDestroy()
990 @*/
991 PetscErrorCode  PetscTokenCreate(const char a[],const char b,PetscToken *t)
992 {
993   PetscErrorCode ierr;
994 
995   PetscFunctionBegin;
996   ierr = PetscNew(t);CHKERRQ(ierr);
997   ierr = PetscStrallocpy(a,&(*t)->array);CHKERRQ(ierr);
998 
999   (*t)->current = (*t)->array;
1000   (*t)->token   = b;
1001   PetscFunctionReturn(0);
1002 }
1003 
1004 /*@C
1005    PetscTokenDestroy - Destroys a PetscToken
1006 
1007    Not Collective
1008 
1009    Input Parameters:
1010 .  a - pointer to token
1011 
1012    Level: intermediate
1013 
1014    Notes:
1015     Not for use in Fortran
1016 
1017 .seealso: PetscTokenCreate(), PetscTokenFind()
1018 @*/
1019 PetscErrorCode  PetscTokenDestroy(PetscToken *a)
1020 {
1021   PetscErrorCode ierr;
1022 
1023   PetscFunctionBegin;
1024   if (!*a) PetscFunctionReturn(0);
1025   ierr = PetscFree((*a)->array);CHKERRQ(ierr);
1026   ierr = PetscFree(*a);CHKERRQ(ierr);
1027   PetscFunctionReturn(0);
1028 }
1029 
1030 /*@C
1031    PetscStrInList - search string in character-delimited list
1032 
1033    Not Collective
1034 
1035    Input Parameters:
1036 +  str - the string to look for
1037 .  list - the list to search in
1038 -  sep - the separator character
1039 
1040    Output Parameter:
1041 .  found - whether str is in list
1042 
1043    Level: intermediate
1044 
1045    Notes:
1046     Not for use in Fortran
1047 
1048 .seealso: PetscTokenCreate(), PetscTokenFind(), PetscStrcmp()
1049 @*/
1050 PetscErrorCode PetscStrInList(const char str[],const char list[],char sep,PetscBool *found)
1051 {
1052   PetscToken     token;
1053   char           *item;
1054   PetscErrorCode ierr;
1055 
1056   PetscFunctionBegin;
1057   *found = PETSC_FALSE;
1058   ierr = PetscTokenCreate(list,sep,&token);CHKERRQ(ierr);
1059   ierr = PetscTokenFind(token,&item);CHKERRQ(ierr);
1060   while (item) {
1061     ierr = PetscStrcmp(str,item,found);CHKERRQ(ierr);
1062     if (*found) break;
1063     ierr = PetscTokenFind(token,&item);CHKERRQ(ierr);
1064   }
1065   ierr = PetscTokenDestroy(&token);CHKERRQ(ierr);
1066   PetscFunctionReturn(0);
1067 }
1068 
1069 /*@C
1070    PetscGetPetscDir - Gets the directory PETSc is installed in
1071 
1072    Not Collective
1073 
1074    Output Parameter:
1075 .  dir - the directory
1076 
1077    Level: developer
1078 
1079    Notes:
1080     Not for use in Fortran
1081 
1082 @*/
1083 PetscErrorCode  PetscGetPetscDir(const char *dir[])
1084 {
1085   PetscFunctionBegin;
1086   *dir = PETSC_DIR;
1087   PetscFunctionReturn(0);
1088 }
1089 
1090 /*@C
1091    PetscStrreplace - Replaces substrings in string with other substrings
1092 
1093    Not Collective
1094 
1095    Input Parameters:
1096 +   comm - MPI_Comm of processors that are processing the string
1097 .   aa - the string to look in
1098 .   b - the resulting copy of a with replaced strings (b can be the same as a)
1099 -   len - the length of b
1100 
1101    Notes:
1102       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
1103       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values
1104       as well as any environmental variables.
1105 
1106       PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what
1107       PETSc was built with and do not use environmental variables.
1108 
1109       Not for use in Fortran
1110 
1111    Level: intermediate
1112 
1113 @*/
1114 PetscErrorCode  PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
1115 {
1116   PetscErrorCode ierr;
1117   int            i = 0;
1118   size_t         l,l1,l2,l3;
1119   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
1120   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}","${HOSTNAME}",0};
1121   char           *r[] = {0,0,0,0,0,0,0,0,0};
1122   PetscBool      flag;
1123 
1124   PetscFunctionBegin;
1125   if (!a || !b) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
1126   if (aa == b) {
1127     ierr = PetscStrallocpy(aa,(char**)&a);CHKERRQ(ierr);
1128   }
1129   ierr = PetscMalloc1(len,&work);CHKERRQ(ierr);
1130 
1131   /* get values for replaced variables */
1132   ierr = PetscStrallocpy(PETSC_ARCH,&r[0]);CHKERRQ(ierr);
1133   ierr = PetscStrallocpy(PETSC_DIR,&r[1]);CHKERRQ(ierr);
1134   ierr = PetscStrallocpy(PETSC_LIB_DIR,&r[2]);CHKERRQ(ierr);
1135   ierr = PetscMalloc1(256,&r[3]);CHKERRQ(ierr);
1136   ierr = PetscMalloc1(PETSC_MAX_PATH_LEN,&r[4]);CHKERRQ(ierr);
1137   ierr = PetscMalloc1(PETSC_MAX_PATH_LEN,&r[5]);CHKERRQ(ierr);
1138   ierr = PetscMalloc1(256,&r[6]);CHKERRQ(ierr);
1139   ierr = PetscMalloc1(256,&r[7]);CHKERRQ(ierr);
1140   ierr = PetscGetDisplay(r[3],256);CHKERRQ(ierr);
1141   ierr = PetscGetHomeDirectory(r[4],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
1142   ierr = PetscGetWorkingDirectory(r[5],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
1143   ierr = PetscGetUserName(r[6],256);CHKERRQ(ierr);
1144   ierr = PetscGetHostName(r[7],256);CHKERRQ(ierr);
1145 
1146   /* replace that are in environment */
1147   ierr = PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);CHKERRQ(ierr);
1148   if (flag) {
1149     ierr = PetscFree(r[2]);CHKERRQ(ierr);
1150     ierr = PetscStrallocpy(env,&r[2]);CHKERRQ(ierr);
1151   }
1152 
1153   /* replace the requested strings */
1154   ierr = PetscStrncpy(b,a,len);CHKERRQ(ierr);
1155   while (s[i]) {
1156     ierr = PetscStrlen(s[i],&l);CHKERRQ(ierr);
1157     ierr = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
1158     while (par) {
1159       *par =  0;
1160       par += l;
1161 
1162       ierr = PetscStrlen(b,&l1);CHKERRQ(ierr);
1163       ierr = PetscStrlen(r[i],&l2);CHKERRQ(ierr);
1164       ierr = PetscStrlen(par,&l3);CHKERRQ(ierr);
1165       if (l1 + l2 + l3 >= len) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
1166       ierr = PetscStrcpy(work,b);CHKERRQ(ierr);
1167       ierr = PetscStrcat(work,r[i]);CHKERRQ(ierr);
1168       ierr = PetscStrcat(work,par);CHKERRQ(ierr);
1169       ierr = PetscStrncpy(b,work,len);CHKERRQ(ierr);
1170       ierr = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
1171     }
1172     i++;
1173   }
1174   i = 0;
1175   while (r[i]) {
1176     tfree = (char*)r[i];
1177     ierr  = PetscFree(tfree);CHKERRQ(ierr);
1178     i++;
1179   }
1180 
1181   /* look for any other ${xxx} strings to replace from environmental variables */
1182   ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
1183   while (par) {
1184     *par  = 0;
1185     par  += 2;
1186     ierr  = PetscStrcpy(work,b);CHKERRQ(ierr);
1187     ierr  = PetscStrstr(par,"}",&epar);CHKERRQ(ierr);
1188     *epar = 0;
1189     epar += 1;
1190     ierr  = PetscOptionsGetenv(comm,par,env,256,&flag);CHKERRQ(ierr);
1191     if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
1192     ierr = PetscStrcat(work,env);CHKERRQ(ierr);
1193     ierr = PetscStrcat(work,epar);CHKERRQ(ierr);
1194     ierr = PetscStrcpy(b,work);CHKERRQ(ierr);
1195     ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
1196   }
1197   ierr = PetscFree(work);CHKERRQ(ierr);
1198   if (aa == b) {
1199     ierr = PetscFree(a);CHKERRQ(ierr);
1200   }
1201   PetscFunctionReturn(0);
1202 }
1203 
1204 /*@C
1205    PetscEListFind - searches list of strings for given string, using case insensitive matching
1206 
1207    Not Collective
1208 
1209    Input Parameters:
1210 +  n - number of strings in
1211 .  list - list of strings to search
1212 -  str - string to look for, empty string "" accepts default (first entry in list)
1213 
1214    Output Parameters:
1215 +  value - index of matching string (if found)
1216 -  found - boolean indicating whether string was found (can be NULL)
1217 
1218    Notes:
1219    Not for use in Fortran
1220 
1221    Level: advanced
1222 @*/
1223 PetscErrorCode PetscEListFind(PetscInt n,const char *const *list,const char *str,PetscInt *value,PetscBool *found)
1224 {
1225   PetscErrorCode ierr;
1226   PetscBool matched;
1227   PetscInt i;
1228 
1229   PetscFunctionBegin;
1230   if (found) *found = PETSC_FALSE;
1231   for (i=0; i<n; i++) {
1232     ierr = PetscStrcasecmp(str,list[i],&matched);CHKERRQ(ierr);
1233     if (matched || !str[0]) {
1234       if (found) *found = PETSC_TRUE;
1235       *value = i;
1236       break;
1237     }
1238   }
1239   PetscFunctionReturn(0);
1240 }
1241 
1242 /*@C
1243    PetscEnumFind - searches enum list of strings for given string, using case insensitive matching
1244 
1245    Not Collective
1246 
1247    Input Parameters:
1248 +  enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL
1249 -  str - string to look for
1250 
1251    Output Parameters:
1252 +  value - index of matching string (if found)
1253 -  found - boolean indicating whether string was found (can be NULL)
1254 
1255    Notes:
1256    Not for use in Fortran
1257 
1258    Level: advanced
1259 @*/
1260 PetscErrorCode PetscEnumFind(const char *const *enumlist,const char *str,PetscEnum *value,PetscBool *found)
1261 {
1262   PetscErrorCode ierr;
1263   PetscInt n = 0,evalue;
1264   PetscBool efound;
1265 
1266   PetscFunctionBegin;
1267   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");
1268   if (n < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument must have at least two entries: typename and type prefix");
1269   n -= 3; /* drop enum name, prefix, and null termination */
1270   ierr = PetscEListFind(n,enumlist,str,&evalue,&efound);CHKERRQ(ierr);
1271   if (efound) *value = (PetscEnum)evalue;
1272   if (found) *found = efound;
1273   PetscFunctionReturn(0);
1274 }
1275