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 */ 7 #include <petscsys.h> /*I "petscsys.h" I*/ 8 #if defined(PETSC_HAVE_STRINGS_H) 9 # include <strings.h> /* strcasecmp */ 10 #endif 11 12 /*@C 13 PetscStrToArray - Separates a string by a character (for example ' ' or '\n') and creates an array of strings 14 15 Not Collective 16 17 Input Parameters: 18 + s - pointer to string 19 - sp - separator character 20 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 24 25 Level: intermediate 26 27 Notes: 28 this may be called before PetscInitialize() or after PetscFinalize() 29 30 Not for use in Fortran 31 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() 35 36 .seealso: PetscStrToArrayDestroy(), PetscToken, PetscTokenCreate() 37 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; 43 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) { 52 return(0); 53 } 54 for (i=0; i<n; i++) { 55 if (s[i] != sp) break; 56 } 57 for (;i<n+1; i++) { 58 if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;} 59 else if (s[i] != sp) {flg = PETSC_FALSE;} 60 } 61 (*args) = (char**) malloc(((*argc)+1)*sizeof(char*)); if (!*args) return PETSC_ERR_MEM; 62 lens = (int*) malloc((*argc)*sizeof(int)); if (!lens) return PETSC_ERR_MEM; 63 for (i=0; i<*argc; i++) lens[i] = 0; 64 65 *argc = 0; 66 for (i=0; i<n; i++) { 67 if (s[i] != sp) break; 68 } 69 for (;i<n+1; i++) { 70 if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*argc)++;} 71 else if (s[i] != sp) {lens[*argc]++;flg = PETSC_FALSE;} 72 } 73 74 for (i=0; i<*argc; i++) { 75 (*args)[i] = (char*) malloc((lens[i]+1)*sizeof(char)); 76 if (!(*args)[i]) { 77 free(lens); 78 for (j=0; j<i; j++) free((*args)[j]); 79 free(*args); 80 return PETSC_ERR_MEM; 81 } 82 } 83 free(lens); 84 (*args)[*argc] = NULL; 85 86 *argc = 0; 87 for (i=0; i<n; i++) { 88 if (s[i] != sp) break; 89 } 90 for (;i<n+1; i++) { 91 if ((s[i] == sp || s[i] == 0) && !flg) {flg = PETSC_TRUE; (*args)[*argc][cnt++] = 0; (*argc)++; cnt = 0;} 92 else if (s[i] != sp && s[i] != 0) {(*args)[*argc][cnt++] = s[i]; flg = PETSC_FALSE;} 93 } 94 return 0; 95 } 96 97 /*@C 98 PetscStrToArrayDestroy - Frees array created with PetscStrToArray(). 99 100 Not Collective 101 102 Output Parameters: 103 + argc - the number of arguments 104 - args - the array of arguments 105 106 Level: intermediate 107 108 Notes: 109 This may be called before PetscInitialize() or after PetscFinalize() 110 111 Not for use in Fortran 112 113 .seealso: PetscStrToArray() 114 115 @*/ 116 PetscErrorCode PetscStrToArrayDestroy(int argc,char **args) 117 { 118 PetscInt i; 119 120 for (i=0; i<argc; i++) free(args[i]); 121 if (args) free(args); 122 return 0; 123 } 124 125 /*@C 126 PetscStrlen - Gets length of a string 127 128 Not Collective 129 130 Input Parameters: 131 . s - pointer to string 132 133 Output Parameter: 134 . len - length in bytes 135 136 Level: intermediate 137 138 Note: 139 This routine is analogous to strlen(). 140 141 Null string returns a length of zero 142 143 Not for use in Fortran 144 145 @*/ 146 PetscErrorCode PetscStrlen(const char s[],size_t *len) 147 { 148 PetscFunctionBegin; 149 if (!s) *len = 0; 150 else *len = strlen(s); 151 PetscFunctionReturn(0); 152 } 153 154 /*@C 155 PetscStrallocpy - Allocates space to hold a copy of a string then copies the string 156 157 Not Collective 158 159 Input Parameters: 160 . s - pointer to string 161 162 Output Parameter: 163 . t - the copied string 164 165 Level: intermediate 166 167 Note: 168 Null string returns a new null string 169 170 Not for use in Fortran 171 172 Warning: If t has previously been allocated then that memory is lost, you may need to PetscFree() 173 the array before calling this routine. 174 175 .seealso: PetscStrArrayallocpy(), PetscStrcpy(), PetscStrNArrayallocpy() 176 177 @*/ 178 PetscErrorCode PetscStrallocpy(const char s[],char *t[]) 179 { 180 PetscErrorCode ierr; 181 size_t len; 182 char *tmp = NULL; 183 184 PetscFunctionBegin; 185 if (s) { 186 ierr = PetscStrlen(s,&len);CHKERRQ(ierr); 187 ierr = PetscMalloc1(1+len,&tmp);CHKERRQ(ierr); 188 ierr = PetscStrcpy(tmp,s);CHKERRQ(ierr); 189 } 190 *t = tmp; 191 PetscFunctionReturn(0); 192 } 193 194 /*@C 195 PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings 196 197 Not Collective 198 199 Input Parameters: 200 . s - pointer to array of strings (final string is a null) 201 202 Output Parameter: 203 . t - the copied array string 204 205 Level: intermediate 206 207 Note: 208 Not for use in Fortran 209 210 Warning: If t has previously been allocated then that memory is lost, you may need to PetscStrArrayDestroy() 211 the array before calling this routine. 212 213 .seealso: PetscStrallocpy(), PetscStrArrayDestroy(), PetscStrNArrayallocpy() 214 215 @*/ 216 PetscErrorCode PetscStrArrayallocpy(const char *const *list,char ***t) 217 { 218 PetscErrorCode ierr; 219 PetscInt i,n = 0; 220 221 PetscFunctionBegin; 222 while (list[n++]) ; 223 ierr = PetscMalloc1(n+1,t);CHKERRQ(ierr); 224 for (i=0; i<n; i++) { 225 ierr = PetscStrallocpy(list[i],(*t)+i);CHKERRQ(ierr); 226 } 227 (*t)[n] = NULL; 228 PetscFunctionReturn(0); 229 } 230 231 /*@C 232 PetscStrArrayDestroy - Frees array of strings created with PetscStrArrayallocpy(). 233 234 Not Collective 235 236 Output Parameters: 237 . list - array of strings 238 239 Level: intermediate 240 241 Notes: 242 Not for use in Fortran 243 244 .seealso: PetscStrArrayallocpy() 245 246 @*/ 247 PetscErrorCode PetscStrArrayDestroy(char ***list) 248 { 249 PetscInt n = 0; 250 PetscErrorCode ierr; 251 252 PetscFunctionBegin; 253 if (!*list) PetscFunctionReturn(0); 254 while ((*list)[n]) { 255 ierr = PetscFree((*list)[n]);CHKERRQ(ierr); 256 n++; 257 } 258 ierr = PetscFree(*list);CHKERRQ(ierr); 259 PetscFunctionReturn(0); 260 } 261 262 /*@C 263 PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings 264 265 Not Collective 266 267 Input Parameters: 268 + n - the number of string entries 269 - s - pointer to array of strings 270 271 Output Parameter: 272 . t - the copied array string 273 274 Level: intermediate 275 276 Note: 277 Not for use in Fortran 278 279 .seealso: PetscStrallocpy(), PetscStrArrayallocpy(), PetscStrNArrayDestroy() 280 281 @*/ 282 PetscErrorCode PetscStrNArrayallocpy(PetscInt n,const char *const *list,char ***t) 283 { 284 PetscErrorCode ierr; 285 PetscInt i; 286 287 PetscFunctionBegin; 288 ierr = PetscMalloc1(n,t);CHKERRQ(ierr); 289 for (i=0; i<n; i++) { 290 ierr = PetscStrallocpy(list[i],(*t)+i);CHKERRQ(ierr); 291 } 292 PetscFunctionReturn(0); 293 } 294 295 /*@C 296 PetscStrNArrayDestroy - Frees array of strings created with PetscStrArrayallocpy(). 297 298 Not Collective 299 300 Output Parameters: 301 + n - number of string entries 302 - list - array of strings 303 304 Level: intermediate 305 306 Notes: 307 Not for use in Fortran 308 309 .seealso: PetscStrArrayallocpy() 310 311 @*/ 312 PetscErrorCode PetscStrNArrayDestroy(PetscInt n,char ***list) 313 { 314 PetscErrorCode ierr; 315 PetscInt i; 316 317 PetscFunctionBegin; 318 if (!*list) PetscFunctionReturn(0); 319 for (i=0; i<n; i++) { 320 ierr = PetscFree((*list)[i]);CHKERRQ(ierr); 321 } 322 ierr = PetscFree(*list);CHKERRQ(ierr); 323 PetscFunctionReturn(0); 324 } 325 326 /*@C 327 PetscStrcpy - Copies a string 328 329 Not Collective 330 331 Input Parameters: 332 . t - pointer to string 333 334 Output Parameter: 335 . s - the copied string 336 337 Level: intermediate 338 339 Notes: 340 Null string returns a string starting with zero 341 342 Not for use in Fortran 343 344 It is recommended you use PetscStrncpy() instead of this routine 345 346 .seealso: PetscStrncpy(), PetscStrcat(), PetscStrlcat() 347 348 @*/ 349 350 PetscErrorCode PetscStrcpy(char s[],const char t[]) 351 { 352 PetscFunctionBegin; 353 PetscCheckFalse(t && !s,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer"); 354 if (t) strcpy(s,t); 355 else if (s) s[0] = 0; 356 PetscFunctionReturn(0); 357 } 358 359 /*@C 360 PetscStrncpy - Copies a string up to a certain length 361 362 Not Collective 363 364 Input Parameters: 365 + t - pointer to string 366 - n - the length to copy 367 368 Output Parameter: 369 . s - the copied string 370 371 Level: intermediate 372 373 Note: 374 Null string returns a string starting with zero 375 376 If the string that is being copied is of length n or larger then the entire string is not 377 copied and the final location of s is set to NULL. This is different then the behavior of 378 strncpy() which leaves s non-terminated if there is not room for the entire string. 379 380 Developers Note: Should this be PetscStrlcpy() to reflect its behavior which is like strlcpy() not strncpy() 381 382 .seealso: PetscStrcpy(), PetscStrcat(), PetscStrlcat() 383 384 @*/ 385 PetscErrorCode PetscStrncpy(char s[],const char t[],size_t n) 386 { 387 PetscFunctionBegin; 388 PetscCheckFalse(t && !s,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to copy string into null pointer"); 389 PetscCheckFalse(s && !n,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Requires an output string of length at least 1 to hold the termination character"); 390 if (t) { 391 if (n > 1) { 392 strncpy(s,t,n-1); 393 s[n-1] = '\0'; 394 } else { 395 s[0] = '\0'; 396 } 397 } else if (s) s[0] = 0; 398 PetscFunctionReturn(0); 399 } 400 401 /*@C 402 PetscStrcat - Concatenates a string onto a given string 403 404 Not Collective 405 406 Input Parameters: 407 + s - string to be added to 408 - t - pointer to string to be added to end 409 410 Level: intermediate 411 412 Notes: 413 Not for use in Fortran 414 415 It is recommended you use PetscStrlcat() instead of this routine 416 417 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrlcat() 418 419 @*/ 420 PetscErrorCode PetscStrcat(char s[],const char t[]) 421 { 422 PetscFunctionBegin; 423 if (!t) PetscFunctionReturn(0); 424 strcat(s,t); 425 PetscFunctionReturn(0); 426 } 427 428 /*@C 429 PetscStrlcat - Concatenates a string onto a given string, up to a given length 430 431 Not Collective 432 433 Input Parameters: 434 + s - pointer to string to be added to at end 435 . t - string to be added 436 - n - length of the original allocated string 437 438 Level: intermediate 439 440 Notes: 441 Not for use in Fortran 442 443 Unlike the system call strncat(), the length passed in is the length of the 444 original allocated space, not the length of the left-over space. This is 445 similar to the BSD system call strlcat(). 446 447 .seealso: PetscStrcpy(), PetscStrncpy(), PetscStrcat() 448 449 @*/ 450 PetscErrorCode PetscStrlcat(char s[],const char t[],size_t n) 451 { 452 size_t len; 453 PetscErrorCode ierr; 454 455 PetscFunctionBegin; 456 PetscCheckFalse(t && !n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"String buffer length must be positive"); 457 if (!t) PetscFunctionReturn(0); 458 ierr = PetscStrlen(t,&len);CHKERRQ(ierr); 459 strncat(s,t,n - len); 460 s[n-1] = 0; 461 PetscFunctionReturn(0); 462 } 463 464 void PetscStrcmpNoError(const char a[],const char b[],PetscBool *flg) 465 { 466 int c; 467 468 if (!a && !b) *flg = PETSC_TRUE; 469 else if (!a || !b) *flg = PETSC_FALSE; 470 else { 471 c = strcmp(a,b); 472 if (c) *flg = PETSC_FALSE; 473 else *flg = PETSC_TRUE; 474 } 475 } 476 477 /*@C 478 PetscStrcmp - Compares two strings, 479 480 Not Collective 481 482 Input Parameters: 483 + a - pointer to string first string 484 - b - pointer to second string 485 486 Output Parameter: 487 . flg - PETSC_TRUE if the two strings are equal 488 489 Level: intermediate 490 491 Notes: 492 Not for use in Fortran 493 494 .seealso: PetscStrgrt(), PetscStrncmp(), PetscStrcasecmp() 495 496 @*/ 497 PetscErrorCode PetscStrcmp(const char a[],const char b[],PetscBool *flg) 498 { 499 PetscFunctionBegin; 500 if (!a && !b) *flg = PETSC_TRUE; 501 else if (!a || !b) *flg = PETSC_FALSE; 502 else { 503 int c = strcmp(a,b); 504 if (c) *flg = PETSC_FALSE; 505 else *flg = PETSC_TRUE; 506 } 507 PetscFunctionReturn(0); 508 } 509 510 /*@C 511 PetscStrgrt - If first string is greater than the second 512 513 Not Collective 514 515 Input Parameters: 516 + a - pointer to first string 517 - b - pointer to second string 518 519 Output Parameter: 520 . flg - if the first string is greater 521 522 Notes: 523 Null arguments are ok, a null string is considered smaller than 524 all others 525 526 Not for use in Fortran 527 528 Level: intermediate 529 530 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrcasecmp() 531 532 @*/ 533 PetscErrorCode PetscStrgrt(const char a[],const char b[],PetscBool *t) 534 { 535 int c; 536 537 PetscFunctionBegin; 538 if (!a && !b) *t = PETSC_FALSE; 539 else if (a && !b) *t = PETSC_TRUE; 540 else if (!a && b) *t = PETSC_FALSE; 541 else { 542 c = strcmp(a,b); 543 if (c > 0) *t = PETSC_TRUE; 544 else *t = PETSC_FALSE; 545 } 546 PetscFunctionReturn(0); 547 } 548 549 /*@C 550 PetscStrcasecmp - Returns true if the two strings are the same 551 except possibly for case. 552 553 Not Collective 554 555 Input Parameters: 556 + a - pointer to first string 557 - b - pointer to second string 558 559 Output Parameter: 560 . flg - if the two strings are the same 561 562 Notes: 563 Null arguments are ok 564 565 Not for use in Fortran 566 567 Level: intermediate 568 569 .seealso: PetscStrcmp(), PetscStrncmp(), PetscStrgrt() 570 571 @*/ 572 PetscErrorCode PetscStrcasecmp(const char a[],const char b[],PetscBool *t) 573 { 574 int c; 575 576 PetscFunctionBegin; 577 if (!a && !b) c = 0; 578 else if (!a || !b) c = 1; 579 #if defined(PETSC_HAVE_STRCASECMP) 580 else c = strcasecmp(a,b); 581 #elif defined(PETSC_HAVE_STRICMP) 582 else c = stricmp(a,b); 583 #else 584 else { 585 char *aa,*bb; 586 PetscErrorCode ierr; 587 ierr = PetscStrallocpy(a,&aa);CHKERRQ(ierr); 588 ierr = PetscStrallocpy(b,&bb);CHKERRQ(ierr); 589 ierr = PetscStrtolower(aa);CHKERRQ(ierr); 590 ierr = PetscStrtolower(bb);CHKERRQ(ierr); 591 ierr = PetscStrcmp(aa,bb,t);CHKERRQ(ierr); 592 ierr = PetscFree(aa);CHKERRQ(ierr); 593 ierr = PetscFree(bb);CHKERRQ(ierr); 594 PetscFunctionReturn(0); 595 } 596 #endif 597 if (!c) *t = PETSC_TRUE; 598 else *t = PETSC_FALSE; 599 PetscFunctionReturn(0); 600 } 601 602 /*@C 603 PetscStrncmp - Compares two strings, up to a certain length 604 605 Not Collective 606 607 Input Parameters: 608 + a - pointer to first string 609 . b - pointer to second string 610 - n - length to compare up to 611 612 Output Parameter: 613 . t - if the two strings are equal 614 615 Level: intermediate 616 617 Notes: 618 Not for use in Fortran 619 620 .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp() 621 622 @*/ 623 PetscErrorCode PetscStrncmp(const char a[],const char b[],size_t n,PetscBool *t) 624 { 625 int c; 626 627 PetscFunctionBegin; 628 c = strncmp(a,b,n); 629 if (!c) *t = PETSC_TRUE; 630 else *t = PETSC_FALSE; 631 PetscFunctionReturn(0); 632 } 633 634 /*@C 635 PetscStrchr - Locates first occurrence of a character in a string 636 637 Not Collective 638 639 Input Parameters: 640 + a - pointer to string 641 - b - character 642 643 Output Parameter: 644 . c - location of occurrence, NULL if not found 645 646 Level: intermediate 647 648 Notes: 649 Not for use in Fortran 650 651 @*/ 652 PetscErrorCode PetscStrchr(const char a[],char b,char *c[]) 653 { 654 PetscFunctionBegin; 655 *c = (char*)strchr(a,b); 656 PetscFunctionReturn(0); 657 } 658 659 /*@C 660 PetscStrrchr - Locates one location past the last occurrence of a character in a string, 661 if the character is not found then returns entire string 662 663 Not Collective 664 665 Input Parameters: 666 + a - pointer to string 667 - b - character 668 669 Output Parameter: 670 . tmp - location of occurrence, a if not found 671 672 Level: intermediate 673 674 Notes: 675 Not for use in Fortran 676 677 @*/ 678 PetscErrorCode PetscStrrchr(const char a[],char b,char *tmp[]) 679 { 680 PetscFunctionBegin; 681 *tmp = (char*)strrchr(a,b); 682 if (!*tmp) *tmp = (char*)a; 683 else *tmp = *tmp + 1; 684 PetscFunctionReturn(0); 685 } 686 687 /*@C 688 PetscStrtolower - Converts string to lower case 689 690 Not Collective 691 692 Input Parameters: 693 . a - pointer to string 694 695 Level: intermediate 696 697 Notes: 698 Not for use in Fortran 699 700 @*/ 701 PetscErrorCode PetscStrtolower(char a[]) 702 { 703 PetscFunctionBegin; 704 while (*a) { 705 if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A'; 706 a++; 707 } 708 PetscFunctionReturn(0); 709 } 710 711 /*@C 712 PetscStrtoupper - Converts string to upper case 713 714 Not Collective 715 716 Input Parameters: 717 . a - pointer to string 718 719 Level: intermediate 720 721 Notes: 722 Not for use in Fortran 723 724 @*/ 725 PetscErrorCode PetscStrtoupper(char a[]) 726 { 727 PetscFunctionBegin; 728 while (*a) { 729 if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a'; 730 a++; 731 } 732 PetscFunctionReturn(0); 733 } 734 735 /*@C 736 PetscStrendswith - Determines if a string ends with a certain string 737 738 Not Collective 739 740 Input Parameters: 741 + a - pointer to string 742 - b - string to endwith 743 744 Output Parameter: 745 . flg - PETSC_TRUE or PETSC_FALSE 746 747 Notes: 748 Not for use in Fortran 749 750 Level: intermediate 751 752 @*/ 753 PetscErrorCode PetscStrendswith(const char a[],const char b[],PetscBool *flg) 754 { 755 char *test; 756 PetscErrorCode ierr; 757 size_t na,nb; 758 759 PetscFunctionBegin; 760 *flg = PETSC_FALSE; 761 ierr = PetscStrrstr(a,b,&test);CHKERRQ(ierr); 762 if (test) { 763 ierr = PetscStrlen(a,&na);CHKERRQ(ierr); 764 ierr = PetscStrlen(b,&nb);CHKERRQ(ierr); 765 if (a+na-nb == test) *flg = PETSC_TRUE; 766 } 767 PetscFunctionReturn(0); 768 } 769 770 /*@C 771 PetscStrbeginswith - Determines if a string begins with a certain string 772 773 Not Collective 774 775 Input Parameters: 776 + a - pointer to string 777 - b - string to begin with 778 779 Output Parameter: 780 . flg - PETSC_TRUE or PETSC_FALSE 781 782 Notes: 783 Not for use in Fortran 784 785 Level: intermediate 786 787 .seealso: PetscStrendswithwhich(), PetscStrendswith(), PetscStrtoupper, PetscStrtolower(), PetscStrrchr(), PetscStrchr(), 788 PetscStrncmp(), PetscStrlen(), PetscStrncmp(), PetscStrcmp() 789 790 @*/ 791 PetscErrorCode PetscStrbeginswith(const char a[],const char b[],PetscBool *flg) 792 { 793 char *test; 794 PetscErrorCode ierr; 795 796 PetscFunctionBegin; 797 *flg = PETSC_FALSE; 798 ierr = PetscStrrstr(a,b,&test);CHKERRQ(ierr); 799 if (test && (test == a)) *flg = PETSC_TRUE; 800 PetscFunctionReturn(0); 801 } 802 803 /*@C 804 PetscStrendswithwhich - Determines if a string ends with one of several possible strings 805 806 Not Collective 807 808 Input Parameters: 809 + a - pointer to string 810 - bs - strings to end with (last entry must be NULL) 811 812 Output Parameter: 813 . cnt - the index of the string it ends with or the index of NULL 814 815 Notes: 816 Not for use in Fortran 817 818 Level: intermediate 819 820 @*/ 821 PetscErrorCode PetscStrendswithwhich(const char a[],const char *const *bs,PetscInt *cnt) 822 { 823 PetscBool flg; 824 PetscErrorCode ierr; 825 826 PetscFunctionBegin; 827 *cnt = 0; 828 while (bs[*cnt]) { 829 ierr = PetscStrendswith(a,bs[*cnt],&flg);CHKERRQ(ierr); 830 if (flg) PetscFunctionReturn(0); 831 *cnt += 1; 832 } 833 PetscFunctionReturn(0); 834 } 835 836 /*@C 837 PetscStrrstr - Locates last occurrence of string in another string 838 839 Not Collective 840 841 Input Parameters: 842 + a - pointer to string 843 - b - string to find 844 845 Output Parameter: 846 . tmp - location of occurrence 847 848 Notes: 849 Not for use in Fortran 850 851 Level: intermediate 852 853 @*/ 854 PetscErrorCode PetscStrrstr(const char a[],const char b[],char *tmp[]) 855 { 856 const char *stmp = a, *ltmp = NULL; 857 858 PetscFunctionBegin; 859 while (stmp) { 860 stmp = (char*)strstr(stmp,b); 861 if (stmp) {ltmp = stmp;stmp++;} 862 } 863 *tmp = (char*)ltmp; 864 PetscFunctionReturn(0); 865 } 866 867 /*@C 868 PetscStrstr - Locates first occurrence of string in another string 869 870 Not Collective 871 872 Input Parameters: 873 + haystack - string to search 874 - needle - string to find 875 876 Output Parameter: 877 . tmp - location of occurrence, is a NULL if the string is not found 878 879 Notes: 880 Not for use in Fortran 881 882 Level: intermediate 883 884 @*/ 885 PetscErrorCode PetscStrstr(const char haystack[],const char needle[],char *tmp[]) 886 { 887 PetscFunctionBegin; 888 *tmp = (char*)strstr(haystack,needle); 889 PetscFunctionReturn(0); 890 } 891 892 struct _p_PetscToken {char token;char *array;char *current;}; 893 894 /*@C 895 PetscTokenFind - Locates next "token" in a string 896 897 Not Collective 898 899 Input Parameters: 900 . a - pointer to token 901 902 Output Parameter: 903 . result - location of occurrence, NULL if not found 904 905 Notes: 906 907 This version is different from the system version in that 908 it allows you to pass a read-only string into the function. 909 910 This version also treats all characters etc. inside a double quote " 911 as a single token. 912 913 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 914 second will return a null terminated y 915 916 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 917 918 Not for use in Fortran 919 920 Level: intermediate 921 922 .seealso: PetscTokenCreate(), PetscTokenDestroy() 923 @*/ 924 PetscErrorCode PetscTokenFind(PetscToken a,char *result[]) 925 { 926 char *ptr = a->current,token; 927 928 PetscFunctionBegin; 929 *result = a->current; 930 if (ptr && !*ptr) {*result = NULL; PetscFunctionReturn(0);} 931 token = a->token; 932 if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;} 933 while (ptr) { 934 if (*ptr == token) { 935 *ptr++ = 0; 936 while (*ptr == a->token) ptr++; 937 a->current = ptr; 938 break; 939 } 940 if (!*ptr) { 941 a->current = NULL; 942 break; 943 } 944 ptr++; 945 } 946 PetscFunctionReturn(0); 947 } 948 949 /*@C 950 PetscTokenCreate - Creates a PetscToken used to find tokens in a string 951 952 Not Collective 953 954 Input Parameters: 955 + string - the string to look in 956 - b - the separator character 957 958 Output Parameter: 959 . t- the token object 960 961 Notes: 962 963 This version is different from the system version in that 964 it allows you to pass a read-only string into the function. 965 966 Not for use in Fortran 967 968 Level: intermediate 969 970 .seealso: PetscTokenFind(), PetscTokenDestroy() 971 @*/ 972 PetscErrorCode PetscTokenCreate(const char a[],const char b,PetscToken *t) 973 { 974 PetscErrorCode ierr; 975 976 PetscFunctionBegin; 977 ierr = PetscNew(t);CHKERRQ(ierr); 978 ierr = PetscStrallocpy(a,&(*t)->array);CHKERRQ(ierr); 979 980 (*t)->current = (*t)->array; 981 (*t)->token = b; 982 PetscFunctionReturn(0); 983 } 984 985 /*@C 986 PetscTokenDestroy - Destroys a PetscToken 987 988 Not Collective 989 990 Input Parameters: 991 . a - pointer to token 992 993 Level: intermediate 994 995 Notes: 996 Not for use in Fortran 997 998 .seealso: PetscTokenCreate(), PetscTokenFind() 999 @*/ 1000 PetscErrorCode PetscTokenDestroy(PetscToken *a) 1001 { 1002 PetscErrorCode ierr; 1003 1004 PetscFunctionBegin; 1005 if (!*a) PetscFunctionReturn(0); 1006 ierr = PetscFree((*a)->array);CHKERRQ(ierr); 1007 ierr = PetscFree(*a);CHKERRQ(ierr); 1008 PetscFunctionReturn(0); 1009 } 1010 1011 /*@C 1012 PetscStrInList - search string in character-delimited list 1013 1014 Not Collective 1015 1016 Input Parameters: 1017 + str - the string to look for 1018 . list - the list to search in 1019 - sep - the separator character 1020 1021 Output Parameter: 1022 . found - whether str is in list 1023 1024 Level: intermediate 1025 1026 Notes: 1027 Not for use in Fortran 1028 1029 .seealso: PetscTokenCreate(), PetscTokenFind(), PetscStrcmp() 1030 @*/ 1031 PetscErrorCode PetscStrInList(const char str[],const char list[],char sep,PetscBool *found) 1032 { 1033 PetscToken token; 1034 char *item; 1035 PetscErrorCode ierr; 1036 1037 PetscFunctionBegin; 1038 *found = PETSC_FALSE; 1039 ierr = PetscTokenCreate(list,sep,&token);CHKERRQ(ierr); 1040 ierr = PetscTokenFind(token,&item);CHKERRQ(ierr); 1041 while (item) { 1042 ierr = PetscStrcmp(str,item,found);CHKERRQ(ierr); 1043 if (*found) break; 1044 ierr = PetscTokenFind(token,&item);CHKERRQ(ierr); 1045 } 1046 ierr = PetscTokenDestroy(&token);CHKERRQ(ierr); 1047 PetscFunctionReturn(0); 1048 } 1049 1050 /*@C 1051 PetscGetPetscDir - Gets the directory PETSc is installed in 1052 1053 Not Collective 1054 1055 Output Parameter: 1056 . dir - the directory 1057 1058 Level: developer 1059 1060 Notes: 1061 Not for use in Fortran 1062 1063 @*/ 1064 PetscErrorCode PetscGetPetscDir(const char *dir[]) 1065 { 1066 PetscFunctionBegin; 1067 *dir = PETSC_DIR; 1068 PetscFunctionReturn(0); 1069 } 1070 1071 /*@C 1072 PetscStrreplace - Replaces substrings in string with other substrings 1073 1074 Not Collective 1075 1076 Input Parameters: 1077 + comm - MPI_Comm of processors that are processing the string 1078 . aa - the string to look in 1079 . b - the resulting copy of a with replaced strings (b can be the same as a) 1080 - len - the length of b 1081 1082 Notes: 1083 Replaces ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY}, 1084 ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values 1085 as well as any environmental variables. 1086 1087 PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what 1088 PETSc was built with and do not use environmental variables. 1089 1090 Not for use in Fortran 1091 1092 Level: intermediate 1093 1094 @*/ 1095 PetscErrorCode PetscStrreplace(MPI_Comm comm,const char aa[],char b[],size_t len) 1096 { 1097 PetscErrorCode ierr; 1098 int i = 0; 1099 size_t l,l1,l2,l3; 1100 char *work,*par,*epar,env[1024],*tfree,*a = (char*)aa; 1101 const char *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}","${HOSTNAME}",NULL}; 1102 char *r[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; 1103 PetscBool flag; 1104 static size_t DISPLAY_LENGTH = 265,USER_LENGTH = 256, HOST_LENGTH = 256; 1105 1106 PetscFunctionBegin; 1107 PetscCheckFalse(!a || !b,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"a and b strings must be nonnull"); 1108 if (aa == b) { 1109 ierr = PetscStrallocpy(aa,(char**)&a);CHKERRQ(ierr); 1110 } 1111 ierr = PetscMalloc1(len,&work);CHKERRQ(ierr); 1112 1113 /* get values for replaced variables */ 1114 ierr = PetscStrallocpy(PETSC_ARCH,&r[0]);CHKERRQ(ierr); 1115 ierr = PetscStrallocpy(PETSC_DIR,&r[1]);CHKERRQ(ierr); 1116 ierr = PetscStrallocpy(PETSC_LIB_DIR,&r[2]);CHKERRQ(ierr); 1117 ierr = PetscMalloc1(DISPLAY_LENGTH,&r[3]);CHKERRQ(ierr); 1118 ierr = PetscMalloc1(PETSC_MAX_PATH_LEN,&r[4]);CHKERRQ(ierr); 1119 ierr = PetscMalloc1(PETSC_MAX_PATH_LEN,&r[5]);CHKERRQ(ierr); 1120 ierr = PetscMalloc1(USER_LENGTH,&r[6]);CHKERRQ(ierr); 1121 ierr = PetscMalloc1(HOST_LENGTH,&r[7]);CHKERRQ(ierr); 1122 ierr = PetscGetDisplay(r[3],DISPLAY_LENGTH);CHKERRQ(ierr); 1123 ierr = PetscGetHomeDirectory(r[4],PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 1124 ierr = PetscGetWorkingDirectory(r[5],PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 1125 ierr = PetscGetUserName(r[6],USER_LENGTH);CHKERRQ(ierr); 1126 ierr = PetscGetHostName(r[7],HOST_LENGTH);CHKERRQ(ierr); 1127 1128 /* replace that are in environment */ 1129 ierr = PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,sizeof(env),&flag);CHKERRQ(ierr); 1130 if (flag) { 1131 ierr = PetscFree(r[2]);CHKERRQ(ierr); 1132 ierr = PetscStrallocpy(env,&r[2]);CHKERRQ(ierr); 1133 } 1134 1135 /* replace the requested strings */ 1136 ierr = PetscStrncpy(b,a,len);CHKERRQ(ierr); 1137 while (s[i]) { 1138 ierr = PetscStrlen(s[i],&l);CHKERRQ(ierr); 1139 ierr = PetscStrstr(b,s[i],&par);CHKERRQ(ierr); 1140 while (par) { 1141 *par = 0; 1142 par += l; 1143 1144 ierr = PetscStrlen(b,&l1);CHKERRQ(ierr); 1145 ierr = PetscStrlen(r[i],&l2);CHKERRQ(ierr); 1146 ierr = PetscStrlen(par,&l3);CHKERRQ(ierr); 1147 PetscCheckFalse(l1 + l2 + l3 >= len,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values"); 1148 ierr = PetscStrncpy(work,b,len);CHKERRQ(ierr); 1149 ierr = PetscStrlcat(work,r[i],len);CHKERRQ(ierr); 1150 ierr = PetscStrlcat(work,par,len);CHKERRQ(ierr); 1151 ierr = PetscStrncpy(b,work,len);CHKERRQ(ierr); 1152 ierr = PetscStrstr(b,s[i],&par);CHKERRQ(ierr); 1153 } 1154 i++; 1155 } 1156 i = 0; 1157 while (r[i]) { 1158 tfree = (char*)r[i]; 1159 ierr = PetscFree(tfree);CHKERRQ(ierr); 1160 i++; 1161 } 1162 1163 /* look for any other ${xxx} strings to replace from environmental variables */ 1164 ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr); 1165 while (par) { 1166 *par = 0; 1167 par += 2; 1168 ierr = PetscStrncpy(work,b,len);CHKERRQ(ierr); 1169 ierr = PetscStrstr(par,"}",&epar);CHKERRQ(ierr); 1170 *epar = 0; 1171 epar += 1; 1172 ierr = PetscOptionsGetenv(comm,par,env,sizeof(env),&flag);CHKERRQ(ierr); 1173 PetscCheckFalse(!flag,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par); 1174 ierr = PetscStrlcat(work,env,len);CHKERRQ(ierr); 1175 ierr = PetscStrlcat(work,epar,len);CHKERRQ(ierr); 1176 ierr = PetscStrncpy(b,work,len);CHKERRQ(ierr); 1177 ierr = PetscStrstr(b,"${",&par);CHKERRQ(ierr); 1178 } 1179 ierr = PetscFree(work);CHKERRQ(ierr); 1180 if (aa == b) { 1181 ierr = PetscFree(a);CHKERRQ(ierr); 1182 } 1183 PetscFunctionReturn(0); 1184 } 1185 1186 /*@C 1187 PetscEListFind - searches list of strings for given string, using case insensitive matching 1188 1189 Not Collective 1190 1191 Input Parameters: 1192 + n - number of strings in 1193 . list - list of strings to search 1194 - str - string to look for, empty string "" accepts default (first entry in list) 1195 1196 Output Parameters: 1197 + value - index of matching string (if found) 1198 - found - boolean indicating whether string was found (can be NULL) 1199 1200 Notes: 1201 Not for use in Fortran 1202 1203 Level: advanced 1204 @*/ 1205 PetscErrorCode PetscEListFind(PetscInt n,const char *const *list,const char *str,PetscInt *value,PetscBool *found) 1206 { 1207 PetscErrorCode ierr; 1208 PetscBool matched; 1209 PetscInt i; 1210 1211 PetscFunctionBegin; 1212 if (found) *found = PETSC_FALSE; 1213 for (i=0; i<n; i++) { 1214 ierr = PetscStrcasecmp(str,list[i],&matched);CHKERRQ(ierr); 1215 if (matched || !str[0]) { 1216 if (found) *found = PETSC_TRUE; 1217 *value = i; 1218 break; 1219 } 1220 } 1221 PetscFunctionReturn(0); 1222 } 1223 1224 /*@C 1225 PetscEnumFind - searches enum list of strings for given string, using case insensitive matching 1226 1227 Not Collective 1228 1229 Input Parameters: 1230 + enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL 1231 - str - string to look for 1232 1233 Output Parameters: 1234 + value - index of matching string (if found) 1235 - found - boolean indicating whether string was found (can be NULL) 1236 1237 Notes: 1238 Not for use in Fortran 1239 1240 Level: advanced 1241 @*/ 1242 PetscErrorCode PetscEnumFind(const char *const *enumlist,const char *str,PetscEnum *value,PetscBool *found) 1243 { 1244 PetscErrorCode ierr; 1245 PetscInt n = 0,evalue; 1246 PetscBool efound; 1247 1248 PetscFunctionBegin; 1249 while (enumlist[n++]) PetscCheckFalse(n > 50,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument appears to be wrong or have more than 50 entries"); 1250 PetscCheckFalse(n < 3,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument must have at least two entries: typename and type prefix"); 1251 n -= 3; /* drop enum name, prefix, and null termination */ 1252 ierr = PetscEListFind(n,enumlist,str,&evalue,&efound);CHKERRQ(ierr); 1253 if (efound) *value = (PetscEnum)evalue; 1254 if (found) *found = efound; 1255 PetscFunctionReturn(0); 1256 } 1257