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