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.
5: */
6: #include <petsc/private/petscimpl.h>
7: #if defined(PETSC_HAVE_STRINGS_H)
8: #include <strings.h> /* strcasecmp */
9: #endif
11: /*@C
12: PetscStrToArray - Separates a string by a character (for example ' ' or '\n') and creates an array of strings
14: Not Collective; No Fortran Support
16: Input Parameters:
17: + s - pointer to string
18: - sp - separator character
20: Output Parameters:
21: + argc - the number of entries in `args`
22: - args - an array of the entries with a `NULL` at the end
24: Level: intermediate
26: Note:
27: This may be called before `PetscInitialize()` or after `PetscFinalize()`
29: Developer Notes:
30: Uses raw `malloc()` and does not call error handlers since this may be used before PETSc is initialized.
32: Used to generate `argc`, `args` arguments passed to `MPI_Init()`
34: .seealso: `PetscStrToArrayDestroy()`, `PetscToken`, `PetscTokenCreate()`
35: @*/
36: PetscErrorCode PetscStrToArray(const char s[], char sp, int *argc, char ***args)
37: {
38: int n, i, j, *lens, cnt = 0;
39: PetscBool flg = PETSC_FALSE;
41: if (!s) n = 0;
42: else n = (int)strlen(s);
43: *argc = 0;
44: *args = NULL;
45: for (; n > 0; n--) { /* remove separator chars at the end - and will empty the string if all chars are separator chars */
46: if (s[n - 1] != sp) break;
47: }
48: if (!n) return PETSC_SUCCESS;
49: for (i = 0; i < n; i++) {
50: if (s[i] != sp) break;
51: }
52: for (; i < n + 1; i++) {
53: if ((s[i] == sp || s[i] == 0) && !flg) {
54: flg = PETSC_TRUE;
55: (*argc)++;
56: } else if (s[i] != sp) {
57: flg = PETSC_FALSE;
58: }
59: }
60: (*args) = (char **)malloc(((*argc) + 1) * sizeof(char *));
61: if (!*args) return PETSC_ERR_MEM;
62: lens = (int *)malloc(((*argc) + 1) * sizeof(int));
63: if (!lens) return PETSC_ERR_MEM;
64: for (i = 0; i < *argc; i++) lens[i] = 0;
66: *argc = 0;
67: for (i = 0; i < n; i++) {
68: if (s[i] != sp) break;
69: }
70: for (; i < n + 1; i++) {
71: if ((s[i] == sp || s[i] == 0) && !flg) {
72: flg = PETSC_TRUE;
73: (*argc)++;
74: } else if (s[i] != sp) {
75: lens[*argc]++;
76: flg = PETSC_FALSE;
77: }
78: }
80: for (i = 0; i < *argc; i++) {
81: (*args)[i] = (char *)malloc((lens[i] + 1) * sizeof(char));
82: if (!(*args)[i]) {
83: free(lens);
84: for (j = 0; j < i; j++) free((*args)[j]);
85: free(*args);
86: return PETSC_ERR_MEM;
87: }
88: }
89: free(lens);
90: (*args)[*argc] = NULL;
92: *argc = 0;
93: for (i = 0; i < n; i++) {
94: if (s[i] != sp) break;
95: }
96: for (; i < n + 1; i++) {
97: if ((s[i] == sp || s[i] == 0) && !flg) {
98: flg = PETSC_TRUE;
99: (*args)[*argc][cnt++] = 0;
100: (*argc)++;
101: cnt = 0;
102: } else if (s[i] != sp && s[i] != 0) {
103: (*args)[*argc][cnt++] = s[i];
104: flg = PETSC_FALSE;
105: }
106: }
107: return PETSC_SUCCESS;
108: }
110: /*@C
111: PetscStrToArrayDestroy - Frees array created with `PetscStrToArray()`.
113: Not Collective; No Fortran Support
115: Output Parameters:
116: + argc - the number of arguments
117: - args - the array of arguments
119: Level: intermediate
121: Note:
122: This may be called before `PetscInitialize()` or after `PetscFinalize()`
124: .seealso: `PetscStrToArray()`
125: @*/
126: PetscErrorCode PetscStrToArrayDestroy(int argc, char **args)
127: {
128: for (int i = 0; i < argc; ++i) free(args[i]);
129: if (args) free(args);
130: return PETSC_SUCCESS;
131: }
133: /*@C
134: PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
136: Not Collective; No Fortran Support
138: Input Parameter:
139: . list - pointer to array of strings (final string is a `NULL`)
141: Output Parameter:
142: . t - the copied array string
144: Level: intermediate
146: Note:
147: Use `PetscStrArrayDestroy()` to free the memory.
149: .seealso: `PetscStrallocpy()`, `PetscStrArrayDestroy()`, `PetscStrNArrayallocpy()`
150: @*/
151: PetscErrorCode PetscStrArrayallocpy(const char *const *list, char ***t)
152: {
153: PetscInt n = 0;
155: PetscFunctionBegin;
156: while (list[n++]);
157: PetscCall(PetscMalloc1(n + 1, t));
158: for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
159: (*t)[n] = NULL;
160: PetscFunctionReturn(PETSC_SUCCESS);
161: }
163: /*@C
164: PetscStrArrayDestroy - Frees array of strings created with `PetscStrArrayallocpy()`.
166: Not Collective; No Fortran Support
168: Output Parameter:
169: . list - array of strings
171: Level: intermediate
173: .seealso: `PetscStrArrayallocpy()`
174: @*/
175: PetscErrorCode PetscStrArrayDestroy(char ***list)
176: {
177: PetscInt n = 0;
179: PetscFunctionBegin;
180: if (!*list) PetscFunctionReturn(PETSC_SUCCESS);
181: while ((*list)[n]) {
182: PetscCall(PetscFree((*list)[n]));
183: ++n;
184: }
185: PetscCall(PetscFree(*list));
186: PetscFunctionReturn(PETSC_SUCCESS);
187: }
189: /*@C
190: PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
192: Not Collective; No Fortran Support
194: Input Parameters:
195: + n - the number of string entries
196: - list - pointer to array of strings
198: Output Parameter:
199: . t - the copied array string
201: Level: intermediate
203: Note:
204: Use `PetscStrNArrayDestroy()` to free the memory.
206: .seealso: `PetscStrallocpy()`, `PetscStrArrayallocpy()`, `PetscStrNArrayDestroy()`
207: @*/
208: PetscErrorCode PetscStrNArrayallocpy(PetscInt n, const char *const *list, char ***t)
209: {
210: PetscFunctionBegin;
211: PetscCall(PetscMalloc1(n, t));
212: for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
213: PetscFunctionReturn(PETSC_SUCCESS);
214: }
216: /*@C
217: PetscStrNArrayDestroy - Frees array of strings created with `PetscStrNArrayallocpy()`.
219: Not Collective; No Fortran Support
221: Output Parameters:
222: + n - number of string entries
223: - list - array of strings
225: Level: intermediate
227: .seealso: `PetscStrNArrayallocpy()`, `PetscStrArrayallocpy()`
228: @*/
229: PetscErrorCode PetscStrNArrayDestroy(PetscInt n, char ***list)
230: {
231: PetscFunctionBegin;
232: if (!*list) PetscFunctionReturn(PETSC_SUCCESS);
233: for (PetscInt i = 0; i < n; i++) PetscCall(PetscFree((*list)[i]));
234: PetscCall(PetscFree(*list));
235: PetscFunctionReturn(PETSC_SUCCESS);
236: }
238: /*@C
239: PetscBasename - returns a pointer to the last entry of a / or \ separated directory path
241: Not Collective; No Fortran Support
243: Input Parameter:
244: . a - pointer to string
246: Level: intermediate
248: .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`, `PetscStrrchr()`, `PetscStrcmp()`, `PetscStrstr()`,
249: `PetscTokenCreate()`, `PetscStrToArray()`, `PetscStrInList()`
250: @*/
251: const char *PetscBasename(const char a[])
252: {
253: const char *ptr = NULL;
255: (void)PetscStrrchr(a, '/', (char **)&ptr);
256: if (ptr == a) {
257: if (PetscStrrchr(a, '\\', (char **)&ptr)) ptr = NULL;
258: }
259: return ptr;
260: }
262: /*@C
263: PetscStrcasecmp - Returns true if the two strings are the same
264: except possibly for case.
266: Not Collective; No Fortran Support
268: Input Parameters:
269: + a - pointer to first string
270: - b - pointer to second string
272: Output Parameter:
273: . t - if the two strings are the same
275: Level: intermediate
277: Note:
278: `NULL` arguments are ok
280: .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrgrt()`
281: @*/
282: PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t)
283: {
284: int c;
286: PetscFunctionBegin;
287: PetscAssertPointer(t, 3);
288: if (!a && !b) c = 0;
289: else if (!a || !b) c = 1;
290: #if defined(PETSC_HAVE_STRCASECMP)
291: else c = strcasecmp(a, b);
292: #elif defined(PETSC_HAVE_STRICMP)
293: else c = stricmp(a, b);
294: #else
295: else {
296: char *aa, *bb;
298: PetscCall(PetscStrallocpy(a, &aa));
299: PetscCall(PetscStrallocpy(b, &bb));
300: PetscCall(PetscStrtolower(aa));
301: PetscCall(PetscStrtolower(bb));
302: PetscCall(PetscStrcmp(aa, bb, t));
303: PetscCall(PetscFree(aa));
304: PetscCall(PetscFree(bb));
305: PetscFunctionReturn(PETSC_SUCCESS);
306: }
307: #endif
308: *t = c ? PETSC_FALSE : PETSC_TRUE;
309: PetscFunctionReturn(PETSC_SUCCESS);
310: }
312: /*@C
313: PetscStrendswithwhich - Determines if a string ends with one of several possible strings
315: Not Collective; No Fortran Support
317: Input Parameters:
318: + a - pointer to string
319: - bs - strings to end with (last entry must be `NULL`)
321: Output Parameter:
322: . cnt - the index of the string it ends with or the index of `NULL`
324: Level: intermediate
326: .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
327: `PetscStrncmp()`, `PetscStrlen()`, `PetscStrcmp()`
328: @*/
329: PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt)
330: {
331: PetscFunctionBegin;
332: PetscAssertPointer(bs, 2);
333: PetscAssertPointer(cnt, 3);
334: *cnt = 0;
335: while (bs[*cnt]) {
336: PetscBool flg;
338: PetscCall(PetscStrendswith(a, bs[*cnt], &flg));
339: if (flg) PetscFunctionReturn(PETSC_SUCCESS);
340: ++(*cnt);
341: }
342: PetscFunctionReturn(PETSC_SUCCESS);
343: }
345: struct _n_PetscToken {
346: char token;
347: char *array;
348: char *current;
349: };
351: /*@C
352: PetscTokenFind - Locates next "token" in a `PetscToken`
354: Not Collective; No Fortran Support
356: Input Parameter:
357: . a - pointer to token
359: Output Parameter:
360: . result - location of occurrence, `NULL` if not found
362: Level: intermediate
364: Notes:
365: Treats all characters etc. inside a double quote "
366: as a single token.
368: 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
369: second will return a `NULL` terminated y
371: 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
373: Do not change or free the value of `result`
375: .seealso: `PetscToken`, `PetscTokenCreate()`, `PetscTokenDestroy()`
376: @*/
377: PetscErrorCode PetscTokenFind(PetscToken a, const char *result[])
378: {
379: char *ptr, token;
381: PetscFunctionBegin;
382: PetscAssertPointer(a, 1);
383: PetscAssertPointer(result, 2);
384: *result = ptr = a->current;
385: if (ptr && !*ptr) {
386: *result = NULL;
387: PetscFunctionReturn(PETSC_SUCCESS);
388: }
389: token = a->token;
390: if (ptr && (*ptr == '"')) {
391: token = '"';
392: (*result)++;
393: ptr++;
394: }
395: while (ptr) {
396: if (*ptr == token) {
397: *ptr++ = 0;
398: while (*ptr == a->token) ptr++;
399: a->current = ptr;
400: break;
401: }
402: if (!*ptr) {
403: a->current = NULL;
404: break;
405: }
406: ptr++;
407: }
408: PetscFunctionReturn(PETSC_SUCCESS);
409: }
411: /*@C
412: PetscTokenCreate - Creates a `PetscToken` used to find tokens in a string
414: Not Collective; No Fortran Support
416: Input Parameters:
417: + a - the string to look in
418: - b - the separator character
420: Output Parameter:
421: . t - the token object
423: Level: intermediate
425: Note:
426: This version is different from the system version in that
427: it allows you to pass a read-only string into the function.
429: .seealso: `PetscToken`, `PetscTokenFind()`, `PetscTokenDestroy()`
430: @*/
431: PetscErrorCode PetscTokenCreate(const char a[], char b, PetscToken *t)
432: {
433: PetscFunctionBegin;
434: PetscAssertPointer(a, 1);
435: PetscAssertPointer(t, 3);
436: PetscCall(PetscNew(t));
437: PetscCall(PetscStrallocpy(a, &(*t)->array));
439: (*t)->current = (*t)->array;
440: (*t)->token = b;
441: PetscFunctionReturn(PETSC_SUCCESS);
442: }
444: /*@C
445: PetscTokenDestroy - Destroys a `PetscToken`
447: Not Collective; No Fortran Support
449: Input Parameter:
450: . a - pointer to token
452: Level: intermediate
454: .seealso: `PetscToken`, `PetscTokenCreate()`, `PetscTokenFind()`
455: @*/
456: PetscErrorCode PetscTokenDestroy(PetscToken *a)
457: {
458: PetscFunctionBegin;
459: if (!*a) PetscFunctionReturn(PETSC_SUCCESS);
460: PetscCall(PetscFree((*a)->array));
461: PetscCall(PetscFree(*a));
462: PetscFunctionReturn(PETSC_SUCCESS);
463: }
465: /*@C
466: PetscStrInList - search for a string in character-delimited list
468: Not Collective; No Fortran Support
470: Input Parameters:
471: + str - the string to look for
472: . list - the list to search in
473: - sep - the separator character
475: Output Parameter:
476: . found - whether `str` is in `list`
478: Level: intermediate
480: .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()`
481: @*/
482: PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found)
483: {
484: PetscToken token;
485: const char *item;
487: PetscFunctionBegin;
488: PetscAssertPointer(found, 4);
489: *found = PETSC_FALSE;
490: PetscCall(PetscTokenCreate(list, sep, &token));
491: PetscCall(PetscTokenFind(token, &item));
492: while (item) {
493: PetscCall(PetscStrcmp(str, item, found));
494: if (*found) break;
495: PetscCall(PetscTokenFind(token, &item));
496: }
497: PetscCall(PetscTokenDestroy(&token));
498: PetscFunctionReturn(PETSC_SUCCESS);
499: }
501: /*@C
502: PetscGetPetscDir - Gets the directory PETSc is installed in
504: Not Collective; No Fortran Support
506: Output Parameter:
507: . dir - the directory
509: Level: developer
511: .seealso: `PetscGetArchType()`
512: @*/
513: PetscErrorCode PetscGetPetscDir(const char *dir[])
514: {
515: PetscFunctionBegin;
516: PetscAssertPointer(dir, 1);
517: *dir = PETSC_DIR;
518: PetscFunctionReturn(PETSC_SUCCESS);
519: }
521: /*@C
522: PetscStrreplace - Replaces substrings in string with other substrings
524: Not Collective; No Fortran Support
526: Input Parameters:
527: + comm - `MPI_Comm` of processors that are processing the string
528: . aa - the string to look in
529: . b - the resulting copy of a with replaced strings (`b` can be the same as `a`)
530: - len - the length of `b`
532: Level: developer
534: Notes:
535: Replaces
536: .vb
537: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${DISPLAY},
538: ${HOMEDIRECTORY}, ${WORKINGDIRECTORY}, ${USERNAME}, ${HOSTNAME}, ${PETSC_MAKE}
539: .ve
540: with appropriate values as well as any environmental variables.
542: `PETSC_LIB_DIR` uses the environmental variable if it exists. `PETSC_ARCH` and `PETSC_DIR` use what
543: PETSc was built with and do not use environmental variables.
545: .seealso: `PetscStrcmp()`
546: @*/
547: PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len)
548: {
549: int i = 0;
550: size_t l, l1, l2, l3;
551: char *work, *par, *epar = NULL, env[1024], *tfree, *a = (char *)aa;
552: const char *s[] = {"${PETSC_ARCH}", "${PETSC_DIR}", "${PETSC_LIB_DIR}", "${DISPLAY}", "${HOMEDIRECTORY}", "${WORKINGDIRECTORY}", "${USERNAME}", "${HOSTNAME}", "${PETSC_MAKE}", NULL};
553: char *r[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
554: PetscBool flag;
555: static size_t DISPLAY_LENGTH = 265, USER_LENGTH = 256, HOST_LENGTH = 256;
557: PetscFunctionBegin;
558: PetscAssertPointer(aa, 2);
559: PetscAssertPointer(b, 3);
560: if (aa == b) PetscCall(PetscStrallocpy(aa, &a));
561: PetscCall(PetscMalloc1(len, &work));
563: /* get values for replaced variables */
564: PetscCall(PetscStrallocpy(PETSC_ARCH, &r[0]));
565: PetscCall(PetscStrallocpy(PETSC_DIR, &r[1]));
566: PetscCall(PetscStrallocpy(PETSC_LIB_DIR, &r[2]));
567: PetscCall(PetscMalloc1(DISPLAY_LENGTH, &r[3]));
568: PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[4]));
569: PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[5]));
570: PetscCall(PetscMalloc1(USER_LENGTH, &r[6]));
571: PetscCall(PetscMalloc1(HOST_LENGTH, &r[7]));
572: PetscCall(PetscGetDisplay(r[3], DISPLAY_LENGTH));
573: PetscCall(PetscGetHomeDirectory(r[4], PETSC_MAX_PATH_LEN));
574: PetscCall(PetscGetWorkingDirectory(r[5], PETSC_MAX_PATH_LEN));
575: PetscCall(PetscGetUserName(r[6], USER_LENGTH));
576: PetscCall(PetscGetHostName(r[7], HOST_LENGTH));
577: PetscCall(PetscStrallocpy(PETSC_OMAKE, &r[8]));
579: /* replace that are in environment */
580: PetscCall(PetscOptionsGetenv(comm, "PETSC_LIB_DIR", env, sizeof(env), &flag));
581: if (flag) {
582: PetscCall(PetscFree(r[2]));
583: PetscCall(PetscStrallocpy(env, &r[2]));
584: }
586: /* replace the requested strings */
587: PetscCall(PetscStrncpy(b, a, len));
588: while (s[i]) {
589: PetscCall(PetscStrlen(s[i], &l));
590: PetscCall(PetscStrstr(b, s[i], &par));
591: while (par) {
592: *par = 0;
593: par += l;
595: PetscCall(PetscStrlen(b, &l1));
596: PetscCall(PetscStrlen(r[i], &l2));
597: PetscCall(PetscStrlen(par, &l3));
598: PetscCheck(l1 + l2 + l3 < len, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "b len is not long enough to hold new values");
599: PetscCall(PetscStrncpy(work, b, len));
600: PetscCall(PetscStrlcat(work, r[i], len));
601: PetscCall(PetscStrlcat(work, par, len));
602: PetscCall(PetscStrncpy(b, work, len));
603: PetscCall(PetscStrstr(b, s[i], &par));
604: }
605: i++;
606: }
607: i = 0;
608: while (r[i]) {
609: tfree = r[i];
610: PetscCall(PetscFree(tfree));
611: i++;
612: }
614: /* look for any other ${xxx} strings to replace from environmental variables */
615: PetscCall(PetscStrstr(b, "${", &par));
616: while (par) {
617: *par = 0;
618: par += 2;
619: PetscCall(PetscStrncpy(work, b, len));
620: PetscCall(PetscStrstr(par, "}", &epar));
621: *epar = 0;
622: epar += 1;
623: PetscCall(PetscOptionsGetenv(comm, par, env, sizeof(env), &flag));
624: PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Substitution string ${%s} not found as environmental variable", par);
625: PetscCall(PetscStrlcat(work, env, len));
626: PetscCall(PetscStrlcat(work, epar, len));
627: PetscCall(PetscStrncpy(b, work, len));
628: PetscCall(PetscStrstr(b, "${", &par));
629: }
630: PetscCall(PetscFree(work));
631: if (aa == b) PetscCall(PetscFree(a));
632: PetscFunctionReturn(PETSC_SUCCESS);
633: }
635: /*@C
636: PetscStrcmpAny - Determines whether a string matches any of a list of strings.
638: Not Collective, No Fortran Support
640: Input Parameters:
641: + src - pointer to input the string
642: - cmp - list of non-null and non-empty strings to be compared against, pass the empty string "" to terminate the list
644: Output Parameter:
645: . match - `PETSC_TRUE` if the input string matches any in the list, else `PETSC_FALSE`
647: Level: intermediate
649: .seealso: `PetscStrcmp()`
650: @*/
651: PetscErrorCode PetscStrcmpAny(const char src[], PetscBool *match, const char cmp[], ...)
652: {
653: va_list Argp;
655: PetscFunctionBegin;
656: PetscAssertPointer(match, 2);
657: *match = PETSC_FALSE;
658: if (!src) PetscFunctionReturn(PETSC_SUCCESS);
659: va_start(Argp, cmp);
660: while (cmp && cmp[0]) {
661: PetscBool found;
662: PetscCall(PetscStrcmp(src, cmp, &found));
663: if (found) {
664: *match = PETSC_TRUE;
665: break;
666: }
667: cmp = va_arg(Argp, const char *);
668: }
669: va_end(Argp);
670: PetscFunctionReturn(PETSC_SUCCESS);
671: }
673: /*@C
674: PetscEListFind - searches list of strings for given string, using case insensitive matching
676: Not Collective; No Fortran Support
678: Input Parameters:
679: + n - number of strings in
680: . list - list of strings to search
681: - str - string to look for, empty string "" accepts default (first entry in list)
683: Output Parameters:
684: + value - index of matching string (if found)
685: - found - boolean indicating whether string was found (can be `NULL`)
687: Level: developer
689: .seealso: `PetscEnumFind()`
690: @*/
691: PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found)
692: {
693: PetscFunctionBegin;
694: if (found) {
695: PetscAssertPointer(found, 5);
696: *found = PETSC_FALSE;
697: }
698: for (PetscInt i = 0; i < n; ++i) {
699: PetscBool matched;
701: PetscCall(PetscStrcasecmp(str, list[i], &matched));
702: if (matched || !str[0]) {
703: if (found) *found = PETSC_TRUE;
704: *value = i;
705: break;
706: }
707: }
708: PetscFunctionReturn(PETSC_SUCCESS);
709: }
711: /*@C
712: PetscEnumFind - searches enum list of strings for given string, using case insensitive matching
714: Not Collective; No Fortran Support
716: Input Parameters:
717: + enumlist - list of strings to search, followed by enum name, then enum prefix, then `NULL`
718: - str - string to look for
720: Output Parameters:
721: + value - index of matching string (if found)
722: - found - boolean indicating whether string was found (can be `NULL`)
724: Level: advanced
726: .seealso: `PetscEListFind()`
727: @*/
728: PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found)
729: {
730: PetscInt n = 0, evalue;
731: PetscBool efound;
733: PetscFunctionBegin;
734: PetscAssertPointer(enumlist, 1);
735: while (enumlist[n++]) PetscCheck(n <= 50, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument appears to be wrong or have more than 50 entries");
736: PetscCheck(n >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
737: n -= 3; /* drop enum name, prefix, and null termination */
738: PetscCall(PetscEListFind(n, enumlist, str, &evalue, &efound));
739: if (efound) {
740: PetscAssertPointer(value, 3);
741: *value = (PetscEnum)evalue;
742: }
743: if (found) {
744: PetscAssertPointer(found, 4);
745: *found = efound;
746: }
747: PetscFunctionReturn(PETSC_SUCCESS);
748: }
750: /*@C
751: PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled.
753: Not Collective; No Fortran Support
755: Input Parameter:
756: . file - the file name
758: Level: developer
760: Note:
761: PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems
762: so that comparisons of output between runs are easy to make.
764: This mode is used for all tests in the test harness, it applies to both debug and optimized builds.
766: Use the option `-petsc_ci` to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for
767: all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness.
769: Always uses the Unix / as the file separate even on Microsoft Windows systems
771: The option `-petsc_ci_portable_error_output` attempts to output the same error messages on all systems for the test harness.
772: In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc
773: error handling by the test harness. This options also causes PETSc to attempt to return an error code of 0 so that the test
774: harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test
775: harness in the args: argument for specific examples. It will not necessarily produce portable output if different errors
776: (or no errors) occur on a subset of the MPI ranks.
778: .seealso: `PetscCILinenumber()`
779: @*/
780: const char *PetscCIFilename(const char *file)
781: {
782: if (!PetscCIEnabledPortableErrorOutput) return file;
783: return PetscBasename(file);
784: }
786: /*@C
787: PetscCILinenumber - returns a line number except if `PetscCIEnablePortableErrorOutput` is set when it returns 0
789: Not Collective; No Fortran Support
791: Input Parameter:
792: . linenumber - the initial line number
794: Level: developer
796: Note:
797: See `PetscCIFilename()` for details on usage
799: .seealso: `PetscCIFilename()`
800: @*/
801: int PetscCILinenumber(int linenumber)
802: {
803: if (!PetscCIEnabledPortableErrorOutput) return linenumber;
804: return 0;
805: }
807: /*@C
808: PetscStrcat - Concatenates a string onto a given string
810: Not Collective, No Fortran Support
812: Input Parameters:
813: + s - string to be added to
814: - t - pointer to string to be added to end
816: Level: deprecated (since 3.18.5)
818: Notes:
819: It is recommended you use `PetscStrlcat()` instead of this routine.
821: .seealso: `PetscStrlcat()`
822: @*/
823: PetscErrorCode PetscStrcat(char s[], const char t[])
824: {
825: PetscFunctionBegin;
826: if (!t) PetscFunctionReturn(PETSC_SUCCESS);
827: PetscAssertPointer(s, 1);
828: strcat(s, t);
829: PetscFunctionReturn(PETSC_SUCCESS);
830: }
832: /*@C
833: PetscStrcpy - Copies a string
835: Not Collective, No Fortran Support
837: Input Parameter:
838: . t - pointer to string
840: Output Parameter:
841: . s - the copied string
843: Level: deprecated (since 3.18.5)
845: Notes:
846: It is recommended you use `PetscStrncpy()` (equivalently `PetscArraycpy()` or
847: `PetscMemcpy()`) instead of this routine.
849: `NULL` strings returns a string starting with zero.
851: .seealso: `PetscStrncpy()`
852: @*/
853: PetscErrorCode PetscStrcpy(char s[], const char t[])
854: {
855: PetscFunctionBegin;
856: if (t) {
857: PetscAssertPointer(s, 1);
858: PetscAssertPointer(t, 2);
859: strcpy(s, t);
860: } else if (s) {
861: s[0] = '\0';
862: }
863: PetscFunctionReturn(PETSC_SUCCESS);
864: }