xref: /petsc/src/sys/utils/str.c (revision 0b4b7b1c20c2ed4ade67e3d50a7710fe0ffbfca5)
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:
216497c311SBarry Smith + argc - the number of entries in `args`
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 
326497c311SBarry 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 {
386497c311SBarry Smith   int       n, i, j, *lens, cnt = 0;
39ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
403c311c98SBarry Smith 
4140a7e1efSBarry Smith   if (!s) n = 0;
426497c311SBarry Smith   else n = (int)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;
62dd460d27SBarry Smith   lens = (int *)malloc(((*argc) + 1) * 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:
147*0b4b7b1cSBarry Smith   Use `PetscStrArrayDestroy()` to free the memory.
1480ecf5a55SBarry Smith 
149811af0c4SBarry Smith .seealso: `PetscStrallocpy()`, `PetscStrArrayDestroy()`, `PetscStrNArrayallocpy()`
15047340559SBarry Smith @*/
151d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrArrayallocpy(const char *const *list, char ***t)
152d71ae5a4SJacob Faibussowitsch {
1535f80ce2aSJacob Faibussowitsch   PetscInt n = 0;
15447340559SBarry Smith 
15547340559SBarry Smith   PetscFunctionBegin;
156fbccb6d4SPierre Jolivet   while (list[n++]);
1579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n + 1, t));
1589566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
1590298fd71SBarry Smith   (*t)[n] = NULL;
1603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16147340559SBarry Smith }
16247340559SBarry Smith 
16347340559SBarry Smith /*@C
164811af0c4SBarry Smith   PetscStrArrayDestroy - Frees array of strings created with `PetscStrArrayallocpy()`.
16547340559SBarry Smith 
166667f096bSBarry Smith   Not Collective; No Fortran Support
16747340559SBarry Smith 
1682fe279fdSBarry Smith   Output Parameter:
16947340559SBarry Smith . list - array of strings
17047340559SBarry Smith 
17147340559SBarry Smith   Level: intermediate
17247340559SBarry Smith 
173db781477SPatrick Sanan .seealso: `PetscStrArrayallocpy()`
17447340559SBarry Smith @*/
175d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrArrayDestroy(char ***list)
176d71ae5a4SJacob Faibussowitsch {
17747340559SBarry Smith   PetscInt n = 0;
17847340559SBarry Smith 
1796fed8037SJed Brown   PetscFunctionBegin;
1803ba16761SJacob Faibussowitsch   if (!*list) PetscFunctionReturn(PETSC_SUCCESS);
1816fed8037SJed Brown   while ((*list)[n]) {
1829566063dSJacob Faibussowitsch     PetscCall(PetscFree((*list)[n]));
1835f80ce2aSJacob Faibussowitsch     ++n;
18447340559SBarry Smith   }
1859566063dSJacob Faibussowitsch   PetscCall(PetscFree(*list));
1863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18747340559SBarry Smith }
18847340559SBarry Smith 
1896991f827SBarry Smith /*@C
1906991f827SBarry Smith   PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
1916991f827SBarry Smith 
192667f096bSBarry Smith   Not Collective; No Fortran Support
1936991f827SBarry Smith 
1946991f827SBarry Smith   Input Parameters:
1956991f827SBarry Smith + n    - the number of string entries
196aec76313SJacob Faibussowitsch - list - pointer to array of strings
1976991f827SBarry Smith 
1986991f827SBarry Smith   Output Parameter:
1996991f827SBarry Smith . t - the copied array string
2006991f827SBarry Smith 
2016991f827SBarry Smith   Level: intermediate
2026991f827SBarry Smith 
203*0b4b7b1cSBarry Smith   Note:
204*0b4b7b1cSBarry Smith   Use `PetscStrNArrayDestroy()` to free the memory.
205*0b4b7b1cSBarry Smith 
206db781477SPatrick Sanan .seealso: `PetscStrallocpy()`, `PetscStrArrayallocpy()`, `PetscStrNArrayDestroy()`
2076991f827SBarry Smith @*/
208d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrNArrayallocpy(PetscInt n, const char *const *list, char ***t)
209d71ae5a4SJacob Faibussowitsch {
2106991f827SBarry Smith   PetscFunctionBegin;
2119566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, t));
2129566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
2133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2146991f827SBarry Smith }
2156991f827SBarry Smith 
2166991f827SBarry Smith /*@C
217811af0c4SBarry Smith   PetscStrNArrayDestroy - Frees array of strings created with `PetscStrNArrayallocpy()`.
2186991f827SBarry Smith 
219667f096bSBarry Smith   Not Collective; No Fortran Support
2206991f827SBarry Smith 
2216991f827SBarry Smith   Output Parameters:
2226991f827SBarry Smith + n    - number of string entries
2236991f827SBarry Smith - list - array of strings
2246991f827SBarry Smith 
2256991f827SBarry Smith   Level: intermediate
2266991f827SBarry Smith 
227811af0c4SBarry Smith .seealso: `PetscStrNArrayallocpy()`, `PetscStrArrayallocpy()`
2286991f827SBarry Smith @*/
229d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrNArrayDestroy(PetscInt n, char ***list)
230d71ae5a4SJacob Faibussowitsch {
2316991f827SBarry Smith   PetscFunctionBegin;
2323ba16761SJacob Faibussowitsch   if (!*list) PetscFunctionReturn(PETSC_SUCCESS);
2339566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscFree((*list)[i]));
2349566063dSJacob Faibussowitsch   PetscCall(PetscFree(*list));
2353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2366991f827SBarry Smith }
2376991f827SBarry Smith 
238e5c89e4eSSatish Balay /*@C
239811af0c4SBarry Smith   PetscBasename - returns a pointer to the last entry of a / or \ separated directory path
24080b92c66SBarry Smith 
241667f096bSBarry Smith   Not Collective; No Fortran Support
24280b92c66SBarry Smith 
24380b92c66SBarry Smith   Input Parameter:
24480b92c66SBarry Smith . a - pointer to string
24580b92c66SBarry Smith 
24680b92c66SBarry Smith   Level: intermediate
24780b92c66SBarry Smith 
24880b92c66SBarry Smith .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`, `PetscStrrchr()`, `PetscStrcmp()`, `PetscStrstr()`,
24980b92c66SBarry Smith           `PetscTokenCreate()`, `PetscStrToArray()`, `PetscStrInList()`
25080b92c66SBarry Smith @*/
251d71ae5a4SJacob Faibussowitsch const char *PetscBasename(const char a[])
252d71ae5a4SJacob Faibussowitsch {
253bbcf679cSJacob Faibussowitsch   const char *ptr = NULL;
25480b92c66SBarry Smith 
255bbcf679cSJacob Faibussowitsch   (void)PetscStrrchr(a, '/', (char **)&ptr);
256660278c0SBarry Smith   if (ptr == a) {
257660278c0SBarry Smith     if (PetscStrrchr(a, '\\', (char **)&ptr)) ptr = NULL;
258660278c0SBarry Smith   }
25980b92c66SBarry Smith   return ptr;
26080b92c66SBarry Smith }
26180b92c66SBarry Smith 
26280b92c66SBarry Smith /*@C
263e5c89e4eSSatish Balay   PetscStrcasecmp - Returns true if the two strings are the same
264e5c89e4eSSatish Balay   except possibly for case.
265e5c89e4eSSatish Balay 
266667f096bSBarry Smith   Not Collective; No Fortran Support
267e5c89e4eSSatish Balay 
268e5c89e4eSSatish Balay   Input Parameters:
269e5c89e4eSSatish Balay + a - pointer to first string
270e5c89e4eSSatish Balay - b - pointer to second string
271e5c89e4eSSatish Balay 
272e5c89e4eSSatish Balay   Output Parameter:
273aec76313SJacob Faibussowitsch . t - if the two strings are the same
274e5c89e4eSSatish Balay 
275e5c89e4eSSatish Balay   Level: intermediate
276e5c89e4eSSatish Balay 
277667f096bSBarry Smith   Note:
278667f096bSBarry Smith   `NULL` arguments are ok
279667f096bSBarry Smith 
280db781477SPatrick Sanan .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrgrt()`
281e5c89e4eSSatish Balay @*/
282d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t)
283d71ae5a4SJacob Faibussowitsch {
284e5c89e4eSSatish Balay   int c;
285e5c89e4eSSatish Balay 
286e5c89e4eSSatish Balay   PetscFunctionBegin;
2874f572ea9SToby Isaac   PetscAssertPointer(t, 3);
288e5c89e4eSSatish Balay   if (!a && !b) c = 0;
289e5c89e4eSSatish Balay   else if (!a || !b) c = 1;
29032b366c8SSatish Balay #if defined(PETSC_HAVE_STRCASECMP)
29132b366c8SSatish Balay   else c = strcasecmp(a, b);
29232b366c8SSatish Balay #elif defined(PETSC_HAVE_STRICMP)
293e5c89e4eSSatish Balay   else c = stricmp(a, b);
294e5c89e4eSSatish Balay #else
29532b366c8SSatish Balay   else {
29632b366c8SSatish Balay     char *aa, *bb;
297bbcf679cSJacob Faibussowitsch 
2989566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(a, &aa));
2999566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(b, &bb));
3009566063dSJacob Faibussowitsch     PetscCall(PetscStrtolower(aa));
3019566063dSJacob Faibussowitsch     PetscCall(PetscStrtolower(bb));
3029566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(aa, bb, t));
3039566063dSJacob Faibussowitsch     PetscCall(PetscFree(aa));
3049566063dSJacob Faibussowitsch     PetscCall(PetscFree(bb));
3053ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
30632b366c8SSatish Balay   }
307e5c89e4eSSatish Balay #endif
3085f80ce2aSJacob Faibussowitsch   *t = c ? PETSC_FALSE : PETSC_TRUE;
3093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
310e5c89e4eSSatish Balay }
311e5c89e4eSSatish Balay 
312e5c89e4eSSatish Balay /*@C
3137ba3a57cSBarry Smith   PetscStrendswithwhich - Determines if a string ends with one of several possible strings
3147ba3a57cSBarry Smith 
315667f096bSBarry Smith   Not Collective; No Fortran Support
3167ba3a57cSBarry Smith 
3177ba3a57cSBarry Smith   Input Parameters:
3187ba3a57cSBarry Smith + a  - pointer to string
319667f096bSBarry Smith - bs - strings to end with (last entry must be `NULL`)
3207ba3a57cSBarry Smith 
3217ba3a57cSBarry Smith   Output Parameter:
322667f096bSBarry Smith . cnt - the index of the string it ends with or the index of `NULL`
3237ba3a57cSBarry Smith 
3247ba3a57cSBarry Smith   Level: intermediate
3257ba3a57cSBarry Smith 
326811af0c4SBarry Smith .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
327aec76313SJacob Faibussowitsch           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrcmp()`
3287ba3a57cSBarry Smith @*/
329d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt)
330d71ae5a4SJacob Faibussowitsch {
3317ba3a57cSBarry Smith   PetscFunctionBegin;
3324f572ea9SToby Isaac   PetscAssertPointer(bs, 2);
3334f572ea9SToby Isaac   PetscAssertPointer(cnt, 3);
3347ba3a57cSBarry Smith   *cnt = 0;
3357ba3a57cSBarry Smith   while (bs[*cnt]) {
3365f80ce2aSJacob Faibussowitsch     PetscBool flg;
3375f80ce2aSJacob Faibussowitsch 
3389566063dSJacob Faibussowitsch     PetscCall(PetscStrendswith(a, bs[*cnt], &flg));
3393ba16761SJacob Faibussowitsch     if (flg) PetscFunctionReturn(PETSC_SUCCESS);
3405f80ce2aSJacob Faibussowitsch     ++(*cnt);
3417ba3a57cSBarry Smith   }
3423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3437ba3a57cSBarry Smith }
3447ba3a57cSBarry Smith 
3459371c9d4SSatish Balay struct _p_PetscToken {
3469371c9d4SSatish Balay   char  token;
3479371c9d4SSatish Balay   char *array;
3489371c9d4SSatish Balay   char *current;
3499371c9d4SSatish Balay };
3501d1a0024SBarry Smith 
351e5c89e4eSSatish Balay /*@C
352667f096bSBarry Smith   PetscTokenFind - Locates next "token" in a `PetscToken`
353e5c89e4eSSatish Balay 
354667f096bSBarry Smith   Not Collective; No Fortran Support
355e5c89e4eSSatish Balay 
3562fe279fdSBarry Smith   Input Parameter:
357e5c89e4eSSatish Balay . a - pointer to token
358e5c89e4eSSatish Balay 
359e5c89e4eSSatish Balay   Output Parameter:
360667f096bSBarry Smith . result - location of occurrence, `NULL` if not found
3616f013253SBarry Smith 
362e5c89e4eSSatish Balay   Level: intermediate
363e5c89e4eSSatish Balay 
364667f096bSBarry Smith   Notes:
365667f096bSBarry Smith   Treats all characters etc. inside a double quote "
366667f096bSBarry Smith   as a single token.
367667f096bSBarry Smith 
368667f096bSBarry 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
369667f096bSBarry Smith   second will return a `NULL` terminated y
370667f096bSBarry Smith 
371667f096bSBarry 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
372667f096bSBarry Smith 
373667f096bSBarry Smith .seealso: `PetscToken`, `PetscTokenCreate()`, `PetscTokenDestroy()`
374e5c89e4eSSatish Balay @*/
375d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTokenFind(PetscToken a, char *result[])
376d71ae5a4SJacob Faibussowitsch {
3775f80ce2aSJacob Faibussowitsch   char *ptr, token;
378e5c89e4eSSatish Balay 
379e5c89e4eSSatish Balay   PetscFunctionBegin;
3804f572ea9SToby Isaac   PetscAssertPointer(a, 1);
3814f572ea9SToby Isaac   PetscAssertPointer(result, 2);
3825f80ce2aSJacob Faibussowitsch   *result = ptr = a->current;
3839371c9d4SSatish Balay   if (ptr && !*ptr) {
3849371c9d4SSatish Balay     *result = NULL;
3853ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3869371c9d4SSatish Balay   }
3874704e885SBarry Smith   token = a->token;
3889371c9d4SSatish Balay   if (ptr && (*ptr == '"')) {
3899371c9d4SSatish Balay     token = '"';
3909371c9d4SSatish Balay     (*result)++;
3919371c9d4SSatish Balay     ptr++;
3929371c9d4SSatish Balay   }
393e5c89e4eSSatish Balay   while (ptr) {
3944704e885SBarry Smith     if (*ptr == token) {
395e5c89e4eSSatish Balay       *ptr++ = 0;
396e5c89e4eSSatish Balay       while (*ptr == a->token) ptr++;
397e5c89e4eSSatish Balay       a->current = ptr;
398e5c89e4eSSatish Balay       break;
399e5c89e4eSSatish Balay     }
400e5c89e4eSSatish Balay     if (!*ptr) {
40102c9f0b5SLisandro Dalcin       a->current = NULL;
402e5c89e4eSSatish Balay       break;
403e5c89e4eSSatish Balay     }
404e5c89e4eSSatish Balay     ptr++;
405e5c89e4eSSatish Balay   }
4063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
407e5c89e4eSSatish Balay }
408e5c89e4eSSatish Balay 
409e5c89e4eSSatish Balay /*@C
410811af0c4SBarry Smith   PetscTokenCreate - Creates a `PetscToken` used to find tokens in a string
411e5c89e4eSSatish Balay 
412667f096bSBarry Smith   Not Collective; No Fortran Support
413e5c89e4eSSatish Balay 
414e5c89e4eSSatish Balay   Input Parameters:
415aec76313SJacob Faibussowitsch + a - the string to look in
4163a9c465aSBarry Smith - b - the separator character
417e5c89e4eSSatish Balay 
418e5c89e4eSSatish Balay   Output Parameter:
4193a9c465aSBarry Smith . t - the token object
420e5c89e4eSSatish Balay 
421667f096bSBarry Smith   Level: intermediate
422667f096bSBarry Smith 
423811af0c4SBarry Smith   Note:
424e5c89e4eSSatish Balay   This version is different from the system version in that
425e5c89e4eSSatish Balay   it allows you to pass a read-only string into the function.
426e5c89e4eSSatish Balay 
427667f096bSBarry Smith .seealso: `PetscToken`, `PetscTokenFind()`, `PetscTokenDestroy()`
428e5c89e4eSSatish Balay @*/
42998e514b7SJacob Faibussowitsch PetscErrorCode PetscTokenCreate(const char a[], char b, PetscToken *t)
430d71ae5a4SJacob Faibussowitsch {
431e5c89e4eSSatish Balay   PetscFunctionBegin;
4324f572ea9SToby Isaac   PetscAssertPointer(a, 1);
4334f572ea9SToby Isaac   PetscAssertPointer(t, 3);
4349566063dSJacob Faibussowitsch   PetscCall(PetscNew(t));
4359566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(a, &(*t)->array));
436a297a907SKarl Rupp 
437e5c89e4eSSatish Balay   (*t)->current = (*t)->array;
438e5c89e4eSSatish Balay   (*t)->token   = b;
4393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
440e5c89e4eSSatish Balay }
441e5c89e4eSSatish Balay 
442e5c89e4eSSatish Balay /*@C
443811af0c4SBarry Smith   PetscTokenDestroy - Destroys a `PetscToken`
444e5c89e4eSSatish Balay 
445667f096bSBarry Smith   Not Collective; No Fortran Support
446e5c89e4eSSatish Balay 
4472fe279fdSBarry Smith   Input Parameter:
448e5c89e4eSSatish Balay . a - pointer to token
449e5c89e4eSSatish Balay 
450e5c89e4eSSatish Balay   Level: intermediate
451e5c89e4eSSatish Balay 
452667f096bSBarry Smith .seealso: `PetscToken`, `PetscTokenCreate()`, `PetscTokenFind()`
453e5c89e4eSSatish Balay @*/
454d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTokenDestroy(PetscToken *a)
455d71ae5a4SJacob Faibussowitsch {
456e5c89e4eSSatish Balay   PetscFunctionBegin;
4573ba16761SJacob Faibussowitsch   if (!*a) PetscFunctionReturn(PETSC_SUCCESS);
4589566063dSJacob Faibussowitsch   PetscCall(PetscFree((*a)->array));
4599566063dSJacob Faibussowitsch   PetscCall(PetscFree(*a));
4603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
461e5c89e4eSSatish Balay }
462e5c89e4eSSatish Balay 
4638e81d068SLisandro Dalcin /*@C
464667f096bSBarry Smith   PetscStrInList - search for a string in character-delimited list
4658e81d068SLisandro Dalcin 
466667f096bSBarry Smith   Not Collective; No Fortran Support
4678e81d068SLisandro Dalcin 
4688e81d068SLisandro Dalcin   Input Parameters:
4698e81d068SLisandro Dalcin + str  - the string to look for
4708e81d068SLisandro Dalcin . list - the list to search in
4718e81d068SLisandro Dalcin - sep  - the separator character
4728e81d068SLisandro Dalcin 
4738e81d068SLisandro Dalcin   Output Parameter:
474667f096bSBarry Smith . found - whether `str` is in `list`
4758e81d068SLisandro Dalcin 
4768e81d068SLisandro Dalcin   Level: intermediate
4778e81d068SLisandro Dalcin 
478db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()`
4798e81d068SLisandro Dalcin @*/
480d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found)
481d71ae5a4SJacob Faibussowitsch {
4828e81d068SLisandro Dalcin   PetscToken token;
4838e81d068SLisandro Dalcin   char      *item;
4848e81d068SLisandro Dalcin 
4858e81d068SLisandro Dalcin   PetscFunctionBegin;
4864f572ea9SToby Isaac   PetscAssertPointer(found, 4);
4878e81d068SLisandro Dalcin   *found = PETSC_FALSE;
4889566063dSJacob Faibussowitsch   PetscCall(PetscTokenCreate(list, sep, &token));
4899566063dSJacob Faibussowitsch   PetscCall(PetscTokenFind(token, &item));
4908e81d068SLisandro Dalcin   while (item) {
4919566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(str, item, found));
4928e81d068SLisandro Dalcin     if (*found) break;
4939566063dSJacob Faibussowitsch     PetscCall(PetscTokenFind(token, &item));
4948e81d068SLisandro Dalcin   }
4959566063dSJacob Faibussowitsch   PetscCall(PetscTokenDestroy(&token));
4963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4978e81d068SLisandro Dalcin }
498e5c89e4eSSatish Balay 
499e5c89e4eSSatish Balay /*@C
500e5c89e4eSSatish Balay   PetscGetPetscDir - Gets the directory PETSc is installed in
501e5c89e4eSSatish Balay 
502667f096bSBarry Smith   Not Collective; No Fortran Support
503e5c89e4eSSatish Balay 
504e5c89e4eSSatish Balay   Output Parameter:
505e5c89e4eSSatish Balay . dir - the directory
506e5c89e4eSSatish Balay 
507e5c89e4eSSatish Balay   Level: developer
508e5c89e4eSSatish Balay 
50910450e9eSJacob Faibussowitsch .seealso: `PetscGetArchType()`
510e5c89e4eSSatish Balay @*/
511d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGetPetscDir(const char *dir[])
512d71ae5a4SJacob Faibussowitsch {
513e5c89e4eSSatish Balay   PetscFunctionBegin;
5144f572ea9SToby Isaac   PetscAssertPointer(dir, 1);
515e5c89e4eSSatish Balay   *dir = PETSC_DIR;
5163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
517e5c89e4eSSatish Balay }
518e5c89e4eSSatish Balay 
519e5c89e4eSSatish Balay /*@C
520e5c89e4eSSatish Balay   PetscStrreplace - Replaces substrings in string with other substrings
521e5c89e4eSSatish Balay 
522667f096bSBarry Smith   Not Collective; No Fortran Support
523e5c89e4eSSatish Balay 
524e5c89e4eSSatish Balay   Input Parameters:
525811af0c4SBarry Smith + comm - `MPI_Comm` of processors that are processing the string
52671573d7dSBarry Smith . aa   - the string to look in
527667f096bSBarry Smith . b    - the resulting copy of a with replaced strings (`b` can be the same as `a`)
528667f096bSBarry Smith - len  - the length of `b`
529e5c89e4eSSatish Balay 
5302fe279fdSBarry Smith   Level: developer
5312fe279fdSBarry Smith 
532e5c89e4eSSatish Balay   Notes:
533e5c89e4eSSatish Balay   Replaces ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
534f236b2adSBarry Smith       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME}, ${PETSC_MAKE} with appropriate values
535e5c89e4eSSatish Balay   as well as any environmental variables.
536e5c89e4eSSatish Balay 
537811af0c4SBarry Smith   `PETSC_LIB_DIR` uses the environmental variable if it exists. `PETSC_ARCH` and `PETSC_DIR` use what
538acc6cc86SBarry Smith   PETSc was built with and do not use environmental variables.
539acc6cc86SBarry Smith 
54010450e9eSJacob Faibussowitsch .seealso: `PetscStrcmp()`
541e5c89e4eSSatish Balay @*/
542d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len)
543d71ae5a4SJacob Faibussowitsch {
544e5c89e4eSSatish Balay   int           i = 0;
545e5c89e4eSSatish Balay   size_t        l, l1, l2, l3;
5467864358aSSatish Balay   char         *work, *par, *epar = NULL, env[1024], *tfree, *a = (char *)aa;
547f236b2adSBarry Smith   const char   *s[] = {"${PETSC_ARCH}", "${PETSC_DIR}", "${PETSC_LIB_DIR}", "${DISPLAY}", "${HOMEDIRECTORY}", "${WORKINGDIRECTORY}", "${USERNAME}", "${HOSTNAME}", "${PETSC_MAKE}", NULL};
548f236b2adSBarry Smith   char         *r[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
549ace3abfcSBarry Smith   PetscBool     flag;
550589a23caSBarry Smith   static size_t DISPLAY_LENGTH = 265, USER_LENGTH = 256, HOST_LENGTH = 256;
551e5c89e4eSSatish Balay 
552e5c89e4eSSatish Balay   PetscFunctionBegin;
5534f572ea9SToby Isaac   PetscAssertPointer(aa, 2);
5544f572ea9SToby Isaac   PetscAssertPointer(b, 3);
5559566063dSJacob Faibussowitsch   if (aa == b) PetscCall(PetscStrallocpy(aa, (char **)&a));
5569566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(len, &work));
557e5c89e4eSSatish Balay 
558e5c89e4eSSatish Balay   /* get values for replaced variables */
5599566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_ARCH, &r[0]));
5609566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_DIR, &r[1]));
5619566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_LIB_DIR, &r[2]));
5629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(DISPLAY_LENGTH, &r[3]));
5639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[4]));
5649566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[5]));
5659566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(USER_LENGTH, &r[6]));
5669566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(HOST_LENGTH, &r[7]));
5679566063dSJacob Faibussowitsch   PetscCall(PetscGetDisplay(r[3], DISPLAY_LENGTH));
5689566063dSJacob Faibussowitsch   PetscCall(PetscGetHomeDirectory(r[4], PETSC_MAX_PATH_LEN));
5699566063dSJacob Faibussowitsch   PetscCall(PetscGetWorkingDirectory(r[5], PETSC_MAX_PATH_LEN));
5709566063dSJacob Faibussowitsch   PetscCall(PetscGetUserName(r[6], USER_LENGTH));
5719566063dSJacob Faibussowitsch   PetscCall(PetscGetHostName(r[7], HOST_LENGTH));
572f236b2adSBarry Smith   PetscCall(PetscStrallocpy(PETSC_OMAKE, &r[8]));
573487e5849SBarry Smith 
574487e5849SBarry Smith   /* replace that are in environment */
5759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetenv(comm, "PETSC_LIB_DIR", env, sizeof(env), &flag));
576487e5849SBarry Smith   if (flag) {
5779566063dSJacob Faibussowitsch     PetscCall(PetscFree(r[2]));
5789566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(env, &r[2]));
579487e5849SBarry Smith   }
580e5c89e4eSSatish Balay 
581e5c89e4eSSatish Balay   /* replace the requested strings */
5829566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(b, a, len));
583e5c89e4eSSatish Balay   while (s[i]) {
5849566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(s[i], &l));
5859566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(b, s[i], &par));
586e5c89e4eSSatish Balay     while (par) {
587e5c89e4eSSatish Balay       *par = 0;
588e5c89e4eSSatish Balay       par += l;
589e5c89e4eSSatish Balay 
5909566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(b, &l1));
5919566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(r[i], &l2));
5929566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(par, &l3));
593cc73adaaSBarry Smith       PetscCheck(l1 + l2 + l3 < len, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "b len is not long enough to hold new values");
5949566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(work, b, len));
5959566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(work, r[i], len));
5969566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(work, par, len));
5979566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(b, work, len));
5989566063dSJacob Faibussowitsch       PetscCall(PetscStrstr(b, s[i], &par));
599e5c89e4eSSatish Balay     }
600e5c89e4eSSatish Balay     i++;
601e5c89e4eSSatish Balay   }
602487e5849SBarry Smith   i = 0;
603487e5849SBarry Smith   while (r[i]) {
604e5c89e4eSSatish Balay     tfree = (char *)r[i];
6059566063dSJacob Faibussowitsch     PetscCall(PetscFree(tfree));
606487e5849SBarry Smith     i++;
607e5c89e4eSSatish Balay   }
608e5c89e4eSSatish Balay 
609e5c89e4eSSatish Balay   /* look for any other ${xxx} strings to replace from environmental variables */
6109566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(b, "${", &par));
611e5c89e4eSSatish Balay   while (par) {
612e5c89e4eSSatish Balay     *par = 0;
613e5c89e4eSSatish Balay     par += 2;
6149566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(work, b, len));
6159566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(par, "}", &epar));
616e5c89e4eSSatish Balay     *epar = 0;
617e5c89e4eSSatish Balay     epar += 1;
6189566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetenv(comm, par, env, sizeof(env), &flag));
61928b400f6SJacob Faibussowitsch     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Substitution string ${%s} not found as environmental variable", par);
6209566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(work, env, len));
6219566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(work, epar, len));
6229566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(b, work, len));
6239566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(b, "${", &par));
624e5c89e4eSSatish Balay   }
6259566063dSJacob Faibussowitsch   PetscCall(PetscFree(work));
6269566063dSJacob Faibussowitsch   if (aa == b) PetscCall(PetscFree(a));
6273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
628e5c89e4eSSatish Balay }
629e5c89e4eSSatish Balay 
630a53986e1SJed Brown /*@C
631c0d8b5b9SStefano Zampini   PetscStrcmpAny - Determines whether a string matches any of a list of strings.
632c0d8b5b9SStefano Zampini 
633cc4c1da9SBarry Smith   Not Collective, No Fortran Support
634c0d8b5b9SStefano Zampini 
635c0d8b5b9SStefano Zampini   Input Parameters:
636c0d8b5b9SStefano Zampini + src - pointer to input the string
637c0d8b5b9SStefano Zampini - cmp - list of non-null and non-empty strings to be compared against, pass the empty string "" to terminate the list
638c0d8b5b9SStefano Zampini 
639c0d8b5b9SStefano Zampini   Output Parameter:
640c0d8b5b9SStefano Zampini . match - `PETSC_TRUE` if the input string matches any in the list, else `PETSC_FALSE`
641c0d8b5b9SStefano Zampini 
642c0d8b5b9SStefano Zampini   Level: intermediate
643c0d8b5b9SStefano Zampini 
64410450e9eSJacob Faibussowitsch .seealso: `PetscStrcmp()`
645c0d8b5b9SStefano Zampini @*/
646c0d8b5b9SStefano Zampini PetscErrorCode PetscStrcmpAny(const char src[], PetscBool *match, const char cmp[], ...)
647c0d8b5b9SStefano Zampini {
648c0d8b5b9SStefano Zampini   va_list Argp;
649c0d8b5b9SStefano Zampini 
650c0d8b5b9SStefano Zampini   PetscFunctionBegin;
6514f572ea9SToby Isaac   PetscAssertPointer(match, 2);
652c0d8b5b9SStefano Zampini   *match = PETSC_FALSE;
653c0d8b5b9SStefano Zampini   if (!src) PetscFunctionReturn(PETSC_SUCCESS);
654c0d8b5b9SStefano Zampini   va_start(Argp, cmp);
655c0d8b5b9SStefano Zampini   while (cmp && cmp[0]) {
656c0d8b5b9SStefano Zampini     PetscBool found;
657c0d8b5b9SStefano Zampini     PetscCall(PetscStrcmp(src, cmp, &found));
658c0d8b5b9SStefano Zampini     if (found) {
659c0d8b5b9SStefano Zampini       *match = PETSC_TRUE;
660c0d8b5b9SStefano Zampini       break;
661c0d8b5b9SStefano Zampini     }
662c0d8b5b9SStefano Zampini     cmp = va_arg(Argp, const char *);
663c0d8b5b9SStefano Zampini   }
664c0d8b5b9SStefano Zampini   va_end(Argp);
665c0d8b5b9SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
666c0d8b5b9SStefano Zampini }
667c0d8b5b9SStefano Zampini 
668c0d8b5b9SStefano Zampini /*@C
669a53986e1SJed Brown   PetscEListFind - searches list of strings for given string, using case insensitive matching
670e5c89e4eSSatish Balay 
671667f096bSBarry Smith   Not Collective; No Fortran Support
672a53986e1SJed Brown 
673a53986e1SJed Brown   Input Parameters:
674a53986e1SJed Brown + n    - number of strings in
675a53986e1SJed Brown . list - list of strings to search
676a53986e1SJed Brown - str  - string to look for, empty string "" accepts default (first entry in list)
677a53986e1SJed Brown 
678a53986e1SJed Brown   Output Parameters:
679a53986e1SJed Brown + value - index of matching string (if found)
680667f096bSBarry Smith - found - boolean indicating whether string was found (can be `NULL`)
681811af0c4SBarry Smith 
68253c0d4aeSBarry Smith   Level: developer
68353c0d4aeSBarry Smith 
684811af0c4SBarry Smith .seealso: `PetscEnumFind()`
685a53986e1SJed Brown @*/
686d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found)
687d71ae5a4SJacob Faibussowitsch {
688a53986e1SJed Brown   PetscFunctionBegin;
6895f80ce2aSJacob Faibussowitsch   if (found) {
6904f572ea9SToby Isaac     PetscAssertPointer(found, 5);
6915f80ce2aSJacob Faibussowitsch     *found = PETSC_FALSE;
6925f80ce2aSJacob Faibussowitsch   }
6935f80ce2aSJacob Faibussowitsch   for (PetscInt i = 0; i < n; ++i) {
6945f80ce2aSJacob Faibussowitsch     PetscBool matched;
6955f80ce2aSJacob Faibussowitsch 
6969566063dSJacob Faibussowitsch     PetscCall(PetscStrcasecmp(str, list[i], &matched));
697a53986e1SJed Brown     if (matched || !str[0]) {
698a53986e1SJed Brown       if (found) *found = PETSC_TRUE;
699a53986e1SJed Brown       *value = i;
700a53986e1SJed Brown       break;
701a53986e1SJed Brown     }
702a53986e1SJed Brown   }
7033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
704a53986e1SJed Brown }
705a53986e1SJed Brown 
706a53986e1SJed Brown /*@C
7078e81d068SLisandro Dalcin   PetscEnumFind - searches enum list of strings for given string, using case insensitive matching
708a53986e1SJed Brown 
709667f096bSBarry Smith   Not Collective; No Fortran Support
710a53986e1SJed Brown 
711a53986e1SJed Brown   Input Parameters:
712667f096bSBarry Smith + enumlist - list of strings to search, followed by enum name, then enum prefix, then `NULL`
713a53986e1SJed Brown - str      - string to look for
714a53986e1SJed Brown 
715a53986e1SJed Brown   Output Parameters:
716a53986e1SJed Brown + value - index of matching string (if found)
717667f096bSBarry Smith - found - boolean indicating whether string was found (can be `NULL`)
718a53986e1SJed Brown 
719a53986e1SJed Brown   Level: advanced
720811af0c4SBarry Smith 
721811af0c4SBarry Smith .seealso: `PetscEListFind()`
722a53986e1SJed Brown @*/
723d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found)
724d71ae5a4SJacob Faibussowitsch {
725d05ba7d2SLisandro Dalcin   PetscInt  n = 0, evalue;
726a53986e1SJed Brown   PetscBool efound;
727a53986e1SJed Brown 
728a53986e1SJed Brown   PetscFunctionBegin;
7294f572ea9SToby Isaac   PetscAssertPointer(enumlist, 1);
7305f80ce2aSJacob 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");
7315f80ce2aSJacob Faibussowitsch   PetscCheck(n >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
732a53986e1SJed Brown   n -= 3; /* drop enum name, prefix, and null termination */
7339566063dSJacob Faibussowitsch   PetscCall(PetscEListFind(n, enumlist, str, &evalue, &efound));
7345f80ce2aSJacob Faibussowitsch   if (efound) {
7354f572ea9SToby Isaac     PetscAssertPointer(value, 3);
7365f80ce2aSJacob Faibussowitsch     *value = (PetscEnum)evalue;
7375f80ce2aSJacob Faibussowitsch   }
7385f80ce2aSJacob Faibussowitsch   if (found) {
7394f572ea9SToby Isaac     PetscAssertPointer(found, 4);
7405f80ce2aSJacob Faibussowitsch     *found = efound;
7415f80ce2aSJacob Faibussowitsch   }
7423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
743a53986e1SJed Brown }
744660278c0SBarry Smith 
745660278c0SBarry Smith /*@C
746660278c0SBarry Smith   PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled.
747660278c0SBarry Smith 
74820f4b53cSBarry Smith   Not Collective; No Fortran Support
749660278c0SBarry Smith 
750660278c0SBarry Smith   Input Parameter:
751660278c0SBarry Smith . file - the file name
752660278c0SBarry Smith 
753667f096bSBarry Smith   Level: developer
754667f096bSBarry Smith 
755660278c0SBarry Smith   Note:
756660278c0SBarry Smith   PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems
757660278c0SBarry Smith   so that comparisons of output between runs are easy to make.
758660278c0SBarry Smith 
759660278c0SBarry Smith   This mode is used for all tests in the test harness, it applies to both debug and optimized builds.
760660278c0SBarry Smith 
761667f096bSBarry Smith   Use the option `-petsc_ci` to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for
762660278c0SBarry Smith   all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness.
763660278c0SBarry Smith 
764660278c0SBarry Smith   Always uses the Unix / as the file separate even on Microsoft Windows systems
765660278c0SBarry Smith 
766667f096bSBarry Smith   The option `-petsc_ci_portable_error_output` attempts to output the same error messages on all systems for the test harness.
767660278c0SBarry Smith   In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc
768660278c0SBarry 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
769660278c0SBarry Smith   harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test
770da81f932SPierre Jolivet   harness in the args: argument for specific examples. It will not necessarily produce portable output if different errors
771660278c0SBarry Smith   (or no errors) occur on a subset of the MPI ranks.
772660278c0SBarry Smith 
773660278c0SBarry Smith .seealso: `PetscCILinenumber()`
774660278c0SBarry Smith @*/
775d71ae5a4SJacob Faibussowitsch const char *PetscCIFilename(const char *file)
776d71ae5a4SJacob Faibussowitsch {
777660278c0SBarry Smith   if (!PetscCIEnabledPortableErrorOutput) return file;
778660278c0SBarry Smith   return PetscBasename(file);
779660278c0SBarry Smith }
780660278c0SBarry Smith 
781660278c0SBarry Smith /*@C
782811af0c4SBarry Smith   PetscCILinenumber - returns a line number except if `PetscCIEnablePortableErrorOutput` is set when it returns 0
783660278c0SBarry Smith 
784667f096bSBarry Smith   Not Collective; No Fortran Support
785660278c0SBarry Smith 
786660278c0SBarry Smith   Input Parameter:
787660278c0SBarry Smith . linenumber - the initial line number
788660278c0SBarry Smith 
789667f096bSBarry Smith   Level: developer
790667f096bSBarry Smith 
791660278c0SBarry Smith   Note:
792660278c0SBarry Smith   See `PetscCIFilename()` for details on usage
793660278c0SBarry Smith 
794660278c0SBarry Smith .seealso: `PetscCIFilename()`
795660278c0SBarry Smith @*/
796d71ae5a4SJacob Faibussowitsch int PetscCILinenumber(int linenumber)
797d71ae5a4SJacob Faibussowitsch {
798660278c0SBarry Smith   if (!PetscCIEnabledPortableErrorOutput) return linenumber;
799660278c0SBarry Smith   return 0;
800660278c0SBarry Smith }
801d11110bcSJacob Faibussowitsch 
802d11110bcSJacob Faibussowitsch /*@C
803d11110bcSJacob Faibussowitsch   PetscStrcat - Concatenates a string onto a given string
804d11110bcSJacob Faibussowitsch 
805d11110bcSJacob Faibussowitsch   Not Collective, No Fortran Support
806d11110bcSJacob Faibussowitsch 
807d11110bcSJacob Faibussowitsch   Input Parameters:
808d11110bcSJacob Faibussowitsch + s - string to be added to
809d11110bcSJacob Faibussowitsch - t - pointer to string to be added to end
810d11110bcSJacob Faibussowitsch 
811d11110bcSJacob Faibussowitsch   Level: deprecated (since 3.18.5)
812d11110bcSJacob Faibussowitsch 
813d11110bcSJacob Faibussowitsch   Notes:
814d11110bcSJacob Faibussowitsch   It is recommended you use `PetscStrlcat()` instead of this routine.
815d11110bcSJacob Faibussowitsch 
816d11110bcSJacob Faibussowitsch .seealso: `PetscStrlcat()`
817d11110bcSJacob Faibussowitsch @*/
818d11110bcSJacob Faibussowitsch PetscErrorCode PetscStrcat(char s[], const char t[])
819d11110bcSJacob Faibussowitsch {
820d11110bcSJacob Faibussowitsch   PetscFunctionBegin;
821d11110bcSJacob Faibussowitsch   if (!t) PetscFunctionReturn(PETSC_SUCCESS);
8224f572ea9SToby Isaac   PetscAssertPointer(s, 1);
823d11110bcSJacob Faibussowitsch   strcat(s, t);
824d11110bcSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
825d11110bcSJacob Faibussowitsch }
826d11110bcSJacob Faibussowitsch 
827d11110bcSJacob Faibussowitsch /*@C
828d11110bcSJacob Faibussowitsch   PetscStrcpy - Copies a string
829d11110bcSJacob Faibussowitsch 
830d11110bcSJacob Faibussowitsch   Not Collective, No Fortran Support
831d11110bcSJacob Faibussowitsch 
8322fe279fdSBarry Smith   Input Parameter:
833d11110bcSJacob Faibussowitsch . t - pointer to string
834d11110bcSJacob Faibussowitsch 
835d11110bcSJacob Faibussowitsch   Output Parameter:
836d11110bcSJacob Faibussowitsch . s - the copied string
837d11110bcSJacob Faibussowitsch 
838d11110bcSJacob Faibussowitsch   Level: deprecated (since 3.18.5)
839d11110bcSJacob Faibussowitsch 
840d11110bcSJacob Faibussowitsch   Notes:
841d11110bcSJacob Faibussowitsch   It is recommended you use `PetscStrncpy()` (equivalently `PetscArraycpy()` or
842d11110bcSJacob Faibussowitsch   `PetscMemcpy()`) instead of this routine.
843d11110bcSJacob Faibussowitsch 
844d11110bcSJacob Faibussowitsch   `NULL` strings returns a string starting with zero.
845d11110bcSJacob Faibussowitsch 
846d11110bcSJacob Faibussowitsch .seealso: `PetscStrncpy()`
847d11110bcSJacob Faibussowitsch @*/
848d11110bcSJacob Faibussowitsch PetscErrorCode PetscStrcpy(char s[], const char t[])
849d11110bcSJacob Faibussowitsch {
850d11110bcSJacob Faibussowitsch   PetscFunctionBegin;
851d11110bcSJacob Faibussowitsch   if (t) {
8524f572ea9SToby Isaac     PetscAssertPointer(s, 1);
8534f572ea9SToby Isaac     PetscAssertPointer(t, 2);
854d11110bcSJacob Faibussowitsch     strcpy(s, t);
855d11110bcSJacob Faibussowitsch   } else if (s) {
856d11110bcSJacob Faibussowitsch     s[0] = '\0';
857d11110bcSJacob Faibussowitsch   }
858d11110bcSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
859d11110bcSJacob Faibussowitsch }
860