Actual source code: str.c

      1: #define PETSC_DLL
      2: /*
      3:     We define the string operations here. The reason we just do not use
      4:   the standard string routines in the PETSc code is that on some machines
      5:   they are broken or have the wrong prototypes.

      7: */
     8:  #include petsc.h
     9:  #include petscsys.h
     10: #if defined(PETSC_HAVE_STRING_H)
     11: #include <string.h>
     12: #endif
     13: #if defined(PETSC_HAVE_STRINGS_H)
     14: #include <strings.h>
     15: #endif
     16: #include "petscfix.h"

     20: /*@C
     21:    PetscStrlen - Gets length of a string

     23:    Not Collective

     25:    Input Parameters:
     26: .  s - pointer to string

     28:    Output Parameter:
     29: .  len - length in bytes

     31:    Level: intermediate

     33:    Note:
     34:    This routine is analogous to strlen().

     36:    Null string returns a length of zero

     38:   Concepts: string length
     39:
     40: @*/
     41: PetscErrorCode PETSC_DLLEXPORT PetscStrlen(const char s[],size_t *len)
     42: {
     44:   if (!s) {
     45:     *len = 0;
     46:   } else {
     47:     *len = strlen(s);
     48:   }
     49:   return(0);
     50: }

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

     57:    Not Collective

     59:    Input Parameters:
     60: .  s - pointer to string

     62:    Output Parameter:
     63: .  t - the copied string

     65:    Level: intermediate

     67:    Note:
     68:       Null string returns a new null string

     70:   Concepts: string copy
     71:
     72: @*/
     73: PetscErrorCode PETSC_DLLEXPORT PetscStrallocpy(const char s[],char *t[])
     74: {
     76:   size_t         len;

     79:   if (s) {
     80:     PetscStrlen(s,&len);
     81:     PetscMalloc((1+len)*sizeof(char),t);
     82:     PetscStrcpy(*t,s);
     83:   } else {
     84:     *t = 0;
     85:   }
     86:   return(0);
     87: }

     91: /*@C
     92:    PetscStrcpy - Copies a string

     94:    Not Collective

     96:    Input Parameters:
     97: .  t - pointer to string

     99:    Output Parameter:
    100: .  s - the copied string

    102:    Level: intermediate

    104:    Note:
    105:      Null string returns a string starting with zero

    107:   Concepts: string copy
    108:
    109: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat()

    111: @*/
    112: PetscErrorCode PETSC_DLLEXPORT PetscStrcpy(char s[],const char t[])
    113: {
    115:   if (t && !s) {
    116:     SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
    117:   }
    118:   if (t) {strcpy(s,t);}
    119:   else if (s) {s[0] = 0;}
    120:   return(0);
    121: }

    125: /*@C
    126:    PetscStrncpy - Copies a string up to a certain length

    128:    Not Collective

    130:    Input Parameters:
    131: +  t - pointer to string
    132: -  n - the length to copy

    134:    Output Parameter:
    135: .  s - the copied string

    137:    Level: intermediate

    139:    Note:
    140:      Null string returns a string starting with zero

    142:   Concepts: string copy

    144: .seealso: PetscStrcpy(), PetscStrcat(), PetscStrncat()
    145:
    146: @*/
    147: PetscErrorCode PETSC_DLLEXPORT PetscStrncpy(char s[],const char t[],size_t n)
    148: {
    150:   if (t && !s) {
    151:     SETERRQ(PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer");
    152:   }
    153:   if (t) {strncpy(s,t,n);}
    154:   else if (s) {s[0] = 0;}
    155:   return(0);
    156: }

    160: /*@C
    161:    PetscStrcat - Concatenates a string onto a given string

    163:    Not Collective

    165:    Input Parameters:
    166: +  s - pointer to string to be added to end
    167: -  t - string to be added to

    169:    Level: intermediate

    171:   Concepts: string copy

    173: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrncat()
    174:
    175: @*/
    176: PetscErrorCode PETSC_DLLEXPORT PetscStrcat(char s[],const char t[])
    177: {
    179:   strcat(s,t);
    180:   return(0);
    181: }

    185: /*@C
    186:    PetscStrncat - Concatenates a string onto a given string, up to a given length

    188:    Not Collective

    190:    Input Parameters:
    191: +  s - pointer to string to be added to end
    192: .  t - string to be added to
    193: .  n - maximum length to copy

    195:    Level: intermediate

    197:   Concepts: string copy

    199: .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat()
    200:
    201: @*/
    202: PetscErrorCode PETSC_DLLEXPORT PetscStrncat(char s[],const char t[],size_t n)
    203: {
    205:   strncat(s,t,n);
    206:   return(0);
    207: }

    211: /*@C
    212:    PetscStrcmp - Compares two strings,

    214:    Not Collective

    216:    Input Parameters:
    217: +  a - pointer to string first string
    218: -  b - pointer to second string

    220:    Output Parameter:
    221: .  flg - if the two strings are equal

    223:    Level: intermediate

    225: .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp()

    227: @*/
    228: PetscErrorCode PETSC_DLLEXPORT PetscStrcmp(const char a[],const char b[],PetscTruth *flg)
    229: {
    230:   int c;

    233:   if (!a && !b) {
    234:     *flg = PETSC_TRUE;
    235:   } else if (!a || !b) {
    236:     *flg = PETSC_FALSE;
    237:   } else {
    238:     c = strcmp(a,b);
    239:     if (c) *flg = PETSC_FALSE;
    240:     else   *flg = PETSC_TRUE;
    241:   }
    242:   return(0);
    243: }

    247: /*@C
    248:    PetscStrgrt - If first string is greater than the second

    250:    Not Collective

    252:    Input Parameters:
    253: +  a - pointer to first string
    254: -  b - pointer to second string

    256:    Output Parameter:
    257: .  flg - if the first string is greater

    259:    Notes:
    260:     Null arguments are ok, a null string is considered smaller than
    261:     all others

    263:    Level: intermediate

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

    267: @*/
    268: PetscErrorCode PETSC_DLLEXPORT PetscStrgrt(const char a[],const char b[],PetscTruth *t)
    269: {
    270:   int c;

    273:   if (!a && !b) {
    274:     *t = PETSC_FALSE;
    275:   } else if (a && !b) {
    276:     *t = PETSC_TRUE;
    277:   } else if (!a && b) {
    278:     *t = PETSC_FALSE;
    279:   } else {
    280:     c = strcmp(a,b);
    281:     if (c > 0) *t = PETSC_TRUE;
    282:     else       *t = PETSC_FALSE;
    283:   }
    284:   return(0);
    285: }

    289: /*@C
    290:    PetscStrcasecmp - Returns true if the two strings are the same
    291:      except possibly for case.

    293:    Not Collective

    295:    Input Parameters:
    296: +  a - pointer to first string
    297: -  b - pointer to second string

    299:    Output Parameter:
    300: .  flg - if the two strings are the same

    302:    Notes:
    303:     Null arguments are ok

    305:    Level: intermediate

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

    309: @*/
    310: PetscErrorCode PETSC_DLLEXPORT PetscStrcasecmp(const char a[],const char b[],PetscTruth *t)
    311: {
    312:   int c;

    315:   if (!a && !b) c = 0;
    316:   else if (!a || !b) c = 1;
    317: #if defined(PETSC_HAVE_STRICMP)
    318:   else c = stricmp(a,b);
    319: #else
    320:   else c = strcasecmp(a,b);
    321: #endif
    322:   if (!c) *t = PETSC_TRUE;
    323:   else    *t = PETSC_FALSE;
    324:   return(0);
    325: }

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

    332:    Not Collective

    334:    Input Parameters:
    335: +  a - pointer to first string
    336: .  b - pointer to second string
    337: -  n - length to compare up to

    339:    Output Parameter:
    340: .  t - if the two strings are equal

    342:    Level: intermediate

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

    346: @*/
    347: PetscErrorCode PETSC_DLLEXPORT PetscStrncmp(const char a[],const char b[],size_t n,PetscTruth *t)
    348: {
    349:   int c;

    352:   c = strncmp(a,b,n);
    353:   if (!c) *t = PETSC_TRUE;
    354:   else    *t = PETSC_FALSE;
    355:   return(0);
    356: }

    360: /*@C
    361:    PetscStrchr - Locates first occurance of a character in a string

    363:    Not Collective

    365:    Input Parameters:
    366: +  a - pointer to string
    367: -  b - character

    369:    Output Parameter:
    370: .  c - location of occurance, PETSC_NULL if not found

    372:    Level: intermediate

    374: @*/
    375: PetscErrorCode PETSC_DLLEXPORT PetscStrchr(const char a[],char b,char *c[])
    376: {
    378:   *c = (char *)strchr(a,b);
    379:   return(0);
    380: }

    384: /*@C
    385:    PetscStrrchr - Locates one location past the last occurance of a character in a string,
    386:       if the character is not found then returns entire string

    388:    Not Collective

    390:    Input Parameters:
    391: +  a - pointer to string
    392: -  b - character

    394:    Output Parameter:
    395: .  tmp - location of occurance, a if not found

    397:    Level: intermediate

    399: @*/
    400: PetscErrorCode PETSC_DLLEXPORT PetscStrrchr(const char a[],char b,char *tmp[])
    401: {
    403:   *tmp = (char *)strrchr(a,b);
    404:   if (!*tmp) *tmp = (char*)a; else *tmp = *tmp + 1;
    405:   return(0);
    406: }

    410: /*@C
    411:    PetscStrtolower - Converts string to lower case

    413:    Not Collective

    415:    Input Parameters:
    416: .  a - pointer to string

    418:    Level: intermediate

    420: @*/
    421: PetscErrorCode PETSC_DLLEXPORT PetscStrtolower(char a[])
    422: {
    424:   while (*a) {
    425:     if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
    426:     a++;
    427:   }
    428:   return(0);
    429: }

    433: /*@C
    434:    PetscTokenFind - Locates next "token" in a string

    436:    Not Collective

    438:    Input Parameters:
    439: .  a - pointer to token

    441:    Output Parameter:
    442: .  result - location of occurance, PETSC_NULL if not found

    444:    Notes:

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

    449:    Level: intermediate

    451: .seealso: PetscTokenCreate(), PetscTokenDestroy()
    452: @*/
    453: PetscErrorCode PETSC_DLLEXPORT PetscTokenFind(PetscToken *a,char *result[])
    454: {
    455:   char *ptr = a->current;

    458:   *result = a->current;
    459:   if (ptr && !*ptr) *result = 0;
    460:   while (ptr) {
    461:     if (*ptr == a->token) {
    462:       *ptr++ = 0;
    463:       while (*ptr == a->token) ptr++;
    464:       a->current = ptr;
    465:       break;
    466:     }
    467:     if (!*ptr) {
    468:       a->current = 0;
    469:       break;
    470:     }
    471:     ptr++;
    472:   }
    473:   return(0);
    474: }

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

    481:    Not Collective

    483:    Input Parameters:
    484: +  string - the string to look in
    485: -  token - the character to look for

    487:    Output Parameter:
    488: .  a - pointer to token

    490:    Notes:

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

    495:    Level: intermediate

    497: .seealso: PetscTokenFind(), PetscTokenDestroy()
    498: @*/
    499: PetscErrorCode PETSC_DLLEXPORT PetscTokenCreate(const char a[],const char b,PetscToken **t)
    500: {
    502:   size_t         len;

    505:   PetscNew(PetscToken,t);
    506:   PetscStrlen(a,&len);
    507:   PetscStrallocpy(a,&(*t)->array);
    508:   (*t)->current = (*t)->array;
    509:   (*t)->token   = b;
    510:   return(0);
    511: }

    515: /*@C
    516:    PetscTokenDestroy - Destroys a PetscToken

    518:    Not Collective

    520:    Input Parameters:
    521: .  a - pointer to token

    523:    Level: intermediate

    525: .seealso: PetscTokenCreate(), PetscTokenFind()
    526: @*/
    527: PetscErrorCode PETSC_DLLEXPORT PetscTokenDestroy(PetscToken *a)
    528: {

    532:   PetscFree(a->array);
    533:   PetscFree(a);
    534:   return(0);
    535: }

    539: /*@C
    540:    PetscStrrstr - Locates last occurance of string in another string

    542:    Not Collective

    544:    Input Parameters:
    545: +  a - pointer to string
    546: -  b - string to find

    548:    Output Parameter:
    549: .  tmp - location of occurance

    551:    Level: intermediate

    553: @*/
    554: PetscErrorCode PETSC_DLLEXPORT PetscStrrstr(const char a[],const char b[],char *tmp[])
    555: {
    556:   const char *stmp = a, *ltmp = 0;

    559:   while (stmp) {
    560:     stmp = (char *)strstr(stmp,b);
    561:     if (stmp) {ltmp = stmp;stmp++;}
    562:   }
    563:   *tmp = (char *)ltmp;
    564:   return(0);
    565: }

    569: /*@C
    570:    PetscStrstr - Locates first occurance of string in another string

    572:    Not Collective

    574:    Input Parameters:
    575: +  a - pointer to string
    576: -  b - string to find

    578:    Output Parameter:
    579: .  tmp - location of occurance

    581:    Level: intermediate

    583: @*/
    584: PetscErrorCode PETSC_DLLEXPORT PetscStrstr(const char a[],const char b[],char *tmp[])
    585: {
    587:   *tmp = (char *)strstr(a,b);
    588:   return(0);
    589: }

    593: /*@C
    594:    PetscGetPetscDir - Gets the directory PETSc is installed in

    596:    Not Collective

    598:    Output Parameter:
    599: .  dir - the directory

    601:    Level: developer

    603: @*/
    604: PetscErrorCode PETSC_DLLEXPORT PetscGetPetscDir(const char *dir[])
    605: {
    607:   *dir = PETSC_DIR;
    608:   return(0);
    609: }

    613: /*@C
    614:    PetscStrreplace - Replaces substrings in string with other substrings

    616:    Not Collective

    618:    Input Parameters:
    619: +   comm - MPI_Comm of processors that are processing the string
    620: .   a - the string to look in
    621: .   b - the resulting copy of a with replaced strings
    622: -   len - the length of b

    624:    Notes:
    625:       Replaces   ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY},
    626:       ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME} with appropriate values
    627:       as well as any environmental variables.
    628:
    629:    Level: intermediate

    631: @*/
    632: PetscErrorCode PETSC_DLLEXPORT PetscStrreplace(MPI_Comm comm,const char a[],char b[],size_t len)
    633: {
    635:   int            i = 0;
    636:   size_t         l,l1,l2,l3;
    637:   char           *work,*par,*epar,env[1024],*tfree;
    638:   const char     *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}",0};
    639:   const char     *r[] = {PETSC_ARCH,PETSC_DIR,PETSC_LIB_DIR,0,0,0,0,0};
    640:   PetscTruth     flag;

    643:   if (!a || !b) SETERRQ(PETSC_ERR_ARG_NULL,"a and b strings must be nonnull");
    644:   PetscMalloc(len*sizeof(char*),&work);

    646:   /* get values for replaced variables */
    647:   PetscMalloc(256*sizeof(char),&r[4]);
    648:   PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[5]);
    649:   PetscMalloc(PETSC_MAX_PATH_LEN*sizeof(char),&r[6]);
    650:   PetscMalloc(256*sizeof(char),&r[7]);
    651:   PetscGetDisplay((char*)r[4],256);
    652:   PetscGetHomeDirectory((char*)r[5],PETSC_MAX_PATH_LEN);
    653:   PetscGetWorkingDirectory((char*)r[6],PETSC_MAX_PATH_LEN);
    654:   PetscGetUserName((char*)r[7],256);

    656:   /* replace the requested strings */
    657:   PetscStrncpy(b,a,len);
    658:   while (s[i]) {
    659:     PetscStrlen(s[i],&l);
    660:     PetscStrstr(b,s[i],&par);
    661:     while (par) {
    662:       *par  =  0;
    663:       par  += l;

    665:       PetscStrlen(b,&l1);
    666:       PetscStrlen(r[i],&l2);
    667:       PetscStrlen(par,&l3);
    668:       if (l1 + l2 + l3 >= len) {
    669:         SETERRQ(PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values");
    670:       }
    671:       PetscStrcpy(work,b);
    672:       PetscStrcat(work,r[i]);
    673:       PetscStrcat(work,par);
    674:       PetscStrncpy(b,work,len);
    675:       PetscStrstr(b,s[i],&par);
    676:     }
    677:     i++;
    678:   }
    679:   for ( i=4; i<8; i++){
    680:     tfree = (char*)r[i];
    681:     PetscFree(tfree);
    682:   }

    684:   /* look for any other ${xxx} strings to replace from environmental variables */
    685:   PetscStrstr(b,"${",&par);
    686:   while (par) {
    687:     *par = 0;
    688:     par += 2;
    689:     PetscStrcpy(work,b);
    690:     PetscStrstr(par,"}",&epar);
    691:     *epar = 0;
    692:     epar += 1;
    693:     PetscOptionsGetenv(comm,par,env,256,&flag);
    694:     if (!flag) {
    695:       SETERRQ1(PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par);
    696:     }
    697:     PetscStrcat(work,env);
    698:     PetscStrcat(work,epar);
    699:     PetscStrcpy(b,work);
    700:     PetscStrstr(b,"${",&par);
    701:   }
    702:   PetscFree(work);
    703:   return(0);
    704: }

    706: /*MC
    707:    PetscStrfree - Frees a string (if it is not null)

    709:    Not Collective

    711:    Synopsis:
    712:    PetscErrorCode PetscStrfree(char *s)

    714:    Input Parameter:
    715: .  s - pointer to string

    717:    Level: intermediate

    719:   Concepts: string free
    720:
    721: .seealso: PetscStrncpy(), PetscStrcat(), PetscStrncat(), PetscStrallocpy()

    723: M*/