Date: 2025-03-29T05:58:46+00:00

Actual source code: str.c

      1: /*
      2:     We define the string operations here. The reason we just do not use
      3:   the standard string routines in the PETSc code is that on some machines
      4:   they are broken or have the wrong prototypes.
      5: */
      6: #include <petsc/private/petscimpl.h>
      7: #if defined(PETSC_HAVE_STRINGS_H)
      8:   #include <strings.h> /* strcasecmp */
      9: #endif

     11: /*@C
     12:   PetscStrToArray - Separates a string by a character (for example ' ' or '\n') and creates an array of strings

     14:   Not Collective; No Fortran Support

     16:   Input Parameters:
     17: + s  - pointer to string
     18: - sp - separator character

     20:   Output Parameters:
     21: + argc - the number of entries in `args`
     22: - args - an array of the entries with a `NULL` at the end

     24:   Level: intermediate

     26:   Note:
     27:   This may be called before `PetscInitialize()` or after `PetscFinalize()`

     29:   Developer Notes:
     30:   Uses raw `malloc()` and does not call error handlers since this may be used before PETSc is initialized.

     32:   Used to generate `argc`, `args` arguments passed to `MPI_Init()`

     34: .seealso: `PetscStrToArrayDestroy()`, `PetscToken`, `PetscTokenCreate()`
     35: @*/
     36: PetscErrorCode PetscStrToArray(const char s[], char sp, int *argc, char ***args)
     37: {
     38:   int       n, i, j, *lens, cnt = 0;
     39:   PetscBool flg = PETSC_FALSE;

     41:   if (!s) n = 0;
     42:   else n = (int)strlen(s);
     43:   *argc = 0;
     44:   *args = NULL;
     45:   for (; n > 0; n--) { /* remove separator chars at the end - and will empty the string if all chars are separator chars */
     46:     if (s[n - 1] != sp) break;
     47:   }
     48:   if (!n) return PETSC_SUCCESS;
     49:   for (i = 0; i < n; i++) {
     50:     if (s[i] != sp) break;
     51:   }
     52:   for (; i < n + 1; i++) {
     53:     if ((s[i] == sp || s[i] == 0) && !flg) {
     54:       flg = PETSC_TRUE;
     55:       (*argc)++;
     56:     } else if (s[i] != sp) {
     57:       flg = PETSC_FALSE;
     58:     }
     59:   }
     60:   (*args) = (char **)malloc(((*argc) + 1) * sizeof(char *));
     61:   if (!*args) return PETSC_ERR_MEM;
     62:   lens = (int *)malloc(((*argc) + 1) * sizeof(int));
     63:   if (!lens) return PETSC_ERR_MEM;
     64:   for (i = 0; i < *argc; i++) lens[i] = 0;

     66:   *argc = 0;
     67:   for (i = 0; i < n; i++) {
     68:     if (s[i] != sp) break;
     69:   }
     70:   for (; i < n + 1; i++) {
     71:     if ((s[i] == sp || s[i] == 0) && !flg) {
     72:       flg = PETSC_TRUE;
     73:       (*argc)++;
     74:     } else if (s[i] != sp) {
     75:       lens[*argc]++;
     76:       flg = PETSC_FALSE;
     77:     }
     78:   }

     80:   for (i = 0; i < *argc; i++) {
     81:     (*args)[i] = (char *)malloc((lens[i] + 1) * sizeof(char));
     82:     if (!(*args)[i]) {
     83:       free(lens);
     84:       for (j = 0; j < i; j++) free((*args)[j]);
     85:       free(*args);
     86:       return PETSC_ERR_MEM;
     87:     }
     88:   }
     89:   free(lens);
     90:   (*args)[*argc] = NULL;

     92:   *argc = 0;
     93:   for (i = 0; i < n; i++) {
     94:     if (s[i] != sp) break;
     95:   }
     96:   for (; i < n + 1; i++) {
     97:     if ((s[i] == sp || s[i] == 0) && !flg) {
     98:       flg                   = PETSC_TRUE;
     99:       (*args)[*argc][cnt++] = 0;
    100:       (*argc)++;
    101:       cnt = 0;
    102:     } else if (s[i] != sp && s[i] != 0) {
    103:       (*args)[*argc][cnt++] = s[i];
    104:       flg                   = PETSC_FALSE;
    105:     }
    106:   }
    107:   return PETSC_SUCCESS;
    108: }

    110: /*@C
    111:   PetscStrToArrayDestroy - Frees array created with `PetscStrToArray()`.

    113:   Not Collective; No Fortran Support

    115:   Output Parameters:
    116: + argc - the number of arguments
    117: - args - the array of arguments

    119:   Level: intermediate

    121:   Note:
    122:   This may be called before `PetscInitialize()` or after `PetscFinalize()`

    124: .seealso: `PetscStrToArray()`
    125: @*/
    126: PetscErrorCode PetscStrToArrayDestroy(int argc, char **args)
    127: {
    128:   for (int i = 0; i < argc; ++i) free(args[i]);
    129:   if (args) free(args);
    130:   return PETSC_SUCCESS;
    131: }

    133: /*@C
    134:   PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings

    136:   Not Collective; No Fortran Support

    138:   Input Parameter:
    139: . list - pointer to array of strings (final string is a `NULL`)

    141:   Output Parameter:
    142: . t - the copied array string

    144:   Level: intermediate

    146:   Note:
    147:   Use `PetscStrArrayDestroy()` to free the memory.

    149: .seealso: `PetscStrallocpy()`, `PetscStrArrayDestroy()`, `PetscStrNArrayallocpy()`
    150: @*/
    151: PetscErrorCode PetscStrArrayallocpy(const char *const *list, char ***t)
    152: {
    153:   PetscInt n = 0;

    155:   PetscFunctionBegin;
    156:   while (list[n++]);
    157:   PetscCall(PetscMalloc1(n + 1, t));
    158:   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
    159:   (*t)[n] = NULL;
    160:   PetscFunctionReturn(PETSC_SUCCESS);
    161: }

    163: /*@C
    164:   PetscStrArrayDestroy - Frees array of strings created with `PetscStrArrayallocpy()`.

    166:   Not Collective; No Fortran Support

    168:   Output Parameter:
    169: . list - array of strings

    171:   Level: intermediate

    173: .seealso: `PetscStrArrayallocpy()`
    174: @*/
    175: PetscErrorCode PetscStrArrayDestroy(char ***list)
    176: {
    177:   PetscInt n = 0;

    179:   PetscFunctionBegin;
    180:   if (!*list) PetscFunctionReturn(PETSC_SUCCESS);
    181:   while ((*list)[n]) {
    182:     PetscCall(PetscFree((*list)[n]));
    183:     ++n;
    184:   }
    185:   PetscCall(PetscFree(*list));
    186:   PetscFunctionReturn(PETSC_SUCCESS);
    187: }

    189: /*@C
    190:   PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings

    192:   Not Collective; No Fortran Support

    194:   Input Parameters:
    195: + n    - the number of string entries
    196: - list - pointer to array of strings

    198:   Output Parameter:
    199: . t - the copied array string

    201:   Level: intermediate

    203:   Note:
    204:   Use `PetscStrNArrayDestroy()` to free the memory.

    206: .seealso: `PetscStrallocpy()`, `PetscStrArrayallocpy()`, `PetscStrNArrayDestroy()`
    207: @*/
    208: PetscErrorCode PetscStrNArrayallocpy(PetscInt n, const char *const *list, char ***t)
    209: {
    210:   PetscFunctionBegin;
    211:   PetscCall(PetscMalloc1(n, t));
    212:   for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i));
    213:   PetscFunctionReturn(PETSC_SUCCESS);
    214: }

    216: /*@C
    217:   PetscStrNArrayDestroy - Frees array of strings created with `PetscStrNArrayallocpy()`.

    219:   Not Collective; No Fortran Support

    221:   Output Parameters:
    222: + n    - number of string entries
    223: - list - array of strings

    225:   Level: intermediate

    227: .seealso: `PetscStrNArrayallocpy()`, `PetscStrArrayallocpy()`
    228: @*/
    229: PetscErrorCode PetscStrNArrayDestroy(PetscInt n, char ***list)
    230: {
    231:   PetscFunctionBegin;
    232:   if (!*list) PetscFunctionReturn(PETSC_SUCCESS);
    233:   for (PetscInt i = 0; i < n; i++) PetscCall(PetscFree((*list)[i]));
    234:   PetscCall(PetscFree(*list));
    235:   PetscFunctionReturn(PETSC_SUCCESS);
    236: }

    238: /*@C
    239:   PetscBasename - returns a pointer to the last entry of a / or \ separated directory path

    241:   Not Collective; No Fortran Support

    243:   Input Parameter:
    244: . a - pointer to string

    246:   Level: intermediate

    248: .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`, `PetscStrrchr()`, `PetscStrcmp()`, `PetscStrstr()`,
    249:           `PetscTokenCreate()`, `PetscStrToArray()`, `PetscStrInList()`
    250: @*/
    251: const char *PetscBasename(const char a[])
    252: {
    253:   const char *ptr = NULL;

    255:   (void)PetscStrrchr(a, '/', (char **)&ptr);
    256:   if (ptr == a) {
    257:     if (PetscStrrchr(a, '\\', (char **)&ptr)) ptr = NULL;
    258:   }
    259:   return ptr;
    260: }

    262: /*@C
    263:   PetscStrcasecmp - Returns true if the two strings are the same
    264:   except possibly for case.

    266:   Not Collective; No Fortran Support

    268:   Input Parameters:
    269: + a - pointer to first string
    270: - b - pointer to second string

    272:   Output Parameter:
    273: . t - if the two strings are the same

    275:   Level: intermediate

    277:   Note:
    278:   `NULL` arguments are ok

    280: .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrgrt()`
    281: @*/
    282: PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t)
    283: {
    284:   int c;

    286:   PetscFunctionBegin;
    287:   PetscAssertPointer(t, 3);
    288:   if (!a && !b) c = 0;
    289:   else if (!a || !b) c = 1;
    290: #if defined(PETSC_HAVE_STRCASECMP)
    291:   else c = strcasecmp(a, b);
    292: #elif defined(PETSC_HAVE_STRICMP)
    293:   else c = stricmp(a, b);
    294: #else
    295:   else {
    296:     char *aa, *bb;

    298:     PetscCall(PetscStrallocpy(a, &aa));
    299:     PetscCall(PetscStrallocpy(b, &bb));
    300:     PetscCall(PetscStrtolower(aa));
    301:     PetscCall(PetscStrtolower(bb));
    302:     PetscCall(PetscStrcmp(aa, bb, t));
    303:     PetscCall(PetscFree(aa));
    304:     PetscCall(PetscFree(bb));
    305:     PetscFunctionReturn(PETSC_SUCCESS);
    306:   }
    307: #endif
    308:   *t = c ? PETSC_FALSE : PETSC_TRUE;
    309:   PetscFunctionReturn(PETSC_SUCCESS);
    310: }

    312: /*@C
    313:   PetscStrendswithwhich - Determines if a string ends with one of several possible strings

    315:   Not Collective; No Fortran Support

    317:   Input Parameters:
    318: + a  - pointer to string
    319: - bs - strings to end with (last entry must be `NULL`)

    321:   Output Parameter:
    322: . cnt - the index of the string it ends with or the index of `NULL`

    324:   Level: intermediate

    326: .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`,
    327:           `PetscStrncmp()`, `PetscStrlen()`, `PetscStrcmp()`
    328: @*/
    329: PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt)
    330: {
    331:   PetscFunctionBegin;
    332:   PetscAssertPointer(bs, 2);
    333:   PetscAssertPointer(cnt, 3);
    334:   *cnt = 0;
    335:   while (bs[*cnt]) {
    336:     PetscBool flg;

    338:     PetscCall(PetscStrendswith(a, bs[*cnt], &flg));
    339:     if (flg) PetscFunctionReturn(PETSC_SUCCESS);
    340:     ++(*cnt);
    341:   }
    342:   PetscFunctionReturn(PETSC_SUCCESS);
    343: }

    345: struct _n_PetscToken {
    346:   char  token;
    347:   char *array;
    348:   char *current;
    349: };

    351: /*@C
    352:   PetscTokenFind - Locates next "token" in a `PetscToken`

    354:   Not Collective; No Fortran Support

    356:   Input Parameter:
    357: . a - pointer to token

    359:   Output Parameter:
    360: . result - location of occurrence, `NULL` if not found

    362:   Level: intermediate

    364:   Notes:
    365:   Treats all characters etc. inside a double quote "
    366:   as a single token.

    368:   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
    369:   second will return a `NULL` terminated y

    371:   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

    373:   Do not change or free the value of `result`

    375: .seealso: `PetscToken`, `PetscTokenCreate()`, `PetscTokenDestroy()`
    376: @*/
    377: PetscErrorCode PetscTokenFind(PetscToken a, const char *result[])
    378: {
    379:   char *ptr, token;

    381:   PetscFunctionBegin;
    382:   PetscAssertPointer(a, 1);
    383:   PetscAssertPointer(result, 2);
    384:   *result = ptr = a->current;
    385:   if (ptr && !*ptr) {
    386:     *result = NULL;
    387:     PetscFunctionReturn(PETSC_SUCCESS);
    388:   }
    389:   token = a->token;
    390:   if (ptr && (*ptr == '"')) {
    391:     token = '"';
    392:     (*result)++;
    393:     ptr++;
    394:   }
    395:   while (ptr) {
    396:     if (*ptr == token) {
    397:       *ptr++ = 0;
    398:       while (*ptr == a->token) ptr++;
    399:       a->current = ptr;
    400:       break;
    401:     }
    402:     if (!*ptr) {
    403:       a->current = NULL;
    404:       break;
    405:     }
    406:     ptr++;
    407:   }
    408:   PetscFunctionReturn(PETSC_SUCCESS);
    409: }

    411: /*@C
    412:   PetscTokenCreate - Creates a `PetscToken` used to find tokens in a string

    414:   Not Collective; No Fortran Support

    416:   Input Parameters:
    417: + a - the string to look in
    418: - b - the separator character

    420:   Output Parameter:
    421: . t - the token object

    423:   Level: intermediate

    425:   Note:
    426:   This version is different from the system version in that
    427:   it allows you to pass a read-only string into the function.

    429: .seealso: `PetscToken`, `PetscTokenFind()`, `PetscTokenDestroy()`
    430: @*/
    431: PetscErrorCode PetscTokenCreate(const char a[], char b, PetscToken *t)
    432: {
    433:   PetscFunctionBegin;
    434:   PetscAssertPointer(a, 1);
    435:   PetscAssertPointer(t, 3);
    436:   PetscCall(PetscNew(t));
    437:   PetscCall(PetscStrallocpy(a, &(*t)->array));

    439:   (*t)->current = (*t)->array;
    440:   (*t)->token   = b;
    441:   PetscFunctionReturn(PETSC_SUCCESS);
    442: }

    444: /*@C
    445:   PetscTokenDestroy - Destroys a `PetscToken`

    447:   Not Collective; No Fortran Support

    449:   Input Parameter:
    450: . a - pointer to token

    452:   Level: intermediate

    454: .seealso: `PetscToken`, `PetscTokenCreate()`, `PetscTokenFind()`
    455: @*/
    456: PetscErrorCode PetscTokenDestroy(PetscToken *a)
    457: {
    458:   PetscFunctionBegin;
    459:   if (!*a) PetscFunctionReturn(PETSC_SUCCESS);
    460:   PetscCall(PetscFree((*a)->array));
    461:   PetscCall(PetscFree(*a));
    462:   PetscFunctionReturn(PETSC_SUCCESS);
    463: }

    465: /*@C
    466:   PetscStrInList - search for a string in character-delimited list

    468:   Not Collective; No Fortran Support

    470:   Input Parameters:
    471: + str  - the string to look for
    472: . list - the list to search in
    473: - sep  - the separator character

    475:   Output Parameter:
    476: . found - whether `str` is in `list`

    478:   Level: intermediate

    480: .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()`
    481: @*/
    482: PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found)
    483: {
    484:   PetscToken  token;
    485:   const char *item;

    487:   PetscFunctionBegin;
    488:   PetscAssertPointer(found, 4);
    489:   *found = PETSC_FALSE;
    490:   PetscCall(PetscTokenCreate(list, sep, &token));
    491:   PetscCall(PetscTokenFind(token, &item));
    492:   while (item) {
    493:     PetscCall(PetscStrcmp(str, item, found));
    494:     if (*found) break;
    495:     PetscCall(PetscTokenFind(token, &item));
    496:   }
    497:   PetscCall(PetscTokenDestroy(&token));
    498:   PetscFunctionReturn(PETSC_SUCCESS);
    499: }

    501: /*@C
    502:   PetscGetPetscDir - Gets the directory PETSc is installed in

    504:   Not Collective; No Fortran Support

    506:   Output Parameter:
    507: . dir - the directory

    509:   Level: developer

    511: .seealso: `PetscGetArchType()`
    512: @*/
    513: PetscErrorCode PetscGetPetscDir(const char *dir[])
    514: {
    515:   PetscFunctionBegin;
    516:   PetscAssertPointer(dir, 1);
    517:   *dir = PETSC_DIR;
    518:   PetscFunctionReturn(PETSC_SUCCESS);
    519: }

    521: /*@C
    522:   PetscStrreplace - Replaces substrings in string with other substrings

    524:   Not Collective; No Fortran Support

    526:   Input Parameters:
    527: + comm - `MPI_Comm` of processors that are processing the string
    528: . aa   - the string to look in
    529: . b    - the resulting copy of a with replaced strings (`b` can be the same as `a`)
    530: - len  - the length of `b`

    532:   Level: developer

    534:   Notes:
    535:   Replaces
    536: .vb
    537:     ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${DISPLAY},
    538:     ${HOMEDIRECTORY}, ${WORKINGDIRECTORY}, ${USERNAME}, ${HOSTNAME}, ${PETSC_MAKE}
    539: .ve
    540:   with appropriate values as well as any environmental variables.

    542:   `PETSC_LIB_DIR` uses the environmental variable if it exists. `PETSC_ARCH` and `PETSC_DIR` use what
    543:   PETSc was built with and do not use environmental variables.

    545: .seealso: `PetscStrcmp()`
    546: @*/
    547: PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len)
    548: {
    549:   int           i = 0;
    550:   size_t        l, l1, l2, l3;
    551:   char         *work, *par, *epar = NULL, env[1024], *tfree, *a = (char *)aa;
    552:   const char   *s[] = {"${PETSC_ARCH}", "${PETSC_DIR}", "${PETSC_LIB_DIR}", "${DISPLAY}", "${HOMEDIRECTORY}", "${WORKINGDIRECTORY}", "${USERNAME}", "${HOSTNAME}", "${PETSC_MAKE}", NULL};
    553:   char         *r[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
    554:   PetscBool     flag;
    555:   static size_t DISPLAY_LENGTH = 265, USER_LENGTH = 256, HOST_LENGTH = 256;

    557:   PetscFunctionBegin;
    558:   PetscAssertPointer(aa, 2);
    559:   PetscAssertPointer(b, 3);
    560:   if (aa == b) PetscCall(PetscStrallocpy(aa, &a));
    561:   PetscCall(PetscMalloc1(len, &work));

    563:   /* get values for replaced variables */
    564:   PetscCall(PetscStrallocpy(PETSC_ARCH, &r[0]));
    565:   PetscCall(PetscStrallocpy(PETSC_DIR, &r[1]));
    566:   PetscCall(PetscStrallocpy(PETSC_LIB_DIR, &r[2]));
    567:   PetscCall(PetscMalloc1(DISPLAY_LENGTH, &r[3]));
    568:   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[4]));
    569:   PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[5]));
    570:   PetscCall(PetscMalloc1(USER_LENGTH, &r[6]));
    571:   PetscCall(PetscMalloc1(HOST_LENGTH, &r[7]));
    572:   PetscCall(PetscGetDisplay(r[3], DISPLAY_LENGTH));
    573:   PetscCall(PetscGetHomeDirectory(r[4], PETSC_MAX_PATH_LEN));
    574:   PetscCall(PetscGetWorkingDirectory(r[5], PETSC_MAX_PATH_LEN));
    575:   PetscCall(PetscGetUserName(r[6], USER_LENGTH));
    576:   PetscCall(PetscGetHostName(r[7], HOST_LENGTH));
    577:   PetscCall(PetscStrallocpy(PETSC_OMAKE, &r[8]));

    579:   /* replace that are in environment */
    580:   PetscCall(PetscOptionsGetenv(comm, "PETSC_LIB_DIR", env, sizeof(env), &flag));
    581:   if (flag) {
    582:     PetscCall(PetscFree(r[2]));
    583:     PetscCall(PetscStrallocpy(env, &r[2]));
    584:   }

    586:   /* replace the requested strings */
    587:   PetscCall(PetscStrncpy(b, a, len));
    588:   while (s[i]) {
    589:     PetscCall(PetscStrlen(s[i], &l));
    590:     PetscCall(PetscStrstr(b, s[i], &par));
    591:     while (par) {
    592:       *par = 0;
    593:       par += l;

    595:       PetscCall(PetscStrlen(b, &l1));
    596:       PetscCall(PetscStrlen(r[i], &l2));
    597:       PetscCall(PetscStrlen(par, &l3));
    598:       PetscCheck(l1 + l2 + l3 < len, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "b len is not long enough to hold new values");
    599:       PetscCall(PetscStrncpy(work, b, len));
    600:       PetscCall(PetscStrlcat(work, r[i], len));
    601:       PetscCall(PetscStrlcat(work, par, len));
    602:       PetscCall(PetscStrncpy(b, work, len));
    603:       PetscCall(PetscStrstr(b, s[i], &par));
    604:     }
    605:     i++;
    606:   }
    607:   i = 0;
    608:   while (r[i]) {
    609:     tfree = r[i];
    610:     PetscCall(PetscFree(tfree));
    611:     i++;
    612:   }

    614:   /* look for any other ${xxx} strings to replace from environmental variables */
    615:   PetscCall(PetscStrstr(b, "${", &par));
    616:   while (par) {
    617:     *par = 0;
    618:     par += 2;
    619:     PetscCall(PetscStrncpy(work, b, len));
    620:     PetscCall(PetscStrstr(par, "}", &epar));
    621:     *epar = 0;
    622:     epar += 1;
    623:     PetscCall(PetscOptionsGetenv(comm, par, env, sizeof(env), &flag));
    624:     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Substitution string ${%s} not found as environmental variable", par);
    625:     PetscCall(PetscStrlcat(work, env, len));
    626:     PetscCall(PetscStrlcat(work, epar, len));
    627:     PetscCall(PetscStrncpy(b, work, len));
    628:     PetscCall(PetscStrstr(b, "${", &par));
    629:   }
    630:   PetscCall(PetscFree(work));
    631:   if (aa == b) PetscCall(PetscFree(a));
    632:   PetscFunctionReturn(PETSC_SUCCESS);
    633: }

    635: /*@C
    636:   PetscStrcmpAny - Determines whether a string matches any of a list of strings.

    638:   Not Collective, No Fortran Support

    640:   Input Parameters:
    641: + src - pointer to input the string
    642: - cmp - list of non-null and non-empty strings to be compared against, pass the empty string "" to terminate the list

    644:   Output Parameter:
    645: . match - `PETSC_TRUE` if the input string matches any in the list, else `PETSC_FALSE`

    647:   Level: intermediate

    649: .seealso: `PetscStrcmp()`
    650: @*/
    651: PetscErrorCode PetscStrcmpAny(const char src[], PetscBool *match, const char cmp[], ...)
    652: {
    653:   va_list Argp;

    655:   PetscFunctionBegin;
    656:   PetscAssertPointer(match, 2);
    657:   *match = PETSC_FALSE;
    658:   if (!src) PetscFunctionReturn(PETSC_SUCCESS);
    659:   va_start(Argp, cmp);
    660:   while (cmp && cmp[0]) {
    661:     PetscBool found;
    662:     PetscCall(PetscStrcmp(src, cmp, &found));
    663:     if (found) {
    664:       *match = PETSC_TRUE;
    665:       break;
    666:     }
    667:     cmp = va_arg(Argp, const char *);
    668:   }
    669:   va_end(Argp);
    670:   PetscFunctionReturn(PETSC_SUCCESS);
    671: }

    673: /*@C
    674:   PetscEListFind - searches list of strings for given string, using case insensitive matching

    676:   Not Collective; No Fortran Support

    678:   Input Parameters:
    679: + n    - number of strings in
    680: . list - list of strings to search
    681: - str  - string to look for, empty string "" accepts default (first entry in list)

    683:   Output Parameters:
    684: + value - index of matching string (if found)
    685: - found - boolean indicating whether string was found (can be `NULL`)

    687:   Level: developer

    689: .seealso: `PetscEnumFind()`
    690: @*/
    691: PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found)
    692: {
    693:   PetscFunctionBegin;
    694:   if (found) {
    695:     PetscAssertPointer(found, 5);
    696:     *found = PETSC_FALSE;
    697:   }
    698:   for (PetscInt i = 0; i < n; ++i) {
    699:     PetscBool matched;

    701:     PetscCall(PetscStrcasecmp(str, list[i], &matched));
    702:     if (matched || !str[0]) {
    703:       if (found) *found = PETSC_TRUE;
    704:       *value = i;
    705:       break;
    706:     }
    707:   }
    708:   PetscFunctionReturn(PETSC_SUCCESS);
    709: }

    711: /*@C
    712:   PetscEnumFind - searches enum list of strings for given string, using case insensitive matching

    714:   Not Collective; No Fortran Support

    716:   Input Parameters:
    717: + enumlist - list of strings to search, followed by enum name, then enum prefix, then `NULL`
    718: - str      - string to look for

    720:   Output Parameters:
    721: + value - index of matching string (if found)
    722: - found - boolean indicating whether string was found (can be `NULL`)

    724:   Level: advanced

    726: .seealso: `PetscEListFind()`
    727: @*/
    728: PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found)
    729: {
    730:   PetscInt  n = 0, evalue;
    731:   PetscBool efound;

    733:   PetscFunctionBegin;
    734:   PetscAssertPointer(enumlist, 1);
    735:   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");
    736:   PetscCheck(n >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
    737:   n -= 3; /* drop enum name, prefix, and null termination */
    738:   PetscCall(PetscEListFind(n, enumlist, str, &evalue, &efound));
    739:   if (efound) {
    740:     PetscAssertPointer(value, 3);
    741:     *value = (PetscEnum)evalue;
    742:   }
    743:   if (found) {
    744:     PetscAssertPointer(found, 4);
    745:     *found = efound;
    746:   }
    747:   PetscFunctionReturn(PETSC_SUCCESS);
    748: }

    750: /*@C
    751:   PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled.

    753:   Not Collective; No Fortran Support

    755:   Input Parameter:
    756: . file - the file name

    758:   Level: developer

    760:   Note:
    761:   PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems
    762:   so that comparisons of output between runs are easy to make.

    764:   This mode is used for all tests in the test harness, it applies to both debug and optimized builds.

    766:   Use the option `-petsc_ci` to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for
    767:   all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness.

    769:   Always uses the Unix / as the file separate even on Microsoft Windows systems

    771:   The option `-petsc_ci_portable_error_output` attempts to output the same error messages on all systems for the test harness.
    772:   In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc
    773:   error handling by the test harness. This options also causes PETSc to attempt to return an error code of 0 so that the test
    774:   harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test
    775:   harness in the args: argument for specific examples. It will not necessarily produce portable output if different errors
    776:   (or no errors) occur on a subset of the MPI ranks.

    778: .seealso: `PetscCILinenumber()`
    779: @*/
    780: const char *PetscCIFilename(const char *file)
    781: {
    782:   if (!PetscCIEnabledPortableErrorOutput) return file;
    783:   return PetscBasename(file);
    784: }

    786: /*@C
    787:   PetscCILinenumber - returns a line number except if `PetscCIEnablePortableErrorOutput` is set when it returns 0

    789:   Not Collective; No Fortran Support

    791:   Input Parameter:
    792: . linenumber - the initial line number

    794:   Level: developer

    796:   Note:
    797:   See `PetscCIFilename()` for details on usage

    799: .seealso: `PetscCIFilename()`
    800: @*/
    801: int PetscCILinenumber(int linenumber)
    802: {
    803:   if (!PetscCIEnabledPortableErrorOutput) return linenumber;
    804:   return 0;
    805: }

    807: /*@C
    808:   PetscStrcat - Concatenates a string onto a given string

    810:   Not Collective, No Fortran Support

    812:   Input Parameters:
    813: + s - string to be added to
    814: - t - pointer to string to be added to end

    816:   Level: deprecated (since 3.18.5)

    818:   Notes:
    819:   It is recommended you use `PetscStrlcat()` instead of this routine.

    821: .seealso: `PetscStrlcat()`
    822: @*/
    823: PetscErrorCode PetscStrcat(char s[], const char t[])
    824: {
    825:   PetscFunctionBegin;
    826:   if (!t) PetscFunctionReturn(PETSC_SUCCESS);
    827:   PetscAssertPointer(s, 1);
    828:   strcat(s, t);
    829:   PetscFunctionReturn(PETSC_SUCCESS);
    830: }

    832: /*@C
    833:   PetscStrcpy - Copies a string

    835:   Not Collective, No Fortran Support

    837:   Input Parameter:
    838: . t - pointer to string

    840:   Output Parameter:
    841: . s - the copied string

    843:   Level: deprecated (since 3.18.5)

    845:   Notes:
    846:   It is recommended you use `PetscStrncpy()` (equivalently `PetscArraycpy()` or
    847:   `PetscMemcpy()`) instead of this routine.

    849:   `NULL` strings returns a string starting with zero.

    851: .seealso: `PetscStrncpy()`
    852: @*/
    853: PetscErrorCode PetscStrcpy(char s[], const char t[])
    854: {
    855:   PetscFunctionBegin;
    856:   if (t) {
    857:     PetscAssertPointer(s, 1);
    858:     PetscAssertPointer(t, 2);
    859:     strcpy(s, t);
    860:   } else if (s) {
    861:     s[0] = '\0';
    862:   }
    863:   PetscFunctionReturn(PETSC_SUCCESS);
    864: }