xref: /petsc/src/sys/utils/str.c (revision f963788bda91a1d728e4d3144eba9dd2a8083b3a)
1 #define PETSC_DLL
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 "petsc.h"                   /*I  "petsc.h"   I*/
9 #include "petscsys.h"
10 #if defined(PETSC_HAVE_STRING_H)
11 #include <string.h>
12 #endif
13 #if defined(PETSC_HAVE_STRINGS_H)
14 #include <strings.h>
15 #endif
16 #include "petscfix.h"
17 
18 #undef __FUNCT__
19 #define __FUNCT__ "PetscStrlen"
20 /*@C
21    PetscStrlen - Gets length of a string
22 
23    Not Collective
24 
25    Input Parameters:
26 .  s - pointer to string
27 
28    Output Parameter:
29 .  len - length in bytes
30 
31    Level: intermediate
32 
33    Note:
34    This routine is analogous to strlen().
35 
36    Null string returns a length of zero
37 
38   Concepts: string length
39 
40 @*/
41 PetscErrorCode PETSC_DLLEXPORT PetscStrlen(const char s[],size_t *len)
42 {
43   PetscFunctionBegin;
44   if (!s) {
45     *len = 0;
46   } else {
47     *len = strlen(s);
48   }
49   PetscFunctionReturn(0);
50 }
51 
52 #undef __FUNCT__
53 #define __FUNCT__ "PetscStrallocpy"
54 /*@C
55    PetscStrallocpy - Allocates space to hold a copy of a string then copies the string
56 
57    Not Collective
58 
59    Input Parameters:
60 .  s - pointer to string
61 
62    Output Parameter:
63 .  t - the copied string
64 
65    Level: intermediate
66 
67    Note:
68       Null string returns a new null string
69 
70   Concepts: string copy
71 
72 @*/
73 PetscErrorCode PETSC_DLLEXPORT PetscStrallocpy(const char s[],char *t[])
74 {
75   PetscErrorCode ierr;
76   size_t         len;
77   char           *tmp = 0;
78 
79   PetscFunctionBegin;
80   if (s) {
81     ierr = PetscStrlen(s,&len);CHKERRQ(ierr);
82     ierr = PetscMalloc((1+len)*sizeof(char),&tmp);CHKERRQ(ierr);
83     ierr = PetscStrcpy(tmp,s);CHKERRQ(ierr);
84   }
85   *t = tmp;
86   PetscFunctionReturn(0);
87 }
88 
89 #undef __FUNCT__
90 #define __FUNCT__ "PetscStrcpy"
91 /*@C
92    PetscStrcpy - Copies a string
93 
94    Not Collective
95 
96    Input Parameters:
97 .  t - pointer to string
98 
99    Output Parameter:
100 .  s - the copied string
101 
102    Level: intermediate
103 
104    Note:
105      Null string returns a string starting with zero
106 
107   Concepts: string copy
108 
109 .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()
110 
111 @*/
112 PetscErrorCode PETSC_DLLEXPORT PetscStrcpy(char s[],const char t[])
113 {
114   PetscFunctionBegin;
115   if (t && !s) {
116     SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
117   }
118   if (t) {strcpy(s,t);}
119   else if (s) {s[0] = 0;}
120   PetscFunctionReturn(0);
121 }
122 
123 #undef __FUNCT__
124 #define __FUNCT__ "PetscStrncpy"
125 /*@C
126    PetscStrncpy - Copies a string up to a certain length
127 
128    Not Collective
129 
130    Input Parameters:
131 +  t - pointer to string
132 -  n - the length to copy
133 
134    Output Parameter:
135 .  s - the copied string
136 
137    Level: intermediate
138 
139    Note:
140      Null string returns a string starting with zero
141 
142   Concepts: string copy
143 
144 .seealso: PetscStrcpy(), PetscStrcat(), PetscStrncat()
145 
146 @*/
147 PetscErrorCode PETSC_DLLEXPORT PetscStrncpy(char s[],const char t[],size_t n)
148 {
149   PetscFunctionBegin;
150   if (t && !s) {
151     SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
152   }
153   if (t) {strncpy(s,t,n);}
154   else if (s) {s[0] = 0;}
155   PetscFunctionReturn(0);
156 }
157 
158 #undef __FUNCT__
159 #define __FUNCT__ "PetscStrcat"
160 /*@C
161    PetscStrcat - Concatenates a string onto a given string
162 
163    Not Collective
164 
165    Input Parameters:
166 +  s - string to be added to
167 -  t - pointer to string to be added to end
168 
169    Level: intermediate
170 
171   Concepts: string copy
172 
173 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
174 
175 @*/
176 PetscErrorCode PETSC_DLLEXPORT PetscStrcat(char s[],const char t[])
177 {
178   PetscFunctionBegin;
179   if (!t) PetscFunctionReturn(0);
180   strcat(s,t);
181   PetscFunctionReturn(0);
182 }
183 
184 #undef __FUNCT__
185 #define __FUNCT__ "PetscStrncat"
186 /*@C
187    PetscStrncat - Concatenates a string onto a given string, up to a given length
188 
189    Not Collective
190 
191    Input Parameters:
192 +  s - pointer to string to be added to end
193 .  t - string to be added to
194 .  n - maximum length to copy
195 
196    Level: intermediate
197 
198   Concepts: string copy
199 
200 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
201 
202 @*/
203 PetscErrorCode PETSC_DLLEXPORT PetscStrncat(char s[],const char t[],size_t n)
204 {
205   PetscFunctionBegin;
206   strncat(s,t,n);
207   PetscFunctionReturn(0);
208 }
209 
210 #undef __FUNCT__
211 #define __FUNCT__ "PetscStrcmp"
212 /*@C
213    PetscStrcmp - Compares two strings,
214 
215    Not Collective
216 
217    Input Parameters:
218 +  a - pointer to string first string
219 -  b - pointer to second string
220 
221    Output Parameter:
222 .  flg - if the two strings are equal
223 
224    Level: intermediate
225 
226 .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()
227 
228 @*/
229 PetscErrorCode PETSC_DLLEXPORT PetscStrcmp(const char a[],const char b[],PetscTruth *flg)
230 {
231   int c;
232 
233   PetscFunctionBegin;
234   if (!a && !b) {
235     *flg = PETSC_TRUE;
236   } else if (!a || !b) {
237     *flg = PETSC_FALSE;
238   } else {
239     c = strcmp(a,b);
240     if (c) *flg = PETSC_FALSE;
241     else   *flg = PETSC_TRUE;
242   }
243   PetscFunctionReturn(0);
244 }
245 
246 #undef __FUNCT__
247 #define __FUNCT__ "PetscStrgrt"
248 /*@C
249    PetscStrgrt - If first string is greater than the second
250 
251    Not Collective
252 
253    Input Parameters:
254 +  a - pointer to first string
255 -  b - pointer to second string
256 
257    Output Parameter:
258 .  flg - if the first string is greater
259 
260    Notes:
261     Null arguments are ok, a null string is considered smaller than
262     all others
263 
264    Level: intermediate
265 
266 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()
267 
268 @*/
269 PetscErrorCode PETSC_DLLEXPORT PetscStrgrt(const char a[],const char b[],PetscTruth *t)
270 {
271   int c;
272 
273   PetscFunctionBegin;
274   if (!a && !b) {
275     *t = PETSC_FALSE;
276   } else if (a && !b) {
277     *t = PETSC_TRUE;
278   } else if (!a && b) {
279     *t = PETSC_FALSE;
280   } else {
281     c = strcmp(a,b);
282     if (c > 0) *t = PETSC_TRUE;
283     else       *t = PETSC_FALSE;
284   }
285   PetscFunctionReturn(0);
286 }
287 
288 #undef __FUNCT__
289 #define __FUNCT__ "PetscStrcasecmp"
290 /*@C
291    PetscStrcasecmp - Returns true if the two strings are the same
292      except possibly for case.
293 
294    Not Collective
295 
296    Input Parameters:
297 +  a - pointer to first string
298 -  b - pointer to second string
299 
300    Output Parameter:
301 .  flg - if the two strings are the same
302 
303    Notes:
304     Null arguments are ok
305 
306    Level: intermediate
307 
308 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()
309 
310 @*/
311 PetscErrorCode PETSC_DLLEXPORT PetscStrcasecmp(const char a[],const char b[],PetscTruth *t)
312 {
313   int c;
314 
315   PetscFunctionBegin;
316   if (!a && !b) c = 0;
317   else if (!a || !b) c = 1;
318 #if defined(PETSC_HAVE_STRCASECMP)
319   else c = strcasecmp(a,b);
320 #elif defined(PETSC_HAVE_STRICMP)
321   else c = stricmp(a,b);
322 #else
323   else {
324     char *aa,*bb;
325     PetscErrorCode ierr;
326     ierr = PetscStrallocpy(a,&aa);CHKERRQ(ierr);
327     ierr = PetscStrallocpy(b,&bb);CHKERRQ(ierr);
328     ierr = PetscStrtolower(aa);CHKERRQ(ierr);
329     ierr = PetscStrtolower(bb);CHKERRQ(ierr);
330     ierr = PetscStrcmp(aa,bb,t);CHKERRQ(ierr);
331     ierr = PetscStrfree(aa);CHKERRQ(ierr);
332     ierr = PetscStrfree(bb);CHKERRQ(ierr);
333     PetscFunctionReturn(0);
334   }
335 #endif
336   if (!c) *t = PETSC_TRUE;
337   else    *t = PETSC_FALSE;
338   PetscFunctionReturn(0);
339 }
340 
341 
342 
343 #undef __FUNCT__
344 #define __FUNCT__ "PetscStrncmp"
345 /*@C
346    PetscStrncmp - Compares two strings, up to a certain length
347 
348    Not Collective
349 
350    Input Parameters:
351 +  a - pointer to first string
352 .  b - pointer to second string
353 -  n - length to compare up to
354 
355    Output Parameter:
356 .  t - if the two strings are equal
357 
358    Level: intermediate
359 
360 .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()
361 
362 @*/
363 PetscErrorCode PETSC_DLLEXPORT PetscStrncmp(const char a[],const char b[],size_t n,PetscTruth *t)
364 {
365   int c;
366 
367   PetscFunctionBegin;
368   c = strncmp(a,b,n);
369   if (!c) *t = PETSC_TRUE;
370   else    *t = PETSC_FALSE;
371   PetscFunctionReturn(0);
372 }
373 
374 #undef __FUNCT__
375 #define __FUNCT__ "PetscStrchr"
376 /*@C
377    PetscStrchr - Locates first occurance of a character in a string
378 
379    Not Collective
380 
381    Input Parameters:
382 +  a - pointer to string
383 -  b - character
384 
385    Output Parameter:
386 .  c - location of occurance, PETSC_NULL if not found
387 
388    Level: intermediate
389 
390 @*/
391 PetscErrorCode PETSC_DLLEXPORT PetscStrchr(const char a[],char b,char *c[])
392 {
393   PetscFunctionBegin;
394   *c = (char *)strchr(a,b);
395   PetscFunctionReturn(0);
396 }
397 
398 #undef __FUNCT__
399 #define __FUNCT__ "PetscStrrchr"
400 /*@C
401    PetscStrrchr - Locates one location past the last occurance of a character in a string,
402       if the character is not found then returns entire string
403 
404    Not Collective
405 
406    Input Parameters:
407 +  a - pointer to string
408 -  b - character
409 
410    Output Parameter:
411 .  tmp - location of occurance, a if not found
412 
413    Level: intermediate
414 
415 @*/
416 PetscErrorCode PETSC_DLLEXPORT PetscStrrchr(const char a[],char b,char *tmp[])
417 {
418   PetscFunctionBegin;
419   *tmp = (char *)strrchr(a,b);
420   if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
421   PetscFunctionReturn(0);
422 }
423 
424 #undef __FUNCT__
425 #define __FUNCT__ "PetscStrtolower"
426 /*@C
427    PetscStrtolower - Converts string to lower case
428 
429    Not Collective
430 
431    Input Parameters:
432 .  a - pointer to string
433 
434    Level: intermediate
435 
436 @*/
437 PetscErrorCode PETSC_DLLEXPORT PetscStrtolower(char a[])
438 {
439   PetscFunctionBegin;
440   while (*a) {
441     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
442     a++;
443   }
444   PetscFunctionReturn(0);
445 }
446 
447 struct _p_PetscToken {char token;char *array;char *current;};
448 
449 
450 #undef __FUNCT__
451 #define __FUNCT__ "PetscTokenFind"
452 /*@C
453    PetscTokenFind - Locates next "token" in a string
454 
455    Not Collective
456 
457    Input Parameters:
458 .  a - pointer to token
459 
460    Output Parameter:
461 .  result - location of occurance, PETSC_NULL if not found
462 
463    Notes:
464 
465      This version is different from the system version in that
466   it allows you to pass a read-only string into the function.
467 
468      This version also treats all characters etc. inside a double quote "
469    as a single token.
470 
471    Level: intermediate
472 
473 .seealso: PetscTokenCreate(), PetscTokenDestroy()
474 @*/
475 PetscErrorCode PETSC_DLLEXPORT PetscTokenFind(PetscToken a,char *result[])
476 {
477   char *ptr = a->current,token;
478 
479   PetscFunctionBegin;
480   *result = a->current;
481   if (ptr && !*ptr) {*result = 0;PetscFunctionReturn(0);}
482   token = a->token;
483   if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
484   while (ptr) {
485     if (*ptr == token) {
486       *ptr++ = 0;
487       while (*ptr == a->token) ptr++;
488       a->current = ptr;
489       break;
490     }
491     if (!*ptr) {
492       a->current = 0;
493       break;
494     }
495     ptr++;
496   }
497   PetscFunctionReturn(0);
498 }
499 
500 #undef __FUNCT__
501 #define __FUNCT__ "PetscTokenCreate"
502 /*@C
503    PetscTokenCreate - Creates a PetscToken used to find tokens in a string
504 
505    Not Collective
506 
507    Input Parameters:
508 +  string - the string to look in
509 -  token - the character to look for
510 
511    Output Parameter:
512 .  a - pointer to token
513 
514    Notes:
515 
516      This version is different from the system version in that
517   it allows you to pass a read-only string into the function.
518 
519    Level: intermediate
520 
521 .seealso: PetscTokenFind(), PetscTokenDestroy()
522 @*/
523 PetscErrorCode PETSC_DLLEXPORT PetscTokenCreate(const char a[],const char b,PetscToken *t)
524 {
525   PetscErrorCode ierr;
526 
527   PetscFunctionBegin;
528   ierr = PetscNew(struct _p_PetscToken,t);CHKERRQ(ierr);
529   ierr = PetscStrallocpy(a,&(*t)->array);CHKERRQ(ierr);
530   (*t)->current = (*t)->array;
531   (*t)->token   = b;
532   PetscFunctionReturn(0);
533 }
534 
535 #undef __FUNCT__
536 #define __FUNCT__ "PetscTokenDestroy"
537 /*@C
538    PetscTokenDestroy - Destroys a PetscToken
539 
540    Not Collective
541 
542    Input Parameters:
543 .  a - pointer to token
544 
545    Level: intermediate
546 
547 .seealso: PetscTokenCreate(), PetscTokenFind()
548 @*/
549 PetscErrorCode PETSC_DLLEXPORT PetscTokenDestroy(PetscToken a)
550 {
551   PetscErrorCode ierr;
552 
553   PetscFunctionBegin;
554   ierr = PetscFree(a->array);CHKERRQ(ierr);
555   ierr = PetscFree(a);CHKERRQ(ierr);
556   PetscFunctionReturn(0);
557 }
558 
559 #undef __FUNCT__
560 #define __FUNCT__ "PetscStrrstr"
561 /*@C
562    PetscStrrstr - Locates last occurance of string in another string
563 
564    Not Collective
565 
566    Input Parameters:
567 +  a - pointer to string
568 -  b - string to find
569 
570    Output Parameter:
571 .  tmp - location of occurance
572 
573    Level: intermediate
574 
575 @*/
576 PetscErrorCode PETSC_DLLEXPORT PetscStrrstr(const char a[],const char b[],char *tmp[])
577 {
578   const char *stmp = a, *ltmp = 0;
579 
580   PetscFunctionBegin;
581   while (stmp) {
582     stmp = (char *)strstr(stmp,b);
583     if (stmp) {ltmp = stmp;stmp++;}
584   }
585   *tmp = (char *)ltmp;
586   PetscFunctionReturn(0);
587 }
588 
589 #undef __FUNCT__
590 #define __FUNCT__ "PetscStrstr"
591 /*@C
592    PetscStrstr - Locates first occurance of string in another string
593 
594    Not Collective
595 
596    Input Parameters:
597 +  a - pointer to string
598 -  b - string to find
599 
600    Output Parameter:
601 .  tmp - location of occurance
602 
603    Level: intermediate
604 
605 @*/
606 PetscErrorCode PETSC_DLLEXPORT PetscStrstr(const char a[],const char b[],char *tmp[])
607 {
608   PetscFunctionBegin;
609   *tmp = (char *)strstr(a,b);
610   PetscFunctionReturn(0);
611 }
612 
613 #undef __FUNCT__
614 #define __FUNCT__ "PetscGetPetscDir"
615 /*@C
616    PetscGetPetscDir - Gets the directory PETSc is installed in
617 
618    Not Collective
619 
620    Output Parameter:
621 .  dir - the directory
622 
623    Level: developer
624 
625 @*/
626 PetscErrorCode PETSC_DLLEXPORT PetscGetPetscDir(const char *dir[])
627 {
628   PetscFunctionBegin;
629   *dir = PETSC_DIR;
630   PetscFunctionReturn(0);
631 }
632 
633 #undef __FUNCT__
634 #define __FUNCT__ "PetscStrreplace"
635 /*@C
636    PetscStrreplace - Replaces substrings in string with other substrings
637 
638    Not Collective
639 
640    Input Parameters:
641 +   comm - MPI_Comm of processors that are processing the string
642 .   aa - the string to look in
643 .   b - the resulting copy of a with replaced strings (b can be the same as a)
644 -   len - the length of b
645 
646    Notes:
647       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
648       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME} with appropriate values
649       as well as any environmental variables.
650 
651    Level: intermediate
652 
653 @*/
654 PetscErrorCode PETSC_DLLEXPORT PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
655 {
656   PetscErrorCode ierr;
657   int            i = 0;
658   size_t         l,l1,l2,l3;
659   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
660   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}",0};
661   const char     *r[] = {0,0,0,0,0,0,0,0};
662   PetscTruth     flag;
663 
664   PetscFunctionBegin;
665   if (!a || !b) SETERRQ(PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
666   if (aa == b) {
667     ierr    = PetscStrallocpy(aa,(char **)&a);
668   }
669   ierr = PetscMalloc(len*sizeof(char*),&work);CHKERRQ(ierr);
670 
671   /* get values for replaced variables */
672   ierr = PetscStrallocpy(PETSC_ARCH,(char**)&r[0]);CHKERRQ(ierr);
673   ierr = PetscStrallocpy(PETSC_DIR,(char**)&r[1]);CHKERRQ(ierr);
674   ierr = PetscStrallocpy(PETSC_LIB_DIR,(char**)&r[2]);CHKERRQ(ierr);
675   ierr = PetscMalloc(256*sizeof(char),&r[3]);CHKERRQ(ierr);
676   ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[4]);CHKERRQ(ierr);
677   ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);CHKERRQ(ierr);
678   ierr = PetscMalloc(256*sizeof(char),&r[6]);CHKERRQ(ierr);
679   ierr = PetscGetDisplay((char*)r[3],256);CHKERRQ(ierr);
680   ierr = PetscGetHomeDirectory((char*)r[4],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
681   ierr = PetscGetWorkingDirectory((char*)r[5],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
682   ierr = PetscGetUserName((char*)r[6],256);CHKERRQ(ierr);
683 
684   /* replace that are in environment */
685   ierr = PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);CHKERRQ(ierr);
686   if (flag) {
687     ierr = PetscStrallocpy(env,(char**)&r[2]);CHKERRQ(ierr);
688   }
689 
690   /* replace the requested strings */
691   ierr = PetscStrncpy(b,a,len);CHKERRQ(ierr);
692   while (s[i]) {
693     ierr = PetscStrlen(s[i],&l);CHKERRQ(ierr);
694     ierr = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
695     while (par) {
696       *par  =  0;
697       par  += l;
698 
699       ierr = PetscStrlen(b,&l1);CHKERRQ(ierr);
700       ierr = PetscStrlen(r[i],&l2);CHKERRQ(ierr);
701       ierr = PetscStrlen(par,&l3);CHKERRQ(ierr);
702       if (l1 + l2 + l3 >= len) {
703         SETERRQ(PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
704       }
705       ierr  = PetscStrcpy(work,b);CHKERRQ(ierr);
706       ierr  = PetscStrcat(work,r[i]);CHKERRQ(ierr);
707       ierr  = PetscStrcat(work,par);CHKERRQ(ierr);
708       ierr  = PetscStrncpy(b,work,len);CHKERRQ(ierr);
709       ierr  = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
710     }
711     i++;
712   }
713   i = 0;
714   while (r[i]) {
715     tfree = (char*)r[i];
716     ierr = PetscFree(tfree);CHKERRQ(ierr);
717     i++;
718   }
719 
720   /* look for any other ${xxx} strings to replace from environmental variables */
721   ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
722   while (par) {
723     *par = 0;
724     par += 2;
725     ierr  = PetscStrcpy(work,b);CHKERRQ(ierr);
726     ierr = PetscStrstr(par,"}",&epar);CHKERRQ(ierr);
727     *epar = 0;
728     epar += 1;
729     ierr = PetscOptionsGetenv(comm,par,env,256,&flag);CHKERRQ(ierr);
730     if (!flag) {
731       SETERRQ1(PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
732     }
733     ierr = PetscStrcat(work,env);CHKERRQ(ierr);
734     ierr = PetscStrcat(work,epar);CHKERRQ(ierr);
735     ierr = PetscStrcpy(b,work);CHKERRQ(ierr);
736     ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
737   }
738   ierr = PetscFree(work);CHKERRQ(ierr);
739   if (aa == b) {
740     ierr = PetscFree(a);CHKERRQ(ierr);
741   }
742   PetscFunctionReturn(0);
743 }
744 
745 /*MC
746    PetscStrfree - Frees a string (if it is not null)
747 
748    Not Collective
749 
750    Synopsis:
751    PetscErrorCode PetscStrfree(char *s)
752 
753    Input Parameter:
754 .  s - pointer to string
755 
756    Level: intermediate
757 
758   Concepts: string free
759 
760 .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat(), PetscStrallocpy()
761 
762 M*/
763