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