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