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