Date: 2022-03-31T04:46:10+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.

      6: */
      7: #include <petsc/private/petscimpl.h>
      8: #if defined(PETSC_HAVE_STRINGS_H)
      9: #  include <strings.h>          /* strcasecmp */
     10: #endif

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

     15:    Not Collective

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

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

     25:    Level: intermediate

     27:    Notes:
     28:     this may be called before PetscInitialize() or after PetscFinalize()

     30:    Not for use in Fortran

     32:    Developer Notes:
     33:     Using raw malloc() and does not call error handlers since this may be used before PETSc is initialized. Used
     34:      to generate argc, args arguments passed to MPI_Init()

     36: .seealso: PetscStrToArrayDestroy(), PetscToken, PetscTokenCreate()

     38: @*/
     39: PetscErrorCode PetscStrToArray(const char s[], char sp, int *argc, char ***args)
     40: {
     41:   int       i,j,n,*lens,cnt = 0;
     42:   PetscBool flg = PETSC_FALSE;

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

     63:   *argc = 0;
     64:   for (i=0; i<n; i++) {
     65:     if (s[i] != sp) break;
     66:   }
     67:   for (;i<n+1; i++) {
     68:     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;}
     69:     else if (s[i] != sp) {lens[*argc]++;flg = PETSC_FALSE;}
     70:   }

     72:   for (i=0; i<*argc; i++) {
     73:     (*args)[i] = (char*) malloc((lens[i]+1)*sizeof(char));
     74:     if (!(*args)[i]) {
     75:       free(lens);
     76:       for (j=0; j<i; j++) free((*args)[j]);
     77:       free(*args);
     78:       return PETSC_ERR_MEM;
     79:     }
     80:   }
     81:   free(lens);
     82:   (*args)[*argc] = NULL;

     84:   *argc = 0;
     85:   for (i=0; i<n; i++) {
     86:     if (s[i] != sp) break;
     87:   }
     88:   for (;i<n+1; i++) {
     89:     if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*args)[*argc][cnt++] = 0; (*argc)++; cnt = 0;}
     90:     else if (s[i] != sp && s[i] != 0) {(*args)[*argc][cnt++] = s[i]; flg = PETSC_FALSE;}
     91:   }
     92:   return 0;
     93: }

     95: /*@C
     96:    PetscStrToArrayDestroy - Frees array created with PetscStrToArray().

     98:    Not Collective

    100:    Output Parameters:
    101: +  argc - the number of arguments
    102: -  args - the array of arguments

    104:    Level: intermediate

    106:    Notes:
    107:     This may be called before PetscInitialize() or after PetscFinalize()

    109:    Not for use in Fortran

    111: .seealso: PetscStrToArray()

    113: @*/
    114: PetscErrorCode PetscStrToArrayDestroy(int argc, char **args)
    115: {
    116:   for (int i = 0; i < argc; ++i) free(args[i]);
    117:   if (args) free(args);
    118:   return 0;
    119: }

    121: /*@C
    122:    PetscStrlen - Gets length of a string

    124:    Not Collective

    126:    Input Parameters:
    127: .  s - pointer to string

    129:    Output Parameter:
    130: .  len - length in bytes

    132:    Level: intermediate

    134:    Note:
    135:    This routine is analogous to strlen().

    137:    Null string returns a length of zero

    139:    Not for use in Fortran

    141: @*/
    142: PetscErrorCode PetscStrlen(const char s[], size_t *len)
    143: {
    144:   *len = s ? strlen(s) : 0;
    145:   return 0;
    146: }

    148: /*@C
    149:    PetscStrallocpy - Allocates space to hold a copy of a string then copies the string

    151:    Not Collective

    153:    Input Parameters:
    154: .  s - pointer to string

    156:    Output Parameter:
    157: .  t - the copied string

    159:    Level: intermediate

    161:    Note:
    162:       Null string returns a new null string

    164:       Not for use in Fortran

    166:       Warning: If t has previously been allocated then that memory is lost, you may need to PetscFree()
    167:       the array before calling this routine.

    169: .seealso: PetscStrArrayallocpy(), PetscStrcpy(), PetscStrNArrayallocpy()

    171: @*/
    172: PetscErrorCode PetscStrallocpy(const char s[], char *t[])
    173: {
    174:   char *tmp = NULL;

    176:   if (s) {
    177:     size_t len;

    179:     PetscStrlen(s,&len);
    180:     PetscMalloc1(1+len,&tmp);
    181:     PetscStrcpy(tmp,s);
    182:   }
    183:   *t = tmp;
    184:   return 0;
    185: }

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

    190:    Not Collective

    192:    Input Parameters:
    193: .  s - pointer to array of strings (final string is a null)

    195:    Output Parameter:
    196: .  t - the copied array string

    198:    Level: intermediate

    200:    Note:
    201:       Not for use in Fortran

    203:       Warning: If t has previously been allocated then that memory is lost, you may need to PetscStrArrayDestroy()
    204:       the array before calling this routine.

    206: .seealso: PetscStrallocpy(), PetscStrArrayDestroy(), PetscStrNArrayallocpy()

    208: @*/
    209: PetscErrorCode PetscStrArrayallocpy(const char *const *list, char ***t)
    210: {
    211:   PetscInt n = 0;

    213:   while (list[n++]) ;
    214:   PetscMalloc1(n+1,t);
    215:   for (PetscInt i=0; i<n; i++) PetscStrallocpy(list[i],(*t)+i);
    216:   (*t)[n] = NULL;
    217:   return 0;
    218: }

    220: /*@C
    221:    PetscStrArrayDestroy - Frees array of strings created with PetscStrArrayallocpy().

    223:    Not Collective

    225:    Output Parameters:
    226: .   list - array of strings

    228:    Level: intermediate

    230:    Notes:
    231:     Not for use in Fortran

    233: .seealso: PetscStrArrayallocpy()

    235: @*/
    236: PetscErrorCode PetscStrArrayDestroy(char ***list)
    237: {
    238:   PetscInt n = 0;

    240:   if (!*list) return 0;
    241:   while ((*list)[n]) {
    242:     PetscFree((*list)[n]);
    243:     ++n;
    244:   }
    245:   PetscFree(*list);
    246:   return 0;
    247: }

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

    252:    Not Collective

    254:    Input Parameters:
    255: +  n - the number of string entries
    256: -  s - pointer to array of strings

    258:    Output Parameter:
    259: .  t - the copied array string

    261:    Level: intermediate

    263:    Note:
    264:       Not for use in Fortran

    266: .seealso: PetscStrallocpy(), PetscStrArrayallocpy(), PetscStrNArrayDestroy()

    268: @*/
    269: PetscErrorCode PetscStrNArrayallocpy(PetscInt n, const char *const *list, char ***t)
    270: {
    271:   PetscMalloc1(n,t);
    272:   for (PetscInt i=0; i<n; i++) PetscStrallocpy(list[i],(*t)+i);
    273:   return 0;
    274: }

    276: /*@C
    277:    PetscStrNArrayDestroy - Frees array of strings created with PetscStrArrayallocpy().

    279:    Not Collective

    281:    Output Parameters:
    282: +   n - number of string entries
    283: -   list - array of strings

    285:    Level: intermediate

    287:    Notes:
    288:     Not for use in Fortran

    290: .seealso: PetscStrArrayallocpy()

    292: @*/
    293: PetscErrorCode PetscStrNArrayDestroy(PetscInt n, char ***list)
    294: {
    295:   if (!*list) return 0;
    296:   for (PetscInt i=0; i<n; i++) PetscFree((*list)[i]);
    297:   PetscFree(*list);
    298:   return 0;
    299: }

    301: /*@C
    302:    PetscStrcpy - Copies a string

    304:    Not Collective

    306:    Input Parameters:
    307: .  t - pointer to string

    309:    Output Parameter:
    310: .  s - the copied string

    312:    Level: intermediate

    314:    Notes:
    315:      Null string returns a string starting with zero

    317:      Not for use in Fortran

    319:      It is recommended you use PetscStrncpy() instead of this routine

    321: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrlcat()

    323: @*/

    325: PetscErrorCode PetscStrcpy(char s[], const char t[])
    326: {
    327:   if (t) {
    330:     strcpy(s,t);
    331:   } else if (s) s[0] = 0;
    332:   return 0;
    333: }

    335: /*@C
    336:    PetscStrncpy - Copies a string up to a certain length

    338:    Not Collective

    340:    Input Parameters:
    341: +  t - pointer to string
    342: -  n - the length to copy

    344:    Output Parameter:
    345: .  s - the copied string

    347:    Level: intermediate

    349:    Note:
    350:      Null string returns a string starting with zero

    352:      If the string that is being copied is of length n or larger then the entire string is not
    353:      copied and the final location of s is set to NULL. This is different then the behavior of
    354:      strncpy() which leaves s non-terminated if there is not room for the entire string.

    356:   Developers Note: Should this be PetscStrlcpy() to reflect its behavior which is like strlcpy() not strncpy()

    358: .seealso: PetscStrcpy(), PetscStrcat(), PetscStrlcat()

    360: @*/
    361: PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n)
    362: {
    364:   if (t) {
    366:     if (n > 1) {
    367:       strncpy(s,t,n-1);
    368:       s[n-1] = '\0';
    369:     } else {
    370:       s[0] = '\0';
    371:     }
    372:   } else if (s) s[0] = 0;
    373:   return 0;
    374: }

    376: /*@C
    377:    PetscStrcat - Concatenates a string onto a given string

    379:    Not Collective

    381:    Input Parameters:
    382: +  s - string to be added to
    383: -  t - pointer to string to be added to end

    385:    Level: intermediate

    387:    Notes:
    388:     Not for use in Fortran

    390:     It is recommended you use PetscStrlcat() instead of this routine

    392: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrlcat()

    394: @*/
    395: PetscErrorCode PetscStrcat(char s[], const char t[])
    396: {
    397:   if (!t) return 0;
    400:   strcat(s,t);
    401:   return 0;
    402: }

    404: /*@C
    405:    PetscStrlcat - Concatenates a string onto a given string, up to a given length

    407:    Not Collective

    409:    Input Parameters:
    410: +  s - pointer to string to be added to at end
    411: .  t - string to be added
    412: -  n - length of the original allocated string

    414:    Level: intermediate

    416:   Notes:
    417:   Not for use in Fortran

    419:   Unlike the system call strncat(), the length passed in is the length of the
    420:   original allocated space, not the length of the left-over space. This is
    421:   similar to the BSD system call strlcat().

    423: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()

    425: @*/
    426: PetscErrorCode PetscStrlcat(char s[], const char t[], size_t n)
    427: {
    428:   size_t len;

    430:   if (!t) return 0;
    434:   PetscStrlen(t,&len);
    435:   strncat(s,t,n - len);
    436:   s[n-1] = 0;
    437:   return 0;
    438: }

    440: void PetscStrcmpNoError(const char a[], const char b[], PetscBool *flg)
    441: {
    442:   if (!a && !b)      *flg = PETSC_TRUE;
    443:   else if (!a || !b) *flg = PETSC_FALSE;
    444:   else *flg = strcmp(a,b) ? PETSC_FALSE : PETSC_TRUE;
    445: }

    447: /*@C
    448:    PetscStrcmp - Compares two strings,

    450:    Not Collective

    452:    Input Parameters:
    453: +  a - pointer to string first string
    454: -  b - pointer to second string

    456:    Output Parameter:
    457: .  flg - PETSC_TRUE if the two strings are equal

    459:    Level: intermediate

    461:    Notes:
    462:     Not for use in Fortran

    464: .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()
    465: @*/
    466: PetscErrorCode  PetscStrcmp(const char a[],const char b[],PetscBool *flg)
    467: {
    469:   if (!a && !b)      *flg = PETSC_TRUE;
    470:   else if (!a || !b) *flg = PETSC_FALSE;
    471:   else               *flg = (PetscBool)!strcmp(a,b);
    472:   return 0;
    473: }

    475: /*@C
    476:    PetscStrgrt - If first string is greater than the second

    478:    Not Collective

    480:    Input Parameters:
    481: +  a - pointer to first string
    482: -  b - pointer to second string

    484:    Output Parameter:
    485: .  flg - if the first string is greater

    487:    Notes:
    488:     Null arguments are ok, a null string is considered smaller than
    489:     all others

    491:    Not for use in Fortran

    493:    Level: intermediate

    495: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp()

    497: @*/
    498: PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t)
    499: {
    501:   if (!a && !b)     *t = PETSC_FALSE;
    502:   else if (a && !b) *t = PETSC_TRUE;
    503:   else if (!a && b) *t = PETSC_FALSE;
    504:   else {
    507:     *t = strcmp(a,b) > 0 ? PETSC_TRUE : PETSC_FALSE;
    508:   }
    509:   return 0;
    510: }

    512: /*@C
    513:    PetscStrcasecmp - Returns true if the two strings are the same
    514:      except possibly for case.

    516:    Not Collective

    518:    Input Parameters:
    519: +  a - pointer to first string
    520: -  b - pointer to second string

    522:    Output Parameter:
    523: .  flg - if the two strings are the same

    525:    Notes:
    526:     Null arguments are ok

    528:    Not for use in Fortran

    530:    Level: intermediate

    532: .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt()

    534: @*/
    535: PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t)
    536: {
    537:   int c;

    540:   if (!a && !b)      c = 0;
    541:   else if (!a || !b) c = 1;
    542: #if defined(PETSC_HAVE_STRCASECMP)
    543:   else c = strcasecmp(a,b);
    544: #elif defined(PETSC_HAVE_STRICMP)
    545:   else c = stricmp(a,b);
    546: #else
    547:   else {
    548:     char           *aa,*bb;
    549:     PetscStrallocpy(a,&aa);
    550:     PetscStrallocpy(b,&bb);
    551:     PetscStrtolower(aa);
    552:     PetscStrtolower(bb);
    553:     PetscStrcmp(aa,bb,t);
    554:     PetscFree(aa);
    555:     PetscFree(bb);
    556:     return 0;
    557:   }
    558: #endif
    559:   *t = c ? PETSC_FALSE : PETSC_TRUE;
    560:   return 0;
    561: }

    563: /*@C
    564:    PetscStrncmp - Compares two strings, up to a certain length

    566:    Not Collective

    568:    Input Parameters:
    569: +  a - pointer to first string
    570: .  b - pointer to second string
    571: -  n - length to compare up to

    573:    Output Parameter:
    574: .  t - if the two strings are equal

    576:    Level: intermediate

    578:    Notes:
    579:     Not for use in Fortran

    581: .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp()

    583: @*/
    584: PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t)
    585: {
    586:   if (n) {
    589:   }
    591:   *t = strncmp(a,b,n) ? PETSC_FALSE : PETSC_TRUE;
    592:   return 0;
    593: }

    595: /*@C
    596:    PetscStrchr - Locates first occurrence of a character in a string

    598:    Not Collective

    600:    Input Parameters:
    601: +  a - pointer to string
    602: -  b - character

    604:    Output Parameter:
    605: .  c - location of occurrence, NULL if not found

    607:    Level: intermediate

    609:    Notes:
    610:     Not for use in Fortran

    612: @*/
    613: PetscErrorCode PetscStrchr(const char a[], char b, char *c[])
    614: {
    617:   *c = (char*)strchr(a,b);
    618:   return 0;
    619: }

    621: /*@C
    622:    PetscStrrchr - Locates one location past the last occurrence of a character in a string,
    623:       if the character is not found then returns entire string

    625:    Not Collective

    627:    Input Parameters:
    628: +  a - pointer to string
    629: -  b - character

    631:    Output Parameter:
    632: .  tmp - location of occurrence, a if not found

    634:    Level: intermediate

    636:    Notes:
    637:     Not for use in Fortran

    639: @*/
    640: PetscErrorCode PetscStrrchr(const char a[], char b, char *tmp[])
    641: {
    644:   *tmp = (char*)strrchr(a,b);
    645:   if (!*tmp) *tmp = (char*)a;
    646:   else *tmp = *tmp + 1;
    647:   return 0;
    648: }

    650: /*@C
    651:    PetscStrtolower - Converts string to lower case

    653:    Not Collective

    655:    Input Parameters:
    656: .  a - pointer to string

    658:    Level: intermediate

    660:    Notes:
    661:     Not for use in Fortran

    663: @*/
    664: PetscErrorCode PetscStrtolower(char a[])
    665: {
    667:   while (*a) {
    668:     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
    669:     a++;
    670:   }
    671:   return 0;
    672: }

    674: /*@C
    675:    PetscStrtoupper - Converts string to upper case

    677:    Not Collective

    679:    Input Parameters:
    680: .  a - pointer to string

    682:    Level: intermediate

    684:    Notes:
    685:     Not for use in Fortran

    687: @*/
    688: PetscErrorCode PetscStrtoupper(char a[])
    689: {
    691:   while (*a) {
    692:     if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a';
    693:     a++;
    694:   }
    695:   return 0;
    696: }

    698: /*@C
    699:    PetscStrendswith - Determines if a string ends with a certain string

    701:    Not Collective

    703:    Input Parameters:
    704: +  a - pointer to string
    705: -  b - string to endwith

    707:    Output Parameter:
    708: .  flg - PETSC_TRUE or PETSC_FALSE

    710:    Notes:
    711:     Not for use in Fortran

    713:    Level: intermediate

    715: @*/
    716: PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg)
    717: {
    718:   char *test;

    721:   *flg = PETSC_FALSE;
    722:   PetscStrrstr(a,b,&test);
    723:   if (test) {
    724:     size_t na,nb;

    726:     PetscStrlen(a,&na);
    727:     PetscStrlen(b,&nb);
    728:     if (a+na-nb == test) *flg = PETSC_TRUE;
    729:   }
    730:   return 0;
    731: }

    733: /*@C
    734:    PetscStrbeginswith - Determines if a string begins with a certain string

    736:    Not Collective

    738:    Input Parameters:
    739: +  a - pointer to string
    740: -  b - string to begin with

    742:    Output Parameter:
    743: .  flg - PETSC_TRUE or PETSC_FALSE

    745:    Notes:
    746:     Not for use in Fortran

    748:    Level: intermediate

    750: .seealso: PetscStrendswithwhich(), PetscStrendswith(), PetscStrtoupper, PetscStrtolower(), PetscStrrchr(), PetscStrchr(),
    751:           PetscStrncmp(), PetscStrlen(), PetscStrncmp(), PetscStrcmp()

    753: @*/
    754: PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg)
    755: {
    756:   char *test;

    761:   *flg = PETSC_FALSE;
    762:   PetscStrrstr(a,b,&test);
    763:   if (test && (test == a)) *flg = PETSC_TRUE;
    764:   return 0;
    765: }

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

    770:    Not Collective

    772:    Input Parameters:
    773: +  a - pointer to string
    774: -  bs - strings to end with (last entry must be NULL)

    776:    Output Parameter:
    777: .  cnt - the index of the string it ends with or the index of NULL

    779:    Notes:
    780:     Not for use in Fortran

    782:    Level: intermediate

    784: @*/
    785: PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt)
    786: {
    789:   *cnt = 0;
    790:   while (bs[*cnt]) {
    791:     PetscBool flg;

    793:     PetscStrendswith(a,bs[*cnt],&flg);
    794:     if (flg) return 0;
    795:     ++(*cnt);
    796:   }
    797:   return 0;
    798: }

    800: /*@C
    801:    PetscStrrstr - Locates last occurrence of string in another string

    803:    Not Collective

    805:    Input Parameters:
    806: +  a - pointer to string
    807: -  b - string to find

    809:    Output Parameter:
    810: .  tmp - location of occurrence

    812:    Notes:
    813:     Not for use in Fortran

    815:    Level: intermediate

    817: @*/
    818: PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[])
    819: {
    820:   const char *ltmp = NULL;

    825:   while (a) {
    826:     a = (char*)strstr(a,b);
    827:     if (a) ltmp = a++;
    828:   }
    829:   *tmp = (char*)ltmp;
    830:   return 0;
    831: }

    833: /*@C
    834:    PetscStrstr - Locates first occurrence of string in another string

    836:    Not Collective

    838:    Input Parameters:
    839: +  haystack - string to search
    840: -  needle - string to find

    842:    Output Parameter:
    843: .  tmp - location of occurrence, is a NULL if the string is not found

    845:    Notes:
    846:     Not for use in Fortran

    848:    Level: intermediate

    850: @*/
    851: PetscErrorCode PetscStrstr(const char haystack[],const char needle[],char *tmp[])
    852: {
    856:   *tmp = (char*)strstr(haystack,needle);
    857:   return 0;
    858: }

    860: struct _p_PetscToken {char token;char *array;char *current;};

    862: /*@C
    863:    PetscTokenFind - Locates next "token" in a string

    865:    Not Collective

    867:    Input Parameters:
    868: .  a - pointer to token

    870:    Output Parameter:
    871: .  result - location of occurrence, NULL if not found

    873:    Notes:

    875:      This version is different from the system version in that
    876:   it allows you to pass a read-only string into the function.

    878:      This version also treats all characters etc. inside a double quote "
    879:    as a single token.

    881:      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
    882:    second will return a null terminated y

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

    886:     Not for use in Fortran

    888:    Level: intermediate

    890: .seealso: PetscTokenCreate(), PetscTokenDestroy()
    891: @*/
    892: PetscErrorCode PetscTokenFind(PetscToken a, char *result[])
    893: {
    894:   char *ptr,token;

    898:   *result = ptr = a->current;
    899:   if (ptr && !*ptr) {*result = NULL; return 0;}
    900:   token = a->token;
    901:   if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;}
    902:   while (ptr) {
    903:     if (*ptr == token) {
    904:       *ptr++ = 0;
    905:       while (*ptr == a->token) ptr++;
    906:       a->current = ptr;
    907:       break;
    908:     }
    909:     if (!*ptr) {
    910:       a->current = NULL;
    911:       break;
    912:     }
    913:     ptr++;
    914:   }
    915:   return 0;
    916: }

    918: /*@C
    919:    PetscTokenCreate - Creates a PetscToken used to find tokens in a string

    921:    Not Collective

    923:    Input Parameters:
    924: +  string - the string to look in
    925: -  b - the separator character

    927:    Output Parameter:
    928: .  t- the token object

    930:    Notes:

    932:      This version is different from the system version in that
    933:   it allows you to pass a read-only string into the function.

    935:     Not for use in Fortran

    937:    Level: intermediate

    939: .seealso: PetscTokenFind(), PetscTokenDestroy()
    940: @*/
    941: PetscErrorCode PetscTokenCreate(const char a[], const char b, PetscToken *t)
    942: {
    945:   PetscNew(t);
    946:   PetscStrallocpy(a,&(*t)->array);

    948:   (*t)->current = (*t)->array;
    949:   (*t)->token   = b;
    950:   return 0;
    951: }

    953: /*@C
    954:    PetscTokenDestroy - Destroys a PetscToken

    956:    Not Collective

    958:    Input Parameters:
    959: .  a - pointer to token

    961:    Level: intermediate

    963:    Notes:
    964:     Not for use in Fortran

    966: .seealso: PetscTokenCreate(), PetscTokenFind()
    967: @*/
    968: PetscErrorCode PetscTokenDestroy(PetscToken *a)
    969: {
    970:   if (!*a) return 0;
    971:   PetscFree((*a)->array);
    972:   PetscFree(*a);
    973:   return 0;
    974: }

    976: /*@C
    977:    PetscStrInList - search string in character-delimited list

    979:    Not Collective

    981:    Input Parameters:
    982: +  str - the string to look for
    983: .  list - the list to search in
    984: -  sep - the separator character

    986:    Output Parameter:
    987: .  found - whether str is in list

    989:    Level: intermediate

    991:    Notes:
    992:     Not for use in Fortran

    994: .seealso: PetscTokenCreate(), PetscTokenFind(), PetscStrcmp()
    995: @*/
    996: PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found)
    997: {
    998:   PetscToken  token;
    999:   char       *item;

    1002:   *found = PETSC_FALSE;
    1003:   PetscTokenCreate(list,sep,&token);
    1004:   PetscTokenFind(token,&item);
    1005:   while (item) {
    1006:     PetscStrcmp(str,item,found);
    1007:     if (*found) break;
    1008:     PetscTokenFind(token,&item);
    1009:   }
    1010:   PetscTokenDestroy(&token);
    1011:   return 0;
    1012: }

    1014: /*@C
    1015:    PetscGetPetscDir - Gets the directory PETSc is installed in

    1017:    Not Collective

    1019:    Output Parameter:
    1020: .  dir - the directory

    1022:    Level: developer

    1024:    Notes:
    1025:     Not for use in Fortran

    1027: @*/
    1028: PetscErrorCode PetscGetPetscDir(const char *dir[])
    1029: {
    1031:   *dir = PETSC_DIR;
    1032:   return 0;
    1033: }

    1035: /*@C
    1036:    PetscStrreplace - Replaces substrings in string with other substrings

    1038:    Not Collective

    1040:    Input Parameters:
    1041: +   comm - MPI_Comm of processors that are processing the string
    1042: .   aa - the string to look in
    1043: .   b - the resulting copy of a with replaced strings (b can be the same as a)
    1044: -   len - the length of b

    1046:    Notes:
    1047:       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
    1048:       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values
    1049:       as well as any environmental variables.

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

    1054:       Not for use in Fortran

    1056:    Level: intermediate

    1058: @*/
    1059: PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len)
    1060: {
    1061:   int            i = 0;
    1062:   size_t         l,l1,l2,l3;
    1063:   char           *work,*par,*epar,env[1024],*tfree,*a = (char*)aa;
    1064:   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}","${HOSTNAME}",NULL};
    1065:   char           *r[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
    1066:   PetscBool      flag;
    1067:   static size_t  DISPLAY_LENGTH = 265,USER_LENGTH = 256, HOST_LENGTH = 256;

    1071:   if (aa == b) PetscStrallocpy(aa,(char**)&a);
    1072:   PetscMalloc1(len,&work);

    1074:   /* get values for replaced variables */
    1075:   PetscStrallocpy(PETSC_ARCH,&r[0]);
    1076:   PetscStrallocpy(PETSC_DIR,&r[1]);
    1077:   PetscStrallocpy(PETSC_LIB_DIR,&r[2]);
    1078:   PetscMalloc1(DISPLAY_LENGTH,&r[3]);
    1079:   PetscMalloc1(PETSC_MAX_PATH_LEN,&r[4]);
    1080:   PetscMalloc1(PETSC_MAX_PATH_LEN,&r[5]);
    1081:   PetscMalloc1(USER_LENGTH,&r[6]);
    1082:   PetscMalloc1(HOST_LENGTH,&r[7]);
    1083:   PetscGetDisplay(r[3],DISPLAY_LENGTH);
    1084:   PetscGetHomeDirectory(r[4],PETSC_MAX_PATH_LEN);
    1085:   PetscGetWorkingDirectory(r[5],PETSC_MAX_PATH_LEN);
    1086:   PetscGetUserName(r[6],USER_LENGTH);
    1087:   PetscGetHostName(r[7],HOST_LENGTH);

    1089:   /* replace that are in environment */
    1090:   PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,sizeof(env),&flag);
    1091:   if (flag) {
    1092:     PetscFree(r[2]);
    1093:     PetscStrallocpy(env,&r[2]);
    1094:   }

    1096:   /* replace the requested strings */
    1097:   PetscStrncpy(b,a,len);
    1098:   while (s[i]) {
    1099:     PetscStrlen(s[i],&l);
    1100:     PetscStrstr(b,s[i],&par);
    1101:     while (par) {
    1102:       *par = 0;
    1103:       par += l;

    1105:       PetscStrlen(b,&l1);
    1106:       PetscStrlen(r[i],&l2);
    1107:       PetscStrlen(par,&l3);
    1109:       PetscStrncpy(work,b,len);
    1110:       PetscStrlcat(work,r[i],len);
    1111:       PetscStrlcat(work,par,len);
    1112:       PetscStrncpy(b,work,len);
    1113:       PetscStrstr(b,s[i],&par);
    1114:     }
    1115:     i++;
    1116:   }
    1117:   i = 0;
    1118:   while (r[i]) {
    1119:     tfree = (char*)r[i];
    1120:     PetscFree(tfree);
    1121:     i++;
    1122:   }

    1124:   /* look for any other ${xxx} strings to replace from environmental variables */
    1125:   PetscStrstr(b,"${",&par);
    1126:   while (par) {
    1127:     *par  = 0;
    1128:     par  += 2;
    1129:     PetscStrncpy(work,b,len);
    1130:     PetscStrstr(par,"}",&epar);
    1131:     *epar = 0;
    1132:     epar += 1;
    1133:     PetscOptionsGetenv(comm,par,env,sizeof(env),&flag);
    1135:     PetscStrlcat(work,env,len);
    1136:     PetscStrlcat(work,epar,len);
    1137:     PetscStrncpy(b,work,len);
    1138:     PetscStrstr(b,"${",&par);
    1139:   }
    1140:   PetscFree(work);
    1141:   if (aa == b) PetscFree(a);
    1142:   return 0;
    1143: }

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

    1148:    Not Collective

    1150:    Input Parameters:
    1151: +  n - number of strings in
    1152: .  list - list of strings to search
    1153: -  str - string to look for, empty string "" accepts default (first entry in list)

    1155:    Output Parameters:
    1156: +  value - index of matching string (if found)
    1157: -  found - boolean indicating whether string was found (can be NULL)

    1159:    Notes:
    1160:    Not for use in Fortran

    1162:    Level: advanced
    1163: @*/
    1164: PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found)
    1165: {
    1166:   if (found) {
    1168:     *found = PETSC_FALSE;
    1169:   }
    1170:   for (PetscInt i = 0; i < n; ++i) {
    1171:     PetscBool matched;

    1173:     PetscStrcasecmp(str,list[i],&matched);
    1174:     if (matched || !str[0]) {
    1175:       if (found) *found = PETSC_TRUE;
    1176:       *value = i;
    1177:       break;
    1178:     }
    1179:   }
    1180:   return 0;
    1181: }

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

    1186:    Not Collective

    1188:    Input Parameters:
    1189: +  enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL
    1190: -  str - string to look for

    1192:    Output Parameters:
    1193: +  value - index of matching string (if found)
    1194: -  found - boolean indicating whether string was found (can be NULL)

    1196:    Notes:
    1197:    Not for use in Fortran

    1199:    Level: advanced
    1200: @*/
    1201: PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found)
    1202: {
    1203:   PetscInt  n = 0,evalue;
    1204:   PetscBool efound;

    1209:   n -= 3; /* drop enum name, prefix, and null termination */
    1210:   PetscEListFind(n,enumlist,str,&evalue,&efound);
    1211:   if (efound) {
    1213:     *value = (PetscEnum)evalue;
    1214:   }
    1215:   if (found) {
    1217:     *found = efound;
    1218:   }
    1219:   return 0;
    1220: }