xref: /petsc/src/sys/utils/str.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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 
2795452b02SPatrick Sanan    Notes:
2895452b02SPatrick Sanan     this may be called before PetscInitialize() or after PetscFinalize()
293c311c98SBarry Smith 
306f013253SBarry Smith    Not for use in Fortran
316f013253SBarry Smith 
3295452b02SPatrick Sanan    Developer Notes:
3395452b02SPatrick Sanan     Using raw malloc() and does not call error handlers since this may be used before PETSc is initialized. Used
34b4cd4cebSBarry Smith      to generate argc, args arguments passed to MPI_Init()
35301d30feSBarry Smith 
36db781477SPatrick Sanan .seealso: `PetscStrToArrayDestroy()`, `PetscToken`, `PetscTokenCreate()`
373c311c98SBarry Smith 
383c311c98SBarry Smith @*/
39*9371c9d4SSatish Balay PetscErrorCode PetscStrToArray(const char s[], char sp, int *argc, char ***args) {
40c3bcdc7eSBarry Smith   int       i, j, n, *lens, cnt = 0;
41ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
423c311c98SBarry Smith 
4340a7e1efSBarry Smith   if (!s) n = 0;
4440a7e1efSBarry Smith   else n = strlen(s);
453c311c98SBarry Smith   *argc = 0;
4661528463SBarry Smith   *args = NULL;
47acf7dc08SSatish Balay   for (; n > 0; n--) { /* remove separator chars at the end - and will empty the string if all chars are separator chars */
48acf7dc08SSatish Balay     if (s[n - 1] != sp) break;
49acf7dc08SSatish Balay   }
505f80ce2aSJacob Faibussowitsch   if (!n) return 0;
513c311c98SBarry Smith   for (i = 0; i < n; i++) {
52d67fe73bSBarry Smith     if (s[i] != sp) break;
533c311c98SBarry Smith   }
543c311c98SBarry Smith   for (; i < n + 1; i++) {
55*9371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
56*9371c9d4SSatish Balay       flg = PETSC_TRUE;
57*9371c9d4SSatish Balay       (*argc)++;
58*9371c9d4SSatish Balay     } else if (s[i] != sp) {
59*9371c9d4SSatish Balay       flg = PETSC_FALSE;
603c311c98SBarry Smith     }
61*9371c9d4SSatish Balay   }
62*9371c9d4SSatish Balay   (*args) = (char **)malloc(((*argc) + 1) * sizeof(char *));
63*9371c9d4SSatish Balay   if (!*args) return PETSC_ERR_MEM;
64*9371c9d4SSatish Balay   lens = (int *)malloc((*argc) * sizeof(int));
65*9371c9d4SSatish Balay   if (!lens) return PETSC_ERR_MEM;
663c311c98SBarry Smith   for (i = 0; i < *argc; i++) lens[i] = 0;
673c311c98SBarry Smith 
683c311c98SBarry Smith   *argc = 0;
693c311c98SBarry Smith   for (i = 0; i < n; i++) {
70d67fe73bSBarry Smith     if (s[i] != sp) break;
713c311c98SBarry Smith   }
727dd9f305SSatish Balay   for (; i < n + 1; i++) {
73*9371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
74*9371c9d4SSatish Balay       flg = PETSC_TRUE;
75*9371c9d4SSatish Balay       (*argc)++;
76*9371c9d4SSatish Balay     } else if (s[i] != sp) {
77*9371c9d4SSatish Balay       lens[*argc]++;
78*9371c9d4SSatish Balay       flg = PETSC_FALSE;
79*9371c9d4SSatish Balay     }
803c311c98SBarry Smith   }
813c311c98SBarry Smith 
823c311c98SBarry Smith   for (i = 0; i < *argc; i++) {
83c3bcdc7eSBarry Smith     (*args)[i] = (char *)malloc((lens[i] + 1) * sizeof(char));
84c3bcdc7eSBarry Smith     if (!(*args)[i]) {
85c3bcdc7eSBarry Smith       free(lens);
86c3bcdc7eSBarry Smith       for (j = 0; j < i; j++) free((*args)[j]);
87c3bcdc7eSBarry Smith       free(*args);
88c3bcdc7eSBarry Smith       return PETSC_ERR_MEM;
89c3bcdc7eSBarry Smith     }
903c311c98SBarry Smith   }
91a2ea699eSBarry Smith   free(lens);
9202c9f0b5SLisandro Dalcin   (*args)[*argc] = NULL;
933c311c98SBarry Smith 
943c311c98SBarry Smith   *argc = 0;
953c311c98SBarry Smith   for (i = 0; i < n; i++) {
96d67fe73bSBarry Smith     if (s[i] != sp) break;
973c311c98SBarry Smith   }
983c311c98SBarry Smith   for (; i < n + 1; i++) {
99*9371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
100*9371c9d4SSatish Balay       flg                   = PETSC_TRUE;
101*9371c9d4SSatish Balay       (*args)[*argc][cnt++] = 0;
102*9371c9d4SSatish Balay       (*argc)++;
103*9371c9d4SSatish Balay       cnt = 0;
104*9371c9d4SSatish Balay     } else if (s[i] != sp && s[i] != 0) {
105*9371c9d4SSatish Balay       (*args)[*argc][cnt++] = s[i];
106*9371c9d4SSatish Balay       flg                   = PETSC_FALSE;
107*9371c9d4SSatish Balay     }
1083c311c98SBarry Smith   }
1093c311c98SBarry Smith   return 0;
1103c311c98SBarry Smith }
1113c311c98SBarry Smith 
112301d30feSBarry Smith /*@C
113301d30feSBarry Smith    PetscStrToArrayDestroy - Frees array created with PetscStrToArray().
114301d30feSBarry Smith 
115301d30feSBarry Smith    Not Collective
116301d30feSBarry Smith 
117301d30feSBarry Smith    Output Parameters:
118301d30feSBarry Smith +  argc - the number of arguments
119301d30feSBarry Smith -  args - the array of arguments
120301d30feSBarry Smith 
121301d30feSBarry Smith    Level: intermediate
122301d30feSBarry Smith 
12395452b02SPatrick Sanan    Notes:
12495452b02SPatrick Sanan     This may be called before PetscInitialize() or after PetscFinalize()
125301d30feSBarry Smith 
1266f013253SBarry Smith    Not for use in Fortran
1276f013253SBarry Smith 
128db781477SPatrick Sanan .seealso: `PetscStrToArray()`
129301d30feSBarry Smith 
130301d30feSBarry Smith @*/
131*9371c9d4SSatish Balay PetscErrorCode PetscStrToArrayDestroy(int argc, char **args) {
1325f80ce2aSJacob Faibussowitsch   for (int i = 0; i < argc; ++i) free(args[i]);
133a297a907SKarl Rupp   if (args) free(args);
134301d30feSBarry Smith   return 0;
135301d30feSBarry Smith }
136301d30feSBarry Smith 
137e5c89e4eSSatish Balay /*@C
138e5c89e4eSSatish Balay    PetscStrlen - Gets length of a string
139e5c89e4eSSatish Balay 
140e5c89e4eSSatish Balay    Not Collective
141e5c89e4eSSatish Balay 
142e5c89e4eSSatish Balay    Input Parameters:
143e5c89e4eSSatish Balay .  s - pointer to string
144e5c89e4eSSatish Balay 
145e5c89e4eSSatish Balay    Output Parameter:
146e5c89e4eSSatish Balay .  len - length in bytes
147e5c89e4eSSatish Balay 
148e5c89e4eSSatish Balay    Level: intermediate
149e5c89e4eSSatish Balay 
150e5c89e4eSSatish Balay    Note:
151e5c89e4eSSatish Balay    This routine is analogous to strlen().
152e5c89e4eSSatish Balay 
153e5c89e4eSSatish Balay    Null string returns a length of zero
154e5c89e4eSSatish Balay 
1556f013253SBarry Smith    Not for use in Fortran
1566f013253SBarry Smith 
157e5c89e4eSSatish Balay @*/
158*9371c9d4SSatish Balay PetscErrorCode PetscStrlen(const char s[], size_t *len) {
159e5c89e4eSSatish Balay   PetscFunctionBegin;
1605f80ce2aSJacob Faibussowitsch   *len = s ? strlen(s) : 0;
161e5c89e4eSSatish Balay   PetscFunctionReturn(0);
162e5c89e4eSSatish Balay }
163e5c89e4eSSatish Balay 
164e5c89e4eSSatish Balay /*@C
165e5c89e4eSSatish Balay    PetscStrallocpy - Allocates space to hold a copy of a string then copies the string
166e5c89e4eSSatish Balay 
167e5c89e4eSSatish Balay    Not Collective
168e5c89e4eSSatish Balay 
169e5c89e4eSSatish Balay    Input Parameters:
170e5c89e4eSSatish Balay .  s - pointer to string
171e5c89e4eSSatish Balay 
172e5c89e4eSSatish Balay    Output Parameter:
173e5c89e4eSSatish Balay .  t - the copied string
174e5c89e4eSSatish Balay 
175e5c89e4eSSatish Balay    Level: intermediate
176e5c89e4eSSatish Balay 
177e5c89e4eSSatish Balay    Note:
178e5c89e4eSSatish Balay       Null string returns a new null string
179e5c89e4eSSatish Balay 
1806f013253SBarry Smith       Not for use in Fortran
1816f013253SBarry Smith 
1820ecf5a55SBarry Smith       Warning: If t has previously been allocated then that memory is lost, you may need to PetscFree()
1830ecf5a55SBarry Smith       the array before calling this routine.
1840ecf5a55SBarry Smith 
185db781477SPatrick Sanan .seealso: `PetscStrArrayallocpy()`, `PetscStrcpy()`, `PetscStrNArrayallocpy()`
1860ecf5a55SBarry Smith 
187e5c89e4eSSatish Balay @*/
188*9371c9d4SSatish Balay PetscErrorCode PetscStrallocpy(const char s[], char *t[]) {
18902c9f0b5SLisandro Dalcin   char *tmp = NULL;
190e5c89e4eSSatish Balay 
191e5c89e4eSSatish Balay   PetscFunctionBegin;
192e5c89e4eSSatish Balay   if (s) {
1935f80ce2aSJacob Faibussowitsch     size_t len;
1945f80ce2aSJacob Faibussowitsch 
1959566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(s, &len));
1969566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(1 + len, &tmp));
1979566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(tmp, s));
198e5c89e4eSSatish Balay   }
19971573d7dSBarry Smith   *t = tmp;
200e5c89e4eSSatish Balay   PetscFunctionReturn(0);
201e5c89e4eSSatish Balay }
202e5c89e4eSSatish Balay 
20347340559SBarry Smith /*@C
20447340559SBarry Smith    PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
20547340559SBarry Smith 
20647340559SBarry Smith    Not Collective
20747340559SBarry Smith 
20847340559SBarry Smith    Input Parameters:
20947340559SBarry Smith .  s - pointer to array of strings (final string is a null)
21047340559SBarry Smith 
21147340559SBarry Smith    Output Parameter:
21247340559SBarry Smith .  t - the copied array string
21347340559SBarry Smith 
21447340559SBarry Smith    Level: intermediate
21547340559SBarry Smith 
21647340559SBarry Smith    Note:
21747340559SBarry Smith       Not for use in Fortran
21847340559SBarry Smith 
2190ecf5a55SBarry Smith       Warning: If t has previously been allocated then that memory is lost, you may need to PetscStrArrayDestroy()
2200ecf5a55SBarry Smith       the array before calling this routine.
2210ecf5a55SBarry Smith 
222db781477SPatrick Sanan .seealso: `PetscStrallocpy()`, `PetscStrArrayDestroy()`, `PetscStrNArrayallocpy()`
22347340559SBarry Smith 
22447340559SBarry Smith @*/
225*9371c9d4SSatish Balay PetscErrorCode PetscStrArrayallocpy(const char *const *list, char ***t) {
2265f80ce2aSJacob Faibussowitsch   PetscInt n = 0;
22747340559SBarry Smith 
22847340559SBarry Smith   PetscFunctionBegin;
229*9371c9d4SSatish Balay   while (list[n++])
230*9371c9d4SSatish Balay     ;
2319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n + 1, t));
2329566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
2330298fd71SBarry Smith   (*t)[n] = NULL;
23447340559SBarry Smith   PetscFunctionReturn(0);
23547340559SBarry Smith }
23647340559SBarry Smith 
23747340559SBarry Smith /*@C
23847340559SBarry Smith    PetscStrArrayDestroy - Frees array of strings created with PetscStrArrayallocpy().
23947340559SBarry Smith 
24047340559SBarry Smith    Not Collective
24147340559SBarry Smith 
24247340559SBarry Smith    Output Parameters:
24347340559SBarry Smith .   list - array of strings
24447340559SBarry Smith 
24547340559SBarry Smith    Level: intermediate
24647340559SBarry Smith 
24795452b02SPatrick Sanan    Notes:
24895452b02SPatrick Sanan     Not for use in Fortran
24947340559SBarry Smith 
250db781477SPatrick Sanan .seealso: `PetscStrArrayallocpy()`
25147340559SBarry Smith 
25247340559SBarry Smith @*/
253*9371c9d4SSatish Balay PetscErrorCode PetscStrArrayDestroy(char ***list) {
25447340559SBarry Smith   PetscInt n = 0;
25547340559SBarry Smith 
2566fed8037SJed Brown   PetscFunctionBegin;
2576fed8037SJed Brown   if (!*list) PetscFunctionReturn(0);
2586fed8037SJed Brown   while ((*list)[n]) {
2599566063dSJacob Faibussowitsch     PetscCall(PetscFree((*list)[n]));
2605f80ce2aSJacob Faibussowitsch     ++n;
26147340559SBarry Smith   }
2629566063dSJacob Faibussowitsch   PetscCall(PetscFree(*list));
2636fed8037SJed Brown   PetscFunctionReturn(0);
26447340559SBarry Smith }
26547340559SBarry Smith 
2666991f827SBarry Smith /*@C
2676991f827SBarry Smith    PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
2686991f827SBarry Smith 
2696991f827SBarry Smith    Not Collective
2706991f827SBarry Smith 
2716991f827SBarry Smith    Input Parameters:
2726991f827SBarry Smith +  n - the number of string entries
2736991f827SBarry Smith -  s - pointer to array of strings
2746991f827SBarry Smith 
2756991f827SBarry Smith    Output Parameter:
2766991f827SBarry Smith .  t - the copied array string
2776991f827SBarry Smith 
2786991f827SBarry Smith    Level: intermediate
2796991f827SBarry Smith 
2806991f827SBarry Smith    Note:
2816991f827SBarry Smith       Not for use in Fortran
2826991f827SBarry Smith 
283db781477SPatrick Sanan .seealso: `PetscStrallocpy()`, `PetscStrArrayallocpy()`, `PetscStrNArrayDestroy()`
2846991f827SBarry Smith 
2856991f827SBarry Smith @*/
286*9371c9d4SSatish Balay PetscErrorCode PetscStrNArrayallocpy(PetscInt n, const char *const *list, char ***t) {
2876991f827SBarry Smith   PetscFunctionBegin;
2889566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, t));
2899566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
2906991f827SBarry Smith   PetscFunctionReturn(0);
2916991f827SBarry Smith }
2926991f827SBarry Smith 
2936991f827SBarry Smith /*@C
2946991f827SBarry Smith    PetscStrNArrayDestroy - Frees array of strings created with PetscStrArrayallocpy().
2956991f827SBarry Smith 
2966991f827SBarry Smith    Not Collective
2976991f827SBarry Smith 
2986991f827SBarry Smith    Output Parameters:
2996991f827SBarry Smith +   n - number of string entries
3006991f827SBarry Smith -   list - array of strings
3016991f827SBarry Smith 
3026991f827SBarry Smith    Level: intermediate
3036991f827SBarry Smith 
30495452b02SPatrick Sanan    Notes:
30595452b02SPatrick Sanan     Not for use in Fortran
3066991f827SBarry Smith 
307db781477SPatrick Sanan .seealso: `PetscStrArrayallocpy()`
3086991f827SBarry Smith 
3096991f827SBarry Smith @*/
310*9371c9d4SSatish 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 
3346f013253SBarry Smith      Not for use in Fortran
3356f013253SBarry Smith 
3360ecf5a55SBarry Smith      It is recommended you use PetscStrncpy() instead of this routine
3370ecf5a55SBarry Smith 
338db781477SPatrick Sanan .seealso: `PetscStrncpy()`, `PetscStrcat()`, `PetscStrlcat()`
339e5c89e4eSSatish Balay 
340e5c89e4eSSatish Balay @*/
341acc6cc86SBarry Smith 
342*9371c9d4SSatish 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
3711b6ef838SBarry Smith      strncpy() which leaves s non-terminated if there is not room for the entire string.
372ff32304bSBarry Smith 
37362a5de14SBarry Smith   Developers Note: Should this be PetscStrlcpy() to reflect its behavior which is like strlcpy() not strncpy()
37462a5de14SBarry Smith 
375db781477SPatrick Sanan .seealso: `PetscStrcpy()`, `PetscStrcat()`, `PetscStrlcat()`
376e5c89e4eSSatish Balay 
377e5c89e4eSSatish Balay @*/
378*9371c9d4SSatish 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 
40495452b02SPatrick Sanan    Notes:
40595452b02SPatrick Sanan     Not for use in Fortran
4066f013253SBarry Smith 
4070ecf5a55SBarry Smith     It is recommended you use PetscStrlcat() instead of this routine
4080ecf5a55SBarry Smith 
409db781477SPatrick Sanan .seealso: `PetscStrcpy()`, `PetscStrncpy()`, `PetscStrlcat()`
410e5c89e4eSSatish Balay 
411e5c89e4eSSatish Balay @*/
412*9371c9d4SSatish 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 
43324a58d73SPatrick Sanan   Notes:
43424a58d73SPatrick Sanan   Not for use in Fortran
4356f013253SBarry Smith 
43624a58d73SPatrick Sanan   Unlike the system call strncat(), the length passed in is the length of the
43724a58d73SPatrick Sanan   original allocated space, not the length of the left-over space. This is
43824a58d73SPatrick Sanan   similar to the BSD system call strlcat().
439153a8027SBarry Smith 
440db781477SPatrick Sanan .seealso: `PetscStrcpy()`, `PetscStrncpy()`, `PetscStrcat()`
441e5c89e4eSSatish Balay 
442e5c89e4eSSatish Balay @*/
443*9371c9d4SSatish 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 
457*9371c9d4SSatish 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
464660278c0SBarry Smith    PetscBasename - returns a pointer to the last entry of a / or \ seperated 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 
47380b92c66SBarry Smith    Notes:
47480b92c66SBarry Smith     Not for use in Fortran
47580b92c66SBarry Smith 
476660278c0SBarry Smith     Works for both Unix and Windows path separators
477660278c0SBarry Smith 
47880b92c66SBarry Smith .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`, `PetscStrrchr()`,`PetscStrcmp()`,`PetscStrstr()`,
47980b92c66SBarry Smith           `PetscTokenCreate()`, `PetscStrToArray()`, `PetscStrInList()`
48080b92c66SBarry Smith @*/
481*9371c9d4SSatish Balay const char *PetscBasename(const char a[]) {
48280b92c66SBarry Smith   const char *ptr;
48380b92c66SBarry Smith 
48480b92c66SBarry Smith   if (PetscStrrchr(a, '/', (char **)&ptr)) ptr = NULL;
485660278c0SBarry Smith   if (ptr == a) {
486660278c0SBarry Smith     if (PetscStrrchr(a, '\\', (char **)&ptr)) ptr = NULL;
487660278c0SBarry Smith   }
48880b92c66SBarry Smith   return ptr;
48980b92c66SBarry Smith }
49080b92c66SBarry Smith 
49180b92c66SBarry Smith /*@C
492e5c89e4eSSatish Balay    PetscStrcmp - Compares two strings,
493e5c89e4eSSatish Balay 
494e5c89e4eSSatish Balay    Not Collective
495e5c89e4eSSatish Balay 
496e5c89e4eSSatish Balay    Input Parameters:
497e5c89e4eSSatish Balay +  a - pointer to string first string
498e5c89e4eSSatish Balay -  b - pointer to second string
499e5c89e4eSSatish Balay 
500e5c89e4eSSatish Balay    Output Parameter:
5018c74ee41SBarry Smith .  flg - PETSC_TRUE if the two strings are equal
502e5c89e4eSSatish Balay 
503e5c89e4eSSatish Balay    Level: intermediate
504e5c89e4eSSatish Balay 
50595452b02SPatrick Sanan    Notes:
50695452b02SPatrick Sanan     Not for use in Fortran
5076f013253SBarry Smith 
508db781477SPatrick Sanan .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`
509e5c89e4eSSatish Balay @*/
510*9371c9d4SSatish Balay PetscErrorCode PetscStrcmp(const char a[], const char b[], PetscBool *flg) {
511e5c89e4eSSatish Balay   PetscFunctionBegin;
5125f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(flg, 3);
513a297a907SKarl Rupp   if (!a && !b) *flg = PETSC_TRUE;
514a297a907SKarl Rupp   else if (!a || !b) *flg = PETSC_FALSE;
515b45e3bf4SStefano Zampini   else *flg = (PetscBool)!strcmp(a, b);
516e5c89e4eSSatish Balay   PetscFunctionReturn(0);
517e5c89e4eSSatish Balay }
518e5c89e4eSSatish Balay 
519e5c89e4eSSatish Balay /*@C
520e5c89e4eSSatish Balay    PetscStrgrt - If first string is greater than the second
521e5c89e4eSSatish Balay 
522e5c89e4eSSatish Balay    Not Collective
523e5c89e4eSSatish Balay 
524e5c89e4eSSatish Balay    Input Parameters:
525e5c89e4eSSatish Balay +  a - pointer to first string
526e5c89e4eSSatish Balay -  b - pointer to second string
527e5c89e4eSSatish Balay 
528e5c89e4eSSatish Balay    Output Parameter:
529e5c89e4eSSatish Balay .  flg - if the first string is greater
530e5c89e4eSSatish Balay 
531e5c89e4eSSatish Balay    Notes:
532e5c89e4eSSatish Balay     Null arguments are ok, a null string is considered smaller than
533e5c89e4eSSatish Balay     all others
534e5c89e4eSSatish Balay 
5356f013253SBarry Smith    Not for use in Fortran
5366f013253SBarry Smith 
537e5c89e4eSSatish Balay    Level: intermediate
538e5c89e4eSSatish Balay 
539db781477SPatrick Sanan .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrcasecmp()`
540e5c89e4eSSatish Balay 
541e5c89e4eSSatish Balay @*/
542*9371c9d4SSatish Balay PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t) {
543e5c89e4eSSatish Balay   PetscFunctionBegin;
5445f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(t, 3);
545a297a907SKarl Rupp   if (!a && !b) *t = PETSC_FALSE;
546a297a907SKarl Rupp   else if (a && !b) *t = PETSC_TRUE;
547a297a907SKarl Rupp   else if (!a && b) *t = PETSC_FALSE;
548a297a907SKarl Rupp   else {
5495f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(a, 1);
5505f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(b, 2);
5515f80ce2aSJacob Faibussowitsch     *t = strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
552e5c89e4eSSatish Balay   }
553e5c89e4eSSatish Balay   PetscFunctionReturn(0);
554e5c89e4eSSatish Balay }
555e5c89e4eSSatish Balay 
556e5c89e4eSSatish Balay /*@C
557e5c89e4eSSatish Balay    PetscStrcasecmp - Returns true if the two strings are the same
558e5c89e4eSSatish Balay      except possibly for case.
559e5c89e4eSSatish Balay 
560e5c89e4eSSatish Balay    Not Collective
561e5c89e4eSSatish Balay 
562e5c89e4eSSatish Balay    Input Parameters:
563e5c89e4eSSatish Balay +  a - pointer to first string
564e5c89e4eSSatish Balay -  b - pointer to second string
565e5c89e4eSSatish Balay 
566e5c89e4eSSatish Balay    Output Parameter:
567e5c89e4eSSatish Balay .  flg - if the two strings are the same
568e5c89e4eSSatish Balay 
569e5c89e4eSSatish Balay    Notes:
570e5c89e4eSSatish Balay     Null arguments are ok
571e5c89e4eSSatish Balay 
5726f013253SBarry Smith    Not for use in Fortran
5736f013253SBarry Smith 
574e5c89e4eSSatish Balay    Level: intermediate
575e5c89e4eSSatish Balay 
576db781477SPatrick Sanan .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrgrt()`
577e5c89e4eSSatish Balay 
578e5c89e4eSSatish Balay @*/
579*9371c9d4SSatish Balay PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t) {
580e5c89e4eSSatish Balay   int c;
581e5c89e4eSSatish Balay 
582e5c89e4eSSatish Balay   PetscFunctionBegin;
5835f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(t, 3);
584e5c89e4eSSatish Balay   if (!a && !b) c = 0;
585e5c89e4eSSatish Balay   else if (!a || !b) c = 1;
58632b366c8SSatish Balay #if defined(PETSC_HAVE_STRCASECMP)
58732b366c8SSatish Balay   else c = strcasecmp(a, b);
58832b366c8SSatish Balay #elif defined(PETSC_HAVE_STRICMP)
589e5c89e4eSSatish Balay   else c = stricmp(a, b);
590e5c89e4eSSatish Balay #else
59132b366c8SSatish Balay   else {
59232b366c8SSatish Balay     char *aa, *bb;
5939566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(a, &aa));
5949566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(b, &bb));
5959566063dSJacob Faibussowitsch     PetscCall(PetscStrtolower(aa));
5969566063dSJacob Faibussowitsch     PetscCall(PetscStrtolower(bb));
5979566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(aa, bb, t));
5989566063dSJacob Faibussowitsch     PetscCall(PetscFree(aa));
5999566063dSJacob Faibussowitsch     PetscCall(PetscFree(bb));
60032b366c8SSatish Balay     PetscFunctionReturn(0);
60132b366c8SSatish Balay   }
602e5c89e4eSSatish Balay #endif
6035f80ce2aSJacob Faibussowitsch   *t = c ? PETSC_FALSE : PETSC_TRUE;
604e5c89e4eSSatish Balay   PetscFunctionReturn(0);
605e5c89e4eSSatish Balay }
606e5c89e4eSSatish Balay 
607e5c89e4eSSatish Balay /*@C
608e5c89e4eSSatish Balay    PetscStrncmp - Compares two strings, up to a certain length
609e5c89e4eSSatish Balay 
610e5c89e4eSSatish Balay    Not Collective
611e5c89e4eSSatish Balay 
612e5c89e4eSSatish Balay    Input Parameters:
613e5c89e4eSSatish Balay +  a - pointer to first string
614e5c89e4eSSatish Balay .  b - pointer to second string
615e5c89e4eSSatish Balay -  n - length to compare up to
616e5c89e4eSSatish Balay 
617e5c89e4eSSatish Balay    Output Parameter:
618e5c89e4eSSatish Balay .  t - if the two strings are equal
619e5c89e4eSSatish Balay 
620e5c89e4eSSatish Balay    Level: intermediate
621e5c89e4eSSatish Balay 
62295452b02SPatrick Sanan    Notes:
62395452b02SPatrick Sanan     Not for use in Fortran
6246f013253SBarry Smith 
625db781477SPatrick Sanan .seealso: `PetscStrgrt()`, `PetscStrcmp()`, `PetscStrcasecmp()`
626e5c89e4eSSatish Balay 
627e5c89e4eSSatish Balay @*/
628*9371c9d4SSatish Balay PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t) {
629e5c89e4eSSatish Balay   PetscFunctionBegin;
6305f80ce2aSJacob Faibussowitsch   if (n) {
6315f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(a, 1);
6325f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(b, 2);
6335f80ce2aSJacob Faibussowitsch   }
6345f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(t, 4);
6355f80ce2aSJacob Faibussowitsch   *t = strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
636e5c89e4eSSatish Balay   PetscFunctionReturn(0);
637e5c89e4eSSatish Balay }
638e5c89e4eSSatish Balay 
639e5c89e4eSSatish Balay /*@C
640a5b23f4aSJose E. Roman    PetscStrchr - Locates first occurrence of a character in a string
641e5c89e4eSSatish Balay 
642e5c89e4eSSatish Balay    Not Collective
643e5c89e4eSSatish Balay 
644e5c89e4eSSatish Balay    Input Parameters:
645e5c89e4eSSatish Balay +  a - pointer to string
646e5c89e4eSSatish Balay -  b - character
647e5c89e4eSSatish Balay 
648e5c89e4eSSatish Balay    Output Parameter:
649a5b23f4aSJose E. Roman .  c - location of occurrence, NULL if not found
650e5c89e4eSSatish Balay 
651e5c89e4eSSatish Balay    Level: intermediate
652e5c89e4eSSatish Balay 
65395452b02SPatrick Sanan    Notes:
65495452b02SPatrick Sanan     Not for use in Fortran
6556f013253SBarry Smith 
656e5c89e4eSSatish Balay @*/
657*9371c9d4SSatish Balay PetscErrorCode PetscStrchr(const char a[], char b, char *c[]) {
658e5c89e4eSSatish Balay   PetscFunctionBegin;
6595f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
6605f80ce2aSJacob Faibussowitsch   PetscValidPointer(c, 3);
661e5c89e4eSSatish Balay   *c = (char *)strchr(a, b);
662e5c89e4eSSatish Balay   PetscFunctionReturn(0);
663e5c89e4eSSatish Balay }
664e5c89e4eSSatish Balay 
665e5c89e4eSSatish Balay /*@C
666a5b23f4aSJose E. Roman    PetscStrrchr - Locates one location past the last occurrence of a character in a string,
667e5c89e4eSSatish Balay       if the character is not found then returns entire string
668e5c89e4eSSatish Balay 
669e5c89e4eSSatish Balay    Not Collective
670e5c89e4eSSatish Balay 
671e5c89e4eSSatish Balay    Input Parameters:
672e5c89e4eSSatish Balay +  a - pointer to string
673e5c89e4eSSatish Balay -  b - character
674e5c89e4eSSatish Balay 
675e5c89e4eSSatish Balay    Output Parameter:
676a5b23f4aSJose E. Roman .  tmp - location of occurrence, a if not found
677e5c89e4eSSatish Balay 
678e5c89e4eSSatish Balay    Level: intermediate
679e5c89e4eSSatish Balay 
68095452b02SPatrick Sanan    Notes:
68195452b02SPatrick Sanan     Not for use in Fortran
6826f013253SBarry Smith 
683e5c89e4eSSatish Balay @*/
684*9371c9d4SSatish Balay PetscErrorCode PetscStrrchr(const char a[], char b, char *tmp[]) {
685e5c89e4eSSatish Balay   PetscFunctionBegin;
6865f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
6875f80ce2aSJacob Faibussowitsch   PetscValidPointer(tmp, 3);
688e5c89e4eSSatish Balay   *tmp = (char *)strrchr(a, b);
689a297a907SKarl Rupp   if (!*tmp) *tmp = (char *)a;
690a297a907SKarl Rupp   else *tmp = *tmp + 1;
691e5c89e4eSSatish Balay   PetscFunctionReturn(0);
692e5c89e4eSSatish Balay }
693e5c89e4eSSatish Balay 
694e5c89e4eSSatish Balay /*@C
695e5c89e4eSSatish Balay    PetscStrtolower - Converts string to lower case
696e5c89e4eSSatish Balay 
697e5c89e4eSSatish Balay    Not Collective
698e5c89e4eSSatish Balay 
699e5c89e4eSSatish Balay    Input Parameters:
700e5c89e4eSSatish Balay .  a - pointer to string
701e5c89e4eSSatish Balay 
702e5c89e4eSSatish Balay    Level: intermediate
703e5c89e4eSSatish Balay 
70495452b02SPatrick Sanan    Notes:
70595452b02SPatrick Sanan     Not for use in Fortran
7066f013253SBarry Smith 
707e5c89e4eSSatish Balay @*/
708*9371c9d4SSatish 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 
72895452b02SPatrick Sanan    Notes:
72995452b02SPatrick Sanan     Not for use in Fortran
7302f234a98SBarry Smith 
7312f234a98SBarry Smith @*/
732*9371c9d4SSatish Balay PetscErrorCode PetscStrtoupper(char a[]) {
7332f234a98SBarry Smith   PetscFunctionBegin;
7345f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
7352f234a98SBarry Smith   while (*a) {
7362f234a98SBarry Smith     if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a';
7372f234a98SBarry Smith     a++;
7382f234a98SBarry Smith   }
7392f234a98SBarry Smith   PetscFunctionReturn(0);
7402f234a98SBarry Smith }
7412f234a98SBarry Smith 
7427ba3a57cSBarry Smith /*@C
7437ba3a57cSBarry Smith    PetscStrendswith - Determines if a string ends with a certain string
7441d1a0024SBarry Smith 
7457ba3a57cSBarry Smith    Not Collective
7467ba3a57cSBarry Smith 
7477ba3a57cSBarry Smith    Input Parameters:
7487ba3a57cSBarry Smith +  a - pointer to string
7497ba3a57cSBarry Smith -  b - string to endwith
7507ba3a57cSBarry Smith 
7517ba3a57cSBarry Smith    Output Parameter:
7527ba3a57cSBarry Smith .  flg - PETSC_TRUE or PETSC_FALSE
7537ba3a57cSBarry Smith 
75495452b02SPatrick Sanan    Notes:
75595452b02SPatrick Sanan     Not for use in Fortran
7567ba3a57cSBarry Smith 
7577ba3a57cSBarry Smith    Level: intermediate
7587ba3a57cSBarry Smith 
7597ba3a57cSBarry Smith @*/
760*9371c9d4SSatish Balay PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg) {
7617ba3a57cSBarry Smith   char *test;
7627ba3a57cSBarry Smith 
7637ba3a57cSBarry Smith   PetscFunctionBegin;
7645f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(flg, 3);
7657ba3a57cSBarry Smith   *flg = PETSC_FALSE;
7669566063dSJacob Faibussowitsch   PetscCall(PetscStrrstr(a, b, &test));
7677ba3a57cSBarry Smith   if (test) {
7685f80ce2aSJacob Faibussowitsch     size_t na, nb;
7695f80ce2aSJacob Faibussowitsch 
7709566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(a, &na));
7719566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(b, &nb));
7727ba3a57cSBarry Smith     if (a + na - nb == test) *flg = PETSC_TRUE;
7737ba3a57cSBarry Smith   }
7747ba3a57cSBarry Smith   PetscFunctionReturn(0);
7757ba3a57cSBarry Smith }
7767ba3a57cSBarry Smith 
7772c9581d2SBarry Smith /*@C
7782c9581d2SBarry Smith    PetscStrbeginswith - Determines if a string begins with a certain string
7792c9581d2SBarry Smith 
7802c9581d2SBarry Smith    Not Collective
7812c9581d2SBarry Smith 
7822c9581d2SBarry Smith    Input Parameters:
7832c9581d2SBarry Smith +  a - pointer to string
7842c9581d2SBarry Smith -  b - string to begin with
7852c9581d2SBarry Smith 
7862c9581d2SBarry Smith    Output Parameter:
7872c9581d2SBarry Smith .  flg - PETSC_TRUE or PETSC_FALSE
7882c9581d2SBarry Smith 
78995452b02SPatrick Sanan    Notes:
79095452b02SPatrick Sanan     Not for use in Fortran
7912c9581d2SBarry Smith 
7922c9581d2SBarry Smith    Level: intermediate
7932c9581d2SBarry Smith 
794db781477SPatrick Sanan .seealso: `PetscStrendswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
795db781477SPatrick Sanan           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()`
7966e3a5469SBarry Smith 
7972c9581d2SBarry Smith @*/
798*9371c9d4SSatish Balay PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg) {
7992c9581d2SBarry Smith   char *test;
8002c9581d2SBarry Smith 
8012c9581d2SBarry Smith   PetscFunctionBegin;
8025f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
8035f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(b, 2);
8045f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(flg, 3);
8052c9581d2SBarry Smith   *flg = PETSC_FALSE;
8069566063dSJacob Faibussowitsch   PetscCall(PetscStrrstr(a, b, &test));
807a297a907SKarl Rupp   if (test && (test == a)) *flg = PETSC_TRUE;
8082c9581d2SBarry Smith   PetscFunctionReturn(0);
8092c9581d2SBarry Smith }
8102c9581d2SBarry Smith 
8117ba3a57cSBarry Smith /*@C
8127ba3a57cSBarry Smith    PetscStrendswithwhich - Determines if a string ends with one of several possible strings
8137ba3a57cSBarry Smith 
8147ba3a57cSBarry Smith    Not Collective
8157ba3a57cSBarry Smith 
8167ba3a57cSBarry Smith    Input Parameters:
8177ba3a57cSBarry Smith +  a - pointer to string
818fa4b66f2SVaclav Hapla -  bs - strings to end with (last entry must be NULL)
8197ba3a57cSBarry Smith 
8207ba3a57cSBarry Smith    Output Parameter:
821fa4b66f2SVaclav Hapla .  cnt - the index of the string it ends with or the index of NULL
8227ba3a57cSBarry Smith 
82395452b02SPatrick Sanan    Notes:
82495452b02SPatrick Sanan     Not for use in Fortran
8257ba3a57cSBarry Smith 
8267ba3a57cSBarry Smith    Level: intermediate
8277ba3a57cSBarry Smith 
8287ba3a57cSBarry Smith @*/
829*9371c9d4SSatish Balay PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt) {
8307ba3a57cSBarry Smith   PetscFunctionBegin;
8315f80ce2aSJacob Faibussowitsch   PetscValidPointer(bs, 2);
8325f80ce2aSJacob Faibussowitsch   PetscValidIntPointer(cnt, 3);
8337ba3a57cSBarry Smith   *cnt = 0;
8347ba3a57cSBarry Smith   while (bs[*cnt]) {
8355f80ce2aSJacob Faibussowitsch     PetscBool flg;
8365f80ce2aSJacob Faibussowitsch 
8379566063dSJacob Faibussowitsch     PetscCall(PetscStrendswith(a, bs[*cnt], &flg));
8387ba3a57cSBarry Smith     if (flg) PetscFunctionReturn(0);
8395f80ce2aSJacob Faibussowitsch     ++(*cnt);
8407ba3a57cSBarry Smith   }
8417ba3a57cSBarry Smith   PetscFunctionReturn(0);
8427ba3a57cSBarry Smith }
8437ba3a57cSBarry Smith 
8447ba3a57cSBarry Smith /*@C
845a5b23f4aSJose E. Roman    PetscStrrstr - Locates last occurrence of string in another string
8467ba3a57cSBarry Smith 
8477ba3a57cSBarry Smith    Not Collective
8487ba3a57cSBarry Smith 
8497ba3a57cSBarry Smith    Input Parameters:
8507ba3a57cSBarry Smith +  a - pointer to string
8517ba3a57cSBarry Smith -  b - string to find
8527ba3a57cSBarry Smith 
8537ba3a57cSBarry Smith    Output Parameter:
854a5b23f4aSJose E. Roman .  tmp - location of occurrence
8557ba3a57cSBarry Smith 
85695452b02SPatrick Sanan    Notes:
85795452b02SPatrick Sanan     Not for use in Fortran
8587ba3a57cSBarry Smith 
8597ba3a57cSBarry Smith    Level: intermediate
8607ba3a57cSBarry Smith 
8617ba3a57cSBarry Smith @*/
862*9371c9d4SSatish Balay PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[]) {
8635f80ce2aSJacob Faibussowitsch   const char *ltmp = NULL;
8647ba3a57cSBarry Smith 
8657ba3a57cSBarry Smith   PetscFunctionBegin;
8665f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
8675f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(b, 2);
8685f80ce2aSJacob Faibussowitsch   PetscValidPointer(tmp, 3);
8695f80ce2aSJacob Faibussowitsch   while (a) {
8705f80ce2aSJacob Faibussowitsch     a = (char *)strstr(a, b);
8715f80ce2aSJacob Faibussowitsch     if (a) ltmp = a++;
8727ba3a57cSBarry Smith   }
8737ba3a57cSBarry Smith   *tmp = (char *)ltmp;
8747ba3a57cSBarry Smith   PetscFunctionReturn(0);
8757ba3a57cSBarry Smith }
8767ba3a57cSBarry Smith 
8777ba3a57cSBarry Smith /*@C
878a5b23f4aSJose E. Roman    PetscStrstr - Locates first occurrence of string in another string
8797ba3a57cSBarry Smith 
8807ba3a57cSBarry Smith    Not Collective
8817ba3a57cSBarry Smith 
8827ba3a57cSBarry Smith    Input Parameters:
883160f4796SJed Brown +  haystack - string to search
884160f4796SJed Brown -  needle - string to find
8857ba3a57cSBarry Smith 
8867ba3a57cSBarry Smith    Output Parameter:
887a5b23f4aSJose E. Roman .  tmp - location of occurrence, is a NULL if the string is not found
8887ba3a57cSBarry Smith 
88995452b02SPatrick Sanan    Notes:
89095452b02SPatrick Sanan     Not for use in Fortran
8917ba3a57cSBarry Smith 
8927ba3a57cSBarry Smith    Level: intermediate
8937ba3a57cSBarry Smith 
8947ba3a57cSBarry Smith @*/
895*9371c9d4SSatish Balay PetscErrorCode PetscStrstr(const char haystack[], const char needle[], char *tmp[]) {
8967ba3a57cSBarry Smith   PetscFunctionBegin;
8975f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(haystack, 1);
8985f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(needle, 2);
8995f80ce2aSJacob Faibussowitsch   PetscValidPointer(tmp, 3);
900160f4796SJed Brown   *tmp = (char *)strstr(haystack, needle);
9017ba3a57cSBarry Smith   PetscFunctionReturn(0);
9027ba3a57cSBarry Smith }
9037ba3a57cSBarry Smith 
904*9371c9d4SSatish Balay struct _p_PetscToken {
905*9371c9d4SSatish Balay   char  token;
906*9371c9d4SSatish Balay   char *array;
907*9371c9d4SSatish Balay   char *current;
908*9371c9d4SSatish Balay };
9091d1a0024SBarry Smith 
910e5c89e4eSSatish Balay /*@C
911e5c89e4eSSatish Balay    PetscTokenFind - Locates next "token" in a string
912e5c89e4eSSatish Balay 
913e5c89e4eSSatish Balay    Not Collective
914e5c89e4eSSatish Balay 
915e5c89e4eSSatish Balay    Input Parameters:
916e5c89e4eSSatish Balay .  a - pointer to token
917e5c89e4eSSatish Balay 
918e5c89e4eSSatish Balay    Output Parameter:
919a5b23f4aSJose E. Roman .  result - location of occurrence, NULL if not found
920e5c89e4eSSatish Balay 
921e5c89e4eSSatish Balay    Notes:
922e5c89e4eSSatish Balay 
923e5c89e4eSSatish Balay      This version is different from the system version in that
924e5c89e4eSSatish Balay   it allows you to pass a read-only string into the function.
925e5c89e4eSSatish Balay 
9264704e885SBarry Smith      This version also treats all characters etc. inside a double quote "
9274704e885SBarry Smith    as a single token.
9284704e885SBarry Smith 
9293a9c465aSBarry 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
9303a9c465aSBarry Smith    second will return a null terminated y
9313a9c465aSBarry Smith 
9323a9c465aSBarry 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
9333a9c465aSBarry Smith 
9346f013253SBarry Smith     Not for use in Fortran
9356f013253SBarry Smith 
936e5c89e4eSSatish Balay    Level: intermediate
937e5c89e4eSSatish Balay 
938db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenDestroy()`
939e5c89e4eSSatish Balay @*/
940*9371c9d4SSatish Balay PetscErrorCode PetscTokenFind(PetscToken a, char *result[]) {
9415f80ce2aSJacob Faibussowitsch   char *ptr, token;
942e5c89e4eSSatish Balay 
943e5c89e4eSSatish Balay   PetscFunctionBegin;
9445f80ce2aSJacob Faibussowitsch   PetscValidPointer(a, 1);
9455f80ce2aSJacob Faibussowitsch   PetscValidPointer(result, 2);
9465f80ce2aSJacob Faibussowitsch   *result = ptr = a->current;
947*9371c9d4SSatish Balay   if (ptr && !*ptr) {
948*9371c9d4SSatish Balay     *result = NULL;
949*9371c9d4SSatish Balay     PetscFunctionReturn(0);
950*9371c9d4SSatish Balay   }
9514704e885SBarry Smith   token = a->token;
952*9371c9d4SSatish Balay   if (ptr && (*ptr == '"')) {
953*9371c9d4SSatish Balay     token = '"';
954*9371c9d4SSatish Balay     (*result)++;
955*9371c9d4SSatish Balay     ptr++;
956*9371c9d4SSatish Balay   }
957e5c89e4eSSatish Balay   while (ptr) {
9584704e885SBarry Smith     if (*ptr == token) {
959e5c89e4eSSatish Balay       *ptr++ = 0;
960e5c89e4eSSatish Balay       while (*ptr == a->token) ptr++;
961e5c89e4eSSatish Balay       a->current = ptr;
962e5c89e4eSSatish Balay       break;
963e5c89e4eSSatish Balay     }
964e5c89e4eSSatish Balay     if (!*ptr) {
96502c9f0b5SLisandro Dalcin       a->current = NULL;
966e5c89e4eSSatish Balay       break;
967e5c89e4eSSatish Balay     }
968e5c89e4eSSatish Balay     ptr++;
969e5c89e4eSSatish Balay   }
970e5c89e4eSSatish Balay   PetscFunctionReturn(0);
971e5c89e4eSSatish Balay }
972e5c89e4eSSatish Balay 
973e5c89e4eSSatish Balay /*@C
974e5c89e4eSSatish Balay    PetscTokenCreate - Creates a PetscToken used to find tokens in a string
975e5c89e4eSSatish Balay 
976e5c89e4eSSatish Balay    Not Collective
977e5c89e4eSSatish Balay 
978e5c89e4eSSatish Balay    Input Parameters:
979e5c89e4eSSatish Balay +  string - the string to look in
9803a9c465aSBarry Smith -  b - the separator character
981e5c89e4eSSatish Balay 
982e5c89e4eSSatish Balay    Output Parameter:
9833a9c465aSBarry Smith .  t- the token object
984e5c89e4eSSatish Balay 
985e5c89e4eSSatish Balay    Notes:
986e5c89e4eSSatish Balay 
987e5c89e4eSSatish Balay      This version is different from the system version in that
988e5c89e4eSSatish Balay   it allows you to pass a read-only string into the function.
989e5c89e4eSSatish Balay 
9906f013253SBarry Smith     Not for use in Fortran
9916f013253SBarry Smith 
992e5c89e4eSSatish Balay    Level: intermediate
993e5c89e4eSSatish Balay 
994db781477SPatrick Sanan .seealso: `PetscTokenFind()`, `PetscTokenDestroy()`
995e5c89e4eSSatish Balay @*/
996*9371c9d4SSatish Balay PetscErrorCode PetscTokenCreate(const char a[], const char b, PetscToken *t) {
997e5c89e4eSSatish Balay   PetscFunctionBegin;
9985f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
9995f80ce2aSJacob Faibussowitsch   PetscValidPointer(t, 3);
10009566063dSJacob Faibussowitsch   PetscCall(PetscNew(t));
10019566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(a, &(*t)->array));
1002a297a907SKarl Rupp 
1003e5c89e4eSSatish Balay   (*t)->current = (*t)->array;
1004e5c89e4eSSatish Balay   (*t)->token   = b;
1005e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1006e5c89e4eSSatish Balay }
1007e5c89e4eSSatish Balay 
1008e5c89e4eSSatish Balay /*@C
1009e5c89e4eSSatish Balay    PetscTokenDestroy - Destroys a PetscToken
1010e5c89e4eSSatish Balay 
1011e5c89e4eSSatish Balay    Not Collective
1012e5c89e4eSSatish Balay 
1013e5c89e4eSSatish Balay    Input Parameters:
1014e5c89e4eSSatish Balay .  a - pointer to token
1015e5c89e4eSSatish Balay 
1016e5c89e4eSSatish Balay    Level: intermediate
1017e5c89e4eSSatish Balay 
101895452b02SPatrick Sanan    Notes:
101995452b02SPatrick Sanan     Not for use in Fortran
10206f013253SBarry Smith 
1021db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenFind()`
1022e5c89e4eSSatish Balay @*/
1023*9371c9d4SSatish Balay PetscErrorCode PetscTokenDestroy(PetscToken *a) {
1024e5c89e4eSSatish Balay   PetscFunctionBegin;
10258c74ee41SBarry Smith   if (!*a) PetscFunctionReturn(0);
10269566063dSJacob Faibussowitsch   PetscCall(PetscFree((*a)->array));
10279566063dSJacob Faibussowitsch   PetscCall(PetscFree(*a));
1028e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1029e5c89e4eSSatish Balay }
1030e5c89e4eSSatish Balay 
10318e81d068SLisandro Dalcin /*@C
10328e81d068SLisandro Dalcin    PetscStrInList - search string in character-delimited list
10338e81d068SLisandro Dalcin 
10348e81d068SLisandro Dalcin    Not Collective
10358e81d068SLisandro Dalcin 
10368e81d068SLisandro Dalcin    Input Parameters:
10378e81d068SLisandro Dalcin +  str - the string to look for
10388e81d068SLisandro Dalcin .  list - the list to search in
10398e81d068SLisandro Dalcin -  sep - the separator character
10408e81d068SLisandro Dalcin 
10418e81d068SLisandro Dalcin    Output Parameter:
10428e81d068SLisandro Dalcin .  found - whether str is in list
10438e81d068SLisandro Dalcin 
10448e81d068SLisandro Dalcin    Level: intermediate
10458e81d068SLisandro Dalcin 
104695452b02SPatrick Sanan    Notes:
104795452b02SPatrick Sanan     Not for use in Fortran
10488e81d068SLisandro Dalcin 
1049db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()`
10508e81d068SLisandro Dalcin @*/
1051*9371c9d4SSatish Balay PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found) {
10528e81d068SLisandro Dalcin   PetscToken token;
10538e81d068SLisandro Dalcin   char      *item;
10548e81d068SLisandro Dalcin 
10558e81d068SLisandro Dalcin   PetscFunctionBegin;
10565f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(found, 4);
10578e81d068SLisandro Dalcin   *found = PETSC_FALSE;
10589566063dSJacob Faibussowitsch   PetscCall(PetscTokenCreate(list, sep, &token));
10599566063dSJacob Faibussowitsch   PetscCall(PetscTokenFind(token, &item));
10608e81d068SLisandro Dalcin   while (item) {
10619566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(str, item, found));
10628e81d068SLisandro Dalcin     if (*found) break;
10639566063dSJacob Faibussowitsch     PetscCall(PetscTokenFind(token, &item));
10648e81d068SLisandro Dalcin   }
10659566063dSJacob Faibussowitsch   PetscCall(PetscTokenDestroy(&token));
10668e81d068SLisandro Dalcin   PetscFunctionReturn(0);
10678e81d068SLisandro Dalcin }
1068e5c89e4eSSatish Balay 
1069e5c89e4eSSatish Balay /*@C
1070e5c89e4eSSatish Balay    PetscGetPetscDir - Gets the directory PETSc is installed in
1071e5c89e4eSSatish Balay 
1072e5c89e4eSSatish Balay    Not Collective
1073e5c89e4eSSatish Balay 
1074e5c89e4eSSatish Balay    Output Parameter:
1075e5c89e4eSSatish Balay .  dir - the directory
1076e5c89e4eSSatish Balay 
1077e5c89e4eSSatish Balay    Level: developer
1078e5c89e4eSSatish Balay 
107995452b02SPatrick Sanan    Notes:
108095452b02SPatrick Sanan     Not for use in Fortran
10816f013253SBarry Smith 
1082e5c89e4eSSatish Balay @*/
1083*9371c9d4SSatish Balay PetscErrorCode PetscGetPetscDir(const char *dir[]) {
1084e5c89e4eSSatish Balay   PetscFunctionBegin;
10855f80ce2aSJacob Faibussowitsch   PetscValidPointer(dir, 1);
1086e5c89e4eSSatish Balay   *dir = PETSC_DIR;
1087e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1088e5c89e4eSSatish Balay }
1089e5c89e4eSSatish Balay 
1090e5c89e4eSSatish Balay /*@C
1091e5c89e4eSSatish Balay    PetscStrreplace - Replaces substrings in string with other substrings
1092e5c89e4eSSatish Balay 
1093e5c89e4eSSatish Balay    Not Collective
1094e5c89e4eSSatish Balay 
1095e5c89e4eSSatish Balay    Input Parameters:
1096e5c89e4eSSatish Balay +   comm - MPI_Comm of processors that are processing the string
109771573d7dSBarry Smith .   aa - the string to look in
1098d8ccf1fbSBarry Smith .   b - the resulting copy of a with replaced strings (b can be the same as a)
1099e5c89e4eSSatish Balay -   len - the length of b
1100e5c89e4eSSatish Balay 
1101e5c89e4eSSatish Balay    Notes:
1102e5c89e4eSSatish Balay       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
1103d5649816SBarry Smith       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values
1104e5c89e4eSSatish Balay       as well as any environmental variables.
1105e5c89e4eSSatish Balay 
11066f013253SBarry Smith       PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what
1107acc6cc86SBarry Smith       PETSc was built with and do not use environmental variables.
1108acc6cc86SBarry Smith 
11096f013253SBarry Smith       Not for use in Fortran
11106f013253SBarry Smith 
1111e5c89e4eSSatish Balay    Level: intermediate
1112e5c89e4eSSatish Balay 
1113e5c89e4eSSatish Balay @*/
1114*9371c9d4SSatish Balay PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len) {
1115e5c89e4eSSatish Balay   int           i = 0;
1116e5c89e4eSSatish Balay   size_t        l, l1, l2, l3;
111771573d7dSBarry Smith   char         *work, *par, *epar, env[1024], *tfree, *a = (char *)aa;
111802c9f0b5SLisandro Dalcin   const char   *s[] = {"${PETSC_ARCH}", "${PETSC_DIR}", "${PETSC_LIB_DIR}", "${DISPLAY}", "${HOMEDIRECTORY}", "${WORKINGDIRECTORY}", "${USERNAME}", "${HOSTNAME}", NULL};
111902c9f0b5SLisandro Dalcin   char         *r[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
1120ace3abfcSBarry Smith   PetscBool     flag;
1121589a23caSBarry Smith   static size_t DISPLAY_LENGTH = 265, USER_LENGTH = 256, HOST_LENGTH = 256;
1122e5c89e4eSSatish Balay 
1123e5c89e4eSSatish Balay   PetscFunctionBegin;
11245f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(aa, 2);
11255f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(b, 3);
11269566063dSJacob Faibussowitsch   if (aa == b) PetscCall(PetscStrallocpy(aa, (char **)&a));
11279566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(len, &work));
1128e5c89e4eSSatish Balay 
1129e5c89e4eSSatish Balay   /* get values for replaced variables */
11309566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_ARCH, &r[0]));
11319566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_DIR, &r[1]));
11329566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_LIB_DIR, &r[2]));
11339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(DISPLAY_LENGTH, &r[3]));
11349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[4]));
11359566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[5]));
11369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(USER_LENGTH, &r[6]));
11379566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(HOST_LENGTH, &r[7]));
11389566063dSJacob Faibussowitsch   PetscCall(PetscGetDisplay(r[3], DISPLAY_LENGTH));
11399566063dSJacob Faibussowitsch   PetscCall(PetscGetHomeDirectory(r[4], PETSC_MAX_PATH_LEN));
11409566063dSJacob Faibussowitsch   PetscCall(PetscGetWorkingDirectory(r[5], PETSC_MAX_PATH_LEN));
11419566063dSJacob Faibussowitsch   PetscCall(PetscGetUserName(r[6], USER_LENGTH));
11429566063dSJacob Faibussowitsch   PetscCall(PetscGetHostName(r[7], HOST_LENGTH));
1143487e5849SBarry Smith 
1144487e5849SBarry Smith   /* replace that are in environment */
11459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetenv(comm, "PETSC_LIB_DIR", env, sizeof(env), &flag));
1146487e5849SBarry Smith   if (flag) {
11479566063dSJacob Faibussowitsch     PetscCall(PetscFree(r[2]));
11489566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(env, &r[2]));
1149487e5849SBarry Smith   }
1150e5c89e4eSSatish Balay 
1151e5c89e4eSSatish Balay   /* replace the requested strings */
11529566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(b, a, len));
1153e5c89e4eSSatish Balay   while (s[i]) {
11549566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(s[i], &l));
11559566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(b, s[i], &par));
1156e5c89e4eSSatish Balay     while (par) {
1157e5c89e4eSSatish Balay       *par = 0;
1158e5c89e4eSSatish Balay       par += l;
1159e5c89e4eSSatish Balay 
11609566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(b, &l1));
11619566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(r[i], &l2));
11629566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(par, &l3));
1163cc73adaaSBarry Smith       PetscCheck(l1 + l2 + l3 < len, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "b len is not long enough to hold new values");
11649566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(work, b, len));
11659566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(work, r[i], len));
11669566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(work, par, len));
11679566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(b, work, len));
11689566063dSJacob Faibussowitsch       PetscCall(PetscStrstr(b, s[i], &par));
1169e5c89e4eSSatish Balay     }
1170e5c89e4eSSatish Balay     i++;
1171e5c89e4eSSatish Balay   }
1172487e5849SBarry Smith   i = 0;
1173487e5849SBarry Smith   while (r[i]) {
1174e5c89e4eSSatish Balay     tfree = (char *)r[i];
11759566063dSJacob Faibussowitsch     PetscCall(PetscFree(tfree));
1176487e5849SBarry Smith     i++;
1177e5c89e4eSSatish Balay   }
1178e5c89e4eSSatish Balay 
1179e5c89e4eSSatish Balay   /* look for any other ${xxx} strings to replace from environmental variables */
11809566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(b, "${", &par));
1181e5c89e4eSSatish Balay   while (par) {
1182e5c89e4eSSatish Balay     *par = 0;
1183e5c89e4eSSatish Balay     par += 2;
11849566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(work, b, len));
11859566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(par, "}", &epar));
1186e5c89e4eSSatish Balay     *epar = 0;
1187e5c89e4eSSatish Balay     epar += 1;
11889566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetenv(comm, par, env, sizeof(env), &flag));
118928b400f6SJacob Faibussowitsch     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Substitution string ${%s} not found as environmental variable", par);
11909566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(work, env, len));
11919566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(work, epar, len));
11929566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(b, work, len));
11939566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(b, "${", &par));
1194e5c89e4eSSatish Balay   }
11959566063dSJacob Faibussowitsch   PetscCall(PetscFree(work));
11969566063dSJacob Faibussowitsch   if (aa == b) PetscCall(PetscFree(a));
1197e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1198e5c89e4eSSatish Balay }
1199e5c89e4eSSatish Balay 
1200a53986e1SJed Brown /*@C
1201a53986e1SJed Brown    PetscEListFind - searches list of strings for given string, using case insensitive matching
1202e5c89e4eSSatish Balay 
1203a53986e1SJed Brown    Not Collective
1204a53986e1SJed Brown 
1205a53986e1SJed Brown    Input Parameters:
1206a53986e1SJed Brown +  n - number of strings in
1207a53986e1SJed Brown .  list - list of strings to search
1208a53986e1SJed Brown -  str - string to look for, empty string "" accepts default (first entry in list)
1209a53986e1SJed Brown 
1210a53986e1SJed Brown    Output Parameters:
1211a53986e1SJed Brown +  value - index of matching string (if found)
1212a53986e1SJed Brown -  found - boolean indicating whether string was found (can be NULL)
1213a53986e1SJed Brown 
1214a53986e1SJed Brown    Notes:
1215a53986e1SJed Brown    Not for use in Fortran
1216a53986e1SJed Brown 
1217a53986e1SJed Brown    Level: advanced
1218a53986e1SJed Brown @*/
1219*9371c9d4SSatish Balay PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found) {
1220a53986e1SJed Brown   PetscFunctionBegin;
12215f80ce2aSJacob Faibussowitsch   if (found) {
12225f80ce2aSJacob Faibussowitsch     PetscValidBoolPointer(found, 5);
12235f80ce2aSJacob Faibussowitsch     *found = PETSC_FALSE;
12245f80ce2aSJacob Faibussowitsch   }
12255f80ce2aSJacob Faibussowitsch   for (PetscInt i = 0; i < n; ++i) {
12265f80ce2aSJacob Faibussowitsch     PetscBool matched;
12275f80ce2aSJacob Faibussowitsch 
12289566063dSJacob Faibussowitsch     PetscCall(PetscStrcasecmp(str, list[i], &matched));
1229a53986e1SJed Brown     if (matched || !str[0]) {
1230a53986e1SJed Brown       if (found) *found = PETSC_TRUE;
1231a53986e1SJed Brown       *value = i;
1232a53986e1SJed Brown       break;
1233a53986e1SJed Brown     }
1234a53986e1SJed Brown   }
1235a53986e1SJed Brown   PetscFunctionReturn(0);
1236a53986e1SJed Brown }
1237a53986e1SJed Brown 
1238a53986e1SJed Brown /*@C
12398e81d068SLisandro Dalcin    PetscEnumFind - searches enum list of strings for given string, using case insensitive matching
1240a53986e1SJed Brown 
1241a53986e1SJed Brown    Not Collective
1242a53986e1SJed Brown 
1243a53986e1SJed Brown    Input Parameters:
1244a53986e1SJed Brown +  enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL
1245a53986e1SJed Brown -  str - string to look for
1246a53986e1SJed Brown 
1247a53986e1SJed Brown    Output Parameters:
1248a53986e1SJed Brown +  value - index of matching string (if found)
1249a53986e1SJed Brown -  found - boolean indicating whether string was found (can be NULL)
1250a53986e1SJed Brown 
1251a53986e1SJed Brown    Notes:
1252a53986e1SJed Brown    Not for use in Fortran
1253a53986e1SJed Brown 
1254a53986e1SJed Brown    Level: advanced
1255a53986e1SJed Brown @*/
1256*9371c9d4SSatish Balay PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found) {
1257d05ba7d2SLisandro Dalcin   PetscInt  n = 0, evalue;
1258a53986e1SJed Brown   PetscBool efound;
1259a53986e1SJed Brown 
1260a53986e1SJed Brown   PetscFunctionBegin;
12615f80ce2aSJacob Faibussowitsch   PetscValidPointer(enumlist, 1);
12625f80ce2aSJacob 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");
12635f80ce2aSJacob Faibussowitsch   PetscCheck(n >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
1264a53986e1SJed Brown   n -= 3; /* drop enum name, prefix, and null termination */
12659566063dSJacob Faibussowitsch   PetscCall(PetscEListFind(n, enumlist, str, &evalue, &efound));
12665f80ce2aSJacob Faibussowitsch   if (efound) {
12675f80ce2aSJacob Faibussowitsch     PetscValidPointer(value, 3);
12685f80ce2aSJacob Faibussowitsch     *value = (PetscEnum)evalue;
12695f80ce2aSJacob Faibussowitsch   }
12705f80ce2aSJacob Faibussowitsch   if (found) {
12715f80ce2aSJacob Faibussowitsch     PetscValidBoolPointer(found, 4);
12725f80ce2aSJacob Faibussowitsch     *found = efound;
12735f80ce2aSJacob Faibussowitsch   }
1274a53986e1SJed Brown   PetscFunctionReturn(0);
1275a53986e1SJed Brown }
1276660278c0SBarry Smith 
1277660278c0SBarry Smith /*@C
1278660278c0SBarry Smith   PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled.
1279660278c0SBarry Smith 
1280660278c0SBarry Smith   Not collective
1281660278c0SBarry Smith 
1282660278c0SBarry Smith   Input Parameter:
1283660278c0SBarry Smith . file - the file name
1284660278c0SBarry Smith 
1285660278c0SBarry Smith   Note:
1286660278c0SBarry Smith   PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems
1287660278c0SBarry Smith   so that comparisons of output between runs are easy to make.
1288660278c0SBarry Smith 
1289660278c0SBarry Smith   This mode is used for all tests in the test harness, it applies to both debug and optimized builds.
1290660278c0SBarry Smith 
1291660278c0SBarry Smith   Use the option -petsc_ci to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for
1292660278c0SBarry Smith   all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness.
1293660278c0SBarry Smith 
1294660278c0SBarry Smith   Always uses the Unix / as the file separate even on Microsoft Windows systems
1295660278c0SBarry Smith 
1296660278c0SBarry Smith   The option -petsc_ci_portable_error_output attempts to output the same error messages on all systems for the test harness.
1297660278c0SBarry Smith   In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc
1298660278c0SBarry 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
1299660278c0SBarry Smith   harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test
1300660278c0SBarry Smith   harness in the args: argument for specific examples. It will not neccessarily produce portable output if different errors
1301660278c0SBarry Smith   (or no errors) occur on a subset of the MPI ranks.
1302660278c0SBarry Smith 
1303660278c0SBarry Smith   Level: developer
1304660278c0SBarry Smith 
1305660278c0SBarry Smith .seealso: `PetscCILinenumber()`
1306660278c0SBarry Smith 
1307660278c0SBarry Smith @*/
1308*9371c9d4SSatish Balay const char *PetscCIFilename(const char *file) {
1309660278c0SBarry Smith   if (!PetscCIEnabledPortableErrorOutput) return file;
1310660278c0SBarry Smith   return PetscBasename(file);
1311660278c0SBarry Smith }
1312660278c0SBarry Smith 
1313660278c0SBarry Smith /*@C
1314660278c0SBarry Smith   PetscCILinenumber - returns a line number except if PetscCIEnablePortableErrorOutput) is set when it returns 0
1315660278c0SBarry Smith 
1316660278c0SBarry Smith   Not collective
1317660278c0SBarry Smith 
1318660278c0SBarry Smith   Input Parameter:
1319660278c0SBarry Smith . linenumber - the initial line number
1320660278c0SBarry Smith 
1321660278c0SBarry Smith   Note:
1322660278c0SBarry Smith   See `PetscCIFilename()` for details on usage
1323660278c0SBarry Smith 
1324660278c0SBarry Smith   Level: developer
1325660278c0SBarry Smith 
1326660278c0SBarry Smith .seealso: `PetscCIFilename()`
1327660278c0SBarry Smith 
1328660278c0SBarry Smith @*/
1329*9371c9d4SSatish Balay int PetscCILinenumber(int linenumber) {
1330660278c0SBarry Smith   if (!PetscCIEnabledPortableErrorOutput) return linenumber;
1331660278c0SBarry Smith   return 0;
1332660278c0SBarry Smith }
1333