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