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