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 PetscBasename - returns a pointer to the last entry of a / or \ seperated directory path 459 460 Not Collective 461 462 Input Parameter: 463 . a - pointer to string 464 465 Level: intermediate 466 467 Notes: 468 Not for use in Fortran 469 470 Works for both Unix and Windows path separators 471 472 .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`, `PetscStrrchr()`,`PetscStrcmp()`,`PetscStrstr()`, 473 `PetscTokenCreate()`, `PetscStrToArray()`, `PetscStrInList()` 474 @*/ 475 const char *PetscBasename(const char a[]) 476 { 477 const char *ptr; 478 479 if (PetscStrrchr(a,'/',(char **)&ptr)) ptr = NULL; 480 if (ptr == a) { 481 if (PetscStrrchr(a,'\\',(char **)&ptr)) ptr = NULL; 482 } 483 return ptr; 484 } 485 486 /*@C 487 PetscStrcmp - Compares two strings, 488 489 Not Collective 490 491 Input Parameters: 492 + a - pointer to string first string 493 - b - pointer to second string 494 495 Output Parameter: 496 . flg - PETSC_TRUE if the two strings are equal 497 498 Level: intermediate 499 500 Notes: 501 Not for use in Fortran 502 503 .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()` 504 @*/ 505 PetscErrorCode PetscStrcmp(const char a[],const char b[],PetscBool *flg) 506 { 507 PetscFunctionBegin; 508 PetscValidBoolPointer(flg,3); 509 if (!a && !b) *flg = PETSC_TRUE; 510 else if (!a || !b) *flg = PETSC_FALSE; 511 else *flg = (PetscBool)!strcmp(a,b); 512 PetscFunctionReturn(0); 513 } 514 515 /*@C 516 PetscStrgrt - If first string is greater than the second 517 518 Not Collective 519 520 Input Parameters: 521 + a - pointer to first string 522 - b - pointer to second string 523 524 Output Parameter: 525 . flg - if the first string is greater 526 527 Notes: 528 Null arguments are ok, a null string is considered smaller than 529 all others 530 531 Not for use in Fortran 532 533 Level: intermediate 534 535 .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrcasecmp()` 536 537 @*/ 538 PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t) 539 { 540 PetscFunctionBegin; 541 PetscValidBoolPointer(t,3); 542 if (!a && !b) *t = PETSC_FALSE; 543 else if (a && !b) *t = PETSC_TRUE; 544 else if (!a && b) *t = PETSC_FALSE; 545 else { 546 PetscValidCharPointer(a,1); 547 PetscValidCharPointer(b,2); 548 *t = strcmp(a,b) > 0 ? PETSC_TRUE : PETSC_FALSE; 549 } 550 PetscFunctionReturn(0); 551 } 552 553 /*@C 554 PetscStrcasecmp - Returns true if the two strings are the same 555 except possibly for case. 556 557 Not Collective 558 559 Input Parameters: 560 + a - pointer to first string 561 - b - pointer to second string 562 563 Output Parameter: 564 . flg - if the two strings are the same 565 566 Notes: 567 Null arguments are ok 568 569 Not for use in Fortran 570 571 Level: intermediate 572 573 .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrgrt()` 574 575 @*/ 576 PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t) 577 { 578 int c; 579 580 PetscFunctionBegin; 581 PetscValidBoolPointer(t,3); 582 if (!a && !b) c = 0; 583 else if (!a || !b) c = 1; 584 #if defined(PETSC_HAVE_STRCASECMP) 585 else c = strcasecmp(a,b); 586 #elif defined(PETSC_HAVE_STRICMP) 587 else c = stricmp(a,b); 588 #else 589 else { 590 char *aa,*bb; 591 PetscCall(PetscStrallocpy(a,&aa)); 592 PetscCall(PetscStrallocpy(b,&bb)); 593 PetscCall(PetscStrtolower(aa)); 594 PetscCall(PetscStrtolower(bb)); 595 PetscCall(PetscStrcmp(aa,bb,t)); 596 PetscCall(PetscFree(aa)); 597 PetscCall(PetscFree(bb)); 598 PetscFunctionReturn(0); 599 } 600 #endif 601 *t = c ? PETSC_FALSE : PETSC_TRUE; 602 PetscFunctionReturn(0); 603 } 604 605 /*@C 606 PetscStrncmp - Compares two strings, up to a certain length 607 608 Not Collective 609 610 Input Parameters: 611 + a - pointer to first string 612 . b - pointer to second string 613 - n - length to compare up to 614 615 Output Parameter: 616 . t - if the two strings are equal 617 618 Level: intermediate 619 620 Notes: 621 Not for use in Fortran 622 623 .seealso: `PetscStrgrt()`, `PetscStrcmp()`, `PetscStrcasecmp()` 624 625 @*/ 626 PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t) 627 { 628 PetscFunctionBegin; 629 if (n) { 630 PetscValidCharPointer(a,1); 631 PetscValidCharPointer(b,2); 632 } 633 PetscValidBoolPointer(t,4); 634 *t = strncmp(a,b,n) ? PETSC_FALSE : PETSC_TRUE; 635 PetscFunctionReturn(0); 636 } 637 638 /*@C 639 PetscStrchr - Locates first occurrence of a character in a string 640 641 Not Collective 642 643 Input Parameters: 644 + a - pointer to string 645 - b - character 646 647 Output Parameter: 648 . c - location of occurrence, NULL if not found 649 650 Level: intermediate 651 652 Notes: 653 Not for use in Fortran 654 655 @*/ 656 PetscErrorCode PetscStrchr(const char a[], char b, char *c[]) 657 { 658 PetscFunctionBegin; 659 PetscValidCharPointer(a,1); 660 PetscValidPointer(c,3); 661 *c = (char*)strchr(a,b); 662 PetscFunctionReturn(0); 663 } 664 665 /*@C 666 PetscStrrchr - Locates one location past the last occurrence of a character in a string, 667 if the character is not found then returns entire string 668 669 Not Collective 670 671 Input Parameters: 672 + a - pointer to string 673 - b - character 674 675 Output Parameter: 676 . tmp - location of occurrence, a if not found 677 678 Level: intermediate 679 680 Notes: 681 Not for use in Fortran 682 683 @*/ 684 PetscErrorCode PetscStrrchr(const char a[], char b, char *tmp[]) 685 { 686 PetscFunctionBegin; 687 PetscValidCharPointer(a,1); 688 PetscValidPointer(tmp,3); 689 *tmp = (char*)strrchr(a,b); 690 if (!*tmp) *tmp = (char*)a; 691 else *tmp = *tmp + 1; 692 PetscFunctionReturn(0); 693 } 694 695 /*@C 696 PetscStrtolower - Converts string to lower case 697 698 Not Collective 699 700 Input Parameters: 701 . a - pointer to string 702 703 Level: intermediate 704 705 Notes: 706 Not for use in Fortran 707 708 @*/ 709 PetscErrorCode PetscStrtolower(char a[]) 710 { 711 PetscFunctionBegin; 712 PetscValidCharPointer(a,1); 713 while (*a) { 714 if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A'; 715 a++; 716 } 717 PetscFunctionReturn(0); 718 } 719 720 /*@C 721 PetscStrtoupper - Converts string to upper case 722 723 Not Collective 724 725 Input Parameters: 726 . a - pointer to string 727 728 Level: intermediate 729 730 Notes: 731 Not for use in Fortran 732 733 @*/ 734 PetscErrorCode PetscStrtoupper(char a[]) 735 { 736 PetscFunctionBegin; 737 PetscValidCharPointer(a,1); 738 while (*a) { 739 if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a'; 740 a++; 741 } 742 PetscFunctionReturn(0); 743 } 744 745 /*@C 746 PetscStrendswith - Determines if a string ends with a certain string 747 748 Not Collective 749 750 Input Parameters: 751 + a - pointer to string 752 - b - string to endwith 753 754 Output Parameter: 755 . flg - PETSC_TRUE or PETSC_FALSE 756 757 Notes: 758 Not for use in Fortran 759 760 Level: intermediate 761 762 @*/ 763 PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg) 764 { 765 char *test; 766 767 PetscFunctionBegin; 768 PetscValidBoolPointer(flg,3); 769 *flg = PETSC_FALSE; 770 PetscCall(PetscStrrstr(a,b,&test)); 771 if (test) { 772 size_t na,nb; 773 774 PetscCall(PetscStrlen(a,&na)); 775 PetscCall(PetscStrlen(b,&nb)); 776 if (a+na-nb == test) *flg = PETSC_TRUE; 777 } 778 PetscFunctionReturn(0); 779 } 780 781 /*@C 782 PetscStrbeginswith - Determines if a string begins with a certain string 783 784 Not Collective 785 786 Input Parameters: 787 + a - pointer to string 788 - b - string to begin with 789 790 Output Parameter: 791 . flg - PETSC_TRUE or PETSC_FALSE 792 793 Notes: 794 Not for use in Fortran 795 796 Level: intermediate 797 798 .seealso: `PetscStrendswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, 799 `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()` 800 801 @*/ 802 PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg) 803 { 804 char *test; 805 806 PetscFunctionBegin; 807 PetscValidCharPointer(a,1); 808 PetscValidCharPointer(b,2); 809 PetscValidBoolPointer(flg,3); 810 *flg = PETSC_FALSE; 811 PetscCall(PetscStrrstr(a,b,&test)); 812 if (test && (test == a)) *flg = PETSC_TRUE; 813 PetscFunctionReturn(0); 814 } 815 816 /*@C 817 PetscStrendswithwhich - Determines if a string ends with one of several possible strings 818 819 Not Collective 820 821 Input Parameters: 822 + a - pointer to string 823 - bs - strings to end with (last entry must be NULL) 824 825 Output Parameter: 826 . cnt - the index of the string it ends with or the index of NULL 827 828 Notes: 829 Not for use in Fortran 830 831 Level: intermediate 832 833 @*/ 834 PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt) 835 { 836 PetscFunctionBegin; 837 PetscValidPointer(bs,2); 838 PetscValidIntPointer(cnt,3); 839 *cnt = 0; 840 while (bs[*cnt]) { 841 PetscBool flg; 842 843 PetscCall(PetscStrendswith(a,bs[*cnt],&flg)); 844 if (flg) PetscFunctionReturn(0); 845 ++(*cnt); 846 } 847 PetscFunctionReturn(0); 848 } 849 850 /*@C 851 PetscStrrstr - Locates last occurrence of string in another string 852 853 Not Collective 854 855 Input Parameters: 856 + a - pointer to string 857 - b - string to find 858 859 Output Parameter: 860 . tmp - location of occurrence 861 862 Notes: 863 Not for use in Fortran 864 865 Level: intermediate 866 867 @*/ 868 PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[]) 869 { 870 const char *ltmp = NULL; 871 872 PetscFunctionBegin; 873 PetscValidCharPointer(a,1); 874 PetscValidCharPointer(b,2); 875 PetscValidPointer(tmp,3); 876 while (a) { 877 a = (char*)strstr(a,b); 878 if (a) ltmp = a++; 879 } 880 *tmp = (char*)ltmp; 881 PetscFunctionReturn(0); 882 } 883 884 /*@C 885 PetscStrstr - Locates first occurrence of string in another string 886 887 Not Collective 888 889 Input Parameters: 890 + haystack - string to search 891 - needle - string to find 892 893 Output Parameter: 894 . tmp - location of occurrence, is a NULL if the string is not found 895 896 Notes: 897 Not for use in Fortran 898 899 Level: intermediate 900 901 @*/ 902 PetscErrorCode PetscStrstr(const char haystack[],const char needle[],char *tmp[]) 903 { 904 PetscFunctionBegin; 905 PetscValidCharPointer(haystack,1); 906 PetscValidCharPointer(needle,2); 907 PetscValidPointer(tmp,3); 908 *tmp = (char*)strstr(haystack,needle); 909 PetscFunctionReturn(0); 910 } 911 912 struct _p_PetscToken {char token;char *array;char *current;}; 913 914 /*@C 915 PetscTokenFind - Locates next "token" in a string 916 917 Not Collective 918 919 Input Parameters: 920 . a - pointer to token 921 922 Output Parameter: 923 . result - location of occurrence, NULL if not found 924 925 Notes: 926 927 This version is different from the system version in that 928 it allows you to pass a read-only string into the function. 929 930 This version also treats all characters etc. inside a double quote " 931 as a single token. 932 933 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 934 second will return a null terminated y 935 936 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 937 938 Not for use in Fortran 939 940 Level: intermediate 941 942 .seealso: `PetscTokenCreate()`, `PetscTokenDestroy()` 943 @*/ 944 PetscErrorCode PetscTokenFind(PetscToken a, char *result[]) 945 { 946 char *ptr,token; 947 948 PetscFunctionBegin; 949 PetscValidPointer(a,1); 950 PetscValidPointer(result,2); 951 *result = ptr = a->current; 952 if (ptr && !*ptr) {*result = NULL; PetscFunctionReturn(0);} 953 token = a->token; 954 if (ptr && (*ptr == '"')) {token = '"';(*result)++;ptr++;} 955 while (ptr) { 956 if (*ptr == token) { 957 *ptr++ = 0; 958 while (*ptr == a->token) ptr++; 959 a->current = ptr; 960 break; 961 } 962 if (!*ptr) { 963 a->current = NULL; 964 break; 965 } 966 ptr++; 967 } 968 PetscFunctionReturn(0); 969 } 970 971 /*@C 972 PetscTokenCreate - Creates a PetscToken used to find tokens in a string 973 974 Not Collective 975 976 Input Parameters: 977 + string - the string to look in 978 - b - the separator character 979 980 Output Parameter: 981 . t- the token object 982 983 Notes: 984 985 This version is different from the system version in that 986 it allows you to pass a read-only string into the function. 987 988 Not for use in Fortran 989 990 Level: intermediate 991 992 .seealso: `PetscTokenFind()`, `PetscTokenDestroy()` 993 @*/ 994 PetscErrorCode PetscTokenCreate(const char a[], const char b, PetscToken *t) 995 { 996 PetscFunctionBegin; 997 PetscValidCharPointer(a,1); 998 PetscValidPointer(t,3); 999 PetscCall(PetscNew(t)); 1000 PetscCall(PetscStrallocpy(a,&(*t)->array)); 1001 1002 (*t)->current = (*t)->array; 1003 (*t)->token = b; 1004 PetscFunctionReturn(0); 1005 } 1006 1007 /*@C 1008 PetscTokenDestroy - Destroys a PetscToken 1009 1010 Not Collective 1011 1012 Input Parameters: 1013 . a - pointer to token 1014 1015 Level: intermediate 1016 1017 Notes: 1018 Not for use in Fortran 1019 1020 .seealso: `PetscTokenCreate()`, `PetscTokenFind()` 1021 @*/ 1022 PetscErrorCode PetscTokenDestroy(PetscToken *a) 1023 { 1024 PetscFunctionBegin; 1025 if (!*a) PetscFunctionReturn(0); 1026 PetscCall(PetscFree((*a)->array)); 1027 PetscCall(PetscFree(*a)); 1028 PetscFunctionReturn(0); 1029 } 1030 1031 /*@C 1032 PetscStrInList - search string in character-delimited list 1033 1034 Not Collective 1035 1036 Input Parameters: 1037 + str - the string to look for 1038 . list - the list to search in 1039 - sep - the separator character 1040 1041 Output Parameter: 1042 . found - whether str is in list 1043 1044 Level: intermediate 1045 1046 Notes: 1047 Not for use in Fortran 1048 1049 .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()` 1050 @*/ 1051 PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found) 1052 { 1053 PetscToken token; 1054 char *item; 1055 1056 PetscFunctionBegin; 1057 PetscValidBoolPointer(found,4); 1058 *found = PETSC_FALSE; 1059 PetscCall(PetscTokenCreate(list,sep,&token)); 1060 PetscCall(PetscTokenFind(token,&item)); 1061 while (item) { 1062 PetscCall(PetscStrcmp(str,item,found)); 1063 if (*found) break; 1064 PetscCall(PetscTokenFind(token,&item)); 1065 } 1066 PetscCall(PetscTokenDestroy(&token)); 1067 PetscFunctionReturn(0); 1068 } 1069 1070 /*@C 1071 PetscGetPetscDir - Gets the directory PETSc is installed in 1072 1073 Not Collective 1074 1075 Output Parameter: 1076 . dir - the directory 1077 1078 Level: developer 1079 1080 Notes: 1081 Not for use in Fortran 1082 1083 @*/ 1084 PetscErrorCode PetscGetPetscDir(const char *dir[]) 1085 { 1086 PetscFunctionBegin; 1087 PetscValidPointer(dir,1); 1088 *dir = PETSC_DIR; 1089 PetscFunctionReturn(0); 1090 } 1091 1092 /*@C 1093 PetscStrreplace - Replaces substrings in string with other substrings 1094 1095 Not Collective 1096 1097 Input Parameters: 1098 + comm - MPI_Comm of processors that are processing the string 1099 . aa - the string to look in 1100 . b - the resulting copy of a with replaced strings (b can be the same as a) 1101 - len - the length of b 1102 1103 Notes: 1104 Replaces ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY}, 1105 ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values 1106 as well as any environmental variables. 1107 1108 PETSC_LIB_DIR uses the environmental variable if it exists. PETSC_ARCH and PETSC_DIR use what 1109 PETSc was built with and do not use environmental variables. 1110 1111 Not for use in Fortran 1112 1113 Level: intermediate 1114 1115 @*/ 1116 PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len) 1117 { 1118 int i = 0; 1119 size_t l,l1,l2,l3; 1120 char *work,*par,*epar,env[1024],*tfree,*a = (char*)aa; 1121 const char *s[] = {"${PETSC_ARCH}","${PETSC_DIR}","${PETSC_LIB_DIR}","${DISPLAY}","${HOMEDIRECTORY}","${WORKINGDIRECTORY}","${USERNAME}","${HOSTNAME}",NULL}; 1122 char *r[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; 1123 PetscBool flag; 1124 static size_t DISPLAY_LENGTH = 265,USER_LENGTH = 256, HOST_LENGTH = 256; 1125 1126 PetscFunctionBegin; 1127 PetscValidCharPointer(aa,2); 1128 PetscValidCharPointer(b,3); 1129 if (aa == b) PetscCall(PetscStrallocpy(aa,(char**)&a)); 1130 PetscCall(PetscMalloc1(len,&work)); 1131 1132 /* get values for replaced variables */ 1133 PetscCall(PetscStrallocpy(PETSC_ARCH,&r[0])); 1134 PetscCall(PetscStrallocpy(PETSC_DIR,&r[1])); 1135 PetscCall(PetscStrallocpy(PETSC_LIB_DIR,&r[2])); 1136 PetscCall(PetscMalloc1(DISPLAY_LENGTH,&r[3])); 1137 PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN,&r[4])); 1138 PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN,&r[5])); 1139 PetscCall(PetscMalloc1(USER_LENGTH,&r[6])); 1140 PetscCall(PetscMalloc1(HOST_LENGTH,&r[7])); 1141 PetscCall(PetscGetDisplay(r[3],DISPLAY_LENGTH)); 1142 PetscCall(PetscGetHomeDirectory(r[4],PETSC_MAX_PATH_LEN)); 1143 PetscCall(PetscGetWorkingDirectory(r[5],PETSC_MAX_PATH_LEN)); 1144 PetscCall(PetscGetUserName(r[6],USER_LENGTH)); 1145 PetscCall(PetscGetHostName(r[7],HOST_LENGTH)); 1146 1147 /* replace that are in environment */ 1148 PetscCall(PetscOptionsGetenv(comm,"PETSC_LIB_DIR",env,sizeof(env),&flag)); 1149 if (flag) { 1150 PetscCall(PetscFree(r[2])); 1151 PetscCall(PetscStrallocpy(env,&r[2])); 1152 } 1153 1154 /* replace the requested strings */ 1155 PetscCall(PetscStrncpy(b,a,len)); 1156 while (s[i]) { 1157 PetscCall(PetscStrlen(s[i],&l)); 1158 PetscCall(PetscStrstr(b,s[i],&par)); 1159 while (par) { 1160 *par = 0; 1161 par += l; 1162 1163 PetscCall(PetscStrlen(b,&l1)); 1164 PetscCall(PetscStrlen(r[i],&l2)); 1165 PetscCall(PetscStrlen(par,&l3)); 1166 PetscCheck(l1 + l2 + l3 < len,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"b len is not long enough to hold new values"); 1167 PetscCall(PetscStrncpy(work,b,len)); 1168 PetscCall(PetscStrlcat(work,r[i],len)); 1169 PetscCall(PetscStrlcat(work,par,len)); 1170 PetscCall(PetscStrncpy(b,work,len)); 1171 PetscCall(PetscStrstr(b,s[i],&par)); 1172 } 1173 i++; 1174 } 1175 i = 0; 1176 while (r[i]) { 1177 tfree = (char*)r[i]; 1178 PetscCall(PetscFree(tfree)); 1179 i++; 1180 } 1181 1182 /* look for any other ${xxx} strings to replace from environmental variables */ 1183 PetscCall(PetscStrstr(b,"${",&par)); 1184 while (par) { 1185 *par = 0; 1186 par += 2; 1187 PetscCall(PetscStrncpy(work,b,len)); 1188 PetscCall(PetscStrstr(par,"}",&epar)); 1189 *epar = 0; 1190 epar += 1; 1191 PetscCall(PetscOptionsGetenv(comm,par,env,sizeof(env),&flag)); 1192 PetscCheck(flag,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Substitution string ${%s} not found as environmental variable",par); 1193 PetscCall(PetscStrlcat(work,env,len)); 1194 PetscCall(PetscStrlcat(work,epar,len)); 1195 PetscCall(PetscStrncpy(b,work,len)); 1196 PetscCall(PetscStrstr(b,"${",&par)); 1197 } 1198 PetscCall(PetscFree(work)); 1199 if (aa == b) PetscCall(PetscFree(a)); 1200 PetscFunctionReturn(0); 1201 } 1202 1203 /*@C 1204 PetscEListFind - searches list of strings for given string, using case insensitive matching 1205 1206 Not Collective 1207 1208 Input Parameters: 1209 + n - number of strings in 1210 . list - list of strings to search 1211 - str - string to look for, empty string "" accepts default (first entry in list) 1212 1213 Output Parameters: 1214 + value - index of matching string (if found) 1215 - found - boolean indicating whether string was found (can be NULL) 1216 1217 Notes: 1218 Not for use in Fortran 1219 1220 Level: advanced 1221 @*/ 1222 PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found) 1223 { 1224 PetscFunctionBegin; 1225 if (found) { 1226 PetscValidBoolPointer(found,5); 1227 *found = PETSC_FALSE; 1228 } 1229 for (PetscInt i = 0; i < n; ++i) { 1230 PetscBool matched; 1231 1232 PetscCall(PetscStrcasecmp(str,list[i],&matched)); 1233 if (matched || !str[0]) { 1234 if (found) *found = PETSC_TRUE; 1235 *value = i; 1236 break; 1237 } 1238 } 1239 PetscFunctionReturn(0); 1240 } 1241 1242 /*@C 1243 PetscEnumFind - searches enum list of strings for given string, using case insensitive matching 1244 1245 Not Collective 1246 1247 Input Parameters: 1248 + enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL 1249 - str - string to look for 1250 1251 Output Parameters: 1252 + value - index of matching string (if found) 1253 - found - boolean indicating whether string was found (can be NULL) 1254 1255 Notes: 1256 Not for use in Fortran 1257 1258 Level: advanced 1259 @*/ 1260 PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found) 1261 { 1262 PetscInt n = 0,evalue; 1263 PetscBool efound; 1264 1265 PetscFunctionBegin; 1266 PetscValidPointer(enumlist,1); 1267 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"); 1268 PetscCheck(n >= 3,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"List argument must have at least two entries: typename and type prefix"); 1269 n -= 3; /* drop enum name, prefix, and null termination */ 1270 PetscCall(PetscEListFind(n,enumlist,str,&evalue,&efound)); 1271 if (efound) { 1272 PetscValidPointer(value,3); 1273 *value = (PetscEnum)evalue; 1274 } 1275 if (found) { 1276 PetscValidBoolPointer(found,4); 1277 *found = efound; 1278 } 1279 PetscFunctionReturn(0); 1280 } 1281 1282 /*@C 1283 PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled. 1284 1285 Not collective 1286 1287 Input Parameter: 1288 . file - the file name 1289 1290 Note: 1291 PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems 1292 so that comparisons of output between runs are easy to make. 1293 1294 This mode is used for all tests in the test harness, it applies to both debug and optimized builds. 1295 1296 Use the option -petsc_ci to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for 1297 all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness. 1298 1299 Always uses the Unix / as the file separate even on Microsoft Windows systems 1300 1301 The option -petsc_ci_portable_error_output attempts to output the same error messages on all systems for the test harness. 1302 In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc 1303 error handling by the test harness. This options also causes PETSc to attempt to return an error code of 0 so that the test 1304 harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test 1305 harness in the args: argument for specific examples. It will not neccessarily produce portable output if different errors 1306 (or no errors) occur on a subset of the MPI ranks. 1307 1308 Level: developer 1309 1310 .seealso: `PetscCILinenumber()` 1311 1312 @*/ 1313 const char *PetscCIFilename(const char *file) 1314 { 1315 if (!PetscCIEnabledPortableErrorOutput) return file; 1316 return PetscBasename(file); 1317 } 1318 1319 /*@C 1320 PetscCILinenumber - returns a line number except if PetscCIEnablePortableErrorOutput) is set when it returns 0 1321 1322 Not collective 1323 1324 Input Parameter: 1325 . linenumber - the initial line number 1326 1327 Note: 1328 See `PetscCIFilename()` for details on usage 1329 1330 Level: developer 1331 1332 .seealso: `PetscCIFilename()` 1333 1334 @*/ 1335 int PetscCILinenumber(int linenumber) 1336 { 1337 if (!PetscCIEnabledPortableErrorOutput) return linenumber; 1338 return 0; 1339 } 1340