Actual source code: str.c
1: /*
2: We define the string operations here. The reason we just do not use
3: the standard string routines in the PETSc code is that on some machines
4: they are broken or have the wrong prototypes.
6: */
7: #include petsc.h
8: #include petscsys.h
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: #include "petscfix.h"
19: /*@C
20: PetscStrlen - Gets length of a string
22: Not Collective
24: Input Parameters:
25: . s - pointer to string
27: Output Parameter:
28: . len - length in bytes
30: Level: intermediate
32: Note:
33: This routine is analogous to strlen().
35: Null string returns a length of zero
37: Concepts: string length
38:
39: @*/
40: PetscErrorCode PetscStrlen(const char s[],size_t *len)
41: {
43: if (!s) {
44: *len = 0;
45: } else {
46: *len = strlen(s);
47: }
48: return(0);
49: }
53: /*@C
54: PetscStrallocpy - Allocates space to hold a copy of a string then copies the string
56: Not Collective
58: Input Parameters:
59: . s - pointer to string
61: Output Parameter:
62: . t - the copied string
64: Level: intermediate
66: Note:
67: Null string returns a new null string
69: Concepts: string copy
70:
71: @*/
72: PetscErrorCode PetscStrallocpy(const char s[],char *t[])
73: {
75: size_t len;
78: if (s) {
79: PetscStrlen(s,&len);
80: PetscMalloc((1+len)*sizeof(char),t);
81: PetscStrcpy(*t,s);
82: } else {
83: *t = 0;
84: }
85: return(0);
86: }
90: /*@C
91: PetscStrcpy - Copies a string
93: Not Collective
95: Input Parameters:
96: . s - pointer to string
98: Output Parameter:
99: . t - the copied string
101: Level: intermediate
103: Note:
104: Null string returns a string starting with zero
106: Concepts: string copy
107:
108: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()
110: @*/
111: PetscErrorCode PetscStrcpy(char s[],const char t[])
112: {
114: if (t && !s) {
115: SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
116: }
117: if (t) {strcpy(s,t);}
118: else {s[0] = 0;}
119: return(0);
120: }
124: /*@C
125: PetscStrncpy - Copies a string up to a certain length
127: Not Collective
129: Input Parameters:
130: + s - pointer to string
131: - n - the length to copy
133: Output Parameter:
134: . t - the copied string
136: Level: intermediate
138: Note:
139: Null string returns a string starting with zero
141: Concepts: string copy
143: .seealso: PetscStrcpy(), PetscStrcat(), PetscStrncat()
144:
145: @*/
146: PetscErrorCode PetscStrncpy(char s[],const char t[],size_t n)
147: {
149: strncpy(s,t,n);
150: return(0);
151: }
155: /*@C
156: PetscStrcat - Concatenates a string onto a given string
158: Not Collective
160: Input Parameters:
161: + s - pointer to string to be added to end
162: - t - string to be added to
164: Level: intermediate
166: Concepts: string copy
168: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
169:
170: @*/
171: PetscErrorCode PetscStrcat(char s[],const char t[])
172: {
174: strcat(s,t);
175: return(0);
176: }
180: /*@C
181: PetscStrncat - Concatenates a string onto a given string, up to a given length
183: Not Collective
185: Input Parameters:
186: + s - pointer to string to be added to end
187: . t - string to be added to
188: . n - maximum length to copy
190: Level: intermediate
192: Concepts: string copy
194: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
195:
196: @*/
197: PetscErrorCode PetscStrncat(char s[],const char t[],size_t n)
198: {
200: strncat(s,t,n);
201: return(0);
202: }
206: /*@C
207: PetscStrcmp - Compares two strings,
209: Not Collective
211: Input Parameters:
212: + a - pointer to string first string
213: - b - pointer to second string
215: Output Parameter:
216: . flg - if the two strings are equal
218: Level: intermediate
220: .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()
222: @*/
223: PetscErrorCode PetscStrcmp(const char a[],const char b[],PetscTruth *flg)
224: {
225: int c;
228: if (!a && !b) {
229: *flg = PETSC_TRUE;
230: } else if (!a || !b) {
231: *flg = PETSC_FALSE;
232: } else {
233: c = strcmp(a,b);
234: if (c) *flg = PETSC_FALSE;
235: else *flg = PETSC_TRUE;
236: }
237: return(0);
238: }
242: /*@C
243: PetscStrgrt - If first string is greater than the second
245: Not Collective
247: Input Parameters:
248: + a - pointer to first string
249: - b - pointer to second string
251: Output Parameter:
252: . flg - if the first string is greater
254: Notes:
255: Null arguments are ok, a null string is considered smaller than
256: all others
258: Level: intermediate
260: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()
262: @*/
263: PetscErrorCode PetscStrgrt(const char a[],const char b[],PetscTruth *t)
264: {
265: int c;
268: if (!a && !b) {
269: *t = PETSC_FALSE;
270: } else if (a && !b) {
271: *t = PETSC_TRUE;
272: } else if (!a && b) {
273: *t = PETSC_FALSE;
274: } else {
275: c = strcmp(a,b);
276: if (c > 0) *t = PETSC_TRUE;
277: else *t = PETSC_FALSE;
278: }
279: return(0);
280: }
284: /*@C
285: PetscStrcasecmp - Returns true if the two strings are the same
286: except possibly for case.
288: Not Collective
290: Input Parameters:
291: + a - pointer to first string
292: - b - pointer to second string
294: Output Parameter:
295: . flg - if the two strings are the same
297: Notes:
298: Null arguments are ok
300: Level: intermediate
302: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()
304: @*/
305: PetscErrorCode PetscStrcasecmp(const char a[],const char b[],PetscTruth *t)
306: {
307: int c;
310: if (!a && !b) c = 0;
311: else if (!a || !b) c = 1;
312: #if defined(PETSC_HAVE_STRICMP)
313: else c = stricmp(a,b);
314: #else
315: else c = strcasecmp(a,b);
316: #endif
317: if (!c) *t = PETSC_TRUE;
318: else *t = PETSC_FALSE;
319: return(0);
320: }
324: /*@C
325: PetscStrncmp - Compares two strings, up to a certain length
327: Not Collective
329: Input Parameters:
330: + a - pointer to first string
331: . b - pointer to second string
332: - n - length to compare up to
334: Output Parameter:
335: . t - if the two strings are equal
337: Level: intermediate
339: .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()
341: @*/
342: PetscErrorCode PetscStrncmp(const char a[],const char b[],size_t n,PetscTruth *t)
343: {
344: int c;
347: c = strncmp(a,b,n);
348: if (!c) *t = PETSC_TRUE;
349: else *t = PETSC_FALSE;
350: return(0);
351: }
355: /*@C
356: PetscStrchr - Locates first occurance of a character in a string
358: Not Collective
360: Input Parameters:
361: + a - pointer to string
362: - b - character
364: Output Parameter:
365: . c - location of occurance, PETSC_NULL if not found
367: Level: intermediate
369: @*/
370: PetscErrorCode PetscStrchr(const char a[],char b,char *c[])
371: {
373: *c = (char *)strchr(a,b);
374: return(0);
375: }
379: /*@C
380: PetscStrrchr - Locates one location past the last occurance of a character in a string,
381: if the character is not found then returns entire string
383: Not Collective
385: Input Parameters:
386: + a - pointer to string
387: - b - character
389: Output Parameter:
390: . tmp - location of occurance, a if not found
392: Level: intermediate
394: @*/
395: PetscErrorCode PetscStrrchr(const char a[],char b,char *tmp[])
396: {
398: *tmp = (char *)strrchr(a,b);
399: if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
400: return(0);
401: }
405: /*@C
406: PetscStrtolower - Converts string to lower case
408: Not Collective
410: Input Parameters:
411: . a - pointer to string
413: Level: intermediate
415: @*/
416: PetscErrorCode PetscStrtolower(char a[])
417: {
419: while (*a) {
420: if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
421: a++;
422: }
423: return(0);
424: }
428: /*@C
429: PetscTokenFind - Locates next "token" in a string
431: Not Collective
433: Input Parameters:
434: . a - pointer to token
436: Output Parameter:
437: . result - location of occurance, PETSC_NULL if not found
439: Notes:
441: This version is different from the system version in that
442: it allows you to pass a read-only string into the function.
444: Level: intermediate
446: .seealso: PetscTokenCreate(), PetscTokenDestroy()
447: @*/
448: PetscErrorCode PetscTokenFind(PetscToken *a,char *result[])
449: {
450: char *ptr = a->current;
453: *result = a->current;
454: if (ptr && !*ptr) *result = 0;
455: while (ptr) {
456: if (*ptr == a->token) {
457: *ptr++ = 0;
458: while (*ptr == a->token) ptr++;
459: a->current = ptr;
460: break;
461: }
462: if (!*ptr) {
463: a->current = 0;
464: break;
465: }
466: ptr++;
467: }
468: return(0);
469: }
473: /*@C
474: PetscTokenCreate - Creates a PetscToken used to find tokens in a string
476: Not Collective
478: Input Parameters:
479: + string - the string to look in
480: - token - the character to look for
482: Output Parameter:
483: . a - pointer to token
485: Notes:
487: This version is different from the system version in that
488: it allows you to pass a read-only string into the function.
490: Level: intermediate
492: .seealso: PetscTokenFind(), PetscTokenDestroy()
493: @*/
494: PetscErrorCode PetscTokenCreate(const char a[],const char b,PetscToken **t)
495: {
497: size_t len;
500: PetscNew(PetscToken,t);
501: PetscStrlen(a,&len);
502: PetscStrallocpy(a,&(*t)->array);
503: (*t)->current = (*t)->array;
504: (*t)->token = b;
505: return(0);
506: }
510: /*@C
511: PetscTokenDestroy - Destroys a PetscToken
513: Not Collective
515: Input Parameters:
516: . a - pointer to token
518: Level: intermediate
520: .seealso: PetscTokenCreate(), PetscTokenFind()
521: @*/
522: PetscErrorCode PetscTokenDestroy(PetscToken *a)
523: {
527: PetscFree(a->array);
528: PetscFree(a);
529: return(0);
530: }
534: /*@C
535: PetscStrstr - Locates first occurance of string in another string
537: Not Collective
539: Input Parameters:
540: + a - pointer to string
541: - b - string to find
543: Output Parameter:
544: . tmp - location of occurance
546: Level: intermediate
548: @*/
549: PetscErrorCode PetscStrstr(const char a[],const char b[],char *tmp[])
550: {
552: *tmp = (char *)strstr(a,b);
553: return(0);
554: }
558: /*@C
559: PetscGetPetscDir - Gets the directory PETSc is installed in
561: Not Collective
563: Output Parameter:
564: . dir - the directory
566: Level: developer
568: @*/
569: PetscErrorCode PetscGetPetscDir(const char *dir[])
570: {
572: *dir = PETSC_DIR;
573: return(0);
574: }
578: /*@C
579: PetscStrreplace - Replaces substrings in string with other substrings
581: Not Collective
583: Input Parameters:
584: + comm - MPI_Comm of processors that are processing the string
585: . a - the string to look in
586: . b - the resulting copy of a with replaced strings
587: - len - the length of b
589: Notes:
590: Replaces ${PETSC_ARCH},${BOPT},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
591: ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME} with appropriate values
592: as well as any environmental variables.
593:
594: Level: intermediate
596: @*/
597: PetscErrorCode PetscStrreplace(MPI_Comm comm,const char a[],char b[],size_t len)
598: {
600: int i = 0;
601: size_t l,l1,l2,l3;
602: char *work,*par,*epar,env[1024],*tfree;
603: const char *s[] = {"${PETSC_ARCH}","${BOPT}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}",0};
604: const char *r[] = {PETSC_ARCH,PETSC_BOPT,PETSC_DIR,PETSC_LIB_DIR,0,0,0,0,0};
605: PetscTruth flag;
608: if (!a || !b) SETERRQ(PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
609: PetscMalloc(len*sizeof(char*),&work);
611: /* get values for replaced variables */
612: PetscMalloc(256*sizeof(char),&r[4]);
613: PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);
614: PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[6]);
615: PetscMalloc(256*sizeof(char),&r[7]);
616: PetscGetDisplay((char*)r[4],256);
617: PetscGetHomeDirectory((char*)r[5],PETSC_MAX_PATH_LEN);
618: PetscGetWorkingDirectory((char*)r[6],PETSC_MAX_PATH_LEN);
619: PetscGetUserName((char*)r[7],256);
621: /* replace the requested strings */
622: PetscStrncpy(b,a,len);
623: while (s[i]) {
624: PetscStrlen(s[i],&l);
625: PetscStrstr(b,s[i],&par);
626: while (par) {
627: *par = 0;
628: par += l;
630: PetscStrlen(b,&l1);
631: PetscStrlen(r[i],&l2);
632: PetscStrlen(par,&l3);
633: if (l1 + l2 + l3 >= len) {
634: SETERRQ(PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
635: }
636: PetscStrcpy(work,b);
637: PetscStrcat(work,r[i]);
638: PetscStrcat(work,par);
639: PetscStrncpy(b,work,len);
640: PetscStrstr(b,s[i],&par);
641: }
642: i++;
643: }
644: for ( i=4; i<8; i++){
645: tfree = (char*)r[i];
646: PetscFree(tfree);
647: }
649: /* look for any other ${xxx} strings to replace from environmental variables */
650: PetscStrstr(b,"${",&par);
651: while (par) {
652: *par = 0;
653: par += 2;
654: PetscStrcpy(work,b);
655: PetscStrstr(par,"}",&epar);
656: *epar = 0;
657: epar += 1;
658: PetscOptionsGetenv(comm,par,env,256,&flag);
659: if (!flag) {
660: SETERRQ1(PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
661: }
662: PetscStrcat(work,env);
663: PetscStrcat(work,epar);
664: PetscStrcpy(b,work);
665: PetscStrstr(b,"${",&par);
666: }
667: PetscFree(work);
668: return(0);
669: }
671: /*MC
672: PetscStrfree - Frees a string (if it is not null)
674: Not Collective
676: Synopsis:
677: PetscErrorCode PetscStrfree(char *s)
679: Input Parameter:
680: . s - pointer to string
682: Level: intermediate
684: Concepts: string free
685:
686: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat(), PetscStrallocpy()
688: M*/