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