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