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