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 Note: 28 this may be called before PetscInitialize() or after PetscFinalize() 29 30 Fortran Note: 31 Not for use in Fortran 32 33 Developer Notes: 34 Uses raw `malloc()` and does not call error handlers since this may be used before PETSc is initialized. 35 36 Used to generate argc, args arguments passed to `MPI_Init()` 37 38 .seealso: `PetscStrToArrayDestroy()`, `PetscToken`, `PetscTokenCreate()` 39 @*/ 40 PetscErrorCode PetscStrToArray(const char s[], char sp, int *argc, char ***args) 41 { 42 int i, j, n, *lens, cnt = 0; 43 PetscBool flg = PETSC_FALSE; 44 45 if (!s) n = 0; 46 else n = strlen(s); 47 *argc = 0; 48 *args = NULL; 49 for (; n > 0; n--) { /* remove separator chars at the end - and will empty the string if all chars are separator chars */ 50 if (s[n - 1] != sp) break; 51 } 52 if (!n) return PETSC_SUCCESS; 53 for (i = 0; i < n; i++) { 54 if (s[i] != sp) break; 55 } 56 for (; i < n + 1; i++) { 57 if ((s[i] == sp || s[i] == 0) && !flg) { 58 flg = PETSC_TRUE; 59 (*argc)++; 60 } else if (s[i] != sp) { 61 flg = PETSC_FALSE; 62 } 63 } 64 (*args) = (char **)malloc(((*argc) + 1) * sizeof(char *)); 65 if (!*args) return PETSC_ERR_MEM; 66 lens = (int *)malloc((*argc) * sizeof(int)); 67 if (!lens) return PETSC_ERR_MEM; 68 for (i = 0; i < *argc; i++) lens[i] = 0; 69 70 *argc = 0; 71 for (i = 0; i < n; i++) { 72 if (s[i] != sp) break; 73 } 74 for (; i < n + 1; i++) { 75 if ((s[i] == sp || s[i] == 0) && !flg) { 76 flg = PETSC_TRUE; 77 (*argc)++; 78 } else if (s[i] != sp) { 79 lens[*argc]++; 80 flg = PETSC_FALSE; 81 } 82 } 83 84 for (i = 0; i < *argc; i++) { 85 (*args)[i] = (char *)malloc((lens[i] + 1) * sizeof(char)); 86 if (!(*args)[i]) { 87 free(lens); 88 for (j = 0; j < i; j++) free((*args)[j]); 89 free(*args); 90 return PETSC_ERR_MEM; 91 } 92 } 93 free(lens); 94 (*args)[*argc] = NULL; 95 96 *argc = 0; 97 for (i = 0; i < n; i++) { 98 if (s[i] != sp) break; 99 } 100 for (; i < n + 1; i++) { 101 if ((s[i] == sp || s[i] == 0) && !flg) { 102 flg = PETSC_TRUE; 103 (*args)[*argc][cnt++] = 0; 104 (*argc)++; 105 cnt = 0; 106 } else if (s[i] != sp && s[i] != 0) { 107 (*args)[*argc][cnt++] = s[i]; 108 flg = PETSC_FALSE; 109 } 110 } 111 return PETSC_SUCCESS; 112 } 113 114 /*@C 115 PetscStrToArrayDestroy - Frees array created with `PetscStrToArray()`. 116 117 Not Collective 118 119 Output Parameters: 120 + argc - the number of arguments 121 - args - the array of arguments 122 123 Level: intermediate 124 125 Note: 126 This may be called before `PetscInitialize()` or after `PetscFinalize()` 127 128 Fortran Note: 129 Not for use in Fortran 130 131 .seealso: `PetscStrToArray()` 132 @*/ 133 PetscErrorCode PetscStrToArrayDestroy(int argc, char **args) 134 { 135 for (int i = 0; i < argc; ++i) free(args[i]); 136 if (args) free(args); 137 return PETSC_SUCCESS; 138 } 139 140 /*@C 141 PetscStrArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings 142 143 Not Collective 144 145 Input Parameters: 146 . s - pointer to array of strings (final string is a null) 147 148 Output Parameter: 149 . t - the copied array string 150 151 Level: intermediate 152 153 Note: 154 If t has previously been allocated then that memory is lost, you may need to PetscStrArrayDestroy() 155 the array before calling this routine. 156 157 Fortran Note: 158 Not for use in Fortran 159 160 .seealso: `PetscStrallocpy()`, `PetscStrArrayDestroy()`, `PetscStrNArrayallocpy()` 161 @*/ 162 PetscErrorCode PetscStrArrayallocpy(const char *const *list, char ***t) 163 { 164 PetscInt n = 0; 165 166 PetscFunctionBegin; 167 while (list[n++]) 168 ; 169 PetscCall(PetscMalloc1(n + 1, t)); 170 for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i)); 171 (*t)[n] = NULL; 172 PetscFunctionReturn(PETSC_SUCCESS); 173 } 174 175 /*@C 176 PetscStrArrayDestroy - Frees array of strings created with `PetscStrArrayallocpy()`. 177 178 Not Collective 179 180 Output Parameters: 181 . list - array of strings 182 183 Level: intermediate 184 185 Fortran Note: 186 Not for use in Fortran 187 188 .seealso: `PetscStrArrayallocpy()` 189 @*/ 190 PetscErrorCode PetscStrArrayDestroy(char ***list) 191 { 192 PetscInt n = 0; 193 194 PetscFunctionBegin; 195 if (!*list) PetscFunctionReturn(PETSC_SUCCESS); 196 while ((*list)[n]) { 197 PetscCall(PetscFree((*list)[n])); 198 ++n; 199 } 200 PetscCall(PetscFree(*list)); 201 PetscFunctionReturn(PETSC_SUCCESS); 202 } 203 204 /*@C 205 PetscStrNArrayallocpy - Allocates space to hold a copy of an array of strings then copies the strings 206 207 Not Collective 208 209 Input Parameters: 210 + n - the number of string entries 211 - s - pointer to array of strings 212 213 Output Parameter: 214 . t - the copied array string 215 216 Level: intermediate 217 218 Fortran Note: 219 Not for use in Fortran 220 221 .seealso: `PetscStrallocpy()`, `PetscStrArrayallocpy()`, `PetscStrNArrayDestroy()` 222 @*/ 223 PetscErrorCode PetscStrNArrayallocpy(PetscInt n, const char *const *list, char ***t) 224 { 225 PetscFunctionBegin; 226 PetscCall(PetscMalloc1(n, t)); 227 for (PetscInt i = 0; i < n; i++) PetscCall(PetscStrallocpy(list[i], (*t) + i)); 228 PetscFunctionReturn(PETSC_SUCCESS); 229 } 230 231 /*@C 232 PetscStrNArrayDestroy - Frees array of strings created with `PetscStrNArrayallocpy()`. 233 234 Not Collective 235 236 Output Parameters: 237 + n - number of string entries 238 - list - array of strings 239 240 Level: intermediate 241 242 Fortran Note: 243 Not for use in Fortran 244 245 .seealso: `PetscStrNArrayallocpy()`, `PetscStrArrayallocpy()` 246 @*/ 247 PetscErrorCode PetscStrNArrayDestroy(PetscInt n, char ***list) 248 { 249 PetscFunctionBegin; 250 if (!*list) PetscFunctionReturn(PETSC_SUCCESS); 251 for (PetscInt i = 0; i < n; i++) PetscCall(PetscFree((*list)[i])); 252 PetscCall(PetscFree(*list)); 253 PetscFunctionReturn(PETSC_SUCCESS); 254 } 255 256 /*@C 257 PetscBasename - returns a pointer to the last entry of a / or \ separated directory path 258 259 Not Collective 260 261 Input Parameter: 262 . a - pointer to string 263 264 Level: intermediate 265 266 Fortran Note: 267 Not for use in Fortran 268 269 .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`, `PetscStrrchr()`, `PetscStrcmp()`, `PetscStrstr()`, 270 `PetscTokenCreate()`, `PetscStrToArray()`, `PetscStrInList()` 271 @*/ 272 const char *PetscBasename(const char a[]) 273 { 274 const char *ptr = NULL; 275 276 (void)PetscStrrchr(a, '/', (char **)&ptr); 277 if (ptr == a) { 278 if (PetscStrrchr(a, '\\', (char **)&ptr)) ptr = NULL; 279 } 280 return ptr; 281 } 282 283 /*@C 284 PetscStrcasecmp - Returns true if the two strings are the same 285 except possibly for case. 286 287 Not Collective 288 289 Input Parameters: 290 + a - pointer to first string 291 - b - pointer to second string 292 293 Output Parameter: 294 . flg - if the two strings are the same 295 296 Note: 297 Null arguments are ok 298 299 Fortran Note: 300 Not for use in Fortran 301 302 Level: intermediate 303 304 .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrgrt()` 305 @*/ 306 PetscErrorCode PetscStrcasecmp(const char a[], const char b[], PetscBool *t) 307 { 308 int c; 309 310 PetscFunctionBegin; 311 PetscValidBoolPointer(t, 3); 312 if (!a && !b) c = 0; 313 else if (!a || !b) c = 1; 314 #if defined(PETSC_HAVE_STRCASECMP) 315 else c = strcasecmp(a, b); 316 #elif defined(PETSC_HAVE_STRICMP) 317 else c = stricmp(a, b); 318 #else 319 else { 320 char *aa, *bb; 321 322 PetscCall(PetscStrallocpy(a, &aa)); 323 PetscCall(PetscStrallocpy(b, &bb)); 324 PetscCall(PetscStrtolower(aa)); 325 PetscCall(PetscStrtolower(bb)); 326 PetscCall(PetscStrcmp(aa, bb, t)); 327 PetscCall(PetscFree(aa)); 328 PetscCall(PetscFree(bb)); 329 PetscFunctionReturn(PETSC_SUCCESS); 330 } 331 #endif 332 *t = c ? PETSC_FALSE : PETSC_TRUE; 333 PetscFunctionReturn(PETSC_SUCCESS); 334 } 335 336 /*@C 337 PetscStrendswithwhich - Determines if a string ends with one of several possible strings 338 339 Not Collective 340 341 Input Parameters: 342 + a - pointer to string 343 - bs - strings to end with (last entry must be NULL) 344 345 Output Parameter: 346 . cnt - the index of the string it ends with or the index of NULL 347 348 Fortran Note: 349 Not for use in Fortran 350 351 Level: intermediate 352 353 .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, 354 `PetscStrncmp()`, `PetscStrlen()`, `PetscStrncmp()`, `PetscStrcmp()` 355 @*/ 356 PetscErrorCode PetscStrendswithwhich(const char a[], const char *const *bs, PetscInt *cnt) 357 { 358 PetscFunctionBegin; 359 PetscValidPointer(bs, 2); 360 PetscValidIntPointer(cnt, 3); 361 *cnt = 0; 362 while (bs[*cnt]) { 363 PetscBool flg; 364 365 PetscCall(PetscStrendswith(a, bs[*cnt], &flg)); 366 if (flg) PetscFunctionReturn(PETSC_SUCCESS); 367 ++(*cnt); 368 } 369 PetscFunctionReturn(PETSC_SUCCESS); 370 } 371 372 struct _p_PetscToken { 373 char token; 374 char *array; 375 char *current; 376 }; 377 378 /*@C 379 PetscTokenFind - Locates next "token" in a string 380 381 Not Collective 382 383 Input Parameters: 384 . a - pointer to token 385 386 Output Parameter: 387 . result - location of occurrence, NULL if not found 388 389 Notes: 390 This version is different from the system version in that 391 it allows you to pass a read-only string into the function. 392 393 This version also treats all characters etc. inside a double quote " 394 as a single token. 395 396 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 397 second will return a null terminated y 398 399 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 400 401 Fortran Note: 402 Not for use in Fortran 403 404 Level: intermediate 405 406 .seealso: `PetscTokenCreate()`, `PetscTokenDestroy()` 407 @*/ 408 PetscErrorCode PetscTokenFind(PetscToken a, char *result[]) 409 { 410 char *ptr, token; 411 412 PetscFunctionBegin; 413 PetscValidPointer(a, 1); 414 PetscValidPointer(result, 2); 415 *result = ptr = a->current; 416 if (ptr && !*ptr) { 417 *result = NULL; 418 PetscFunctionReturn(PETSC_SUCCESS); 419 } 420 token = a->token; 421 if (ptr && (*ptr == '"')) { 422 token = '"'; 423 (*result)++; 424 ptr++; 425 } 426 while (ptr) { 427 if (*ptr == token) { 428 *ptr++ = 0; 429 while (*ptr == a->token) ptr++; 430 a->current = ptr; 431 break; 432 } 433 if (!*ptr) { 434 a->current = NULL; 435 break; 436 } 437 ptr++; 438 } 439 PetscFunctionReturn(PETSC_SUCCESS); 440 } 441 442 /*@C 443 PetscTokenCreate - Creates a `PetscToken` used to find tokens in a string 444 445 Not Collective 446 447 Input Parameters: 448 + string - the string to look in 449 - b - the separator character 450 451 Output Parameter: 452 . t- the token object 453 454 Note: 455 This version is different from the system version in that 456 it allows you to pass a read-only string into the function. 457 458 Fortran Note: 459 Not for use in Fortran 460 461 Level: intermediate 462 463 .seealso: `PetscTokenFind()`, `PetscTokenDestroy()` 464 @*/ 465 PetscErrorCode PetscTokenCreate(const char a[], char b, PetscToken *t) 466 { 467 PetscFunctionBegin; 468 PetscValidCharPointer(a, 1); 469 PetscValidPointer(t, 3); 470 PetscCall(PetscNew(t)); 471 PetscCall(PetscStrallocpy(a, &(*t)->array)); 472 473 (*t)->current = (*t)->array; 474 (*t)->token = b; 475 PetscFunctionReturn(PETSC_SUCCESS); 476 } 477 478 /*@C 479 PetscTokenDestroy - Destroys a `PetscToken` 480 481 Not Collective 482 483 Input Parameters: 484 . a - pointer to token 485 486 Level: intermediate 487 488 Fortran Note: 489 Not for use in Fortran 490 491 .seealso: `PetscTokenCreate()`, `PetscTokenFind()` 492 @*/ 493 PetscErrorCode PetscTokenDestroy(PetscToken *a) 494 { 495 PetscFunctionBegin; 496 if (!*a) PetscFunctionReturn(PETSC_SUCCESS); 497 PetscCall(PetscFree((*a)->array)); 498 PetscCall(PetscFree(*a)); 499 PetscFunctionReturn(PETSC_SUCCESS); 500 } 501 502 /*@C 503 PetscStrInList - search for string in character-delimited list 504 505 Not Collective 506 507 Input Parameters: 508 + str - the string to look for 509 . list - the list to search in 510 - sep - the separator character 511 512 Output Parameter: 513 . found - whether str is in list 514 515 Level: intermediate 516 517 Fortran Note: 518 Not for use in Fortran 519 520 .seealso: `PetscTokenCreate()`, `PetscTokenFind()`, `PetscStrcmp()` 521 @*/ 522 PetscErrorCode PetscStrInList(const char str[], const char list[], char sep, PetscBool *found) 523 { 524 PetscToken token; 525 char *item; 526 527 PetscFunctionBegin; 528 PetscValidBoolPointer(found, 4); 529 *found = PETSC_FALSE; 530 PetscCall(PetscTokenCreate(list, sep, &token)); 531 PetscCall(PetscTokenFind(token, &item)); 532 while (item) { 533 PetscCall(PetscStrcmp(str, item, found)); 534 if (*found) break; 535 PetscCall(PetscTokenFind(token, &item)); 536 } 537 PetscCall(PetscTokenDestroy(&token)); 538 PetscFunctionReturn(PETSC_SUCCESS); 539 } 540 541 /*@C 542 PetscGetPetscDir - Gets the directory PETSc is installed in 543 544 Not Collective 545 546 Output Parameter: 547 . dir - the directory 548 549 Level: developer 550 551 Fortran Note: 552 Not for use in Fortran 553 554 @*/ 555 PetscErrorCode PetscGetPetscDir(const char *dir[]) 556 { 557 PetscFunctionBegin; 558 PetscValidPointer(dir, 1); 559 *dir = PETSC_DIR; 560 PetscFunctionReturn(PETSC_SUCCESS); 561 } 562 563 /*@C 564 PetscStrreplace - Replaces substrings in string with other substrings 565 566 Not Collective 567 568 Input Parameters: 569 + comm - `MPI_Comm` of processors that are processing the string 570 . aa - the string to look in 571 . b - the resulting copy of a with replaced strings (b can be the same as a) 572 - len - the length of b 573 574 Notes: 575 Replaces ${PETSC_ARCH},${PETSC_DIR},${PETSC_LIB_DIR},${DISPLAY}, 576 ${HOMEDIRECTORY},${WORKINGDIRECTORY},${USERNAME}, ${HOSTNAME} with appropriate values 577 as well as any environmental variables. 578 579 `PETSC_LIB_DIR` uses the environmental variable if it exists. `PETSC_ARCH` and `PETSC_DIR` use what 580 PETSc was built with and do not use environmental variables. 581 582 Fortran Note: 583 Not for use in Fortran 584 585 Level: developer 586 587 @*/ 588 PetscErrorCode PetscStrreplace(MPI_Comm comm, const char aa[], char b[], size_t len) 589 { 590 int i = 0; 591 size_t l, l1, l2, l3; 592 char *work, *par, *epar, env[1024], *tfree, *a = (char *)aa; 593 const char *s[] = {"${PETSC_ARCH}", "${PETSC_DIR}", "${PETSC_LIB_DIR}", "${DISPLAY}", "${HOMEDIRECTORY}", "${WORKINGDIRECTORY}", "${USERNAME}", "${HOSTNAME}", NULL}; 594 char *r[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; 595 PetscBool flag; 596 static size_t DISPLAY_LENGTH = 265, USER_LENGTH = 256, HOST_LENGTH = 256; 597 598 PetscFunctionBegin; 599 PetscValidCharPointer(aa, 2); 600 PetscValidCharPointer(b, 3); 601 if (aa == b) PetscCall(PetscStrallocpy(aa, (char **)&a)); 602 PetscCall(PetscMalloc1(len, &work)); 603 604 /* get values for replaced variables */ 605 PetscCall(PetscStrallocpy(PETSC_ARCH, &r[0])); 606 PetscCall(PetscStrallocpy(PETSC_DIR, &r[1])); 607 PetscCall(PetscStrallocpy(PETSC_LIB_DIR, &r[2])); 608 PetscCall(PetscMalloc1(DISPLAY_LENGTH, &r[3])); 609 PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[4])); 610 PetscCall(PetscMalloc1(PETSC_MAX_PATH_LEN, &r[5])); 611 PetscCall(PetscMalloc1(USER_LENGTH, &r[6])); 612 PetscCall(PetscMalloc1(HOST_LENGTH, &r[7])); 613 PetscCall(PetscGetDisplay(r[3], DISPLAY_LENGTH)); 614 PetscCall(PetscGetHomeDirectory(r[4], PETSC_MAX_PATH_LEN)); 615 PetscCall(PetscGetWorkingDirectory(r[5], PETSC_MAX_PATH_LEN)); 616 PetscCall(PetscGetUserName(r[6], USER_LENGTH)); 617 PetscCall(PetscGetHostName(r[7], HOST_LENGTH)); 618 619 /* replace that are in environment */ 620 PetscCall(PetscOptionsGetenv(comm, "PETSC_LIB_DIR", env, sizeof(env), &flag)); 621 if (flag) { 622 PetscCall(PetscFree(r[2])); 623 PetscCall(PetscStrallocpy(env, &r[2])); 624 } 625 626 /* replace the requested strings */ 627 PetscCall(PetscStrncpy(b, a, len)); 628 while (s[i]) { 629 PetscCall(PetscStrlen(s[i], &l)); 630 PetscCall(PetscStrstr(b, s[i], &par)); 631 while (par) { 632 *par = 0; 633 par += l; 634 635 PetscCall(PetscStrlen(b, &l1)); 636 PetscCall(PetscStrlen(r[i], &l2)); 637 PetscCall(PetscStrlen(par, &l3)); 638 PetscCheck(l1 + l2 + l3 < len, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "b len is not long enough to hold new values"); 639 PetscCall(PetscStrncpy(work, b, len)); 640 PetscCall(PetscStrlcat(work, r[i], len)); 641 PetscCall(PetscStrlcat(work, par, len)); 642 PetscCall(PetscStrncpy(b, work, len)); 643 PetscCall(PetscStrstr(b, s[i], &par)); 644 } 645 i++; 646 } 647 i = 0; 648 while (r[i]) { 649 tfree = (char *)r[i]; 650 PetscCall(PetscFree(tfree)); 651 i++; 652 } 653 654 /* look for any other ${xxx} strings to replace from environmental variables */ 655 PetscCall(PetscStrstr(b, "${", &par)); 656 while (par) { 657 *par = 0; 658 par += 2; 659 PetscCall(PetscStrncpy(work, b, len)); 660 PetscCall(PetscStrstr(par, "}", &epar)); 661 *epar = 0; 662 epar += 1; 663 PetscCall(PetscOptionsGetenv(comm, par, env, sizeof(env), &flag)); 664 PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Substitution string ${%s} not found as environmental variable", par); 665 PetscCall(PetscStrlcat(work, env, len)); 666 PetscCall(PetscStrlcat(work, epar, len)); 667 PetscCall(PetscStrncpy(b, work, len)); 668 PetscCall(PetscStrstr(b, "${", &par)); 669 } 670 PetscCall(PetscFree(work)); 671 if (aa == b) PetscCall(PetscFree(a)); 672 PetscFunctionReturn(PETSC_SUCCESS); 673 } 674 675 /*@C 676 PetscEListFind - searches list of strings for given string, using case insensitive matching 677 678 Not Collective 679 680 Input Parameters: 681 + n - number of strings in 682 . list - list of strings to search 683 - str - string to look for, empty string "" accepts default (first entry in list) 684 685 Output Parameters: 686 + value - index of matching string (if found) 687 - found - boolean indicating whether string was found (can be NULL) 688 689 Fortran Note: 690 Not for use in Fortran 691 692 Level: advanced 693 694 .seealso: `PetscEnumFind()` 695 @*/ 696 PetscErrorCode PetscEListFind(PetscInt n, const char *const *list, const char *str, PetscInt *value, PetscBool *found) 697 { 698 PetscFunctionBegin; 699 if (found) { 700 PetscValidBoolPointer(found, 5); 701 *found = PETSC_FALSE; 702 } 703 for (PetscInt i = 0; i < n; ++i) { 704 PetscBool matched; 705 706 PetscCall(PetscStrcasecmp(str, list[i], &matched)); 707 if (matched || !str[0]) { 708 if (found) *found = PETSC_TRUE; 709 *value = i; 710 break; 711 } 712 } 713 PetscFunctionReturn(PETSC_SUCCESS); 714 } 715 716 /*@C 717 PetscEnumFind - searches enum list of strings for given string, using case insensitive matching 718 719 Not Collective 720 721 Input Parameters: 722 + enumlist - list of strings to search, followed by enum name, then enum prefix, then NUL 723 - str - string to look for 724 725 Output Parameters: 726 + value - index of matching string (if found) 727 - found - boolean indicating whether string was found (can be NULL) 728 729 Fortran Note: 730 Not for use in Fortran 731 732 Level: advanced 733 734 .seealso: `PetscEListFind()` 735 @*/ 736 PetscErrorCode PetscEnumFind(const char *const *enumlist, const char *str, PetscEnum *value, PetscBool *found) 737 { 738 PetscInt n = 0, evalue; 739 PetscBool efound; 740 741 PetscFunctionBegin; 742 PetscValidPointer(enumlist, 1); 743 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"); 744 PetscCheck(n >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix"); 745 n -= 3; /* drop enum name, prefix, and null termination */ 746 PetscCall(PetscEListFind(n, enumlist, str, &evalue, &efound)); 747 if (efound) { 748 PetscValidPointer(value, 3); 749 *value = (PetscEnum)evalue; 750 } 751 if (found) { 752 PetscValidBoolPointer(found, 4); 753 *found = efound; 754 } 755 PetscFunctionReturn(PETSC_SUCCESS); 756 } 757 758 /*@C 759 PetscCIFilename - returns the basename of a file name when the PETSc CI portable error output mode is enabled. 760 761 Not collective 762 763 Input Parameter: 764 . file - the file name 765 766 Note: 767 PETSc CI mode is a mode of running PETSc where output (both error and non-error) is made portable across all systems 768 so that comparisons of output between runs are easy to make. 769 770 This mode is used for all tests in the test harness, it applies to both debug and optimized builds. 771 772 Use the option -petsc_ci to turn on PETSc CI mode. It changes certain output in non-error situations to be portable for 773 all systems, mainly the output of options. It is passed to all PETSc programs automatically by the test harness. 774 775 Always uses the Unix / as the file separate even on Microsoft Windows systems 776 777 The option -petsc_ci_portable_error_output attempts to output the same error messages on all systems for the test harness. 778 In particular the output of filenames and line numbers in PETSc stacks. This is to allow (limited) checking of PETSc 779 error handling by the test harness. This options also causes PETSc to attempt to return an error code of 0 so that the test 780 harness can process the output for differences in the usual manner as for successful runs. It should be provided to the test 781 harness in the args: argument for specific examples. It will not necessarily produce portable output if different errors 782 (or no errors) occur on a subset of the MPI ranks. 783 784 Level: developer 785 786 .seealso: `PetscCILinenumber()` 787 @*/ 788 const char *PetscCIFilename(const char *file) 789 { 790 if (!PetscCIEnabledPortableErrorOutput) return file; 791 return PetscBasename(file); 792 } 793 794 /*@C 795 PetscCILinenumber - returns a line number except if `PetscCIEnablePortableErrorOutput` is set when it returns 0 796 797 Not collective 798 799 Input Parameter: 800 . linenumber - the initial line number 801 802 Note: 803 See `PetscCIFilename()` for details on usage 804 805 Level: developer 806 807 .seealso: `PetscCIFilename()` 808 @*/ 809 int PetscCILinenumber(int linenumber) 810 { 811 if (!PetscCIEnabledPortableErrorOutput) return linenumber; 812 return 0; 813 } 814