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 the array
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 i, j, n, *lens, cnt = 0;
39: PetscBool flg = PETSC_FALSE;
41: if (!s) n = 0;
42: else n = 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) * 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: If `t` has previously been allocated then that memory is lost, you may need to `PetscStrArrayDestroy()`
148: the array before calling this routine.
150: .seealso: `PetscStrallocpy()`, `PetscStrArrayDestroy()`, `PetscStrNArrayallocpy()`
151: @*/
152: PetscErrorCode PetscStrArrayallocpy(const char *const *list, char ***t)
153: {
154: PetscInt n = 0;
156: PetscFunctionBegin;
157: while (list[n++])
158: ;
159: PetscCall(PetscMalloc1(n + 1, t));
160: for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
161: (*t)[n] = NULL;
162: PetscFunctionReturn(PETSC_SUCCESS);
163: }
165: /*@C
166: PetscStrArrayDestroy - Frees array of strings created with `PetscStrArrayallocpy()`.
168: Not Collective; No Fortran Support
170: Output Parameter:
171: . list - array of strings
173: Level: intermediate
175: .seealso: `PetscStrArrayallocpy()`
176: @*/
177: PetscErrorCode PetscStrArrayDestroy(char ***list)
178: {
179: PetscInt n = 0;
181: PetscFunctionBegin;
182: if (!*list) PetscFunctionReturn(PETSC_SUCCESS);
183: while ((*list)[n]) {
184: PetscCall(PetscFree((*list)[n]));
185: ++n;
186: }
187: PetscCall(PetscFree(*list));
188: PetscFunctionReturn(PETSC_SUCCESS);
189: }
191: /*@C
192: PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
194: Not Collective; No Fortran Support
196: Input Parameters:
197: + n - the number of string entries
198: - list - pointer to array of strings
200: Output Parameter:
201: . t - the copied array string
203: Level: intermediate
205: .seealso: `PetscStrallocpy()`, `PetscStrArrayallocpy()`, `PetscStrNArrayDestroy()`
206: @*/
207: PetscErrorCode PetscStrNArrayallocpy(PetscInt n, const char *const *list, char ***t)
208: {
209: PetscFunctionBegin;
210: PetscCall(PetscMalloc1(n, t));
211: for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
212: PetscFunctionReturn(PETSC_SUCCESS);
213: }
215: /*@C
216: PetscStrNArrayDestroy - Frees array of strings created with `PetscStrNArrayallocpy()`.
218: Not Collective; No Fortran Support
220: Output Parameters:
221: + n - number of string entries
222: - list - array of strings
224: Level: intermediate
226: .seealso: `PetscStrNArrayallocpy()`, `PetscStrArrayallocpy()`
227: @*/
228: PetscErrorCode PetscStrNArrayDestroy(PetscInt n, char ***list)
229: {
230: PetscFunctionBegin;
231: if (!*list) PetscFunctionReturn(PETSC_SUCCESS);
232: for (PetscInt i = 0; i < n; i++) PetscCall(PetscFree((*list)[i]));
233: PetscCall(PetscFree(*list));
234: PetscFunctionReturn(PETSC_SUCCESS);
235: }
237: /*@C
238: PetscBasename - returns a pointer to the last entry of a / or \ separated directory path
240: Not Collective; No Fortran Support
242: Input Parameter:
243: . a - pointer to string
245: Level: intermediate
247: .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`, `PetscStrrchr()`, `PetscStrcmp()`, `PetscStrstr()`,
248: `PetscTokenCreate()`, `PetscStrToArray()`, `PetscStrInList()`
249: @*/
250: const char *PetscBasename(const char a[])
251: {
252: const char *ptr = NULL;
254: (void)PetscStrrchr(a, '/', (char **)&ptr);
255: if (ptr == a) {
256: if (PetscStrrchr(a, '\\', (char **)&ptr)) ptr = NULL;
257: }
258: return ptr;
259: }
261: /*@C
262: PetscStrcasecmp - Returns true if the two strings are the same
263: except possibly for case.
265: Not Collective; No Fortran Support
267: Input Parameters:
268: + a - pointer to first string
269: - b - pointer to second string
271: Output Parameter:
272: . t - if the two strings are the same
274: Level: intermediate
276: Note:
277: `NULL` arguments are ok
279: .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrgrt()`
280: @*/
281: PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t)
282: {
283: int c;
285: PetscFunctionBegin;
286: PetscAssertPointer(t, 3);
287: if (!a && !b) c = 0;
288: else if (!a || !b) c = 1;
289: #if defined(PETSC_HAVE_STRCASECMP)
290: else c = strcasecmp(a, b);
291: #elif defined(PETSC_HAVE_STRICMP)
292: else c = stricmp(a, b);
293: #else
294: else {
295: char *aa, *bb;
297: PetscCall(PetscStrallocpy(a, &aa));
298: PetscCall(PetscStrallocpy(b, &bb));
299: PetscCall(PetscStrtolower(aa));
300: PetscCall(PetscStrtolower(bb));
301: PetscCall(PetscStrcmp(aa, bb, t));
302: PetscCall(PetscFree(aa));
303: PetscCall(PetscFree(bb));
304: PetscFunctionReturn(PETSC_SUCCESS);
305: }
306: #endif
307: *t = c ? PETSC_FALSE : PETSC_TRUE;
308: PetscFunctionReturn(PETSC_SUCCESS);
309: }
311: /*@C
312: PetscStrendswithwhich - Determines if a string ends with one of several possible strings
314: Not Collective; No Fortran Support
316: Input Parameters:
317: + a - pointer to string
318: - bs - strings to end with (last entry must be `NULL`)
320: Output Parameter:
321: . cnt - the index of the string it ends with or the index of `NULL`
323: Level: intermediate
325: .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
326: `PetscStrncmp()`, `PetscStrlen()`, `PetscStrcmp()`
327: @*/
328: PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt)
329: {
330: PetscFunctionBegin;
331: PetscAssertPointer(bs, 2);
332: PetscAssertPointer(cnt, 3);
333: *cnt = 0;
334: while (bs[*cnt]) {
335: PetscBool flg;
337: PetscCall(PetscStrendswith(a, bs[*cnt], &flg));
338: if (flg) PetscFunctionReturn(PETSC_SUCCESS);
339: ++(*cnt);
340: }
341: PetscFunctionReturn(PETSC_SUCCESS);
342: }
344: struct _p_PetscToken {
345: char token;
346: char *array;
347: char *current;
348: };
350: /*@C
351: PetscTokenFind - Locates next "token" in a `PetscToken`
353: Not Collective; No Fortran Support
355: Input Parameter:
356: . a - pointer to token
358: Output Parameter:
359: . result - location of occurrence, `NULL` if not found
361: Level: intermediate
363: Notes:
364: Treats all characters etc. inside a double quote "
365: as a single token.
367: 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
368: second will return a `NULL` terminated y
370: 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
372: .seealso: `PetscToken`, `PetscTokenCreate()`, `PetscTokenDestroy()`
373: @*/
374: PetscErrorCode PetscTokenFind(PetscToken a, char *result[])
375: {
376: char *ptr, token;
378: PetscFunctionBegin;
379: PetscAssertPointer(a, 1);
380: PetscAssertPointer(result, 2);
381: *result = ptr = a->current;
382: if (ptr && !*ptr) {
383: *result = NULL;
384: PetscFunctionReturn(PETSC_SUCCESS);
385: }
386: token = a->token;
387: if (ptr && (*ptr == '"')) {
388: token = '"';
389: (*result)++;
390: ptr++;
391: }
392: while (ptr) {
393: if (*ptr == token) {
394: *ptr++ = 0;
395: while (*ptr == a->token) ptr++;
396: a->current = ptr;
397: break;
398: }
399: if (!*ptr) {
400: a->current = NULL;
401: break;
402: }
403: ptr++;
404: }
405: PetscFunctionReturn(PETSC_SUCCESS);
406: }
408: /*@C
409: PetscTokenCreate - Creates a `PetscToken` used to find tokens in a string
411: Not Collective; No Fortran Support
413: Input Parameters:
414: + a - the string to look in
415: - b - the separator character
417: Output Parameter:
418: . t - the token object
420: Level: intermediate
422: Note:
423: This version is different from the system version in that
424: it allows you to pass a read-only string into the function.
426: .seealso: `PetscToken`, `PetscTokenFind()`, `PetscTokenDestroy()`
427: @*/
428: PetscErrorCode PetscTokenCreate(const char a[], char b, PetscToken *t)
429: {
430: PetscFunctionBegin;
431: PetscAssertPointer(a, 1);
432: PetscAssertPointer(t, 3);
433: PetscCall(PetscNew(t));
434: PetscCall(PetscStrallocpy(a, &(*t)->array));
436: (*t)->current = (*t)->array;
437: (*t)->token = b;
438: PetscFunctionReturn(PETSC_SUCCESS);
439: }
441: /*@C
442: PetscTokenDestroy - Destroys a `PetscToken`
444: Not Collective; No Fortran Support
446: Input Parameter:
447: . a - pointer to token
449: Level: intermediate
451: .seealso: `PetscToken`, `PetscTokenCreate()`, `PetscTokenFind()`
452: @*/
453: PetscErrorCode PetscTokenDestroy(PetscToken *a)
454: {
455: PetscFunctionBegin;
456: if (!*a) PetscFunctionReturn(PETSC_SUCCESS);
457: PetscCall(PetscFree((*a)->array));
458: PetscCall(PetscFree(*a));
459: PetscFunctionReturn(PETSC_SUCCESS);
460: }
462: /*@C
463: PetscStrInList - search for a string in character-delimited list
465: Not Collective; No Fortran Support
467: Input Parameters:
468: + str - the string to look for
469: . list - the list to search in
470: - sep - the separator character
472: Output Parameter:
473: . found - whether `str` is in `list`
475: Level: intermediate
477: .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()`
478: @*/
479: PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found)
480: {
481: PetscToken token;
482: char *item;
484: PetscFunctionBegin;
485: PetscAssertPointer(found, 4);
486: *found = PETSC_FALSE;
487: PetscCall(PetscTokenCreate(list, sep, &token));
488: PetscCall(PetscTokenFind(token, &item));
489: while (item) {
490: PetscCall(PetscStrcmp(str, item, found));
491: if (*found) break;
492: PetscCall(PetscTokenFind(token, &item));
493: }
494: PetscCall(PetscTokenDestroy(&token));
495: PetscFunctionReturn(PETSC_SUCCESS);
496: }
498: /*@C
499: PetscGetPetscDir - Gets the directory PETSc is installed in
501: Not Collective; No Fortran Support
503: Output Parameter:
504: . dir - the directory
506: Level: developer
508: .seealso: `PetscGetArchType()`
509: @*/
510: PetscErrorCode PetscGetPetscDir(const char *dir[])
511: {
512: PetscFunctionBegin;
513: PetscAssertPointer(dir, 1);
514: *dir = PETSC_DIR;
515: PetscFunctionReturn(PETSC_SUCCESS);
516: }
518: /*@C
519: PetscStrreplace - Replaces substrings in string with other substrings
521: Not Collective; No Fortran Support
523: Input Parameters:
524: + comm - `MPI_Comm` of processors that are processing the string
525: . aa - the string to look in
526: . b - the resulting copy of a with replaced strings (`b` can be the same as `a`)
527: - len - the length of `b`
529: Level: developer
531: Notes:
532: Replaces ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
533: ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME}, ${PETSC_MAKE} with appropriate values
534: as well as any environmental variables.
536: `PETSC_LIB_DIR` uses the environmental variable if it exists. `PETSC_ARCH` and `PETSC_DIR` use what
537: PETSc was built with and do not use environmental variables.
539: .seealso: `PetscStrcmp()`
540: @*/
541: PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len)
542: {
543: int i = 0;
544: size_t l, l1, l2, l3;
545: char *work, *par, *epar = NULL, env[1024], *tfree, *a = (char *)aa;
546: const char *s[] = {"${PETSC_ARCH}", "${PETSC_DIR}", "${PETSC_LIB_DIR}", "${DISPLAY}", "${HOMEDIRECTORY}", "${WORKINGDIRECTORY}", "${USERNAME}", "${HOSTNAME}", "${PETSC_MAKE}", NULL};
547: char *r[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
548: PetscBool flag;
549: static size_t DISPLAY_LENGTH = 265, USER_LENGTH = 256, HOST_LENGTH = 256;
551: PetscFunctionBegin;
552: PetscAssertPointer(aa, 2);
553: PetscAssertPointer(b, 3);
554: if (aa == b) PetscCall(PetscStrallocpy(aa, (char **)&a));
555: PetscCall(PetscMalloc1(len, &work));
557: /* get values for replaced variables */
558: PetscCall(PetscStrallocpy(PETSC_ARCH, &r[0]));
559: PetscCall(PetscStrallocpy(PETSC_DIR, &r[1]));
560: PetscCall(PetscStrallocpy(PETSC_LIB_DIR, &r[2]));
561: PetscCall(PetscMalloc1(DISPLAY_LENGTH, &r[3]));
562: PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[4]));
563: PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[5]));
564: PetscCall(PetscMalloc1(USER_LENGTH, &r[6]));
565: PetscCall(PetscMalloc1(HOST_LENGTH, &r[7]));
566: PetscCall(PetscGetDisplay(r[3], DISPLAY_LENGTH));
567: PetscCall(PetscGetHomeDirectory(r[4], PETSC_MAX_PATH_LEN));
568: PetscCall(PetscGetWorkingDirectory(r[5], PETSC_MAX_PATH_LEN));
569: PetscCall(PetscGetUserName(r[6], USER_LENGTH));
570: PetscCall(PetscGetHostName(r[7], HOST_LENGTH));
571: PetscCall(PetscStrallocpy(PETSC_OMAKE, &r[8]));
573: /* replace that are in environment */
574: PetscCall(PetscOptionsGetenv(comm, "PETSC_LIB_DIR", env, sizeof(env), &flag));
575: if (flag) {
576: PetscCall(PetscFree(r[2]));
577: PetscCall(PetscStrallocpy(env, &r[2]));
578: }
580: /* replace the requested strings */
581: PetscCall(PetscStrncpy(b, a, len));
582: while (s[i]) {
583: PetscCall(PetscStrlen(s[i], &l));
584: PetscCall(PetscStrstr(b, s[i], &par));
585: while (par) {
586: *par = 0;
587: par += l;
589: PetscCall(PetscStrlen(b, &l1));
590: PetscCall(PetscStrlen(r[i], &l2));
591: PetscCall(PetscStrlen(par, &l3));
592: PetscCheck(l1 + l2 + l3 < len, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "b len is not long enough to hold new values");
593: PetscCall(PetscStrncpy(work, b, len));
594: PetscCall(PetscStrlcat(work, r[i], len));
595: PetscCall(PetscStrlcat(work, par, len));
596: PetscCall(PetscStrncpy(b, work, len));
597: PetscCall(PetscStrstr(b, s[i], &par));
598: }
599: i++;
600: }
601: i = 0;
602: while (r[i]) {
603: tfree = (char *)r[i];
604: PetscCall(PetscFree(tfree));
605: i++;
606: }
608: /* look for any other ${xxx} strings to replace from environmental variables */
609: PetscCall(PetscStrstr(b, "${", &par));
610: while (par) {
611: *par = 0;
612: par += 2;
613: PetscCall(PetscStrncpy(work, b, len));
614: PetscCall(PetscStrstr(par, "}", &epar));
615: *epar = 0;
616: epar += 1;
617: PetscCall(PetscOptionsGetenv(comm, par, env, sizeof(env), &flag));
618: PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Substitution string ${%s} not found as environmental variable", par);
619: PetscCall(PetscStrlcat(work, env, len));
620: PetscCall(PetscStrlcat(work, epar, len));
621: PetscCall(PetscStrncpy(b, work, len));
622: PetscCall(PetscStrstr(b, "${", &par));
623: }
624: PetscCall(PetscFree(work));
625: if (aa == b) PetscCall(PetscFree(a));
626: PetscFunctionReturn(PETSC_SUCCESS);
627: }
629: /*@C
630: PetscStrcmpAny - Determines whether a string matches any of a list of strings.
632: Not Collective
634: Input Parameters:
635: + src - pointer to input the string
636: - cmp - list of non-null and non-empty strings to be compared against, pass the empty string "" to terminate the list
638: Output Parameter:
639: . match - `PETSC_TRUE` if the input string matches any in the list, else `PETSC_FALSE`
641: Level: intermediate
643: .seealso: `PetscStrcmp()`
644: @*/
645: PetscErrorCode PetscStrcmpAny(const char src[], PetscBool *match, const char cmp[], ...)
646: {
647: va_list Argp;
649: PetscFunctionBegin;
650: PetscAssertPointer(match, 2);
651: *match = PETSC_FALSE;
652: if (!src) PetscFunctionReturn(PETSC_SUCCESS);
653: va_start(Argp, cmp);
654: while (cmp && cmp[0]) {
655: PetscBool found;
656: PetscCall(PetscStrcmp(src, cmp, &found));
657: if (found) {
658: *match = PETSC_TRUE;
659: break;
660: }
661: cmp = va_arg(Argp, const char *);
662: }
663: va_end(Argp);
664: PetscFunctionReturn(PETSC_SUCCESS);
665: }
667: /*@C
668: PetscEListFind - searches list of strings for given string, using case insensitive matching
670: Not Collective; No Fortran Support
672: Input Parameters:
673: + n - number of strings in
674: . list - list of strings to search
675: - str - string to look for, empty string "" accepts default (first entry in list)
677: Output Parameters:
678: + value - index of matching string (if found)
679: - found - boolean indicating whether string was found (can be `NULL`)
681: Level: developer
683: .seealso: `PetscEnumFind()`
684: @*/
685: PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found)
686: {
687: PetscFunctionBegin;
688: if (found) {
689: PetscAssertPointer(found, 5);
690: *found = PETSC_FALSE;
691: }
692: for (PetscInt i = 0; i < n; ++i) {
693: PetscBool matched;
695: PetscCall(PetscStrcasecmp(str, list[i], &matched));
696: if (matched || !str[0]) {
697: if (found) *found = PETSC_TRUE;
698: *value = i;
699: break;
700: }
701: }
702: PetscFunctionReturn(PETSC_SUCCESS);
703: }
705: /*@C
706: PetscEnumFind - searches enum list of strings for given string, using case insensitive matching
708: Not Collective; No Fortran Support
710: Input Parameters:
711: + enumlist - list of strings to search, followed by enum name, then enum prefix, then `NULL`
712: - str - string to look for
714: Output Parameters:
715: + value - index of matching string (if found)
716: - found - boolean indicating whether string was found (can be `NULL`)
718: Level: advanced
720: .seealso: `PetscEListFind()`
721: @*/
722: PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found)
723: {
724: PetscInt n = 0, evalue;
725: PetscBool efound;
727: PetscFunctionBegin;
728: PetscAssertPointer(enumlist, 1);
729: 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");
730: PetscCheck(n >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
731: n -= 3; /* drop enum name, prefix, and null termination */
732: PetscCall(PetscEListFind(n, enumlist, str, &evalue, &efound));
733: if (efound) {
734: PetscAssertPointer(value, 3);
735: *value = (PetscEnum)evalue;
736: }
737: if (found) {
738: PetscAssertPointer(found, 4);
739: *found = efound;
740: }
741: PetscFunctionReturn(PETSC_SUCCESS);
742: }
744: /*@C
745: PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled.
747: Not Collective; No Fortran Support
749: Input Parameter:
750: . file - the file name
752: Level: developer
754: Note:
755: PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems
756: so that comparisons of output between runs are easy to make.
758: This mode is used for all tests in the test harness, it applies to both debug and optimized builds.
760: Use the option `-petsc_ci` to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for
761: all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness.
763: Always uses the Unix / as the file separate even on Microsoft Windows systems
765: The option `-petsc_ci_portable_error_output` attempts to output the same error messages on all systems for the test harness.
766: In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc
767: error handling by the test harness. This options also causes PETSc to attempt to return an error code of 0 so that the test
768: harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test
769: harness in the args: argument for specific examples. It will not necessarily produce portable output if different errors
770: (or no errors) occur on a subset of the MPI ranks.
772: .seealso: `PetscCILinenumber()`
773: @*/
774: const char *PetscCIFilename(const char *file)
775: {
776: if (!PetscCIEnabledPortableErrorOutput) return file;
777: return PetscBasename(file);
778: }
780: /*@C
781: PetscCILinenumber - returns a line number except if `PetscCIEnablePortableErrorOutput` is set when it returns 0
783: Not Collective; No Fortran Support
785: Input Parameter:
786: . linenumber - the initial line number
788: Level: developer
790: Note:
791: See `PetscCIFilename()` for details on usage
793: .seealso: `PetscCIFilename()`
794: @*/
795: int PetscCILinenumber(int linenumber)
796: {
797: if (!PetscCIEnabledPortableErrorOutput) return linenumber;
798: return 0;
799: }
801: /*@C
802: PetscStrcat - Concatenates a string onto a given string
804: Not Collective, No Fortran Support
806: Input Parameters:
807: + s - string to be added to
808: - t - pointer to string to be added to end
810: Level: deprecated (since 3.18.5)
812: Notes:
813: It is recommended you use `PetscStrlcat()` instead of this routine.
815: .seealso: `PetscStrlcat()`
816: @*/
817: PetscErrorCode PetscStrcat(char s[], const char t[])
818: {
819: PetscFunctionBegin;
820: if (!t) PetscFunctionReturn(PETSC_SUCCESS);
821: PetscAssertPointer(s, 1);
822: strcat(s, t);
823: PetscFunctionReturn(PETSC_SUCCESS);
824: }
826: /*@C
827: PetscStrcpy - Copies a string
829: Not Collective, No Fortran Support
831: Input Parameter:
832: . t - pointer to string
834: Output Parameter:
835: . s - the copied string
837: Level: deprecated (since 3.18.5)
839: Notes:
840: It is recommended you use `PetscStrncpy()` (equivalently `PetscArraycpy()` or
841: `PetscMemcpy()`) instead of this routine.
843: `NULL` strings returns a string starting with zero.
845: .seealso: `PetscStrncpy()`
846: @*/
847: PetscErrorCode PetscStrcpy(char s[], const char t[])
848: {
849: PetscFunctionBegin;
850: if (t) {
851: PetscAssertPointer(s, 1);
852: PetscAssertPointer(t, 2);
853: strcpy(s, t);
854: } else if (s) {
855: s[0] = '\0';
856: }
857: PetscFunctionReturn(PETSC_SUCCESS);
858: }