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: if (!t) return(0);
180: strcat(s,t);
181: return(0);
182: }
186: /*@C
187: PetscStrncat - Concatenates a string onto a given string, up to a given length
189: Not Collective
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
196: Level: intermediate
198: Concepts: string copy
200: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
201:
202: @*/
203: PetscErrorCode PetscStrncat(char s[],const char t[],size_t n)
204: {
206: strncat(s,t,n);
207: return(0);
208: }
212: /*@C
213: PetscStrcmp - Compares two strings,
215: Not Collective
217: Input Parameters:
218: + a - pointer to string first string
219: - b - pointer to second string
221: Output Parameter:
222: . flg - if the two strings are equal
224: Level: intermediate
226: .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()
228: @*/
229: PetscErrorCode PetscStrcmp(const char a[],const char b[],PetscTruth *flg)
230: {
231: int c;
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: return(0);
244: }
248: /*@C
249: PetscStrgrt - If first string is greater than the second
251: Not Collective
253: Input Parameters:
254: + a - pointer to first string
255: - b - pointer to second string
257: Output Parameter:
258: . flg - if the first string is greater
260: Notes:
261: Null arguments are ok, a null string is considered smaller than
262: all others
264: Level: intermediate
266: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()
268: @*/
269: PetscErrorCode PetscStrgrt(const char a[],const char b[],PetscTruth *t)
270: {
271: int c;
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: return(0);
286: }
290: /*@C
291: PetscStrcasecmp - Returns true if the two strings are the same
292: except possibly for case.
294: Not Collective
296: Input Parameters:
297: + a - pointer to first string
298: - b - pointer to second string
300: Output Parameter:
301: . flg - if the two strings are the same
303: Notes:
304: Null arguments are ok
306: Level: intermediate
308: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()
310: @*/
311: PetscErrorCode PetscStrcasecmp(const char a[],const char b[],PetscTruth *t)
312: {
313: int c;
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;
326: PetscStrallocpy(a,&aa);
327: PetscStrallocpy(b,&bb);
328: PetscStrtolower(aa);
329: PetscStrtolower(bb);
330: PetscStrcmp(aa,bb,t);
331: PetscStrfree(aa);
332: PetscStrfree(bb);
333: return(0);
334: }
335: #endif
336: if (!c) *t = PETSC_TRUE;
337: else *t = PETSC_FALSE;
338: return(0);
339: }
345: /*@C
346: PetscStrncmp - Compares two strings, up to a certain length
348: Not Collective
350: Input Parameters:
351: + a - pointer to first string
352: . b - pointer to second string
353: - n - length to compare up to
355: Output Parameter:
356: . t - if the two strings are equal
358: Level: intermediate
360: .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()
362: @*/
363: PetscErrorCode PetscStrncmp(const char a[],const char b[],size_t n,PetscTruth *t)
364: {
365: int c;
368: c = strncmp(a,b,n);
369: if (!c) *t = PETSC_TRUE;
370: else *t = PETSC_FALSE;
371: return(0);
372: }
376: /*@C
377: PetscStrchr - Locates first occurance of a character in a string
379: Not Collective
381: Input Parameters:
382: + a - pointer to string
383: - b - character
385: Output Parameter:
386: . c - location of occurance, PETSC_NULL if not found
388: Level: intermediate
390: @*/
391: PetscErrorCode PetscStrchr(const char a[],char b,char *c[])
392: {
394: *c = (char *)strchr(a,b);
395: return(0);
396: }
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
404: Not Collective
406: Input Parameters:
407: + a - pointer to string
408: - b - character
410: Output Parameter:
411: . tmp - location of occurance, a if not found
413: Level: intermediate
415: @*/
416: PetscErrorCode PetscStrrchr(const char a[],char b,char *tmp[])
417: {
419: *tmp = (char *)strrchr(a,b);
420: if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
421: return(0);
422: }
426: /*@C
427: PetscStrtolower - Converts string to lower case
429: Not Collective
431: Input Parameters:
432: . a - pointer to string
434: Level: intermediate
436: @*/
437: PetscErrorCode PetscStrtolower(char a[])
438: {
440: while (*a) {
441: if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
442: a++;
443: }
444: return(0);
445: }
447: struct _p_PetscToken {char token;char *array;char *current;};
452: /*@C
453: PetscTokenFind - Locates next "token" in a string
455: Not Collective
457: Input Parameters:
458: . a - pointer to token
460: Output Parameter:
461: . result - location of occurance, PETSC_NULL if not found
463: Notes:
465: This version is different from the system version in that
466: it allows you to pass a read-only string into the function.
468: This version also treats all characters etc. inside a double quote "
469: as a single token.
471: Level: intermediate
473: .seealso: PetscTokenCreate(), PetscTokenDestroy()
474: @*/
475: PetscErrorCode PetscTokenFind(PetscToken a,char *result[])
476: {
477: char *ptr = a->current,token;
480: *result = a->current;
481: if (ptr && !*ptr) {*result = 0;return(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: return(0);
498: }
502: /*@C
503: PetscTokenCreate - Creates a PetscToken used to find tokens in a string
505: Not Collective
507: Input Parameters:
508: + string - the string to look in
509: - token - the character to look for
511: Output Parameter:
512: . a - pointer to token
514: Notes:
516: This version is different from the system version in that
517: it allows you to pass a read-only string into the function.
519: Level: intermediate
521: .seealso: PetscTokenFind(), PetscTokenDestroy()
522: @*/
523: PetscErrorCode PetscTokenCreate(const char a[],const char b,PetscToken *t)
524: {
528: PetscNew(struct _p_PetscToken,t);
529: PetscStrallocpy(a,&(*t)->array);
530: (*t)->current = (*t)->array;
531: (*t)->token = b;
532: return(0);
533: }
537: /*@C
538: PetscTokenDestroy - Destroys a PetscToken
540: Not Collective
542: Input Parameters:
543: . a - pointer to token
545: Level: intermediate
547: .seealso: PetscTokenCreate(), PetscTokenFind()
548: @*/
549: PetscErrorCode PetscTokenDestroy(PetscToken a)
550: {
554: PetscFree(a->array);
555: PetscFree(a);
556: return(0);
557: }
561: /*@C
562: PetscStrrstr - Locates last occurance of string in another string
564: Not Collective
566: Input Parameters:
567: + a - pointer to string
568: - b - string to find
570: Output Parameter:
571: . tmp - location of occurance
573: Level: intermediate
575: @*/
576: PetscErrorCode PetscStrrstr(const char a[],const char b[],char *tmp[])
577: {
578: const char *stmp = a, *ltmp = 0;
581: while (stmp) {
582: stmp = (char *)strstr(stmp,b);
583: if (stmp) {ltmp = stmp;stmp++;}
584: }
585: *tmp = (char *)ltmp;
586: return(0);
587: }
591: /*@C
592: PetscStrstr - Locates first occurance of string in another string
594: Not Collective
596: Input Parameters:
597: + a - pointer to string
598: - b - string to find
600: Output Parameter:
601: . tmp - location of occurance
603: Level: intermediate
605: @*/
606: PetscErrorCode PetscStrstr(const char a[],const char b[],char *tmp[])
607: {
609: *tmp = (char *)strstr(a,b);
610: return(0);
611: }
615: /*@C
616: PetscGetPetscDir - Gets the directory PETSc is installed in
618: Not Collective
620: Output Parameter:
621: . dir - the directory
623: Level: developer
625: @*/
626: PetscErrorCode PetscGetPetscDir(const char *dir[])
627: {
629: *dir = PETSC_DIR;
630: return(0);
631: }
635: /*@C
636: PetscStrreplace - Replaces substrings in string with other substrings
638: Not Collective
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
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
653: @*/
654: PetscErrorCode PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
655: {
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;
665: if (!a || !b) SETERRQ(PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
666: if (aa == b) {
667: PetscStrallocpy(aa,(char **)&a);
668: }
669: PetscMalloc(len*sizeof(char*),&work);
671: /* get values for replaced variables */
672: PetscStrallocpy(PETSC_ARCH,(char**)&r[0]);
673: PetscStrallocpy(PETSC_DIR,(char**)&r[1]);
674: PetscStrallocpy(PETSC_LIB_DIR,(char**)&r[2]);
675: PetscMalloc(256*sizeof(char),&r[3]);
676: PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[4]);
677: PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);
678: PetscMalloc(256*sizeof(char),&r[6]);
679: PetscGetDisplay((char*)r[3],256);
680: PetscGetHomeDirectory((char*)r[4],PETSC_MAX_PATH_LEN);
681: PetscGetWorkingDirectory((char*)r[5],PETSC_MAX_PATH_LEN);
682: PetscGetUserName((char*)r[6],256);
684: /* replace that are in environment */
685: PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);
686: if (flag) {
687: PetscStrallocpy(env,(char**)&r[2]);
688: }
690: /* replace the requested strings */
691: PetscStrncpy(b,a,len);
692: while (s[i]) {
693: PetscStrlen(s[i],&l);
694: PetscStrstr(b,s[i],&par);
695: while (par) {
696: *par = 0;
697: par += l;
699: PetscStrlen(b,&l1);
700: PetscStrlen(r[i],&l2);
701: PetscStrlen(par,&l3);
702: if (l1 + l2 + l3 >= len) {
703: SETERRQ(PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
704: }
705: PetscStrcpy(work,b);
706: PetscStrcat(work,r[i]);
707: PetscStrcat(work,par);
708: PetscStrncpy(b,work,len);
709: PetscStrstr(b,s[i],&par);
710: }
711: i++;
712: }
713: i = 0;
714: while (r[i]) {
715: tfree = (char*)r[i];
716: PetscFree(tfree);
717: i++;
718: }
720: /* look for any other ${xxx} strings to replace from environmental variables */
721: PetscStrstr(b,"${",&par);
722: while (par) {
723: *par = 0;
724: par += 2;
725: PetscStrcpy(work,b);
726: PetscStrstr(par,"}",&epar);
727: *epar = 0;
728: epar += 1;
729: PetscOptionsGetenv(comm,par,env,256,&flag);
730: if (!flag) {
731: SETERRQ1(PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
732: }
733: PetscStrcat(work,env);
734: PetscStrcat(work,epar);
735: PetscStrcpy(b,work);
736: PetscStrstr(b,"${",&par);
737: }
738: PetscFree(work);
739: if (aa == b) {
740: PetscFree(a);
741: }
742: return(0);
743: }
745: /*MC
746: PetscStrfree - Frees a string (if it is not null)
748: Not Collective
750: Synopsis:
751: PetscErrorCode PetscStrfree(char *s)
753: Input Parameter:
754: . s - pointer to string
756: Level: intermediate
758: Concepts: string free
759:
760: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat(), PetscStrallocpy()
762: M*/