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