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