Actual source code: str.c
petsc-3.11.4 2019-09-28
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> /* strstr */
11: #endif
12: #if defined(PETSC_HAVE_STRINGS_H)
13: # include <strings.h> /* strcasecmp */
14: #endif
16: /*@C
17: PetscStrToArray - Separates a string by a charactor (for example ' ' or '\n') and creates an array of strings
19: Not Collective
21: Input Parameters:
22: + s - pointer to string
23: - sp - separator charactor
25: Output Parameter:
26: + argc - the number of entries in the array
27: - args - an array of the entries with a null at the end
29: Level: intermediate
31: Notes:
32: this may be called before PetscInitialize() or after PetscFinalize()
34: Not for use in Fortran
36: Developer Notes:
37: Using raw malloc() and does not call error handlers since this may be used before PETSc is initialized. Used
38: to generate argc, args arguments passed to MPI_Init()
40: .seealso: PetscStrToArrayDestroy(), PetscToken, PetscTokenCreate()
42: @*/
43: PetscErrorCode PetscStrToArray(const char s[],char sp,int *argc,char ***args)
44: {
45: int i,j,n,*lens,cnt = 0;
46: PetscBool flg = PETSC_FALSE;
48: if (!s) n = 0;
49: else n = strlen(s);
50: *argc = 0;
51: *args = NULL;
52: for (; n>0; n--) { /* remove separator chars at the end - and will empty the string if all chars are separator chars */
53: if (s[n-1] != sp) break;
54: }
55: if (!n) {
56: return(0);
57: }
58: for (i=0; i<n; i++) {
59: if (s[i] != sp) break;
60: }
61: for (;i<n+1; i++) {
62: if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
63: else if (s[i] != sp) {flg = PETSC_FALSE;}
64: }
65: (*args) = (char**) malloc(((*argc)+1)*sizeof(char*)); if (!*args) return PETSC_ERR_MEM;
66: lens = (int*) malloc((*argc)*sizeof(int)); if (!lens) return PETSC_ERR_MEM;
67: for (i=0; i<*argc; i++) lens[i] = 0;
69: *argc = 0;
70: for (i=0; i<n; i++) {
71: if (s[i] != sp) break;
72: }
73: for (;i<n+1; i++) {
74: if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
75: else if (s[i] != sp) {lens[*argc]++;flg = PETSC_FALSE;}
76: }
78: for (i=0; i<*argc; i++) {
79: (*args)[i] = (char*) malloc((lens[i]+1)*sizeof(char));
80: if (!(*args)[i]) {
81: free(lens);
82: for (j=0; j<i; j++) free((*args)[j]);
83: free(*args);
84: return PETSC_ERR_MEM;
85: }
86: }
87: free(lens);
88: (*args)[*argc] = 0;
90: *argc = 0;
91: for (i=0; i<n; i++) {
92: if (s[i] != sp) break;
93: }
94: for (;i<n+1; i++) {
95: if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*args)[*argc][cnt++] = 0; (*argc)++; cnt = 0;}
96: else if (s[i] != sp && s[i] != 0) {(*args)[*argc][cnt++] = s[i]; flg = PETSC_FALSE;}
97: }
98: return 0;
99: }
101: /*@C
102: PetscStrToArrayDestroy - Frees array created with PetscStrToArray().
104: Not Collective
106: Output Parameters:
107: + argc - the number of arguments
108: - args - the array of arguments
110: Level: intermediate
112: Concepts: command line arguments
114: Notes:
115: This may be called before PetscInitialize() or after PetscFinalize()
117: Not for use in Fortran
119: .seealso: PetscStrToArray()
121: @*/
122: PetscErrorCode PetscStrToArrayDestroy(int argc,char **args)
123: {
124: PetscInt i;
126: for (i=0; i<argc; i++) free(args[i]);
127: if (args) free(args);
128: return 0;
129: }
131: /*@C
132: PetscStrlen - Gets length of a string
134: Not Collective
136: Input Parameters:
137: . s - pointer to string
139: Output Parameter:
140: . len - length in bytes
142: Level: intermediate
144: Note:
145: This routine is analogous to strlen().
147: Null string returns a length of zero
149: Not for use in Fortran
151: Concepts: string length
153: @*/
154: PetscErrorCode PetscStrlen(const char s[],size_t *len)
155: {
157: if (!s) *len = 0;
158: else *len = strlen(s);
159: return(0);
160: }
162: /*@C
163: PetscStrallocpy - Allocates space to hold a copy of a string then copies the string
165: Not Collective
167: Input Parameters:
168: . s - pointer to string
170: Output Parameter:
171: . t - the copied string
173: Level: intermediate
175: Note:
176: Null string returns a new null string
178: Not for use in Fortran
180: Concepts: string copy
182: @*/
183: PetscErrorCode PetscStrallocpy(const char s[],char *t[])
184: {
186: size_t len;
187: char *tmp = 0;
190: if (s) {
191: PetscStrlen(s,&len);
192: PetscMalloc1(1+len,&tmp);
193: PetscStrcpy(tmp,s);
194: }
195: *t = tmp;
196: return(0);
197: }
199: /*@C
200: PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
202: Not Collective
204: Input Parameters:
205: . s - pointer to array of strings (final string is a null)
207: Output Parameter:
208: . t - the copied array string
210: Level: intermediate
212: Note:
213: Not for use in Fortran
215: Concepts: string copy
217: .seealso: PetscStrallocpy() PetscStrArrayDestroy()
219: @*/
220: PetscErrorCode PetscStrArrayallocpy(const char *const *list,char ***t)
221: {
223: PetscInt i,n = 0;
226: while (list[n++]) ;
227: PetscMalloc1(n+1,t);
228: for (i=0; i<n; i++) {
229: PetscStrallocpy(list[i],(*t)+i);
230: }
231: (*t)[n] = NULL;
232: return(0);
233: }
235: /*@C
236: PetscStrArrayDestroy - Frees array of strings created with PetscStrArrayallocpy().
238: Not Collective
240: Output Parameters:
241: . list - array of strings
243: Level: intermediate
245: Concepts: command line arguments
247: Notes:
248: Not for use in Fortran
250: .seealso: PetscStrArrayallocpy()
252: @*/
253: PetscErrorCode PetscStrArrayDestroy(char ***list)
254: {
255: PetscInt n = 0;
259: if (!*list) return(0);
260: while ((*list)[n]) {
261: PetscFree((*list)[n]);
262: n++;
263: }
264: PetscFree(*list);
265: return(0);
266: }
268: /*@C
269: PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
271: Not Collective
273: Input Parameters:
274: + n - the number of string entries
275: - s - pointer to array of strings
277: Output Parameter:
278: . t - the copied array string
280: Level: intermediate
282: Note:
283: Not for use in Fortran
285: Concepts: string copy
287: .seealso: PetscStrallocpy() PetscStrArrayDestroy()
289: @*/
290: PetscErrorCode PetscStrNArrayallocpy(PetscInt n,const char *const *list,char ***t)
291: {
293: PetscInt i;
296: PetscMalloc1(n,t);
297: for (i=0; i<n; i++) {
298: PetscStrallocpy(list[i],(*t)+i);
299: }
300: return(0);
301: }
303: /*@C
304: PetscStrNArrayDestroy - Frees array of strings created with PetscStrArrayallocpy().
306: Not Collective
308: Output Parameters:
309: + n - number of string entries
310: - list - array of strings
312: Level: intermediate
314: Notes:
315: Not for use in Fortran
317: .seealso: PetscStrArrayallocpy()
319: @*/
320: PetscErrorCode PetscStrNArrayDestroy(PetscInt n,char ***list)
321: {
323: PetscInt i;
326: if (!*list) return(0);
327: for (i=0; i<n; i++){
328: PetscFree((*list)[i]);
329: }
330: PetscFree(*list);
331: return(0);
332: }
334: /*@C
335: PetscStrcpy - Copies a string
337: Not Collective
339: Input Parameters:
340: . t - pointer to string
342: Output Parameter:
343: . s - the copied string
345: Level: intermediate
347: Notes:
348: Null string returns a string starting with zero
350: Not for use in Fortran
352: Concepts: string copy
354: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrlcat()
356: @*/
358: PetscErrorCode PetscStrcpy(char s[],const char t[])
359: {
361: if (t && !s) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
362: if (t) strcpy(s,t);
363: else if (s) s[0] = 0;
364: return(0);
365: }
367: /*@C
368: PetscStrncpy - Copies a string up to a certain length
370: Not Collective
372: Input Parameters:
373: + t - pointer to string
374: - n - the length to copy
376: Output Parameter:
377: . s - the copied string
379: Level: intermediate
381: Note:
382: Null string returns a string starting with zero
384: If the string that is being copied is of length n or larger then the entire string is not
385: copied and the final location of s is set to NULL. This is different then the behavior of
386: strncpy() which leaves s non-terminated if there is not room for the entire string.
388: Concepts: string copy
390: Developers Note: Should this be PetscStrlcpy() to reflect its behavior which is like strlcpy() not strncpy()
392: .seealso: PetscStrcpy(), PetscStrcat(), PetscStrlcat()
394: @*/
395: PetscErrorCode PetscStrncpy(char s[],const char t[],size_t n)
396: {
398: if (t && !s) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
399: if (s && !n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Requires an output string of length at least 1 to hold the termination character");
400: if (t) {
401: if (n > 1) {
402: strncpy(s,t,n-1);
403: s[n-1] = '\0';
404: } else {
405: s[0] = '\0';
406: }
407: } else if (s) s[0] = 0;
408: return(0);
409: }
411: /*@C
412: PetscStrcat - Concatenates a string onto a given string
414: Not Collective
416: Input Parameters:
417: + s - string to be added to
418: - t - pointer to string to be added to end
420: Level: intermediate
422: Notes:
423: Not for use in Fortran
425: Concepts: string copy
427: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrlcat()
429: @*/
430: PetscErrorCode PetscStrcat(char s[],const char t[])
431: {
433: if (!t) return(0);
434: strcat(s,t);
435: return(0);
436: }
438: /*@C
439: PetscStrlcat - Concatenates a string onto a given string, up to a given length
441: Not Collective
443: Input Parameters:
444: + s - pointer to string to be added to at end
445: . t - string to be added to
446: - n - length of the original allocated string
448: Level: intermediate
450: Notes:
451: Not for use in Fortran
453: Unlike the system call strncat(), the length passed in is the length of the
454: original allocated space, not the length of the left-over space. This is
455: similar to the BSD system call strlcat().
457: Concepts: string copy
459: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
461: @*/
462: PetscErrorCode PetscStrlcat(char s[],const char t[],size_t n)
463: {
464: size_t len;
468: if (t && !n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"String buffer length must be positive");
469: if (!t) return(0);
470: PetscStrlen(t,&len);
471: strncat(s,t,n - len);
472: s[n-1] = 0;
473: return(0);
474: }
476: void PetscStrcmpNoError(const char a[],const char b[],PetscBool *flg)
477: {
478: int c;
480: if (!a && !b) *flg = PETSC_TRUE;
481: else if (!a || !b) *flg = PETSC_FALSE;
482: else {
483: c = strcmp(a,b);
484: if (c) *flg = PETSC_FALSE;
485: else *flg = PETSC_TRUE;
486: }
487: }
489: /*@C
490: PetscStrcmp - Compares two strings,
492: Not Collective
494: Input Parameters:
495: + a - pointer to string first string
496: - b - pointer to second string
498: Output Parameter:
499: . flg - PETSC_TRUE if the two strings are equal
501: Level: intermediate
503: Notes:
504: Not for use in Fortran
506: .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()
508: @*/
509: PetscErrorCode PetscStrcmp(const char a[],const char b[],PetscBool *flg)
510: {
511: int c;
514: if (!a && !b) *flg = PETSC_TRUE;
515: else if (!a || !b) *flg = PETSC_FALSE;
516: else {
517: c = strcmp(a,b);
518: if (c) *flg = PETSC_FALSE;
519: else *flg = PETSC_TRUE;
520: }
521: return(0);
522: }
524: /*@C
525: PetscStrgrt - If first string is greater than the second
527: Not Collective
529: Input Parameters:
530: + a - pointer to first string
531: - b - pointer to second string
533: Output Parameter:
534: . flg - if the first string is greater
536: Notes:
537: Null arguments are ok, a null string is considered smaller than
538: all others
540: Not for use in Fortran
542: Level: intermediate
544: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()
546: @*/
547: PetscErrorCode PetscStrgrt(const char a[],const char b[],PetscBool *t)
548: {
549: int c;
552: if (!a && !b) *t = PETSC_FALSE;
553: else if (a && !b) *t = PETSC_TRUE;
554: else if (!a && b) *t = PETSC_FALSE;
555: else {
556: c = strcmp(a,b);
557: if (c > 0) *t = PETSC_TRUE;
558: else *t = PETSC_FALSE;
559: }
560: return(0);
561: }
563: /*@C
564: PetscStrcasecmp - Returns true if the two strings are the same
565: except possibly for case.
567: Not Collective
569: Input Parameters:
570: + a - pointer to first string
571: - b - pointer to second string
573: Output Parameter:
574: . flg - if the two strings are the same
576: Notes:
577: Null arguments are ok
579: Not for use in Fortran
581: Level: intermediate
583: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()
585: @*/
586: PetscErrorCode PetscStrcasecmp(const char a[],const char b[],PetscBool *t)
587: {
588: int c;
591: if (!a && !b) c = 0;
592: else if (!a || !b) c = 1;
593: #if defined(PETSC_HAVE_STRCASECMP)
594: else c = strcasecmp(a,b);
595: #elif defined(PETSC_HAVE_STRICMP)
596: else c = stricmp(a,b);
597: #else
598: else {
599: char *aa,*bb;
601: PetscStrallocpy(a,&aa);
602: PetscStrallocpy(b,&bb);
603: PetscStrtolower(aa);
604: PetscStrtolower(bb);
605: PetscStrcmp(aa,bb,t);
606: PetscFree(aa);
607: PetscFree(bb);
608: return(0);
609: }
610: #endif
611: if (!c) *t = PETSC_TRUE;
612: else *t = PETSC_FALSE;
613: return(0);
614: }
618: /*@C
619: PetscStrncmp - Compares two strings, up to a certain length
621: Not Collective
623: Input Parameters:
624: + a - pointer to first string
625: . b - pointer to second string
626: - n - length to compare up to
628: Output Parameter:
629: . t - if the two strings are equal
631: Level: intermediate
633: Notes:
634: Not for use in Fortran
636: .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()
638: @*/
639: PetscErrorCode PetscStrncmp(const char a[],const char b[],size_t n,PetscBool *t)
640: {
641: int c;
644: c = strncmp(a,b,n);
645: if (!c) *t = PETSC_TRUE;
646: else *t = PETSC_FALSE;
647: return(0);
648: }
650: /*@C
651: PetscStrchr - Locates first occurance of a character in a string
653: Not Collective
655: Input Parameters:
656: + a - pointer to string
657: - b - character
659: Output Parameter:
660: . c - location of occurance, NULL if not found
662: Level: intermediate
664: Notes:
665: Not for use in Fortran
667: @*/
668: PetscErrorCode PetscStrchr(const char a[],char b,char *c[])
669: {
671: *c = (char*)strchr(a,b);
672: return(0);
673: }
675: /*@C
676: PetscStrrchr - Locates one location past the last occurance of a character in a string,
677: if the character is not found then returns entire string
679: Not Collective
681: Input Parameters:
682: + a - pointer to string
683: - b - character
685: Output Parameter:
686: . tmp - location of occurance, a if not found
688: Level: intermediate
690: Notes:
691: Not for use in Fortran
693: @*/
694: PetscErrorCode PetscStrrchr(const char a[],char b,char *tmp[])
695: {
697: *tmp = (char*)strrchr(a,b);
698: if (!*tmp) *tmp = (char*)a;
699: else *tmp = *tmp + 1;
700: return(0);
701: }
703: /*@C
704: PetscStrtolower - Converts string to lower case
706: Not Collective
708: Input Parameters:
709: . a - pointer to string
711: Level: intermediate
713: Notes:
714: Not for use in Fortran
716: @*/
717: PetscErrorCode PetscStrtolower(char a[])
718: {
720: while (*a) {
721: if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
722: a++;
723: }
724: return(0);
725: }
727: /*@C
728: PetscStrtoupper - Converts string to upper case
730: Not Collective
732: Input Parameters:
733: . a - pointer to string
735: Level: intermediate
737: Notes:
738: Not for use in Fortran
740: @*/
741: PetscErrorCode PetscStrtoupper(char a[])
742: {
744: while (*a) {
745: if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a';
746: a++;
747: }
748: return(0);
749: }
751: /*@C
752: PetscStrendswith - Determines if a string ends with a certain string
754: Not Collective
756: Input Parameters:
757: + a - pointer to string
758: - b - string to endwith
760: Output Parameter:
761: . flg - PETSC_TRUE or PETSC_FALSE
763: Notes:
764: Not for use in Fortran
766: Level: intermediate
768: @*/
769: PetscErrorCode PetscStrendswith(const char a[],const char b[],PetscBool *flg)
770: {
771: char *test;
773: size_t na,nb;
776: *flg = PETSC_FALSE;
777: PetscStrrstr(a,b,&test);
778: if (test) {
779: PetscStrlen(a,&na);
780: PetscStrlen(b,&nb);
781: if (a+na-nb == test) *flg = PETSC_TRUE;
782: }
783: return(0);
784: }
786: /*@C
787: PetscStrbeginswith - Determines if a string begins with a certain string
789: Not Collective
791: Input Parameters:
792: + a - pointer to string
793: - b - string to begin with
795: Output Parameter:
796: . flg - PETSC_TRUE or PETSC_FALSE
798: Notes:
799: Not for use in Fortran
801: Level: intermediate
803: .seealso: PetscStrendswithwhich(), PetscStrendswith(), PetscStrtoupper, PetscStrtolower(), PetscStrrchr(), PetscStrchr(),
804: PetscStrncmp(), PetscStrlen(), PetscStrncmp(), PetscStrcmp()
806: @*/
807: PetscErrorCode PetscStrbeginswith(const char a[],const char b[],PetscBool *flg)
808: {
809: char *test;
813: *flg = PETSC_FALSE;
814: PetscStrrstr(a,b,&test);
815: if (test && (test == a)) *flg = PETSC_TRUE;
816: return(0);
817: }
820: /*@C
821: PetscStrendswithwhich - Determines if a string ends with one of several possible strings
823: Not Collective
825: Input Parameters:
826: + a - pointer to string
827: - bs - strings to endwith (last entry must be null)
829: Output Parameter:
830: . cnt - the index of the string it ends with or 1+the last possible index
832: Notes:
833: Not for use in Fortran
835: Level: intermediate
837: @*/
838: PetscErrorCode PetscStrendswithwhich(const char a[],const char *const *bs,PetscInt *cnt)
839: {
840: PetscBool flg;
844: *cnt = 0;
845: while (bs[*cnt]) {
846: PetscStrendswith(a,bs[*cnt],&flg);
847: if (flg) return(0);
848: *cnt += 1;
849: }
850: return(0);
851: }
853: /*@C
854: PetscStrrstr - Locates last occurance of string in another string
856: Not Collective
858: Input Parameters:
859: + a - pointer to string
860: - b - string to find
862: Output Parameter:
863: . tmp - location of occurance
865: Notes:
866: Not for use in Fortran
868: Level: intermediate
870: @*/
871: PetscErrorCode PetscStrrstr(const char a[],const char b[],char *tmp[])
872: {
873: const char *stmp = a, *ltmp = 0;
876: while (stmp) {
877: stmp = (char*)strstr(stmp,b);
878: if (stmp) {ltmp = stmp;stmp++;}
879: }
880: *tmp = (char*)ltmp;
881: return(0);
882: }
884: /*@C
885: PetscStrstr - Locates first occurance of string in another string
887: Not Collective
889: Input Parameters:
890: + haystack - string to search
891: - needle - string to find
893: Output Parameter:
894: . tmp - location of occurance, is a NULL if the string is not found
896: Notes:
897: Not for use in Fortran
899: Level: intermediate
901: @*/
902: PetscErrorCode PetscStrstr(const char haystack[],const char needle[],char *tmp[])
903: {
905: *tmp = (char*)strstr(haystack,needle);
906: return(0);
907: }
909: struct _p_PetscToken {char token;char *array;char *current;};
911: /*@C
912: PetscTokenFind - Locates next "token" in a string
914: Not Collective
916: Input Parameters:
917: . a - pointer to token
919: Output Parameter:
920: . result - location of occurance, NULL if not found
922: Notes:
924: This version is different from the system version in that
925: it allows you to pass a read-only string into the function.
927: This version also treats all characters etc. inside a double quote "
928: as a single token.
930: For example if the separator character is + and the string is xxxx+y then the first fine will return a pointer to a null terminated xxxx and the
931: second will return a null terminated y
933: If the separator character is + and the string is xxxx then the first and only token found will be a pointer to a null terminated xxxx
935: Not for use in Fortran
937: Level: intermediate
940: .seealso: PetscTokenCreate(), PetscTokenDestroy()
941: @*/
942: PetscErrorCode PetscTokenFind(PetscToken a,char *result[])
943: {
944: char *ptr = a->current,token;
947: *result = a->current;
948: if (ptr && !*ptr) {*result = 0;return(0);}
949: token = a->token;
950: if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
951: while (ptr) {
952: if (*ptr == token) {
953: *ptr++ = 0;
954: while (*ptr == a->token) ptr++;
955: a->current = ptr;
956: break;
957: }
958: if (!*ptr) {
959: a->current = 0;
960: break;
961: }
962: ptr++;
963: }
964: return(0);
965: }
967: /*@C
968: PetscTokenCreate - Creates a PetscToken used to find tokens in a string
970: Not Collective
972: Input Parameters:
973: + string - the string to look in
974: - b - the separator character
976: Output Parameter:
977: . t- the token object
979: Notes:
981: This version is different from the system version in that
982: it allows you to pass a read-only string into the function.
984: Not for use in Fortran
986: Level: intermediate
988: .seealso: PetscTokenFind(), PetscTokenDestroy()
989: @*/
990: PetscErrorCode PetscTokenCreate(const char a[],const char b,PetscToken *t)
991: {
995: PetscNew(t);
996: PetscStrallocpy(a,&(*t)->array);
998: (*t)->current = (*t)->array;
999: (*t)->token = b;
1000: return(0);
1001: }
1003: /*@C
1004: PetscTokenDestroy - Destroys a PetscToken
1006: Not Collective
1008: Input Parameters:
1009: . a - pointer to token
1011: Level: intermediate
1013: Notes:
1014: Not for use in Fortran
1016: .seealso: PetscTokenCreate(), PetscTokenFind()
1017: @*/
1018: PetscErrorCode PetscTokenDestroy(PetscToken *a)
1019: {
1023: if (!*a) return(0);
1024: PetscFree((*a)->array);
1025: PetscFree(*a);
1026: return(0);
1027: }
1029: /*@C
1030: PetscStrInList - search string in character-delimited list
1032: Not Collective
1034: Input Parameters:
1035: + str - the string to look for
1036: . list - the list to search in
1037: - sep - the separator character
1039: Output Parameter:
1040: . found - whether str is in list
1042: Level: intermediate
1044: Notes:
1045: Not for use in Fortran
1047: .seealso: PetscTokenCreate(), PetscTokenFind(), PetscStrcmp()
1048: @*/
1049: PetscErrorCode PetscStrInList(const char str[],const char list[],char sep,PetscBool *found)
1050: {
1051: PetscToken token;
1052: char *item;
1056: *found = PETSC_FALSE;
1057: PetscTokenCreate(list,sep,&token);
1058: PetscTokenFind(token,&item);
1059: while (item) {
1060: PetscStrcmp(str,item,found);
1061: if (*found) break;
1062: PetscTokenFind(token,&item);
1063: }
1064: PetscTokenDestroy(&token);
1065: return(0);
1066: }
1068: /*@C
1069: PetscGetPetscDir - Gets the directory PETSc is installed in
1071: Not Collective
1073: Output Parameter:
1074: . dir - the directory
1076: Level: developer
1078: Notes:
1079: Not for use in Fortran
1081: @*/
1082: PetscErrorCode PetscGetPetscDir(const char *dir[])
1083: {
1085: *dir = PETSC_DIR;
1086: return(0);
1087: }
1089: /*@C
1090: PetscStrreplace - Replaces substrings in string with other substrings
1092: Not Collective
1094: Input Parameters:
1095: + comm - MPI_Comm of processors that are processing the string
1096: . aa - the string to look in
1097: . b - the resulting copy of a with replaced strings (b can be the same as a)
1098: - len - the length of b
1100: Notes:
1101: Replaces ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
1102: ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values
1103: as well as any environmental variables.
1105: PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what
1106: PETSc was built with and do not use environmental variables.
1108: Not for use in Fortran
1110: Level: intermediate
1112: @*/
1113: PetscErrorCode PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len)
1114: {
1116: int i = 0;
1117: size_t l,l1,l2,l3;
1118: char *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
1119: const char *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}","${HOSTNAME}",0};
1120: char *r[] = {0,0,0,0,0,0,0,0,0};
1121: PetscBool flag;
1124: if (!a || !b) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
1125: if (aa == b) {
1126: PetscStrallocpy(aa,(char**)&a);
1127: }
1128: PetscMalloc1(len,&work);
1130: /* get values for replaced variables */
1131: PetscStrallocpy(PETSC_ARCH,&r[0]);
1132: PetscStrallocpy(PETSC_DIR,&r[1]);
1133: PetscStrallocpy(PETSC_LIB_DIR,&r[2]);
1134: PetscMalloc1(256,&r[3]);
1135: PetscMalloc1(PETSC_MAX_PATH_LEN,&r[4]);
1136: PetscMalloc1(PETSC_MAX_PATH_LEN,&r[5]);
1137: PetscMalloc1(256,&r[6]);
1138: PetscMalloc1(256,&r[7]);
1139: PetscGetDisplay(r[3],256);
1140: PetscGetHomeDirectory(r[4],PETSC_MAX_PATH_LEN);
1141: PetscGetWorkingDirectory(r[5],PETSC_MAX_PATH_LEN);
1142: PetscGetUserName(r[6],256);
1143: PetscGetHostName(r[7],256);
1145: /* replace that are in environment */
1146: PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,1024,&flag);
1147: if (flag) {
1148: PetscFree(r[2]);
1149: PetscStrallocpy(env,&r[2]);
1150: }
1152: /* replace the requested strings */
1153: PetscStrncpy(b,a,len);
1154: while (s[i]) {
1155: PetscStrlen(s[i],&l);
1156: PetscStrstr(b,s[i],&par);
1157: while (par) {
1158: *par = 0;
1159: par += l;
1161: PetscStrlen(b,&l1);
1162: PetscStrlen(r[i],&l2);
1163: PetscStrlen(par,&l3);
1164: if (l1 + l2 + l3 >= len) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
1165: PetscStrcpy(work,b);
1166: PetscStrcat(work,r[i]);
1167: PetscStrcat(work,par);
1168: PetscStrncpy(b,work,len);
1169: PetscStrstr(b,s[i],&par);
1170: }
1171: i++;
1172: }
1173: i = 0;
1174: while (r[i]) {
1175: tfree = (char*)r[i];
1176: PetscFree(tfree);
1177: i++;
1178: }
1180: /* look for any other ${xxx} strings to replace from environmental variables */
1181: PetscStrstr(b,"${",&par);
1182: while (par) {
1183: *par = 0;
1184: par += 2;
1185: PetscStrcpy(work,b);
1186: PetscStrstr(par,"}",&epar);
1187: *epar = 0;
1188: epar += 1;
1189: PetscOptionsGetenv(comm,par,env,256,&flag);
1190: if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
1191: PetscStrcat(work,env);
1192: PetscStrcat(work,epar);
1193: PetscStrcpy(b,work);
1194: PetscStrstr(b,"${",&par);
1195: }
1196: PetscFree(work);
1197: if (aa == b) {
1198: PetscFree(a);
1199: }
1200: return(0);
1201: }
1203: /*@C
1204: PetscEListFind - searches list of strings for given string, using case insensitive matching
1206: Not Collective
1208: Input Parameters:
1209: + n - number of strings in
1210: . list - list of strings to search
1211: - str - string to look for, empty string "" accepts default (first entry in list)
1213: Output Parameters:
1214: + value - index of matching string (if found)
1215: - found - boolean indicating whether string was found (can be NULL)
1217: Notes:
1218: Not for use in Fortran
1220: Level: advanced
1221: @*/
1222: PetscErrorCode PetscEListFind(PetscInt n,const char *const *list,const char *str,PetscInt *value,PetscBool *found)
1223: {
1225: PetscBool matched;
1226: PetscInt i;
1229: if (found) *found = PETSC_FALSE;
1230: for (i=0; i<n; i++) {
1231: PetscStrcasecmp(str,list[i],&matched);
1232: if (matched || !str[0]) {
1233: if (found) *found = PETSC_TRUE;
1234: *value = i;
1235: break;
1236: }
1237: }
1238: return(0);
1239: }
1241: /*@C
1242: PetscEnumFind - searches enum list of strings for given string, using case insensitive matching
1244: Not Collective
1246: Input Parameters:
1247: + enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL
1248: - str - string to look for
1250: Output Parameters:
1251: + value - index of matching string (if found)
1252: - found - boolean indicating whether string was found (can be NULL)
1254: Notes:
1255: Not for use in Fortran
1257: Level: advanced
1258: @*/
1259: PetscErrorCode PetscEnumFind(const char *const *enumlist,const char *str,PetscEnum *value,PetscBool *found)
1260: {
1262: PetscInt n = 0,evalue;
1263: PetscBool efound;
1266: while (enumlist[n++]) if (n > 50) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument appears to be wrong or have more than 50 entries");
1267: if (n < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument must have at least two entries: typename and type prefix");
1268: n -= 3; /* drop enum name, prefix, and null termination */
1269: PetscEListFind(n,enumlist,str,&evalue,&efound);
1270: if (efound) *value = (PetscEnum)evalue;
1271: if (found) *found = efound;
1272: return(0);
1273: }