xref: /petsc/src/sys/utils/str.c (revision 10450e9e44b354a0a3da7bbd573407bdf051df10)
1e5c89e4eSSatish Balay /*
2e5c89e4eSSatish Balay     We define the string operations here. The reason we just do not use
3e5c89e4eSSatish Balay   the standard string routines in the PETSc code is that on some machines
4e5c89e4eSSatish Balay   they are broken or have the wrong prototypes.
5e5c89e4eSSatish Balay */
65f80ce2aSJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I  "petscsys.h"   I*/
73964eb88SJed Brown #if defined(PETSC_HAVE_STRINGS_H)
83964eb88SJed Brown   #include <strings.h> /* strcasecmp */
93964eb88SJed Brown #endif
103964eb88SJed Brown 
113c311c98SBarry Smith /*@C
1251a1f156SVaclav Hapla   PetscStrToArray - Separates a string by a character (for example ' ' or '\n') and creates an array of strings
133c311c98SBarry Smith 
14667f096bSBarry Smith   Not Collective; No Fortran Support
153c311c98SBarry Smith 
163c311c98SBarry Smith   Input Parameters:
17d67fe73bSBarry Smith + s  - pointer to string
1851a1f156SVaclav Hapla - sp - separator character
193c311c98SBarry Smith 
20d8d19677SJose E. Roman   Output Parameters:
213c311c98SBarry Smith + argc - the number of entries in the array
22667f096bSBarry Smith - args - an array of the entries with a `NULL` at the end
233c311c98SBarry Smith 
243c311c98SBarry Smith   Level: intermediate
253c311c98SBarry Smith 
26811af0c4SBarry Smith   Note:
27667f096bSBarry Smith   This may be called before `PetscInitialize()` or after `PetscFinalize()`
286f013253SBarry Smith 
2995452b02SPatrick Sanan   Developer Notes:
30811af0c4SBarry Smith   Uses raw `malloc()` and does not call error handlers since this may be used before PETSc is initialized.
31811af0c4SBarry Smith 
32811af0c4SBarry Smith   Used to generate argc, args arguments passed to `MPI_Init()`
33301d30feSBarry Smith 
34db781477SPatrick Sanan .seealso: `PetscStrToArrayDestroy()`, `PetscToken`, `PetscTokenCreate()`
353c311c98SBarry Smith @*/
36d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrToArray(const char s[], char sp, int *argc, char ***args)
37d71ae5a4SJacob Faibussowitsch {
38c3bcdc7eSBarry Smith   int       i, j, n, *lens, cnt = 0;
39ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
403c311c98SBarry Smith 
4140a7e1efSBarry Smith   if (!s) n = 0;
4240a7e1efSBarry Smith   else n = strlen(s);
433c311c98SBarry Smith   *argc = 0;
4461528463SBarry Smith   *args = NULL;
45acf7dc08SSatish Balay   for (; n > 0; n--) { /* remove separator chars at the end - and will empty the string if all chars are separator chars */
46acf7dc08SSatish Balay     if (s[n - 1] != sp) break;
47acf7dc08SSatish Balay   }
483ba16761SJacob Faibussowitsch   if (!n) return PETSC_SUCCESS;
493c311c98SBarry Smith   for (i = 0; i < n; i++) {
50d67fe73bSBarry Smith     if (s[i] != sp) break;
513c311c98SBarry Smith   }
523c311c98SBarry Smith   for (; i < n + 1; i++) {
539371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
549371c9d4SSatish Balay       flg = PETSC_TRUE;
559371c9d4SSatish Balay       (*argc)++;
569371c9d4SSatish Balay     } else if (s[i] != sp) {
579371c9d4SSatish Balay       flg = PETSC_FALSE;
583c311c98SBarry Smith     }
599371c9d4SSatish Balay   }
609371c9d4SSatish Balay   (*args) = (char **)malloc(((*argc) + 1) * sizeof(char *));
619371c9d4SSatish Balay   if (!*args) return PETSC_ERR_MEM;
629371c9d4SSatish Balay   lens = (int *)malloc((*argc) * sizeof(int));
639371c9d4SSatish Balay   if (!lens) return PETSC_ERR_MEM;
643c311c98SBarry Smith   for (i = 0; i < *argc; i++) lens[i] = 0;
653c311c98SBarry Smith 
663c311c98SBarry Smith   *argc = 0;
673c311c98SBarry Smith   for (i = 0; i < n; i++) {
68d67fe73bSBarry Smith     if (s[i] != sp) break;
693c311c98SBarry Smith   }
707dd9f305SSatish Balay   for (; i < n + 1; i++) {
719371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
729371c9d4SSatish Balay       flg = PETSC_TRUE;
739371c9d4SSatish Balay       (*argc)++;
749371c9d4SSatish Balay     } else if (s[i] != sp) {
759371c9d4SSatish Balay       lens[*argc]++;
769371c9d4SSatish Balay       flg = PETSC_FALSE;
779371c9d4SSatish Balay     }
783c311c98SBarry Smith   }
793c311c98SBarry Smith 
803c311c98SBarry Smith   for (i = 0; i < *argc; i++) {
81c3bcdc7eSBarry Smith     (*args)[i] = (char *)malloc((lens[i] + 1) * sizeof(char));
82c3bcdc7eSBarry Smith     if (!(*args)[i]) {
83c3bcdc7eSBarry Smith       free(lens);
84c3bcdc7eSBarry Smith       for (j = 0; j < i; j++) free((*args)[j]);
85c3bcdc7eSBarry Smith       free(*args);
86c3bcdc7eSBarry Smith       return PETSC_ERR_MEM;
87c3bcdc7eSBarry Smith     }
883c311c98SBarry Smith   }
89a2ea699eSBarry Smith   free(lens);
9002c9f0b5SLisandro Dalcin   (*args)[*argc] = NULL;
913c311c98SBarry Smith 
923c311c98SBarry Smith   *argc = 0;
933c311c98SBarry Smith   for (i = 0; i < n; i++) {
94d67fe73bSBarry Smith     if (s[i] != sp) break;
953c311c98SBarry Smith   }
963c311c98SBarry Smith   for (; i < n + 1; i++) {
979371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
989371c9d4SSatish Balay       flg                   = PETSC_TRUE;
999371c9d4SSatish Balay       (*args)[*argc][cnt++] = 0;
1009371c9d4SSatish Balay       (*argc)++;
1019371c9d4SSatish Balay       cnt = 0;
1029371c9d4SSatish Balay     } else if (s[i] != sp && s[i] != 0) {
1039371c9d4SSatish Balay       (*args)[*argc][cnt++] = s[i];
1049371c9d4SSatish Balay       flg                   = PETSC_FALSE;
1059371c9d4SSatish Balay     }
1063c311c98SBarry Smith   }
1073ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
1083c311c98SBarry Smith }
1093c311c98SBarry Smith 
110301d30feSBarry Smith /*@C
111811af0c4SBarry Smith   PetscStrToArrayDestroy - Frees array created with `PetscStrToArray()`.
112301d30feSBarry Smith 
113667f096bSBarry Smith   Not Collective; No Fortran Support
114301d30feSBarry Smith 
115301d30feSBarry Smith   Output Parameters:
116301d30feSBarry Smith + argc - the number of arguments
117301d30feSBarry Smith - args - the array of arguments
118301d30feSBarry Smith 
119301d30feSBarry Smith   Level: intermediate
120301d30feSBarry Smith 
121811af0c4SBarry Smith   Note:
122811af0c4SBarry Smith   This may be called before `PetscInitialize()` or after `PetscFinalize()`
123301d30feSBarry Smith 
124db781477SPatrick Sanan .seealso: `PetscStrToArray()`
125301d30feSBarry Smith @*/
126d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrToArrayDestroy(int argc, char **args)
127d71ae5a4SJacob Faibussowitsch {
1285f80ce2aSJacob Faibussowitsch   for (int i = 0; i < argc; ++i) free(args[i]);
129a297a907SKarl Rupp   if (args) free(args);
1303ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
131301d30feSBarry Smith }
132301d30feSBarry Smith 
133e5c89e4eSSatish Balay /*@C
13447340559SBarry Smith   PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
13547340559SBarry Smith 
136667f096bSBarry Smith   Not Collective; No Fortran Support
13747340559SBarry Smith 
1382fe279fdSBarry Smith   Input Parameter:
139aec76313SJacob Faibussowitsch . list - pointer to array of strings (final string is a `NULL`)
14047340559SBarry Smith 
14147340559SBarry Smith   Output Parameter:
14247340559SBarry Smith . t - the copied array string
14347340559SBarry Smith 
14447340559SBarry Smith   Level: intermediate
14547340559SBarry Smith 
14647340559SBarry Smith   Note:
147667f096bSBarry Smith   If `t` has previously been allocated then that memory is lost, you may need to `PetscStrArrayDestroy()`
1480ecf5a55SBarry Smith   the array before calling this routine.
1490ecf5a55SBarry Smith 
150811af0c4SBarry Smith .seealso: `PetscStrallocpy()`, `PetscStrArrayDestroy()`, `PetscStrNArrayallocpy()`
15147340559SBarry Smith @*/
152d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrArrayallocpy(const char *const *list, char ***t)
153d71ae5a4SJacob Faibussowitsch {
1545f80ce2aSJacob Faibussowitsch   PetscInt n = 0;
15547340559SBarry Smith 
15647340559SBarry Smith   PetscFunctionBegin;
1579371c9d4SSatish Balay   while (list[n++])
1589371c9d4SSatish Balay     ;
1599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n + 1, t));
1609566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
1610298fd71SBarry Smith   (*t)[n] = NULL;
1623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16347340559SBarry Smith }
16447340559SBarry Smith 
16547340559SBarry Smith /*@C
166811af0c4SBarry Smith   PetscStrArrayDestroy - Frees array of strings created with `PetscStrArrayallocpy()`.
16747340559SBarry Smith 
168667f096bSBarry Smith   Not Collective; No Fortran Support
16947340559SBarry Smith 
1702fe279fdSBarry Smith   Output Parameter:
17147340559SBarry Smith . list - array of strings
17247340559SBarry Smith 
17347340559SBarry Smith   Level: intermediate
17447340559SBarry Smith 
175db781477SPatrick Sanan .seealso: `PetscStrArrayallocpy()`
17647340559SBarry Smith @*/
177d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrArrayDestroy(char ***list)
178d71ae5a4SJacob Faibussowitsch {
17947340559SBarry Smith   PetscInt n = 0;
18047340559SBarry Smith 
1816fed8037SJed Brown   PetscFunctionBegin;
1823ba16761SJacob Faibussowitsch   if (!*list) PetscFunctionReturn(PETSC_SUCCESS);
1836fed8037SJed Brown   while ((*list)[n]) {
1849566063dSJacob Faibussowitsch     PetscCall(PetscFree((*list)[n]));
1855f80ce2aSJacob Faibussowitsch     ++n;
18647340559SBarry Smith   }
1879566063dSJacob Faibussowitsch   PetscCall(PetscFree(*list));
1883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18947340559SBarry Smith }
19047340559SBarry Smith 
1916991f827SBarry Smith /*@C
1926991f827SBarry Smith   PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
1936991f827SBarry Smith 
194667f096bSBarry Smith   Not Collective; No Fortran Support
1956991f827SBarry Smith 
1966991f827SBarry Smith   Input Parameters:
1976991f827SBarry Smith + n    - the number of string entries
198aec76313SJacob Faibussowitsch - list - pointer to array of strings
1996991f827SBarry Smith 
2006991f827SBarry Smith   Output Parameter:
2016991f827SBarry Smith . t - the copied array string
2026991f827SBarry Smith 
2036991f827SBarry Smith   Level: intermediate
2046991f827SBarry Smith 
205db781477SPatrick Sanan .seealso: `PetscStrallocpy()`, `PetscStrArrayallocpy()`, `PetscStrNArrayDestroy()`
2066991f827SBarry Smith @*/
207d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrNArrayallocpy(PetscInt n, const char *const *list, char ***t)
208d71ae5a4SJacob Faibussowitsch {
2096991f827SBarry Smith   PetscFunctionBegin;
2109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, t));
2119566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
2123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2136991f827SBarry Smith }
2146991f827SBarry Smith 
2156991f827SBarry Smith /*@C
216811af0c4SBarry Smith   PetscStrNArrayDestroy - Frees array of strings created with `PetscStrNArrayallocpy()`.
2176991f827SBarry Smith 
218667f096bSBarry Smith   Not Collective; No Fortran Support
2196991f827SBarry Smith 
2206991f827SBarry Smith   Output Parameters:
2216991f827SBarry Smith + n    - number of string entries
2226991f827SBarry Smith - list - array of strings
2236991f827SBarry Smith 
2246991f827SBarry Smith   Level: intermediate
2256991f827SBarry Smith 
226811af0c4SBarry Smith .seealso: `PetscStrNArrayallocpy()`, `PetscStrArrayallocpy()`
2276991f827SBarry Smith @*/
228d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrNArrayDestroy(PetscInt n, char ***list)
229d71ae5a4SJacob Faibussowitsch {
2306991f827SBarry Smith   PetscFunctionBegin;
2313ba16761SJacob Faibussowitsch   if (!*list) PetscFunctionReturn(PETSC_SUCCESS);
2329566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscFree((*list)[i]));
2339566063dSJacob Faibussowitsch   PetscCall(PetscFree(*list));
2343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2356991f827SBarry Smith }
2366991f827SBarry Smith 
237e5c89e4eSSatish Balay /*@C
238811af0c4SBarry Smith   PetscBasename - returns a pointer to the last entry of a / or \ separated directory path
23980b92c66SBarry Smith 
240667f096bSBarry Smith   Not Collective; No Fortran Support
24180b92c66SBarry Smith 
24280b92c66SBarry Smith   Input Parameter:
24380b92c66SBarry Smith . a - pointer to string
24480b92c66SBarry Smith 
24580b92c66SBarry Smith   Level: intermediate
24680b92c66SBarry Smith 
24780b92c66SBarry Smith .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`, `PetscStrrchr()`, `PetscStrcmp()`, `PetscStrstr()`,
24880b92c66SBarry Smith           `PetscTokenCreate()`, `PetscStrToArray()`, `PetscStrInList()`
24980b92c66SBarry Smith @*/
250d71ae5a4SJacob Faibussowitsch const char *PetscBasename(const char a[])
251d71ae5a4SJacob Faibussowitsch {
252bbcf679cSJacob Faibussowitsch   const char *ptr = NULL;
25380b92c66SBarry Smith 
254bbcf679cSJacob Faibussowitsch   (void)PetscStrrchr(a, '/', (char **)&ptr);
255660278c0SBarry Smith   if (ptr == a) {
256660278c0SBarry Smith     if (PetscStrrchr(a, '\\', (char **)&ptr)) ptr = NULL;
257660278c0SBarry Smith   }
25880b92c66SBarry Smith   return ptr;
25980b92c66SBarry Smith }
26080b92c66SBarry Smith 
26180b92c66SBarry Smith /*@C
262e5c89e4eSSatish Balay   PetscStrcasecmp - Returns true if the two strings are the same
263e5c89e4eSSatish Balay   except possibly for case.
264e5c89e4eSSatish Balay 
265667f096bSBarry Smith   Not Collective; No Fortran Support
266e5c89e4eSSatish Balay 
267e5c89e4eSSatish Balay   Input Parameters:
268e5c89e4eSSatish Balay + a - pointer to first string
269e5c89e4eSSatish Balay - b - pointer to second string
270e5c89e4eSSatish Balay 
271e5c89e4eSSatish Balay   Output Parameter:
272aec76313SJacob Faibussowitsch . t - if the two strings are the same
273e5c89e4eSSatish Balay 
274e5c89e4eSSatish Balay   Level: intermediate
275e5c89e4eSSatish Balay 
276667f096bSBarry Smith   Note:
277667f096bSBarry Smith   `NULL` arguments are ok
278667f096bSBarry Smith 
279db781477SPatrick Sanan .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrgrt()`
280e5c89e4eSSatish Balay @*/
281d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t)
282d71ae5a4SJacob Faibussowitsch {
283e5c89e4eSSatish Balay   int c;
284e5c89e4eSSatish Balay 
285e5c89e4eSSatish Balay   PetscFunctionBegin;
2865f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(t, 3);
287e5c89e4eSSatish Balay   if (!a && !b) c = 0;
288e5c89e4eSSatish Balay   else if (!a || !b) c = 1;
28932b366c8SSatish Balay #if defined(PETSC_HAVE_STRCASECMP)
29032b366c8SSatish Balay   else c = strcasecmp(a, b);
29132b366c8SSatish Balay #elif defined(PETSC_HAVE_STRICMP)
292e5c89e4eSSatish Balay   else c = stricmp(a, b);
293e5c89e4eSSatish Balay #else
29432b366c8SSatish Balay   else {
29532b366c8SSatish Balay     char *aa, *bb;
296bbcf679cSJacob Faibussowitsch 
2979566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(a, &aa));
2989566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(b, &bb));
2999566063dSJacob Faibussowitsch     PetscCall(PetscStrtolower(aa));
3009566063dSJacob Faibussowitsch     PetscCall(PetscStrtolower(bb));
3019566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(aa, bb, t));
3029566063dSJacob Faibussowitsch     PetscCall(PetscFree(aa));
3039566063dSJacob Faibussowitsch     PetscCall(PetscFree(bb));
3043ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
30532b366c8SSatish Balay   }
306e5c89e4eSSatish Balay #endif
3075f80ce2aSJacob Faibussowitsch   *t = c ? PETSC_FALSE : PETSC_TRUE;
3083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
309e5c89e4eSSatish Balay }
310e5c89e4eSSatish Balay 
311e5c89e4eSSatish Balay /*@C
3127ba3a57cSBarry Smith   PetscStrendswithwhich - Determines if a string ends with one of several possible strings
3137ba3a57cSBarry Smith 
314667f096bSBarry Smith   Not Collective; No Fortran Support
3157ba3a57cSBarry Smith 
3167ba3a57cSBarry Smith   Input Parameters:
3177ba3a57cSBarry Smith + a  - pointer to string
318667f096bSBarry Smith - bs - strings to end with (last entry must be `NULL`)
3197ba3a57cSBarry Smith 
3207ba3a57cSBarry Smith   Output Parameter:
321667f096bSBarry Smith . cnt - the index of the string it ends with or the index of `NULL`
3227ba3a57cSBarry Smith 
3237ba3a57cSBarry Smith   Level: intermediate
3247ba3a57cSBarry Smith 
325811af0c4SBarry Smith .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
326aec76313SJacob Faibussowitsch           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrcmp()`
3277ba3a57cSBarry Smith @*/
328d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt)
329d71ae5a4SJacob Faibussowitsch {
3307ba3a57cSBarry Smith   PetscFunctionBegin;
3315f80ce2aSJacob Faibussowitsch   PetscValidPointer(bs, 2);
3325f80ce2aSJacob Faibussowitsch   PetscValidIntPointer(cnt, 3);
3337ba3a57cSBarry Smith   *cnt = 0;
3347ba3a57cSBarry Smith   while (bs[*cnt]) {
3355f80ce2aSJacob Faibussowitsch     PetscBool flg;
3365f80ce2aSJacob Faibussowitsch 
3379566063dSJacob Faibussowitsch     PetscCall(PetscStrendswith(a, bs[*cnt], &flg));
3383ba16761SJacob Faibussowitsch     if (flg) PetscFunctionReturn(PETSC_SUCCESS);
3395f80ce2aSJacob Faibussowitsch     ++(*cnt);
3407ba3a57cSBarry Smith   }
3413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3427ba3a57cSBarry Smith }
3437ba3a57cSBarry Smith 
3449371c9d4SSatish Balay struct _p_PetscToken {
3459371c9d4SSatish Balay   char  token;
3469371c9d4SSatish Balay   char *array;
3479371c9d4SSatish Balay   char *current;
3489371c9d4SSatish Balay };
3491d1a0024SBarry Smith 
350e5c89e4eSSatish Balay /*@C
351667f096bSBarry Smith   PetscTokenFind - Locates next "token" in a `PetscToken`
352e5c89e4eSSatish Balay 
353667f096bSBarry Smith   Not Collective; No Fortran Support
354e5c89e4eSSatish Balay 
3552fe279fdSBarry Smith   Input Parameter:
356e5c89e4eSSatish Balay . a - pointer to token
357e5c89e4eSSatish Balay 
358e5c89e4eSSatish Balay   Output Parameter:
359667f096bSBarry Smith . result - location of occurrence, `NULL` if not found
3606f013253SBarry Smith 
361e5c89e4eSSatish Balay   Level: intermediate
362e5c89e4eSSatish Balay 
363667f096bSBarry Smith   Notes:
364667f096bSBarry Smith   Treats all characters etc. inside a double quote "
365667f096bSBarry Smith   as a single token.
366667f096bSBarry Smith 
367667f096bSBarry Smith   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
368667f096bSBarry Smith   second will return a `NULL` terminated y
369667f096bSBarry Smith 
370667f096bSBarry Smith   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
371667f096bSBarry Smith 
372667f096bSBarry Smith .seealso: `PetscToken`, `PetscTokenCreate()`, `PetscTokenDestroy()`
373e5c89e4eSSatish Balay @*/
374d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTokenFind(PetscToken a, char *result[])
375d71ae5a4SJacob Faibussowitsch {
3765f80ce2aSJacob Faibussowitsch   char *ptr, token;
377e5c89e4eSSatish Balay 
378e5c89e4eSSatish Balay   PetscFunctionBegin;
3795f80ce2aSJacob Faibussowitsch   PetscValidPointer(a, 1);
3805f80ce2aSJacob Faibussowitsch   PetscValidPointer(result, 2);
3815f80ce2aSJacob Faibussowitsch   *result = ptr = a->current;
3829371c9d4SSatish Balay   if (ptr && !*ptr) {
3839371c9d4SSatish Balay     *result = NULL;
3843ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3859371c9d4SSatish Balay   }
3864704e885SBarry Smith   token = a->token;
3879371c9d4SSatish Balay   if (ptr && (*ptr == '"')) {
3889371c9d4SSatish Balay     token = '"';
3899371c9d4SSatish Balay     (*result)++;
3909371c9d4SSatish Balay     ptr++;
3919371c9d4SSatish Balay   }
392e5c89e4eSSatish Balay   while (ptr) {
3934704e885SBarry Smith     if (*ptr == token) {
394e5c89e4eSSatish Balay       *ptr++ = 0;
395e5c89e4eSSatish Balay       while (*ptr == a->token) ptr++;
396e5c89e4eSSatish Balay       a->current = ptr;
397e5c89e4eSSatish Balay       break;
398e5c89e4eSSatish Balay     }
399e5c89e4eSSatish Balay     if (!*ptr) {
40002c9f0b5SLisandro Dalcin       a->current = NULL;
401e5c89e4eSSatish Balay       break;
402e5c89e4eSSatish Balay     }
403e5c89e4eSSatish Balay     ptr++;
404e5c89e4eSSatish Balay   }
4053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
406e5c89e4eSSatish Balay }
407e5c89e4eSSatish Balay 
408e5c89e4eSSatish Balay /*@C
409811af0c4SBarry Smith   PetscTokenCreate - Creates a `PetscToken` used to find tokens in a string
410e5c89e4eSSatish Balay 
411667f096bSBarry Smith   Not Collective; No Fortran Support
412e5c89e4eSSatish Balay 
413e5c89e4eSSatish Balay   Input Parameters:
414aec76313SJacob Faibussowitsch + a - the string to look in
4153a9c465aSBarry Smith - b - the separator character
416e5c89e4eSSatish Balay 
417e5c89e4eSSatish Balay   Output Parameter:
4183a9c465aSBarry Smith . t - the token object
419e5c89e4eSSatish Balay 
420667f096bSBarry Smith   Level: intermediate
421667f096bSBarry Smith 
422811af0c4SBarry Smith   Note:
423e5c89e4eSSatish Balay   This version is different from the system version in that
424e5c89e4eSSatish Balay   it allows you to pass a read-only string into the function.
425e5c89e4eSSatish Balay 
426667f096bSBarry Smith .seealso: `PetscToken`, `PetscTokenFind()`, `PetscTokenDestroy()`
427e5c89e4eSSatish Balay @*/
42898e514b7SJacob Faibussowitsch PetscErrorCode PetscTokenCreate(const char a[], char b, PetscToken *t)
429d71ae5a4SJacob Faibussowitsch {
430e5c89e4eSSatish Balay   PetscFunctionBegin;
4315f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
4325f80ce2aSJacob Faibussowitsch   PetscValidPointer(t, 3);
4339566063dSJacob Faibussowitsch   PetscCall(PetscNew(t));
4349566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(a, &(*t)->array));
435a297a907SKarl Rupp 
436e5c89e4eSSatish Balay   (*t)->current = (*t)->array;
437e5c89e4eSSatish Balay   (*t)->token   = b;
4383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
439e5c89e4eSSatish Balay }
440e5c89e4eSSatish Balay 
441e5c89e4eSSatish Balay /*@C
442811af0c4SBarry Smith   PetscTokenDestroy - Destroys a `PetscToken`
443e5c89e4eSSatish Balay 
444667f096bSBarry Smith   Not Collective; No Fortran Support
445e5c89e4eSSatish Balay 
4462fe279fdSBarry Smith   Input Parameter:
447e5c89e4eSSatish Balay . a - pointer to token
448e5c89e4eSSatish Balay 
449e5c89e4eSSatish Balay   Level: intermediate
450e5c89e4eSSatish Balay 
451667f096bSBarry Smith .seealso: `PetscToken`, `PetscTokenCreate()`, `PetscTokenFind()`
452e5c89e4eSSatish Balay @*/
453d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTokenDestroy(PetscToken *a)
454d71ae5a4SJacob Faibussowitsch {
455e5c89e4eSSatish Balay   PetscFunctionBegin;
4563ba16761SJacob Faibussowitsch   if (!*a) PetscFunctionReturn(PETSC_SUCCESS);
4579566063dSJacob Faibussowitsch   PetscCall(PetscFree((*a)->array));
4589566063dSJacob Faibussowitsch   PetscCall(PetscFree(*a));
4593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
460e5c89e4eSSatish Balay }
461e5c89e4eSSatish Balay 
4628e81d068SLisandro Dalcin /*@C
463667f096bSBarry Smith   PetscStrInList - search for a string in character-delimited list
4648e81d068SLisandro Dalcin 
465667f096bSBarry Smith   Not Collective; No Fortran Support
4668e81d068SLisandro Dalcin 
4678e81d068SLisandro Dalcin   Input Parameters:
4688e81d068SLisandro Dalcin + str  - the string to look for
4698e81d068SLisandro Dalcin . list - the list to search in
4708e81d068SLisandro Dalcin - sep  - the separator character
4718e81d068SLisandro Dalcin 
4728e81d068SLisandro Dalcin   Output Parameter:
473667f096bSBarry Smith . found - whether `str` is in `list`
4748e81d068SLisandro Dalcin 
4758e81d068SLisandro Dalcin   Level: intermediate
4768e81d068SLisandro Dalcin 
477db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()`
4788e81d068SLisandro Dalcin @*/
479d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found)
480d71ae5a4SJacob Faibussowitsch {
4818e81d068SLisandro Dalcin   PetscToken token;
4828e81d068SLisandro Dalcin   char      *item;
4838e81d068SLisandro Dalcin 
4848e81d068SLisandro Dalcin   PetscFunctionBegin;
4855f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(found, 4);
4868e81d068SLisandro Dalcin   *found = PETSC_FALSE;
4879566063dSJacob Faibussowitsch   PetscCall(PetscTokenCreate(list, sep, &token));
4889566063dSJacob Faibussowitsch   PetscCall(PetscTokenFind(token, &item));
4898e81d068SLisandro Dalcin   while (item) {
4909566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(str, item, found));
4918e81d068SLisandro Dalcin     if (*found) break;
4929566063dSJacob Faibussowitsch     PetscCall(PetscTokenFind(token, &item));
4938e81d068SLisandro Dalcin   }
4949566063dSJacob Faibussowitsch   PetscCall(PetscTokenDestroy(&token));
4953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4968e81d068SLisandro Dalcin }
497e5c89e4eSSatish Balay 
498e5c89e4eSSatish Balay /*@C
499e5c89e4eSSatish Balay   PetscGetPetscDir - Gets the directory PETSc is installed in
500e5c89e4eSSatish Balay 
501667f096bSBarry Smith   Not Collective; No Fortran Support
502e5c89e4eSSatish Balay 
503e5c89e4eSSatish Balay   Output Parameter:
504e5c89e4eSSatish Balay . dir - the directory
505e5c89e4eSSatish Balay 
506e5c89e4eSSatish Balay   Level: developer
507e5c89e4eSSatish Balay 
508*10450e9eSJacob Faibussowitsch .seealso: `PetscGetArchType()`
509e5c89e4eSSatish Balay @*/
510d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGetPetscDir(const char *dir[])
511d71ae5a4SJacob Faibussowitsch {
512e5c89e4eSSatish Balay   PetscFunctionBegin;
5135f80ce2aSJacob Faibussowitsch   PetscValidPointer(dir, 1);
514e5c89e4eSSatish Balay   *dir = PETSC_DIR;
5153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
516e5c89e4eSSatish Balay }
517e5c89e4eSSatish Balay 
518e5c89e4eSSatish Balay /*@C
519e5c89e4eSSatish Balay   PetscStrreplace - Replaces substrings in string with other substrings
520e5c89e4eSSatish Balay 
521667f096bSBarry Smith   Not Collective; No Fortran Support
522e5c89e4eSSatish Balay 
523e5c89e4eSSatish Balay   Input Parameters:
524811af0c4SBarry Smith + comm - `MPI_Comm` of processors that are processing the string
52571573d7dSBarry Smith . aa   - the string to look in
526667f096bSBarry Smith . b    - the resulting copy of a with replaced strings (`b` can be the same as `a`)
527667f096bSBarry Smith - len  - the length of `b`
528e5c89e4eSSatish Balay 
5292fe279fdSBarry Smith   Level: developer
5302fe279fdSBarry Smith 
531e5c89e4eSSatish Balay   Notes:
532e5c89e4eSSatish Balay   Replaces ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
533f236b2adSBarry Smith       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME}, ${PETSC_MAKE} with appropriate values
534e5c89e4eSSatish Balay   as well as any environmental variables.
535e5c89e4eSSatish Balay 
536811af0c4SBarry Smith   `PETSC_LIB_DIR` uses the environmental variable if it exists. `PETSC_ARCH` and `PETSC_DIR` use what
537acc6cc86SBarry Smith   PETSc was built with and do not use environmental variables.
538acc6cc86SBarry Smith 
539*10450e9eSJacob Faibussowitsch .seealso: `PetscStrcmp()`
540e5c89e4eSSatish Balay @*/
541d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len)
542d71ae5a4SJacob Faibussowitsch {
543e5c89e4eSSatish Balay   int           i = 0;
544e5c89e4eSSatish Balay   size_t        l, l1, l2, l3;
5457864358aSSatish Balay   char         *work, *par, *epar = NULL, env[1024], *tfree, *a = (char *)aa;
546f236b2adSBarry Smith   const char   *s[] = {"${PETSC_ARCH}", "${PETSC_DIR}", "${PETSC_LIB_DIR}", "${DISPLAY}", "${HOMEDIRECTORY}", "${WORKINGDIRECTORY}", "${USERNAME}", "${HOSTNAME}", "${PETSC_MAKE}", NULL};
547f236b2adSBarry Smith   char         *r[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
548ace3abfcSBarry Smith   PetscBool     flag;
549589a23caSBarry Smith   static size_t DISPLAY_LENGTH = 265, USER_LENGTH = 256, HOST_LENGTH = 256;
550e5c89e4eSSatish Balay 
551e5c89e4eSSatish Balay   PetscFunctionBegin;
5525f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(aa, 2);
5535f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(b, 3);
5549566063dSJacob Faibussowitsch   if (aa == b) PetscCall(PetscStrallocpy(aa, (char **)&a));
5559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(len, &work));
556e5c89e4eSSatish Balay 
557e5c89e4eSSatish Balay   /* get values for replaced variables */
5589566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_ARCH, &r[0]));
5599566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_DIR, &r[1]));
5609566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_LIB_DIR, &r[2]));
5619566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(DISPLAY_LENGTH, &r[3]));
5629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[4]));
5639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[5]));
5649566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(USER_LENGTH, &r[6]));
5659566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(HOST_LENGTH, &r[7]));
5669566063dSJacob Faibussowitsch   PetscCall(PetscGetDisplay(r[3], DISPLAY_LENGTH));
5679566063dSJacob Faibussowitsch   PetscCall(PetscGetHomeDirectory(r[4], PETSC_MAX_PATH_LEN));
5689566063dSJacob Faibussowitsch   PetscCall(PetscGetWorkingDirectory(r[5], PETSC_MAX_PATH_LEN));
5699566063dSJacob Faibussowitsch   PetscCall(PetscGetUserName(r[6], USER_LENGTH));
5709566063dSJacob Faibussowitsch   PetscCall(PetscGetHostName(r[7], HOST_LENGTH));
571f236b2adSBarry Smith   PetscCall(PetscStrallocpy(PETSC_OMAKE, &r[8]));
572487e5849SBarry Smith 
573487e5849SBarry Smith   /* replace that are in environment */
5749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetenv(comm, "PETSC_LIB_DIR", env, sizeof(env), &flag));
575487e5849SBarry Smith   if (flag) {
5769566063dSJacob Faibussowitsch     PetscCall(PetscFree(r[2]));
5779566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(env, &r[2]));
578487e5849SBarry Smith   }
579e5c89e4eSSatish Balay 
580e5c89e4eSSatish Balay   /* replace the requested strings */
5819566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(b, a, len));
582e5c89e4eSSatish Balay   while (s[i]) {
5839566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(s[i], &l));
5849566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(b, s[i], &par));
585e5c89e4eSSatish Balay     while (par) {
586e5c89e4eSSatish Balay       *par = 0;
587e5c89e4eSSatish Balay       par += l;
588e5c89e4eSSatish Balay 
5899566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(b, &l1));
5909566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(r[i], &l2));
5919566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(par, &l3));
592cc73adaaSBarry Smith       PetscCheck(l1 + l2 + l3 < len, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "b len is not long enough to hold new values");
5939566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(work, b, len));
5949566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(work, r[i], len));
5959566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(work, par, len));
5969566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(b, work, len));
5979566063dSJacob Faibussowitsch       PetscCall(PetscStrstr(b, s[i], &par));
598e5c89e4eSSatish Balay     }
599e5c89e4eSSatish Balay     i++;
600e5c89e4eSSatish Balay   }
601487e5849SBarry Smith   i = 0;
602487e5849SBarry Smith   while (r[i]) {
603e5c89e4eSSatish Balay     tfree = (char *)r[i];
6049566063dSJacob Faibussowitsch     PetscCall(PetscFree(tfree));
605487e5849SBarry Smith     i++;
606e5c89e4eSSatish Balay   }
607e5c89e4eSSatish Balay 
608e5c89e4eSSatish Balay   /* look for any other ${xxx} strings to replace from environmental variables */
6099566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(b, "${", &par));
610e5c89e4eSSatish Balay   while (par) {
611e5c89e4eSSatish Balay     *par = 0;
612e5c89e4eSSatish Balay     par += 2;
6139566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(work, b, len));
6149566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(par, "}", &epar));
615e5c89e4eSSatish Balay     *epar = 0;
616e5c89e4eSSatish Balay     epar += 1;
6179566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetenv(comm, par, env, sizeof(env), &flag));
61828b400f6SJacob Faibussowitsch     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Substitution string ${%s} not found as environmental variable", par);
6199566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(work, env, len));
6209566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(work, epar, len));
6219566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(b, work, len));
6229566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(b, "${", &par));
623e5c89e4eSSatish Balay   }
6249566063dSJacob Faibussowitsch   PetscCall(PetscFree(work));
6259566063dSJacob Faibussowitsch   if (aa == b) PetscCall(PetscFree(a));
6263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
627e5c89e4eSSatish Balay }
628e5c89e4eSSatish Balay 
629a53986e1SJed Brown /*@C
630c0d8b5b9SStefano Zampini   PetscStrcmpAny - Determines whether a string matches any of a list of strings.
631c0d8b5b9SStefano Zampini 
632c0d8b5b9SStefano Zampini   Not Collective
633c0d8b5b9SStefano Zampini 
634c0d8b5b9SStefano Zampini   Input Parameters:
635c0d8b5b9SStefano Zampini + src - pointer to input the string
636c0d8b5b9SStefano Zampini - cmp - list of non-null and non-empty strings to be compared against, pass the empty string "" to terminate the list
637c0d8b5b9SStefano Zampini 
638c0d8b5b9SStefano Zampini   Output Parameter:
639c0d8b5b9SStefano Zampini . match - `PETSC_TRUE` if the input string matches any in the list, else `PETSC_FALSE`
640c0d8b5b9SStefano Zampini 
641c0d8b5b9SStefano Zampini   Level: intermediate
642c0d8b5b9SStefano Zampini 
643*10450e9eSJacob Faibussowitsch .seealso: `PetscStrcmp()`
644c0d8b5b9SStefano Zampini @*/
645c0d8b5b9SStefano Zampini PetscErrorCode PetscStrcmpAny(const char src[], PetscBool *match, const char cmp[], ...)
646c0d8b5b9SStefano Zampini {
647c0d8b5b9SStefano Zampini   va_list Argp;
648c0d8b5b9SStefano Zampini 
649c0d8b5b9SStefano Zampini   PetscFunctionBegin;
650c0d8b5b9SStefano Zampini   PetscValidBoolPointer(match, 2);
651c0d8b5b9SStefano Zampini   *match = PETSC_FALSE;
652c0d8b5b9SStefano Zampini   if (!src) PetscFunctionReturn(PETSC_SUCCESS);
653c0d8b5b9SStefano Zampini   va_start(Argp, cmp);
654c0d8b5b9SStefano Zampini   while (cmp && cmp[0]) {
655c0d8b5b9SStefano Zampini     PetscBool found;
656c0d8b5b9SStefano Zampini     PetscCall(PetscStrcmp(src, cmp, &found));
657c0d8b5b9SStefano Zampini     if (found) {
658c0d8b5b9SStefano Zampini       *match = PETSC_TRUE;
659c0d8b5b9SStefano Zampini       break;
660c0d8b5b9SStefano Zampini     }
661c0d8b5b9SStefano Zampini     cmp = va_arg(Argp, const char *);
662c0d8b5b9SStefano Zampini   }
663c0d8b5b9SStefano Zampini   va_end(Argp);
664c0d8b5b9SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
665c0d8b5b9SStefano Zampini }
666c0d8b5b9SStefano Zampini 
667c0d8b5b9SStefano Zampini /*@C
668a53986e1SJed Brown   PetscEListFind - searches list of strings for given string, using case insensitive matching
669e5c89e4eSSatish Balay 
670667f096bSBarry Smith   Not Collective; No Fortran Support
671a53986e1SJed Brown 
672a53986e1SJed Brown   Input Parameters:
673a53986e1SJed Brown + n    - number of strings in
674a53986e1SJed Brown . list - list of strings to search
675a53986e1SJed Brown - str  - string to look for, empty string "" accepts default (first entry in list)
676a53986e1SJed Brown 
677a53986e1SJed Brown   Output Parameters:
678a53986e1SJed Brown + value - index of matching string (if found)
679667f096bSBarry Smith - found - boolean indicating whether string was found (can be `NULL`)
680811af0c4SBarry Smith 
68153c0d4aeSBarry Smith   Level: developer
68253c0d4aeSBarry Smith 
683811af0c4SBarry Smith .seealso: `PetscEnumFind()`
684a53986e1SJed Brown @*/
685d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found)
686d71ae5a4SJacob Faibussowitsch {
687a53986e1SJed Brown   PetscFunctionBegin;
6885f80ce2aSJacob Faibussowitsch   if (found) {
6895f80ce2aSJacob Faibussowitsch     PetscValidBoolPointer(found, 5);
6905f80ce2aSJacob Faibussowitsch     *found = PETSC_FALSE;
6915f80ce2aSJacob Faibussowitsch   }
6925f80ce2aSJacob Faibussowitsch   for (PetscInt i = 0; i < n; ++i) {
6935f80ce2aSJacob Faibussowitsch     PetscBool matched;
6945f80ce2aSJacob Faibussowitsch 
6959566063dSJacob Faibussowitsch     PetscCall(PetscStrcasecmp(str, list[i], &matched));
696a53986e1SJed Brown     if (matched || !str[0]) {
697a53986e1SJed Brown       if (found) *found = PETSC_TRUE;
698a53986e1SJed Brown       *value = i;
699a53986e1SJed Brown       break;
700a53986e1SJed Brown     }
701a53986e1SJed Brown   }
7023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
703a53986e1SJed Brown }
704a53986e1SJed Brown 
705a53986e1SJed Brown /*@C
7068e81d068SLisandro Dalcin   PetscEnumFind - searches enum list of strings for given string, using case insensitive matching
707a53986e1SJed Brown 
708667f096bSBarry Smith   Not Collective; No Fortran Support
709a53986e1SJed Brown 
710a53986e1SJed Brown   Input Parameters:
711667f096bSBarry Smith + enumlist - list of strings to search, followed by enum name, then enum prefix, then `NULL`
712a53986e1SJed Brown - str      - string to look for
713a53986e1SJed Brown 
714a53986e1SJed Brown   Output Parameters:
715a53986e1SJed Brown + value - index of matching string (if found)
716667f096bSBarry Smith - found - boolean indicating whether string was found (can be `NULL`)
717a53986e1SJed Brown 
718a53986e1SJed Brown   Level: advanced
719811af0c4SBarry Smith 
720811af0c4SBarry Smith .seealso: `PetscEListFind()`
721a53986e1SJed Brown @*/
722d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found)
723d71ae5a4SJacob Faibussowitsch {
724d05ba7d2SLisandro Dalcin   PetscInt  n = 0, evalue;
725a53986e1SJed Brown   PetscBool efound;
726a53986e1SJed Brown 
727a53986e1SJed Brown   PetscFunctionBegin;
7285f80ce2aSJacob Faibussowitsch   PetscValidPointer(enumlist, 1);
7295f80ce2aSJacob Faibussowitsch   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");
7305f80ce2aSJacob Faibussowitsch   PetscCheck(n >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
731a53986e1SJed Brown   n -= 3; /* drop enum name, prefix, and null termination */
7329566063dSJacob Faibussowitsch   PetscCall(PetscEListFind(n, enumlist, str, &evalue, &efound));
7335f80ce2aSJacob Faibussowitsch   if (efound) {
7345f80ce2aSJacob Faibussowitsch     PetscValidPointer(value, 3);
7355f80ce2aSJacob Faibussowitsch     *value = (PetscEnum)evalue;
7365f80ce2aSJacob Faibussowitsch   }
7375f80ce2aSJacob Faibussowitsch   if (found) {
7385f80ce2aSJacob Faibussowitsch     PetscValidBoolPointer(found, 4);
7395f80ce2aSJacob Faibussowitsch     *found = efound;
7405f80ce2aSJacob Faibussowitsch   }
7413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
742a53986e1SJed Brown }
743660278c0SBarry Smith 
744660278c0SBarry Smith /*@C
745660278c0SBarry Smith   PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled.
746660278c0SBarry Smith 
74720f4b53cSBarry Smith   Not Collective; No Fortran Support
748660278c0SBarry Smith 
749660278c0SBarry Smith   Input Parameter:
750660278c0SBarry Smith . file - the file name
751660278c0SBarry Smith 
752667f096bSBarry Smith   Level: developer
753667f096bSBarry Smith 
754660278c0SBarry Smith   Note:
755660278c0SBarry Smith   PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems
756660278c0SBarry Smith   so that comparisons of output between runs are easy to make.
757660278c0SBarry Smith 
758660278c0SBarry Smith   This mode is used for all tests in the test harness, it applies to both debug and optimized builds.
759660278c0SBarry Smith 
760667f096bSBarry Smith   Use the option `-petsc_ci` to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for
761660278c0SBarry Smith   all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness.
762660278c0SBarry Smith 
763660278c0SBarry Smith   Always uses the Unix / as the file separate even on Microsoft Windows systems
764660278c0SBarry Smith 
765667f096bSBarry Smith   The option `-petsc_ci_portable_error_output` attempts to output the same error messages on all systems for the test harness.
766660278c0SBarry Smith   In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc
767660278c0SBarry Smith   error handling by the test harness. This options also causes PETSc to attempt to return an error code of 0 so that the test
768660278c0SBarry Smith   harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test
769da81f932SPierre Jolivet   harness in the args: argument for specific examples. It will not necessarily produce portable output if different errors
770660278c0SBarry Smith   (or no errors) occur on a subset of the MPI ranks.
771660278c0SBarry Smith 
772660278c0SBarry Smith .seealso: `PetscCILinenumber()`
773660278c0SBarry Smith @*/
774d71ae5a4SJacob Faibussowitsch const char *PetscCIFilename(const char *file)
775d71ae5a4SJacob Faibussowitsch {
776660278c0SBarry Smith   if (!PetscCIEnabledPortableErrorOutput) return file;
777660278c0SBarry Smith   return PetscBasename(file);
778660278c0SBarry Smith }
779660278c0SBarry Smith 
780660278c0SBarry Smith /*@C
781811af0c4SBarry Smith   PetscCILinenumber - returns a line number except if `PetscCIEnablePortableErrorOutput` is set when it returns 0
782660278c0SBarry Smith 
783667f096bSBarry Smith   Not Collective; No Fortran Support
784660278c0SBarry Smith 
785660278c0SBarry Smith   Input Parameter:
786660278c0SBarry Smith . linenumber - the initial line number
787660278c0SBarry Smith 
788667f096bSBarry Smith   Level: developer
789667f096bSBarry Smith 
790660278c0SBarry Smith   Note:
791660278c0SBarry Smith   See `PetscCIFilename()` for details on usage
792660278c0SBarry Smith 
793660278c0SBarry Smith .seealso: `PetscCIFilename()`
794660278c0SBarry Smith @*/
795d71ae5a4SJacob Faibussowitsch int PetscCILinenumber(int linenumber)
796d71ae5a4SJacob Faibussowitsch {
797660278c0SBarry Smith   if (!PetscCIEnabledPortableErrorOutput) return linenumber;
798660278c0SBarry Smith   return 0;
799660278c0SBarry Smith }
800d11110bcSJacob Faibussowitsch 
801d11110bcSJacob Faibussowitsch /*@C
802d11110bcSJacob Faibussowitsch   PetscStrcat - Concatenates a string onto a given string
803d11110bcSJacob Faibussowitsch 
804d11110bcSJacob Faibussowitsch   Not Collective, No Fortran Support
805d11110bcSJacob Faibussowitsch 
806d11110bcSJacob Faibussowitsch   Input Parameters:
807d11110bcSJacob Faibussowitsch + s - string to be added to
808d11110bcSJacob Faibussowitsch - t - pointer to string to be added to end
809d11110bcSJacob Faibussowitsch 
810d11110bcSJacob Faibussowitsch   Level: deprecated (since 3.18.5)
811d11110bcSJacob Faibussowitsch 
812d11110bcSJacob Faibussowitsch   Notes:
813d11110bcSJacob Faibussowitsch   It is recommended you use `PetscStrlcat()` instead of this routine.
814d11110bcSJacob Faibussowitsch 
815d11110bcSJacob Faibussowitsch .seealso: `PetscStrlcat()`
816d11110bcSJacob Faibussowitsch @*/
817d11110bcSJacob Faibussowitsch PetscErrorCode PetscStrcat(char s[], const char t[])
818d11110bcSJacob Faibussowitsch {
819d11110bcSJacob Faibussowitsch   PetscFunctionBegin;
820d11110bcSJacob Faibussowitsch   if (!t) PetscFunctionReturn(PETSC_SUCCESS);
821d11110bcSJacob Faibussowitsch   PetscValidCharPointer(s, 1);
822d11110bcSJacob Faibussowitsch   strcat(s, t);
823d11110bcSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
824d11110bcSJacob Faibussowitsch }
825d11110bcSJacob Faibussowitsch 
826d11110bcSJacob Faibussowitsch /*@C
827d11110bcSJacob Faibussowitsch   PetscStrcpy - Copies a string
828d11110bcSJacob Faibussowitsch 
829d11110bcSJacob Faibussowitsch   Not Collective, No Fortran Support
830d11110bcSJacob Faibussowitsch 
8312fe279fdSBarry Smith   Input Parameter:
832d11110bcSJacob Faibussowitsch . t - pointer to string
833d11110bcSJacob Faibussowitsch 
834d11110bcSJacob Faibussowitsch   Output Parameter:
835d11110bcSJacob Faibussowitsch . s - the copied string
836d11110bcSJacob Faibussowitsch 
837d11110bcSJacob Faibussowitsch   Level: deprecated (since 3.18.5)
838d11110bcSJacob Faibussowitsch 
839d11110bcSJacob Faibussowitsch   Notes:
840d11110bcSJacob Faibussowitsch   It is recommended you use `PetscStrncpy()` (equivalently `PetscArraycpy()` or
841d11110bcSJacob Faibussowitsch   `PetscMemcpy()`) instead of this routine.
842d11110bcSJacob Faibussowitsch 
843d11110bcSJacob Faibussowitsch   `NULL` strings returns a string starting with zero.
844d11110bcSJacob Faibussowitsch 
845d11110bcSJacob Faibussowitsch .seealso: `PetscStrncpy()`
846d11110bcSJacob Faibussowitsch @*/
847d11110bcSJacob Faibussowitsch PetscErrorCode PetscStrcpy(char s[], const char t[])
848d11110bcSJacob Faibussowitsch {
849d11110bcSJacob Faibussowitsch   PetscFunctionBegin;
850d11110bcSJacob Faibussowitsch   if (t) {
851d11110bcSJacob Faibussowitsch     PetscValidCharPointer(s, 1);
852d11110bcSJacob Faibussowitsch     PetscValidCharPointer(t, 2);
853d11110bcSJacob Faibussowitsch     strcpy(s, t);
854d11110bcSJacob Faibussowitsch   } else if (s) {
855d11110bcSJacob Faibussowitsch     s[0] = '\0';
856d11110bcSJacob Faibussowitsch   }
857d11110bcSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
858d11110bcSJacob Faibussowitsch }
859