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 CHKERRQ(PetscStrlen(s,&len)); 182 CHKERRQ(PetscMalloc1(1+len,&tmp)); 183 CHKERRQ(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 CHKERRQ(PetscMalloc1(n+1,t)); 218 for (PetscInt i=0; i<n; i++) CHKERRQ(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 CHKERRQ(PetscFree((*list)[n])); 247 ++n; 248 } 249 CHKERRQ(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 CHKERRQ(PetscMalloc1(n,t)); 277 for (PetscInt i=0; i<n; i++) CHKERRQ(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++) CHKERRQ(PetscFree((*list)[i])); 303 CHKERRQ(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 CHKERRQ(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 PetscErrorCode ierr; 563 CHKERRQ(PetscStrallocpy(a,&aa)); 564 CHKERRQ(PetscStrallocpy(b,&bb)); 565 CHKERRQ(PetscStrtolower(aa)); 566 CHKERRQ(PetscStrtolower(bb)); 567 CHKERRQ(PetscStrcmp(aa,bb,t)); 568 CHKERRQ(PetscFree(aa)); 569 CHKERRQ(PetscFree(bb)); 570 PetscFunctionReturn(0); 571 } 572 #endif 573 *t = c ? PETSC_FALSE : PETSC_TRUE; 574 PetscFunctionReturn(0); 575 } 576 577 /*@C 578 PetscStrncmp - Compares two strings, up to a certain length 579 580 Not Collective 581 582 Input Parameters: 583 + a - pointer to first string 584 . b - pointer to second string 585 - n - length to compare up to 586 587 Output Parameter: 588 . t - if the two strings are equal 589 590 Level: intermediate 591 592 Notes: 593 Not for use in Fortran 594 595 .seealso: PetscStrgrt(), PetscStrcmp(), PetscStrcasecmp() 596 597 @*/ 598 PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t) 599 { 600 PetscFunctionBegin; 601 if (n) { 602 PetscValidCharPointer(a,1); 603 PetscValidCharPointer(b,2); 604 } 605 PetscValidBoolPointer(t,4); 606 *t = strncmp(a,b,n) ? PETSC_FALSE : PETSC_TRUE; 607 PetscFunctionReturn(0); 608 } 609 610 /*@C 611 PetscStrchr - Locates first occurrence of a character in a string 612 613 Not Collective 614 615 Input Parameters: 616 + a - pointer to string 617 - b - character 618 619 Output Parameter: 620 . c - location of occurrence, NULL if not found 621 622 Level: intermediate 623 624 Notes: 625 Not for use in Fortran 626 627 @*/ 628 PetscErrorCode PetscStrchr(const char a[], char b, char *c[]) 629 { 630 PetscFunctionBegin; 631 PetscValidCharPointer(a,1); 632 PetscValidPointer(c,3); 633 *c = (char*)strchr(a,b); 634 PetscFunctionReturn(0); 635 } 636 637 /*@C 638 PetscStrrchr - Locates one location past the last occurrence of a character in a string, 639 if the character is not found then returns entire string 640 641 Not Collective 642 643 Input Parameters: 644 + a - pointer to string 645 - b - character 646 647 Output Parameter: 648 . tmp - location of occurrence, a if not found 649 650 Level: intermediate 651 652 Notes: 653 Not for use in Fortran 654 655 @*/ 656 PetscErrorCode PetscStrrchr(const char a[], char b, char *tmp[]) 657 { 658 PetscFunctionBegin; 659 PetscValidCharPointer(a,1); 660 PetscValidPointer(tmp,3); 661 *tmp = (char*)strrchr(a,b); 662 if (!*tmp) *tmp = (char*)a; 663 else *tmp = *tmp + 1; 664 PetscFunctionReturn(0); 665 } 666 667 /*@C 668 PetscStrtolower - Converts string to lower case 669 670 Not Collective 671 672 Input Parameters: 673 . a - pointer to string 674 675 Level: intermediate 676 677 Notes: 678 Not for use in Fortran 679 680 @*/ 681 PetscErrorCode PetscStrtolower(char a[]) 682 { 683 PetscFunctionBegin; 684 PetscValidCharPointer(a,1); 685 while (*a) { 686 if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A'; 687 a++; 688 } 689 PetscFunctionReturn(0); 690 } 691 692 /*@C 693 PetscStrtoupper - Converts string to upper case 694 695 Not Collective 696 697 Input Parameters: 698 . a - pointer to string 699 700 Level: intermediate 701 702 Notes: 703 Not for use in Fortran 704 705 @*/ 706 PetscErrorCode PetscStrtoupper(char a[]) 707 { 708 PetscFunctionBegin; 709 PetscValidCharPointer(a,1); 710 while (*a) { 711 if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a'; 712 a++; 713 } 714 PetscFunctionReturn(0); 715 } 716 717 /*@C 718 PetscStrendswith - Determines if a string ends with a certain string 719 720 Not Collective 721 722 Input Parameters: 723 + a - pointer to string 724 - b - string to endwith 725 726 Output Parameter: 727 . flg - PETSC_TRUE or PETSC_FALSE 728 729 Notes: 730 Not for use in Fortran 731 732 Level: intermediate 733 734 @*/ 735 PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg) 736 { 737 char *test; 738 739 PetscFunctionBegin; 740 PetscValidBoolPointer(flg,3); 741 *flg = PETSC_FALSE; 742 CHKERRQ(PetscStrrstr(a,b,&test)); 743 if (test) { 744 size_t na,nb; 745 746 CHKERRQ(PetscStrlen(a,&na)); 747 CHKERRQ(PetscStrlen(b,&nb)); 748 if (a+na-nb == test) *flg = PETSC_TRUE; 749 } 750 PetscFunctionReturn(0); 751 } 752 753 /*@C 754 PetscStrbeginswith - Determines if a string begins with a certain string 755 756 Not Collective 757 758 Input Parameters: 759 + a - pointer to string 760 - b - string to begin with 761 762 Output Parameter: 763 . flg - PETSC_TRUE or PETSC_FALSE 764 765 Notes: 766 Not for use in Fortran 767 768 Level: intermediate 769 770 .seealso: PetscStrendswithwhich(), PetscStrendswith(), PetscStrtoupper, PetscStrtolower(), PetscStrrchr(), PetscStrchr(), 771 PetscStrncmp(), PetscStrlen(), PetscStrncmp(), PetscStrcmp() 772 773 @*/ 774 PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg) 775 { 776 char *test; 777 778 PetscFunctionBegin; 779 PetscValidCharPointer(a,1); 780 PetscValidCharPointer(b,2); 781 PetscValidBoolPointer(flg,3); 782 *flg = PETSC_FALSE; 783 CHKERRQ(PetscStrrstr(a,b,&test)); 784 if (test && (test == a)) *flg = PETSC_TRUE; 785 PetscFunctionReturn(0); 786 } 787 788 /*@C 789 PetscStrendswithwhich - Determines if a string ends with one of several possible strings 790 791 Not Collective 792 793 Input Parameters: 794 + a - pointer to string 795 - bs - strings to end with (last entry must be NULL) 796 797 Output Parameter: 798 . cnt - the index of the string it ends with or the index of NULL 799 800 Notes: 801 Not for use in Fortran 802 803 Level: intermediate 804 805 @*/ 806 PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt) 807 { 808 PetscFunctionBegin; 809 PetscValidPointer(bs,2); 810 PetscValidIntPointer(cnt,3); 811 *cnt = 0; 812 while (bs[*cnt]) { 813 PetscBool flg; 814 815 CHKERRQ(PetscStrendswith(a,bs[*cnt],&flg)); 816 if (flg) PetscFunctionReturn(0); 817 ++(*cnt); 818 } 819 PetscFunctionReturn(0); 820 } 821 822 /*@C 823 PetscStrrstr - Locates last occurrence of string in another string 824 825 Not Collective 826 827 Input Parameters: 828 + a - pointer to string 829 - b - string to find 830 831 Output Parameter: 832 . tmp - location of occurrence 833 834 Notes: 835 Not for use in Fortran 836 837 Level: intermediate 838 839 @*/ 840 PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[]) 841 { 842 const char *ltmp = NULL; 843 844 PetscFunctionBegin; 845 PetscValidCharPointer(a,1); 846 PetscValidCharPointer(b,2); 847 PetscValidPointer(tmp,3); 848 while (a) { 849 a = (char*)strstr(a,b); 850 if (a) ltmp = a++; 851 } 852 *tmp = (char*)ltmp; 853 PetscFunctionReturn(0); 854 } 855 856 /*@C 857 PetscStrstr - Locates first occurrence of string in another string 858 859 Not Collective 860 861 Input Parameters: 862 + haystack - string to search 863 - needle - string to find 864 865 Output Parameter: 866 . tmp - location of occurrence, is a NULL if the string is not found 867 868 Notes: 869 Not for use in Fortran 870 871 Level: intermediate 872 873 @*/ 874 PetscErrorCode PetscStrstr(const char haystack[],const char needle[],char *tmp[]) 875 { 876 PetscFunctionBegin; 877 PetscValidCharPointer(haystack,1); 878 PetscValidCharPointer(needle,2); 879 PetscValidPointer(tmp,3); 880 *tmp = (char*)strstr(haystack,needle); 881 PetscFunctionReturn(0); 882 } 883 884 struct _p_PetscToken {char token;char *array;char *current;}; 885 886 /*@C 887 PetscTokenFind - Locates next "token" in a string 888 889 Not Collective 890 891 Input Parameters: 892 . a - pointer to token 893 894 Output Parameter: 895 . result - location of occurrence, NULL if not found 896 897 Notes: 898 899 This version is different from the system version in that 900 it allows you to pass a read-only string into the function. 901 902 This version also treats all characters etc. inside a double quote " 903 as a single token. 904 905 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 906 second will return a null terminated y 907 908 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 909 910 Not for use in Fortran 911 912 Level: intermediate 913 914 .seealso: PetscTokenCreate(), PetscTokenDestroy() 915 @*/ 916 PetscErrorCode PetscTokenFind(PetscToken a, char *result[]) 917 { 918 char *ptr,token; 919 920 PetscFunctionBegin; 921 PetscValidPointer(a,1); 922 PetscValidPointer(result,2); 923 *result = ptr = a->current; 924 if (ptr && !*ptr) {*result = NULL; PetscFunctionReturn(0);} 925 token = a->token; 926 if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;} 927 while (ptr) { 928 if (*ptr == token) { 929 *ptr++ = 0; 930 while (*ptr == a->token) ptr++; 931 a->current = ptr; 932 break; 933 } 934 if (!*ptr) { 935 a->current = NULL; 936 break; 937 } 938 ptr++; 939 } 940 PetscFunctionReturn(0); 941 } 942 943 /*@C 944 PetscTokenCreate - Creates a PetscToken used to find tokens in a string 945 946 Not Collective 947 948 Input Parameters: 949 + string - the string to look in 950 - b - the separator character 951 952 Output Parameter: 953 . t- the token object 954 955 Notes: 956 957 This version is different from the system version in that 958 it allows you to pass a read-only string into the function. 959 960 Not for use in Fortran 961 962 Level: intermediate 963 964 .seealso: PetscTokenFind(), PetscTokenDestroy() 965 @*/ 966 PetscErrorCode PetscTokenCreate(const char a[], const char b, PetscToken *t) 967 { 968 PetscFunctionBegin; 969 PetscValidCharPointer(a,1); 970 PetscValidPointer(t,3); 971 CHKERRQ(PetscNew(t)); 972 CHKERRQ(PetscStrallocpy(a,&(*t)->array)); 973 974 (*t)->current = (*t)->array; 975 (*t)->token = b; 976 PetscFunctionReturn(0); 977 } 978 979 /*@C 980 PetscTokenDestroy - Destroys a PetscToken 981 982 Not Collective 983 984 Input Parameters: 985 . a - pointer to token 986 987 Level: intermediate 988 989 Notes: 990 Not for use in Fortran 991 992 .seealso: PetscTokenCreate(), PetscTokenFind() 993 @*/ 994 PetscErrorCode PetscTokenDestroy(PetscToken *a) 995 { 996 PetscFunctionBegin; 997 if (!*a) PetscFunctionReturn(0); 998 CHKERRQ(PetscFree((*a)->array)); 999 CHKERRQ(PetscFree(*a)); 1000 PetscFunctionReturn(0); 1001 } 1002 1003 /*@C 1004 PetscStrInList - search string in character-delimited list 1005 1006 Not Collective 1007 1008 Input Parameters: 1009 + str - the string to look for 1010 . list - the list to search in 1011 - sep - the separator character 1012 1013 Output Parameter: 1014 . found - whether str is in list 1015 1016 Level: intermediate 1017 1018 Notes: 1019 Not for use in Fortran 1020 1021 .seealso: PetscTokenCreate(), PetscTokenFind(), PetscStrcmp() 1022 @*/ 1023 PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found) 1024 { 1025 PetscToken token; 1026 char *item; 1027 1028 PetscFunctionBegin; 1029 PetscValidBoolPointer(found,4); 1030 *found = PETSC_FALSE; 1031 CHKERRQ(PetscTokenCreate(list,sep,&token)); 1032 CHKERRQ(PetscTokenFind(token,&item)); 1033 while (item) { 1034 CHKERRQ(PetscStrcmp(str,item,found)); 1035 if (*found) break; 1036 CHKERRQ(PetscTokenFind(token,&item)); 1037 } 1038 CHKERRQ(PetscTokenDestroy(&token)); 1039 PetscFunctionReturn(0); 1040 } 1041 1042 /*@C 1043 PetscGetPetscDir - Gets the directory PETSc is installed in 1044 1045 Not Collective 1046 1047 Output Parameter: 1048 . dir - the directory 1049 1050 Level: developer 1051 1052 Notes: 1053 Not for use in Fortran 1054 1055 @*/ 1056 PetscErrorCode PetscGetPetscDir(const char *dir[]) 1057 { 1058 PetscFunctionBegin; 1059 PetscValidPointer(dir,1); 1060 *dir = PETSC_DIR; 1061 PetscFunctionReturn(0); 1062 } 1063 1064 /*@C 1065 PetscStrreplace - Replaces substrings in string with other substrings 1066 1067 Not Collective 1068 1069 Input Parameters: 1070 + comm - MPI_Comm of processors that are processing the string 1071 . aa - the string to look in 1072 . b - the resulting copy of a with replaced strings (b can be the same as a) 1073 - len - the length of b 1074 1075 Notes: 1076 Replaces ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY}, 1077 ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values 1078 as well as any environmental variables. 1079 1080 PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what 1081 PETSc was built with and do not use environmental variables. 1082 1083 Not for use in Fortran 1084 1085 Level: intermediate 1086 1087 @*/ 1088 PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len) 1089 { 1090 int i = 0; 1091 size_t l,l1,l2,l3; 1092 char *work,*par,*epar,env[1024],*tfree,*a = (char*)aa; 1093 const char *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}","${HOSTNAME}",NULL}; 1094 char *r[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; 1095 PetscBool flag; 1096 static size_t DISPLAY_LENGTH = 265,USER_LENGTH = 256, HOST_LENGTH = 256; 1097 1098 PetscFunctionBegin; 1099 PetscValidCharPointer(aa,2); 1100 PetscValidCharPointer(b,3); 1101 if (aa == b) CHKERRQ(PetscStrallocpy(aa,(char**)&a)); 1102 CHKERRQ(PetscMalloc1(len,&work)); 1103 1104 /* get values for replaced variables */ 1105 CHKERRQ(PetscStrallocpy(PETSC_ARCH,&r[0])); 1106 CHKERRQ(PetscStrallocpy(PETSC_DIR,&r[1])); 1107 CHKERRQ(PetscStrallocpy(PETSC_LIB_DIR,&r[2])); 1108 CHKERRQ(PetscMalloc1(DISPLAY_LENGTH,&r[3])); 1109 CHKERRQ(PetscMalloc1(PETSC_MAX_PATH_LEN,&r[4])); 1110 CHKERRQ(PetscMalloc1(PETSC_MAX_PATH_LEN,&r[5])); 1111 CHKERRQ(PetscMalloc1(USER_LENGTH,&r[6])); 1112 CHKERRQ(PetscMalloc1(HOST_LENGTH,&r[7])); 1113 CHKERRQ(PetscGetDisplay(r[3],DISPLAY_LENGTH)); 1114 CHKERRQ(PetscGetHomeDirectory(r[4],PETSC_MAX_PATH_LEN)); 1115 CHKERRQ(PetscGetWorkingDirectory(r[5],PETSC_MAX_PATH_LEN)); 1116 CHKERRQ(PetscGetUserName(r[6],USER_LENGTH)); 1117 CHKERRQ(PetscGetHostName(r[7],HOST_LENGTH)); 1118 1119 /* replace that are in environment */ 1120 CHKERRQ(PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,sizeof(env),&flag)); 1121 if (flag) { 1122 CHKERRQ(PetscFree(r[2])); 1123 CHKERRQ(PetscStrallocpy(env,&r[2])); 1124 } 1125 1126 /* replace the requested strings */ 1127 CHKERRQ(PetscStrncpy(b,a,len)); 1128 while (s[i]) { 1129 CHKERRQ(PetscStrlen(s[i],&l)); 1130 CHKERRQ(PetscStrstr(b,s[i],&par)); 1131 while (par) { 1132 *par = 0; 1133 par += l; 1134 1135 CHKERRQ(PetscStrlen(b,&l1)); 1136 CHKERRQ(PetscStrlen(r[i],&l2)); 1137 CHKERRQ(PetscStrlen(par,&l3)); 1138 PetscCheckFalse(l1 + l2 + l3 >= len,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values"); 1139 CHKERRQ(PetscStrncpy(work,b,len)); 1140 CHKERRQ(PetscStrlcat(work,r[i],len)); 1141 CHKERRQ(PetscStrlcat(work,par,len)); 1142 CHKERRQ(PetscStrncpy(b,work,len)); 1143 CHKERRQ(PetscStrstr(b,s[i],&par)); 1144 } 1145 i++; 1146 } 1147 i = 0; 1148 while (r[i]) { 1149 tfree = (char*)r[i]; 1150 CHKERRQ(PetscFree(tfree)); 1151 i++; 1152 } 1153 1154 /* look for any other ${xxx} strings to replace from environmental variables */ 1155 CHKERRQ(PetscStrstr(b,"${",&par)); 1156 while (par) { 1157 *par = 0; 1158 par += 2; 1159 CHKERRQ(PetscStrncpy(work,b,len)); 1160 CHKERRQ(PetscStrstr(par,"}",&epar)); 1161 *epar = 0; 1162 epar += 1; 1163 CHKERRQ(PetscOptionsGetenv(comm,par,env,sizeof(env),&flag)); 1164 PetscCheck(flag,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par); 1165 CHKERRQ(PetscStrlcat(work,env,len)); 1166 CHKERRQ(PetscStrlcat(work,epar,len)); 1167 CHKERRQ(PetscStrncpy(b,work,len)); 1168 CHKERRQ(PetscStrstr(b,"${",&par)); 1169 } 1170 CHKERRQ(PetscFree(work)); 1171 if (aa == b) CHKERRQ(PetscFree(a)); 1172 PetscFunctionReturn(0); 1173 } 1174 1175 /*@C 1176 PetscEListFind - searches list of strings for given string, using case insensitive matching 1177 1178 Not Collective 1179 1180 Input Parameters: 1181 + n - number of strings in 1182 . list - list of strings to search 1183 - str - string to look for, empty string "" accepts default (first entry in list) 1184 1185 Output Parameters: 1186 + value - index of matching string (if found) 1187 - found - boolean indicating whether string was found (can be NULL) 1188 1189 Notes: 1190 Not for use in Fortran 1191 1192 Level: advanced 1193 @*/ 1194 PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found) 1195 { 1196 PetscFunctionBegin; 1197 if (found) { 1198 PetscValidBoolPointer(found,5); 1199 *found = PETSC_FALSE; 1200 } 1201 for (PetscInt i = 0; i < n; ++i) { 1202 PetscBool matched; 1203 1204 CHKERRQ(PetscStrcasecmp(str,list[i],&matched)); 1205 if (matched || !str[0]) { 1206 if (found) *found = PETSC_TRUE; 1207 *value = i; 1208 break; 1209 } 1210 } 1211 PetscFunctionReturn(0); 1212 } 1213 1214 /*@C 1215 PetscEnumFind - searches enum list of strings for given string, using case insensitive matching 1216 1217 Not Collective 1218 1219 Input Parameters: 1220 + enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL 1221 - str - string to look for 1222 1223 Output Parameters: 1224 + value - index of matching string (if found) 1225 - found - boolean indicating whether string was found (can be NULL) 1226 1227 Notes: 1228 Not for use in Fortran 1229 1230 Level: advanced 1231 @*/ 1232 PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found) 1233 { 1234 PetscInt n = 0,evalue; 1235 PetscBool efound; 1236 1237 PetscFunctionBegin; 1238 PetscValidPointer(enumlist,1); 1239 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"); 1240 PetscCheck(n >= 3,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument must have at least two entries: typename and type prefix"); 1241 n -= 3; /* drop enum name, prefix, and null termination */ 1242 CHKERRQ(PetscEListFind(n,enumlist,str,&evalue,&efound)); 1243 if (efound) { 1244 PetscValidPointer(value,3); 1245 *value = (PetscEnum)evalue; 1246 } 1247 if (found) { 1248 PetscValidBoolPointer(found,4); 1249 *found = efound; 1250 } 1251 PetscFunctionReturn(0); 1252 } 1253