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