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