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