xref: /petsc/src/sys/utils/str.c (revision 98e514b7077570bc6c93fc943f55a2431c068401)
1e5c89e4eSSatish Balay /*
2e5c89e4eSSatish Balay     We define the string operations here. The reason we just do not use
3e5c89e4eSSatish Balay   the standard string routines in the PETSc code is that on some machines
4e5c89e4eSSatish Balay   they are broken or have the wrong prototypes.
5e5c89e4eSSatish Balay 
6e5c89e4eSSatish Balay */
75f80ce2aSJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I  "petscsys.h"   I*/
83964eb88SJed Brown #if defined(PETSC_HAVE_STRINGS_H)
93964eb88SJed Brown   #include <strings.h> /* strcasecmp */
103964eb88SJed Brown #endif
113964eb88SJed Brown 
123c311c98SBarry Smith /*@C
1351a1f156SVaclav Hapla    PetscStrToArray - Separates a string by a character (for example ' ' or '\n') and creates an array of strings
143c311c98SBarry Smith 
153c311c98SBarry Smith    Not Collective
163c311c98SBarry Smith 
173c311c98SBarry Smith    Input Parameters:
18d67fe73bSBarry Smith +  s - pointer to string
1951a1f156SVaclav Hapla -  sp - separator character
203c311c98SBarry Smith 
21d8d19677SJose E. Roman    Output Parameters:
223c311c98SBarry Smith +   argc - the number of entries in the array
233c311c98SBarry Smith -   args - an array of the entries with a null at the end
243c311c98SBarry Smith 
253c311c98SBarry Smith    Level: intermediate
263c311c98SBarry Smith 
27811af0c4SBarry Smith    Note:
2895452b02SPatrick Sanan     this may be called before PetscInitialize() or after PetscFinalize()
293c311c98SBarry Smith 
30811af0c4SBarry Smith    Fortran Note:
316f013253SBarry Smith    Not for use in Fortran
326f013253SBarry Smith 
3395452b02SPatrick Sanan    Developer Notes:
34811af0c4SBarry Smith    Uses raw `malloc()` and does not call error handlers since this may be used before PETSc is initialized.
35811af0c4SBarry Smith 
36811af0c4SBarry Smith    Used to generate argc, args arguments passed to `MPI_Init()`
37301d30feSBarry Smith 
38db781477SPatrick Sanan .seealso: `PetscStrToArrayDestroy()`, `PetscToken`, `PetscTokenCreate()`
393c311c98SBarry Smith @*/
40d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrToArray(const char s[], char sp, int *argc, char ***args)
41d71ae5a4SJacob Faibussowitsch {
42c3bcdc7eSBarry Smith   int       i, j, n, *lens, cnt = 0;
43ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
443c311c98SBarry Smith 
4540a7e1efSBarry Smith   if (!s) n = 0;
4640a7e1efSBarry Smith   else n = strlen(s);
473c311c98SBarry Smith   *argc = 0;
4861528463SBarry Smith   *args = NULL;
49acf7dc08SSatish Balay   for (; n > 0; n--) { /* remove separator chars at the end - and will empty the string if all chars are separator chars */
50acf7dc08SSatish Balay     if (s[n - 1] != sp) break;
51acf7dc08SSatish Balay   }
525f80ce2aSJacob Faibussowitsch   if (!n) return 0;
533c311c98SBarry Smith   for (i = 0; i < n; i++) {
54d67fe73bSBarry Smith     if (s[i] != sp) break;
553c311c98SBarry Smith   }
563c311c98SBarry Smith   for (; i < n + 1; i++) {
579371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
589371c9d4SSatish Balay       flg = PETSC_TRUE;
599371c9d4SSatish Balay       (*argc)++;
609371c9d4SSatish Balay     } else if (s[i] != sp) {
619371c9d4SSatish Balay       flg = PETSC_FALSE;
623c311c98SBarry Smith     }
639371c9d4SSatish Balay   }
649371c9d4SSatish Balay   (*args) = (char **)malloc(((*argc) + 1) * sizeof(char *));
659371c9d4SSatish Balay   if (!*args) return PETSC_ERR_MEM;
669371c9d4SSatish Balay   lens = (int *)malloc((*argc) * sizeof(int));
679371c9d4SSatish Balay   if (!lens) return PETSC_ERR_MEM;
683c311c98SBarry Smith   for (i = 0; i < *argc; i++) lens[i] = 0;
693c311c98SBarry Smith 
703c311c98SBarry Smith   *argc = 0;
713c311c98SBarry Smith   for (i = 0; i < n; i++) {
72d67fe73bSBarry Smith     if (s[i] != sp) break;
733c311c98SBarry Smith   }
747dd9f305SSatish Balay   for (; i < n + 1; i++) {
759371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
769371c9d4SSatish Balay       flg = PETSC_TRUE;
779371c9d4SSatish Balay       (*argc)++;
789371c9d4SSatish Balay     } else if (s[i] != sp) {
799371c9d4SSatish Balay       lens[*argc]++;
809371c9d4SSatish Balay       flg = PETSC_FALSE;
819371c9d4SSatish Balay     }
823c311c98SBarry Smith   }
833c311c98SBarry Smith 
843c311c98SBarry Smith   for (i = 0; i < *argc; i++) {
85c3bcdc7eSBarry Smith     (*args)[i] = (char *)malloc((lens[i] + 1) * sizeof(char));
86c3bcdc7eSBarry Smith     if (!(*args)[i]) {
87c3bcdc7eSBarry Smith       free(lens);
88c3bcdc7eSBarry Smith       for (j = 0; j < i; j++) free((*args)[j]);
89c3bcdc7eSBarry Smith       free(*args);
90c3bcdc7eSBarry Smith       return PETSC_ERR_MEM;
91c3bcdc7eSBarry Smith     }
923c311c98SBarry Smith   }
93a2ea699eSBarry Smith   free(lens);
9402c9f0b5SLisandro Dalcin   (*args)[*argc] = NULL;
953c311c98SBarry Smith 
963c311c98SBarry Smith   *argc = 0;
973c311c98SBarry Smith   for (i = 0; i < n; i++) {
98d67fe73bSBarry Smith     if (s[i] != sp) break;
993c311c98SBarry Smith   }
1003c311c98SBarry Smith   for (; i < n + 1; i++) {
1019371c9d4SSatish Balay     if ((s[i] == sp || s[i] == 0) && !flg) {
1029371c9d4SSatish Balay       flg                   = PETSC_TRUE;
1039371c9d4SSatish Balay       (*args)[*argc][cnt++] = 0;
1049371c9d4SSatish Balay       (*argc)++;
1059371c9d4SSatish Balay       cnt = 0;
1069371c9d4SSatish Balay     } else if (s[i] != sp && s[i] != 0) {
1079371c9d4SSatish Balay       (*args)[*argc][cnt++] = s[i];
1089371c9d4SSatish Balay       flg                   = PETSC_FALSE;
1099371c9d4SSatish Balay     }
1103c311c98SBarry Smith   }
1113c311c98SBarry Smith   return 0;
1123c311c98SBarry Smith }
1133c311c98SBarry Smith 
114301d30feSBarry Smith /*@C
115811af0c4SBarry Smith    PetscStrToArrayDestroy - Frees array created with `PetscStrToArray()`.
116301d30feSBarry Smith 
117301d30feSBarry Smith    Not Collective
118301d30feSBarry Smith 
119301d30feSBarry Smith    Output Parameters:
120301d30feSBarry Smith +  argc - the number of arguments
121301d30feSBarry Smith -  args - the array of arguments
122301d30feSBarry Smith 
123301d30feSBarry Smith    Level: intermediate
124301d30feSBarry Smith 
125811af0c4SBarry Smith    Note:
126811af0c4SBarry Smith     This may be called before `PetscInitialize()` or after `PetscFinalize()`
127301d30feSBarry Smith 
128811af0c4SBarry Smith    Fortran Note:
1296f013253SBarry Smith    Not for use in Fortran
1306f013253SBarry Smith 
131db781477SPatrick Sanan .seealso: `PetscStrToArray()`
132301d30feSBarry Smith @*/
133d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrToArrayDestroy(int argc, char **args)
134d71ae5a4SJacob Faibussowitsch {
1355f80ce2aSJacob Faibussowitsch   for (int i = 0; i < argc; ++i) free(args[i]);
136a297a907SKarl Rupp   if (args) free(args);
137301d30feSBarry Smith   return 0;
138301d30feSBarry Smith }
139301d30feSBarry Smith 
140e5c89e4eSSatish Balay /*@C
141e5c89e4eSSatish Balay    PetscStrlen - Gets length of a string
142e5c89e4eSSatish Balay 
143e5c89e4eSSatish Balay    Not Collective
144e5c89e4eSSatish Balay 
145e5c89e4eSSatish Balay    Input Parameters:
146e5c89e4eSSatish Balay .  s - pointer to string
147e5c89e4eSSatish Balay 
148e5c89e4eSSatish Balay    Output Parameter:
149e5c89e4eSSatish Balay .  len - length in bytes
150e5c89e4eSSatish Balay 
151e5c89e4eSSatish Balay    Level: intermediate
152e5c89e4eSSatish Balay 
153e5c89e4eSSatish Balay    Note:
154811af0c4SBarry Smith    This routine is analogous to `strlen()`.
155e5c89e4eSSatish Balay 
156e5c89e4eSSatish Balay    Null string returns a length of zero
157e5c89e4eSSatish Balay 
158811af0c4SBarry Smith    Fortran Note:
1596f013253SBarry Smith    Not for use in Fortran
1606f013253SBarry Smith 
161811af0c4SBarry Smith .seealso: `PetscStrallocpy()`
162e5c89e4eSSatish Balay @*/
163d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrlen(const char s[], size_t *len)
164d71ae5a4SJacob Faibussowitsch {
165e5c89e4eSSatish Balay   PetscFunctionBegin;
1665f80ce2aSJacob Faibussowitsch   *len = s ? strlen(s) : 0;
167e5c89e4eSSatish Balay   PetscFunctionReturn(0);
168e5c89e4eSSatish Balay }
169e5c89e4eSSatish Balay 
170e5c89e4eSSatish Balay /*@C
171811af0c4SBarry Smith    PetscStrallocpy - Allocates space to hold a copy of a string then copies the string in the new space
172e5c89e4eSSatish Balay 
173e5c89e4eSSatish Balay    Not Collective
174e5c89e4eSSatish Balay 
175e5c89e4eSSatish Balay    Input Parameters:
176e5c89e4eSSatish Balay .  s - pointer to string
177e5c89e4eSSatish Balay 
178e5c89e4eSSatish Balay    Output Parameter:
179e5c89e4eSSatish Balay .  t - the copied string
180e5c89e4eSSatish Balay 
181e5c89e4eSSatish Balay    Level: intermediate
182e5c89e4eSSatish Balay 
183811af0c4SBarry Smith    Notes:
184e5c89e4eSSatish Balay    Null string returns a new null string
185e5c89e4eSSatish Balay 
186811af0c4SBarry Smith    If t has previously been allocated then that memory is lost, you may need to PetscFree()
1870ecf5a55SBarry Smith    the array before calling this routine.
1880ecf5a55SBarry Smith 
189811af0c4SBarry Smith    Fortran Note:
190811af0c4SBarry Smith    Not for use in Fortran
1910ecf5a55SBarry Smith 
192811af0c4SBarry Smith .seealso: `PetscStrArrayallocpy()`, `PetscStrcpy()`, `PetscStrNArrayallocpy()`
193e5c89e4eSSatish Balay @*/
194d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrallocpy(const char s[], char *t[])
195d71ae5a4SJacob Faibussowitsch {
19602c9f0b5SLisandro Dalcin   char *tmp = NULL;
197e5c89e4eSSatish Balay 
198e5c89e4eSSatish Balay   PetscFunctionBegin;
199e5c89e4eSSatish Balay   if (s) {
2005f80ce2aSJacob Faibussowitsch     size_t len;
2015f80ce2aSJacob Faibussowitsch 
2029566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(s, &len));
2039566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(1 + len, &tmp));
2049566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(tmp, s));
205e5c89e4eSSatish Balay   }
20671573d7dSBarry Smith   *t = tmp;
207e5c89e4eSSatish Balay   PetscFunctionReturn(0);
208e5c89e4eSSatish Balay }
209e5c89e4eSSatish Balay 
21047340559SBarry Smith /*@C
21147340559SBarry Smith    PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
21247340559SBarry Smith 
21347340559SBarry Smith    Not Collective
21447340559SBarry Smith 
21547340559SBarry Smith    Input Parameters:
21647340559SBarry Smith .  s - pointer to array of strings (final string is a null)
21747340559SBarry Smith 
21847340559SBarry Smith    Output Parameter:
21947340559SBarry Smith .  t - the copied array string
22047340559SBarry Smith 
22147340559SBarry Smith    Level: intermediate
22247340559SBarry Smith 
22347340559SBarry Smith    Note:
224811af0c4SBarry Smith    If t has previously been allocated then that memory is lost, you may need to PetscStrArrayDestroy()
2250ecf5a55SBarry Smith    the array before calling this routine.
2260ecf5a55SBarry Smith 
227811af0c4SBarry Smith    Fortran Note:
228811af0c4SBarry Smith    Not for use in Fortran
22947340559SBarry Smith 
230811af0c4SBarry Smith .seealso: `PetscStrallocpy()`, `PetscStrArrayDestroy()`, `PetscStrNArrayallocpy()`
23147340559SBarry Smith @*/
232d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrArrayallocpy(const char *const *list, char ***t)
233d71ae5a4SJacob Faibussowitsch {
2345f80ce2aSJacob Faibussowitsch   PetscInt n = 0;
23547340559SBarry Smith 
23647340559SBarry Smith   PetscFunctionBegin;
2379371c9d4SSatish Balay   while (list[n++])
2389371c9d4SSatish Balay     ;
2399566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n + 1, t));
2409566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
2410298fd71SBarry Smith   (*t)[n] = NULL;
24247340559SBarry Smith   PetscFunctionReturn(0);
24347340559SBarry Smith }
24447340559SBarry Smith 
24547340559SBarry Smith /*@C
246811af0c4SBarry Smith    PetscStrArrayDestroy - Frees array of strings created with `PetscStrArrayallocpy()`.
24747340559SBarry Smith 
24847340559SBarry Smith    Not Collective
24947340559SBarry Smith 
25047340559SBarry Smith    Output Parameters:
25147340559SBarry Smith .   list - array of strings
25247340559SBarry Smith 
25347340559SBarry Smith    Level: intermediate
25447340559SBarry Smith 
255811af0c4SBarry Smith    Fortran Note:
25695452b02SPatrick Sanan     Not for use in Fortran
25747340559SBarry Smith 
258db781477SPatrick Sanan .seealso: `PetscStrArrayallocpy()`
25947340559SBarry Smith @*/
260d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrArrayDestroy(char ***list)
261d71ae5a4SJacob Faibussowitsch {
26247340559SBarry Smith   PetscInt n = 0;
26347340559SBarry Smith 
2646fed8037SJed Brown   PetscFunctionBegin;
2656fed8037SJed Brown   if (!*list) PetscFunctionReturn(0);
2666fed8037SJed Brown   while ((*list)[n]) {
2679566063dSJacob Faibussowitsch     PetscCall(PetscFree((*list)[n]));
2685f80ce2aSJacob Faibussowitsch     ++n;
26947340559SBarry Smith   }
2709566063dSJacob Faibussowitsch   PetscCall(PetscFree(*list));
2716fed8037SJed Brown   PetscFunctionReturn(0);
27247340559SBarry Smith }
27347340559SBarry Smith 
2746991f827SBarry Smith /*@C
2756991f827SBarry Smith    PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings
2766991f827SBarry Smith 
2776991f827SBarry Smith    Not Collective
2786991f827SBarry Smith 
2796991f827SBarry Smith    Input Parameters:
2806991f827SBarry Smith +  n - the number of string entries
2816991f827SBarry Smith -  s - pointer to array of strings
2826991f827SBarry Smith 
2836991f827SBarry Smith    Output Parameter:
2846991f827SBarry Smith .  t - the copied array string
2856991f827SBarry Smith 
2866991f827SBarry Smith    Level: intermediate
2876991f827SBarry Smith 
288811af0c4SBarry Smith    Fortran Note:
2896991f827SBarry Smith       Not for use in Fortran
2906991f827SBarry Smith 
291db781477SPatrick Sanan .seealso: `PetscStrallocpy()`, `PetscStrArrayallocpy()`, `PetscStrNArrayDestroy()`
2926991f827SBarry Smith @*/
293d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrNArrayallocpy(PetscInt n, const char *const *list, char ***t)
294d71ae5a4SJacob Faibussowitsch {
2956991f827SBarry Smith   PetscFunctionBegin;
2969566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, t));
2979566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
2986991f827SBarry Smith   PetscFunctionReturn(0);
2996991f827SBarry Smith }
3006991f827SBarry Smith 
3016991f827SBarry Smith /*@C
302811af0c4SBarry Smith    PetscStrNArrayDestroy - Frees array of strings created with `PetscStrNArrayallocpy()`.
3036991f827SBarry Smith 
3046991f827SBarry Smith    Not Collective
3056991f827SBarry Smith 
3066991f827SBarry Smith    Output Parameters:
3076991f827SBarry Smith +   n - number of string entries
3086991f827SBarry Smith -   list - array of strings
3096991f827SBarry Smith 
3106991f827SBarry Smith    Level: intermediate
3116991f827SBarry Smith 
312811af0c4SBarry Smith    Fortran Note:
31395452b02SPatrick Sanan     Not for use in Fortran
3146991f827SBarry Smith 
315811af0c4SBarry Smith .seealso: `PetscStrNArrayallocpy()`, `PetscStrArrayallocpy()`
3166991f827SBarry Smith @*/
317d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrNArrayDestroy(PetscInt n, char ***list)
318d71ae5a4SJacob Faibussowitsch {
3196991f827SBarry Smith   PetscFunctionBegin;
3206991f827SBarry Smith   if (!*list) PetscFunctionReturn(0);
3219566063dSJacob Faibussowitsch   for (PetscInt i = 0; i < n; i++) PetscCall(PetscFree((*list)[i]));
3229566063dSJacob Faibussowitsch   PetscCall(PetscFree(*list));
3236991f827SBarry Smith   PetscFunctionReturn(0);
3246991f827SBarry Smith }
3256991f827SBarry Smith 
326e5c89e4eSSatish Balay /*@C
327e5c89e4eSSatish Balay    PetscStrcpy - Copies a string
328e5c89e4eSSatish Balay 
329e5c89e4eSSatish Balay    Not Collective
330e5c89e4eSSatish Balay 
331e5c89e4eSSatish Balay    Input Parameters:
332e5c89e4eSSatish Balay .  t - pointer to string
333e5c89e4eSSatish Balay 
334e5c89e4eSSatish Balay    Output Parameter:
335e5c89e4eSSatish Balay .  s - the copied string
336e5c89e4eSSatish Balay 
337e5c89e4eSSatish Balay    Level: intermediate
338e5c89e4eSSatish Balay 
3396f013253SBarry Smith    Notes:
340e5c89e4eSSatish Balay      Null string returns a string starting with zero
341e5c89e4eSSatish Balay 
342811af0c4SBarry Smith      It is recommended you use `PetscStrncpy()` instead of this routine
343811af0c4SBarry Smith 
344811af0c4SBarry Smith    Fortran Note:
3456f013253SBarry Smith     Not for use in Fortran
3466f013253SBarry Smith 
347811af0c4SBarry Smith .seealso: `PetscStrncpy()`, `PetscStrcat()`, `PetscStrlcat()`, `PetscStrallocpy()`
348e5c89e4eSSatish Balay @*/
349acc6cc86SBarry Smith 
350d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrcpy(char s[], const char t[])
351d71ae5a4SJacob Faibussowitsch {
352e5c89e4eSSatish Balay   PetscFunctionBegin;
3535f80ce2aSJacob Faibussowitsch   if (t) {
3545f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(s, 1);
3555f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(t, 2);
3565f80ce2aSJacob Faibussowitsch     strcpy(s, t);
3575f80ce2aSJacob Faibussowitsch   } else if (s) s[0] = 0;
358e5c89e4eSSatish Balay   PetscFunctionReturn(0);
359e5c89e4eSSatish Balay }
360e5c89e4eSSatish Balay 
361e5c89e4eSSatish Balay /*@C
362e5c89e4eSSatish Balay    PetscStrncpy - Copies a string up to a certain length
363e5c89e4eSSatish Balay 
364e5c89e4eSSatish Balay    Not Collective
365e5c89e4eSSatish Balay 
366e5c89e4eSSatish Balay    Input Parameters:
367e5c89e4eSSatish Balay +  t - pointer to string
368e5c89e4eSSatish Balay -  n - the length to copy
369e5c89e4eSSatish Balay 
370e5c89e4eSSatish Balay    Output Parameter:
371e5c89e4eSSatish Balay .  s - the copied string
372e5c89e4eSSatish Balay 
373e5c89e4eSSatish Balay    Level: intermediate
374e5c89e4eSSatish Balay 
375e5c89e4eSSatish Balay    Note:
376e5c89e4eSSatish Balay      Null string returns a string starting with zero
377e5c89e4eSSatish Balay 
378ff32304bSBarry Smith      If the string that is being copied is of length n or larger then the entire string is not
3791b6ef838SBarry Smith      copied and the final location of s is set to NULL. This is different then the behavior of
380811af0c4SBarry Smith      `strncpy()` which leaves s non-terminated if there is not room for the entire string.
381ff32304bSBarry Smith 
382811af0c4SBarry Smith   Developers Note:
383811af0c4SBarry Smith   Should this be `PetscStrlcpy()` to reflect its behavior which is like `strlcpy()` not `strncpy()`
38462a5de14SBarry Smith 
385811af0c4SBarry Smith .seealso: `PetscStrcpy()`, `PetscStrcat()`, `PetscStrlcat()`, `PetscStrallocpy()`
386e5c89e4eSSatish Balay @*/
387d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n)
388d71ae5a4SJacob Faibussowitsch {
389e5c89e4eSSatish Balay   PetscFunctionBegin;
3905f80ce2aSJacob 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");
391ff32304bSBarry Smith   if (t) {
3925f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(s, 1);
3938dc57659SBarry Smith     if (n > 1) {
3942c26941aSBarry Smith       strncpy(s, t, n - 1);
395ff32304bSBarry Smith       s[n - 1] = '\0';
3968dc57659SBarry Smith     } else {
3978dc57659SBarry Smith       s[0] = '\0';
3988dc57659SBarry Smith     }
399ff32304bSBarry Smith   } else if (s) s[0] = 0;
400e5c89e4eSSatish Balay   PetscFunctionReturn(0);
401e5c89e4eSSatish Balay }
402e5c89e4eSSatish Balay 
403e5c89e4eSSatish Balay /*@C
404e5c89e4eSSatish Balay    PetscStrcat - Concatenates a string onto a given string
405e5c89e4eSSatish Balay 
406e5c89e4eSSatish Balay    Not Collective
407e5c89e4eSSatish Balay 
408e5c89e4eSSatish Balay    Input Parameters:
409e5e2177aSMatthew Knepley +  s - string to be added to
410e5e2177aSMatthew Knepley -  t - pointer to string to be added to end
411e5c89e4eSSatish Balay 
412e5c89e4eSSatish Balay    Level: intermediate
413e5c89e4eSSatish Balay 
414811af0c4SBarry Smith    Note:
415811af0c4SBarry Smith     It is recommended you use `PetscStrlcat()` instead of this routine
416811af0c4SBarry Smith 
417811af0c4SBarry Smith    Fortran Note:
41895452b02SPatrick Sanan     Not for use in Fortran
4196f013253SBarry Smith 
420db781477SPatrick Sanan .seealso: `PetscStrcpy()`, `PetscStrncpy()`, `PetscStrlcat()`
421e5c89e4eSSatish Balay @*/
422d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrcat(char s[], const char t[])
423d71ae5a4SJacob Faibussowitsch {
424e5c89e4eSSatish Balay   PetscFunctionBegin;
4259b754dc9SBarry Smith   if (!t) PetscFunctionReturn(0);
4265f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(s, 1);
4275f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(t, 2);
428e5c89e4eSSatish Balay   strcat(s, t);
429e5c89e4eSSatish Balay   PetscFunctionReturn(0);
430e5c89e4eSSatish Balay }
431e5c89e4eSSatish Balay 
432e5c89e4eSSatish Balay /*@C
433a126751eSBarry Smith    PetscStrlcat - Concatenates a string onto a given string, up to a given length
434e5c89e4eSSatish Balay 
435e5c89e4eSSatish Balay    Not Collective
436e5c89e4eSSatish Balay 
437e5c89e4eSSatish Balay    Input Parameters:
438e0ffd71fSBarry Smith +  s - pointer to string to be added to at end
43972fa4726SStefano Zampini .  t - string to be added
44024a58d73SPatrick Sanan -  n - length of the original allocated string
441e5c89e4eSSatish Balay 
442e5c89e4eSSatish Balay    Level: intermediate
443e5c89e4eSSatish Balay 
444811af0c4SBarry Smith   Note:
445811af0c4SBarry Smith   Unlike the system call `strncat()`, the length passed in is the length of the
446811af0c4SBarry Smith   original allocated space, not the length of the left-over space. This is
447811af0c4SBarry Smith   similar to the BSD system call `strlcat()`.
448811af0c4SBarry Smith 
449811af0c4SBarry Smith   Fortran Note:
45024a58d73SPatrick Sanan   Not for use in Fortran
4516f013253SBarry Smith 
452db781477SPatrick Sanan .seealso: `PetscStrcpy()`, `PetscStrncpy()`, `PetscStrcat()`
453e5c89e4eSSatish Balay @*/
454d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrlcat(char s[], const char t[], size_t n)
455d71ae5a4SJacob Faibussowitsch {
456153a8027SBarry Smith   size_t len;
457153a8027SBarry Smith 
458e5c89e4eSSatish Balay   PetscFunctionBegin;
459e0ffd71fSBarry Smith   if (!t) PetscFunctionReturn(0);
4605f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(s, 1);
4615f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(t, 2);
4625f80ce2aSJacob Faibussowitsch   PetscCheck(n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "String buffer length must be positive");
4639566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(t, &len));
464153a8027SBarry Smith   strncat(s, t, n - len);
465681eeb0aSBarry Smith   s[n - 1] = 0;
466e5c89e4eSSatish Balay   PetscFunctionReturn(0);
467e5c89e4eSSatish Balay }
468e5c89e4eSSatish Balay 
469d71ae5a4SJacob Faibussowitsch void PetscStrcmpNoError(const char a[], const char b[], PetscBool *flg)
470d71ae5a4SJacob Faibussowitsch {
471573b0fb4SBarry Smith   if (!a && !b) *flg = PETSC_TRUE;
472573b0fb4SBarry Smith   else if (!a || !b) *flg = PETSC_FALSE;
4735f80ce2aSJacob Faibussowitsch   else *flg = strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE;
474573b0fb4SBarry Smith }
475573b0fb4SBarry Smith 
476e5c89e4eSSatish Balay /*@C
477811af0c4SBarry Smith    PetscBasename - returns a pointer to the last entry of a / or \ separated directory path
47880b92c66SBarry Smith 
47980b92c66SBarry Smith    Not Collective
48080b92c66SBarry Smith 
48180b92c66SBarry Smith    Input Parameter:
48280b92c66SBarry Smith .  a - pointer to string
48380b92c66SBarry Smith 
48480b92c66SBarry Smith    Level: intermediate
48580b92c66SBarry Smith 
486811af0c4SBarry Smith    Fortran Note:
48780b92c66SBarry Smith     Not for use in Fortran
48880b92c66SBarry Smith 
48980b92c66SBarry Smith .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`, `PetscStrrchr()`, `PetscStrcmp()`, `PetscStrstr()`,
49080b92c66SBarry Smith           `PetscTokenCreate()`, `PetscStrToArray()`, `PetscStrInList()`
49180b92c66SBarry Smith @*/
492d71ae5a4SJacob Faibussowitsch const char *PetscBasename(const char a[])
493d71ae5a4SJacob Faibussowitsch {
49480b92c66SBarry Smith   const char *ptr;
49580b92c66SBarry Smith 
49680b92c66SBarry Smith   if (PetscStrrchr(a, '/', (char **)&ptr)) ptr = NULL;
497660278c0SBarry Smith   if (ptr == a) {
498660278c0SBarry Smith     if (PetscStrrchr(a, '\\', (char **)&ptr)) ptr = NULL;
499660278c0SBarry Smith   }
50080b92c66SBarry Smith   return ptr;
50180b92c66SBarry Smith }
50280b92c66SBarry Smith 
50380b92c66SBarry Smith /*@C
504e5c89e4eSSatish Balay    PetscStrcmp - Compares two strings,
505e5c89e4eSSatish Balay 
506e5c89e4eSSatish Balay    Not Collective
507e5c89e4eSSatish Balay 
508e5c89e4eSSatish Balay    Input Parameters:
509e5c89e4eSSatish Balay +  a - pointer to string first string
510e5c89e4eSSatish Balay -  b - pointer to second string
511e5c89e4eSSatish Balay 
512e5c89e4eSSatish Balay    Output Parameter:
513811af0c4SBarry Smith .  flg - `PETSC_TRUE` if the two strings are equal
514e5c89e4eSSatish Balay 
515e5c89e4eSSatish Balay    Level: intermediate
516e5c89e4eSSatish Balay 
517811af0c4SBarry Smith    Fortran Note:
51895452b02SPatrick Sanan     Not for use in Fortran
5196f013253SBarry Smith 
520db781477SPatrick Sanan .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`
521e5c89e4eSSatish Balay @*/
522d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrcmp(const char a[], const char b[], PetscBool *flg)
523d71ae5a4SJacob Faibussowitsch {
524e5c89e4eSSatish Balay   PetscFunctionBegin;
5255f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(flg, 3);
526a297a907SKarl Rupp   if (!a && !b) *flg = PETSC_TRUE;
527a297a907SKarl Rupp   else if (!a || !b) *flg = PETSC_FALSE;
528b45e3bf4SStefano Zampini   else *flg = (PetscBool)!strcmp(a, b);
529e5c89e4eSSatish Balay   PetscFunctionReturn(0);
530e5c89e4eSSatish Balay }
531e5c89e4eSSatish Balay 
532e5c89e4eSSatish Balay /*@C
533e5c89e4eSSatish Balay    PetscStrgrt - If first string is greater than the second
534e5c89e4eSSatish Balay 
535e5c89e4eSSatish Balay    Not Collective
536e5c89e4eSSatish Balay 
537e5c89e4eSSatish Balay    Input Parameters:
538e5c89e4eSSatish Balay +  a - pointer to first string
539e5c89e4eSSatish Balay -  b - pointer to second string
540e5c89e4eSSatish Balay 
541e5c89e4eSSatish Balay    Output Parameter:
542e5c89e4eSSatish Balay .  flg - if the first string is greater
543e5c89e4eSSatish Balay 
544811af0c4SBarry Smith    Note:
545e5c89e4eSSatish Balay     Null arguments are ok, a null string is considered smaller than
546e5c89e4eSSatish Balay     all others
547e5c89e4eSSatish Balay 
548811af0c4SBarry Smith    Fortran Note:
5496f013253SBarry Smith    Not for use in Fortran
5506f013253SBarry Smith 
551e5c89e4eSSatish Balay    Level: intermediate
552e5c89e4eSSatish Balay 
553db781477SPatrick Sanan .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrcasecmp()`
554e5c89e4eSSatish Balay @*/
555d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t)
556d71ae5a4SJacob Faibussowitsch {
557e5c89e4eSSatish Balay   PetscFunctionBegin;
5585f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(t, 3);
559a297a907SKarl Rupp   if (!a && !b) *t = PETSC_FALSE;
560a297a907SKarl Rupp   else if (a && !b) *t = PETSC_TRUE;
561a297a907SKarl Rupp   else if (!a && b) *t = PETSC_FALSE;
562a297a907SKarl Rupp   else {
5635f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(a, 1);
5645f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(b, 2);
5655f80ce2aSJacob Faibussowitsch     *t = strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
566e5c89e4eSSatish Balay   }
567e5c89e4eSSatish Balay   PetscFunctionReturn(0);
568e5c89e4eSSatish Balay }
569e5c89e4eSSatish Balay 
570e5c89e4eSSatish Balay /*@C
571e5c89e4eSSatish Balay    PetscStrcasecmp - Returns true if the two strings are the same
572e5c89e4eSSatish Balay      except possibly for case.
573e5c89e4eSSatish Balay 
574e5c89e4eSSatish Balay    Not Collective
575e5c89e4eSSatish Balay 
576e5c89e4eSSatish Balay    Input Parameters:
577e5c89e4eSSatish Balay +  a - pointer to first string
578e5c89e4eSSatish Balay -  b - pointer to second string
579e5c89e4eSSatish Balay 
580e5c89e4eSSatish Balay    Output Parameter:
581e5c89e4eSSatish Balay .  flg - if the two strings are the same
582e5c89e4eSSatish Balay 
583811af0c4SBarry Smith    Note:
584e5c89e4eSSatish Balay     Null arguments are ok
585e5c89e4eSSatish Balay 
586811af0c4SBarry Smith    Fortran Note:
5876f013253SBarry Smith    Not for use in Fortran
5886f013253SBarry Smith 
589e5c89e4eSSatish Balay    Level: intermediate
590e5c89e4eSSatish Balay 
591db781477SPatrick Sanan .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrgrt()`
592e5c89e4eSSatish Balay @*/
593d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t)
594d71ae5a4SJacob Faibussowitsch {
595e5c89e4eSSatish Balay   int c;
596e5c89e4eSSatish Balay 
597e5c89e4eSSatish Balay   PetscFunctionBegin;
5985f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(t, 3);
599e5c89e4eSSatish Balay   if (!a && !b) c = 0;
600e5c89e4eSSatish Balay   else if (!a || !b) c = 1;
60132b366c8SSatish Balay #if defined(PETSC_HAVE_STRCASECMP)
60232b366c8SSatish Balay   else c = strcasecmp(a, b);
60332b366c8SSatish Balay #elif defined(PETSC_HAVE_STRICMP)
604e5c89e4eSSatish Balay   else c = stricmp(a, b);
605e5c89e4eSSatish Balay #else
60632b366c8SSatish Balay   else {
60732b366c8SSatish Balay     char *aa, *bb;
6089566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(a, &aa));
6099566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(b, &bb));
6109566063dSJacob Faibussowitsch     PetscCall(PetscStrtolower(aa));
6119566063dSJacob Faibussowitsch     PetscCall(PetscStrtolower(bb));
6129566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(aa, bb, t));
6139566063dSJacob Faibussowitsch     PetscCall(PetscFree(aa));
6149566063dSJacob Faibussowitsch     PetscCall(PetscFree(bb));
61532b366c8SSatish Balay     PetscFunctionReturn(0);
61632b366c8SSatish Balay   }
617e5c89e4eSSatish Balay #endif
6185f80ce2aSJacob Faibussowitsch   *t = c ? PETSC_FALSE : PETSC_TRUE;
619e5c89e4eSSatish Balay   PetscFunctionReturn(0);
620e5c89e4eSSatish Balay }
621e5c89e4eSSatish Balay 
622e5c89e4eSSatish Balay /*@C
623e5c89e4eSSatish Balay    PetscStrncmp - Compares two strings, up to a certain length
624e5c89e4eSSatish Balay 
625e5c89e4eSSatish Balay    Not Collective
626e5c89e4eSSatish Balay 
627e5c89e4eSSatish Balay    Input Parameters:
628e5c89e4eSSatish Balay +  a - pointer to first string
629e5c89e4eSSatish Balay .  b - pointer to second string
630e5c89e4eSSatish Balay -  n - length to compare up to
631e5c89e4eSSatish Balay 
632e5c89e4eSSatish Balay    Output Parameter:
633e5c89e4eSSatish Balay .  t - if the two strings are equal
634e5c89e4eSSatish Balay 
635e5c89e4eSSatish Balay    Level: intermediate
636e5c89e4eSSatish Balay 
637811af0c4SBarry Smith    Fortran Note:
63895452b02SPatrick Sanan     Not for use in Fortran
6396f013253SBarry Smith 
640db781477SPatrick Sanan .seealso: `PetscStrgrt()`, `PetscStrcmp()`, `PetscStrcasecmp()`
641e5c89e4eSSatish Balay @*/
642d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t)
643d71ae5a4SJacob Faibussowitsch {
644e5c89e4eSSatish Balay   PetscFunctionBegin;
6455f80ce2aSJacob Faibussowitsch   if (n) {
6465f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(a, 1);
6475f80ce2aSJacob Faibussowitsch     PetscValidCharPointer(b, 2);
6485f80ce2aSJacob Faibussowitsch   }
6495f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(t, 4);
6505f80ce2aSJacob Faibussowitsch   *t = strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
651e5c89e4eSSatish Balay   PetscFunctionReturn(0);
652e5c89e4eSSatish Balay }
653e5c89e4eSSatish Balay 
654e5c89e4eSSatish Balay /*@C
655a5b23f4aSJose E. Roman    PetscStrchr - Locates first occurrence of a character in a string
656e5c89e4eSSatish Balay 
657e5c89e4eSSatish Balay    Not Collective
658e5c89e4eSSatish Balay 
659e5c89e4eSSatish Balay    Input Parameters:
660e5c89e4eSSatish Balay +  a - pointer to string
661e5c89e4eSSatish Balay -  b - character
662e5c89e4eSSatish Balay 
663e5c89e4eSSatish Balay    Output Parameter:
664a5b23f4aSJose E. Roman .  c - location of occurrence, NULL if not found
665e5c89e4eSSatish Balay 
666e5c89e4eSSatish Balay    Level: intermediate
667e5c89e4eSSatish Balay 
668811af0c4SBarry Smith    Fortran Note:
66995452b02SPatrick Sanan     Not for use in Fortran
6706f013253SBarry Smith 
671811af0c4SBarry Smith .seealso: `PetscStrrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
672e5c89e4eSSatish Balay @*/
673d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrchr(const char a[], char b, char *c[])
674d71ae5a4SJacob Faibussowitsch {
675e5c89e4eSSatish Balay   PetscFunctionBegin;
6765f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
6775f80ce2aSJacob Faibussowitsch   PetscValidPointer(c, 3);
678e5c89e4eSSatish Balay   *c = (char *)strchr(a, b);
679e5c89e4eSSatish Balay   PetscFunctionReturn(0);
680e5c89e4eSSatish Balay }
681e5c89e4eSSatish Balay 
682e5c89e4eSSatish Balay /*@C
683a5b23f4aSJose E. Roman    PetscStrrchr - Locates one location past the last occurrence of a character in a string,
684e5c89e4eSSatish Balay       if the character is not found then returns entire string
685e5c89e4eSSatish Balay 
686e5c89e4eSSatish Balay    Not Collective
687e5c89e4eSSatish Balay 
688e5c89e4eSSatish Balay    Input Parameters:
689e5c89e4eSSatish Balay +  a - pointer to string
690e5c89e4eSSatish Balay -  b - character
691e5c89e4eSSatish Balay 
692e5c89e4eSSatish Balay    Output Parameter:
693a5b23f4aSJose E. Roman .  tmp - location of occurrence, a if not found
694e5c89e4eSSatish Balay 
695e5c89e4eSSatish Balay    Level: intermediate
696e5c89e4eSSatish Balay 
697811af0c4SBarry Smith    Fortran Note:
69895452b02SPatrick Sanan     Not for use in Fortran
6996f013253SBarry Smith 
700811af0c4SBarry Smith .seealso: `PetscStrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
701e5c89e4eSSatish Balay @*/
702d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrrchr(const char a[], char b, char *tmp[])
703d71ae5a4SJacob Faibussowitsch {
704e5c89e4eSSatish Balay   PetscFunctionBegin;
7055f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
7065f80ce2aSJacob Faibussowitsch   PetscValidPointer(tmp, 3);
707e5c89e4eSSatish Balay   *tmp = (char *)strrchr(a, b);
708a297a907SKarl Rupp   if (!*tmp) *tmp = (char *)a;
709a297a907SKarl Rupp   else *tmp = *tmp + 1;
710e5c89e4eSSatish Balay   PetscFunctionReturn(0);
711e5c89e4eSSatish Balay }
712e5c89e4eSSatish Balay 
713e5c89e4eSSatish Balay /*@C
714e5c89e4eSSatish Balay    PetscStrtolower - Converts string to lower case
715e5c89e4eSSatish Balay 
716e5c89e4eSSatish Balay    Not Collective
717e5c89e4eSSatish Balay 
718e5c89e4eSSatish Balay    Input Parameters:
719e5c89e4eSSatish Balay .  a - pointer to string
720e5c89e4eSSatish Balay 
721e5c89e4eSSatish Balay    Level: intermediate
722e5c89e4eSSatish Balay 
723811af0c4SBarry Smith    Fortran Note:
72495452b02SPatrick Sanan     Not for use in Fortran
7256f013253SBarry Smith 
726811af0c4SBarry Smith .seealso: `PetscStrtoupper()`
727e5c89e4eSSatish Balay @*/
728d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrtolower(char a[])
729d71ae5a4SJacob Faibussowitsch {
730e5c89e4eSSatish Balay   PetscFunctionBegin;
7315f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
732e5c89e4eSSatish Balay   while (*a) {
733e5c89e4eSSatish Balay     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
734e5c89e4eSSatish Balay     a++;
735e5c89e4eSSatish Balay   }
736e5c89e4eSSatish Balay   PetscFunctionReturn(0);
737e5c89e4eSSatish Balay }
738e5c89e4eSSatish Balay 
7392f234a98SBarry Smith /*@C
7406e3a5469SBarry Smith    PetscStrtoupper - Converts string to upper case
7412f234a98SBarry Smith 
7422f234a98SBarry Smith    Not Collective
7432f234a98SBarry Smith 
7442f234a98SBarry Smith    Input Parameters:
7452f234a98SBarry Smith .  a - pointer to string
7462f234a98SBarry Smith 
7472f234a98SBarry Smith    Level: intermediate
7482f234a98SBarry Smith 
749811af0c4SBarry Smith    Fortran Note:
75095452b02SPatrick Sanan     Not for use in Fortran
7512f234a98SBarry Smith 
752811af0c4SBarry Smith .seealso: `PetscStrtolower()`
7532f234a98SBarry Smith @*/
754d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrtoupper(char a[])
755d71ae5a4SJacob Faibussowitsch {
7562f234a98SBarry Smith   PetscFunctionBegin;
7575f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
7582f234a98SBarry Smith   while (*a) {
7592f234a98SBarry Smith     if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a';
7602f234a98SBarry Smith     a++;
7612f234a98SBarry Smith   }
7622f234a98SBarry Smith   PetscFunctionReturn(0);
7632f234a98SBarry Smith }
7642f234a98SBarry Smith 
7657ba3a57cSBarry Smith /*@C
7667ba3a57cSBarry Smith    PetscStrendswith - Determines if a string ends with a certain string
7671d1a0024SBarry Smith 
7687ba3a57cSBarry Smith    Not Collective
7697ba3a57cSBarry Smith 
7707ba3a57cSBarry Smith    Input Parameters:
7717ba3a57cSBarry Smith +  a - pointer to string
7727ba3a57cSBarry Smith -  b - string to endwith
7737ba3a57cSBarry Smith 
7747ba3a57cSBarry Smith    Output Parameter:
775811af0c4SBarry Smith .  flg - `PETSC_TRUE` or `PETSC_FALSE`
7767ba3a57cSBarry Smith 
777811af0c4SBarry Smith    Fortran Note:
77895452b02SPatrick Sanan     Not for use in Fortran
7797ba3a57cSBarry Smith 
7807ba3a57cSBarry Smith    Level: intermediate
7817ba3a57cSBarry Smith 
782811af0c4SBarry Smith .seealso: `PetscStrendswithwhich()`, `PetscStrbeginswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
783811af0c4SBarry Smith           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()`
7847ba3a57cSBarry Smith @*/
785d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg)
786d71ae5a4SJacob Faibussowitsch {
7877ba3a57cSBarry Smith   char *test;
7887ba3a57cSBarry Smith 
7897ba3a57cSBarry Smith   PetscFunctionBegin;
7905f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(flg, 3);
7917ba3a57cSBarry Smith   *flg = PETSC_FALSE;
7929566063dSJacob Faibussowitsch   PetscCall(PetscStrrstr(a, b, &test));
7937ba3a57cSBarry Smith   if (test) {
7945f80ce2aSJacob Faibussowitsch     size_t na, nb;
7955f80ce2aSJacob Faibussowitsch 
7969566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(a, &na));
7979566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(b, &nb));
7987ba3a57cSBarry Smith     if (a + na - nb == test) *flg = PETSC_TRUE;
7997ba3a57cSBarry Smith   }
8007ba3a57cSBarry Smith   PetscFunctionReturn(0);
8017ba3a57cSBarry Smith }
8027ba3a57cSBarry Smith 
8032c9581d2SBarry Smith /*@C
8042c9581d2SBarry Smith    PetscStrbeginswith - Determines if a string begins with a certain string
8052c9581d2SBarry Smith 
8062c9581d2SBarry Smith    Not Collective
8072c9581d2SBarry Smith 
8082c9581d2SBarry Smith    Input Parameters:
8092c9581d2SBarry Smith +  a - pointer to string
8102c9581d2SBarry Smith -  b - string to begin with
8112c9581d2SBarry Smith 
8122c9581d2SBarry Smith    Output Parameter:
8132c9581d2SBarry Smith .  flg - PETSC_TRUE or PETSC_FALSE
8142c9581d2SBarry Smith 
815811af0c4SBarry Smith    Fortran Note:
81695452b02SPatrick Sanan     Not for use in Fortran
8172c9581d2SBarry Smith 
8182c9581d2SBarry Smith    Level: intermediate
8192c9581d2SBarry Smith 
820db781477SPatrick Sanan .seealso: `PetscStrendswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
821db781477SPatrick Sanan           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()`
8222c9581d2SBarry Smith @*/
823d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg)
824d71ae5a4SJacob Faibussowitsch {
8252c9581d2SBarry Smith   char *test;
8262c9581d2SBarry Smith 
8272c9581d2SBarry Smith   PetscFunctionBegin;
8285f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
8295f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(b, 2);
8305f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(flg, 3);
8312c9581d2SBarry Smith   *flg = PETSC_FALSE;
8329566063dSJacob Faibussowitsch   PetscCall(PetscStrrstr(a, b, &test));
833a297a907SKarl Rupp   if (test && (test == a)) *flg = PETSC_TRUE;
8342c9581d2SBarry Smith   PetscFunctionReturn(0);
8352c9581d2SBarry Smith }
8362c9581d2SBarry Smith 
8377ba3a57cSBarry Smith /*@C
8387ba3a57cSBarry Smith    PetscStrendswithwhich - Determines if a string ends with one of several possible strings
8397ba3a57cSBarry Smith 
8407ba3a57cSBarry Smith    Not Collective
8417ba3a57cSBarry Smith 
8427ba3a57cSBarry Smith    Input Parameters:
8437ba3a57cSBarry Smith +  a - pointer to string
844fa4b66f2SVaclav Hapla -  bs - strings to end with (last entry must be NULL)
8457ba3a57cSBarry Smith 
8467ba3a57cSBarry Smith    Output Parameter:
847fa4b66f2SVaclav Hapla .  cnt - the index of the string it ends with or the index of NULL
8487ba3a57cSBarry Smith 
849811af0c4SBarry Smith    Fortran Note:
85095452b02SPatrick Sanan     Not for use in Fortran
8517ba3a57cSBarry Smith 
8527ba3a57cSBarry Smith    Level: intermediate
8537ba3a57cSBarry Smith 
854811af0c4SBarry Smith .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
855811af0c4SBarry Smith           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()`
8567ba3a57cSBarry Smith @*/
857d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt)
858d71ae5a4SJacob Faibussowitsch {
8597ba3a57cSBarry Smith   PetscFunctionBegin;
8605f80ce2aSJacob Faibussowitsch   PetscValidPointer(bs, 2);
8615f80ce2aSJacob Faibussowitsch   PetscValidIntPointer(cnt, 3);
8627ba3a57cSBarry Smith   *cnt = 0;
8637ba3a57cSBarry Smith   while (bs[*cnt]) {
8645f80ce2aSJacob Faibussowitsch     PetscBool flg;
8655f80ce2aSJacob Faibussowitsch 
8669566063dSJacob Faibussowitsch     PetscCall(PetscStrendswith(a, bs[*cnt], &flg));
8677ba3a57cSBarry Smith     if (flg) PetscFunctionReturn(0);
8685f80ce2aSJacob Faibussowitsch     ++(*cnt);
8697ba3a57cSBarry Smith   }
8707ba3a57cSBarry Smith   PetscFunctionReturn(0);
8717ba3a57cSBarry Smith }
8727ba3a57cSBarry Smith 
8737ba3a57cSBarry Smith /*@C
874a5b23f4aSJose E. Roman    PetscStrrstr - Locates last occurrence of string in another string
8757ba3a57cSBarry Smith 
8767ba3a57cSBarry Smith    Not Collective
8777ba3a57cSBarry Smith 
8787ba3a57cSBarry Smith    Input Parameters:
8797ba3a57cSBarry Smith +  a - pointer to string
8807ba3a57cSBarry Smith -  b - string to find
8817ba3a57cSBarry Smith 
8827ba3a57cSBarry Smith    Output Parameter:
883a5b23f4aSJose E. Roman .  tmp - location of occurrence
8847ba3a57cSBarry Smith 
885811af0c4SBarry Smith    Fortran Note:
88695452b02SPatrick Sanan     Not for use in Fortran
8877ba3a57cSBarry Smith 
8887ba3a57cSBarry Smith    Level: intermediate
8897ba3a57cSBarry Smith 
890811af0c4SBarry Smith .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
891811af0c4SBarry Smith           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()`
8927ba3a57cSBarry Smith @*/
893d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[])
894d71ae5a4SJacob Faibussowitsch {
8955f80ce2aSJacob Faibussowitsch   const char *ltmp = NULL;
8967ba3a57cSBarry Smith 
8977ba3a57cSBarry Smith   PetscFunctionBegin;
8985f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
8995f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(b, 2);
9005f80ce2aSJacob Faibussowitsch   PetscValidPointer(tmp, 3);
9015f80ce2aSJacob Faibussowitsch   while (a) {
9025f80ce2aSJacob Faibussowitsch     a = (char *)strstr(a, b);
9035f80ce2aSJacob Faibussowitsch     if (a) ltmp = a++;
9047ba3a57cSBarry Smith   }
9057ba3a57cSBarry Smith   *tmp = (char *)ltmp;
9067ba3a57cSBarry Smith   PetscFunctionReturn(0);
9077ba3a57cSBarry Smith }
9087ba3a57cSBarry Smith 
9097ba3a57cSBarry Smith /*@C
910a5b23f4aSJose E. Roman    PetscStrstr - Locates first occurrence of string in another string
9117ba3a57cSBarry Smith 
9127ba3a57cSBarry Smith    Not Collective
9137ba3a57cSBarry Smith 
9147ba3a57cSBarry Smith    Input Parameters:
915160f4796SJed Brown +  haystack - string to search
916160f4796SJed Brown -  needle - string to find
9177ba3a57cSBarry Smith 
9187ba3a57cSBarry Smith    Output Parameter:
919a5b23f4aSJose E. Roman .  tmp - location of occurrence, is a NULL if the string is not found
9207ba3a57cSBarry Smith 
921811af0c4SBarry Smith    Fortran Note:
92295452b02SPatrick Sanan     Not for use in Fortran
9237ba3a57cSBarry Smith 
9247ba3a57cSBarry Smith    Level: intermediate
9257ba3a57cSBarry Smith 
926811af0c4SBarry Smith .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
927811af0c4SBarry Smith           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()`
9287ba3a57cSBarry Smith @*/
929d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrstr(const char haystack[], const char needle[], char *tmp[])
930d71ae5a4SJacob Faibussowitsch {
9317ba3a57cSBarry Smith   PetscFunctionBegin;
9325f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(haystack, 1);
9335f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(needle, 2);
9345f80ce2aSJacob Faibussowitsch   PetscValidPointer(tmp, 3);
935160f4796SJed Brown   *tmp = (char *)strstr(haystack, needle);
9367ba3a57cSBarry Smith   PetscFunctionReturn(0);
9377ba3a57cSBarry Smith }
9387ba3a57cSBarry Smith 
9399371c9d4SSatish Balay struct _p_PetscToken {
9409371c9d4SSatish Balay   char  token;
9419371c9d4SSatish Balay   char *array;
9429371c9d4SSatish Balay   char *current;
9439371c9d4SSatish Balay };
9441d1a0024SBarry Smith 
945e5c89e4eSSatish Balay /*@C
946e5c89e4eSSatish Balay    PetscTokenFind - Locates next "token" in a string
947e5c89e4eSSatish Balay 
948e5c89e4eSSatish Balay    Not Collective
949e5c89e4eSSatish Balay 
950e5c89e4eSSatish Balay    Input Parameters:
951e5c89e4eSSatish Balay .  a - pointer to token
952e5c89e4eSSatish Balay 
953e5c89e4eSSatish Balay    Output Parameter:
954a5b23f4aSJose E. Roman .  result - location of occurrence, NULL if not found
955e5c89e4eSSatish Balay 
956e5c89e4eSSatish Balay    Notes:
957e5c89e4eSSatish Balay      This version is different from the system version in that
958e5c89e4eSSatish Balay   it allows you to pass a read-only string into the function.
959e5c89e4eSSatish Balay 
9604704e885SBarry Smith      This version also treats all characters etc. inside a double quote "
9614704e885SBarry Smith    as a single token.
9624704e885SBarry Smith 
9633a9c465aSBarry 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
9643a9c465aSBarry Smith    second will return a null terminated y
9653a9c465aSBarry Smith 
9663a9c465aSBarry 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
9673a9c465aSBarry Smith 
968811af0c4SBarry Smith    Fortran Note:
9696f013253SBarry Smith     Not for use in Fortran
9706f013253SBarry Smith 
971e5c89e4eSSatish Balay    Level: intermediate
972e5c89e4eSSatish Balay 
973db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenDestroy()`
974e5c89e4eSSatish Balay @*/
975d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTokenFind(PetscToken a, char *result[])
976d71ae5a4SJacob Faibussowitsch {
9775f80ce2aSJacob Faibussowitsch   char *ptr, token;
978e5c89e4eSSatish Balay 
979e5c89e4eSSatish Balay   PetscFunctionBegin;
9805f80ce2aSJacob Faibussowitsch   PetscValidPointer(a, 1);
9815f80ce2aSJacob Faibussowitsch   PetscValidPointer(result, 2);
9825f80ce2aSJacob Faibussowitsch   *result = ptr = a->current;
9839371c9d4SSatish Balay   if (ptr && !*ptr) {
9849371c9d4SSatish Balay     *result = NULL;
9859371c9d4SSatish Balay     PetscFunctionReturn(0);
9869371c9d4SSatish Balay   }
9874704e885SBarry Smith   token = a->token;
9889371c9d4SSatish Balay   if (ptr && (*ptr == '"')) {
9899371c9d4SSatish Balay     token = '"';
9909371c9d4SSatish Balay     (*result)++;
9919371c9d4SSatish Balay     ptr++;
9929371c9d4SSatish Balay   }
993e5c89e4eSSatish Balay   while (ptr) {
9944704e885SBarry Smith     if (*ptr == token) {
995e5c89e4eSSatish Balay       *ptr++ = 0;
996e5c89e4eSSatish Balay       while (*ptr == a->token) ptr++;
997e5c89e4eSSatish Balay       a->current = ptr;
998e5c89e4eSSatish Balay       break;
999e5c89e4eSSatish Balay     }
1000e5c89e4eSSatish Balay     if (!*ptr) {
100102c9f0b5SLisandro Dalcin       a->current = NULL;
1002e5c89e4eSSatish Balay       break;
1003e5c89e4eSSatish Balay     }
1004e5c89e4eSSatish Balay     ptr++;
1005e5c89e4eSSatish Balay   }
1006e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1007e5c89e4eSSatish Balay }
1008e5c89e4eSSatish Balay 
1009e5c89e4eSSatish Balay /*@C
1010811af0c4SBarry Smith    PetscTokenCreate - Creates a `PetscToken` used to find tokens in a string
1011e5c89e4eSSatish Balay 
1012e5c89e4eSSatish Balay    Not Collective
1013e5c89e4eSSatish Balay 
1014e5c89e4eSSatish Balay    Input Parameters:
1015e5c89e4eSSatish Balay +  string - the string to look in
10163a9c465aSBarry Smith -  b - the separator character
1017e5c89e4eSSatish Balay 
1018e5c89e4eSSatish Balay    Output Parameter:
10193a9c465aSBarry Smith .  t- the token object
1020e5c89e4eSSatish Balay 
1021811af0c4SBarry Smith    Note:
1022e5c89e4eSSatish Balay      This version is different from the system version in that
1023e5c89e4eSSatish Balay   it allows you to pass a read-only string into the function.
1024e5c89e4eSSatish Balay 
1025811af0c4SBarry Smith    Fortran Note:
10266f013253SBarry Smith     Not for use in Fortran
10276f013253SBarry Smith 
1028e5c89e4eSSatish Balay    Level: intermediate
1029e5c89e4eSSatish Balay 
1030db781477SPatrick Sanan .seealso: `PetscTokenFind()`, `PetscTokenDestroy()`
1031e5c89e4eSSatish Balay @*/
1032*98e514b7SJacob Faibussowitsch PetscErrorCode PetscTokenCreate(const char a[], char b, PetscToken *t)
1033d71ae5a4SJacob Faibussowitsch {
1034e5c89e4eSSatish Balay   PetscFunctionBegin;
10355f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(a, 1);
10365f80ce2aSJacob Faibussowitsch   PetscValidPointer(t, 3);
10379566063dSJacob Faibussowitsch   PetscCall(PetscNew(t));
10389566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(a, &(*t)->array));
1039a297a907SKarl Rupp 
1040e5c89e4eSSatish Balay   (*t)->current = (*t)->array;
1041e5c89e4eSSatish Balay   (*t)->token   = b;
1042e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1043e5c89e4eSSatish Balay }
1044e5c89e4eSSatish Balay 
1045e5c89e4eSSatish Balay /*@C
1046811af0c4SBarry Smith    PetscTokenDestroy - Destroys a `PetscToken`
1047e5c89e4eSSatish Balay 
1048e5c89e4eSSatish Balay    Not Collective
1049e5c89e4eSSatish Balay 
1050e5c89e4eSSatish Balay    Input Parameters:
1051e5c89e4eSSatish Balay .  a - pointer to token
1052e5c89e4eSSatish Balay 
1053e5c89e4eSSatish Balay    Level: intermediate
1054e5c89e4eSSatish Balay 
1055811af0c4SBarry Smith    Fortran Note:
105695452b02SPatrick Sanan     Not for use in Fortran
10576f013253SBarry Smith 
1058db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenFind()`
1059e5c89e4eSSatish Balay @*/
1060d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTokenDestroy(PetscToken *a)
1061d71ae5a4SJacob Faibussowitsch {
1062e5c89e4eSSatish Balay   PetscFunctionBegin;
10638c74ee41SBarry Smith   if (!*a) PetscFunctionReturn(0);
10649566063dSJacob Faibussowitsch   PetscCall(PetscFree((*a)->array));
10659566063dSJacob Faibussowitsch   PetscCall(PetscFree(*a));
1066e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1067e5c89e4eSSatish Balay }
1068e5c89e4eSSatish Balay 
10698e81d068SLisandro Dalcin /*@C
1070811af0c4SBarry Smith    PetscStrInList - search for string in character-delimited list
10718e81d068SLisandro Dalcin 
10728e81d068SLisandro Dalcin    Not Collective
10738e81d068SLisandro Dalcin 
10748e81d068SLisandro Dalcin    Input Parameters:
10758e81d068SLisandro Dalcin +  str - the string to look for
10768e81d068SLisandro Dalcin .  list - the list to search in
10778e81d068SLisandro Dalcin -  sep - the separator character
10788e81d068SLisandro Dalcin 
10798e81d068SLisandro Dalcin    Output Parameter:
10808e81d068SLisandro Dalcin .  found - whether str is in list
10818e81d068SLisandro Dalcin 
10828e81d068SLisandro Dalcin    Level: intermediate
10838e81d068SLisandro Dalcin 
1084811af0c4SBarry Smith    Fortran Note:
108595452b02SPatrick Sanan     Not for use in Fortran
10868e81d068SLisandro Dalcin 
1087db781477SPatrick Sanan .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()`
10888e81d068SLisandro Dalcin @*/
1089d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found)
1090d71ae5a4SJacob Faibussowitsch {
10918e81d068SLisandro Dalcin   PetscToken token;
10928e81d068SLisandro Dalcin   char      *item;
10938e81d068SLisandro Dalcin 
10948e81d068SLisandro Dalcin   PetscFunctionBegin;
10955f80ce2aSJacob Faibussowitsch   PetscValidBoolPointer(found, 4);
10968e81d068SLisandro Dalcin   *found = PETSC_FALSE;
10979566063dSJacob Faibussowitsch   PetscCall(PetscTokenCreate(list, sep, &token));
10989566063dSJacob Faibussowitsch   PetscCall(PetscTokenFind(token, &item));
10998e81d068SLisandro Dalcin   while (item) {
11009566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(str, item, found));
11018e81d068SLisandro Dalcin     if (*found) break;
11029566063dSJacob Faibussowitsch     PetscCall(PetscTokenFind(token, &item));
11038e81d068SLisandro Dalcin   }
11049566063dSJacob Faibussowitsch   PetscCall(PetscTokenDestroy(&token));
11058e81d068SLisandro Dalcin   PetscFunctionReturn(0);
11068e81d068SLisandro Dalcin }
1107e5c89e4eSSatish Balay 
1108e5c89e4eSSatish Balay /*@C
1109e5c89e4eSSatish Balay    PetscGetPetscDir - Gets the directory PETSc is installed in
1110e5c89e4eSSatish Balay 
1111e5c89e4eSSatish Balay    Not Collective
1112e5c89e4eSSatish Balay 
1113e5c89e4eSSatish Balay    Output Parameter:
1114e5c89e4eSSatish Balay .  dir - the directory
1115e5c89e4eSSatish Balay 
1116e5c89e4eSSatish Balay    Level: developer
1117e5c89e4eSSatish Balay 
1118811af0c4SBarry Smith    Fortran Note:
111995452b02SPatrick Sanan     Not for use in Fortran
11206f013253SBarry Smith 
1121e5c89e4eSSatish Balay @*/
1122d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGetPetscDir(const char *dir[])
1123d71ae5a4SJacob Faibussowitsch {
1124e5c89e4eSSatish Balay   PetscFunctionBegin;
11255f80ce2aSJacob Faibussowitsch   PetscValidPointer(dir, 1);
1126e5c89e4eSSatish Balay   *dir = PETSC_DIR;
1127e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1128e5c89e4eSSatish Balay }
1129e5c89e4eSSatish Balay 
1130e5c89e4eSSatish Balay /*@C
1131e5c89e4eSSatish Balay    PetscStrreplace - Replaces substrings in string with other substrings
1132e5c89e4eSSatish Balay 
1133e5c89e4eSSatish Balay    Not Collective
1134e5c89e4eSSatish Balay 
1135e5c89e4eSSatish Balay    Input Parameters:
1136811af0c4SBarry Smith +   comm - `MPI_Comm` of processors that are processing the string
113771573d7dSBarry Smith .   aa - the string to look in
1138d8ccf1fbSBarry Smith .   b - the resulting copy of a with replaced strings (b can be the same as a)
1139e5c89e4eSSatish Balay -   len - the length of b
1140e5c89e4eSSatish Balay 
1141e5c89e4eSSatish Balay    Notes:
1142e5c89e4eSSatish Balay       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
1143d5649816SBarry Smith       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values
1144e5c89e4eSSatish Balay       as well as any environmental variables.
1145e5c89e4eSSatish Balay 
1146811af0c4SBarry Smith       `PETSC_LIB_DIR` uses the environmental variable if it exists. `PETSC_ARCH` and `PETSC_DIR` use what
1147acc6cc86SBarry Smith       PETSc was built with and do not use environmental variables.
1148acc6cc86SBarry Smith 
1149811af0c4SBarry Smith    Fortran Note:
11506f013253SBarry Smith       Not for use in Fortran
11516f013253SBarry Smith 
1152811af0c4SBarry Smith    Level: developer
1153e5c89e4eSSatish Balay 
1154e5c89e4eSSatish Balay @*/
1155d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len)
1156d71ae5a4SJacob Faibussowitsch {
1157e5c89e4eSSatish Balay   int           i = 0;
1158e5c89e4eSSatish Balay   size_t        l, l1, l2, l3;
115971573d7dSBarry Smith   char         *work, *par, *epar, env[1024], *tfree, *a = (char *)aa;
116002c9f0b5SLisandro Dalcin   const char   *s[] = {"${PETSC_ARCH}", "${PETSC_DIR}", "${PETSC_LIB_DIR}", "${DISPLAY}", "${HOMEDIRECTORY}", "${WORKINGDIRECTORY}", "${USERNAME}", "${HOSTNAME}", NULL};
116102c9f0b5SLisandro Dalcin   char         *r[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
1162ace3abfcSBarry Smith   PetscBool     flag;
1163589a23caSBarry Smith   static size_t DISPLAY_LENGTH = 265, USER_LENGTH = 256, HOST_LENGTH = 256;
1164e5c89e4eSSatish Balay 
1165e5c89e4eSSatish Balay   PetscFunctionBegin;
11665f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(aa, 2);
11675f80ce2aSJacob Faibussowitsch   PetscValidCharPointer(b, 3);
11689566063dSJacob Faibussowitsch   if (aa == b) PetscCall(PetscStrallocpy(aa, (char **)&a));
11699566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(len, &work));
1170e5c89e4eSSatish Balay 
1171e5c89e4eSSatish Balay   /* get values for replaced variables */
11729566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_ARCH, &r[0]));
11739566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_DIR, &r[1]));
11749566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(PETSC_LIB_DIR, &r[2]));
11759566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(DISPLAY_LENGTH, &r[3]));
11769566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[4]));
11779566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[5]));
11789566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(USER_LENGTH, &r[6]));
11799566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(HOST_LENGTH, &r[7]));
11809566063dSJacob Faibussowitsch   PetscCall(PetscGetDisplay(r[3], DISPLAY_LENGTH));
11819566063dSJacob Faibussowitsch   PetscCall(PetscGetHomeDirectory(r[4], PETSC_MAX_PATH_LEN));
11829566063dSJacob Faibussowitsch   PetscCall(PetscGetWorkingDirectory(r[5], PETSC_MAX_PATH_LEN));
11839566063dSJacob Faibussowitsch   PetscCall(PetscGetUserName(r[6], USER_LENGTH));
11849566063dSJacob Faibussowitsch   PetscCall(PetscGetHostName(r[7], HOST_LENGTH));
1185487e5849SBarry Smith 
1186487e5849SBarry Smith   /* replace that are in environment */
11879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetenv(comm, "PETSC_LIB_DIR", env, sizeof(env), &flag));
1188487e5849SBarry Smith   if (flag) {
11899566063dSJacob Faibussowitsch     PetscCall(PetscFree(r[2]));
11909566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(env, &r[2]));
1191487e5849SBarry Smith   }
1192e5c89e4eSSatish Balay 
1193e5c89e4eSSatish Balay   /* replace the requested strings */
11949566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(b, a, len));
1195e5c89e4eSSatish Balay   while (s[i]) {
11969566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(s[i], &l));
11979566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(b, s[i], &par));
1198e5c89e4eSSatish Balay     while (par) {
1199e5c89e4eSSatish Balay       *par = 0;
1200e5c89e4eSSatish Balay       par += l;
1201e5c89e4eSSatish Balay 
12029566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(b, &l1));
12039566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(r[i], &l2));
12049566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(par, &l3));
1205cc73adaaSBarry Smith       PetscCheck(l1 + l2 + l3 < len, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "b len is not long enough to hold new values");
12069566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(work, b, len));
12079566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(work, r[i], len));
12089566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(work, par, len));
12099566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(b, work, len));
12109566063dSJacob Faibussowitsch       PetscCall(PetscStrstr(b, s[i], &par));
1211e5c89e4eSSatish Balay     }
1212e5c89e4eSSatish Balay     i++;
1213e5c89e4eSSatish Balay   }
1214487e5849SBarry Smith   i = 0;
1215487e5849SBarry Smith   while (r[i]) {
1216e5c89e4eSSatish Balay     tfree = (char *)r[i];
12179566063dSJacob Faibussowitsch     PetscCall(PetscFree(tfree));
1218487e5849SBarry Smith     i++;
1219e5c89e4eSSatish Balay   }
1220e5c89e4eSSatish Balay 
1221e5c89e4eSSatish Balay   /* look for any other ${xxx} strings to replace from environmental variables */
12229566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(b, "${", &par));
1223e5c89e4eSSatish Balay   while (par) {
1224e5c89e4eSSatish Balay     *par = 0;
1225e5c89e4eSSatish Balay     par += 2;
12269566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(work, b, len));
12279566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(par, "}", &epar));
1228e5c89e4eSSatish Balay     *epar = 0;
1229e5c89e4eSSatish Balay     epar += 1;
12309566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetenv(comm, par, env, sizeof(env), &flag));
123128b400f6SJacob Faibussowitsch     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Substitution string ${%s} not found as environmental variable", par);
12329566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(work, env, len));
12339566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(work, epar, len));
12349566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(b, work, len));
12359566063dSJacob Faibussowitsch     PetscCall(PetscStrstr(b, "${", &par));
1236e5c89e4eSSatish Balay   }
12379566063dSJacob Faibussowitsch   PetscCall(PetscFree(work));
12389566063dSJacob Faibussowitsch   if (aa == b) PetscCall(PetscFree(a));
1239e5c89e4eSSatish Balay   PetscFunctionReturn(0);
1240e5c89e4eSSatish Balay }
1241e5c89e4eSSatish Balay 
1242a53986e1SJed Brown /*@C
1243a53986e1SJed Brown    PetscEListFind - searches list of strings for given string, using case insensitive matching
1244e5c89e4eSSatish Balay 
1245a53986e1SJed Brown    Not Collective
1246a53986e1SJed Brown 
1247a53986e1SJed Brown    Input Parameters:
1248a53986e1SJed Brown +  n - number of strings in
1249a53986e1SJed Brown .  list - list of strings to search
1250a53986e1SJed Brown -  str - string to look for, empty string "" accepts default (first entry in list)
1251a53986e1SJed Brown 
1252a53986e1SJed Brown    Output Parameters:
1253a53986e1SJed Brown +  value - index of matching string (if found)
1254a53986e1SJed Brown -  found - boolean indicating whether string was found (can be NULL)
1255a53986e1SJed Brown 
1256811af0c4SBarry Smith    Fortran Note:
1257a53986e1SJed Brown    Not for use in Fortran
1258a53986e1SJed Brown 
1259a53986e1SJed Brown    Level: advanced
1260811af0c4SBarry Smith 
1261811af0c4SBarry Smith .seealso: `PetscEnumFind()`
1262a53986e1SJed Brown @*/
1263d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found)
1264d71ae5a4SJacob Faibussowitsch {
1265a53986e1SJed Brown   PetscFunctionBegin;
12665f80ce2aSJacob Faibussowitsch   if (found) {
12675f80ce2aSJacob Faibussowitsch     PetscValidBoolPointer(found, 5);
12685f80ce2aSJacob Faibussowitsch     *found = PETSC_FALSE;
12695f80ce2aSJacob Faibussowitsch   }
12705f80ce2aSJacob Faibussowitsch   for (PetscInt i = 0; i < n; ++i) {
12715f80ce2aSJacob Faibussowitsch     PetscBool matched;
12725f80ce2aSJacob Faibussowitsch 
12739566063dSJacob Faibussowitsch     PetscCall(PetscStrcasecmp(str, list[i], &matched));
1274a53986e1SJed Brown     if (matched || !str[0]) {
1275a53986e1SJed Brown       if (found) *found = PETSC_TRUE;
1276a53986e1SJed Brown       *value = i;
1277a53986e1SJed Brown       break;
1278a53986e1SJed Brown     }
1279a53986e1SJed Brown   }
1280a53986e1SJed Brown   PetscFunctionReturn(0);
1281a53986e1SJed Brown }
1282a53986e1SJed Brown 
1283a53986e1SJed Brown /*@C
12848e81d068SLisandro Dalcin    PetscEnumFind - searches enum list of strings for given string, using case insensitive matching
1285a53986e1SJed Brown 
1286a53986e1SJed Brown    Not Collective
1287a53986e1SJed Brown 
1288a53986e1SJed Brown    Input Parameters:
1289a53986e1SJed Brown +  enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL
1290a53986e1SJed Brown -  str - string to look for
1291a53986e1SJed Brown 
1292a53986e1SJed Brown    Output Parameters:
1293a53986e1SJed Brown +  value - index of matching string (if found)
1294a53986e1SJed Brown -  found - boolean indicating whether string was found (can be NULL)
1295a53986e1SJed Brown 
1296811af0c4SBarry Smith    Fortran Note:
1297a53986e1SJed Brown    Not for use in Fortran
1298a53986e1SJed Brown 
1299a53986e1SJed Brown    Level: advanced
1300811af0c4SBarry Smith 
1301811af0c4SBarry Smith .seealso: `PetscEListFind()`
1302a53986e1SJed Brown @*/
1303d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found)
1304d71ae5a4SJacob Faibussowitsch {
1305d05ba7d2SLisandro Dalcin   PetscInt  n = 0, evalue;
1306a53986e1SJed Brown   PetscBool efound;
1307a53986e1SJed Brown 
1308a53986e1SJed Brown   PetscFunctionBegin;
13095f80ce2aSJacob Faibussowitsch   PetscValidPointer(enumlist, 1);
13105f80ce2aSJacob 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");
13115f80ce2aSJacob Faibussowitsch   PetscCheck(n >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
1312a53986e1SJed Brown   n -= 3; /* drop enum name, prefix, and null termination */
13139566063dSJacob Faibussowitsch   PetscCall(PetscEListFind(n, enumlist, str, &evalue, &efound));
13145f80ce2aSJacob Faibussowitsch   if (efound) {
13155f80ce2aSJacob Faibussowitsch     PetscValidPointer(value, 3);
13165f80ce2aSJacob Faibussowitsch     *value = (PetscEnum)evalue;
13175f80ce2aSJacob Faibussowitsch   }
13185f80ce2aSJacob Faibussowitsch   if (found) {
13195f80ce2aSJacob Faibussowitsch     PetscValidBoolPointer(found, 4);
13205f80ce2aSJacob Faibussowitsch     *found = efound;
13215f80ce2aSJacob Faibussowitsch   }
1322a53986e1SJed Brown   PetscFunctionReturn(0);
1323a53986e1SJed Brown }
1324660278c0SBarry Smith 
1325660278c0SBarry Smith /*@C
1326660278c0SBarry Smith   PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled.
1327660278c0SBarry Smith 
1328660278c0SBarry Smith   Not collective
1329660278c0SBarry Smith 
1330660278c0SBarry Smith   Input Parameter:
1331660278c0SBarry Smith . file - the file name
1332660278c0SBarry Smith 
1333660278c0SBarry Smith   Note:
1334660278c0SBarry Smith   PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems
1335660278c0SBarry Smith   so that comparisons of output between runs are easy to make.
1336660278c0SBarry Smith 
1337660278c0SBarry Smith   This mode is used for all tests in the test harness, it applies to both debug and optimized builds.
1338660278c0SBarry Smith 
1339660278c0SBarry Smith   Use the option -petsc_ci to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for
1340660278c0SBarry Smith   all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness.
1341660278c0SBarry Smith 
1342660278c0SBarry Smith   Always uses the Unix / as the file separate even on Microsoft Windows systems
1343660278c0SBarry Smith 
1344660278c0SBarry Smith   The option -petsc_ci_portable_error_output attempts to output the same error messages on all systems for the test harness.
1345660278c0SBarry Smith   In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc
1346660278c0SBarry 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
1347660278c0SBarry Smith   harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test
1348660278c0SBarry Smith   harness in the args: argument for specific examples. It will not neccessarily produce portable output if different errors
1349660278c0SBarry Smith   (or no errors) occur on a subset of the MPI ranks.
1350660278c0SBarry Smith 
1351660278c0SBarry Smith   Level: developer
1352660278c0SBarry Smith 
1353660278c0SBarry Smith .seealso: `PetscCILinenumber()`
1354660278c0SBarry Smith @*/
1355d71ae5a4SJacob Faibussowitsch const char *PetscCIFilename(const char *file)
1356d71ae5a4SJacob Faibussowitsch {
1357660278c0SBarry Smith   if (!PetscCIEnabledPortableErrorOutput) return file;
1358660278c0SBarry Smith   return PetscBasename(file);
1359660278c0SBarry Smith }
1360660278c0SBarry Smith 
1361660278c0SBarry Smith /*@C
1362811af0c4SBarry Smith   PetscCILinenumber - returns a line number except if `PetscCIEnablePortableErrorOutput` is set when it returns 0
1363660278c0SBarry Smith 
1364660278c0SBarry Smith   Not collective
1365660278c0SBarry Smith 
1366660278c0SBarry Smith   Input Parameter:
1367660278c0SBarry Smith . linenumber - the initial line number
1368660278c0SBarry Smith 
1369660278c0SBarry Smith   Note:
1370660278c0SBarry Smith   See `PetscCIFilename()` for details on usage
1371660278c0SBarry Smith 
1372660278c0SBarry Smith   Level: developer
1373660278c0SBarry Smith 
1374660278c0SBarry Smith .seealso: `PetscCIFilename()`
1375660278c0SBarry Smith @*/
1376d71ae5a4SJacob Faibussowitsch int PetscCILinenumber(int linenumber)
1377d71ae5a4SJacob Faibussowitsch {
1378660278c0SBarry Smith   if (!PetscCIEnabledPortableErrorOutput) return linenumber;
1379660278c0SBarry Smith   return 0;
1380660278c0SBarry Smith }
1381