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