xref: /petsc/src/sys/utils/str.c (revision bbcf679c7ce315810b13005931dd3a7fb75b5053)
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 
6e5c89e4eSSatish Balay */
75f80ce2aSJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I  "petscsys.h"   I*/
83964eb88SJed Brown #if defined(PETSC_HAVE_STRINGS_H)
93964eb88SJed Brown   #include <strings.h> /* strcasecmp */
103964eb88SJed Brown #endif
113964eb88SJed Brown 
123c311c98SBarry Smith /*@C
1351a1f156SVaclav Hapla    PetscStrToArray - Separates a string by a character (for example ' ' or '\n') and creates an array of strings
143c311c98SBarry Smith 
153c311c98SBarry Smith    Not Collective
163c311c98SBarry Smith 
173c311c98SBarry Smith    Input Parameters:
18d67fe73bSBarry Smith +  s - pointer to string
1951a1f156SVaclav Hapla -  sp - separator character
203c311c98SBarry Smith 
21d8d19677SJose E. Roman    Output Parameters:
223c311c98SBarry Smith +   argc - the number of entries in the array
233c311c98SBarry Smith -   args - an array of the entries with a null at the end
243c311c98SBarry Smith 
253c311c98SBarry Smith    Level: intermediate
263c311c98SBarry Smith 
27811af0c4SBarry Smith    Note:
2895452b02SPatrick Sanan     this may be called before PetscInitialize() or after PetscFinalize()
293c311c98SBarry Smith 
30811af0c4SBarry Smith    Fortran Note:
316f013253SBarry Smith    Not for use in Fortran
326f013253SBarry Smith 
3395452b02SPatrick Sanan    Developer Notes:
34811af0c4SBarry Smith    Uses raw `malloc()` and does not call error handlers since this may be used before PETSc is initialized.
35811af0c4SBarry Smith 
36811af0c4SBarry Smith    Used to generate argc, args arguments passed to `MPI_Init()`
37301d30feSBarry Smith 
38db781477SPatrick Sanan .seealso: `PetscStrToArrayDestroy()`, `PetscToken`, `PetscTokenCreate()`
393c311c98SBarry Smith @*/
40d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrToArray(const char s[], char sp, int *argc, char ***args)
41d71ae5a4SJacob Faibussowitsch {
42c3bcdc7eSBarry Smith   int       i, j, n, *lens, cnt = 0;
43ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
443c311c98SBarry Smith 
4540a7e1efSBarry Smith   if (!s) n = 0;
4640a7e1efSBarry Smith   else n = strlen(s);
473c311c98SBarry Smith   *argc = 0;
4861528463SBarry Smith   *args = NULL;
49acf7dc08SSatish Balay   for (; n > 0; n--) { /* remove separator chars at the end - and will empty the string if all chars are separator chars */
50acf7dc08SSatish Balay     if (s[n - 1] != sp) break;
51acf7dc08SSatish Balay   }
523ba16761SJacob Faibussowitsch   if (!n) return PETSC_SUCCESS;
533c311c98SBarry Smith   for (i = 0; i < n; i++) {
54d67fe73bSBarry Smith     if (s[i] != sp) break;
553c311c98SBarry Smith   }
563c311c98SBarry Smith   for (; i < n + 1; i++) {
579371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
589371c9d4SSatish Balay       flg = PETSC_TRUE;
599371c9d4SSatish Balay       (*argc)++;
609371c9d4SSatish Balay     } else if (s[i] != sp) {
619371c9d4SSatish Balay       flg = PETSC_FALSE;
623c311c98SBarry Smith     }
639371c9d4SSatish Balay   }
649371c9d4SSatish Balay   (*args) = (char **)malloc(((*argc) + 1) * sizeof(char *));
659371c9d4SSatish Balay   if (!*args) return PETSC_ERR_MEM;
669371c9d4SSatish Balay   lens = (int *)malloc((*argc) * sizeof(int));
679371c9d4SSatish Balay   if (!lens) return PETSC_ERR_MEM;
683c311c98SBarry Smith   for (i = 0; i < *argc; i++) lens[i] = 0;
693c311c98SBarry Smith 
703c311c98SBarry Smith   *argc = 0;
713c311c98SBarry Smith   for (i = 0; i < n; i++) {
72d67fe73bSBarry Smith     if (s[i] != sp) break;
733c311c98SBarry Smith   }
747dd9f305SSatish Balay   for (; i < n + 1; i++) {
759371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
769371c9d4SSatish Balay       flg = PETSC_TRUE;
779371c9d4SSatish Balay       (*argc)++;
789371c9d4SSatish Balay     } else if (s[i] != sp) {
799371c9d4SSatish Balay       lens[*argc]++;
809371c9d4SSatish Balay       flg = PETSC_FALSE;
819371c9d4SSatish Balay     }
823c311c98SBarry Smith   }
833c311c98SBarry Smith 
843c311c98SBarry Smith   for (i = 0; i < *argc; i++) {
85c3bcdc7eSBarry Smith     (*args)[i] = (char *)malloc((lens[i] + 1) * sizeof(char));
86c3bcdc7eSBarry Smith     if (!(*args)[i]) {
87c3bcdc7eSBarry Smith       free(lens);
88c3bcdc7eSBarry Smith       for (j = 0; j < i; j++) free((*args)[j]);
89c3bcdc7eSBarry Smith       free(*args);
90c3bcdc7eSBarry Smith       return PETSC_ERR_MEM;
91c3bcdc7eSBarry Smith     }
923c311c98SBarry Smith   }
93a2ea699eSBarry Smith   free(lens);
9402c9f0b5SLisandro Dalcin   (*args)[*argc] = NULL;
953c311c98SBarry Smith 
963c311c98SBarry Smith   *argc = 0;
973c311c98SBarry Smith   for (i = 0; i < n; i++) {
98d67fe73bSBarry Smith     if (s[i] != sp) break;
993c311c98SBarry Smith   }
1003c311c98SBarry Smith   for (; i < n + 1; i++) {
1019371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
1029371c9d4SSatish Balay       flg                   = PETSC_TRUE;
1039371c9d4SSatish Balay       (*args)[*argc][cnt++] = 0;
1049371c9d4SSatish Balay       (*argc)++;
1059371c9d4SSatish Balay       cnt = 0;
1069371c9d4SSatish Balay     } else if (s[i] != sp && s[i] != 0) {
1079371c9d4SSatish Balay       (*args)[*argc][cnt++] = s[i];
1089371c9d4SSatish Balay       flg                   = PETSC_FALSE;
1099371c9d4SSatish Balay     }
1103c311c98SBarry Smith   }
1113ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
1123c311c98SBarry Smith }
1133c311c98SBarry Smith 
114301d30feSBarry Smith /*@C
115811af0c4SBarry Smith    PetscStrToArrayDestroy - Frees array created with `PetscStrToArray()`.
116301d30feSBarry Smith 
117301d30feSBarry Smith    Not Collective
118301d30feSBarry Smith 
119301d30feSBarry Smith    Output Parameters:
120301d30feSBarry Smith +  argc - the number of arguments
121301d30feSBarry Smith -  args - the array of arguments
122301d30feSBarry Smith 
123301d30feSBarry Smith    Level: intermediate
124301d30feSBarry Smith 
125811af0c4SBarry Smith    Note:
126811af0c4SBarry Smith     This may be called before `PetscInitialize()` or after `PetscFinalize()`
127301d30feSBarry Smith 
128811af0c4SBarry Smith    Fortran Note:
1296f013253SBarry Smith    Not for use in Fortran
1306f013253SBarry Smith 
131db781477SPatrick Sanan .seealso: `PetscStrToArray()`
132301d30feSBarry Smith @*/
133d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrToArrayDestroy(int argc, char **args)
134d71ae5a4SJacob Faibussowitsch {
1355f80ce2aSJacob Faibussowitsch   for (int i = 0; i < argc; ++i) free(args[i]);
136a297a907SKarl Rupp   if (args) free(args);
1373ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
138301d30feSBarry Smith }
139301d30feSBarry Smith 
140e5c89e4eSSatish Balay /*@C
14147340559SBarry Smith    PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
14247340559SBarry Smith 
14347340559SBarry Smith    Not Collective
14447340559SBarry Smith 
14547340559SBarry Smith    Input Parameters:
14647340559SBarry Smith .  s - pointer to array of strings (final string is a null)
14747340559SBarry Smith 
14847340559SBarry Smith    Output Parameter:
14947340559SBarry Smith .  t - the copied array string
15047340559SBarry Smith 
15147340559SBarry Smith    Level: intermediate
15247340559SBarry Smith 
15347340559SBarry Smith    Note:
154811af0c4SBarry Smith    If t has previously been allocated then that memory is lost, you may need to PetscStrArrayDestroy()
1550ecf5a55SBarry Smith    the array before calling this routine.
1560ecf5a55SBarry Smith 
157811af0c4SBarry Smith    Fortran Note:
158811af0c4SBarry Smith    Not for use in Fortran
15947340559SBarry Smith 
160811af0c4SBarry Smith .seealso: `PetscStrallocpy()`, `PetscStrArrayDestroy()`, `PetscStrNArrayallocpy()`
16147340559SBarry Smith @*/
162d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrArrayallocpy(const char *const *list, char ***t)
163d71ae5a4SJacob Faibussowitsch {
1645f80ce2aSJacob Faibussowitsch   PetscInt n = 0;
16547340559SBarry Smith 
16647340559SBarry Smith   PetscFunctionBegin;
1679371c9d4SSatish Balay   while (list[n++])
1689371c9d4SSatish Balay     ;
1699566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n + 1, t));
1709566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
1710298fd71SBarry Smith   (*t)[n] = NULL;
1723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17347340559SBarry Smith }
17447340559SBarry Smith 
17547340559SBarry Smith /*@C
176811af0c4SBarry Smith    PetscStrArrayDestroy - Frees array of strings created with `PetscStrArrayallocpy()`.
17747340559SBarry Smith 
17847340559SBarry Smith    Not Collective
17947340559SBarry Smith 
18047340559SBarry Smith    Output Parameters:
18147340559SBarry Smith .   list - array of strings
18247340559SBarry Smith 
18347340559SBarry Smith    Level: intermediate
18447340559SBarry Smith 
185811af0c4SBarry Smith    Fortran Note:
18695452b02SPatrick Sanan     Not for use in Fortran
18747340559SBarry Smith 
188db781477SPatrick Sanan .seealso: `PetscStrArrayallocpy()`
18947340559SBarry Smith @*/
190d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrArrayDestroy(char ***list)
191d71ae5a4SJacob Faibussowitsch {
19247340559SBarry Smith   PetscInt n = 0;
19347340559SBarry Smith 
1946fed8037SJed Brown   PetscFunctionBegin;
1953ba16761SJacob Faibussowitsch   if (!*list) PetscFunctionReturn(PETSC_SUCCESS);
1966fed8037SJed Brown   while ((*list)[n]) {
1979566063dSJacob Faibussowitsch     PetscCall(PetscFree((*list)[n]));
1985f80ce2aSJacob Faibussowitsch     ++n;
19947340559SBarry Smith   }
2009566063dSJacob Faibussowitsch   PetscCall(PetscFree(*list));
2013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20247340559SBarry Smith }
20347340559SBarry Smith 
2046991f827SBarry Smith /*@C
2056991f827SBarry Smith    PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
2066991f827SBarry Smith 
2076991f827SBarry Smith    Not Collective
2086991f827SBarry Smith 
2096991f827SBarry Smith    Input Parameters:
2106991f827SBarry Smith +  n - the number of string entries
2116991f827SBarry Smith -  s - pointer to array of strings
2126991f827SBarry Smith 
2136991f827SBarry Smith    Output Parameter:
2146991f827SBarry Smith .  t - the copied array string
2156991f827SBarry Smith 
2166991f827SBarry Smith    Level: intermediate
2176991f827SBarry Smith 
218811af0c4SBarry Smith    Fortran Note:
2196991f827SBarry Smith       Not for use in Fortran
2206991f827SBarry Smith 
221db781477SPatrick Sanan .seealso: `PetscStrallocpy()`, `PetscStrArrayallocpy()`, `PetscStrNArrayDestroy()`
2226991f827SBarry Smith @*/
223d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrNArrayallocpy(PetscInt n, const char *const *list, char ***t)
224d71ae5a4SJacob Faibussowitsch {
2256991f827SBarry Smith   PetscFunctionBegin;
2269566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, t));
2279566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
2283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2296991f827SBarry Smith }
2306991f827SBarry Smith 
2316991f827SBarry Smith /*@C
232811af0c4SBarry Smith    PetscStrNArrayDestroy - Frees array of strings created with `PetscStrNArrayallocpy()`.
2336991f827SBarry Smith 
2346991f827SBarry Smith    Not Collective
2356991f827SBarry Smith 
2366991f827SBarry Smith    Output Parameters:
2376991f827SBarry Smith +   n - number of string entries
2386991f827SBarry Smith -   list - array of strings
2396991f827SBarry Smith 
2406991f827SBarry Smith    Level: intermediate
2416991f827SBarry Smith 
242811af0c4SBarry Smith    Fortran Note:
24395452b02SPatrick Sanan     Not for use in Fortran
2446991f827SBarry Smith 
245811af0c4SBarry Smith .seealso: `PetscStrNArrayallocpy()`, `PetscStrArrayallocpy()`
2466991f827SBarry Smith @*/
247d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrNArrayDestroy(PetscInt n, char ***list)
248d71ae5a4SJacob Faibussowitsch {
2496991f827SBarry Smith   PetscFunctionBegin;
2503ba16761SJacob Faibussowitsch   if (!*list) PetscFunctionReturn(PETSC_SUCCESS);
2519566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscFree((*list)[i]));
2529566063dSJacob Faibussowitsch   PetscCall(PetscFree(*list));
2533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2546991f827SBarry Smith }
2556991f827SBarry Smith 
256e5c89e4eSSatish Balay /*@C
257811af0c4SBarry Smith    PetscBasename - returns a pointer to the last entry of a / or \ separated directory path
25880b92c66SBarry Smith 
25980b92c66SBarry Smith    Not Collective
26080b92c66SBarry Smith 
26180b92c66SBarry Smith    Input Parameter:
26280b92c66SBarry Smith .  a - pointer to string
26380b92c66SBarry Smith 
26480b92c66SBarry Smith    Level: intermediate
26580b92c66SBarry Smith 
266811af0c4SBarry Smith    Fortran Note:
26780b92c66SBarry Smith     Not for use in Fortran
26880b92c66SBarry Smith 
26980b92c66SBarry Smith .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`, `PetscStrrchr()`, `PetscStrcmp()`, `PetscStrstr()`,
27080b92c66SBarry Smith           `PetscTokenCreate()`, `PetscStrToArray()`, `PetscStrInList()`
27180b92c66SBarry Smith @*/
272d71ae5a4SJacob Faibussowitsch const char *PetscBasename(const char a[])
273d71ae5a4SJacob Faibussowitsch {
274*bbcf679cSJacob Faibussowitsch   const char *ptr = NULL;
27580b92c66SBarry Smith 
276*bbcf679cSJacob Faibussowitsch   (void)PetscStrrchr(a, '/', (char **)&ptr);
277660278c0SBarry Smith   if (ptr == a) {
278660278c0SBarry Smith     if (PetscStrrchr(a, '\\', (char **)&ptr)) ptr = NULL;
279660278c0SBarry Smith   }
28080b92c66SBarry Smith   return ptr;
28180b92c66SBarry Smith }
28280b92c66SBarry Smith 
28380b92c66SBarry Smith /*@C
284e5c89e4eSSatish Balay    PetscStrcasecmp - Returns true if the two strings are the same
285e5c89e4eSSatish Balay      except possibly for case.
286e5c89e4eSSatish Balay 
287e5c89e4eSSatish Balay    Not Collective
288e5c89e4eSSatish Balay 
289e5c89e4eSSatish Balay    Input Parameters:
290e5c89e4eSSatish Balay +  a - pointer to first string
291e5c89e4eSSatish Balay -  b - pointer to second string
292e5c89e4eSSatish Balay 
293e5c89e4eSSatish Balay    Output Parameter:
294e5c89e4eSSatish Balay .  flg - if the two strings are the same
295e5c89e4eSSatish Balay 
296811af0c4SBarry Smith    Note:
297e5c89e4eSSatish Balay     Null arguments are ok
298e5c89e4eSSatish Balay 
299811af0c4SBarry Smith    Fortran Note:
3006f013253SBarry Smith    Not for use in Fortran
3016f013253SBarry Smith 
302e5c89e4eSSatish Balay    Level: intermediate
303e5c89e4eSSatish Balay 
304db781477SPatrick Sanan .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrgrt()`
305e5c89e4eSSatish Balay @*/
306d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t)
307d71ae5a4SJacob Faibussowitsch {
308e5c89e4eSSatish Balay   int c;
309e5c89e4eSSatish Balay 
310e5c89e4eSSatish Balay   PetscFunctionBegin;
3115f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(t, 3);
312e5c89e4eSSatish Balay   if (!a && !b) c = 0;
313e5c89e4eSSatish Balay   else if (!a || !b) c = 1;
31432b366c8SSatish Balay #if defined(PETSC_HAVE_STRCASECMP)
31532b366c8SSatish Balay   else c = strcasecmp(a, b);
31632b366c8SSatish Balay #elif defined(PETSC_HAVE_STRICMP)
317e5c89e4eSSatish Balay   else c = stricmp(a, b);
318e5c89e4eSSatish Balay #else
31932b366c8SSatish Balay   else {
32032b366c8SSatish Balay     char *aa, *bb;
321*bbcf679cSJacob Faibussowitsch 
3229566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(a, &aa));
3239566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(b, &bb));
3249566063dSJacob Faibussowitsch     PetscCall(PetscStrtolower(aa));
3259566063dSJacob Faibussowitsch     PetscCall(PetscStrtolower(bb));
3269566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(aa, bb, t));
3279566063dSJacob Faibussowitsch     PetscCall(PetscFree(aa));
3289566063dSJacob Faibussowitsch     PetscCall(PetscFree(bb));
3293ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
33032b366c8SSatish Balay   }
331e5c89e4eSSatish Balay #endif
3325f80ce2aSJacob Faibussowitsch   *t = c ? PETSC_FALSE : PETSC_TRUE;
3333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
334e5c89e4eSSatish Balay }
335e5c89e4eSSatish Balay 
336e5c89e4eSSatish Balay /*@C
3377ba3a57cSBarry Smith    PetscStrendswithwhich - Determines if a string ends with one of several possible strings
3387ba3a57cSBarry Smith 
3397ba3a57cSBarry Smith    Not Collective
3407ba3a57cSBarry Smith 
3417ba3a57cSBarry Smith    Input Parameters:
3427ba3a57cSBarry Smith +  a - pointer to string
343fa4b66f2SVaclav Hapla -  bs - strings to end with (last entry must be NULL)
3447ba3a57cSBarry Smith 
3457ba3a57cSBarry Smith    Output Parameter:
346fa4b66f2SVaclav Hapla .  cnt - the index of the string it ends with or the index of NULL
3477ba3a57cSBarry Smith 
348811af0c4SBarry Smith    Fortran Note:
34995452b02SPatrick Sanan     Not for use in Fortran
3507ba3a57cSBarry Smith 
3517ba3a57cSBarry Smith    Level: intermediate
3527ba3a57cSBarry Smith 
353811af0c4SBarry Smith .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
354811af0c4SBarry Smith           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()`
3557ba3a57cSBarry Smith @*/
356d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt)
357d71ae5a4SJacob Faibussowitsch {
3587ba3a57cSBarry Smith   PetscFunctionBegin;
3595f80ce2aSJacob Faibussowitsch   PetscValidPointer(bs, 2);
3605f80ce2aSJacob Faibussowitsch   PetscValidIntPointer(cnt, 3);
3617ba3a57cSBarry Smith   *cnt = 0;
3627ba3a57cSBarry Smith   while (bs[*cnt]) {
3635f80ce2aSJacob Faibussowitsch     PetscBool flg;
3645f80ce2aSJacob Faibussowitsch 
3659566063dSJacob Faibussowitsch     PetscCall(PetscStrendswith(a, bs[*cnt], &flg));
3663ba16761SJacob Faibussowitsch     if (flg) PetscFunctionReturn(PETSC_SUCCESS);
3675f80ce2aSJacob Faibussowitsch     ++(*cnt);
3687ba3a57cSBarry Smith   }
3693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3707ba3a57cSBarry Smith }
3717ba3a57cSBarry Smith 
3729371c9d4SSatish Balay struct _p_PetscToken {
3739371c9d4SSatish Balay   char  token;
3749371c9d4SSatish Balay   char *array;
3759371c9d4SSatish Balay   char *current;
3769371c9d4SSatish Balay };
3771d1a0024SBarry Smith 
378e5c89e4eSSatish Balay /*@C
379e5c89e4eSSatish Balay    PetscTokenFind - Locates next "token" in a string
380e5c89e4eSSatish Balay 
381e5c89e4eSSatish Balay    Not Collective
382e5c89e4eSSatish Balay 
383e5c89e4eSSatish Balay    Input Parameters:
384e5c89e4eSSatish Balay .  a - pointer to token
385e5c89e4eSSatish Balay 
386e5c89e4eSSatish Balay    Output Parameter:
387a5b23f4aSJose E. Roman .  result - location of occurrence, NULL if not found
388e5c89e4eSSatish Balay 
389e5c89e4eSSatish Balay    Notes:
390e5c89e4eSSatish Balay      This version is different from the system version in that
391e5c89e4eSSatish Balay   it allows you to pass a read-only string into the function.
392e5c89e4eSSatish Balay 
3934704e885SBarry Smith      This version also treats all characters etc. inside a double quote "
3944704e885SBarry Smith    as a single token.
3954704e885SBarry Smith 
3963a9c465aSBarry 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
3973a9c465aSBarry Smith    second will return a null terminated y
3983a9c465aSBarry Smith 
3993a9c465aSBarry 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
4003a9c465aSBarry Smith 
401811af0c4SBarry Smith    Fortran Note:
4026f013253SBarry Smith     Not for use in Fortran
4036f013253SBarry Smith 
404e5c89e4eSSatish Balay    Level: intermediate
405e5c89e4eSSatish Balay 
406db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenDestroy()`
407e5c89e4eSSatish Balay @*/
408d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTokenFind(PetscToken a, char *result[])
409d71ae5a4SJacob Faibussowitsch {
4105f80ce2aSJacob Faibussowitsch   char *ptr, token;
411e5c89e4eSSatish Balay 
412e5c89e4eSSatish Balay   PetscFunctionBegin;
4135f80ce2aSJacob Faibussowitsch   PetscValidPointer(a, 1);
4145f80ce2aSJacob Faibussowitsch   PetscValidPointer(result, 2);
4155f80ce2aSJacob Faibussowitsch   *result = ptr = a->current;
4169371c9d4SSatish Balay   if (ptr && !*ptr) {
4179371c9d4SSatish Balay     *result = NULL;
4183ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
4199371c9d4SSatish Balay   }
4204704e885SBarry Smith   token = a->token;
4219371c9d4SSatish Balay   if (ptr && (*ptr == '"')) {
4229371c9d4SSatish Balay     token = '"';
4239371c9d4SSatish Balay     (*result)++;
4249371c9d4SSatish Balay     ptr++;
4259371c9d4SSatish Balay   }
426e5c89e4eSSatish Balay   while (ptr) {
4274704e885SBarry Smith     if (*ptr == token) {
428e5c89e4eSSatish Balay       *ptr++ = 0;
429e5c89e4eSSatish Balay       while (*ptr == a->token) ptr++;
430e5c89e4eSSatish Balay       a->current = ptr;
431e5c89e4eSSatish Balay       break;
432e5c89e4eSSatish Balay     }
433e5c89e4eSSatish Balay     if (!*ptr) {
43402c9f0b5SLisandro Dalcin       a->current = NULL;
435e5c89e4eSSatish Balay       break;
436e5c89e4eSSatish Balay     }
437e5c89e4eSSatish Balay     ptr++;
438e5c89e4eSSatish Balay   }
4393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
440e5c89e4eSSatish Balay }
441e5c89e4eSSatish Balay 
442e5c89e4eSSatish Balay /*@C
443811af0c4SBarry Smith    PetscTokenCreate - Creates a `PetscToken` used to find tokens in a string
444e5c89e4eSSatish Balay 
445e5c89e4eSSatish Balay    Not Collective
446e5c89e4eSSatish Balay 
447e5c89e4eSSatish Balay    Input Parameters:
448e5c89e4eSSatish Balay +  string - the string to look in
4493a9c465aSBarry Smith -  b - the separator character
450e5c89e4eSSatish Balay 
451e5c89e4eSSatish Balay    Output Parameter:
4523a9c465aSBarry Smith .  t- the token object
453e5c89e4eSSatish Balay 
454811af0c4SBarry Smith    Note:
455e5c89e4eSSatish Balay      This version is different from the system version in that
456e5c89e4eSSatish Balay   it allows you to pass a read-only string into the function.
457e5c89e4eSSatish Balay 
458811af0c4SBarry Smith    Fortran Note:
4596f013253SBarry Smith     Not for use in Fortran
4606f013253SBarry Smith 
461e5c89e4eSSatish Balay    Level: intermediate
462e5c89e4eSSatish Balay 
463db781477SPatrick Sanan .seealso: `PetscTokenFind()`, `PetscTokenDestroy()`
464e5c89e4eSSatish Balay @*/
46598e514b7SJacob Faibussowitsch PetscErrorCode PetscTokenCreate(const char a[], char b, PetscToken *t)
466d71ae5a4SJacob Faibussowitsch {
467e5c89e4eSSatish Balay   PetscFunctionBegin;
4685f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
4695f80ce2aSJacob Faibussowitsch   PetscValidPointer(t, 3);
4709566063dSJacob Faibussowitsch   PetscCall(PetscNew(t));
4719566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(a, &(*t)->array));
472a297a907SKarl Rupp 
473e5c89e4eSSatish Balay   (*t)->current = (*t)->array;
474e5c89e4eSSatish Balay   (*t)->token   = b;
4753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
476e5c89e4eSSatish Balay }
477e5c89e4eSSatish Balay 
478e5c89e4eSSatish Balay /*@C
479811af0c4SBarry Smith    PetscTokenDestroy - Destroys a `PetscToken`
480e5c89e4eSSatish Balay 
481e5c89e4eSSatish Balay    Not Collective
482e5c89e4eSSatish Balay 
483e5c89e4eSSatish Balay    Input Parameters:
484e5c89e4eSSatish Balay .  a - pointer to token
485e5c89e4eSSatish Balay 
486e5c89e4eSSatish Balay    Level: intermediate
487e5c89e4eSSatish Balay 
488811af0c4SBarry Smith    Fortran Note:
48995452b02SPatrick Sanan     Not for use in Fortran
4906f013253SBarry Smith 
491db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenFind()`
492e5c89e4eSSatish Balay @*/
493d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTokenDestroy(PetscToken *a)
494d71ae5a4SJacob Faibussowitsch {
495e5c89e4eSSatish Balay   PetscFunctionBegin;
4963ba16761SJacob Faibussowitsch   if (!*a) PetscFunctionReturn(PETSC_SUCCESS);
4979566063dSJacob Faibussowitsch   PetscCall(PetscFree((*a)->array));
4989566063dSJacob Faibussowitsch   PetscCall(PetscFree(*a));
4993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
500e5c89e4eSSatish Balay }
501e5c89e4eSSatish Balay 
5028e81d068SLisandro Dalcin /*@C
503811af0c4SBarry Smith    PetscStrInList - search for string in character-delimited list
5048e81d068SLisandro Dalcin 
5058e81d068SLisandro Dalcin    Not Collective
5068e81d068SLisandro Dalcin 
5078e81d068SLisandro Dalcin    Input Parameters:
5088e81d068SLisandro Dalcin +  str - the string to look for
5098e81d068SLisandro Dalcin .  list - the list to search in
5108e81d068SLisandro Dalcin -  sep - the separator character
5118e81d068SLisandro Dalcin 
5128e81d068SLisandro Dalcin    Output Parameter:
5138e81d068SLisandro Dalcin .  found - whether str is in list
5148e81d068SLisandro Dalcin 
5158e81d068SLisandro Dalcin    Level: intermediate
5168e81d068SLisandro Dalcin 
517811af0c4SBarry Smith    Fortran Note:
51895452b02SPatrick Sanan     Not for use in Fortran
5198e81d068SLisandro Dalcin 
520db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()`
5218e81d068SLisandro Dalcin @*/
522d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found)
523d71ae5a4SJacob Faibussowitsch {
5248e81d068SLisandro Dalcin   PetscToken token;
5258e81d068SLisandro Dalcin   char      *item;
5268e81d068SLisandro Dalcin 
5278e81d068SLisandro Dalcin   PetscFunctionBegin;
5285f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(found, 4);
5298e81d068SLisandro Dalcin   *found = PETSC_FALSE;
5309566063dSJacob Faibussowitsch   PetscCall(PetscTokenCreate(list, sep, &token));
5319566063dSJacob Faibussowitsch   PetscCall(PetscTokenFind(token, &item));
5328e81d068SLisandro Dalcin   while (item) {
5339566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(str, item, found));
5348e81d068SLisandro Dalcin     if (*found) break;
5359566063dSJacob Faibussowitsch     PetscCall(PetscTokenFind(token, &item));
5368e81d068SLisandro Dalcin   }
5379566063dSJacob Faibussowitsch   PetscCall(PetscTokenDestroy(&token));
5383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5398e81d068SLisandro Dalcin }
540e5c89e4eSSatish Balay 
541e5c89e4eSSatish Balay /*@C
542e5c89e4eSSatish Balay    PetscGetPetscDir - Gets the directory PETSc is installed in
543e5c89e4eSSatish Balay 
544e5c89e4eSSatish Balay    Not Collective
545e5c89e4eSSatish Balay 
546e5c89e4eSSatish Balay    Output Parameter:
547e5c89e4eSSatish Balay .  dir - the directory
548e5c89e4eSSatish Balay 
549e5c89e4eSSatish Balay    Level: developer
550e5c89e4eSSatish Balay 
551811af0c4SBarry Smith    Fortran Note:
55295452b02SPatrick Sanan     Not for use in Fortran
5536f013253SBarry Smith 
554e5c89e4eSSatish Balay @*/
555d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGetPetscDir(const char *dir[])
556d71ae5a4SJacob Faibussowitsch {
557e5c89e4eSSatish Balay   PetscFunctionBegin;
5585f80ce2aSJacob Faibussowitsch   PetscValidPointer(dir, 1);
559e5c89e4eSSatish Balay   *dir = PETSC_DIR;
5603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
561e5c89e4eSSatish Balay }
562e5c89e4eSSatish Balay 
563e5c89e4eSSatish Balay /*@C
564e5c89e4eSSatish Balay    PetscStrreplace - Replaces substrings in string with other substrings
565e5c89e4eSSatish Balay 
566e5c89e4eSSatish Balay    Not Collective
567e5c89e4eSSatish Balay 
568e5c89e4eSSatish Balay    Input Parameters:
569811af0c4SBarry Smith +   comm - `MPI_Comm` of processors that are processing the string
57071573d7dSBarry Smith .   aa - the string to look in
571d8ccf1fbSBarry Smith .   b - the resulting copy of a with replaced strings (b can be the same as a)
572e5c89e4eSSatish Balay -   len - the length of b
573e5c89e4eSSatish Balay 
574e5c89e4eSSatish Balay    Notes:
575e5c89e4eSSatish Balay       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
576d5649816SBarry Smith       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values
577e5c89e4eSSatish Balay       as well as any environmental variables.
578e5c89e4eSSatish Balay 
579811af0c4SBarry Smith       `PETSC_LIB_DIR` uses the environmental variable if it exists. `PETSC_ARCH` and `PETSC_DIR` use what
580acc6cc86SBarry Smith       PETSc was built with and do not use environmental variables.
581acc6cc86SBarry Smith 
582811af0c4SBarry Smith    Fortran Note:
5836f013253SBarry Smith       Not for use in Fortran
5846f013253SBarry Smith 
585811af0c4SBarry Smith    Level: developer
586e5c89e4eSSatish Balay 
587e5c89e4eSSatish Balay @*/
588d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len)
589d71ae5a4SJacob Faibussowitsch {
590e5c89e4eSSatish Balay   int           i = 0;
591e5c89e4eSSatish Balay   size_t        l, l1, l2, l3;
59271573d7dSBarry Smith   char         *work, *par, *epar, env[1024], *tfree, *a = (char *)aa;
59302c9f0b5SLisandro Dalcin   const char   *s[] = {"${PETSC_ARCH}", "${PETSC_DIR}", "${PETSC_LIB_DIR}", "${DISPLAY}", "${HOMEDIRECTORY}", "${WORKINGDIRECTORY}", "${USERNAME}", "${HOSTNAME}", NULL};
59402c9f0b5SLisandro Dalcin   char         *r[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
595ace3abfcSBarry Smith   PetscBool     flag;
596589a23caSBarry Smith   static size_t DISPLAY_LENGTH = 265, USER_LENGTH = 256, HOST_LENGTH = 256;
597e5c89e4eSSatish Balay 
598e5c89e4eSSatish Balay   PetscFunctionBegin;
5995f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(aa, 2);
6005f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(b, 3);
6019566063dSJacob Faibussowitsch   if (aa == b) PetscCall(PetscStrallocpy(aa, (char **)&a));
6029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(len, &work));
603e5c89e4eSSatish Balay 
604e5c89e4eSSatish Balay   /* get values for replaced variables */
6059566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_ARCH, &r[0]));
6069566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_DIR, &r[1]));
6079566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_LIB_DIR, &r[2]));
6089566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(DISPLAY_LENGTH, &r[3]));
6099566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[4]));
6109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[5]));
6119566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(USER_LENGTH, &r[6]));
6129566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(HOST_LENGTH, &r[7]));
6139566063dSJacob Faibussowitsch   PetscCall(PetscGetDisplay(r[3], DISPLAY_LENGTH));
6149566063dSJacob Faibussowitsch   PetscCall(PetscGetHomeDirectory(r[4], PETSC_MAX_PATH_LEN));
6159566063dSJacob Faibussowitsch   PetscCall(PetscGetWorkingDirectory(r[5], PETSC_MAX_PATH_LEN));
6169566063dSJacob Faibussowitsch   PetscCall(PetscGetUserName(r[6], USER_LENGTH));
6179566063dSJacob Faibussowitsch   PetscCall(PetscGetHostName(r[7], HOST_LENGTH));
618487e5849SBarry Smith 
619487e5849SBarry Smith   /* replace that are in environment */
6209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetenv(comm, "PETSC_LIB_DIR", env, sizeof(env), &flag));
621487e5849SBarry Smith   if (flag) {
6229566063dSJacob Faibussowitsch     PetscCall(PetscFree(r[2]));
6239566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(env, &r[2]));
624487e5849SBarry Smith   }
625e5c89e4eSSatish Balay 
626e5c89e4eSSatish Balay   /* replace the requested strings */
6279566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(b, a, len));
628e5c89e4eSSatish Balay   while (s[i]) {
6299566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(s[i], &l));
6309566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(b, s[i], &par));
631e5c89e4eSSatish Balay     while (par) {
632e5c89e4eSSatish Balay       *par = 0;
633e5c89e4eSSatish Balay       par += l;
634e5c89e4eSSatish Balay 
6359566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(b, &l1));
6369566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(r[i], &l2));
6379566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(par, &l3));
638cc73adaaSBarry Smith       PetscCheck(l1 + l2 + l3 < len, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "b len is not long enough to hold new values");
6399566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(work, b, len));
6409566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(work, r[i], len));
6419566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(work, par, len));
6429566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(b, work, len));
6439566063dSJacob Faibussowitsch       PetscCall(PetscStrstr(b, s[i], &par));
644e5c89e4eSSatish Balay     }
645e5c89e4eSSatish Balay     i++;
646e5c89e4eSSatish Balay   }
647487e5849SBarry Smith   i = 0;
648487e5849SBarry Smith   while (r[i]) {
649e5c89e4eSSatish Balay     tfree = (char *)r[i];
6509566063dSJacob Faibussowitsch     PetscCall(PetscFree(tfree));
651487e5849SBarry Smith     i++;
652e5c89e4eSSatish Balay   }
653e5c89e4eSSatish Balay 
654e5c89e4eSSatish Balay   /* look for any other ${xxx} strings to replace from environmental variables */
6559566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(b, "${", &par));
656e5c89e4eSSatish Balay   while (par) {
657e5c89e4eSSatish Balay     *par = 0;
658e5c89e4eSSatish Balay     par += 2;
6599566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(work, b, len));
6609566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(par, "}", &epar));
661e5c89e4eSSatish Balay     *epar = 0;
662e5c89e4eSSatish Balay     epar += 1;
6639566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetenv(comm, par, env, sizeof(env), &flag));
66428b400f6SJacob Faibussowitsch     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Substitution string ${%s} not found as environmental variable", par);
6659566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(work, env, len));
6669566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(work, epar, len));
6679566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(b, work, len));
6689566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(b, "${", &par));
669e5c89e4eSSatish Balay   }
6709566063dSJacob Faibussowitsch   PetscCall(PetscFree(work));
6719566063dSJacob Faibussowitsch   if (aa == b) PetscCall(PetscFree(a));
6723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
673e5c89e4eSSatish Balay }
674e5c89e4eSSatish Balay 
675a53986e1SJed Brown /*@C
676a53986e1SJed Brown    PetscEListFind - searches list of strings for given string, using case insensitive matching
677e5c89e4eSSatish Balay 
678a53986e1SJed Brown    Not Collective
679a53986e1SJed Brown 
680a53986e1SJed Brown    Input Parameters:
681a53986e1SJed Brown +  n - number of strings in
682a53986e1SJed Brown .  list - list of strings to search
683a53986e1SJed Brown -  str - string to look for, empty string "" accepts default (first entry in list)
684a53986e1SJed Brown 
685a53986e1SJed Brown    Output Parameters:
686a53986e1SJed Brown +  value - index of matching string (if found)
687a53986e1SJed Brown -  found - boolean indicating whether string was found (can be NULL)
688a53986e1SJed Brown 
689811af0c4SBarry Smith    Fortran Note:
690a53986e1SJed Brown    Not for use in Fortran
691a53986e1SJed Brown 
692a53986e1SJed Brown    Level: advanced
693811af0c4SBarry Smith 
694811af0c4SBarry Smith .seealso: `PetscEnumFind()`
695a53986e1SJed Brown @*/
696d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found)
697d71ae5a4SJacob Faibussowitsch {
698a53986e1SJed Brown   PetscFunctionBegin;
6995f80ce2aSJacob Faibussowitsch   if (found) {
7005f80ce2aSJacob Faibussowitsch     PetscValidBoolPointer(found, 5);
7015f80ce2aSJacob Faibussowitsch     *found = PETSC_FALSE;
7025f80ce2aSJacob Faibussowitsch   }
7035f80ce2aSJacob Faibussowitsch   for (PetscInt i = 0; i < n; ++i) {
7045f80ce2aSJacob Faibussowitsch     PetscBool matched;
7055f80ce2aSJacob Faibussowitsch 
7069566063dSJacob Faibussowitsch     PetscCall(PetscStrcasecmp(str, list[i], &matched));
707a53986e1SJed Brown     if (matched || !str[0]) {
708a53986e1SJed Brown       if (found) *found = PETSC_TRUE;
709a53986e1SJed Brown       *value = i;
710a53986e1SJed Brown       break;
711a53986e1SJed Brown     }
712a53986e1SJed Brown   }
7133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
714a53986e1SJed Brown }
715a53986e1SJed Brown 
716a53986e1SJed Brown /*@C
7178e81d068SLisandro Dalcin    PetscEnumFind - searches enum list of strings for given string, using case insensitive matching
718a53986e1SJed Brown 
719a53986e1SJed Brown    Not Collective
720a53986e1SJed Brown 
721a53986e1SJed Brown    Input Parameters:
722a53986e1SJed Brown +  enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL
723a53986e1SJed Brown -  str - string to look for
724a53986e1SJed Brown 
725a53986e1SJed Brown    Output Parameters:
726a53986e1SJed Brown +  value - index of matching string (if found)
727a53986e1SJed Brown -  found - boolean indicating whether string was found (can be NULL)
728a53986e1SJed Brown 
729811af0c4SBarry Smith    Fortran Note:
730a53986e1SJed Brown    Not for use in Fortran
731a53986e1SJed Brown 
732a53986e1SJed Brown    Level: advanced
733811af0c4SBarry Smith 
734811af0c4SBarry Smith .seealso: `PetscEListFind()`
735a53986e1SJed Brown @*/
736d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found)
737d71ae5a4SJacob Faibussowitsch {
738d05ba7d2SLisandro Dalcin   PetscInt  n = 0, evalue;
739a53986e1SJed Brown   PetscBool efound;
740a53986e1SJed Brown 
741a53986e1SJed Brown   PetscFunctionBegin;
7425f80ce2aSJacob Faibussowitsch   PetscValidPointer(enumlist, 1);
7435f80ce2aSJacob 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");
7445f80ce2aSJacob Faibussowitsch   PetscCheck(n >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
745a53986e1SJed Brown   n -= 3; /* drop enum name, prefix, and null termination */
7469566063dSJacob Faibussowitsch   PetscCall(PetscEListFind(n, enumlist, str, &evalue, &efound));
7475f80ce2aSJacob Faibussowitsch   if (efound) {
7485f80ce2aSJacob Faibussowitsch     PetscValidPointer(value, 3);
7495f80ce2aSJacob Faibussowitsch     *value = (PetscEnum)evalue;
7505f80ce2aSJacob Faibussowitsch   }
7515f80ce2aSJacob Faibussowitsch   if (found) {
7525f80ce2aSJacob Faibussowitsch     PetscValidBoolPointer(found, 4);
7535f80ce2aSJacob Faibussowitsch     *found = efound;
7545f80ce2aSJacob Faibussowitsch   }
7553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
756a53986e1SJed Brown }
757660278c0SBarry Smith 
758660278c0SBarry Smith /*@C
759660278c0SBarry Smith   PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled.
760660278c0SBarry Smith 
761660278c0SBarry Smith   Not collective
762660278c0SBarry Smith 
763660278c0SBarry Smith   Input Parameter:
764660278c0SBarry Smith . file - the file name
765660278c0SBarry Smith 
766660278c0SBarry Smith   Note:
767660278c0SBarry Smith   PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems
768660278c0SBarry Smith   so that comparisons of output between runs are easy to make.
769660278c0SBarry Smith 
770660278c0SBarry Smith   This mode is used for all tests in the test harness, it applies to both debug and optimized builds.
771660278c0SBarry Smith 
772660278c0SBarry Smith   Use the option -petsc_ci to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for
773660278c0SBarry Smith   all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness.
774660278c0SBarry Smith 
775660278c0SBarry Smith   Always uses the Unix / as the file separate even on Microsoft Windows systems
776660278c0SBarry Smith 
777660278c0SBarry Smith   The option -petsc_ci_portable_error_output attempts to output the same error messages on all systems for the test harness.
778660278c0SBarry Smith   In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc
779660278c0SBarry 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
780660278c0SBarry Smith   harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test
781da81f932SPierre Jolivet   harness in the args: argument for specific examples. It will not necessarily produce portable output if different errors
782660278c0SBarry Smith   (or no errors) occur on a subset of the MPI ranks.
783660278c0SBarry Smith 
784660278c0SBarry Smith   Level: developer
785660278c0SBarry Smith 
786660278c0SBarry Smith .seealso: `PetscCILinenumber()`
787660278c0SBarry Smith @*/
788d71ae5a4SJacob Faibussowitsch const char *PetscCIFilename(const char *file)
789d71ae5a4SJacob Faibussowitsch {
790660278c0SBarry Smith   if (!PetscCIEnabledPortableErrorOutput) return file;
791660278c0SBarry Smith   return PetscBasename(file);
792660278c0SBarry Smith }
793660278c0SBarry Smith 
794660278c0SBarry Smith /*@C
795811af0c4SBarry Smith   PetscCILinenumber - returns a line number except if `PetscCIEnablePortableErrorOutput` is set when it returns 0
796660278c0SBarry Smith 
797660278c0SBarry Smith   Not collective
798660278c0SBarry Smith 
799660278c0SBarry Smith   Input Parameter:
800660278c0SBarry Smith . linenumber - the initial line number
801660278c0SBarry Smith 
802660278c0SBarry Smith   Note:
803660278c0SBarry Smith   See `PetscCIFilename()` for details on usage
804660278c0SBarry Smith 
805660278c0SBarry Smith   Level: developer
806660278c0SBarry Smith 
807660278c0SBarry Smith .seealso: `PetscCIFilename()`
808660278c0SBarry Smith @*/
809d71ae5a4SJacob Faibussowitsch int PetscCILinenumber(int linenumber)
810d71ae5a4SJacob Faibussowitsch {
811660278c0SBarry Smith   if (!PetscCIEnabledPortableErrorOutput) return linenumber;
812660278c0SBarry Smith   return 0;
813660278c0SBarry Smith }
814