xref: /petsc/src/sys/utils/str.c (revision a58c3bc3391eee32bc3fd94ac7edeea38fe57aae)
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   strcat(s,t);
180   PetscFunctionReturn(0);
181 }
182 
183 #undef __FUNCT__
184 #define __FUNCT__ "PetscStrncat"
185 /*@C
186    PetscStrncat - Concatenates a string onto a given string, up to a given length
187 
188    Not Collective
189 
190    Input Parameters:
191 +  s - pointer to string to be added to end
192 .  t - string to be added to
193 .  n - maximum length to copy
194 
195    Level: intermediate
196 
197   Concepts: string copy
198 
199 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
200 
201 @*/
202 PetscErrorCode PETSC_DLLEXPORT PetscStrncat(char s[],const char t[],size_t n)
203 {
204   PetscFunctionBegin;
205   strncat(s,t,n);
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "PetscStrcmp"
211 /*@C
212    PetscStrcmp - Compares two strings,
213 
214    Not Collective
215 
216    Input Parameters:
217 +  a - pointer to string first string
218 -  b - pointer to second string
219 
220    Output Parameter:
221 .  flg - if the two strings are equal
222 
223    Level: intermediate
224 
225 .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()
226 
227 @*/
228 PetscErrorCode PETSC_DLLEXPORT PetscStrcmp(const char a[],const char b[],PetscTruth *flg)
229 {
230   int c;
231 
232   PetscFunctionBegin;
233   if (!a && !b) {
234     *flg = PETSC_TRUE;
235   } else if (!a || !b) {
236     *flg = PETSC_FALSE;
237   } else {
238     c = strcmp(a,b);
239     if (c) *flg = PETSC_FALSE;
240     else   *flg = PETSC_TRUE;
241   }
242   PetscFunctionReturn(0);
243 }
244 
245 #undef __FUNCT__
246 #define __FUNCT__ "PetscStrgrt"
247 /*@C
248    PetscStrgrt - If first string is greater than the second
249 
250    Not Collective
251 
252    Input Parameters:
253 +  a - pointer to first string
254 -  b - pointer to second string
255 
256    Output Parameter:
257 .  flg - if the first string is greater
258 
259    Notes:
260     Null arguments are ok, a null string is considered smaller than
261     all others
262 
263    Level: intermediate
264 
265 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()
266 
267 @*/
268 PetscErrorCode PETSC_DLLEXPORT PetscStrgrt(const char a[],const char b[],PetscTruth *t)
269 {
270   int c;
271 
272   PetscFunctionBegin;
273   if (!a && !b) {
274     *t = PETSC_FALSE;
275   } else if (a && !b) {
276     *t = PETSC_TRUE;
277   } else if (!a && b) {
278     *t = PETSC_FALSE;
279   } else {
280     c = strcmp(a,b);
281     if (c > 0) *t = PETSC_TRUE;
282     else       *t = PETSC_FALSE;
283   }
284   PetscFunctionReturn(0);
285 }
286 
287 #undef __FUNCT__
288 #define __FUNCT__ "PetscStrcasecmp"
289 /*@C
290    PetscStrcasecmp - Returns true if the two strings are the same
291      except possibly for case.
292 
293    Not Collective
294 
295    Input Parameters:
296 +  a - pointer to first string
297 -  b - pointer to second string
298 
299    Output Parameter:
300 .  flg - if the two strings are the same
301 
302    Notes:
303     Null arguments are ok
304 
305    Level: intermediate
306 
307 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()
308 
309 @*/
310 PetscErrorCode PETSC_DLLEXPORT PetscStrcasecmp(const char a[],const char b[],PetscTruth *t)
311 {
312   int c;
313 
314   PetscFunctionBegin;
315   if (!a && !b) c = 0;
316   else if (!a || !b) c = 1;
317 #if defined(PETSC_HAVE_STRICMP)
318   else c = stricmp(a,b);
319 #else
320   else c = strcasecmp(a,b);
321 #endif
322   if (!c) *t = PETSC_TRUE;
323   else    *t = PETSC_FALSE;
324   PetscFunctionReturn(0);
325 }
326 
327 #undef __FUNCT__
328 #define __FUNCT__ "PetscStrncmp"
329 /*@C
330    PetscStrncmp - Compares two strings, up to a certain length
331 
332    Not Collective
333 
334    Input Parameters:
335 +  a - pointer to first string
336 .  b - pointer to second string
337 -  n - length to compare up to
338 
339    Output Parameter:
340 .  t - if the two strings are equal
341 
342    Level: intermediate
343 
344 .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()
345 
346 @*/
347 PetscErrorCode PETSC_DLLEXPORT PetscStrncmp(const char a[],const char b[],size_t n,PetscTruth *t)
348 {
349   int c;
350 
351   PetscFunctionBegin;
352   c = strncmp(a,b,n);
353   if (!c) *t = PETSC_TRUE;
354   else    *t = PETSC_FALSE;
355   PetscFunctionReturn(0);
356 }
357 
358 #undef __FUNCT__
359 #define __FUNCT__ "PetscStrchr"
360 /*@C
361    PetscStrchr - Locates first occurance of a character in a string
362 
363    Not Collective
364 
365    Input Parameters:
366 +  a - pointer to string
367 -  b - character
368 
369    Output Parameter:
370 .  c - location of occurance, PETSC_NULL if not found
371 
372    Level: intermediate
373 
374 @*/
375 PetscErrorCode PETSC_DLLEXPORT PetscStrchr(const char a[],char b,char *c[])
376 {
377   PetscFunctionBegin;
378   *c = (char *)strchr(a,b);
379   PetscFunctionReturn(0);
380 }
381 
382 #undef __FUNCT__
383 #define __FUNCT__ "PetscStrrchr"
384 /*@C
385    PetscStrrchr - Locates one location past the last occurance of a character in a string,
386       if the character is not found then returns entire string
387 
388    Not Collective
389 
390    Input Parameters:
391 +  a - pointer to string
392 -  b - character
393 
394    Output Parameter:
395 .  tmp - location of occurance, a if not found
396 
397    Level: intermediate
398 
399 @*/
400 PetscErrorCode PETSC_DLLEXPORT PetscStrrchr(const char a[],char b,char *tmp[])
401 {
402   PetscFunctionBegin;
403   *tmp = (char *)strrchr(a,b);
404   if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
405   PetscFunctionReturn(0);
406 }
407 
408 #undef __FUNCT__
409 #define __FUNCT__ "PetscStrtolower"
410 /*@C
411    PetscStrtolower - Converts string to lower case
412 
413    Not Collective
414 
415    Input Parameters:
416 .  a - pointer to string
417 
418    Level: intermediate
419 
420 @*/
421 PetscErrorCode PETSC_DLLEXPORT PetscStrtolower(char a[])
422 {
423   PetscFunctionBegin;
424   while (*a) {
425     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
426     a++;
427   }
428   PetscFunctionReturn(0);
429 }
430 
431 #undef __FUNCT__
432 #define __FUNCT__ "PetscTokenFind"
433 /*@C
434    PetscTokenFind - Locates next "token" in a string
435 
436    Not Collective
437 
438    Input Parameters:
439 .  a - pointer to token
440 
441    Output Parameter:
442 .  result - location of occurance, PETSC_NULL if not found
443 
444    Notes:
445 
446      This version is different from the system version in that
447   it allows you to pass a read-only string into the function.
448 
449    Level: intermediate
450 
451 .seealso: PetscTokenCreate(), PetscTokenDestroy()
452 @*/
453 PetscErrorCode PETSC_DLLEXPORT PetscTokenFind(PetscToken *a,char *result[])
454 {
455   char *ptr = a->current;
456 
457   PetscFunctionBegin;
458   *result = a->current;
459   if (ptr && !*ptr) *result = 0;
460   while (ptr) {
461     if (*ptr == a->token) {
462       *ptr++ = 0;
463       while (*ptr == a->token) ptr++;
464       a->current = ptr;
465       break;
466     }
467     if (!*ptr) {
468       a->current = 0;
469       break;
470     }
471     ptr++;
472   }
473   PetscFunctionReturn(0);
474 }
475 
476 #undef __FUNCT__
477 #define __FUNCT__ "PetscTokenCreate"
478 /*@C
479    PetscTokenCreate - Creates a PetscToken used to find tokens in a string
480 
481    Not Collective
482 
483    Input Parameters:
484 +  string - the string to look in
485 -  token - the character to look for
486 
487    Output Parameter:
488 .  a - pointer to token
489 
490    Notes:
491 
492      This version is different from the system version in that
493   it allows you to pass a read-only string into the function.
494 
495    Level: intermediate
496 
497 .seealso: PetscTokenFind(), PetscTokenDestroy()
498 @*/
499 PetscErrorCode PETSC_DLLEXPORT PetscTokenCreate(const char a[],const char b,PetscToken **t)
500 {
501   PetscErrorCode ierr;
502 
503   PetscFunctionBegin;
504   ierr = PetscNew(PetscToken,t);CHKERRQ(ierr);
505   ierr = PetscStrallocpy(a,&(*t)->array);CHKERRQ(ierr);
506   (*t)->current = (*t)->array;
507   (*t)->token   = b;
508   PetscFunctionReturn(0);
509 }
510 
511 #undef __FUNCT__
512 #define __FUNCT__ "PetscTokenDestroy"
513 /*@C
514    PetscTokenDestroy - Destroys a PetscToken
515 
516    Not Collective
517 
518    Input Parameters:
519 .  a - pointer to token
520 
521    Level: intermediate
522 
523 .seealso: PetscTokenCreate(), PetscTokenFind()
524 @*/
525 PetscErrorCode PETSC_DLLEXPORT PetscTokenDestroy(PetscToken *a)
526 {
527   PetscErrorCode ierr;
528 
529   PetscFunctionBegin;
530   ierr = PetscFree(a->array);CHKERRQ(ierr);
531   ierr = PetscFree(a);CHKERRQ(ierr);
532   PetscFunctionReturn(0);
533 }
534 
535 #undef __FUNCT__
536 #define __FUNCT__ "PetscStrrstr"
537 /*@C
538    PetscStrrstr - Locates last occurance of string in another string
539 
540    Not Collective
541 
542    Input Parameters:
543 +  a - pointer to string
544 -  b - string to find
545 
546    Output Parameter:
547 .  tmp - location of occurance
548 
549    Level: intermediate
550 
551 @*/
552 PetscErrorCode PETSC_DLLEXPORT PetscStrrstr(const char a[],const char b[],char *tmp[])
553 {
554   const char *stmp = a, *ltmp = 0;
555 
556   PetscFunctionBegin;
557   while (stmp) {
558     stmp = (char *)strstr(stmp,b);
559     if (stmp) {ltmp = stmp;stmp++;}
560   }
561   *tmp = (char *)ltmp;
562   PetscFunctionReturn(0);
563 }
564 
565 #undef __FUNCT__
566 #define __FUNCT__ "PetscStrstr"
567 /*@C
568    PetscStrstr - Locates first occurance of string in another string
569 
570    Not Collective
571 
572    Input Parameters:
573 +  a - pointer to string
574 -  b - string to find
575 
576    Output Parameter:
577 .  tmp - location of occurance
578 
579    Level: intermediate
580 
581 @*/
582 PetscErrorCode PETSC_DLLEXPORT PetscStrstr(const char a[],const char b[],char *tmp[])
583 {
584   PetscFunctionBegin;
585   *tmp = (char *)strstr(a,b);
586   PetscFunctionReturn(0);
587 }
588 
589 #undef __FUNCT__
590 #define __FUNCT__ "PetscGetPetscDir"
591 /*@C
592    PetscGetPetscDir - Gets the directory PETSc is installed in
593 
594    Not Collective
595 
596    Output Parameter:
597 .  dir - the directory
598 
599    Level: developer
600 
601 @*/
602 PetscErrorCode PETSC_DLLEXPORT PetscGetPetscDir(const char *dir[])
603 {
604   PetscFunctionBegin;
605   *dir = PETSC_DIR;
606   PetscFunctionReturn(0);
607 }
608 
609 #undef __FUNCT__
610 #define __FUNCT__ "PetscStrreplace"
611 /*@C
612    PetscStrreplace - Replaces substrings in string with other substrings
613 
614    Not Collective
615 
616    Input Parameters:
617 +   comm - MPI_Comm of processors that are processing the string
618 .   aa - the string to look in
619 .   b - the resulting copy of a with replaced strings (b can be the same as a)
620 -   len - the length of b
621 
622    Notes:
623       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
624       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME} with appropriate values
625       as well as any environmental variables.
626 
627    Level: intermediate
628 
629 @*/
630 PetscErrorCode PETSC_DLLEXPORT PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
631 {
632   PetscErrorCode ierr;
633   int            i = 0;
634   size_t         l,l1,l2,l3;
635   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
636   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}",0};
637   const char     *r[] = {PETSC_ARCH,PETSC_DIR,PETSC_LIB_DIR,0,0,0,0,0};
638   PetscTruth     flag;
639 
640   PetscFunctionBegin;
641   if (!a || !b) SETERRQ(PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
642   if (aa == b) {
643     ierr    = PetscStrallocpy(aa,(char **)&a);
644   }
645   ierr = PetscMalloc(len*sizeof(char*),&work);CHKERRQ(ierr);
646 
647   /* get values for replaced variables */
648   ierr = PetscMalloc(256*sizeof(char),&r[4]);CHKERRQ(ierr);
649   ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);CHKERRQ(ierr);
650   ierr = PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[6]);CHKERRQ(ierr);
651   ierr = PetscMalloc(256*sizeof(char),&r[7]);CHKERRQ(ierr);
652   ierr = PetscGetDisplay((char*)r[4],256);CHKERRQ(ierr);
653   ierr = PetscGetHomeDirectory((char*)r[5],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
654   ierr = PetscGetWorkingDirectory((char*)r[6],PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
655   ierr = PetscGetUserName((char*)r[7],256);CHKERRQ(ierr);
656 
657   /* replace the requested strings */
658   ierr = PetscStrncpy(b,a,len);CHKERRQ(ierr);
659   while (s[i]) {
660     ierr = PetscStrlen(s[i],&l);CHKERRQ(ierr);
661     ierr = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
662     while (par) {
663       *par  =  0;
664       par  += l;
665 
666       ierr = PetscStrlen(b,&l1);CHKERRQ(ierr);
667       ierr = PetscStrlen(r[i],&l2);CHKERRQ(ierr);
668       ierr = PetscStrlen(par,&l3);CHKERRQ(ierr);
669       if (l1 + l2 + l3 >= len) {
670         SETERRQ(PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
671       }
672       ierr  = PetscStrcpy(work,b);CHKERRQ(ierr);
673       ierr  = PetscStrcat(work,r[i]);CHKERRQ(ierr);
674       ierr  = PetscStrcat(work,par);CHKERRQ(ierr);
675       ierr  = PetscStrncpy(b,work,len);CHKERRQ(ierr);
676       ierr  = PetscStrstr(b,s[i],&par);CHKERRQ(ierr);
677     }
678     i++;
679   }
680   for ( i=4; i<8; i++){
681     tfree = (char*)r[i];
682     ierr = PetscFree(tfree);CHKERRQ(ierr);
683   }
684 
685   /* look for any other ${xxx} strings to replace from environmental variables */
686   ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
687   while (par) {
688     *par = 0;
689     par += 2;
690     ierr  = PetscStrcpy(work,b);CHKERRQ(ierr);
691     ierr = PetscStrstr(par,"}",&epar);CHKERRQ(ierr);
692     *epar = 0;
693     epar += 1;
694     ierr = PetscOptionsGetenv(comm,par,env,256,&flag);CHKERRQ(ierr);
695     if (!flag) {
696       SETERRQ1(PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
697     }
698     ierr = PetscStrcat(work,env);CHKERRQ(ierr);
699     ierr = PetscStrcat(work,epar);CHKERRQ(ierr);
700     ierr = PetscStrcpy(b,work);CHKERRQ(ierr);
701     ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr);
702   }
703   ierr = PetscFree(work);CHKERRQ(ierr);
704   if (aa == b) {
705     ierr = PetscFree(a);CHKERRQ(ierr);
706   }
707   PetscFunctionReturn(0);
708 }
709 
710 /*MC
711    PetscStrfree - Frees a string (if it is not null)
712 
713    Not Collective
714 
715    Synopsis:
716    PetscErrorCode PetscStrfree(char *s)
717 
718    Input Parameter:
719 .  s - pointer to string
720 
721    Level: intermediate
722 
723   Concepts: string free
724 
725 .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat(), PetscStrallocpy()
726 
727 M*/
728