xref: /petsc/src/sys/utils/str.c (revision d67fe73b814e98b751355dda2eadc2214e19abb5)
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>
11 #endif
12 #if defined(PETSC_HAVE_STRINGS_H)
13 #include <strings.h>
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 - seperator 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   for (i=0; i<n; i++) {
52     if (s[i] != sp) break;
53   }
54   for (;i<n+1; i++) {
55     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
56     else if (s[i] != sp) {flg = PETSC_FALSE;}
57   }
58   (*args) = (char **) malloc(((*argc)+1)*sizeof(char**)); if (!*args) return PETSC_ERR_MEM;
59   lens    = (int*) malloc((*argc)*sizeof(int)); if (!lens) return PETSC_ERR_MEM;
60   for (i=0; i<*argc; i++) lens[i] = 0;
61 
62   *argc = 0;
63   for (i=0; i<n; i++) {
64     if (s[i] != sp) break;
65   }
66   for (;i<n+1; i++) {
67     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
68     else if (s[i] != sp) {lens[*argc]++;flg = PETSC_FALSE;}
69   }
70 
71   for (i=0; i<*argc; i++) {
72     (*args)[i] = (char*) malloc((lens[i]+1)*sizeof(char)); if (!(*args)[i]) return PETSC_ERR_MEM;
73   }
74   (*args)[*argc] = 0;
75 
76   *argc = 0;
77   for (i=0; i<n; i++) {
78     if (s[i] != sp) break;
79   }
80   for (;i<n+1; i++) {
81     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*args)[*argc][cnt++] = 0; (*argc)++; cnt = 0;}
82     else if (s[i] != sp && s[i] != 0) {(*args)[*argc][cnt++] = s[i]; flg = PETSC_FALSE;}
83   }
84   return 0;
85 }
86 
87 #undef __FUNCT__
88 #define __FUNCT__ "PetscStrToArrayDestroy"
89 /*@C
90    PetscStrToArrayDestroy - Frees array created with PetscStrToArray().
91 
92    Not Collective
93 
94    Output Parameters:
95 +  argc - the number of arguments
96 -  args - the array of arguments
97 
98    Level: intermediate
99 
100    Concepts: command line arguments
101 
102    Notes: This may be called before PetscInitialize() or after PetscFinalize()
103 
104    Not for use in Fortran
105 
106 .seealso: PetscStrToArray()
107 
108 @*/
109 PetscErrorCode  PetscStrToArrayDestroy(int argc,char **args)
110 {
111   PetscInt i;
112 
113   for (i=0; i<argc; i++) {
114     free(args[i]);
115   }
116   free(args);
117   return 0;
118 }
119 
120 #undef __FUNCT__
121 #define __FUNCT__ "PetscStrlen"
122 /*@C
123    PetscStrlen - Gets length of a string
124 
125    Not Collective
126 
127    Input Parameters:
128 .  s - pointer to string
129 
130    Output Parameter:
131 .  len - length in bytes
132 
133    Level: intermediate
134 
135    Note:
136    This routine is analogous to strlen().
137 
138    Null string returns a length of zero
139 
140    Not for use in Fortran
141 
142   Concepts: string length
143 
144 @*/
145 PetscErrorCode  PetscStrlen(const char s[],size_t *len)
146 {
147   PetscFunctionBegin;
148   if (!s) {
149     *len = 0;
150   } else {
151     *len = strlen(s);
152   }
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 = PetscMalloc((1+len)*sizeof(char),&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 = PetscMalloc((n+1)*sizeof(char**),t);CHKERRQ(ierr);
226   for (i=0; i<n; i++) {
227     ierr = PetscStrallocpy(list[i],(*t)+i);CHKERRQ(ierr);
228   }
229   (*t)[n] = PETSC_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   Concepts: string copy
322 
323 .seealso: PetscStrcpy(), PetscStrcat(), PetscStrncat()
324 
325 @*/
326 PetscErrorCode  PetscStrncpy(char s[],const char t[],size_t n)
327 {
328   PetscFunctionBegin;
329   if (t && !s) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
330   if (t) {strncpy(s,t,n);}
331   else if (s) {s[0] = 0;}
332   PetscFunctionReturn(0);
333 }
334 
335 #undef __FUNCT__
336 #define __FUNCT__ "PetscStrcat"
337 /*@C
338    PetscStrcat - Concatenates a string onto a given string
339 
340    Not Collective
341 
342    Input Parameters:
343 +  s - string to be added to
344 -  t - pointer to string to be added to end
345 
346    Level: intermediate
347 
348    Notes: Not for use in Fortran
349 
350   Concepts: string copy
351 
352 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
353 
354 @*/
355 PetscErrorCode  PetscStrcat(char s[],const char t[])
356 {
357   PetscFunctionBegin;
358   if (!t) PetscFunctionReturn(0);
359   strcat(s,t);
360   PetscFunctionReturn(0);
361 }
362 
363 #undef __FUNCT__
364 #define __FUNCT__ "PetscStrncat"
365 /*@C
366    PetscStrncat - Concatenates a string onto a given string, up to a given length
367 
368    Not Collective
369 
370    Input Parameters:
371 +  s - pointer to string to be added to end
372 .  t - string to be added to
373 .  n - maximum length to copy
374 
375    Level: intermediate
376 
377   Notes:    Not for use in Fortran
378 
379   Concepts: string copy
380 
381 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
382 
383 @*/
384 PetscErrorCode  PetscStrncat(char s[],const char t[],size_t n)
385 {
386   PetscFunctionBegin;
387   strncat(s,t,n);
388   PetscFunctionReturn(0);
389 }
390 
391 #undef __FUNCT__
392 #define __FUNCT__ "PetscStrcmp"
393 /*@C
394    PetscStrcmp - Compares two strings,
395 
396    Not Collective
397 
398    Input Parameters:
399 +  a - pointer to string first string
400 -  b - pointer to second string
401 
402    Output Parameter:
403 .  flg - PETSC_TRUE if the two strings are equal
404 
405    Level: intermediate
406 
407    Notes:    Not for use in Fortran
408 
409 .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()
410 
411 @*/
412 PetscErrorCode  PetscStrcmp(const char a[],const char b[],PetscBool  *flg)
413 {
414   int c;
415 
416   PetscFunctionBegin;
417   if (!a && !b) {
418     *flg = PETSC_TRUE;
419   } else if (!a || !b) {
420     *flg = PETSC_FALSE;
421   } else {
422     c = strcmp(a,b);
423     if (c) *flg = PETSC_FALSE;
424     else   *flg = PETSC_TRUE;
425   }
426   PetscFunctionReturn(0);
427 }
428 
429 #undef __FUNCT__
430 #define __FUNCT__ "PetscStrgrt"
431 /*@C
432    PetscStrgrt - If first string is greater than the second
433 
434    Not Collective
435 
436    Input Parameters:
437 +  a - pointer to first string
438 -  b - pointer to second string
439 
440    Output Parameter:
441 .  flg - if the first string is greater
442 
443    Notes:
444     Null arguments are ok, a null string is considered smaller than
445     all others
446 
447    Not for use in Fortran
448 
449    Level: intermediate
450 
451 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()
452 
453 @*/
454 PetscErrorCode  PetscStrgrt(const char a[],const char b[],PetscBool  *t)
455 {
456   int c;
457 
458   PetscFunctionBegin;
459   if (!a && !b) {
460     *t = PETSC_FALSE;
461   } else if (a && !b) {
462     *t = PETSC_TRUE;
463   } else if (!a && b) {
464     *t = PETSC_FALSE;
465   } else {
466     c = strcmp(a,b);
467     if (c > 0) *t = PETSC_TRUE;
468     else       *t = PETSC_FALSE;
469   }
470   PetscFunctionReturn(0);
471 }
472 
473 #undef __FUNCT__
474 #define __FUNCT__ "PetscStrcasecmp"
475 /*@C
476    PetscStrcasecmp - Returns true if the two strings are the same
477      except possibly for case.
478 
479    Not Collective
480 
481    Input Parameters:
482 +  a - pointer to first string
483 -  b - pointer to second string
484 
485    Output Parameter:
486 .  flg - if the two strings are the same
487 
488    Notes:
489     Null arguments are ok
490 
491    Not for use in Fortran
492 
493    Level: intermediate
494 
495 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()
496 
497 @*/
498 PetscErrorCode  PetscStrcasecmp(const char a[],const char b[],PetscBool  *t)
499 {
500   int c;
501 
502   PetscFunctionBegin;
503   if (!a && !b) c = 0;
504   else if (!a || !b) c = 1;
505 #if defined(PETSC_HAVE_STRCASECMP)
506   else c = strcasecmp(a,b);
507 #elif defined(PETSC_HAVE_STRICMP)
508   else c = stricmp(a,b);
509 #else
510   else {
511     char           *aa,*bb;
512     PetscErrorCode ierr;
513     ierr = PetscStrallocpy(a,&aa);CHKERRQ(ierr);
514     ierr = PetscStrallocpy(b,&bb);CHKERRQ(ierr);
515     ierr = PetscStrtolower(aa);CHKERRQ(ierr);
516     ierr = PetscStrtolower(bb);CHKERRQ(ierr);
517     ierr = PetscStrcmp(aa,bb,t);CHKERRQ(ierr);
518     ierr = PetscFree(aa);CHKERRQ(ierr);
519     ierr = PetscFree(bb);CHKERRQ(ierr);
520     PetscFunctionReturn(0);
521   }
522 #endif
523   if (!c) *t = PETSC_TRUE;
524   else    *t = PETSC_FALSE;
525   PetscFunctionReturn(0);
526 }
527 
528 
529 
530 #undef __FUNCT__
531 #define __FUNCT__ "PetscStrncmp"
532 /*@C
533    PetscStrncmp - Compares two strings, up to a certain length
534 
535    Not Collective
536 
537    Input Parameters:
538 +  a - pointer to first string
539 .  b - pointer to second string
540 -  n - length to compare up to
541 
542    Output Parameter:
543 .  t - if the two strings are equal
544 
545    Level: intermediate
546 
547    Notes:    Not for use in Fortran
548 
549 .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()
550 
551 @*/
552 PetscErrorCode  PetscStrncmp(const char a[],const char b[],size_t n,PetscBool  *t)
553 {
554   int c;
555 
556   PetscFunctionBegin;
557   c = strncmp(a,b,n);
558   if (!c) *t = PETSC_TRUE;
559   else    *t = PETSC_FALSE;
560   PetscFunctionReturn(0);
561 }
562 
563 #undef __FUNCT__
564 #define __FUNCT__ "PetscStrchr"
565 /*@C
566    PetscStrchr - Locates first occurance of a character in a string
567 
568    Not Collective
569 
570    Input Parameters:
571 +  a - pointer to string
572 -  b - character
573 
574    Output Parameter:
575 .  c - location of occurance, PETSC_NULL if not found
576 
577    Level: intermediate
578 
579    Notes:    Not for use in Fortran
580 
581 @*/
582 PetscErrorCode  PetscStrchr(const char a[],char b,char *c[])
583 {
584   PetscFunctionBegin;
585   *c = (char *)strchr(a,b);
586   PetscFunctionReturn(0);
587 }
588 
589 #undef __FUNCT__
590 #define __FUNCT__ "PetscStrrchr"
591 /*@C
592    PetscStrrchr - Locates one location past the last occurance of a character in a string,
593       if the character is not found then returns entire string
594 
595    Not Collective
596 
597    Input Parameters:
598 +  a - pointer to string
599 -  b - character
600 
601    Output Parameter:
602 .  tmp - location of occurance, a if not found
603 
604    Level: intermediate
605 
606    Notes:    Not for use in Fortran
607 
608 @*/
609 PetscErrorCode  PetscStrrchr(const char a[],char b,char *tmp[])
610 {
611   PetscFunctionBegin;
612   *tmp = (char *)strrchr(a,b);
613   if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
614   PetscFunctionReturn(0);
615 }
616 
617 #undef __FUNCT__
618 #define __FUNCT__ "PetscStrtolower"
619 /*@C
620    PetscStrtolower - Converts string to lower case
621 
622    Not Collective
623 
624    Input Parameters:
625 .  a - pointer to string
626 
627    Level: intermediate
628 
629    Notes:    Not for use in Fortran
630 
631 @*/
632 PetscErrorCode  PetscStrtolower(char a[])
633 {
634   PetscFunctionBegin;
635   while (*a) {
636     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
637     a++;
638   }
639   PetscFunctionReturn(0);
640 }
641 
642 #undef __FUNCT__
643 #define __FUNCT__ "PetscStrendswith"
644 /*@C
645    PetscStrendswith - Determines if a string ends with a certain string
646 
647    Not Collective
648 
649    Input Parameters:
650 +  a - pointer to string
651 -  b - string to endwith
652 
653    Output Parameter:
654 .  flg - PETSC_TRUE or PETSC_FALSE
655 
656    Notes:     Not for use in Fortran
657 
658    Level: intermediate
659 
660 @*/
661 PetscErrorCode  PetscStrendswith(const char a[],const char b[],PetscBool *flg)
662 {
663   char           *test;
664   PetscErrorCode ierr;
665   size_t         na,nb;
666 
667   PetscFunctionBegin;
668   *flg = PETSC_FALSE;
669   ierr = PetscStrrstr(a,b,&test);CHKERRQ(ierr);
670   if (test) {
671     ierr = PetscStrlen(a,&na);CHKERRQ(ierr);
672     ierr = PetscStrlen(b,&nb);CHKERRQ(ierr);
673     if (a+na-nb == test) *flg = PETSC_TRUE;
674   }
675   PetscFunctionReturn(0);
676 }
677 
678 #undef __FUNCT__
679 #define __FUNCT__ "PetscStrendswithwhich"
680 /*@C
681    PetscStrendswithwhich - Determines if a string ends with one of several possible strings
682 
683    Not Collective
684 
685    Input Parameters:
686 +  a - pointer to string
687 -  bs - strings to endwith (last entry must be null)
688 
689    Output Parameter:
690 .  cnt - the index of the string it ends with or 1+the last possible index
691 
692    Notes:     Not for use in Fortran
693 
694    Level: intermediate
695 
696 @*/
697 PetscErrorCode  PetscStrendswithwhich(const char a[],const char *const *bs,PetscInt *cnt)
698 {
699   PetscBool      flg;
700   PetscErrorCode ierr;
701 
702   PetscFunctionBegin;
703   *cnt = 0;
704   while (bs[*cnt]) {
705     ierr = PetscStrendswith(a,bs[*cnt],&flg);CHKERRQ(ierr);
706     if (flg) PetscFunctionReturn(0);
707     *cnt += 1;
708   }
709   PetscFunctionReturn(0);
710 }
711 
712 #undef __FUNCT__
713 #define __FUNCT__ "PetscStrrstr"
714 /*@C
715    PetscStrrstr - Locates last occurance of string in another string
716 
717    Not Collective
718 
719    Input Parameters:
720 +  a - pointer to string
721 -  b - string to find
722 
723    Output Parameter:
724 .  tmp - location of occurance
725 
726    Notes:     Not for use in Fortran
727 
728    Level: intermediate
729 
730 @*/
731 PetscErrorCode  PetscStrrstr(const char a[],const char b[],char *tmp[])
732 {
733   const char *stmp = a, *ltmp = 0;
734 
735   PetscFunctionBegin;
736   while (stmp) {
737     stmp = (char *)strstr(stmp,b);
738     if (stmp) {ltmp = stmp;stmp++;}
739   }
740   *tmp = (char *)ltmp;
741   PetscFunctionReturn(0);
742 }
743 
744 #undef __FUNCT__
745 #define __FUNCT__ "PetscStrstr"
746 /*@C
747    PetscStrstr - Locates first occurance of string in another string
748 
749    Not Collective
750 
751    Input Parameters:
752 +  haystack - string to search
753 -  needle - string to find
754 
755    Output Parameter:
756 .  tmp - location of occurance, is a PETSC_NULL if the string is not found
757 
758    Notes: Not for use in Fortran
759 
760    Level: intermediate
761 
762 @*/
763 PetscErrorCode  PetscStrstr(const char haystack[],const char needle[],char *tmp[])
764 {
765   PetscFunctionBegin;
766   *tmp = (char *)strstr(haystack,needle);
767   PetscFunctionReturn(0);
768 }
769 
770 struct _p_PetscToken {char token;char *array;char *current;};
771 
772 #undef __FUNCT__
773 #define __FUNCT__ "PetscTokenFind"
774 /*@C
775    PetscTokenFind - Locates next "token" in a string
776 
777    Not Collective
778 
779    Input Parameters:
780 .  a - pointer to token
781 
782    Output Parameter:
783 .  result - location of occurance, PETSC_NULL if not found
784 
785    Notes:
786 
787      This version is different from the system version in that
788   it allows you to pass a read-only string into the function.
789 
790      This version also treats all characters etc. inside a double quote "
791    as a single token.
792 
793     Not for use in Fortran
794 
795    Level: intermediate
796 
797 
798 .seealso: PetscTokenCreate(), PetscTokenDestroy()
799 @*/
800 PetscErrorCode  PetscTokenFind(PetscToken a,char *result[])
801 {
802   char *ptr = a->current,token;
803 
804   PetscFunctionBegin;
805   *result = a->current;
806   if (ptr && !*ptr) {*result = 0;PetscFunctionReturn(0);}
807   token = a->token;
808   if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
809   while (ptr) {
810     if (*ptr == token) {
811       *ptr++ = 0;
812       while (*ptr == a->token) ptr++;
813       a->current = ptr;
814       break;
815     }
816     if (!*ptr) {
817       a->current = 0;
818       break;
819     }
820     ptr++;
821   }
822   PetscFunctionReturn(0);
823 }
824 
825 #undef __FUNCT__
826 #define __FUNCT__ "PetscTokenCreate"
827 /*@C
828    PetscTokenCreate - Creates a PetscToken used to find tokens in a string
829 
830    Not Collective
831 
832    Input Parameters:
833 +  string - the string to look in
834 -  token - the character to look for
835 
836    Output Parameter:
837 .  a - pointer to token
838 
839    Notes:
840 
841      This version is different from the system version in that
842   it allows you to pass a read-only string into the function.
843 
844     Not for use in Fortran
845 
846    Level: intermediate
847 
848 .seealso: PetscTokenFind(), PetscTokenDestroy()
849 @*/
850 PetscErrorCode  PetscTokenCreate(const char a[],const char b,PetscToken *t)
851 {
852   PetscErrorCode ierr;
853 
854   PetscFunctionBegin;
855   ierr = PetscNew(struct _p_PetscToken,t);CHKERRQ(ierr);
856   ierr = PetscStrallocpy(a,&(*t)->array);CHKERRQ(ierr);
857   (*t)->current = (*t)->array;
858   (*t)->token   = b;
859   PetscFunctionReturn(0);
860 }
861 
862 #undef __FUNCT__
863 #define __FUNCT__ "PetscTokenDestroy"
864 /*@C
865    PetscTokenDestroy - Destroys a PetscToken
866 
867    Not Collective
868 
869    Input Parameters:
870 .  a - pointer to token
871 
872    Level: intermediate
873 
874    Notes:     Not for use in Fortran
875 
876 .seealso: PetscTokenCreate(), PetscTokenFind()
877 @*/
878 PetscErrorCode  PetscTokenDestroy(PetscToken *a)
879 {
880   PetscErrorCode ierr;
881 
882   PetscFunctionBegin;
883   if (!*a) PetscFunctionReturn(0);
884   ierr = PetscFree((*a)->array);CHKERRQ(ierr);
885   ierr = PetscFree(*a);CHKERRQ(ierr);
886   PetscFunctionReturn(0);
887 }
888 
889 
890 #undef __FUNCT__
891 #define __FUNCT__ "PetscGetPetscDir"
892 /*@C
893    PetscGetPetscDir - Gets the directory PETSc is installed in
894 
895    Not Collective
896 
897    Output Parameter:
898 .  dir - the directory
899 
900    Level: developer
901 
902    Notes: Not for use in Fortran
903 
904 @*/
905 PetscErrorCode  PetscGetPetscDir(const char *dir[])
906 {
907   PetscFunctionBegin;
908   *dir = PETSC_DIR;
909   PetscFunctionReturn(0);
910 }
911 
912 #undef __FUNCT__
913 #define __FUNCT__ "PetscStrreplace"
914 /*@C
915    PetscStrreplace - Replaces substrings in string with other substrings
916 
917    Not Collective
918 
919    Input Parameters:
920 +   comm - MPI_Comm of processors that are processing the string
921 .   aa - the string to look in
922 .   b - the resulting copy of a with replaced strings (b can be the same as a)
923 -   len - the length of b
924 
925    Notes:
926       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
927       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values
928       as well as any environmental variables.
929 
930       PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what
931       PETSc was built with and do not use environmental variables.
932 
933       Not for use in Fortran
934 
935    Level: intermediate
936 
937 @*/
938 PetscErrorCode  PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
939 {
940   PetscErrorCode ierr;
941   int            i = 0;
942   size_t         l,l1,l2,l3;
943   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
944   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}","${HOSTNAME}",0};
945   const char     *r[] = {0,0,0,0,0,0,0,0,0};
946   PetscBool      flag;
947 
948   PetscFunctionBegin;
949   if (!a || !b) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
950   if (aa == b) {
951     ierr    = PetscStrallocpy(aa,(char **)&a);CHKERRQ(ierr);
952   }
953   ierr = PetscMalloc(len*sizeof(char*),&work);CHKERRQ(ierr);
954 
955   /* get values for replaced variables */
956   ierr = PetscStrallocpy(PETSC_ARCH,(char**)&r[0]);CHKERRQ(ierr);
957   ierr = PetscStrallocpy(PETSC_DIR,(char**)&r[1]);CHKERRQ(ierr);
958   ierr = PetscStrallocpy(PETSC_LIB_DIR,(char**)&r[2]);CHKERRQ(ierr);
959   ierr = PetscMalloc(256*sizeof(char),&r[3]);CHKERRQ(ierr);
960   ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[4]);CHKERRQ(ierr);
961   ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);CHKERRQ(ierr);
962   ierr = PetscMalloc(256*sizeof(char),&r[6]);CHKERRQ(ierr);
963   ierr = PetscMalloc(256*sizeof(char),&r[7]);CHKERRQ(ierr);
964   ierr = PetscGetDisplay((char*)r[3],256);CHKERRQ(ierr);
965   ierr = PetscGetHomeDirectory((char*)r[4],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
966   ierr = PetscGetWorkingDirectory((char*)r[5],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
967   ierr = PetscGetUserName((char*)r[6],256);CHKERRQ(ierr);
968   ierr = PetscGetHostName((char*)r[7],256);CHKERRQ(ierr);
969 
970   /* replace that are in environment */
971   ierr = PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);CHKERRQ(ierr);
972   if (flag) {
973     ierr = PetscStrallocpy(env,(char**)&r[2]);CHKERRQ(ierr);
974   }
975 
976   /* replace the requested strings */
977   ierr = PetscStrncpy(b,a,len);CHKERRQ(ierr);
978   while (s[i]) {
979     ierr = PetscStrlen(s[i],&l);CHKERRQ(ierr);
980     ierr = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
981     while (par) {
982       *par  =  0;
983       par  += l;
984 
985       ierr = PetscStrlen(b,&l1);CHKERRQ(ierr);
986       ierr = PetscStrlen(r[i],&l2);CHKERRQ(ierr);
987       ierr = PetscStrlen(par,&l3);CHKERRQ(ierr);
988       if (l1 + l2 + l3 >= len) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
989       ierr  = PetscStrcpy(work,b);CHKERRQ(ierr);
990       ierr  = PetscStrcat(work,r[i]);CHKERRQ(ierr);
991       ierr  = PetscStrcat(work,par);CHKERRQ(ierr);
992       ierr  = PetscStrncpy(b,work,len);CHKERRQ(ierr);
993       ierr  = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
994     }
995     i++;
996   }
997   i = 0;
998   while (r[i]) {
999     tfree = (char*)r[i];
1000     ierr = PetscFree(tfree);CHKERRQ(ierr);
1001     i++;
1002   }
1003 
1004   /* look for any other ${xxx} strings to replace from environmental variables */
1005   ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
1006   while (par) {
1007     *par = 0;
1008     par += 2;
1009     ierr  = PetscStrcpy(work,b);CHKERRQ(ierr);
1010     ierr = PetscStrstr(par,"}",&epar);CHKERRQ(ierr);
1011     *epar = 0;
1012     epar += 1;
1013     ierr = PetscOptionsGetenv(comm,par,env,256,&flag);CHKERRQ(ierr);
1014     if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
1015     ierr = PetscStrcat(work,env);CHKERRQ(ierr);
1016     ierr = PetscStrcat(work,epar);CHKERRQ(ierr);
1017     ierr = PetscStrcpy(b,work);CHKERRQ(ierr);
1018     ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
1019   }
1020   ierr = PetscFree(work);CHKERRQ(ierr);
1021   if (aa == b) {
1022     ierr = PetscFree(a);CHKERRQ(ierr);
1023   }
1024   PetscFunctionReturn(0);
1025 }
1026 
1027 
1028