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