Actual source code: str.c
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.
7: */
8: #include petsc.h
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"
20: /*@C
21: PetscStrlen - Gets length of a string
23: Not Collective
25: Input Parameters:
26: . s - pointer to string
28: Output Parameter:
29: . len - length in bytes
31: Level: intermediate
33: Note:
34: This routine is analogous to strlen().
36: Null string returns a length of zero
38: Concepts: string length
39:
40: @*/
41: PetscErrorCode PetscStrlen(const char s[],size_t *len)
42: {
44: if (!s) {
45: *len = 0;
46: } else {
47: *len = strlen(s);
48: }
49: return(0);
50: }
54: /*@C
55: PetscStrallocpy - Allocates space to hold a copy of a string then copies the string
57: Not Collective
59: Input Parameters:
60: . s - pointer to string
62: Output Parameter:
63: . t - the copied string
65: Level: intermediate
67: Note:
68: Null string returns a new null string
70: Concepts: string copy
71:
72: @*/
73: PetscErrorCode PetscStrallocpy(const char s[],char *t[])
74: {
76: size_t len;
77: char *tmp = 0;
80: if (s) {
81: PetscStrlen(s,&len);
82: PetscMalloc((1+len)*sizeof(char),&tmp);
83: PetscStrcpy(tmp,s);
84: }
85: *t = tmp;
86: return(0);
87: }
91: /*@C
92: PetscStrcpy - Copies a string
94: Not Collective
96: Input Parameters:
97: . t - pointer to string
99: Output Parameter:
100: . s - the copied string
102: Level: intermediate
104: Note:
105: Null string returns a string starting with zero
107: Concepts: string copy
108:
109: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()
111: @*/
112: PetscErrorCode PetscStrcpy(char s[],const char t[])
113: {
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: return(0);
121: }
125: /*@C
126: PetscStrncpy - Copies a string up to a certain length
128: Not Collective
130: Input Parameters:
131: + t - pointer to string
132: - n - the length to copy
134: Output Parameter:
135: . s - the copied string
137: Level: intermediate
139: Note:
140: Null string returns a string starting with zero
142: Concepts: string copy
144: .seealso: PetscStrcpy(), PetscStrcat(), PetscStrncat()
145:
146: @*/
147: PetscErrorCode PetscStrncpy(char s[],const char t[],size_t n)
148: {
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: return(0);
156: }
160: /*@C
161: PetscStrcat - Concatenates a string onto a given string
163: Not Collective
165: Input Parameters:
166: + s - string to be added to
167: - t - pointer to string to be added to end
169: Level: intermediate
171: Concepts: string copy
173: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
174:
175: @*/
176: PetscErrorCode PetscStrcat(char s[],const char t[])
177: {
179: strcat(s,t);
180: return(0);
181: }
185: /*@C
186: PetscStrncat - Concatenates a string onto a given string, up to a given length
188: Not Collective
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
195: Level: intermediate
197: Concepts: string copy
199: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
200:
201: @*/
202: PetscErrorCode PetscStrncat(char s[],const char t[],size_t n)
203: {
205: strncat(s,t,n);
206: return(0);
207: }
211: /*@C
212: PetscStrcmp - Compares two strings,
214: Not Collective
216: Input Parameters:
217: + a - pointer to string first string
218: - b - pointer to second string
220: Output Parameter:
221: . flg - if the two strings are equal
223: Level: intermediate
225: .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()
227: @*/
228: PetscErrorCode PetscStrcmp(const char a[],const char b[],PetscTruth *flg)
229: {
230: int c;
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: return(0);
243: }
247: /*@C
248: PetscStrgrt - If first string is greater than the second
250: Not Collective
252: Input Parameters:
253: + a - pointer to first string
254: - b - pointer to second string
256: Output Parameter:
257: . flg - if the first string is greater
259: Notes:
260: Null arguments are ok, a null string is considered smaller than
261: all others
263: Level: intermediate
265: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()
267: @*/
268: PetscErrorCode PetscStrgrt(const char a[],const char b[],PetscTruth *t)
269: {
270: int c;
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: return(0);
285: }
289: /*@C
290: PetscStrcasecmp - Returns true if the two strings are the same
291: except possibly for case.
293: Not Collective
295: Input Parameters:
296: + a - pointer to first string
297: - b - pointer to second string
299: Output Parameter:
300: . flg - if the two strings are the same
302: Notes:
303: Null arguments are ok
305: Level: intermediate
307: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()
309: @*/
310: PetscErrorCode PetscStrcasecmp(const char a[],const char b[],PetscTruth *t)
311: {
312: int c;
315: if (!a && !b) c = 0;
316: else if (!a || !b) c = 1;
317: #if defined(PETSC_HAVE_STRCASECMP)
318: else c = strcasecmp(a,b);
319: #elif defined(PETSC_HAVE_STRICMP)
320: else c = stricmp(a,b);
321: #else
322: else {
323: char *aa,*bb;
325: PetscStrallocpy(a,&aa);
326: PetscStrallocpy(b,&bb);
327: PetscStrtolower(aa);
328: PetscStrtolower(bb);
329: PetscStrcmp(aa,bb,t);
330: PetscStrfree(aa);
331: PetscStrfree(bb);
332: return(0);
333: }
334: #endif
335: if (!c) *t = PETSC_TRUE;
336: else *t = PETSC_FALSE;
337: return(0);
338: }
344: /*@C
345: PetscStrncmp - Compares two strings, up to a certain length
347: Not Collective
349: Input Parameters:
350: + a - pointer to first string
351: . b - pointer to second string
352: - n - length to compare up to
354: Output Parameter:
355: . t - if the two strings are equal
357: Level: intermediate
359: .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()
361: @*/
362: PetscErrorCode PetscStrncmp(const char a[],const char b[],size_t n,PetscTruth *t)
363: {
364: int c;
367: c = strncmp(a,b,n);
368: if (!c) *t = PETSC_TRUE;
369: else *t = PETSC_FALSE;
370: return(0);
371: }
375: /*@C
376: PetscStrchr - Locates first occurance of a character in a string
378: Not Collective
380: Input Parameters:
381: + a - pointer to string
382: - b - character
384: Output Parameter:
385: . c - location of occurance, PETSC_NULL if not found
387: Level: intermediate
389: @*/
390: PetscErrorCode PetscStrchr(const char a[],char b,char *c[])
391: {
393: *c = (char *)strchr(a,b);
394: return(0);
395: }
399: /*@C
400: PetscStrrchr - Locates one location past the last occurance of a character in a string,
401: if the character is not found then returns entire string
403: Not Collective
405: Input Parameters:
406: + a - pointer to string
407: - b - character
409: Output Parameter:
410: . tmp - location of occurance, a if not found
412: Level: intermediate
414: @*/
415: PetscErrorCode PetscStrrchr(const char a[],char b,char *tmp[])
416: {
418: *tmp = (char *)strrchr(a,b);
419: if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
420: return(0);
421: }
425: /*@C
426: PetscStrtolower - Converts string to lower case
428: Not Collective
430: Input Parameters:
431: . a - pointer to string
433: Level: intermediate
435: @*/
436: PetscErrorCode PetscStrtolower(char a[])
437: {
439: while (*a) {
440: if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
441: a++;
442: }
443: return(0);
444: }
446: struct _p_PetscToken {char token;char *array;char *current;};
451: /*@C
452: PetscTokenFind - Locates next "token" in a string
454: Not Collective
456: Input Parameters:
457: . a - pointer to token
459: Output Parameter:
460: . result - location of occurance, PETSC_NULL if not found
462: Notes:
464: This version is different from the system version in that
465: it allows you to pass a read-only string into the function.
467: Level: intermediate
469: .seealso: PetscTokenCreate(), PetscTokenDestroy()
470: @*/
471: PetscErrorCode PetscTokenFind(PetscToken a,char *result[])
472: {
473: char *ptr = a->current;
476: *result = a->current;
477: if (ptr && !*ptr) *result = 0;
478: while (ptr) {
479: if (*ptr == a->token) {
480: *ptr++ = 0;
481: while (*ptr == a->token) ptr++;
482: a->current = ptr;
483: break;
484: }
485: if (!*ptr) {
486: a->current = 0;
487: break;
488: }
489: ptr++;
490: }
491: return(0);
492: }
496: /*@C
497: PetscTokenCreate - Creates a PetscToken used to find tokens in a string
499: Not Collective
501: Input Parameters:
502: + string - the string to look in
503: - token - the character to look for
505: Output Parameter:
506: . a - pointer to token
508: Notes:
510: This version is different from the system version in that
511: it allows you to pass a read-only string into the function.
513: Level: intermediate
515: .seealso: PetscTokenFind(), PetscTokenDestroy()
516: @*/
517: PetscErrorCode PetscTokenCreate(const char a[],const char b,PetscToken *t)
518: {
522: PetscNew(struct _p_PetscToken,t);
523: PetscStrallocpy(a,&(*t)->array);
524: (*t)->current = (*t)->array;
525: (*t)->token = b;
526: return(0);
527: }
531: /*@C
532: PetscTokenDestroy - Destroys a PetscToken
534: Not Collective
536: Input Parameters:
537: . a - pointer to token
539: Level: intermediate
541: .seealso: PetscTokenCreate(), PetscTokenFind()
542: @*/
543: PetscErrorCode PetscTokenDestroy(PetscToken a)
544: {
548: PetscFree(a->array);
549: PetscFree(a);
550: return(0);
551: }
555: /*@C
556: PetscStrrstr - Locates last occurance of string in another string
558: Not Collective
560: Input Parameters:
561: + a - pointer to string
562: - b - string to find
564: Output Parameter:
565: . tmp - location of occurance
567: Level: intermediate
569: @*/
570: PetscErrorCode PetscStrrstr(const char a[],const char b[],char *tmp[])
571: {
572: const char *stmp = a, *ltmp = 0;
575: while (stmp) {
576: stmp = (char *)strstr(stmp,b);
577: if (stmp) {ltmp = stmp;stmp++;}
578: }
579: *tmp = (char *)ltmp;
580: return(0);
581: }
585: /*@C
586: PetscStrstr - Locates first occurance of string in another string
588: Not Collective
590: Input Parameters:
591: + a - pointer to string
592: - b - string to find
594: Output Parameter:
595: . tmp - location of occurance
597: Level: intermediate
599: @*/
600: PetscErrorCode PetscStrstr(const char a[],const char b[],char *tmp[])
601: {
603: *tmp = (char *)strstr(a,b);
604: return(0);
605: }
609: /*@C
610: PetscGetPetscDir - Gets the directory PETSc is installed in
612: Not Collective
614: Output Parameter:
615: . dir - the directory
617: Level: developer
619: @*/
620: PetscErrorCode PetscGetPetscDir(const char *dir[])
621: {
623: *dir = PETSC_DIR;
624: return(0);
625: }
629: /*@C
630: PetscStrreplace - Replaces substrings in string with other substrings
632: Not Collective
634: Input Parameters:
635: + comm - MPI_Comm of processors that are processing the string
636: . aa - the string to look in
637: . b - the resulting copy of a with replaced strings (b can be the same as a)
638: - len - the length of b
640: Notes:
641: Replaces ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
642: ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME} with appropriate values
643: as well as any environmental variables.
644:
645: Level: intermediate
647: @*/
648: PetscErrorCode PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
649: {
651: int i = 0;
652: size_t l,l1,l2,l3;
653: char *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
654: const char *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}",0};
655: const char *r[] = {0,0,0,0,0,0,0,0};
656: PetscTruth flag;
659: if (!a || !b) SETERRQ(PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
660: if (aa == b) {
661: PetscStrallocpy(aa,(char **)&a);
662: }
663: PetscMalloc(len*sizeof(char*),&work);
665: /* get values for replaced variables */
666: PetscStrallocpy(PETSC_ARCH,(char**)&r[0]);
667: PetscStrallocpy(PETSC_DIR,(char**)&r[1]);
668: PetscStrallocpy(PETSC_LIB_DIR,(char**)&r[2]);
669: PetscMalloc(256*sizeof(char),&r[3]);
670: PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[4]);
671: PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);
672: PetscMalloc(256*sizeof(char),&r[6]);
673: PetscGetDisplay((char*)r[3],256);
674: PetscGetHomeDirectory((char*)r[4],PETSC_MAX_PATH_LEN);
675: PetscGetWorkingDirectory((char*)r[5],PETSC_MAX_PATH_LEN);
676: PetscGetUserName((char*)r[6],256);
678: /* replace that are in environment */
679: PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);
680: if (flag) {
681: PetscStrallocpy(env,(char**)&r[2]);
682: }
684: /* replace the requested strings */
685: PetscStrncpy(b,a,len);
686: while (s[i]) {
687: PetscStrlen(s[i],&l);
688: PetscStrstr(b,s[i],&par);
689: while (par) {
690: *par = 0;
691: par += l;
693: PetscStrlen(b,&l1);
694: PetscStrlen(r[i],&l2);
695: PetscStrlen(par,&l3);
696: if (l1 + l2 + l3 >= len) {
697: SETERRQ(PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
698: }
699: PetscStrcpy(work,b);
700: PetscStrcat(work,r[i]);
701: PetscStrcat(work,par);
702: PetscStrncpy(b,work,len);
703: PetscStrstr(b,s[i],&par);
704: }
705: i++;
706: }
707: i = 0;
708: while (r[i]) {
709: tfree = (char*)r[i];
710: PetscFree(tfree);
711: i++;
712: }
714: /* look for any other ${xxx} strings to replace from environmental variables */
715: PetscStrstr(b,"${",&par);
716: while (par) {
717: *par = 0;
718: par += 2;
719: PetscStrcpy(work,b);
720: PetscStrstr(par,"}",&epar);
721: *epar = 0;
722: epar += 1;
723: PetscOptionsGetenv(comm,par,env,256,&flag);
724: if (!flag) {
725: SETERRQ1(PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
726: }
727: PetscStrcat(work,env);
728: PetscStrcat(work,epar);
729: PetscStrcpy(b,work);
730: PetscStrstr(b,"${",&par);
731: }
732: PetscFree(work);
733: if (aa == b) {
734: PetscFree(a);
735: }
736: return(0);
737: }
739: /*MC
740: PetscStrfree - Frees a string (if it is not null)
742: Not Collective
744: Synopsis:
745: PetscErrorCode PetscStrfree(char *s)
747: Input Parameter:
748: . s - pointer to string
750: Level: intermediate
752: Concepts: string free
753:
754: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat(), PetscStrallocpy()
756: M*/