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