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 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
18: /*@C
19: PetscStrlen - Gets length of a string
21: Not Collective
23: Input Parameters:
24: . s - pointer to string
26: Output Parameter:
27: . len - length in bytes
29: Level: intermediate
31: Note:
32: This routine is analogous to strlen().
34: Null string returns a length of zero
36: Concepts: string length
37:
38: @*/
39: PetscErrorCode PetscStrlen(const char s[],size_t *len)
40: {
42: if (!s) {
43: *len = 0;
44: } else {
45: *len = strlen(s);
46: }
47: return(0);
48: }
52: /*@C
53: PetscStrallocpy - Allocates space to hold a copy of a string then copies the string
55: Not Collective
57: Input Parameters:
58: . s - pointer to string
60: Output Parameter:
61: . t - the copied string
63: Level: intermediate
65: Note:
66: Null string returns a new null string
68: Concepts: string copy
69:
70: @*/
71: PetscErrorCode PetscStrallocpy(const char s[],char *t[])
72: {
74: size_t len;
75: char *tmp = 0;
78: if (s) {
79: PetscStrlen(s,&len);
80: PetscMalloc((1+len)*sizeof(char),&tmp);
81: PetscStrcpy(tmp,s);
82: }
83: *t = tmp;
84: return(0);
85: }
89: /*@C
90: PetscStrcpy - Copies a string
92: Not Collective
94: Input Parameters:
95: . t - pointer to string
97: Output Parameter:
98: . s - the copied string
100: Level: intermediate
102: Note:
103: Null string returns a string starting with zero
105: Concepts: string copy
106:
107: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()
109: @*/
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 if (s) {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: + t - pointer to string
131: - n - the length to copy
133: Output Parameter:
134: . s - 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: if (t && !s) {
150: SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
151: }
152: if (t) {strncpy(s,t,n);}
153: else if (s) {s[0] = 0;}
154: return(0);
155: }
159: /*@C
160: PetscStrcat - Concatenates a string onto a given string
162: Not Collective
164: Input Parameters:
165: + s - string to be added to
166: - t - pointer to string to be added to end
168: Level: intermediate
170: Concepts: string copy
172: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
173:
174: @*/
175: PetscErrorCode PetscStrcat(char s[],const char t[])
176: {
178: if (!t) return(0);
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: This version also treats all characters etc. inside a double quote "
468: as a single token.
470: Level: intermediate
472: .seealso: PetscTokenCreate(), PetscTokenDestroy()
473: @*/
474: PetscErrorCode PetscTokenFind(PetscToken a,char *result[])
475: {
476: char *ptr = a->current,token;
479: *result = a->current;
480: if (ptr && !*ptr) {*result = 0;return(0);}
481: token = a->token;
482: if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
483: while (ptr) {
484: if (*ptr == token) {
485: *ptr++ = 0;
486: while (*ptr == a->token) ptr++;
487: a->current = ptr;
488: break;
489: }
490: if (!*ptr) {
491: a->current = 0;
492: break;
493: }
494: ptr++;
495: }
496: return(0);
497: }
501: /*@C
502: PetscTokenCreate - Creates a PetscToken used to find tokens in a string
504: Not Collective
506: Input Parameters:
507: + string - the string to look in
508: - token - the character to look for
510: Output Parameter:
511: . a - pointer to token
513: Notes:
515: This version is different from the system version in that
516: it allows you to pass a read-only string into the function.
518: Level: intermediate
520: .seealso: PetscTokenFind(), PetscTokenDestroy()
521: @*/
522: PetscErrorCode PetscTokenCreate(const char a[],const char b,PetscToken *t)
523: {
527: PetscNew(struct _p_PetscToken,t);
528: PetscStrallocpy(a,&(*t)->array);
529: (*t)->current = (*t)->array;
530: (*t)->token = b;
531: return(0);
532: }
536: /*@C
537: PetscTokenDestroy - Destroys a PetscToken
539: Not Collective
541: Input Parameters:
542: . a - pointer to token
544: Level: intermediate
546: .seealso: PetscTokenCreate(), PetscTokenFind()
547: @*/
548: PetscErrorCode PetscTokenDestroy(PetscToken a)
549: {
553: PetscFree(a->array);
554: PetscFree(a);
555: return(0);
556: }
560: /*@C
561: PetscStrrstr - Locates last occurance of string in another string
563: Not Collective
565: Input Parameters:
566: + a - pointer to string
567: - b - string to find
569: Output Parameter:
570: . tmp - location of occurance
572: Level: intermediate
574: @*/
575: PetscErrorCode PetscStrrstr(const char a[],const char b[],char *tmp[])
576: {
577: const char *stmp = a, *ltmp = 0;
580: while (stmp) {
581: stmp = (char *)strstr(stmp,b);
582: if (stmp) {ltmp = stmp;stmp++;}
583: }
584: *tmp = (char *)ltmp;
585: return(0);
586: }
590: /*@C
591: PetscStrstr - Locates first occurance of string in another string
593: Not Collective
595: Input Parameters:
596: + a - pointer to string
597: - b - string to find
599: Output Parameter:
600: . tmp - location of occurance
602: Level: intermediate
604: @*/
605: PetscErrorCode PetscStrstr(const char a[],const char b[],char *tmp[])
606: {
608: *tmp = (char *)strstr(a,b);
609: return(0);
610: }
614: /*@C
615: PetscGetPetscDir - Gets the directory PETSc is installed in
617: Not Collective
619: Output Parameter:
620: . dir - the directory
622: Level: developer
624: @*/
625: PetscErrorCode PetscGetPetscDir(const char *dir[])
626: {
628: *dir = PETSC_DIR;
629: return(0);
630: }
634: /*@C
635: PetscStrreplace - Replaces substrings in string with other substrings
637: Not Collective
639: Input Parameters:
640: + comm - MPI_Comm of processors that are processing the string
641: . aa - the string to look in
642: . b - the resulting copy of a with replaced strings (b can be the same as a)
643: - len - the length of b
645: Notes:
646: Replaces ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
647: ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME} with appropriate values
648: as well as any environmental variables.
650: Note: PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what
651: PETSc was built with and do not use environmental variables.
652:
653: Level: intermediate
655: @*/
656: PetscErrorCode PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
657: {
659: int i = 0;
660: size_t l,l1,l2,l3;
661: char *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
662: const char *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}",0};
663: const char *r[] = {0,0,0,0,0,0,0,0};
664: PetscTruth flag;
667: if (!a || !b) SETERRQ(PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
668: if (aa == b) {
669: PetscStrallocpy(aa,(char **)&a);
670: }
671: PetscMalloc(len*sizeof(char*),&work);
673: /* get values for replaced variables */
674: PetscStrallocpy(PETSC_ARCH,(char**)&r[0]);
675: PetscStrallocpy(PETSC_DIR,(char**)&r[1]);
676: PetscStrallocpy(PETSC_LIB_DIR,(char**)&r[2]);
677: PetscMalloc(256*sizeof(char),&r[3]);
678: PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[4]);
679: PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);
680: PetscMalloc(256*sizeof(char),&r[6]);
681: PetscGetDisplay((char*)r[3],256);
682: PetscGetHomeDirectory((char*)r[4],PETSC_MAX_PATH_LEN);
683: PetscGetWorkingDirectory((char*)r[5],PETSC_MAX_PATH_LEN);
684: PetscGetUserName((char*)r[6],256);
686: /* replace that are in environment */
687: PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);
688: if (flag) {
689: PetscStrallocpy(env,(char**)&r[2]);
690: }
692: /* replace the requested strings */
693: PetscStrncpy(b,a,len);
694: while (s[i]) {
695: PetscStrlen(s[i],&l);
696: PetscStrstr(b,s[i],&par);
697: while (par) {
698: *par = 0;
699: par += l;
701: PetscStrlen(b,&l1);
702: PetscStrlen(r[i],&l2);
703: PetscStrlen(par,&l3);
704: if (l1 + l2 + l3 >= len) {
705: SETERRQ(PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
706: }
707: PetscStrcpy(work,b);
708: PetscStrcat(work,r[i]);
709: PetscStrcat(work,par);
710: PetscStrncpy(b,work,len);
711: PetscStrstr(b,s[i],&par);
712: }
713: i++;
714: }
715: i = 0;
716: while (r[i]) {
717: tfree = (char*)r[i];
718: PetscFree(tfree);
719: i++;
720: }
722: /* look for any other ${xxx} strings to replace from environmental variables */
723: PetscStrstr(b,"${",&par);
724: while (par) {
725: *par = 0;
726: par += 2;
727: PetscStrcpy(work,b);
728: PetscStrstr(par,"}",&epar);
729: *epar = 0;
730: epar += 1;
731: PetscOptionsGetenv(comm,par,env,256,&flag);
732: if (!flag) {
733: SETERRQ1(PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
734: }
735: PetscStrcat(work,env);
736: PetscStrcat(work,epar);
737: PetscStrcpy(b,work);
738: PetscStrstr(b,"${",&par);
739: }
740: PetscFree(work);
741: if (aa == b) {
742: PetscFree(a);
743: }
744: return(0);
745: }
747: /*MC
748: PetscStrfree - Frees a string (if it is not null)
750: Not Collective
752: Synopsis:
753: PetscErrorCode PetscStrfree(char *s)
755: Input Parameter:
756: . s - pointer to string
758: Level: intermediate
760: Concepts: string free
761:
762: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat(), PetscStrallocpy()
764: M*/