xref: /petsc/src/sys/utils/str.c (revision 811af0c4b09a35de4306c442f88bd09fdc09897d)
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 
27*811af0c4SBarry Smith    Note:
2895452b02SPatrick Sanan     this may be called before PetscInitialize() or after PetscFinalize()
293c311c98SBarry Smith 
30*811af0c4SBarry Smith    Fortran Note:
316f013253SBarry Smith    Not for use in Fortran
326f013253SBarry Smith 
3395452b02SPatrick Sanan    Developer Notes:
34*811af0c4SBarry Smith    Uses raw `malloc()` and does not call error handlers since this may be used before PETSc is initialized.
35*811af0c4SBarry Smith 
36*811af0c4SBarry Smith    Used to generate argc, args arguments passed to `MPI_Init()`
37301d30feSBarry Smith 
38db781477SPatrick Sanan .seealso: `PetscStrToArrayDestroy()`, `PetscToken`, `PetscTokenCreate()`
393c311c98SBarry Smith @*/
409371c9d4SSatish Balay PetscErrorCode PetscStrToArray(const char s[], char sp, int *argc, char ***args) {
41c3bcdc7eSBarry Smith   int       i, j, n, *lens, cnt = 0;
42ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
433c311c98SBarry Smith 
4440a7e1efSBarry Smith   if (!s) n = 0;
4540a7e1efSBarry Smith   else n = strlen(s);
463c311c98SBarry Smith   *argc = 0;
4761528463SBarry Smith   *args = NULL;
48acf7dc08SSatish Balay   for (; n > 0; n--) { /* remove separator chars at the end - and will empty the string if all chars are separator chars */
49acf7dc08SSatish Balay     if (s[n - 1] != sp) break;
50acf7dc08SSatish Balay   }
515f80ce2aSJacob Faibussowitsch   if (!n) return 0;
523c311c98SBarry Smith   for (i = 0; i < n; i++) {
53d67fe73bSBarry Smith     if (s[i] != sp) break;
543c311c98SBarry Smith   }
553c311c98SBarry Smith   for (; i < n + 1; i++) {
569371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
579371c9d4SSatish Balay       flg = PETSC_TRUE;
589371c9d4SSatish Balay       (*argc)++;
599371c9d4SSatish Balay     } else if (s[i] != sp) {
609371c9d4SSatish Balay       flg = PETSC_FALSE;
613c311c98SBarry Smith     }
629371c9d4SSatish Balay   }
639371c9d4SSatish Balay   (*args) = (char **)malloc(((*argc) + 1) * sizeof(char *));
649371c9d4SSatish Balay   if (!*args) return PETSC_ERR_MEM;
659371c9d4SSatish Balay   lens = (int *)malloc((*argc) * sizeof(int));
669371c9d4SSatish Balay   if (!lens) return PETSC_ERR_MEM;
673c311c98SBarry Smith   for (i = 0; i < *argc; i++) lens[i] = 0;
683c311c98SBarry Smith 
693c311c98SBarry Smith   *argc = 0;
703c311c98SBarry Smith   for (i = 0; i < n; i++) {
71d67fe73bSBarry Smith     if (s[i] != sp) break;
723c311c98SBarry Smith   }
737dd9f305SSatish Balay   for (; i < n + 1; i++) {
749371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
759371c9d4SSatish Balay       flg = PETSC_TRUE;
769371c9d4SSatish Balay       (*argc)++;
779371c9d4SSatish Balay     } else if (s[i] != sp) {
789371c9d4SSatish Balay       lens[*argc]++;
799371c9d4SSatish Balay       flg = PETSC_FALSE;
809371c9d4SSatish Balay     }
813c311c98SBarry Smith   }
823c311c98SBarry Smith 
833c311c98SBarry Smith   for (i = 0; i < *argc; i++) {
84c3bcdc7eSBarry Smith     (*args)[i] = (char *)malloc((lens[i] + 1) * sizeof(char));
85c3bcdc7eSBarry Smith     if (!(*args)[i]) {
86c3bcdc7eSBarry Smith       free(lens);
87c3bcdc7eSBarry Smith       for (j = 0; j < i; j++) free((*args)[j]);
88c3bcdc7eSBarry Smith       free(*args);
89c3bcdc7eSBarry Smith       return PETSC_ERR_MEM;
90c3bcdc7eSBarry Smith     }
913c311c98SBarry Smith   }
92a2ea699eSBarry Smith   free(lens);
9302c9f0b5SLisandro Dalcin   (*args)[*argc] = NULL;
943c311c98SBarry Smith 
953c311c98SBarry Smith   *argc = 0;
963c311c98SBarry Smith   for (i = 0; i < n; i++) {
97d67fe73bSBarry Smith     if (s[i] != sp) break;
983c311c98SBarry Smith   }
993c311c98SBarry Smith   for (; i < n + 1; i++) {
1009371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
1019371c9d4SSatish Balay       flg                   = PETSC_TRUE;
1029371c9d4SSatish Balay       (*args)[*argc][cnt++] = 0;
1039371c9d4SSatish Balay       (*argc)++;
1049371c9d4SSatish Balay       cnt = 0;
1059371c9d4SSatish Balay     } else if (s[i] != sp && s[i] != 0) {
1069371c9d4SSatish Balay       (*args)[*argc][cnt++] = s[i];
1079371c9d4SSatish Balay       flg                   = PETSC_FALSE;
1089371c9d4SSatish Balay     }
1093c311c98SBarry Smith   }
1103c311c98SBarry Smith   return 0;
1113c311c98SBarry Smith }
1123c311c98SBarry Smith 
113301d30feSBarry Smith /*@C
114*811af0c4SBarry Smith    PetscStrToArrayDestroy - Frees array created with `PetscStrToArray()`.
115301d30feSBarry Smith 
116301d30feSBarry Smith    Not Collective
117301d30feSBarry Smith 
118301d30feSBarry Smith    Output Parameters:
119301d30feSBarry Smith +  argc - the number of arguments
120301d30feSBarry Smith -  args - the array of arguments
121301d30feSBarry Smith 
122301d30feSBarry Smith    Level: intermediate
123301d30feSBarry Smith 
124*811af0c4SBarry Smith    Note:
125*811af0c4SBarry Smith     This may be called before `PetscInitialize()` or after `PetscFinalize()`
126301d30feSBarry Smith 
127*811af0c4SBarry Smith    Fortran Note:
1286f013253SBarry Smith    Not for use in Fortran
1296f013253SBarry Smith 
130db781477SPatrick Sanan .seealso: `PetscStrToArray()`
131301d30feSBarry Smith @*/
1329371c9d4SSatish Balay PetscErrorCode PetscStrToArrayDestroy(int argc, char **args) {
1335f80ce2aSJacob Faibussowitsch   for (int i = 0; i < argc; ++i) free(args[i]);
134a297a907SKarl Rupp   if (args) free(args);
135301d30feSBarry Smith   return 0;
136301d30feSBarry Smith }
137301d30feSBarry Smith 
138e5c89e4eSSatish Balay /*@C
139e5c89e4eSSatish Balay    PetscStrlen - Gets length of a string
140e5c89e4eSSatish Balay 
141e5c89e4eSSatish Balay    Not Collective
142e5c89e4eSSatish Balay 
143e5c89e4eSSatish Balay    Input Parameters:
144e5c89e4eSSatish Balay .  s - pointer to string
145e5c89e4eSSatish Balay 
146e5c89e4eSSatish Balay    Output Parameter:
147e5c89e4eSSatish Balay .  len - length in bytes
148e5c89e4eSSatish Balay 
149e5c89e4eSSatish Balay    Level: intermediate
150e5c89e4eSSatish Balay 
151e5c89e4eSSatish Balay    Note:
152*811af0c4SBarry Smith    This routine is analogous to `strlen()`.
153e5c89e4eSSatish Balay 
154e5c89e4eSSatish Balay    Null string returns a length of zero
155e5c89e4eSSatish Balay 
156*811af0c4SBarry Smith    Fortran Note:
1576f013253SBarry Smith    Not for use in Fortran
1586f013253SBarry Smith 
159*811af0c4SBarry Smith .seealso: `PetscStrallocpy()`
160e5c89e4eSSatish Balay @*/
1619371c9d4SSatish Balay PetscErrorCode PetscStrlen(const char s[], size_t *len) {
162e5c89e4eSSatish Balay   PetscFunctionBegin;
1635f80ce2aSJacob Faibussowitsch   *len = s ? strlen(s) : 0;
164e5c89e4eSSatish Balay   PetscFunctionReturn(0);
165e5c89e4eSSatish Balay }
166e5c89e4eSSatish Balay 
167e5c89e4eSSatish Balay /*@C
168*811af0c4SBarry Smith    PetscStrallocpy - Allocates space to hold a copy of a string then copies the string in the new space
169e5c89e4eSSatish Balay 
170e5c89e4eSSatish Balay    Not Collective
171e5c89e4eSSatish Balay 
172e5c89e4eSSatish Balay    Input Parameters:
173e5c89e4eSSatish Balay .  s - pointer to string
174e5c89e4eSSatish Balay 
175e5c89e4eSSatish Balay    Output Parameter:
176e5c89e4eSSatish Balay .  t - the copied string
177e5c89e4eSSatish Balay 
178e5c89e4eSSatish Balay    Level: intermediate
179e5c89e4eSSatish Balay 
180*811af0c4SBarry Smith    Notes:
181e5c89e4eSSatish Balay    Null string returns a new null string
182e5c89e4eSSatish Balay 
183*811af0c4SBarry Smith    If t has previously been allocated then that memory is lost, you may need to PetscFree()
1840ecf5a55SBarry Smith    the array before calling this routine.
1850ecf5a55SBarry Smith 
186*811af0c4SBarry Smith    Fortran Note:
187*811af0c4SBarry Smith    Not for use in Fortran
1880ecf5a55SBarry Smith 
189*811af0c4SBarry Smith .seealso: `PetscStrArrayallocpy()`, `PetscStrcpy()`, `PetscStrNArrayallocpy()`
190e5c89e4eSSatish Balay @*/
1919371c9d4SSatish Balay PetscErrorCode PetscStrallocpy(const char s[], char *t[]) {
19202c9f0b5SLisandro Dalcin   char *tmp = NULL;
193e5c89e4eSSatish Balay 
194e5c89e4eSSatish Balay   PetscFunctionBegin;
195e5c89e4eSSatish Balay   if (s) {
1965f80ce2aSJacob Faibussowitsch     size_t len;
1975f80ce2aSJacob Faibussowitsch 
1989566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(s, &len));
1999566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(1 + len, &tmp));
2009566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(tmp, s));
201e5c89e4eSSatish Balay   }
20271573d7dSBarry Smith   *t = tmp;
203e5c89e4eSSatish Balay   PetscFunctionReturn(0);
204e5c89e4eSSatish Balay }
205e5c89e4eSSatish Balay 
20647340559SBarry Smith /*@C
20747340559SBarry Smith    PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
20847340559SBarry Smith 
20947340559SBarry Smith    Not Collective
21047340559SBarry Smith 
21147340559SBarry Smith    Input Parameters:
21247340559SBarry Smith .  s - pointer to array of strings (final string is a null)
21347340559SBarry Smith 
21447340559SBarry Smith    Output Parameter:
21547340559SBarry Smith .  t - the copied array string
21647340559SBarry Smith 
21747340559SBarry Smith    Level: intermediate
21847340559SBarry Smith 
21947340559SBarry Smith    Note:
220*811af0c4SBarry Smith    If t has previously been allocated then that memory is lost, you may need to PetscStrArrayDestroy()
2210ecf5a55SBarry Smith    the array before calling this routine.
2220ecf5a55SBarry Smith 
223*811af0c4SBarry Smith    Fortran Note:
224*811af0c4SBarry Smith    Not for use in Fortran
22547340559SBarry Smith 
226*811af0c4SBarry Smith .seealso: `PetscStrallocpy()`, `PetscStrArrayDestroy()`, `PetscStrNArrayallocpy()`
22747340559SBarry Smith @*/
2289371c9d4SSatish Balay PetscErrorCode PetscStrArrayallocpy(const char *const *list, char ***t) {
2295f80ce2aSJacob Faibussowitsch   PetscInt n = 0;
23047340559SBarry Smith 
23147340559SBarry Smith   PetscFunctionBegin;
2329371c9d4SSatish Balay   while (list[n++])
2339371c9d4SSatish Balay     ;
2349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n + 1, t));
2359566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
2360298fd71SBarry Smith   (*t)[n] = NULL;
23747340559SBarry Smith   PetscFunctionReturn(0);
23847340559SBarry Smith }
23947340559SBarry Smith 
24047340559SBarry Smith /*@C
241*811af0c4SBarry Smith    PetscStrArrayDestroy - Frees array of strings created with `PetscStrArrayallocpy()`.
24247340559SBarry Smith 
24347340559SBarry Smith    Not Collective
24447340559SBarry Smith 
24547340559SBarry Smith    Output Parameters:
24647340559SBarry Smith .   list - array of strings
24747340559SBarry Smith 
24847340559SBarry Smith    Level: intermediate
24947340559SBarry Smith 
250*811af0c4SBarry Smith    Fortran Note:
25195452b02SPatrick Sanan     Not for use in Fortran
25247340559SBarry Smith 
253db781477SPatrick Sanan .seealso: `PetscStrArrayallocpy()`
25447340559SBarry Smith @*/
2559371c9d4SSatish Balay PetscErrorCode PetscStrArrayDestroy(char ***list) {
25647340559SBarry Smith   PetscInt n = 0;
25747340559SBarry Smith 
2586fed8037SJed Brown   PetscFunctionBegin;
2596fed8037SJed Brown   if (!*list) PetscFunctionReturn(0);
2606fed8037SJed Brown   while ((*list)[n]) {
2619566063dSJacob Faibussowitsch     PetscCall(PetscFree((*list)[n]));
2625f80ce2aSJacob Faibussowitsch     ++n;
26347340559SBarry Smith   }
2649566063dSJacob Faibussowitsch   PetscCall(PetscFree(*list));
2656fed8037SJed Brown   PetscFunctionReturn(0);
26647340559SBarry Smith }
26747340559SBarry Smith 
2686991f827SBarry Smith /*@C
2696991f827SBarry Smith    PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
2706991f827SBarry Smith 
2716991f827SBarry Smith    Not Collective
2726991f827SBarry Smith 
2736991f827SBarry Smith    Input Parameters:
2746991f827SBarry Smith +  n - the number of string entries
2756991f827SBarry Smith -  s - pointer to array of strings
2766991f827SBarry Smith 
2776991f827SBarry Smith    Output Parameter:
2786991f827SBarry Smith .  t - the copied array string
2796991f827SBarry Smith 
2806991f827SBarry Smith    Level: intermediate
2816991f827SBarry Smith 
282*811af0c4SBarry Smith    Fortran Note:
2836991f827SBarry Smith       Not for use in Fortran
2846991f827SBarry Smith 
285db781477SPatrick Sanan .seealso: `PetscStrallocpy()`, `PetscStrArrayallocpy()`, `PetscStrNArrayDestroy()`
2866991f827SBarry Smith @*/
2879371c9d4SSatish Balay PetscErrorCode PetscStrNArrayallocpy(PetscInt n, const char *const *list, char ***t) {
2886991f827SBarry Smith   PetscFunctionBegin;
2899566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, t));
2909566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
2916991f827SBarry Smith   PetscFunctionReturn(0);
2926991f827SBarry Smith }
2936991f827SBarry Smith 
2946991f827SBarry Smith /*@C
295*811af0c4SBarry Smith    PetscStrNArrayDestroy - Frees array of strings created with `PetscStrNArrayallocpy()`.
2966991f827SBarry Smith 
2976991f827SBarry Smith    Not Collective
2986991f827SBarry Smith 
2996991f827SBarry Smith    Output Parameters:
3006991f827SBarry Smith +   n - number of string entries
3016991f827SBarry Smith -   list - array of strings
3026991f827SBarry Smith 
3036991f827SBarry Smith    Level: intermediate
3046991f827SBarry Smith 
305*811af0c4SBarry Smith    Fortran Note:
30695452b02SPatrick Sanan     Not for use in Fortran
3076991f827SBarry Smith 
308*811af0c4SBarry Smith .seealso: `PetscStrNArrayallocpy()`, `PetscStrArrayallocpy()`
3096991f827SBarry Smith @*/
3109371c9d4SSatish Balay PetscErrorCode PetscStrNArrayDestroy(PetscInt n, char ***list) {
3116991f827SBarry Smith   PetscFunctionBegin;
3126991f827SBarry Smith   if (!*list) PetscFunctionReturn(0);
3139566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscFree((*list)[i]));
3149566063dSJacob Faibussowitsch   PetscCall(PetscFree(*list));
3156991f827SBarry Smith   PetscFunctionReturn(0);
3166991f827SBarry Smith }
3176991f827SBarry Smith 
318e5c89e4eSSatish Balay /*@C
319e5c89e4eSSatish Balay    PetscStrcpy - Copies a string
320e5c89e4eSSatish Balay 
321e5c89e4eSSatish Balay    Not Collective
322e5c89e4eSSatish Balay 
323e5c89e4eSSatish Balay    Input Parameters:
324e5c89e4eSSatish Balay .  t - pointer to string
325e5c89e4eSSatish Balay 
326e5c89e4eSSatish Balay    Output Parameter:
327e5c89e4eSSatish Balay .  s - the copied string
328e5c89e4eSSatish Balay 
329e5c89e4eSSatish Balay    Level: intermediate
330e5c89e4eSSatish Balay 
3316f013253SBarry Smith    Notes:
332e5c89e4eSSatish Balay      Null string returns a string starting with zero
333e5c89e4eSSatish Balay 
334*811af0c4SBarry Smith      It is recommended you use `PetscStrncpy()` instead of this routine
335*811af0c4SBarry Smith 
336*811af0c4SBarry Smith    Fortran Note:
3376f013253SBarry Smith     Not for use in Fortran
3386f013253SBarry Smith 
339*811af0c4SBarry Smith .seealso: `PetscStrncpy()`, `PetscStrcat()`, `PetscStrlcat()`, `PetscStrallocpy()`
340e5c89e4eSSatish Balay @*/
341acc6cc86SBarry Smith 
3429371c9d4SSatish Balay PetscErrorCode PetscStrcpy(char s[], const char t[]) {
343e5c89e4eSSatish Balay   PetscFunctionBegin;
3445f80ce2aSJacob Faibussowitsch   if (t) {
3455f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(s, 1);
3465f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(t, 2);
3475f80ce2aSJacob Faibussowitsch     strcpy(s, t);
3485f80ce2aSJacob Faibussowitsch   } else if (s) s[0] = 0;
349e5c89e4eSSatish Balay   PetscFunctionReturn(0);
350e5c89e4eSSatish Balay }
351e5c89e4eSSatish Balay 
352e5c89e4eSSatish Balay /*@C
353e5c89e4eSSatish Balay    PetscStrncpy - Copies a string up to a certain length
354e5c89e4eSSatish Balay 
355e5c89e4eSSatish Balay    Not Collective
356e5c89e4eSSatish Balay 
357e5c89e4eSSatish Balay    Input Parameters:
358e5c89e4eSSatish Balay +  t - pointer to string
359e5c89e4eSSatish Balay -  n - the length to copy
360e5c89e4eSSatish Balay 
361e5c89e4eSSatish Balay    Output Parameter:
362e5c89e4eSSatish Balay .  s - the copied string
363e5c89e4eSSatish Balay 
364e5c89e4eSSatish Balay    Level: intermediate
365e5c89e4eSSatish Balay 
366e5c89e4eSSatish Balay    Note:
367e5c89e4eSSatish Balay      Null string returns a string starting with zero
368e5c89e4eSSatish Balay 
369ff32304bSBarry Smith      If the string that is being copied is of length n or larger then the entire string is not
3701b6ef838SBarry Smith      copied and the final location of s is set to NULL. This is different then the behavior of
371*811af0c4SBarry Smith      `strncpy()` which leaves s non-terminated if there is not room for the entire string.
372ff32304bSBarry Smith 
373*811af0c4SBarry Smith   Developers Note:
374*811af0c4SBarry Smith   Should this be `PetscStrlcpy()` to reflect its behavior which is like `strlcpy()` not `strncpy()`
37562a5de14SBarry Smith 
376*811af0c4SBarry Smith .seealso: `PetscStrcpy()`, `PetscStrcat()`, `PetscStrlcat()`, `PetscStrallocpy()`
377e5c89e4eSSatish Balay @*/
3789371c9d4SSatish Balay PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n) {
379e5c89e4eSSatish Balay   PetscFunctionBegin;
3805f80ce2aSJacob Faibussowitsch   if (s) PetscCheck(n, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Requires an output string of length at least 1 to hold the termination character");
381ff32304bSBarry Smith   if (t) {
3825f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(s, 1);
3838dc57659SBarry Smith     if (n > 1) {
3842c26941aSBarry Smith       strncpy(s, t, n - 1);
385ff32304bSBarry Smith       s[n - 1] = '\0';
3868dc57659SBarry Smith     } else {
3878dc57659SBarry Smith       s[0] = '\0';
3888dc57659SBarry Smith     }
389ff32304bSBarry Smith   } else if (s) s[0] = 0;
390e5c89e4eSSatish Balay   PetscFunctionReturn(0);
391e5c89e4eSSatish Balay }
392e5c89e4eSSatish Balay 
393e5c89e4eSSatish Balay /*@C
394e5c89e4eSSatish Balay    PetscStrcat - Concatenates a string onto a given string
395e5c89e4eSSatish Balay 
396e5c89e4eSSatish Balay    Not Collective
397e5c89e4eSSatish Balay 
398e5c89e4eSSatish Balay    Input Parameters:
399e5e2177aSMatthew Knepley +  s - string to be added to
400e5e2177aSMatthew Knepley -  t - pointer to string to be added to end
401e5c89e4eSSatish Balay 
402e5c89e4eSSatish Balay    Level: intermediate
403e5c89e4eSSatish Balay 
404*811af0c4SBarry Smith    Note:
405*811af0c4SBarry Smith     It is recommended you use `PetscStrlcat()` instead of this routine
406*811af0c4SBarry Smith 
407*811af0c4SBarry Smith    Fortran Note:
40895452b02SPatrick Sanan     Not for use in Fortran
4096f013253SBarry Smith 
410db781477SPatrick Sanan .seealso: `PetscStrcpy()`, `PetscStrncpy()`, `PetscStrlcat()`
411e5c89e4eSSatish Balay @*/
4129371c9d4SSatish Balay PetscErrorCode PetscStrcat(char s[], const char t[]) {
413e5c89e4eSSatish Balay   PetscFunctionBegin;
4149b754dc9SBarry Smith   if (!t) PetscFunctionReturn(0);
4155f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(s, 1);
4165f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(t, 2);
417e5c89e4eSSatish Balay   strcat(s, t);
418e5c89e4eSSatish Balay   PetscFunctionReturn(0);
419e5c89e4eSSatish Balay }
420e5c89e4eSSatish Balay 
421e5c89e4eSSatish Balay /*@C
422a126751eSBarry Smith    PetscStrlcat - Concatenates a string onto a given string, up to a given length
423e5c89e4eSSatish Balay 
424e5c89e4eSSatish Balay    Not Collective
425e5c89e4eSSatish Balay 
426e5c89e4eSSatish Balay    Input Parameters:
427e0ffd71fSBarry Smith +  s - pointer to string to be added to at end
42872fa4726SStefano Zampini .  t - string to be added
42924a58d73SPatrick Sanan -  n - length of the original allocated string
430e5c89e4eSSatish Balay 
431e5c89e4eSSatish Balay    Level: intermediate
432e5c89e4eSSatish Balay 
433*811af0c4SBarry Smith   Note:
434*811af0c4SBarry Smith   Unlike the system call `strncat()`, the length passed in is the length of the
435*811af0c4SBarry Smith   original allocated space, not the length of the left-over space. This is
436*811af0c4SBarry Smith   similar to the BSD system call `strlcat()`.
437*811af0c4SBarry Smith 
438*811af0c4SBarry Smith   Fortran Note:
43924a58d73SPatrick Sanan   Not for use in Fortran
4406f013253SBarry Smith 
441db781477SPatrick Sanan .seealso: `PetscStrcpy()`, `PetscStrncpy()`, `PetscStrcat()`
442e5c89e4eSSatish Balay @*/
4439371c9d4SSatish Balay PetscErrorCode PetscStrlcat(char s[], const char t[], size_t n) {
444153a8027SBarry Smith   size_t len;
445153a8027SBarry Smith 
446e5c89e4eSSatish Balay   PetscFunctionBegin;
447e0ffd71fSBarry Smith   if (!t) PetscFunctionReturn(0);
4485f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(s, 1);
4495f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(t, 2);
4505f80ce2aSJacob Faibussowitsch   PetscCheck(n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "String buffer length must be positive");
4519566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(t, &len));
452153a8027SBarry Smith   strncat(s, t, n - len);
453681eeb0aSBarry Smith   s[n - 1] = 0;
454e5c89e4eSSatish Balay   PetscFunctionReturn(0);
455e5c89e4eSSatish Balay }
456e5c89e4eSSatish Balay 
4579371c9d4SSatish Balay void PetscStrcmpNoError(const char a[], const char b[], PetscBool *flg) {
458573b0fb4SBarry Smith   if (!a && !b) *flg = PETSC_TRUE;
459573b0fb4SBarry Smith   else if (!a || !b) *flg = PETSC_FALSE;
4605f80ce2aSJacob Faibussowitsch   else *flg = strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE;
461573b0fb4SBarry Smith }
462573b0fb4SBarry Smith 
463e5c89e4eSSatish Balay /*@C
464*811af0c4SBarry Smith    PetscBasename - returns a pointer to the last entry of a / or \ separated directory path
46580b92c66SBarry Smith 
46680b92c66SBarry Smith    Not Collective
46780b92c66SBarry Smith 
46880b92c66SBarry Smith    Input Parameter:
46980b92c66SBarry Smith .  a - pointer to string
47080b92c66SBarry Smith 
47180b92c66SBarry Smith    Level: intermediate
47280b92c66SBarry Smith 
473*811af0c4SBarry Smith    Fortran Note:
47480b92c66SBarry Smith     Not for use in Fortran
47580b92c66SBarry Smith 
47680b92c66SBarry Smith .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`, `PetscStrrchr()`,`PetscStrcmp()`,`PetscStrstr()`,
47780b92c66SBarry Smith           `PetscTokenCreate()`, `PetscStrToArray()`, `PetscStrInList()`
47880b92c66SBarry Smith @*/
4799371c9d4SSatish Balay const char *PetscBasename(const char a[]) {
48080b92c66SBarry Smith   const char *ptr;
48180b92c66SBarry Smith 
48280b92c66SBarry Smith   if (PetscStrrchr(a, '/', (char **)&ptr)) ptr = NULL;
483660278c0SBarry Smith   if (ptr == a) {
484660278c0SBarry Smith     if (PetscStrrchr(a, '\\', (char **)&ptr)) ptr = NULL;
485660278c0SBarry Smith   }
48680b92c66SBarry Smith   return ptr;
48780b92c66SBarry Smith }
48880b92c66SBarry Smith 
48980b92c66SBarry Smith /*@C
490e5c89e4eSSatish Balay    PetscStrcmp - Compares two strings,
491e5c89e4eSSatish Balay 
492e5c89e4eSSatish Balay    Not Collective
493e5c89e4eSSatish Balay 
494e5c89e4eSSatish Balay    Input Parameters:
495e5c89e4eSSatish Balay +  a - pointer to string first string
496e5c89e4eSSatish Balay -  b - pointer to second string
497e5c89e4eSSatish Balay 
498e5c89e4eSSatish Balay    Output Parameter:
499*811af0c4SBarry Smith .  flg - `PETSC_TRUE` if the two strings are equal
500e5c89e4eSSatish Balay 
501e5c89e4eSSatish Balay    Level: intermediate
502e5c89e4eSSatish Balay 
503*811af0c4SBarry Smith    Fortran Note:
50495452b02SPatrick Sanan     Not for use in Fortran
5056f013253SBarry Smith 
506db781477SPatrick Sanan .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`
507e5c89e4eSSatish Balay @*/
5089371c9d4SSatish Balay PetscErrorCode PetscStrcmp(const char a[], const char b[], PetscBool *flg) {
509e5c89e4eSSatish Balay   PetscFunctionBegin;
5105f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(flg, 3);
511a297a907SKarl Rupp   if (!a && !b) *flg = PETSC_TRUE;
512a297a907SKarl Rupp   else if (!a || !b) *flg = PETSC_FALSE;
513b45e3bf4SStefano Zampini   else *flg = (PetscBool)!strcmp(a, b);
514e5c89e4eSSatish Balay   PetscFunctionReturn(0);
515e5c89e4eSSatish Balay }
516e5c89e4eSSatish Balay 
517e5c89e4eSSatish Balay /*@C
518e5c89e4eSSatish Balay    PetscStrgrt - If first string is greater than the second
519e5c89e4eSSatish Balay 
520e5c89e4eSSatish Balay    Not Collective
521e5c89e4eSSatish Balay 
522e5c89e4eSSatish Balay    Input Parameters:
523e5c89e4eSSatish Balay +  a - pointer to first string
524e5c89e4eSSatish Balay -  b - pointer to second string
525e5c89e4eSSatish Balay 
526e5c89e4eSSatish Balay    Output Parameter:
527e5c89e4eSSatish Balay .  flg - if the first string is greater
528e5c89e4eSSatish Balay 
529*811af0c4SBarry Smith    Note:
530e5c89e4eSSatish Balay     Null arguments are ok, a null string is considered smaller than
531e5c89e4eSSatish Balay     all others
532e5c89e4eSSatish Balay 
533*811af0c4SBarry Smith    Fortran Note:
5346f013253SBarry Smith    Not for use in Fortran
5356f013253SBarry Smith 
536e5c89e4eSSatish Balay    Level: intermediate
537e5c89e4eSSatish Balay 
538db781477SPatrick Sanan .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrcasecmp()`
539e5c89e4eSSatish Balay @*/
5409371c9d4SSatish Balay PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t) {
541e5c89e4eSSatish Balay   PetscFunctionBegin;
5425f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(t, 3);
543a297a907SKarl Rupp   if (!a && !b) *t = PETSC_FALSE;
544a297a907SKarl Rupp   else if (a && !b) *t = PETSC_TRUE;
545a297a907SKarl Rupp   else if (!a && b) *t = PETSC_FALSE;
546a297a907SKarl Rupp   else {
5475f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(a, 1);
5485f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(b, 2);
5495f80ce2aSJacob Faibussowitsch     *t = strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
550e5c89e4eSSatish Balay   }
551e5c89e4eSSatish Balay   PetscFunctionReturn(0);
552e5c89e4eSSatish Balay }
553e5c89e4eSSatish Balay 
554e5c89e4eSSatish Balay /*@C
555e5c89e4eSSatish Balay    PetscStrcasecmp - Returns true if the two strings are the same
556e5c89e4eSSatish Balay      except possibly for case.
557e5c89e4eSSatish Balay 
558e5c89e4eSSatish Balay    Not Collective
559e5c89e4eSSatish Balay 
560e5c89e4eSSatish Balay    Input Parameters:
561e5c89e4eSSatish Balay +  a - pointer to first string
562e5c89e4eSSatish Balay -  b - pointer to second string
563e5c89e4eSSatish Balay 
564e5c89e4eSSatish Balay    Output Parameter:
565e5c89e4eSSatish Balay .  flg - if the two strings are the same
566e5c89e4eSSatish Balay 
567*811af0c4SBarry Smith    Note:
568e5c89e4eSSatish Balay     Null arguments are ok
569e5c89e4eSSatish Balay 
570*811af0c4SBarry Smith    Fortran Note:
5716f013253SBarry Smith    Not for use in Fortran
5726f013253SBarry Smith 
573e5c89e4eSSatish Balay    Level: intermediate
574e5c89e4eSSatish Balay 
575db781477SPatrick Sanan .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrgrt()`
576e5c89e4eSSatish Balay @*/
5779371c9d4SSatish Balay PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t) {
578e5c89e4eSSatish Balay   int c;
579e5c89e4eSSatish Balay 
580e5c89e4eSSatish Balay   PetscFunctionBegin;
5815f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(t, 3);
582e5c89e4eSSatish Balay   if (!a && !b) c = 0;
583e5c89e4eSSatish Balay   else if (!a || !b) c = 1;
58432b366c8SSatish Balay #if defined(PETSC_HAVE_STRCASECMP)
58532b366c8SSatish Balay   else c = strcasecmp(a, b);
58632b366c8SSatish Balay #elif defined(PETSC_HAVE_STRICMP)
587e5c89e4eSSatish Balay   else c = stricmp(a, b);
588e5c89e4eSSatish Balay #else
58932b366c8SSatish Balay   else {
59032b366c8SSatish Balay     char *aa, *bb;
5919566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(a, &aa));
5929566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(b, &bb));
5939566063dSJacob Faibussowitsch     PetscCall(PetscStrtolower(aa));
5949566063dSJacob Faibussowitsch     PetscCall(PetscStrtolower(bb));
5959566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(aa, bb, t));
5969566063dSJacob Faibussowitsch     PetscCall(PetscFree(aa));
5979566063dSJacob Faibussowitsch     PetscCall(PetscFree(bb));
59832b366c8SSatish Balay     PetscFunctionReturn(0);
59932b366c8SSatish Balay   }
600e5c89e4eSSatish Balay #endif
6015f80ce2aSJacob Faibussowitsch   *t = c ? PETSC_FALSE : PETSC_TRUE;
602e5c89e4eSSatish Balay   PetscFunctionReturn(0);
603e5c89e4eSSatish Balay }
604e5c89e4eSSatish Balay 
605e5c89e4eSSatish Balay /*@C
606e5c89e4eSSatish Balay    PetscStrncmp - Compares two strings, up to a certain length
607e5c89e4eSSatish Balay 
608e5c89e4eSSatish Balay    Not Collective
609e5c89e4eSSatish Balay 
610e5c89e4eSSatish Balay    Input Parameters:
611e5c89e4eSSatish Balay +  a - pointer to first string
612e5c89e4eSSatish Balay .  b - pointer to second string
613e5c89e4eSSatish Balay -  n - length to compare up to
614e5c89e4eSSatish Balay 
615e5c89e4eSSatish Balay    Output Parameter:
616e5c89e4eSSatish Balay .  t - if the two strings are equal
617e5c89e4eSSatish Balay 
618e5c89e4eSSatish Balay    Level: intermediate
619e5c89e4eSSatish Balay 
620*811af0c4SBarry Smith    Fortran Note:
62195452b02SPatrick Sanan     Not for use in Fortran
6226f013253SBarry Smith 
623db781477SPatrick Sanan .seealso: `PetscStrgrt()`, `PetscStrcmp()`, `PetscStrcasecmp()`
624e5c89e4eSSatish Balay @*/
6259371c9d4SSatish Balay PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t) {
626e5c89e4eSSatish Balay   PetscFunctionBegin;
6275f80ce2aSJacob Faibussowitsch   if (n) {
6285f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(a, 1);
6295f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(b, 2);
6305f80ce2aSJacob Faibussowitsch   }
6315f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(t, 4);
6325f80ce2aSJacob Faibussowitsch   *t = strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
633e5c89e4eSSatish Balay   PetscFunctionReturn(0);
634e5c89e4eSSatish Balay }
635e5c89e4eSSatish Balay 
636e5c89e4eSSatish Balay /*@C
637a5b23f4aSJose E. Roman    PetscStrchr - Locates first occurrence of a character in a string
638e5c89e4eSSatish Balay 
639e5c89e4eSSatish Balay    Not Collective
640e5c89e4eSSatish Balay 
641e5c89e4eSSatish Balay    Input Parameters:
642e5c89e4eSSatish Balay +  a - pointer to string
643e5c89e4eSSatish Balay -  b - character
644e5c89e4eSSatish Balay 
645e5c89e4eSSatish Balay    Output Parameter:
646a5b23f4aSJose E. Roman .  c - location of occurrence, NULL if not found
647e5c89e4eSSatish Balay 
648e5c89e4eSSatish Balay    Level: intermediate
649e5c89e4eSSatish Balay 
650*811af0c4SBarry Smith    Fortran Note:
65195452b02SPatrick Sanan     Not for use in Fortran
6526f013253SBarry Smith 
653*811af0c4SBarry Smith .seealso: `PetscStrrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
654e5c89e4eSSatish Balay @*/
6559371c9d4SSatish Balay PetscErrorCode PetscStrchr(const char a[], char b, char *c[]) {
656e5c89e4eSSatish Balay   PetscFunctionBegin;
6575f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
6585f80ce2aSJacob Faibussowitsch   PetscValidPointer(c, 3);
659e5c89e4eSSatish Balay   *c = (char *)strchr(a, b);
660e5c89e4eSSatish Balay   PetscFunctionReturn(0);
661e5c89e4eSSatish Balay }
662e5c89e4eSSatish Balay 
663e5c89e4eSSatish Balay /*@C
664a5b23f4aSJose E. Roman    PetscStrrchr - Locates one location past the last occurrence of a character in a string,
665e5c89e4eSSatish Balay       if the character is not found then returns entire string
666e5c89e4eSSatish Balay 
667e5c89e4eSSatish Balay    Not Collective
668e5c89e4eSSatish Balay 
669e5c89e4eSSatish Balay    Input Parameters:
670e5c89e4eSSatish Balay +  a - pointer to string
671e5c89e4eSSatish Balay -  b - character
672e5c89e4eSSatish Balay 
673e5c89e4eSSatish Balay    Output Parameter:
674a5b23f4aSJose E. Roman .  tmp - location of occurrence, a if not found
675e5c89e4eSSatish Balay 
676e5c89e4eSSatish Balay    Level: intermediate
677e5c89e4eSSatish Balay 
678*811af0c4SBarry Smith    Fortran Note:
67995452b02SPatrick Sanan     Not for use in Fortran
6806f013253SBarry Smith 
681*811af0c4SBarry Smith .seealso: `PetscStrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
682e5c89e4eSSatish Balay @*/
6839371c9d4SSatish Balay PetscErrorCode PetscStrrchr(const char a[], char b, char *tmp[]) {
684e5c89e4eSSatish Balay   PetscFunctionBegin;
6855f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
6865f80ce2aSJacob Faibussowitsch   PetscValidPointer(tmp, 3);
687e5c89e4eSSatish Balay   *tmp = (char *)strrchr(a, b);
688a297a907SKarl Rupp   if (!*tmp) *tmp = (char *)a;
689a297a907SKarl Rupp   else *tmp = *tmp + 1;
690e5c89e4eSSatish Balay   PetscFunctionReturn(0);
691e5c89e4eSSatish Balay }
692e5c89e4eSSatish Balay 
693e5c89e4eSSatish Balay /*@C
694e5c89e4eSSatish Balay    PetscStrtolower - Converts string to lower case
695e5c89e4eSSatish Balay 
696e5c89e4eSSatish Balay    Not Collective
697e5c89e4eSSatish Balay 
698e5c89e4eSSatish Balay    Input Parameters:
699e5c89e4eSSatish Balay .  a - pointer to string
700e5c89e4eSSatish Balay 
701e5c89e4eSSatish Balay    Level: intermediate
702e5c89e4eSSatish Balay 
703*811af0c4SBarry Smith    Fortran Note:
70495452b02SPatrick Sanan     Not for use in Fortran
7056f013253SBarry Smith 
706*811af0c4SBarry Smith .seealso: `PetscStrtoupper()`
707e5c89e4eSSatish Balay @*/
7089371c9d4SSatish Balay PetscErrorCode PetscStrtolower(char a[]) {
709e5c89e4eSSatish Balay   PetscFunctionBegin;
7105f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
711e5c89e4eSSatish Balay   while (*a) {
712e5c89e4eSSatish Balay     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
713e5c89e4eSSatish Balay     a++;
714e5c89e4eSSatish Balay   }
715e5c89e4eSSatish Balay   PetscFunctionReturn(0);
716e5c89e4eSSatish Balay }
717e5c89e4eSSatish Balay 
7182f234a98SBarry Smith /*@C
7196e3a5469SBarry Smith    PetscStrtoupper - Converts string to upper case
7202f234a98SBarry Smith 
7212f234a98SBarry Smith    Not Collective
7222f234a98SBarry Smith 
7232f234a98SBarry Smith    Input Parameters:
7242f234a98SBarry Smith .  a - pointer to string
7252f234a98SBarry Smith 
7262f234a98SBarry Smith    Level: intermediate
7272f234a98SBarry Smith 
728*811af0c4SBarry Smith    Fortran Note:
72995452b02SPatrick Sanan     Not for use in Fortran
7302f234a98SBarry Smith 
731*811af0c4SBarry Smith .seealso: `PetscStrtolower()`
7322f234a98SBarry Smith @*/
7339371c9d4SSatish Balay PetscErrorCode PetscStrtoupper(char a[]) {
7342f234a98SBarry Smith   PetscFunctionBegin;
7355f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
7362f234a98SBarry Smith   while (*a) {
7372f234a98SBarry Smith     if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a';
7382f234a98SBarry Smith     a++;
7392f234a98SBarry Smith   }
7402f234a98SBarry Smith   PetscFunctionReturn(0);
7412f234a98SBarry Smith }
7422f234a98SBarry Smith 
7437ba3a57cSBarry Smith /*@C
7447ba3a57cSBarry Smith    PetscStrendswith - Determines if a string ends with a certain string
7451d1a0024SBarry Smith 
7467ba3a57cSBarry Smith    Not Collective
7477ba3a57cSBarry Smith 
7487ba3a57cSBarry Smith    Input Parameters:
7497ba3a57cSBarry Smith +  a - pointer to string
7507ba3a57cSBarry Smith -  b - string to endwith
7517ba3a57cSBarry Smith 
7527ba3a57cSBarry Smith    Output Parameter:
753*811af0c4SBarry Smith .  flg - `PETSC_TRUE` or `PETSC_FALSE`
7547ba3a57cSBarry Smith 
755*811af0c4SBarry Smith    Fortran Note:
75695452b02SPatrick Sanan     Not for use in Fortran
7577ba3a57cSBarry Smith 
7587ba3a57cSBarry Smith    Level: intermediate
7597ba3a57cSBarry Smith 
760*811af0c4SBarry Smith .seealso: `PetscStrendswithwhich()`, `PetscStrbeginswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
761*811af0c4SBarry Smith           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()`
7627ba3a57cSBarry Smith @*/
7639371c9d4SSatish Balay PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg) {
7647ba3a57cSBarry Smith   char *test;
7657ba3a57cSBarry Smith 
7667ba3a57cSBarry Smith   PetscFunctionBegin;
7675f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(flg, 3);
7687ba3a57cSBarry Smith   *flg = PETSC_FALSE;
7699566063dSJacob Faibussowitsch   PetscCall(PetscStrrstr(a, b, &test));
7707ba3a57cSBarry Smith   if (test) {
7715f80ce2aSJacob Faibussowitsch     size_t na, nb;
7725f80ce2aSJacob Faibussowitsch 
7739566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(a, &na));
7749566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(b, &nb));
7757ba3a57cSBarry Smith     if (a + na - nb == test) *flg = PETSC_TRUE;
7767ba3a57cSBarry Smith   }
7777ba3a57cSBarry Smith   PetscFunctionReturn(0);
7787ba3a57cSBarry Smith }
7797ba3a57cSBarry Smith 
7802c9581d2SBarry Smith /*@C
7812c9581d2SBarry Smith    PetscStrbeginswith - Determines if a string begins with a certain string
7822c9581d2SBarry Smith 
7832c9581d2SBarry Smith    Not Collective
7842c9581d2SBarry Smith 
7852c9581d2SBarry Smith    Input Parameters:
7862c9581d2SBarry Smith +  a - pointer to string
7872c9581d2SBarry Smith -  b - string to begin with
7882c9581d2SBarry Smith 
7892c9581d2SBarry Smith    Output Parameter:
7902c9581d2SBarry Smith .  flg - PETSC_TRUE or PETSC_FALSE
7912c9581d2SBarry Smith 
792*811af0c4SBarry Smith    Fortran Note:
79395452b02SPatrick Sanan     Not for use in Fortran
7942c9581d2SBarry Smith 
7952c9581d2SBarry Smith    Level: intermediate
7962c9581d2SBarry Smith 
797db781477SPatrick Sanan .seealso: `PetscStrendswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
798db781477SPatrick Sanan           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()`
7992c9581d2SBarry Smith @*/
8009371c9d4SSatish Balay PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg) {
8012c9581d2SBarry Smith   char *test;
8022c9581d2SBarry Smith 
8032c9581d2SBarry Smith   PetscFunctionBegin;
8045f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
8055f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(b, 2);
8065f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(flg, 3);
8072c9581d2SBarry Smith   *flg = PETSC_FALSE;
8089566063dSJacob Faibussowitsch   PetscCall(PetscStrrstr(a, b, &test));
809a297a907SKarl Rupp   if (test && (test == a)) *flg = PETSC_TRUE;
8102c9581d2SBarry Smith   PetscFunctionReturn(0);
8112c9581d2SBarry Smith }
8122c9581d2SBarry Smith 
8137ba3a57cSBarry Smith /*@C
8147ba3a57cSBarry Smith    PetscStrendswithwhich - Determines if a string ends with one of several possible strings
8157ba3a57cSBarry Smith 
8167ba3a57cSBarry Smith    Not Collective
8177ba3a57cSBarry Smith 
8187ba3a57cSBarry Smith    Input Parameters:
8197ba3a57cSBarry Smith +  a - pointer to string
820fa4b66f2SVaclav Hapla -  bs - strings to end with (last entry must be NULL)
8217ba3a57cSBarry Smith 
8227ba3a57cSBarry Smith    Output Parameter:
823fa4b66f2SVaclav Hapla .  cnt - the index of the string it ends with or the index of NULL
8247ba3a57cSBarry Smith 
825*811af0c4SBarry Smith    Fortran Note:
82695452b02SPatrick Sanan     Not for use in Fortran
8277ba3a57cSBarry Smith 
8287ba3a57cSBarry Smith    Level: intermediate
8297ba3a57cSBarry Smith 
830*811af0c4SBarry Smith .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
831*811af0c4SBarry Smith           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()`
8327ba3a57cSBarry Smith @*/
8339371c9d4SSatish Balay PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt) {
8347ba3a57cSBarry Smith   PetscFunctionBegin;
8355f80ce2aSJacob Faibussowitsch   PetscValidPointer(bs, 2);
8365f80ce2aSJacob Faibussowitsch   PetscValidIntPointer(cnt, 3);
8377ba3a57cSBarry Smith   *cnt = 0;
8387ba3a57cSBarry Smith   while (bs[*cnt]) {
8395f80ce2aSJacob Faibussowitsch     PetscBool flg;
8405f80ce2aSJacob Faibussowitsch 
8419566063dSJacob Faibussowitsch     PetscCall(PetscStrendswith(a, bs[*cnt], &flg));
8427ba3a57cSBarry Smith     if (flg) PetscFunctionReturn(0);
8435f80ce2aSJacob Faibussowitsch     ++(*cnt);
8447ba3a57cSBarry Smith   }
8457ba3a57cSBarry Smith   PetscFunctionReturn(0);
8467ba3a57cSBarry Smith }
8477ba3a57cSBarry Smith 
8487ba3a57cSBarry Smith /*@C
849a5b23f4aSJose E. Roman    PetscStrrstr - Locates last occurrence of string in another string
8507ba3a57cSBarry Smith 
8517ba3a57cSBarry Smith    Not Collective
8527ba3a57cSBarry Smith 
8537ba3a57cSBarry Smith    Input Parameters:
8547ba3a57cSBarry Smith +  a - pointer to string
8557ba3a57cSBarry Smith -  b - string to find
8567ba3a57cSBarry Smith 
8577ba3a57cSBarry Smith    Output Parameter:
858a5b23f4aSJose E. Roman .  tmp - location of occurrence
8597ba3a57cSBarry Smith 
860*811af0c4SBarry Smith    Fortran Note:
86195452b02SPatrick Sanan     Not for use in Fortran
8627ba3a57cSBarry Smith 
8637ba3a57cSBarry Smith    Level: intermediate
8647ba3a57cSBarry Smith 
865*811af0c4SBarry Smith .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
866*811af0c4SBarry Smith           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()`
8677ba3a57cSBarry Smith @*/
8689371c9d4SSatish Balay PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[]) {
8695f80ce2aSJacob Faibussowitsch   const char *ltmp = NULL;
8707ba3a57cSBarry Smith 
8717ba3a57cSBarry Smith   PetscFunctionBegin;
8725f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
8735f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(b, 2);
8745f80ce2aSJacob Faibussowitsch   PetscValidPointer(tmp, 3);
8755f80ce2aSJacob Faibussowitsch   while (a) {
8765f80ce2aSJacob Faibussowitsch     a = (char *)strstr(a, b);
8775f80ce2aSJacob Faibussowitsch     if (a) ltmp = a++;
8787ba3a57cSBarry Smith   }
8797ba3a57cSBarry Smith   *tmp = (char *)ltmp;
8807ba3a57cSBarry Smith   PetscFunctionReturn(0);
8817ba3a57cSBarry Smith }
8827ba3a57cSBarry Smith 
8837ba3a57cSBarry Smith /*@C
884a5b23f4aSJose E. Roman    PetscStrstr - Locates first occurrence of string in another string
8857ba3a57cSBarry Smith 
8867ba3a57cSBarry Smith    Not Collective
8877ba3a57cSBarry Smith 
8887ba3a57cSBarry Smith    Input Parameters:
889160f4796SJed Brown +  haystack - string to search
890160f4796SJed Brown -  needle - string to find
8917ba3a57cSBarry Smith 
8927ba3a57cSBarry Smith    Output Parameter:
893a5b23f4aSJose E. Roman .  tmp - location of occurrence, is a NULL if the string is not found
8947ba3a57cSBarry Smith 
895*811af0c4SBarry Smith    Fortran Note:
89695452b02SPatrick Sanan     Not for use in Fortran
8977ba3a57cSBarry Smith 
8987ba3a57cSBarry Smith    Level: intermediate
8997ba3a57cSBarry Smith 
900*811af0c4SBarry Smith .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
901*811af0c4SBarry Smith           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()`
9027ba3a57cSBarry Smith @*/
9039371c9d4SSatish Balay PetscErrorCode PetscStrstr(const char haystack[], const char needle[], char *tmp[]) {
9047ba3a57cSBarry Smith   PetscFunctionBegin;
9055f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(haystack, 1);
9065f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(needle, 2);
9075f80ce2aSJacob Faibussowitsch   PetscValidPointer(tmp, 3);
908160f4796SJed Brown   *tmp = (char *)strstr(haystack, needle);
9097ba3a57cSBarry Smith   PetscFunctionReturn(0);
9107ba3a57cSBarry Smith }
9117ba3a57cSBarry Smith 
9129371c9d4SSatish Balay struct _p_PetscToken {
9139371c9d4SSatish Balay   char  token;
9149371c9d4SSatish Balay   char *array;
9159371c9d4SSatish Balay   char *current;
9169371c9d4SSatish Balay };
9171d1a0024SBarry Smith 
918e5c89e4eSSatish Balay /*@C
919e5c89e4eSSatish Balay    PetscTokenFind - Locates next "token" in a string
920e5c89e4eSSatish Balay 
921e5c89e4eSSatish Balay    Not Collective
922e5c89e4eSSatish Balay 
923e5c89e4eSSatish Balay    Input Parameters:
924e5c89e4eSSatish Balay .  a - pointer to token
925e5c89e4eSSatish Balay 
926e5c89e4eSSatish Balay    Output Parameter:
927a5b23f4aSJose E. Roman .  result - location of occurrence, NULL if not found
928e5c89e4eSSatish Balay 
929e5c89e4eSSatish Balay    Notes:
930e5c89e4eSSatish Balay      This version is different from the system version in that
931e5c89e4eSSatish Balay   it allows you to pass a read-only string into the function.
932e5c89e4eSSatish Balay 
9334704e885SBarry Smith      This version also treats all characters etc. inside a double quote "
9344704e885SBarry Smith    as a single token.
9354704e885SBarry Smith 
9363a9c465aSBarry 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
9373a9c465aSBarry Smith    second will return a null terminated y
9383a9c465aSBarry Smith 
9393a9c465aSBarry 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
9403a9c465aSBarry Smith 
941*811af0c4SBarry Smith    Fortran Note:
9426f013253SBarry Smith     Not for use in Fortran
9436f013253SBarry Smith 
944e5c89e4eSSatish Balay    Level: intermediate
945e5c89e4eSSatish Balay 
946db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenDestroy()`
947e5c89e4eSSatish Balay @*/
9489371c9d4SSatish Balay PetscErrorCode PetscTokenFind(PetscToken a, char *result[]) {
9495f80ce2aSJacob Faibussowitsch   char *ptr, token;
950e5c89e4eSSatish Balay 
951e5c89e4eSSatish Balay   PetscFunctionBegin;
9525f80ce2aSJacob Faibussowitsch   PetscValidPointer(a, 1);
9535f80ce2aSJacob Faibussowitsch   PetscValidPointer(result, 2);
9545f80ce2aSJacob Faibussowitsch   *result = ptr = a->current;
9559371c9d4SSatish Balay   if (ptr && !*ptr) {
9569371c9d4SSatish Balay     *result = NULL;
9579371c9d4SSatish Balay     PetscFunctionReturn(0);
9589371c9d4SSatish Balay   }
9594704e885SBarry Smith   token = a->token;
9609371c9d4SSatish Balay   if (ptr && (*ptr == '"')) {
9619371c9d4SSatish Balay     token = '"';
9629371c9d4SSatish Balay     (*result)++;
9639371c9d4SSatish Balay     ptr++;
9649371c9d4SSatish Balay   }
965e5c89e4eSSatish Balay   while (ptr) {
9664704e885SBarry Smith     if (*ptr == token) {
967e5c89e4eSSatish Balay       *ptr++ = 0;
968e5c89e4eSSatish Balay       while (*ptr == a->token) ptr++;
969e5c89e4eSSatish Balay       a->current = ptr;
970e5c89e4eSSatish Balay       break;
971e5c89e4eSSatish Balay     }
972e5c89e4eSSatish Balay     if (!*ptr) {
97302c9f0b5SLisandro Dalcin       a->current = NULL;
974e5c89e4eSSatish Balay       break;
975e5c89e4eSSatish Balay     }
976e5c89e4eSSatish Balay     ptr++;
977e5c89e4eSSatish Balay   }
978e5c89e4eSSatish Balay   PetscFunctionReturn(0);
979e5c89e4eSSatish Balay }
980e5c89e4eSSatish Balay 
981e5c89e4eSSatish Balay /*@C
982*811af0c4SBarry Smith    PetscTokenCreate - Creates a `PetscToken` used to find tokens in a string
983e5c89e4eSSatish Balay 
984e5c89e4eSSatish Balay    Not Collective
985e5c89e4eSSatish Balay 
986e5c89e4eSSatish Balay    Input Parameters:
987e5c89e4eSSatish Balay +  string - the string to look in
9883a9c465aSBarry Smith -  b - the separator character
989e5c89e4eSSatish Balay 
990e5c89e4eSSatish Balay    Output Parameter:
9913a9c465aSBarry Smith .  t- the token object
992e5c89e4eSSatish Balay 
993*811af0c4SBarry Smith    Note:
994e5c89e4eSSatish Balay      This version is different from the system version in that
995e5c89e4eSSatish Balay   it allows you to pass a read-only string into the function.
996e5c89e4eSSatish Balay 
997*811af0c4SBarry Smith    Fortran Note:
9986f013253SBarry Smith     Not for use in Fortran
9996f013253SBarry Smith 
1000e5c89e4eSSatish Balay    Level: intermediate
1001e5c89e4eSSatish Balay 
1002db781477SPatrick Sanan .seealso: `PetscTokenFind()`, `PetscTokenDestroy()`
1003e5c89e4eSSatish Balay @*/
10049371c9d4SSatish Balay PetscErrorCode PetscTokenCreate(const char a[], const char b, PetscToken *t) {
1005e5c89e4eSSatish Balay   PetscFunctionBegin;
10065f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
10075f80ce2aSJacob Faibussowitsch   PetscValidPointer(t, 3);
10089566063dSJacob Faibussowitsch   PetscCall(PetscNew(t));
10099566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(a, &(*t)->array));
1010a297a907SKarl Rupp 
1011e5c89e4eSSatish Balay   (*t)->current = (*t)->array;
1012e5c89e4eSSatish Balay   (*t)->token   = b;
1013e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1014e5c89e4eSSatish Balay }
1015e5c89e4eSSatish Balay 
1016e5c89e4eSSatish Balay /*@C
1017*811af0c4SBarry Smith    PetscTokenDestroy - Destroys a `PetscToken`
1018e5c89e4eSSatish Balay 
1019e5c89e4eSSatish Balay    Not Collective
1020e5c89e4eSSatish Balay 
1021e5c89e4eSSatish Balay    Input Parameters:
1022e5c89e4eSSatish Balay .  a - pointer to token
1023e5c89e4eSSatish Balay 
1024e5c89e4eSSatish Balay    Level: intermediate
1025e5c89e4eSSatish Balay 
1026*811af0c4SBarry Smith    Fortran Note:
102795452b02SPatrick Sanan     Not for use in Fortran
10286f013253SBarry Smith 
1029db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenFind()`
1030e5c89e4eSSatish Balay @*/
10319371c9d4SSatish Balay PetscErrorCode PetscTokenDestroy(PetscToken *a) {
1032e5c89e4eSSatish Balay   PetscFunctionBegin;
10338c74ee41SBarry Smith   if (!*a) PetscFunctionReturn(0);
10349566063dSJacob Faibussowitsch   PetscCall(PetscFree((*a)->array));
10359566063dSJacob Faibussowitsch   PetscCall(PetscFree(*a));
1036e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1037e5c89e4eSSatish Balay }
1038e5c89e4eSSatish Balay 
10398e81d068SLisandro Dalcin /*@C
1040*811af0c4SBarry Smith    PetscStrInList - search for string in character-delimited list
10418e81d068SLisandro Dalcin 
10428e81d068SLisandro Dalcin    Not Collective
10438e81d068SLisandro Dalcin 
10448e81d068SLisandro Dalcin    Input Parameters:
10458e81d068SLisandro Dalcin +  str - the string to look for
10468e81d068SLisandro Dalcin .  list - the list to search in
10478e81d068SLisandro Dalcin -  sep - the separator character
10488e81d068SLisandro Dalcin 
10498e81d068SLisandro Dalcin    Output Parameter:
10508e81d068SLisandro Dalcin .  found - whether str is in list
10518e81d068SLisandro Dalcin 
10528e81d068SLisandro Dalcin    Level: intermediate
10538e81d068SLisandro Dalcin 
1054*811af0c4SBarry Smith    Fortran Note:
105595452b02SPatrick Sanan     Not for use in Fortran
10568e81d068SLisandro Dalcin 
1057db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()`
10588e81d068SLisandro Dalcin @*/
10599371c9d4SSatish Balay PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found) {
10608e81d068SLisandro Dalcin   PetscToken token;
10618e81d068SLisandro Dalcin   char      *item;
10628e81d068SLisandro Dalcin 
10638e81d068SLisandro Dalcin   PetscFunctionBegin;
10645f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(found, 4);
10658e81d068SLisandro Dalcin   *found = PETSC_FALSE;
10669566063dSJacob Faibussowitsch   PetscCall(PetscTokenCreate(list, sep, &token));
10679566063dSJacob Faibussowitsch   PetscCall(PetscTokenFind(token, &item));
10688e81d068SLisandro Dalcin   while (item) {
10699566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(str, item, found));
10708e81d068SLisandro Dalcin     if (*found) break;
10719566063dSJacob Faibussowitsch     PetscCall(PetscTokenFind(token, &item));
10728e81d068SLisandro Dalcin   }
10739566063dSJacob Faibussowitsch   PetscCall(PetscTokenDestroy(&token));
10748e81d068SLisandro Dalcin   PetscFunctionReturn(0);
10758e81d068SLisandro Dalcin }
1076e5c89e4eSSatish Balay 
1077e5c89e4eSSatish Balay /*@C
1078e5c89e4eSSatish Balay    PetscGetPetscDir - Gets the directory PETSc is installed in
1079e5c89e4eSSatish Balay 
1080e5c89e4eSSatish Balay    Not Collective
1081e5c89e4eSSatish Balay 
1082e5c89e4eSSatish Balay    Output Parameter:
1083e5c89e4eSSatish Balay .  dir - the directory
1084e5c89e4eSSatish Balay 
1085e5c89e4eSSatish Balay    Level: developer
1086e5c89e4eSSatish Balay 
1087*811af0c4SBarry Smith    Fortran Note:
108895452b02SPatrick Sanan     Not for use in Fortran
10896f013253SBarry Smith 
1090e5c89e4eSSatish Balay @*/
10919371c9d4SSatish Balay PetscErrorCode PetscGetPetscDir(const char *dir[]) {
1092e5c89e4eSSatish Balay   PetscFunctionBegin;
10935f80ce2aSJacob Faibussowitsch   PetscValidPointer(dir, 1);
1094e5c89e4eSSatish Balay   *dir = PETSC_DIR;
1095e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1096e5c89e4eSSatish Balay }
1097e5c89e4eSSatish Balay 
1098e5c89e4eSSatish Balay /*@C
1099e5c89e4eSSatish Balay    PetscStrreplace - Replaces substrings in string with other substrings
1100e5c89e4eSSatish Balay 
1101e5c89e4eSSatish Balay    Not Collective
1102e5c89e4eSSatish Balay 
1103e5c89e4eSSatish Balay    Input Parameters:
1104*811af0c4SBarry Smith +   comm - `MPI_Comm` of processors that are processing the string
110571573d7dSBarry Smith .   aa - the string to look in
1106d8ccf1fbSBarry Smith .   b - the resulting copy of a with replaced strings (b can be the same as a)
1107e5c89e4eSSatish Balay -   len - the length of b
1108e5c89e4eSSatish Balay 
1109e5c89e4eSSatish Balay    Notes:
1110e5c89e4eSSatish Balay       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
1111d5649816SBarry Smith       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values
1112e5c89e4eSSatish Balay       as well as any environmental variables.
1113e5c89e4eSSatish Balay 
1114*811af0c4SBarry Smith       `PETSC_LIB_DIR` uses the environmental variable if it exists. `PETSC_ARCH` and `PETSC_DIR` use what
1115acc6cc86SBarry Smith       PETSc was built with and do not use environmental variables.
1116acc6cc86SBarry Smith 
1117*811af0c4SBarry Smith    Fortran Note:
11186f013253SBarry Smith       Not for use in Fortran
11196f013253SBarry Smith 
1120*811af0c4SBarry Smith    Level: developer
1121e5c89e4eSSatish Balay 
1122e5c89e4eSSatish Balay @*/
11239371c9d4SSatish Balay PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len) {
1124e5c89e4eSSatish Balay   int           i = 0;
1125e5c89e4eSSatish Balay   size_t        l, l1, l2, l3;
112671573d7dSBarry Smith   char         *work, *par, *epar, env[1024], *tfree, *a = (char *)aa;
112702c9f0b5SLisandro Dalcin   const char   *s[] = {"${PETSC_ARCH}", "${PETSC_DIR}", "${PETSC_LIB_DIR}", "${DISPLAY}", "${HOMEDIRECTORY}", "${WORKINGDIRECTORY}", "${USERNAME}", "${HOSTNAME}", NULL};
112802c9f0b5SLisandro Dalcin   char         *r[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
1129ace3abfcSBarry Smith   PetscBool     flag;
1130589a23caSBarry Smith   static size_t DISPLAY_LENGTH = 265, USER_LENGTH = 256, HOST_LENGTH = 256;
1131e5c89e4eSSatish Balay 
1132e5c89e4eSSatish Balay   PetscFunctionBegin;
11335f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(aa, 2);
11345f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(b, 3);
11359566063dSJacob Faibussowitsch   if (aa == b) PetscCall(PetscStrallocpy(aa, (char **)&a));
11369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(len, &work));
1137e5c89e4eSSatish Balay 
1138e5c89e4eSSatish Balay   /* get values for replaced variables */
11399566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_ARCH, &r[0]));
11409566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_DIR, &r[1]));
11419566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_LIB_DIR, &r[2]));
11429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(DISPLAY_LENGTH, &r[3]));
11439566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[4]));
11449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[5]));
11459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(USER_LENGTH, &r[6]));
11469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(HOST_LENGTH, &r[7]));
11479566063dSJacob Faibussowitsch   PetscCall(PetscGetDisplay(r[3], DISPLAY_LENGTH));
11489566063dSJacob Faibussowitsch   PetscCall(PetscGetHomeDirectory(r[4], PETSC_MAX_PATH_LEN));
11499566063dSJacob Faibussowitsch   PetscCall(PetscGetWorkingDirectory(r[5], PETSC_MAX_PATH_LEN));
11509566063dSJacob Faibussowitsch   PetscCall(PetscGetUserName(r[6], USER_LENGTH));
11519566063dSJacob Faibussowitsch   PetscCall(PetscGetHostName(r[7], HOST_LENGTH));
1152487e5849SBarry Smith 
1153487e5849SBarry Smith   /* replace that are in environment */
11549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetenv(comm, "PETSC_LIB_DIR", env, sizeof(env), &flag));
1155487e5849SBarry Smith   if (flag) {
11569566063dSJacob Faibussowitsch     PetscCall(PetscFree(r[2]));
11579566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(env, &r[2]));
1158487e5849SBarry Smith   }
1159e5c89e4eSSatish Balay 
1160e5c89e4eSSatish Balay   /* replace the requested strings */
11619566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(b, a, len));
1162e5c89e4eSSatish Balay   while (s[i]) {
11639566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(s[i], &l));
11649566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(b, s[i], &par));
1165e5c89e4eSSatish Balay     while (par) {
1166e5c89e4eSSatish Balay       *par = 0;
1167e5c89e4eSSatish Balay       par += l;
1168e5c89e4eSSatish Balay 
11699566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(b, &l1));
11709566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(r[i], &l2));
11719566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(par, &l3));
1172cc73adaaSBarry Smith       PetscCheck(l1 + l2 + l3 < len, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "b len is not long enough to hold new values");
11739566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(work, b, len));
11749566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(work, r[i], len));
11759566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(work, par, len));
11769566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(b, work, len));
11779566063dSJacob Faibussowitsch       PetscCall(PetscStrstr(b, s[i], &par));
1178e5c89e4eSSatish Balay     }
1179e5c89e4eSSatish Balay     i++;
1180e5c89e4eSSatish Balay   }
1181487e5849SBarry Smith   i = 0;
1182487e5849SBarry Smith   while (r[i]) {
1183e5c89e4eSSatish Balay     tfree = (char *)r[i];
11849566063dSJacob Faibussowitsch     PetscCall(PetscFree(tfree));
1185487e5849SBarry Smith     i++;
1186e5c89e4eSSatish Balay   }
1187e5c89e4eSSatish Balay 
1188e5c89e4eSSatish Balay   /* look for any other ${xxx} strings to replace from environmental variables */
11899566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(b, "${", &par));
1190e5c89e4eSSatish Balay   while (par) {
1191e5c89e4eSSatish Balay     *par = 0;
1192e5c89e4eSSatish Balay     par += 2;
11939566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(work, b, len));
11949566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(par, "}", &epar));
1195e5c89e4eSSatish Balay     *epar = 0;
1196e5c89e4eSSatish Balay     epar += 1;
11979566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetenv(comm, par, env, sizeof(env), &flag));
119828b400f6SJacob Faibussowitsch     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Substitution string ${%s} not found as environmental variable", par);
11999566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(work, env, len));
12009566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(work, epar, len));
12019566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(b, work, len));
12029566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(b, "${", &par));
1203e5c89e4eSSatish Balay   }
12049566063dSJacob Faibussowitsch   PetscCall(PetscFree(work));
12059566063dSJacob Faibussowitsch   if (aa == b) PetscCall(PetscFree(a));
1206e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1207e5c89e4eSSatish Balay }
1208e5c89e4eSSatish Balay 
1209a53986e1SJed Brown /*@C
1210a53986e1SJed Brown    PetscEListFind - searches list of strings for given string, using case insensitive matching
1211e5c89e4eSSatish Balay 
1212a53986e1SJed Brown    Not Collective
1213a53986e1SJed Brown 
1214a53986e1SJed Brown    Input Parameters:
1215a53986e1SJed Brown +  n - number of strings in
1216a53986e1SJed Brown .  list - list of strings to search
1217a53986e1SJed Brown -  str - string to look for, empty string "" accepts default (first entry in list)
1218a53986e1SJed Brown 
1219a53986e1SJed Brown    Output Parameters:
1220a53986e1SJed Brown +  value - index of matching string (if found)
1221a53986e1SJed Brown -  found - boolean indicating whether string was found (can be NULL)
1222a53986e1SJed Brown 
1223*811af0c4SBarry Smith    Fortran Note:
1224a53986e1SJed Brown    Not for use in Fortran
1225a53986e1SJed Brown 
1226a53986e1SJed Brown    Level: advanced
1227*811af0c4SBarry Smith 
1228*811af0c4SBarry Smith .seealso: `PetscEnumFind()`
1229a53986e1SJed Brown @*/
12309371c9d4SSatish Balay PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found) {
1231a53986e1SJed Brown   PetscFunctionBegin;
12325f80ce2aSJacob Faibussowitsch   if (found) {
12335f80ce2aSJacob Faibussowitsch     PetscValidBoolPointer(found, 5);
12345f80ce2aSJacob Faibussowitsch     *found = PETSC_FALSE;
12355f80ce2aSJacob Faibussowitsch   }
12365f80ce2aSJacob Faibussowitsch   for (PetscInt i = 0; i < n; ++i) {
12375f80ce2aSJacob Faibussowitsch     PetscBool matched;
12385f80ce2aSJacob Faibussowitsch 
12399566063dSJacob Faibussowitsch     PetscCall(PetscStrcasecmp(str, list[i], &matched));
1240a53986e1SJed Brown     if (matched || !str[0]) {
1241a53986e1SJed Brown       if (found) *found = PETSC_TRUE;
1242a53986e1SJed Brown       *value = i;
1243a53986e1SJed Brown       break;
1244a53986e1SJed Brown     }
1245a53986e1SJed Brown   }
1246a53986e1SJed Brown   PetscFunctionReturn(0);
1247a53986e1SJed Brown }
1248a53986e1SJed Brown 
1249a53986e1SJed Brown /*@C
12508e81d068SLisandro Dalcin    PetscEnumFind - searches enum list of strings for given string, using case insensitive matching
1251a53986e1SJed Brown 
1252a53986e1SJed Brown    Not Collective
1253a53986e1SJed Brown 
1254a53986e1SJed Brown    Input Parameters:
1255a53986e1SJed Brown +  enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL
1256a53986e1SJed Brown -  str - string to look for
1257a53986e1SJed Brown 
1258a53986e1SJed Brown    Output Parameters:
1259a53986e1SJed Brown +  value - index of matching string (if found)
1260a53986e1SJed Brown -  found - boolean indicating whether string was found (can be NULL)
1261a53986e1SJed Brown 
1262*811af0c4SBarry Smith    Fortran Note:
1263a53986e1SJed Brown    Not for use in Fortran
1264a53986e1SJed Brown 
1265a53986e1SJed Brown    Level: advanced
1266*811af0c4SBarry Smith 
1267*811af0c4SBarry Smith .seealso: `PetscEListFind()`
1268a53986e1SJed Brown @*/
12699371c9d4SSatish Balay PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found) {
1270d05ba7d2SLisandro Dalcin   PetscInt  n = 0, evalue;
1271a53986e1SJed Brown   PetscBool efound;
1272a53986e1SJed Brown 
1273a53986e1SJed Brown   PetscFunctionBegin;
12745f80ce2aSJacob Faibussowitsch   PetscValidPointer(enumlist, 1);
12755f80ce2aSJacob 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");
12765f80ce2aSJacob Faibussowitsch   PetscCheck(n >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
1277a53986e1SJed Brown   n -= 3; /* drop enum name, prefix, and null termination */
12789566063dSJacob Faibussowitsch   PetscCall(PetscEListFind(n, enumlist, str, &evalue, &efound));
12795f80ce2aSJacob Faibussowitsch   if (efound) {
12805f80ce2aSJacob Faibussowitsch     PetscValidPointer(value, 3);
12815f80ce2aSJacob Faibussowitsch     *value = (PetscEnum)evalue;
12825f80ce2aSJacob Faibussowitsch   }
12835f80ce2aSJacob Faibussowitsch   if (found) {
12845f80ce2aSJacob Faibussowitsch     PetscValidBoolPointer(found, 4);
12855f80ce2aSJacob Faibussowitsch     *found = efound;
12865f80ce2aSJacob Faibussowitsch   }
1287a53986e1SJed Brown   PetscFunctionReturn(0);
1288a53986e1SJed Brown }
1289660278c0SBarry Smith 
1290660278c0SBarry Smith /*@C
1291660278c0SBarry Smith   PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled.
1292660278c0SBarry Smith 
1293660278c0SBarry Smith   Not collective
1294660278c0SBarry Smith 
1295660278c0SBarry Smith   Input Parameter:
1296660278c0SBarry Smith . file - the file name
1297660278c0SBarry Smith 
1298660278c0SBarry Smith   Note:
1299660278c0SBarry Smith   PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems
1300660278c0SBarry Smith   so that comparisons of output between runs are easy to make.
1301660278c0SBarry Smith 
1302660278c0SBarry Smith   This mode is used for all tests in the test harness, it applies to both debug and optimized builds.
1303660278c0SBarry Smith 
1304660278c0SBarry Smith   Use the option -petsc_ci to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for
1305660278c0SBarry Smith   all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness.
1306660278c0SBarry Smith 
1307660278c0SBarry Smith   Always uses the Unix / as the file separate even on Microsoft Windows systems
1308660278c0SBarry Smith 
1309660278c0SBarry Smith   The option -petsc_ci_portable_error_output attempts to output the same error messages on all systems for the test harness.
1310660278c0SBarry Smith   In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc
1311660278c0SBarry 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
1312660278c0SBarry Smith   harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test
1313660278c0SBarry Smith   harness in the args: argument for specific examples. It will not neccessarily produce portable output if different errors
1314660278c0SBarry Smith   (or no errors) occur on a subset of the MPI ranks.
1315660278c0SBarry Smith 
1316660278c0SBarry Smith   Level: developer
1317660278c0SBarry Smith 
1318660278c0SBarry Smith .seealso: `PetscCILinenumber()`
1319660278c0SBarry Smith @*/
13209371c9d4SSatish Balay const char *PetscCIFilename(const char *file) {
1321660278c0SBarry Smith   if (!PetscCIEnabledPortableErrorOutput) return file;
1322660278c0SBarry Smith   return PetscBasename(file);
1323660278c0SBarry Smith }
1324660278c0SBarry Smith 
1325660278c0SBarry Smith /*@C
1326*811af0c4SBarry Smith   PetscCILinenumber - returns a line number except if `PetscCIEnablePortableErrorOutput` is set when it returns 0
1327660278c0SBarry Smith 
1328660278c0SBarry Smith   Not collective
1329660278c0SBarry Smith 
1330660278c0SBarry Smith   Input Parameter:
1331660278c0SBarry Smith . linenumber - the initial line number
1332660278c0SBarry Smith 
1333660278c0SBarry Smith   Note:
1334660278c0SBarry Smith   See `PetscCIFilename()` for details on usage
1335660278c0SBarry Smith 
1336660278c0SBarry Smith   Level: developer
1337660278c0SBarry Smith 
1338660278c0SBarry Smith .seealso: `PetscCIFilename()`
1339660278c0SBarry Smith @*/
13409371c9d4SSatish Balay int PetscCILinenumber(int linenumber) {
1341660278c0SBarry Smith   if (!PetscCIEnabledPortableErrorOutput) return linenumber;
1342660278c0SBarry Smith   return 0;
1343660278c0SBarry Smith }
1344